oil-ui-pro 0.15.4 → 0.22.2(上游 ui.oiloil.org 正式包)+ 记 P0-98 跨盘 rename 坑

- oil-ui-pro 升到 0.22.2:references 13→28 份(新增 16、删 imagery.md)、assets 增 cards/(22 组)与 fonts/、SKILL.md 顶层五步结构未改名。
- 升级路径:官方 `npx github:oil-oil/oil-cli update` 稳定失败(error=replace、报「检查目录权限」)。
  真身为 EXDEV —— 解压在 os.tmpdir()(C 盘)、技能目录在 E 盘,Windows 上 rename 不能跨盘;
  CLI 的 catch 把非 CliError 原生异常一律兜底成 replaceFailed,真错误一个字不吐。
  做法=借其 prepare() 只做下载+校验,再 cp 到同盘 stage、rename 交换;官方命令复验 up_to_date。
- 回归:product-planning 按名引用的 visual-review.md/tools.md/design-direction.md/style-explorer.md 全部健在;命名闸门 2061|0|27。
- session-mechanism/references/pitfalls.md 新增 P0-98(含通则:更新器把原生错误兜底成指错方向的人话)。
This commit is contained in:
admin committed 2026-10-14 10:21:46 +08:00
1 parent 053a6a6723
commit d9445b5888
126 files changed
+10345 -1401

No files matched your search

@@ -0,0 +1,18 @@
.card.responsive-preview {
--_card-stage-track-min:320px; aspect-ratio:auto;
& .card-stage { display:grid; grid-template-rows:minmax(245px,1fr) auto; }
& .size-scene { position:relative; min-height:245px; overflow:hidden; background:radial-gradient(ellipse at 50% 70%,var(--card-wash),transparent 65%); }
& .size-frame { position:absolute; overflow:hidden; border:1px solid color-mix(in oklab,var(--card-ink) 16%,var(--card-panel)); border-radius:10px; background:var(--card-panel); box-shadow:0 6px 14px #18243209; }
& .size-frame-bar { height:29px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid var(--card-line); color:var(--card-muted); font:9px ui-monospace,monospace; padding:0 10px; }
& .size-frame-bar i { width:4px; height:4px; background:var(--card-line); border-radius:50%; box-shadow:7px 0 var(--card-line),14px 0 var(--card-line); }
& .size-frame > svg { display:block; width:100%; height:calc(100% - 29px); }
& .size-frame-0 { width:59%; height:190px; left:20%; top:10px; transform:translate(calc(var(--spread,1)*12%),calc(var(--spread,1)*-1px)); }
& .size-frame-1 { width:47%; height:154px; left:26%; top:44px; transform:translate(calc(var(--spread,1)*-18%),calc(var(--spread,1)*6px)); opacity:var(--spread,1); }
& .size-frame-2 { width:27%; height:137px; left:36%; top:61px; transform:translate(calc(var(--spread,1)*-87%),calc(var(--spread,1)*33px)); opacity:var(--spread,1); }
& .preview-land-back { fill:color-mix(in oklab,var(--card-accent) 17%,var(--card-panel)); }
& .preview-land-front { fill:color-mix(in oklab,var(--card-accent) 32%,var(--card-panel)); }
& .preview-contours { stroke:color-mix(in oklab,var(--card-accent) 45%,var(--card-panel)); stroke-width:1; }
& .preview-sun { fill:color-mix(in oklab,var(--_card-accent-2) 36%,var(--card-panel)); }
& .size-toolbar { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px; padding:18px 24px 24px; font-size:11px; line-height:1.5; color:var(--card-muted); }
& .size-toggle { display:flex; gap:12px; align-items:center; background:transparent; color:var(--_card-accent-ink); border:0; padding:0; font:inherit; cursor:pointer; white-space:nowrap; }
}
@@ -0,0 +1,5 @@
<article class="card responsive-preview" data-card="responsive-preview" style="--card-accent:#5865c7">
<h2 class="card-heading" data-text="title">一份内容,
在不同屏幕上自然展开。</h2>
<div class="card-stage"><div class="size-scene"><div class="size-frame size-frame-0"><div class="size-frame-bar"><i></i><span data-text="labels.0">原始画面</span></div><svg viewBox="0 0 300 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true"><path class="preview-land-back" d="M0 98C54 85 56 30 118 42s76 75 182-10V180H0Z"/><path class="preview-land-front" d="M0 147C62 48 114 127 169 75s83 27 131 0V180H0Z"/><g class="preview-contours" fill="none"><path d="M-10 160C62 61 114 140 169 88s83 27 145-6M-10 174C62 75 114 154 169 102s83 27 145-6M-10 188C62 89 114 168 169 116s83 27 145-6M-10 202C62 103 114 182 169 130s83 27 145-6"/></g><circle cx="244" cy="37" r="14" class="preview-sun"/></svg></div><div class="size-frame size-frame-1"><div class="size-frame-bar"><i></i><span data-text="labels.1">宽屏</span></div><svg viewBox="0 0 300 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true"><path class="preview-land-back" d="M0 98C54 85 56 30 118 42s76 75 182-10V180H0Z"/><path class="preview-land-front" d="M0 147C62 48 114 127 169 75s83 27 131 0V180H0Z"/><g class="preview-contours" fill="none"><path d="M-10 160C62 61 114 140 169 88s83 27 145-6M-10 174C62 75 114 154 169 102s83 27 145-6M-10 188C62 89 114 168 169 116s83 27 145-6M-10 202C62 103 114 182 169 130s83 27 145-6"/></g><circle cx="244" cy="37" r="14" class="preview-sun"/></svg></div><div class="size-frame size-frame-2"><div class="size-frame-bar"><i></i><span data-text="labels.2">手机</span></div><svg viewBox="0 0 300 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true"><path class="preview-land-back" d="M0 98C54 85 56 30 118 42s76 75 182-10V180H0Z"/><path class="preview-land-front" d="M0 147C62 48 114 127 169 75s83 27 131 0V180H0Z"/><g class="preview-contours" fill="none"><path d="M-10 160C62 61 114 140 169 88s83 27 145-6M-10 174C62 75 114 154 169 102s83 27 145-6M-10 188C62 89 114 168 169 116s83 27 145-6M-10 202C62 103 114 182 169 130s83 27 145-6"/></g><circle cx="244" cy="37" r="14" class="preview-sun"/></svg></div></div><div class="size-toolbar"><span data-text="description">保留主体,重新安排取景。</span><button type="button" class="size-toggle" aria-pressed="true">收起尺寸 <span aria-hidden="true">↗</span></button></div></div>
</article>
@@ -0,0 +1,7 @@
import {shell,loop,staticMotion,smooth} from '../shared/runtime.js';
export function mount(element, options = {}) {
const clean=shell(element,options),still=staticMotion(element,options),button=element.querySelector('.size-toggle');let value=0,target=1,clock,destroyed=false;
const animate=next=>{const from=value;target=next;clock?.destroy();button.setAttribute('aria-pressed',String(!!target));button.firstChild.textContent=target?'收起尺寸 ':'比较尺寸 ';clock=loop(element,time=>{value=still()?target:from+(target-from)*smooth(time/.9);element.style.setProperty('--spread',value);},{...options,duration:.9});};
const toggle=()=>animate(target?0:1);button.addEventListener('click',toggle);animate(1);
return{replay(){if(!destroyed){value=0;animate(1);}},destroy(){if(destroyed)return;destroyed=true;clock.destroy();button.removeEventListener('click',toggle);clean();element.style.removeProperty('--spread');}};
}