Files
workbuddy_skills/oil-ui-pro/assets/cards/flow-object/card.js
T
admin d9445b5888 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(含通则:更新器把原生错误兜底成指错方向的人话)。
2026-10-14 10:21:46 +08:00

28 lines
1.8 KiB
JavaScript

import {loop, watchColors, shell, mix, clamp, staticMotion} from '../shared/runtime.js';
import {coatedSurface} from './material.js';
export function mount(element, options = {}) {
const variant=options.variant ?? element.dataset.variant ?? 'token';
const cleanShell=shell(element,{...options,variant:variant==='card'?'card':'token'});
const surface=coatedSurface(element.querySelector('.flow-surface'));
const card=element.querySelector('.physical-card');
let palette,x=0,y=0,tx=0,ty=0;
const still=staticMotion(element,options);
const draw=(time,dt)=>{
if(still())x=y=tx=ty=0;
if(dt || still()){
const ease=1-Math.exp(-dt*7);x=mix(x,tx,ease);y=mix(y,ty,ease);
card.style.transform=`rotateX(${-y*5}deg) rotateY(${x*7}deg)`;
}
surface.draw(time,palette,[x,y]);
element.style.setProperty('--token-pulse',still()?.8:.65+.35*(.5+.5*Math.sin(time*2.2)));
};
const clock=loop(element,draw,{...options,settled:()=>Math.abs(x-tx)+Math.abs(y-ty)<.001});
const off=watchColors(element,p=>{palette=p;clock.invalidate();});
const ro=new ResizeObserver(()=>{surface.resize();clock.invalidate();});ro.observe(card);
const move=e=>{if(e.pointerType==='touch' || still())return;const r=element.getBoundingClientRect();tx=clamp((e.clientX-r.left)/r.width*2-1,-1,1);ty=clamp((e.clientY-r.top)/r.height*2-1,-1,1);};
const leave=()=>{tx=ty=0;};
element.addEventListener('pointermove',move);element.addEventListener('pointerleave',leave);element.addEventListener('pointercancel',leave);
return {destroy(){clock.destroy();off();ro.disconnect();surface.destroy();cleanShell();element.removeEventListener('pointermove',move);element.removeEventListener('pointerleave',leave);element.removeEventListener('pointercancel',leave);card.style.removeProperty('transform');element.style.removeProperty('--token-pulse');}};
}