@jayyuen66/dsh-plugin-shared 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -76,28 +76,30 @@ import{createElement as e,useCallback as t,useEffect as n,useId as r,useLayoutEf
76
76
  @media (prefers-reduced-motion:reduce){
77
77
  .dsu-switch,.dsu-knob,.dsu-chevron,.dsu-btn{transition:none}
78
78
  }
79
- `;function l(e,t=30){return e.length<=t?{hint:e}:{detail:e}}function u(t){return e(`div`,{className:`dsu-form`},t.children)}function d(t){return e(`section`,{className:`dsu-section`},e(`h2`,{className:`dsu-sectionTitle`},t.title),t.hint===void 0?null:e(`p`,{className:`dsu-sectionHint`},t.hint),t.children)}function f(t){return e(`div`,{className:`dsu-grid`},t.children)}function p(t){if(t.items.length===0)return null;let n=t.items.map((t,n)=>e(`span`,{key:n},n===0?t:`· ${t}`));return e(`div`,{className:`dsu-statusbar`},...n)}function m(){return`happyDOM`in globalThis?!1:typeof CSS<`u`&&typeof CSS.supports==`function`&&CSS.supports(`position-area: block-end`)}function h(a){let c=r(),l=`--dsu-tip-${c.replaceAll(/[^a-zA-Z0-9]/gu,``)}`,[u,d]=s(!1),f=o(!1),p=o(!1),h=o(!1),g=o(null),_=o(null),v=o(null),y=o(null),b=t(()=>{y.current!==null&&(clearTimeout(y.current),y.current=null)},[]),x=t(()=>{let e=_.current,t=v.current;if(e===null||t===null||m())return;t.style.marginTop=`0px`;let n=e.getBoundingClientRect(),r=t.offsetWidth,i=t.offsetHeight,{left:a}=n,o=n.bottom+8;o+i>window.innerHeight-8&&(o=n.top-i-8),a+r>window.innerWidth-8&&(a=window.innerWidth-r-8);let s=Math.max(8,window.innerWidth-r-8),c=Math.max(8,window.innerHeight-i-8);t.style.left=`${Math.min(Math.max(8,a),s)}px`,t.style.top=`${Math.min(Math.max(8,o),c)}px`},[]),S=t(()=>{b(),h.current=!1,d(!1)},[b]),C=t(()=>{b(),d(!0)},[b]),w=t(()=>{b(),f.current||p.current||h.current||(y.current=setTimeout(()=>{
79
+ `;function l(e,t=30){return e.length<=t?{hint:e}:{detail:e}}function u(t){return e(`div`,{className:`dsu-form`},t.children)}function d(t){return e(`section`,{className:`dsu-section`},e(`h2`,{className:`dsu-sectionTitle`},t.title),t.hint===void 0?null:e(`p`,{className:`dsu-sectionHint`},t.hint),t.children)}function f(t){return e(`div`,{className:`dsu-grid`},t.children)}function p(t){if(t.items.length===0)return null;let n=t.items.map((t,n)=>e(`span`,{key:n},n===0?t:`· ${t}`));return e(`div`,{className:`dsu-statusbar`},...n)}function m(){return`happyDOM`in globalThis?!1:typeof CSS<`u`&&typeof CSS.supports==`function`&&CSS.supports(`position-area: block-end`)}function h(e,t){let n=Math.abs(t.left-e.left)<=2,r=Math.abs(t.right-e.right)<=2;if(!n&&!r)return!0;let i=t.top>=e.bottom-2,a=t.bottom<=e.top+2;return!i&&!a}function g(a){let c=r(),l=`--dsu-tip-${c.replaceAll(/[^a-zA-Z0-9]/gu,``)}`,[u,d]=s(!1),f=o(!1),p=o(!1),g=o(!1),_=o(null),v=o(null),y=o(null),b=o(null),x=t(()=>{b.current!==null&&(clearTimeout(b.current),b.current=null)},[]),S=t(()=>{let e=v.current,t=y.current;
80
+ /* v8 ignore next 3 -- place 只在 open 的 layout effect 与挂载期监听器里调用;refs 为空只可能是卸载竞态 */
81
+ if(e===null||t===null)return;let n=m()&&t.style.positionArea!==`none`,r=e.getBoundingClientRect();if(n&&!h(r,t.getBoundingClientRect()))return;n&&(t.style.positionArea=`none`),t.style.marginTop=`0px`;let i=t.offsetWidth,a=t.offsetHeight,{left:o}=r,s=r.bottom+8;s+a>window.innerHeight-8&&(s=r.top-a-8),o+i>window.innerWidth-8&&(o=window.innerWidth-i-8);let c=Math.max(8,window.innerWidth-i-8),l=Math.max(8,window.innerHeight-a-8);t.style.left=`${Math.min(Math.max(8,o),c)}px`,t.style.top=`${Math.min(Math.max(8,s),l)}px`},[]),C=t(()=>{x(),g.current=!1,d(!1)},[x]),w=t(()=>{x(),d(!0)},[x]),T=t(()=>{x(),f.current||p.current||g.current||(b.current=setTimeout(()=>{
80
82
  /* v8 ignore next 3 -- 任何重新进入/钉住都会 cancelHide;这次复查只防未来的异步路径 */
81
- y.current=null,f.current||p.current||h.current||d(!1)},120))},[b]),T=t(e=>{h.current=e},[]);i(()=>{if(!u)return()=>{};x();let e=e=>{let{target:t}=e;t instanceof Node&&v.current?.contains(t)===!0||(h.current?x():S())},t=()=>{x()},n=e=>{let t=e.target;g.current?.contains(t)!==!0&&S()};return document.addEventListener(`pointerdown`,n,!0),window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,t),()=>{document.removeEventListener(`pointerdown`,n,!0),window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,t)}},[u,a.detail,x,S]),n(()=>{if(!u)return()=>{};let e=e=>{e.key===`Escape`&&S()};return document.addEventListener(`keydown`,e),()=>{document.removeEventListener(`keydown`,e)}},[u,S]),n(()=>b,[b]);let E=e(`button`,{ref:_,type:`button`,className:`dsu-helpBtn`,style:{anchorName:l},"aria-label":`${a.label} 说明`,"aria-expanded":u,"aria-controls":c,onClick:()=>{h.current?S():(T(!0),C())}},e(`svg`,{width:12,height:12,viewBox:`0 0 14 14`,"aria-hidden":!0},e(`circle`,{cx:7,cy:7,r:6,fill:`none`,stroke:`currentColor`,strokeWidth:1.2}),e(`path`,{d:`M7 6.2v4`,stroke:`currentColor`,strokeWidth:1.3,strokeLinecap:`round`}),e(`circle`,{cx:7,cy:4.3,r:.8,fill:`currentColor`}))),D=e(`div`,{ref:v,id:c,role:`tooltip`,className:`dsu-tip`,style:{positionAnchor:l,positionTryFallbacks:`flip-block, flip-inline`},hidden:!u},a.detail),O=a.showLabel===!1?null:e(`span`,{className:`dsu-label${a.compact===!0?` dsu-labelMono`:``}`},a.label);return e(`span`,{ref:g,className:`dsu-help`,onMouseEnter:()=>{f.current=!0,C()},onMouseLeave:()=>{f.current=!1,w()},onFocus:()=>{p.current=!0,C()},onBlur:e=>{let t=e.relatedTarget;t instanceof Node&&e.currentTarget.contains(t)||(p.current=!1,w())}},O,E,D)}function g(t){let n=`dsu-label${t.compact===!0?` dsu-labelMono`:``}`,r=t.controlId===void 0?e(`span`,{className:n},t.label):e(`label`,{className:n,htmlFor:t.controlId},t.label);return e(`div`,{className:`dsu-labelRow`},r,t.detail===void 0?null:e(h,{label:t.label,detail:t.detail,showLabel:!1}))}function _(t){let n=t.controlId===void 0?void 0:`${t.controlId}-hint`;return e(`div`,{className:`dsu-field${t.wide===!0?` dsu-fieldWide`:``}`},e(`div`,{className:`dsu-fieldMeta`},e(g,{label:t.label,detail:t.detail,compact:t.compact,controlId:t.controlId}),t.hint===void 0?null:e(`p`,{className:`dsu-hint`,id:n},t.hint)),e(`div`,{className:`dsu-control`},t.children))}function v(t){let n=r(),i=t.hint===void 0?void 0:`${n}-hint`;return e(_,{...t,controlId:n},e(`button`,{type:`button`,role:`switch`,id:n,className:`dsu-switch`,"aria-checked":t.checked,"aria-describedby":i,"data-field":t.field,disabled:t.disabled===!0,onClick:()=>{t.onChange(!t.checked)}},e(`span`,{className:`dsu-knob`})))}function y(t){let i=typeof t.value==`number`&&Number.isFinite(t.value)?String(t.value):``,[a,c]=s(i),[l,u]=s(!1),[d,f]=s(!1),p=o(void 0),m=r(),h=r(),g=t.hint===void 0?void 0:`${m}-hint`,v=l&&d,y=[g,v?h:void 0].filter(e=>e!==void 0),b=y.length===0?void 0:y.join(` `);n(()=>{t.value!==p.current&&(p.current=t.value,c(i),u(!1),f(!1))},[t.value,i]);let x=e=>{let n=t.min??-1/0,r=t.max??1/0;if(!Number.isFinite(e)||e<n||e>r)return!1;let{step:i}=t;if(i===void 0||i<=0)return!0;let a=(e-(t.min??0))/i;return Math.abs(a-Math.round(a))<1e-9},S=e=>{if(f(!1),c(e),e===``){u(!1),p.current=void 0,t.onChange(void 0);return}let n=Number(e);x(n)?(u(!1),p.current=n,t.onChange(n)):u(!0)},C=()=>{a===``||l||c(String(Number(a)))},w=()=>{f(l),C()};return e(_,{...t,controlId:m},e(`div`,{className:`dsu-numberWrap`},e(`div`,{className:`dsu-number`},e(`input`,{className:`dsu-input`,type:`number`,inputMode:`numeric`,id:m,value:a,min:t.min,max:t.max,step:t.step,placeholder:t.placeholder,"aria-invalid":v||void 0,"aria-describedby":b,"data-field":t.field,disabled:t.disabled===!0,onChange:e=>{S(e.target.value)},onBlur:w}),t.unit===void 0?null:e(`span`,{className:`dsu-unit`},t.unit)),v?e(`p`,{className:`dsu-error`,id:h},t.invalidHint):null))}function b(t){let[i,a]=s(t.value),[o,c]=s(!1),l=r(),u=t.hint===void 0?void 0:`${l}-hint`;n(()=>{o||a(t.value)},[t.value,o]);let d={id:l,className:`dsu-input${t.multiline===!0?` dsu-textarea`:``}${t.monospace===!0?` dsu-mono`:``}`,value:i,placeholder:t.placeholder,"aria-describedby":u,"data-field":t.field,disabled:t.disabled===!0,onFocus:()=>{c(!0)},onBlur:()=>{c(!1)},onChange:e=>{a(e.target.value),t.onChange(e.target.value)}};return e(_,{...t,controlId:l},t.multiline===!0?e(`textarea`,d):e(`input`,d))}function x(t){let i=t.separator??`comma`,a=t.value.join(i===`newline`?`
83
+ b.current=null,f.current||p.current||g.current||d(!1)},120))},[x]),E=t(e=>{g.current=e},[]);i(()=>{if(!u)return()=>{};S();let e=e=>{let{target:t}=e;t instanceof Node&&y.current?.contains(t)===!0||(g.current?S():C())},t=()=>{S()},n=e=>{let t=e.target;_.current?.contains(t)!==!0&&C()};return document.addEventListener(`pointerdown`,n,!0),window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,t),()=>{document.removeEventListener(`pointerdown`,n,!0),window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,t)}},[u,a.detail,S,C]),n(()=>{if(!u)return()=>{};let e=e=>{e.key===`Escape`&&C()};return document.addEventListener(`keydown`,e),()=>{document.removeEventListener(`keydown`,e)}},[u,C]),n(()=>x,[x]);let D=e(`button`,{ref:v,type:`button`,className:`dsu-helpBtn`,style:{anchorName:l},"aria-label":`${a.label} 说明`,"aria-expanded":u,"aria-controls":c,onClick:()=>{g.current?C():(E(!0),w())}},e(`svg`,{width:12,height:12,viewBox:`0 0 14 14`,"aria-hidden":!0},e(`circle`,{cx:7,cy:7,r:6,fill:`none`,stroke:`currentColor`,strokeWidth:1.2}),e(`path`,{d:`M7 6.2v4`,stroke:`currentColor`,strokeWidth:1.3,strokeLinecap:`round`}),e(`circle`,{cx:7,cy:4.3,r:.8,fill:`currentColor`}))),O=e(`div`,{ref:y,id:c,role:`tooltip`,className:`dsu-tip`,style:{positionAnchor:l,positionTryFallbacks:`flip-block, flip-inline`},hidden:!u},a.detail),k=a.showLabel===!1?null:e(`span`,{className:`dsu-label${a.compact===!0?` dsu-labelMono`:``}`},a.label);return e(`span`,{ref:_,className:`dsu-help`,onMouseEnter:()=>{f.current=!0,w()},onMouseLeave:()=>{f.current=!1,T()},onFocus:()=>{p.current=!0,w()},onBlur:e=>{let t=e.relatedTarget;t instanceof Node&&e.currentTarget.contains(t)||(p.current=!1,T())}},k,D,O)}function _(t){let n=`dsu-label${t.compact===!0?` dsu-labelMono`:``}`,r=t.controlId===void 0?e(`span`,{className:n},t.label):e(`label`,{className:n,htmlFor:t.controlId},t.label);return e(`div`,{className:`dsu-labelRow`},r,t.detail===void 0?null:e(g,{label:t.label,detail:t.detail,showLabel:!1}))}function v(t){let n=t.controlId===void 0?void 0:`${t.controlId}-hint`;return e(`div`,{className:`dsu-field${t.wide===!0?` dsu-fieldWide`:``}`},e(`div`,{className:`dsu-fieldMeta`},e(_,{label:t.label,detail:t.detail,compact:t.compact,controlId:t.controlId}),t.hint===void 0?null:e(`p`,{className:`dsu-hint`,id:n},t.hint)),e(`div`,{className:`dsu-control`},t.children))}function y(t){let n=r(),i=t.hint===void 0?void 0:`${n}-hint`;return e(v,{...t,controlId:n},e(`button`,{type:`button`,role:`switch`,id:n,className:`dsu-switch`,"aria-checked":t.checked,"aria-describedby":i,"data-field":t.field,disabled:t.disabled===!0,onClick:()=>{t.onChange(!t.checked)}},e(`span`,{className:`dsu-knob`})))}function b(t){let i=typeof t.value==`number`&&Number.isFinite(t.value)?String(t.value):``,[a,c]=s(i),[l,u]=s(!1),[d,f]=s(!1),p=o(void 0),m=r(),h=r(),g=t.hint===void 0?void 0:`${m}-hint`,_=l&&d,y=[g,_?h:void 0].filter(e=>e!==void 0),b=y.length===0?void 0:y.join(` `);n(()=>{t.value!==p.current&&(p.current=t.value,c(i),u(!1),f(!1))},[t.value,i]);let x=e=>{let n=t.min??-1/0,r=t.max??1/0;if(!Number.isFinite(e)||e<n||e>r)return!1;let{step:i}=t;if(i===void 0||i<=0)return!0;let a=(e-(t.min??0))/i;return Math.abs(a-Math.round(a))<1e-9},S=e=>{if(f(!1),c(e),e===``){u(!1),p.current=void 0,t.onChange(void 0);return}let n=Number(e);x(n)?(u(!1),p.current=n,t.onChange(n)):u(!0)},C=()=>{a===``||l||c(String(Number(a)))},w=()=>{f(l),C()};return e(v,{...t,controlId:m},e(`div`,{className:`dsu-numberWrap`},e(`div`,{className:`dsu-number`},e(`input`,{className:`dsu-input`,type:`number`,inputMode:`numeric`,id:m,value:a,min:t.min,max:t.max,step:t.step,placeholder:t.placeholder,"aria-invalid":_||void 0,"aria-describedby":b,"data-field":t.field,disabled:t.disabled===!0,onChange:e=>{S(e.target.value)},onBlur:w}),t.unit===void 0?null:e(`span`,{className:`dsu-unit`},t.unit)),_?e(`p`,{className:`dsu-error`,id:h},t.invalidHint):null))}function x(t){let[i,a]=s(t.value),[o,c]=s(!1),l=r(),u=t.hint===void 0?void 0:`${l}-hint`;n(()=>{o||a(t.value)},[t.value,o]);let d={id:l,className:`dsu-input${t.multiline===!0?` dsu-textarea`:``}${t.monospace===!0?` dsu-mono`:``}`,value:i,placeholder:t.placeholder,"aria-describedby":u,"data-field":t.field,disabled:t.disabled===!0,onFocus:()=>{c(!0)},onBlur:()=>{c(!1)},onChange:e=>{a(e.target.value),t.onChange(e.target.value)}};return e(v,{...t,controlId:l},t.multiline===!0?e(`textarea`,d):e(`input`,d))}function S(t){let i=t.separator??`comma`,a=t.value.join(i===`newline`?`
82
84
  `:`, `),[o,c]=s(a),[l,u]=s(!1),d=r(),f=t.hint===void 0?void 0:`${d}-hint`;n(()=>{l||c(a)},[a,l]);let p=e=>e.split(i===`newline`?`
83
- `:`,`).map(e=>e.trim()).filter(e=>e.length>0),m={id:d,className:`dsu-input${i===`newline`?` dsu-textarea dsu-mono`:``}`,value:o,placeholder:t.placeholder,"aria-describedby":f,"data-field":t.field,disabled:t.disabled===!0,onFocus:()=>{u(!0)},onBlur:()=>{u(!1)},onChange:e=>{c(e.target.value),t.onChange(p(e.target.value))}};return e(_,{...t,controlId:d},e(i===`newline`?`textarea`:`input`,m))}function S(c){let[l,u]=s(!1),[d,f]=s(0),p=o(null),h=o(null),g=r(),v=r(),y=`--dsu-${v.replaceAll(/[^a-zA-Z0-9]/gu,``)}`,b=c.hint===void 0?void 0:`${v}-hint`,{disabled:x,value:S,options:C,onChange:w}=c,T=a(()=>C.map((e,t)=>({option:e,index:t})).filter(e=>e.option.disabled!==!0),[C]),E=C.find(e=>e.value===S)?.label??S,D=C[d],O=D!==void 0&&D.disabled!==!0,k=t(()=>{let e=p.current,t=h.current;
85
+ `:`,`).map(e=>e.trim()).filter(e=>e.length>0),m={id:d,className:`dsu-input${i===`newline`?` dsu-textarea dsu-mono`:``}`,value:o,placeholder:t.placeholder,"aria-describedby":f,"data-field":t.field,disabled:t.disabled===!0,onFocus:()=>{u(!0)},onBlur:()=>{u(!1)},onChange:e=>{c(e.target.value),t.onChange(p(e.target.value))}};return e(v,{...t,controlId:d},e(i===`newline`?`textarea`:`input`,m))}function C(c){let[l,u]=s(!1),[d,f]=s(0),p=o(null),g=o(null),_=r(),y=r(),b=`--dsu-${y.replaceAll(/[^a-zA-Z0-9]/gu,``)}`,x=c.hint===void 0?void 0:`${y}-hint`,{disabled:S,value:C,options:w,onChange:T}=c,E=a(()=>w.map((e,t)=>({option:e,index:t})).filter(e=>e.option.disabled!==!0),[w]),D=w.find(e=>e.value===C)?.label??C,O=w[d],k=O!==void 0&&O.disabled!==!0,A=t(()=>{let e=p.current,t=g.current;
84
86
  /* v8 ignore next 3 -- place 只在 open 的 layout effect 里调用;refs 为空只可能是卸载竞态 */
85
- if(e===null||t===null)return;let n=e.getBoundingClientRect(),r=Math.min(n.width,window.innerWidth-16);if(t.style.width=`${r}px`,m())return;t.style.marginTop=`0px`;let{left:i}=n;i+r>window.innerWidth-8&&(i=window.innerWidth-r-8);let a=t.offsetHeight,o=n.bottom+6;o+a>window.innerHeight-8&&(o=n.top-a-6);let s=Math.max(8,window.innerWidth-r-8),c=Math.max(8,window.innerHeight-a-8);t.style.left=`${Math.min(Math.max(8,i),s)}px`,t.style.top=`${Math.min(Math.max(8,o),c)}px`},[]),A=t(()=>{u(!1)},[]),j=t(()=>{if(x===!0)return;let e=T.find(e=>e.option.value===S)??T.at(0);e!==void 0&&(f(e.index),u(!0))},[x,S,T]),M=t(e=>{
87
+ if(e===null||t===null)return;let n=e.getBoundingClientRect(),r=Math.min(n.width,window.innerWidth-16);t.style.width=`${r}px`;let i=m()&&t.style.positionArea!==`none`;if(i&&!h(n,t.getBoundingClientRect()))return;i&&(t.style.positionArea=`none`),t.style.marginTop=`0px`;let{left:a}=n;a+r>window.innerWidth-8&&(a=window.innerWidth-r-8);let o=t.offsetHeight,s=n.bottom+6;s+o>window.innerHeight-8&&(s=n.top-o-6);let c=Math.max(8,window.innerWidth-r-8),l=Math.max(8,window.innerHeight-o-8);t.style.left=`${Math.min(Math.max(8,a),c)}px`,t.style.top=`${Math.min(Math.max(8,s),l)}px`},[]),j=t(()=>{u(!1)},[]),M=t(()=>{if(S===!0)return;let e=E.find(e=>e.option.value===C)??E.at(0);e!==void 0&&(f(e.index),u(!0))},[S,C,E]),N=t(e=>{
86
88
  /* v8 ignore next 3 -- 浮层只能经由 openMenu 打开;组件禁用时打不开 */
87
- if(x===!0)return;let t=C[e];
89
+ if(S===!0)return;let t=w[e];
88
90
  /* v8 ignore next 3 -- disabled 选项在浏览器里不派发 click;越界下标由调用方保证 */
89
- t!==void 0&&t.disabled!==!0&&(w(t.value),A(),p.current?.focus())},[x,C,w,A]),N=t(e=>{let t=T.findIndex(e=>e.index===d);
91
+ t!==void 0&&t.disabled!==!0&&(T(t.value),j(),p.current?.focus())},[S,w,T,j]),P=t(e=>{let t=E.findIndex(e=>e.index===d);
90
92
  /* v8 ignore next 5 -- open 时归一 effect 已保证 enabled 非空且 active 落在可用项上 */
91
- if(t===-1||T.length===0)return;let n=(t+e+T.length)%T.length,r=T[n];
93
+ if(t===-1||E.length===0)return;let n=(t+e+E.length)%E.length,r=E[n];
92
94
  /* v8 ignore next 3 -- next 由取模保证在界内 */
93
- r!==void 0&&f(r.index)},[d,T]);i(()=>{if(!l)return()=>{};k();let e=e=>{let t=e.target;h.current?.contains(t)!==!0&&p.current?.contains(t)!==!0&&A()},t=e=>{let{target:t}=e;t instanceof Node&&h.current?.contains(t)===!0||A()},n=()=>{k()};return document.addEventListener(`pointerdown`,e,!0),window.addEventListener(`scroll`,t,!0),window.addEventListener(`resize`,n),()=>{document.removeEventListener(`pointerdown`,e,!0),window.removeEventListener(`scroll`,t,!0),window.removeEventListener(`resize`,n)}},[l,c.options,k,A]),n(()=>{if(!l)return;if(x===!0||T.length===0){A();return}if(T.some(e=>e.index===d))return;let e=T.find(e=>e.option.value===S)??T.at(0);
95
+ r!==void 0&&f(r.index)},[d,E]);i(()=>{if(!l)return()=>{};A();let e=e=>{let t=e.target;g.current?.contains(t)!==!0&&p.current?.contains(t)!==!0&&j()},t=e=>{let{target:t}=e;t instanceof Node&&g.current?.contains(t)===!0||j()},n=()=>{A()};return document.addEventListener(`pointerdown`,e,!0),window.addEventListener(`scroll`,t,!0),window.addEventListener(`resize`,n),()=>{document.removeEventListener(`pointerdown`,e,!0),window.removeEventListener(`scroll`,t,!0),window.removeEventListener(`resize`,n)}},[l,c.options,A,j]),n(()=>{if(!l)return;if(S===!0||E.length===0){j();return}if(E.some(e=>e.index===d))return;let e=E.find(e=>e.option.value===C)??E.at(0);
94
96
  /* v8 ignore next 3 -- enabled 非空在上一分支已保证 */
95
- e!==void 0&&f(e.index)},[l,x,S,C,d,A,T]),i(()=>{if(!l)return;let e=h.current;
97
+ e!==void 0&&f(e.index)},[l,S,C,w,d,j,E]),i(()=>{if(!l)return;let e=g.current;
96
98
  /* v8 ignore next 2 -- 同上,menu 在 open 的 commit 之后必然已挂上 */
97
99
  if(e===null)return;let t=e.querySelector(`[data-active="true"]`);
98
100
  /* v8 ignore next 2 -- active 已由归一 effect 保证落在可用项上 */
99
- t!==null&&(t.offsetTop<e.scrollTop?e.scrollTop=t.offsetTop:t.offsetTop+t.offsetHeight>e.scrollTop+e.clientHeight&&(e.scrollTop=t.offsetTop+t.offsetHeight-e.clientHeight))},[l,d,C]);let P=e=>{if(e.key===`ArrowDown`||e.key===`ArrowUp`){if(e.preventDefault(),!l){j();return}N(e.key===`ArrowDown`?1:-1)}else if(e.key===`Home`||e.key===`End`){if(e.preventDefault(),l||j(),T.length===0)return;let t=e.key===`Home`?T.at(0):T.at(-1);
101
+ t!==null&&(t.offsetTop<e.scrollTop?e.scrollTop=t.offsetTop:t.offsetTop+t.offsetHeight>e.scrollTop+e.clientHeight&&(e.scrollTop=t.offsetTop+t.offsetHeight-e.clientHeight))},[l,d,w]);let F=e=>{if(e.key===`ArrowDown`||e.key===`ArrowUp`){if(e.preventDefault(),!l){M();return}P(e.key===`ArrowDown`?1:-1)}else if(e.key===`Home`||e.key===`End`){if(e.preventDefault(),l||M(),E.length===0)return;let t=e.key===`Home`?E.at(0):E.at(-1);
100
102
  /* v8 ignore next 3 -- enabled 为空已在上一条返回 */
101
- if(t===void 0)return;f(t.index)}else if(e.key===`Enter`||e.key===` `){if(e.preventDefault(),!l){j();return}M(d)}else(e.key===`Tab`||e.key===`Escape`)&&A()},F=[],I;for(let[t,n]of C.entries())n.group!==I&&(n.group!==void 0&&F.push(e(`div`,{key:`group-${t}-${n.group}`,className:`dsu-optionGroup`,role:`presentation`},n.group)),I=n.group),F.push(e(`button`,{key:`option-${n.value}`,type:`button`,role:`option`,id:`${g}-${t}`,className:`dsu-option`,tabIndex:-1,"aria-selected":n.value===c.value,"data-active":t===d,disabled:n.disabled===!0,onMouseDown:e=>{e.preventDefault()},onClick:()=>{M(t)},onMouseEnter:()=>{
103
+ if(t===void 0)return;f(t.index)}else if(e.key===`Enter`||e.key===` `){if(e.preventDefault(),!l){M();return}N(d)}else(e.key===`Tab`||e.key===`Escape`)&&j()},I=[],L;for(let[t,n]of w.entries())n.group!==L&&(n.group!==void 0&&I.push(e(`div`,{key:`group-${t}-${n.group}`,className:`dsu-optionGroup`,role:`presentation`},n.group)),L=n.group),I.push(e(`button`,{key:`option-${n.value}`,type:`button`,role:`option`,id:`${_}-${t}`,className:`dsu-option`,tabIndex:-1,"aria-selected":n.value===c.value,"data-active":t===d,disabled:n.disabled===!0,onMouseDown:e=>{e.preventDefault()},onClick:()=>{N(t)},onMouseEnter:()=>{
102
104
  /* v8 ignore next -- happy-dom 对 disabled 元素不派发 mouse 事件;浏览器实现各有差异,保留禁用检查 */
103
- n.disabled!==!0&&f(t)}},e(`span`,null,n.label),e(`svg`,{className:`dsu-check`,width:14,height:14,viewBox:`0 0 14 14`,"aria-hidden":!0},e(`path`,{d:`M2.5 7.5l3 3 6-7`,fill:`none`,stroke:`currentColor`,strokeWidth:1.5,strokeLinecap:`round`,strokeLinejoin:`round`}))));return e(_,{...c,controlId:v},e(`div`,{className:`dsu-selectWrap`,onBlur:e=>{let t=e.relatedTarget;t instanceof Node&&e.currentTarget.contains(t)||A()}},e(`button`,{ref:p,type:`button`,id:v,style:{anchorName:y},className:`dsu-select dsu-input`,role:`combobox`,"aria-haspopup":`listbox`,"aria-expanded":l,"aria-controls":`${g}-list`,"aria-activedescendant":l&&O?`${g}-${d}`:void 0,"aria-describedby":b,"data-field":c.field,disabled:x===!0||C.length===0,onClick:()=>{l?A():j()},onKeyDown:P},e(`span`,{className:`dsu-selectValue`},E),e(`svg`,{className:`dsu-chevron`,width:14,height:14,viewBox:`0 0 14 14`,"aria-hidden":!0},e(`path`,{d:`M3 5l4 4 4-4`,fill:`none`,stroke:`currentColor`,strokeWidth:1.5,strokeLinecap:`round`,strokeLinejoin:`round`}))),e(`div`,{ref:h,id:`${g}-list`,role:`listbox`,className:`dsu-menu`,style:{positionAnchor:y,positionTryFallbacks:`flip-block, flip-inline`},"aria-label":c.label,hidden:!l},...F)))}function C(t){let n=!t.writable||t.busy||!t.dirty,r;return r=t.error===null?t.writable?t.dirty?t.dirtyLabel:t.cleanLabel:t.readOnlyLabel:t.error,e(`div`,{className:`dsu-savebar`,"data-dirty":t.dirty},e(`button`,{type:`button`,className:`dsu-btn dsu-btnPrimary`,"data-field":`save`,disabled:n,onClick:t.onSave},t.busy?t.savingLabel:t.saveLabel),e(`button`,{type:`button`,className:`dsu-btn`,"data-field":`discard`,disabled:n,onClick:t.onDiscard},t.revertLabel),e(`span`,{role:`status`,className:t.error===null?`dsu-status`:`dsu-status dsu-statusError`},r))}export{b as a,g as c,f as d,d as f,c as h,y as i,h as l,l as m,S as n,v as o,p,x as r,_ as s,C as t,u};
105
+ n.disabled!==!0&&f(t)}},e(`span`,null,n.label),e(`svg`,{className:`dsu-check`,width:14,height:14,viewBox:`0 0 14 14`,"aria-hidden":!0},e(`path`,{d:`M2.5 7.5l3 3 6-7`,fill:`none`,stroke:`currentColor`,strokeWidth:1.5,strokeLinecap:`round`,strokeLinejoin:`round`}))));return e(v,{...c,controlId:y},e(`div`,{className:`dsu-selectWrap`,onBlur:e=>{let t=e.relatedTarget;t instanceof Node&&e.currentTarget.contains(t)||j()}},e(`button`,{ref:p,type:`button`,id:y,style:{anchorName:b},className:`dsu-select dsu-input`,role:`combobox`,"aria-haspopup":`listbox`,"aria-expanded":l,"aria-controls":`${_}-list`,"aria-activedescendant":l&&k?`${_}-${d}`:void 0,"aria-describedby":x,"data-field":c.field,disabled:S===!0||w.length===0,onClick:()=>{l?j():M()},onKeyDown:F},e(`span`,{className:`dsu-selectValue`},D),e(`svg`,{className:`dsu-chevron`,width:14,height:14,viewBox:`0 0 14 14`,"aria-hidden":!0},e(`path`,{d:`M3 5l4 4 4-4`,fill:`none`,stroke:`currentColor`,strokeWidth:1.5,strokeLinecap:`round`,strokeLinejoin:`round`}))),e(`div`,{ref:g,id:`${_}-list`,role:`listbox`,className:`dsu-menu`,style:{positionAnchor:b,positionTryFallbacks:`flip-block, flip-inline`},"aria-label":c.label,hidden:!l},...I)))}function w(t){let n=!t.writable||t.busy||!t.dirty,r;return r=t.error===null?t.writable?t.dirty?t.dirtyLabel:t.cleanLabel:t.readOnlyLabel:t.error,e(`div`,{className:`dsu-savebar`,"data-dirty":t.dirty},e(`button`,{type:`button`,className:`dsu-btn dsu-btnPrimary`,"data-field":`save`,disabled:n,onClick:t.onSave},t.busy?t.savingLabel:t.saveLabel),e(`button`,{type:`button`,className:`dsu-btn`,"data-field":`discard`,disabled:n,onClick:t.onDiscard},t.revertLabel),e(`span`,{role:`status`,className:t.error===null?`dsu-status`:`dsu-status dsu-statusError`},r))}export{x as a,_ as c,f as d,d as f,c as h,b as i,g as l,l as m,C as n,y as o,p,S as r,v as s,w as t,u};
package/dist/card-ui.js CHANGED
@@ -1 +1 @@
1
- export{h as CARD_UI_CSS,u as CardForm,s as Field,d as FieldGrid,c as FieldLabel,l as InfoTip,r as ListField,i as NumberField,t as SaveBar,f as Section,n as SelectField,p as StatusBar,a as TextField,o as ToggleField,m as splitHint}from"./card-ui-CV_X0CV5.js";
1
+ export{h as CARD_UI_CSS,u as CardForm,s as Field,d as FieldGrid,c as FieldLabel,l as InfoTip,r as ListField,i as NumberField,t as SaveBar,f as Section,n as SelectField,p as StatusBar,a as TextField,o as ToggleField,m as splitHint}from"./card-ui-yf56_khz.js";
@@ -1 +1 @@
1
- import{a as e,c as t,d as n,f as r,h as i,i as a,l as o,m as s,n as c,o as l,p as u,r as d,s as f,t as p,u as m}from"./card-ui-CV_X0CV5.js";import{diffTouched as h}from"./card-diff.js";import{claimApply as g}from"./card-apply.js";import{fieldOf as _,isRecord as v}from"./record.js";import{errorText as y}from"./errors.js";const b=`@jayyuen66/dsh-plugin-shared`;function x(){}export{i as CARD_UI_CSS,m as CardForm,f as Field,n as FieldGrid,t as FieldLabel,o as InfoTip,d as ListField,a as NumberField,p as SaveBar,r as Section,c as SelectField,u as StatusBar,e as TextField,l as ToggleField,x as apply,g as claimApply,h as diffTouched,y as errorText,_ as fieldOf,v as isRecord,b as name,s as splitHint};
1
+ import{a as e,c as t,d as n,f as r,h as i,i as a,l as o,m as s,n as c,o as l,p as u,r as d,s as f,t as p,u as m}from"./card-ui-yf56_khz.js";import{diffTouched as h}from"./card-diff.js";import{claimApply as g}from"./card-apply.js";import{fieldOf as _,isRecord as v}from"./record.js";import{errorText as y}from"./errors.js";const b=`@jayyuen66/dsh-plugin-shared`;function x(){}export{i as CARD_UI_CSS,m as CardForm,f as Field,n as FieldGrid,t as FieldLabel,o as InfoTip,d as ListField,a as NumberField,p as SaveBar,r as Section,c as SelectField,u as StatusBar,e as TextField,l as ToggleField,x as apply,g as claimApply,h as diffTouched,y as errorText,_ as fieldOf,v as isRecord,b as name,s as splitHint};
package/dist/client.js CHANGED
@@ -129,6 +129,30 @@ function cssAnchorSupported() {
129
129
  if ("happyDOM" in globalThis) return false;
130
130
  return typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("position-area: block-end");
131
131
  }
132
+ /**
133
+ * 锚定之后浮层是否真的落在触发器上。
134
+ *
135
+ * cssAnchorSupported() 只回答「这个引擎认识这套 CSS」,不回答「这条规则最终有没有生效」。
136
+ * 0.2.5–0.2.6 的事故形态就是后者:规则写法(span-inline-start)把浮层钉到视口左边缘,
137
+ * 而引擎完全支持它,于是没有任何一层会报错——只有实测矩形看得见。宿主若用更高优先级的
138
+ * 规则覆盖 position-area,症状相同(元素仍是 position:fixed,没有 left/top 时落到静态
139
+ * 位置即视口左侧)。
140
+ *
141
+ * 判据用「对齐」而不是「坐标相等」:flip-inline 会把浮层改成与触发器右边缘对齐,所以
142
+ * 行内起始边或结束边任一重合即算贴住;块向则要求不重叠(flip-block 翻到上方时浮层的
143
+ * 下边缘贴在触发器上边缘)。两条都不成立时调用方改用 JS 矩形定位。
144
+ * @param trigger - 触发器(下拉按钮 / 说明按钮)的矩形
145
+ * @param floating - 浮层(候选列表 / 说明浮层)的矩形
146
+ * @returns 浮层没有贴住触发器时为 true
147
+ */
148
+ function anchorPlacementOff(trigger, floating) {
149
+ const inlineStart = Math.abs(floating.left - trigger.left) <= 2;
150
+ const inlineEnd = Math.abs(floating.right - trigger.right) <= 2;
151
+ if (!inlineStart && !inlineEnd) return true;
152
+ const below = floating.top >= trigger.bottom - 2;
153
+ const above = floating.bottom <= trigger.top + 2;
154
+ return !below && !above;
155
+ }
132
156
  // lib/card-ui/field.ts
133
157
  /** 说明按钮与浮层:悬停/聚焦显示,点击钉住,Esc 或点击外部关闭。 */
134
158
  function InfoTip(props) {
@@ -153,9 +177,11 @@ function InfoTip(props) {
153
177
  const tip = tipRef.current;
154
178
  /* v8 ignore next 3 -- place 只在 open 的 layout effect 与挂载期监听器里调用;refs 为空只可能是卸载竞态 */
155
179
  if (anchor === null || tip === null) return;
156
- if (cssAnchorSupported()) return;
157
- tip.style.marginTop = "0px";
180
+ const anchored = cssAnchorSupported() && tip.style.positionArea !== "none";
158
181
  const rect = anchor.getBoundingClientRect();
182
+ if (anchored && !anchorPlacementOff(rect, tip.getBoundingClientRect())) return;
183
+ if (anchored) tip.style.positionArea = "none";
184
+ tip.style.marginTop = "0px";
159
185
  const width = tip.offsetWidth;
160
186
  const height = tip.offsetHeight;
161
187
  let { left } = rect;
@@ -532,7 +558,9 @@ function SelectField(props) {
532
558
  const rect = trigger.getBoundingClientRect();
533
559
  const width = Math.min(rect.width, window.innerWidth - 16);
534
560
  menu.style.width = `${width}px`;
535
- if (cssAnchorSupported()) return;
561
+ const anchored = cssAnchorSupported() && menu.style.positionArea !== "none";
562
+ if (anchored && !anchorPlacementOff(rect, menu.getBoundingClientRect())) return;
563
+ if (anchored) menu.style.positionArea = "none";
536
564
  menu.style.marginTop = "0px";
537
565
  let { left } = rect;
538
566
  if (left + width > window.innerWidth - 8) left = window.innerWidth - width - 8;
@@ -5,3 +5,22 @@
5
5
  * 误返 true,但它并不真做 anchor 布局;happy-dom 在 window 上暴露 happyDOM 属性,据此排除
6
6
  * (真实浏览器没有该属性)。 */
7
7
  export declare function cssAnchorSupported(): boolean;
8
+ /** 几何判据的容差(px):亚像素舍入、1px 边框与缩放都不该触发回退。 */
9
+ export declare const ANCHOR_PLACEMENT_TOLERANCE = 2;
10
+ /**
11
+ * 锚定之后浮层是否真的落在触发器上。
12
+ *
13
+ * cssAnchorSupported() 只回答「这个引擎认识这套 CSS」,不回答「这条规则最终有没有生效」。
14
+ * 0.2.5–0.2.6 的事故形态就是后者:规则写法(span-inline-start)把浮层钉到视口左边缘,
15
+ * 而引擎完全支持它,于是没有任何一层会报错——只有实测矩形看得见。宿主若用更高优先级的
16
+ * 规则覆盖 position-area,症状相同(元素仍是 position:fixed,没有 left/top 时落到静态
17
+ * 位置即视口左侧)。
18
+ *
19
+ * 判据用「对齐」而不是「坐标相等」:flip-inline 会把浮层改成与触发器右边缘对齐,所以
20
+ * 行内起始边或结束边任一重合即算贴住;块向则要求不重叠(flip-block 翻到上方时浮层的
21
+ * 下边缘贴在触发器上边缘)。两条都不成立时调用方改用 JS 矩形定位。
22
+ * @param trigger - 触发器(下拉按钮 / 说明按钮)的矩形
23
+ * @param floating - 浮层(候选列表 / 说明浮层)的矩形
24
+ * @returns 浮层没有贴住触发器时为 true
25
+ */
26
+ export declare function anchorPlacementOff(trigger: DOMRect, floating: DOMRect): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jayyuen66/dsh-plugin-shared",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "dsh 自研插件的共享工具库:tool 事件流记账扫描 + 卡片 apply/差异骨架 + 统一设置卡 UI 组件 + 官方作业结局映射 + 项目键派生 + 代理对安全截断。宿主半由各插件 import;客户端半以 ./client 共享行由插件 patch 启用,不由用户单独停用",
5
5
  "keywords": [
6
6
  "cordis",