@vielzeug/refine 3.2.1 → 3.3.0

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.
Files changed (108) hide show
  1. package/dist/chip.cjs +9 -9
  2. package/dist/chip.cjs.map +1 -1
  3. package/dist/chip.js +38 -35
  4. package/dist/chip.js.map +1 -1
  5. package/dist/command-palette.cjs +5 -5
  6. package/dist/command-palette.cjs.map +1 -1
  7. package/dist/command-palette.js +5 -5
  8. package/dist/command-palette.js.map +1 -1
  9. package/dist/content/card/card.css.cjs +1 -1
  10. package/dist/content/card/card.css.cjs.map +1 -1
  11. package/dist/content/card/card.css.js +1 -1
  12. package/dist/content/card/card.css.js.map +1 -1
  13. package/dist/content/index.d.ts +4 -0
  14. package/dist/content/index.d.ts.map +1 -1
  15. package/dist/content/keyboard-key/keyboard-key.css.cjs +2 -0
  16. package/dist/content/keyboard-key/keyboard-key.css.cjs.map +1 -0
  17. package/dist/content/keyboard-key/keyboard-key.css.js +6 -0
  18. package/dist/content/keyboard-key/keyboard-key.css.js.map +1 -0
  19. package/dist/content/keyboard-key/keyboard-key.d.ts +12 -0
  20. package/dist/content/keyboard-key/keyboard-key.d.ts.map +1 -0
  21. package/dist/content/keyboard-key/keyboard-shortcut.css.cjs +2 -0
  22. package/dist/content/keyboard-key/keyboard-shortcut.css.cjs.map +1 -0
  23. package/dist/content/keyboard-key/keyboard-shortcut.css.js +6 -0
  24. package/dist/content/keyboard-key/keyboard-shortcut.css.js.map +1 -0
  25. package/dist/content/qr-code/qr-code.css.cjs +2 -0
  26. package/dist/content/qr-code/qr-code.css.cjs.map +1 -0
  27. package/dist/content/qr-code/qr-code.css.js +6 -0
  28. package/dist/content/qr-code/qr-code.css.js.map +1 -0
  29. package/dist/content/qr-code/qr-code.d.ts +74 -0
  30. package/dist/content/qr-code/qr-code.d.ts.map +1 -0
  31. package/dist/counter.cjs +91 -0
  32. package/dist/counter.cjs.map +1 -0
  33. package/dist/counter.js +180 -0
  34. package/dist/counter.js.map +1 -0
  35. package/dist/custom-elements.json +4183 -3462
  36. package/dist/disclosure/tabs/tabs.css.cjs +1 -1
  37. package/dist/disclosure/tabs/tabs.css.cjs.map +1 -1
  38. package/dist/disclosure/tabs/tabs.css.js +1 -1
  39. package/dist/disclosure/tabs/tabs.css.js.map +1 -1
  40. package/dist/feedback/chip/chip.css.cjs +1 -1
  41. package/dist/feedback/chip/chip.css.cjs.map +1 -1
  42. package/dist/feedback/chip/chip.css.js +1 -1
  43. package/dist/feedback/chip/chip.css.js.map +1 -1
  44. package/dist/feedback/chip/chip.d.ts +6 -2
  45. package/dist/feedback/chip/chip.d.ts.map +1 -1
  46. package/dist/feedback/progress/progress.css.cjs +1 -1
  47. package/dist/feedback/progress/progress.css.cjs.map +1 -1
  48. package/dist/feedback/progress/progress.css.js +1 -1
  49. package/dist/feedback/progress/progress.css.js.map +1 -1
  50. package/dist/feedback/progress/progress.d.ts +6 -0
  51. package/dist/feedback/progress/progress.d.ts.map +1 -1
  52. package/dist/frameworks/elements.d.ts +1 -1
  53. package/dist/inputs/button/button.css.cjs +1 -1
  54. package/dist/inputs/button/button.css.cjs.map +1 -1
  55. package/dist/inputs/button/button.css.js +1 -1
  56. package/dist/inputs/button/button.css.js.map +1 -1
  57. package/dist/inputs/counter/counter.css.cjs +2 -0
  58. package/dist/inputs/counter/counter.css.cjs.map +1 -0
  59. package/dist/inputs/counter/counter.css.js +6 -0
  60. package/dist/inputs/counter/counter.css.js.map +1 -0
  61. package/dist/inputs/counter/counter.d.ts +100 -0
  62. package/dist/inputs/counter/counter.d.ts.map +1 -0
  63. package/dist/inputs/index.d.ts +4 -0
  64. package/dist/inputs/index.d.ts.map +1 -1
  65. package/dist/inputs/qr-scanner/qr-scanner.css.cjs +2 -0
  66. package/dist/inputs/qr-scanner/qr-scanner.css.cjs.map +1 -0
  67. package/dist/inputs/qr-scanner/qr-scanner.css.js +6 -0
  68. package/dist/inputs/qr-scanner/qr-scanner.css.js.map +1 -0
  69. package/dist/inputs/qr-scanner/qr-scanner.d.ts +87 -0
  70. package/dist/inputs/qr-scanner/qr-scanner.d.ts.map +1 -0
  71. package/dist/keyboard-key.cjs +9 -0
  72. package/dist/keyboard-key.cjs.map +1 -0
  73. package/dist/keyboard-key.js +36 -0
  74. package/dist/keyboard-key.js.map +1 -0
  75. package/dist/menu.cjs +1 -1
  76. package/dist/menu.cjs.map +1 -1
  77. package/dist/menu.js +2 -1
  78. package/dist/menu.js.map +1 -1
  79. package/dist/overlay/command-palette/command-palette.css.cjs +1 -1
  80. package/dist/overlay/command-palette/command-palette.css.cjs.map +1 -1
  81. package/dist/overlay/command-palette/command-palette.css.js +1 -1
  82. package/dist/overlay/command-palette/command-palette.css.js.map +1 -1
  83. package/dist/overlay/command-palette/command-palette.d.ts +1 -0
  84. package/dist/overlay/command-palette/command-palette.d.ts.map +1 -1
  85. package/dist/progress.cjs +14 -6
  86. package/dist/progress.cjs.map +1 -1
  87. package/dist/progress.js +19 -7
  88. package/dist/progress.js.map +1 -1
  89. package/dist/qr-code.cjs +15 -0
  90. package/dist/qr-code.cjs.map +1 -0
  91. package/dist/qr-code.js +70 -0
  92. package/dist/qr-code.js.map +1 -0
  93. package/dist/qr-scanner.cjs +46 -0
  94. package/dist/qr-scanner.cjs.map +1 -0
  95. package/dist/qr-scanner.js +129 -0
  96. package/dist/qr-scanner.js.map +1 -0
  97. package/dist/refine.cjs +327 -166
  98. package/dist/refine.cjs.map +1 -1
  99. package/dist/refine.iife.js +355 -194
  100. package/dist/refine.iife.js.map +1 -1
  101. package/dist/refine.js +298 -137
  102. package/dist/refine.js.map +1 -1
  103. package/dist/tabs.cjs +2 -2
  104. package/dist/tabs.cjs.map +1 -1
  105. package/dist/tabs.js +37 -34
  106. package/dist/tabs.js.map +1 -1
  107. package/dist/types/elements.d.ts +9 -0
  108. package/package.json +34 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-key.js","names":[],"sources":["../src/content/keyboard-key/keyboard-key.ts"],"sourcesContent":["import { define, html, prop } from '@vielzeug/ore';\nimport { reducedMotionMixin } from '../../styles';\nimport componentStyles from './keyboard-key.css?inline';\nimport shortcutStyles from './keyboard-shortcut.css?inline';\n\nexport type KeyboardKeySize = 'sm' | 'lg';\n\nexport type OreKeyboardKeyProps = {\n pressed?: boolean;\n size?: KeyboardKeySize;\n symbol?: string;\n};\n\nexport type OreKeyboardShortcutProps = {\n pressed?: boolean;\n};\n\nexport const KEYBOARD_SHORTCUT_TAG = 'ore-keyboard-shortcut' as const;\ndefine<OreKeyboardShortcutProps>(KEYBOARD_SHORTCUT_TAG, {\n props: {\n pressed: prop.bool(false),\n },\n setup(props) {\n return html`\n <span class=\"shortcut\" part=\"shortcut\" ?data-pressed=\"${props.pressed}\"><slot></slot></span>\n `;\n },\n styles: [reducedMotionMixin, shortcutStyles],\n});\n\nexport const KEYBOARD_KEY_TAG = 'ore-keyboard-key' as const;\ndefine<OreKeyboardKeyProps>(KEYBOARD_KEY_TAG, {\n props: {\n pressed: prop.bool(false),\n size: prop.string<KeyboardKeySize>('sm'),\n symbol: prop.string(),\n },\n setup(props) {\n return html`\n <kbd class=\"key\" part=\"key\" ?data-has-symbol=\"${() => Boolean(props.symbol.value)}\" ?data-pressed=\"${props.pressed}\">\n <span class=\"symbol\" aria-hidden=\"true\" ?hidden=\"${() => !props.symbol.value}\">${props.symbol}</span>\n <span class=\"label\"><slot></slot></span>\n </kbd>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n"],"mappings":";;;;;AAiBA,IAAa,IAAwB;AACrC,EAAiC,GAAuB;CACtD,OAAO,EACL,SAAS,EAAK,KAAK,EAAK,EAC1B;CACA,MAAM,GAAO;EACX,OAAO,CAAI;8DAC+C,EAAM,QAAQ;;CAE1E;CACA,QAAQ,CAAC,GAAoB,CAAc;AAC7C,CAAC;AAED,IAAa,IAAmB;AAChC,EAA4B,GAAkB;CAC5C,OAAO;EACL,SAAS,EAAK,KAAK,EAAK;EACxB,MAAM,EAAK,OAAwB,IAAI;EACvC,QAAQ,EAAK,OAAO;CACtB;CACA,MAAM,GAAO;EACX,OAAO,CAAI;4DAC6C,EAAQ,EAAM,OAAO,MAAO,mBAAmB,EAAM,QAAQ;iEACxD,CAAC,EAAM,OAAO,MAAM,IAAI,EAAM,OAAO;;;;CAIpG;CACA,QAAQ,CAAC,GAAoB,CAAe;AAC9C,CAAC"}
package/dist/menu.cjs CHANGED
@@ -14,7 +14,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
14
14
  <span class="icon-slot"><slot name="icon"></slot></span>
15
15
  <span class="item-label"><slot></slot></span>
16
16
  </div>
17
- `},styles:[t.colorThemeMixin,u.default]});var g=`ore-menu-separator`;(0,f.define)(g,{setup(){return f.html``},styles:[d.default]});var _=e=>e===`checkbox`||e===`radio`,v=e=>e==null?void 0:e===``||e===`true`,y=`ore-menu`;(0,f.define)(y,{props:{...s.sizableBundle,...s.disablableBundle,"default-open":f.prop.bool(!1),open:{default:void 0,parse:v},placement:f.prop.oneOf([`bottom`,`bottom-start`,`bottom-end`,`top`,`top-start`,`top-end`],`bottom-start`)},setup(e){let t=(0,f.getHost)(),s=(0,f.useEmit)(),c=(0,f.useSlots)(),l=f.watchEffect,u=(0,f.createId)(`menu`),d=(0,p.computed)(()=>!!e.disabled.value),h=r.lifecycleSignal(f.onCleanup),g=null,v=null,y=null;function b(){return Array.from(t.querySelectorAll(`ore-menu-item:not([disabled])`))}function x(e){return e?e.shadowRoot?.querySelector(`[role^="menuitem"]`)??e:null}function S(){return b().findIndex(e=>{let t=x(e);return e===document.activeElement||t===document.activeElement})}let C=(0,p.signal)(!1),w=null,T=o.createDropdownPositioner({getFloating:()=>v,getPlacement:()=>e.placement.value??`bottom-start`,getReference:()=>g,matchWidth:!1,offsetPx:4,padding:6}),E=a.createListControl({disabled:(0,p.computed)(()=>!C.value),getItems:b,isItemDisabled:e=>e.hasAttribute(`disabled`),onNavigate:({item:e})=>{x(e)?.focus()},signal:h}),D=(e=`programmatic`,t=!0)=>{C.value&&(C.value=!1,E.reset(),w?.(),w=null,t&&(0,m.restoreFocus)(()=>g),s(`open-change`,{open:!1,reason:e}))},O=(e=`programmatic`)=>{d.value||C.value||(C.value=!0,T.update(),w=T.startAutoUpdate?.()??null,s(`open-change`,{open:!0,reason:e}))},k=()=>{C.value?D(`trigger`):O(`click`)};i.createOutsidePointerDismissal({getTargets:()=>[t,v],isActive:()=>C.value,onDismiss:()=>D(`outsideClick`),signal:h});let A=!1;(0,p.watch)(e.open,t=>{t===void 0?A?D(`programmatic`):e[`default-open`].value&&O(`programmatic`):t?O(`programmatic`):D(`programmatic`),A=!0},{immediate:!0}),h.addEventListener(`abort`,()=>{C.value&&(C.value=!1,E.reset(),w?.(),w=null)},{once:!0});let j=e=>{let n=e.getAttribute(`type`),r=_(n);if(n===`checkbox`)e.toggleAttribute(`checked`,!e.hasAttribute(`checked`));else if(n===`radio`)for(let n of t.querySelectorAll(`ore-menu-item[type="radio"]`))n.toggleAttribute(`checked`,n===e);let i=e.getAttribute(`value`)??``,a=r?e.hasAttribute(`checked`):void 0;s(`select`,{checked:a,value:i}),r||D(`programmatic`)},M=n.createInteraction({keys:[`Enter`,` `,`ArrowDown`],onPress:()=>{O(`keyboard`),requestAnimationFrame(()=>E.set(0))}}),N=n.createInteraction({onPress:()=>{let e=E.getActiveItem();e&&j(e)}});function P(e){if(d.value)return;if(!C.value){M.handleKeydown(e);return}let t=S();if(t>=0&&E.set(t),e.key===`Escape`){e.preventDefault(),D(`escape`);return}if(!E.handleKeydown(e)){if(e.key===` `||e.key===`Enter`){N.handleKeydown(e);return}e.key===`Tab`&&D(`programmatic`)}}(0,f.bind)({on:{click:e=>{let t=e.composedPath();if(!C.value)return;let n=t.find(e=>e instanceof HTMLElement&&e.tagName===`ORE-MENU-ITEM`)??e.target?.closest(`ore-menu-item`)??null;n&&!n.hasAttribute(`disabled`)&&j(n)}}}),l(()=>{let e=C.value;v&&v.toggleAttribute(`data-open`,e)});function F(){if(y?.(),y=null,g=c.elements(`trigger`).value?.[0]??null,!g)return;let e=[],t=(0,f.bind)({attr:{"aria-controls":()=>u,"aria-disabled":()=>d.value,"aria-expanded":()=>String(C.value),"aria-haspopup":`menu`}},{target:g}),n=e=>{e.stopPropagation(),!d.value&&k()},r=e=>{P(e)};g.addEventListener(`click`,n),g.addEventListener(`keydown`,r),e.push(()=>g?.removeEventListener(`click`,n)),e.push(()=>g?.removeEventListener(`keydown`,r)),y=()=>{t();for(let t of e)t()}}return(0,p.watch)(c.elements(`trigger`),F,{immediate:!0}),(0,f.onMounted)(()=>(F(),()=>{y?.(),y=null})),f.html`
17
+ `},styles:[t.colorThemeMixin,u.default]});var g=`ore-menu-separator`;(0,f.define)(g,{setup(){return f.html``},styles:[d.default]});var _=e=>e===`checkbox`||e===`radio`,v=e=>e==null?void 0:e===``||e===`true`,y=`ore-menu`;(0,f.define)(y,{props:{...s.sizableBundle,...s.disablableBundle,"default-open":f.prop.bool(!1),open:{default:void 0,parse:v},placement:f.prop.oneOf([`bottom`,`bottom-start`,`bottom-end`,`top`,`top-start`,`top-end`],`bottom-start`)},setup(e){let t=(0,f.getHost)(),s=(0,f.useEmit)(),c=(0,f.useSlots)(),l=f.watchEffect,u=(0,f.createId)(`menu`),d=(0,p.computed)(()=>!!e.disabled.value),h=r.lifecycleSignal(f.onCleanup),g=null,v=null,y=null;function b(){return Array.from(t.querySelectorAll(`ore-menu-item:not([disabled])`))}function x(e){return e?e.shadowRoot?.querySelector(`[role^="menuitem"]`)??e:null}function S(){return b().findIndex(e=>{let t=x(e);return e===document.activeElement||t===document.activeElement})}let C=(0,p.signal)(!1),w=null,T=o.createDropdownPositioner({getFloating:()=>v,getPlacement:()=>e.placement.value??`bottom-start`,getReference:()=>g,matchWidth:!1,offsetPx:4,padding:6,useClippingAncestor:!1}),E=a.createListControl({disabled:(0,p.computed)(()=>!C.value),getItems:b,isItemDisabled:e=>e.hasAttribute(`disabled`),onNavigate:({item:e})=>{x(e)?.focus()},signal:h}),D=(e=`programmatic`,t=!0)=>{C.value&&(C.value=!1,E.reset(),w?.(),w=null,t&&(0,m.restoreFocus)(()=>g),s(`open-change`,{open:!1,reason:e}))},O=(e=`programmatic`)=>{d.value||C.value||(C.value=!0,T.update(),w=T.startAutoUpdate?.()??null,s(`open-change`,{open:!0,reason:e}))},k=()=>{C.value?D(`trigger`):O(`click`)};i.createOutsidePointerDismissal({getTargets:()=>[t,v],isActive:()=>C.value,onDismiss:()=>D(`outsideClick`),signal:h});let A=!1;(0,p.watch)(e.open,t=>{t===void 0?A?D(`programmatic`):e[`default-open`].value&&O(`programmatic`):t?O(`programmatic`):D(`programmatic`),A=!0},{immediate:!0}),h.addEventListener(`abort`,()=>{C.value&&(C.value=!1,E.reset(),w?.(),w=null)},{once:!0});let j=e=>{let n=e.getAttribute(`type`),r=_(n);if(n===`checkbox`)e.toggleAttribute(`checked`,!e.hasAttribute(`checked`));else if(n===`radio`)for(let n of t.querySelectorAll(`ore-menu-item[type="radio"]`))n.toggleAttribute(`checked`,n===e);let i=e.getAttribute(`value`)??``,a=r?e.hasAttribute(`checked`):void 0;s(`select`,{checked:a,value:i}),r||D(`programmatic`)},M=n.createInteraction({keys:[`Enter`,` `,`ArrowDown`],onPress:()=>{O(`keyboard`),requestAnimationFrame(()=>E.set(0))}}),N=n.createInteraction({onPress:()=>{let e=E.getActiveItem();e&&j(e)}});function P(e){if(d.value)return;if(!C.value){M.handleKeydown(e);return}let t=S();if(t>=0&&E.set(t),e.key===`Escape`){e.preventDefault(),D(`escape`);return}if(!E.handleKeydown(e)){if(e.key===` `||e.key===`Enter`){N.handleKeydown(e);return}e.key===`Tab`&&D(`programmatic`)}}(0,f.bind)({on:{click:e=>{let t=e.composedPath();if(!C.value)return;let n=t.find(e=>e instanceof HTMLElement&&e.tagName===`ORE-MENU-ITEM`)??e.target?.closest(`ore-menu-item`)??null;n&&!n.hasAttribute(`disabled`)&&j(n)}}}),l(()=>{let e=C.value;v&&v.toggleAttribute(`data-open`,e)});function F(){if(y?.(),y=null,g=c.elements(`trigger`).value?.[0]??null,!g)return;let e=[],t=(0,f.bind)({attr:{"aria-controls":()=>u,"aria-disabled":()=>d.value,"aria-expanded":()=>String(C.value),"aria-haspopup":`menu`}},{target:g}),n=e=>{e.stopPropagation(),!d.value&&k()},r=e=>{P(e)};g.addEventListener(`click`,n),g.addEventListener(`keydown`,r),e.push(()=>g?.removeEventListener(`click`,n)),e.push(()=>g?.removeEventListener(`keydown`,r)),y=()=>{t();for(let t of e)t()}}return(0,p.watch)(c.elements(`trigger`),F,{immediate:!0}),(0,f.onMounted)(()=>(F(),()=>{y?.(),y=null})),f.html`
18
18
  <slot name="trigger"></slot>
19
19
  <div
20
20
  class="menu-panel"
package/dist/menu.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"menu.cjs","names":[],"sources":["../src/overlay/menu/menu.ts"],"sourcesContent":["import { restoreFocus } from '@vielzeug/focus';\nimport type { Placement } from '@vielzeug/orbit';\nimport {\n bind,\n createId,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n useEmit,\n useSlots,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport {\n createDropdownPositioner,\n createInteraction,\n createListControl,\n createOutsidePointerDismissal,\n type DropdownCloseReason,\n lifecycleSignal,\n type OverlayOpenChangeDetail,\n type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport componentStyles from './menu.css?inline';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n checked?: boolean;\n value: string;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n 'open-change': OverlayOpenChangeDetail;\n select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: OreMenuItemType;\n value?: string;\n};\n\nexport type OreMenuProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n disabled?: boolean;\n /** Controlled open state. */\n open?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n props: {\n checked: prop.bool(false),\n disabled: prop.bool(false),\n type: prop.string<OreMenuItemType>(),\n value: prop.string(),\n },\n setup(props) {\n const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n const isChecked = () => isCheckable() && props.checked.value;\n const itemRole = () => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n };\n const itemClass = () => {\n const type = props.type.value;\n\n return [\n 'item',\n type === 'checkbox' ? 'is-checkbox' : '',\n type === 'radio' ? 'is-radio' : '',\n isChecked() ? 'is-checked' : '',\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return isCheckable()\n ? html`\n <div\n class=\"${itemClass}\"\n tabindex=\"-1\"\n role=\"${itemRole}\"\n aria-checked=\"${() => String(isChecked())}\"\n aria-disabled=\"${props.disabled}\">\n <span class=\"item-check\" aria-hidden=\"true\"></span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `\n : html`\n <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `;\n },\n styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n setup() {\n return html``;\n },\n styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n * <button slot=\"trigger\">Actions</button>\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'default-open': prop.bool(false),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n 'bottom-start',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreMenuEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const menuId = createId('menu');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const abortSignal = lifecycleSignal(onCleanup);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n let cleanupTrigger: (() => void) | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n }\n\n function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n if (!item) return null;\n\n return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n }\n\n function getFocusedItemIndex(): number {\n const items = getItems();\n\n return items.findIndex((item) => {\n const focusable = getItemFocusable(item);\n\n return item === document.activeElement || focusable === document.activeElement;\n });\n }\n\n const isOpenSignal = signal(false);\n let stopPositioning: (() => void) | null = null;\n const positioner = createDropdownPositioner({\n getFloating: () => panelEl,\n getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n getReference: () => triggerEl,\n matchWidth: false,\n offsetPx: 4,\n padding: 6,\n });\n const list = createListControl<HTMLElement>({\n disabled: computed(() => !isOpenSignal.value),\n getItems: getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n onNavigate: ({ item }) => {\n getItemFocusable(item)?.focus();\n },\n signal: abortSignal,\n });\n\n const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n\n if (shouldRestoreFocus) restoreFocus(() => triggerEl);\n\n emit('open-change', { open: false, reason });\n };\n\n const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n if (isDisabled.value || isOpenSignal.value) return;\n\n isOpenSignal.value = true;\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n emit('open-change', { open: true, reason });\n };\n\n const toggle = (): void => {\n if (isOpenSignal.value) close('trigger');\n else open('click');\n };\n\n createOutsidePointerDismissal({\n getTargets: () => [el, panelEl],\n isActive: () => isOpenSignal.value,\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n let initialized = false;\n\n rippleWatch(\n props.open,\n (value) => {\n if (value === undefined) {\n if (!initialized) {\n if (props['default-open'].value) open('programmatic');\n } else {\n close('programmatic');\n }\n } else if (value) {\n open('programmatic');\n } else {\n close('programmatic');\n }\n\n initialized = true;\n },\n { immediate: true },\n );\n abortSignal.addEventListener(\n 'abort',\n () => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n },\n { once: true },\n );\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n const isCheckable = isCheckableItemType(type);\n\n if (type === 'checkbox') {\n item.toggleAttribute('checked', !item.hasAttribute('checked'));\n } else if (type === 'radio') {\n for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n radio.toggleAttribute('checked', radio === item);\n }\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (!isCheckable) {\n close('programmatic');\n }\n };\n\n const openFromKeyboardPress = createInteraction({\n keys: ['Enter', ' ', 'ArrowDown'],\n onPress: () => {\n open('keyboard');\n requestAnimationFrame(() => list.set(0));\n },\n });\n\n const activateFocusedFromKeyboardPress = createInteraction({\n onPress: () => {\n const focused = list.getActiveItem();\n\n if (focused) activateItem(focused);\n },\n });\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const open = isOpenSignal.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n openFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n const currentFocusedIndex = getFocusedItemIndex();\n\n if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n if (e.key === 'Escape') {\n e.preventDefault();\n close('escape');\n\n return;\n }\n\n if (list.handleKeydown(e)) return;\n\n // When open: navigate and activate\n if (e.key === ' ' || e.key === 'Enter') {\n activateFocusedFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n if (e.key === 'Tab') {\n close('programmatic');\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n bind({\n on: {\n click: (e: MouseEvent) => {\n const path = e.composedPath();\n\n if (!isOpenSignal.value) return;\n\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n );\n const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n },\n },\n });\n\n watch(() => {\n const open = isOpenSignal.value;\n\n if (!panelEl) return;\n\n panelEl.toggleAttribute('data-open', open);\n });\n\n function resolveTrigger() {\n cleanupTrigger?.();\n cleanupTrigger = null;\n\n const assigned = slots.elements('trigger').value;\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n if (!triggerEl) return;\n\n const cleanups: Array<() => void> = [];\n const removeAria = bind(\n {\n attr: {\n 'aria-controls': () => menuId,\n 'aria-disabled': () => isDisabled.value,\n 'aria-expanded': () => String(isOpenSignal.value),\n 'aria-haspopup': 'menu',\n },\n },\n { target: triggerEl },\n );\n\n const onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n toggle();\n };\n const onTriggerKeydown = (event: KeyboardEvent) => {\n handleMenuKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n cleanupTrigger = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n };\n }\n\n rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n onMounted(() => {\n resolveTrigger();\n\n return () => {\n cleanupTrigger?.();\n cleanupTrigger = null;\n };\n });\n\n return html`\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-panel\"\n part=\"panel\"\n id=\"${menuId}\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n @keydown=\"${handleMenuKeydown}\"\n ref=\"${(el: HTMLElement | null) => {\n panelEl = el;\n panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n }}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"menu.cjs","names":[],"sources":["../src/overlay/menu/menu.ts"],"sourcesContent":["import { restoreFocus } from '@vielzeug/focus';\nimport type { Placement } from '@vielzeug/orbit';\nimport {\n bind,\n createId,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n useEmit,\n useSlots,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport {\n createDropdownPositioner,\n createInteraction,\n createListControl,\n createOutsidePointerDismissal,\n type DropdownCloseReason,\n lifecycleSignal,\n type OverlayOpenChangeDetail,\n type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport componentStyles from './menu.css?inline';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n checked?: boolean;\n value: string;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n 'open-change': OverlayOpenChangeDetail;\n select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: OreMenuItemType;\n value?: string;\n};\n\nexport type OreMenuProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n disabled?: boolean;\n /** Controlled open state. */\n open?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n props: {\n checked: prop.bool(false),\n disabled: prop.bool(false),\n type: prop.string<OreMenuItemType>(),\n value: prop.string(),\n },\n setup(props) {\n const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n const isChecked = () => isCheckable() && props.checked.value;\n const itemRole = () => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n };\n const itemClass = () => {\n const type = props.type.value;\n\n return [\n 'item',\n type === 'checkbox' ? 'is-checkbox' : '',\n type === 'radio' ? 'is-radio' : '',\n isChecked() ? 'is-checked' : '',\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return isCheckable()\n ? html`\n <div\n class=\"${itemClass}\"\n tabindex=\"-1\"\n role=\"${itemRole}\"\n aria-checked=\"${() => String(isChecked())}\"\n aria-disabled=\"${props.disabled}\">\n <span class=\"item-check\" aria-hidden=\"true\"></span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `\n : html`\n <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `;\n },\n styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n setup() {\n return html``;\n },\n styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n * <button slot=\"trigger\">Actions</button>\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'default-open': prop.bool(false),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n 'bottom-start',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreMenuEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const menuId = createId('menu');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const abortSignal = lifecycleSignal(onCleanup);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n let cleanupTrigger: (() => void) | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n }\n\n function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n if (!item) return null;\n\n return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n }\n\n function getFocusedItemIndex(): number {\n const items = getItems();\n\n return items.findIndex((item) => {\n const focusable = getItemFocusable(item);\n\n return item === document.activeElement || focusable === document.activeElement;\n });\n }\n\n const isOpenSignal = signal(false);\n let stopPositioning: (() => void) | null = null;\n const positioner = createDropdownPositioner({\n getFloating: () => panelEl,\n getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n getReference: () => triggerEl,\n matchWidth: false,\n offsetPx: 4,\n padding: 6,\n useClippingAncestor: false,\n });\n const list = createListControl<HTMLElement>({\n disabled: computed(() => !isOpenSignal.value),\n getItems: getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n onNavigate: ({ item }) => {\n getItemFocusable(item)?.focus();\n },\n signal: abortSignal,\n });\n\n const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n\n if (shouldRestoreFocus) restoreFocus(() => triggerEl);\n\n emit('open-change', { open: false, reason });\n };\n\n const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n if (isDisabled.value || isOpenSignal.value) return;\n\n isOpenSignal.value = true;\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n emit('open-change', { open: true, reason });\n };\n\n const toggle = (): void => {\n if (isOpenSignal.value) close('trigger');\n else open('click');\n };\n\n createOutsidePointerDismissal({\n getTargets: () => [el, panelEl],\n isActive: () => isOpenSignal.value,\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n let initialized = false;\n\n rippleWatch(\n props.open,\n (value) => {\n if (value === undefined) {\n if (!initialized) {\n if (props['default-open'].value) open('programmatic');\n } else {\n close('programmatic');\n }\n } else if (value) {\n open('programmatic');\n } else {\n close('programmatic');\n }\n\n initialized = true;\n },\n { immediate: true },\n );\n abortSignal.addEventListener(\n 'abort',\n () => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n },\n { once: true },\n );\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n const isCheckable = isCheckableItemType(type);\n\n if (type === 'checkbox') {\n item.toggleAttribute('checked', !item.hasAttribute('checked'));\n } else if (type === 'radio') {\n for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n radio.toggleAttribute('checked', radio === item);\n }\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (!isCheckable) {\n close('programmatic');\n }\n };\n\n const openFromKeyboardPress = createInteraction({\n keys: ['Enter', ' ', 'ArrowDown'],\n onPress: () => {\n open('keyboard');\n requestAnimationFrame(() => list.set(0));\n },\n });\n\n const activateFocusedFromKeyboardPress = createInteraction({\n onPress: () => {\n const focused = list.getActiveItem();\n\n if (focused) activateItem(focused);\n },\n });\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const open = isOpenSignal.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n openFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n const currentFocusedIndex = getFocusedItemIndex();\n\n if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n if (e.key === 'Escape') {\n e.preventDefault();\n close('escape');\n\n return;\n }\n\n if (list.handleKeydown(e)) return;\n\n // When open: navigate and activate\n if (e.key === ' ' || e.key === 'Enter') {\n activateFocusedFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n if (e.key === 'Tab') {\n close('programmatic');\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n bind({\n on: {\n click: (e: MouseEvent) => {\n const path = e.composedPath();\n\n if (!isOpenSignal.value) return;\n\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n );\n const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n },\n },\n });\n\n watch(() => {\n const open = isOpenSignal.value;\n\n if (!panelEl) return;\n\n panelEl.toggleAttribute('data-open', open);\n });\n\n function resolveTrigger() {\n cleanupTrigger?.();\n cleanupTrigger = null;\n\n const assigned = slots.elements('trigger').value;\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n if (!triggerEl) return;\n\n const cleanups: Array<() => void> = [];\n const removeAria = bind(\n {\n attr: {\n 'aria-controls': () => menuId,\n 'aria-disabled': () => isDisabled.value,\n 'aria-expanded': () => String(isOpenSignal.value),\n 'aria-haspopup': 'menu',\n },\n },\n { target: triggerEl },\n );\n\n const onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n toggle();\n };\n const onTriggerKeydown = (event: KeyboardEvent) => {\n handleMenuKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n cleanupTrigger = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n };\n }\n\n rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n onMounted(() => {\n resolveTrigger();\n\n return () => {\n cleanupTrigger?.();\n cleanupTrigger = null;\n };\n });\n\n return html`\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-panel\"\n part=\"panel\"\n id=\"${menuId}\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n @keydown=\"${handleMenuKeydown}\"\n ref=\"${(el: HTMLElement | null) => {\n panelEl = el;\n panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n }}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n"],"mappings":"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"}
package/dist/menu.js CHANGED
@@ -98,7 +98,8 @@ g(N, {
98
98
  getReference: () => p,
99
99
  matchWidth: !1,
100
100
  offsetPx: 4,
101
- padding: 6
101
+ padding: 6,
102
+ useClippingAncestor: !1
102
103
  }), I = o({
103
104
  disabled: T(() => !N.value),
104
105
  getItems: k,
package/dist/menu.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","names":[],"sources":["../src/overlay/menu/menu.ts"],"sourcesContent":["import { restoreFocus } from '@vielzeug/focus';\nimport type { Placement } from '@vielzeug/orbit';\nimport {\n bind,\n createId,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n useEmit,\n useSlots,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport {\n createDropdownPositioner,\n createInteraction,\n createListControl,\n createOutsidePointerDismissal,\n type DropdownCloseReason,\n lifecycleSignal,\n type OverlayOpenChangeDetail,\n type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport componentStyles from './menu.css?inline';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n checked?: boolean;\n value: string;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n 'open-change': OverlayOpenChangeDetail;\n select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: OreMenuItemType;\n value?: string;\n};\n\nexport type OreMenuProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n disabled?: boolean;\n /** Controlled open state. */\n open?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n props: {\n checked: prop.bool(false),\n disabled: prop.bool(false),\n type: prop.string<OreMenuItemType>(),\n value: prop.string(),\n },\n setup(props) {\n const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n const isChecked = () => isCheckable() && props.checked.value;\n const itemRole = () => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n };\n const itemClass = () => {\n const type = props.type.value;\n\n return [\n 'item',\n type === 'checkbox' ? 'is-checkbox' : '',\n type === 'radio' ? 'is-radio' : '',\n isChecked() ? 'is-checked' : '',\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return isCheckable()\n ? html`\n <div\n class=\"${itemClass}\"\n tabindex=\"-1\"\n role=\"${itemRole}\"\n aria-checked=\"${() => String(isChecked())}\"\n aria-disabled=\"${props.disabled}\">\n <span class=\"item-check\" aria-hidden=\"true\"></span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `\n : html`\n <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `;\n },\n styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n setup() {\n return html``;\n },\n styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n * <button slot=\"trigger\">Actions</button>\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'default-open': prop.bool(false),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n 'bottom-start',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreMenuEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const menuId = createId('menu');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const abortSignal = lifecycleSignal(onCleanup);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n let cleanupTrigger: (() => void) | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n }\n\n function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n if (!item) return null;\n\n return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n }\n\n function getFocusedItemIndex(): number {\n const items = getItems();\n\n return items.findIndex((item) => {\n const focusable = getItemFocusable(item);\n\n return item === document.activeElement || focusable === document.activeElement;\n });\n }\n\n const isOpenSignal = signal(false);\n let stopPositioning: (() => void) | null = null;\n const positioner = createDropdownPositioner({\n getFloating: () => panelEl,\n getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n getReference: () => triggerEl,\n matchWidth: false,\n offsetPx: 4,\n padding: 6,\n });\n const list = createListControl<HTMLElement>({\n disabled: computed(() => !isOpenSignal.value),\n getItems: getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n onNavigate: ({ item }) => {\n getItemFocusable(item)?.focus();\n },\n signal: abortSignal,\n });\n\n const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n\n if (shouldRestoreFocus) restoreFocus(() => triggerEl);\n\n emit('open-change', { open: false, reason });\n };\n\n const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n if (isDisabled.value || isOpenSignal.value) return;\n\n isOpenSignal.value = true;\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n emit('open-change', { open: true, reason });\n };\n\n const toggle = (): void => {\n if (isOpenSignal.value) close('trigger');\n else open('click');\n };\n\n createOutsidePointerDismissal({\n getTargets: () => [el, panelEl],\n isActive: () => isOpenSignal.value,\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n let initialized = false;\n\n rippleWatch(\n props.open,\n (value) => {\n if (value === undefined) {\n if (!initialized) {\n if (props['default-open'].value) open('programmatic');\n } else {\n close('programmatic');\n }\n } else if (value) {\n open('programmatic');\n } else {\n close('programmatic');\n }\n\n initialized = true;\n },\n { immediate: true },\n );\n abortSignal.addEventListener(\n 'abort',\n () => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n },\n { once: true },\n );\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n const isCheckable = isCheckableItemType(type);\n\n if (type === 'checkbox') {\n item.toggleAttribute('checked', !item.hasAttribute('checked'));\n } else if (type === 'radio') {\n for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n radio.toggleAttribute('checked', radio === item);\n }\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (!isCheckable) {\n close('programmatic');\n }\n };\n\n const openFromKeyboardPress = createInteraction({\n keys: ['Enter', ' ', 'ArrowDown'],\n onPress: () => {\n open('keyboard');\n requestAnimationFrame(() => list.set(0));\n },\n });\n\n const activateFocusedFromKeyboardPress = createInteraction({\n onPress: () => {\n const focused = list.getActiveItem();\n\n if (focused) activateItem(focused);\n },\n });\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const open = isOpenSignal.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n openFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n const currentFocusedIndex = getFocusedItemIndex();\n\n if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n if (e.key === 'Escape') {\n e.preventDefault();\n close('escape');\n\n return;\n }\n\n if (list.handleKeydown(e)) return;\n\n // When open: navigate and activate\n if (e.key === ' ' || e.key === 'Enter') {\n activateFocusedFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n if (e.key === 'Tab') {\n close('programmatic');\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n bind({\n on: {\n click: (e: MouseEvent) => {\n const path = e.composedPath();\n\n if (!isOpenSignal.value) return;\n\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n );\n const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n },\n },\n });\n\n watch(() => {\n const open = isOpenSignal.value;\n\n if (!panelEl) return;\n\n panelEl.toggleAttribute('data-open', open);\n });\n\n function resolveTrigger() {\n cleanupTrigger?.();\n cleanupTrigger = null;\n\n const assigned = slots.elements('trigger').value;\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n if (!triggerEl) return;\n\n const cleanups: Array<() => void> = [];\n const removeAria = bind(\n {\n attr: {\n 'aria-controls': () => menuId,\n 'aria-disabled': () => isDisabled.value,\n 'aria-expanded': () => String(isOpenSignal.value),\n 'aria-haspopup': 'menu',\n },\n },\n { target: triggerEl },\n );\n\n const onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n toggle();\n };\n const onTriggerKeydown = (event: KeyboardEvent) => {\n handleMenuKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n cleanupTrigger = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n };\n }\n\n rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n onMounted(() => {\n resolveTrigger();\n\n return () => {\n cleanupTrigger?.();\n cleanupTrigger = null;\n };\n });\n\n return html`\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-panel\"\n part=\"panel\"\n id=\"${menuId}\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n @keydown=\"${handleMenuKeydown}\"\n ref=\"${(el: HTMLElement | null) => {\n panelEl = el;\n panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n }}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"menu.js","names":[],"sources":["../src/overlay/menu/menu.ts"],"sourcesContent":["import { restoreFocus } from '@vielzeug/focus';\nimport type { Placement } from '@vielzeug/orbit';\nimport {\n bind,\n createId,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n useEmit,\n useSlots,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport {\n createDropdownPositioner,\n createInteraction,\n createListControl,\n createOutsidePointerDismissal,\n type DropdownCloseReason,\n lifecycleSignal,\n type OverlayOpenChangeDetail,\n type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport componentStyles from './menu.css?inline';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n checked?: boolean;\n value: string;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n 'open-change': OverlayOpenChangeDetail;\n select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: OreMenuItemType;\n value?: string;\n};\n\nexport type OreMenuProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n disabled?: boolean;\n /** Controlled open state. */\n open?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n props: {\n checked: prop.bool(false),\n disabled: prop.bool(false),\n type: prop.string<OreMenuItemType>(),\n value: prop.string(),\n },\n setup(props) {\n const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n const isChecked = () => isCheckable() && props.checked.value;\n const itemRole = () => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n };\n const itemClass = () => {\n const type = props.type.value;\n\n return [\n 'item',\n type === 'checkbox' ? 'is-checkbox' : '',\n type === 'radio' ? 'is-radio' : '',\n isChecked() ? 'is-checked' : '',\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return isCheckable()\n ? html`\n <div\n class=\"${itemClass}\"\n tabindex=\"-1\"\n role=\"${itemRole}\"\n aria-checked=\"${() => String(isChecked())}\"\n aria-disabled=\"${props.disabled}\">\n <span class=\"item-check\" aria-hidden=\"true\"></span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `\n : html`\n <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `;\n },\n styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n setup() {\n return html``;\n },\n styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n * <button slot=\"trigger\">Actions</button>\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'default-open': prop.bool(false),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n 'bottom-start',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreMenuEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const menuId = createId('menu');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const abortSignal = lifecycleSignal(onCleanup);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n let cleanupTrigger: (() => void) | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n }\n\n function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n if (!item) return null;\n\n return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n }\n\n function getFocusedItemIndex(): number {\n const items = getItems();\n\n return items.findIndex((item) => {\n const focusable = getItemFocusable(item);\n\n return item === document.activeElement || focusable === document.activeElement;\n });\n }\n\n const isOpenSignal = signal(false);\n let stopPositioning: (() => void) | null = null;\n const positioner = createDropdownPositioner({\n getFloating: () => panelEl,\n getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n getReference: () => triggerEl,\n matchWidth: false,\n offsetPx: 4,\n padding: 6,\n useClippingAncestor: false,\n });\n const list = createListControl<HTMLElement>({\n disabled: computed(() => !isOpenSignal.value),\n getItems: getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n onNavigate: ({ item }) => {\n getItemFocusable(item)?.focus();\n },\n signal: abortSignal,\n });\n\n const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n\n if (shouldRestoreFocus) restoreFocus(() => triggerEl);\n\n emit('open-change', { open: false, reason });\n };\n\n const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n if (isDisabled.value || isOpenSignal.value) return;\n\n isOpenSignal.value = true;\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n emit('open-change', { open: true, reason });\n };\n\n const toggle = (): void => {\n if (isOpenSignal.value) close('trigger');\n else open('click');\n };\n\n createOutsidePointerDismissal({\n getTargets: () => [el, panelEl],\n isActive: () => isOpenSignal.value,\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n let initialized = false;\n\n rippleWatch(\n props.open,\n (value) => {\n if (value === undefined) {\n if (!initialized) {\n if (props['default-open'].value) open('programmatic');\n } else {\n close('programmatic');\n }\n } else if (value) {\n open('programmatic');\n } else {\n close('programmatic');\n }\n\n initialized = true;\n },\n { immediate: true },\n );\n abortSignal.addEventListener(\n 'abort',\n () => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n },\n { once: true },\n );\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n const isCheckable = isCheckableItemType(type);\n\n if (type === 'checkbox') {\n item.toggleAttribute('checked', !item.hasAttribute('checked'));\n } else if (type === 'radio') {\n for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n radio.toggleAttribute('checked', radio === item);\n }\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (!isCheckable) {\n close('programmatic');\n }\n };\n\n const openFromKeyboardPress = createInteraction({\n keys: ['Enter', ' ', 'ArrowDown'],\n onPress: () => {\n open('keyboard');\n requestAnimationFrame(() => list.set(0));\n },\n });\n\n const activateFocusedFromKeyboardPress = createInteraction({\n onPress: () => {\n const focused = list.getActiveItem();\n\n if (focused) activateItem(focused);\n },\n });\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const open = isOpenSignal.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n openFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n const currentFocusedIndex = getFocusedItemIndex();\n\n if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n if (e.key === 'Escape') {\n e.preventDefault();\n close('escape');\n\n return;\n }\n\n if (list.handleKeydown(e)) return;\n\n // When open: navigate and activate\n if (e.key === ' ' || e.key === 'Enter') {\n activateFocusedFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n if (e.key === 'Tab') {\n close('programmatic');\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n bind({\n on: {\n click: (e: MouseEvent) => {\n const path = e.composedPath();\n\n if (!isOpenSignal.value) return;\n\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n );\n const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n },\n },\n });\n\n watch(() => {\n const open = isOpenSignal.value;\n\n if (!panelEl) return;\n\n panelEl.toggleAttribute('data-open', open);\n });\n\n function resolveTrigger() {\n cleanupTrigger?.();\n cleanupTrigger = null;\n\n const assigned = slots.elements('trigger').value;\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n if (!triggerEl) return;\n\n const cleanups: Array<() => void> = [];\n const removeAria = bind(\n {\n attr: {\n 'aria-controls': () => menuId,\n 'aria-disabled': () => isDisabled.value,\n 'aria-expanded': () => String(isOpenSignal.value),\n 'aria-haspopup': 'menu',\n },\n },\n { target: triggerEl },\n );\n\n const onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n toggle();\n };\n const onTriggerKeydown = (event: KeyboardEvent) => {\n handleMenuKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n cleanupTrigger = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n };\n }\n\n rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n onMounted(() => {\n resolveTrigger();\n\n return () => {\n cleanupTrigger?.();\n cleanupTrigger = null;\n };\n });\n\n return html`\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-panel\"\n part=\"panel\"\n id=\"${menuId}\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n @keydown=\"${handleMenuKeydown}\"\n ref=\"${(el: HTMLElement | null) => {\n panelEl = el;\n panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n }}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- var e=`@layer refine.base{:host{--_radius:var(--command-palette-radius,var(--rounded-lg));--_max-width:var(--command-palette-max-width,40rem);--_backdrop-bg:var(--command-palette-backdrop,color-mix(in oklch, var(--color-canvas) 40%, transparent));--_panel-bg:var(--command-palette-bg,var(--color-canvas));--_panel-border-color:var(--command-palette-border-color,var(--color-divider));--_option-hover-bg:var(--command-palette-option-hover-bg,var(--color-contrast-100));--_option-focus-bg:var(--command-palette-option-focus-bg,color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100)));display:contents}dialog{all:unset;box-sizing:border-box;pointer-events:none;width:100%;max-width:100%;height:100%;max-height:100%;transition:display .2s allow-discrete, overlay .2s allow-discrete;padding-top:min(14vh, var(--size-24));background:0 0;border:none;justify-content:center;align-items:flex-start;margin:0;display:flex;position:fixed;inset:0;overflow:hidden}dialog:not([open]),dialog:not([open]) .panel{display:none}dialog[open]{pointer-events:auto}dialog::-ms-backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::-ms-backdrop{opacity:0}}dialog::backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::backdrop{opacity:0}}dialog.closing::-ms-backdrop{opacity:0}dialog.closing::backdrop{opacity:0}.panel{box-sizing:border-box;width:var(--_max-width);max-width:calc(100vw - var(--size-8));max-height:min(28rem, calc(100dvh - var(--size-16)));background:var(--_panel-bg);border:var(--border) solid var(--_panel-border-color);border-radius:var(--_radius);box-shadow:var(--command-palette-shadow,var(--shadow-2xl));opacity:1;-webkit-backdrop-filter:blur(var(--blur-md));backdrop-filter:blur(var(--blur-md));transition:opacity .2s var(--ease-spring), transform .2s var(--ease-spring);flex-direction:column;display:flex;position:relative;overflow:hidden;transform:scale(1)translateY(0)}@starting-style{.panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px)}}dialog.closing .panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px);transition:opacity .15s var(--ease-spring), transform .15s var(--ease-spring)}@media (width<=640px){.panel{width:calc(100vw - var(--size-4));max-width:calc(100vw - var(--size-4))}dialog{padding-top:var(--size-4)}}.search{gap:var(--size-2);padding:var(--size-3) var(--size-4);border-bottom:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.search-icon{color:var(--color-contrast-400);flex-shrink:0;display:inline-flex}.search-input{min-width:0;font:inherit;font-size:var(--text-md);color:var(--color-contrast-900);background:0 0;border:none;outline:none;flex:1;padding:0}.search-input::placeholder{color:var(--color-contrast-400)}.search-loader{border:2px solid var(--color-contrast-300);width:1em;height:1em;animation:command-palette-spin var(--transition-loader) infinite;border-radius:50%;flex-shrink:0;display:inline-flex}.search-loader:not(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))){border-right-color:#0000}.search-loader:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)){border-left-color:#0000}.search-loader[hidden]{display:none}@keyframes command-palette-spin{to{transform:rotate(360deg)}}.listbox{padding:var(--size-1);overscroll-behavior:contain;scrollbar-width:thin;flex:1;overflow-y:auto}.empty{padding:var(--size-6) var(--size-3);font-size:var(--text-sm);color:var(--color-contrast-400);text-align:center}.group-heading{padding:var(--size-2) var(--size-2-5) var(--size-1);font-size:var(--text-xs);font-weight:var(--font-semibold);color:var(--color-contrast-500);text-transform:uppercase;letter-spacing:var(--tracking-wide,.05em)}.item{gap:var(--size-2-5);padding:var(--size-2) var(--size-2-5);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--color-contrast-800);cursor:pointer;border-radius:var(--rounded-md);transition:background var(--transition-fast);align-items:center;display:flex}.item:hover:not([data-disabled]){background:var(--_option-hover-bg)}.item[data-focused]:not([data-disabled]){background:var(--_option-focus-bg)}.item[data-disabled]{color:var(--color-contrast-400);cursor:not-allowed;opacity:.6}.item-icon{color:var(--color-contrast-500);flex-shrink:0;align-items:center;display:inline-flex}.item-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.item-shortcut{gap:var(--size-1);flex-shrink:0;display:inline-flex}.item-shortcut kbd{padding:var(--size-0-5) var(--size-1-5);font-family:var(--font-mono,monospace);font-size:var(--text-xs);color:var(--color-contrast-500);background:var(--color-contrast-100);border:var(--border) solid var(--color-contrast-200);border-bottom-width:calc(var(--border) + 1px);border-radius:var(--rounded-sm)}.footer{gap:var(--size-4);padding:var(--size-2) var(--size-4);font-size:var(--text-xs);color:var(--color-contrast-500);border-top:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.footer-hint{gap:var(--size-1);align-items:center;display:inline-flex}.footer kbd{padding:var(--size-0-5) var(--size-1);font-family:inherit;font-size:var(--text-xs);background:var(--color-contrast-100);border:var(--border) solid var(--color-contrast-200);border-bottom-width:calc(var(--border) + 1px);border-radius:var(--rounded-sm)}::slotted(ore-command-palette-item){display:none}}`;exports.default=e;
1
+ var e=`@layer refine.base{:host{--_radius:var(--command-palette-radius,var(--rounded-lg));--_max-width:var(--command-palette-max-width,40rem);--_backdrop-bg:var(--command-palette-backdrop,color-mix(in oklch, var(--color-canvas) 40%, transparent));--_panel-bg:var(--command-palette-bg,var(--color-canvas));--_panel-border-color:var(--command-palette-border-color,var(--color-divider));--_option-hover-bg:var(--command-palette-option-hover-bg,var(--color-contrast-100));--_option-focus-bg:var(--command-palette-option-focus-bg,color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100)));display:contents}dialog{all:unset;box-sizing:border-box;pointer-events:none;width:100%;max-width:100%;height:100%;max-height:100%;transition:display .2s allow-discrete, overlay .2s allow-discrete;padding-top:min(14vh, var(--size-24));background:0 0;border:none;justify-content:center;align-items:flex-start;margin:0;display:flex;position:fixed;inset:0;overflow:hidden}dialog:not([open]),dialog:not([open]) .panel{display:none}dialog[open]{pointer-events:auto}dialog::-ms-backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::-ms-backdrop{opacity:0}}dialog::backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::backdrop{opacity:0}}dialog.closing::-ms-backdrop{opacity:0}dialog.closing::backdrop{opacity:0}.panel{box-sizing:border-box;width:var(--_max-width);max-width:calc(100vw - var(--size-8));max-height:min(28rem, calc(100dvh - var(--size-16)));background:var(--_panel-bg);border:var(--border) solid var(--_panel-border-color);border-radius:var(--_radius);box-shadow:var(--command-palette-shadow,var(--shadow-2xl));opacity:1;-webkit-backdrop-filter:blur(var(--blur-md));backdrop-filter:blur(var(--blur-md));transition:opacity .2s var(--ease-spring), transform .2s var(--ease-spring);flex-direction:column;display:flex;position:relative;overflow:hidden;transform:scale(1)translateY(0)}@starting-style{.panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px)}}dialog.closing .panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px);transition:opacity .15s var(--ease-spring), transform .15s var(--ease-spring)}@media (width<=640px){.panel{width:calc(100vw - var(--size-4));max-width:calc(100vw - var(--size-4))}dialog{padding-top:var(--size-4)}}.search{gap:var(--size-2);padding:var(--size-3) var(--size-4);border-bottom:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.search-icon{color:var(--color-contrast-400);flex-shrink:0;display:inline-flex}.search-input{min-width:0;font:inherit;font-size:var(--text-md);color:var(--color-contrast-900);background:0 0;border:none;outline:none;flex:1;padding:0}.search-input::placeholder{color:var(--color-contrast-400)}.search-loader{border:2px solid var(--color-contrast-300);width:1em;height:1em;animation:command-palette-spin var(--transition-loader) infinite;border-radius:50%;flex-shrink:0;display:inline-flex}.search-loader:not(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))){border-right-color:#0000}.search-loader:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)){border-left-color:#0000}.search-loader[hidden]{display:none}@keyframes command-palette-spin{to{transform:rotate(360deg)}}.listbox{padding:var(--size-1);overscroll-behavior:contain;scrollbar-width:thin;flex:1;overflow-y:auto}.empty{padding:var(--size-6) var(--size-3);font-size:var(--text-sm);color:var(--color-contrast-400);text-align:center}.group-heading{padding:var(--size-2) var(--size-2-5) var(--size-1);font-size:var(--text-xs);font-weight:var(--font-semibold);color:var(--color-contrast-500);text-transform:uppercase;letter-spacing:var(--tracking-wide,.05em)}.item{gap:var(--size-2-5);padding:var(--size-2) var(--size-2-5);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--color-contrast-800);cursor:pointer;border-radius:var(--rounded-md);transition:background var(--transition-fast);align-items:center;display:flex}.item:hover:not([data-disabled]){background:var(--_option-hover-bg)}.item[data-focused]:not([data-disabled]){background:var(--_option-focus-bg)}.item[data-disabled]{color:var(--color-contrast-400);cursor:not-allowed;opacity:.6}.item-icon{color:var(--color-contrast-500);flex-shrink:0;align-items:center;display:inline-flex}.item-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.item-shortcut{gap:var(--size-1);flex-shrink:0;display:inline-flex}.footer{gap:var(--size-4);padding:var(--size-2) var(--size-4);font-size:var(--text-xs);color:var(--color-contrast-500);border-top:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.footer-hint{gap:var(--size-1);align-items:center;display:inline-flex}.footer ore-keyboard-key{--keyboard-key-font-family:inherit;--keyboard-key-padding-inline:var(--size-1)}::slotted(ore-command-palette-item){display:none}}`;exports.default=e;
2
2
  //# sourceMappingURL=command-palette.css.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.css.cjs","names":[],"sources":["../../../src/overlay/command-palette/command-palette.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --_radius: var(--command-palette-radius, var(--rounded-lg));\n --_max-width: var(--command-palette-max-width, 40rem);\n --_backdrop-bg: var(--command-palette-backdrop, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n --_panel-bg: var(--command-palette-bg, var(--color-canvas));\n --_panel-border-color: var(--command-palette-border-color, var(--color-divider));\n --_option-hover-bg: var(--command-palette-option-hover-bg, var(--color-contrast-100));\n --_option-focus-bg: var(\n --command-palette-option-focus-bg,\n color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100))\n );\n\n display: contents;\n }\n\n /* =====================\n Native <dialog> resets — see ore-dialog for the full rationale.\n ===================== */\n\n dialog {\n all: unset;\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n padding-block-start: min(14vh, var(--size-24));\n margin: 0;\n overflow: hidden;\n pointer-events: none;\n background: transparent;\n border: none;\n transition:\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n }\n\n dialog:not([open]) {\n display: none;\n }\n\n dialog:not([open]) .panel {\n display: none;\n }\n\n dialog[open] {\n pointer-events: auto;\n }\n\n dialog::backdrop {\n background: var(--_backdrop-bg);\n opacity: 1;\n backdrop-filter: blur(var(--blur-xs));\n transition:\n opacity var(--transition-normal),\n overlay var(--transition-normal) allow-discrete,\n display var(--transition-normal) allow-discrete;\n\n @starting-style {\n opacity: 0;\n }\n }\n\n dialog.closing::backdrop {\n opacity: 0;\n }\n\n /* =====================\n Panel\n ===================== */\n\n .panel {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--_max-width);\n max-width: calc(100vw - var(--size-8));\n max-height: min(28rem, calc(100dvh - var(--size-16)));\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--_radius);\n box-shadow: var(--command-palette-shadow, var(--shadow-2xl));\n opacity: 1;\n backdrop-filter: blur(var(--blur-md));\n transform: scale(1) translateY(0);\n transition:\n opacity 200ms var(--ease-spring),\n transform 200ms var(--ease-spring);\n\n @starting-style {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n }\n }\n\n dialog.closing .panel {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n transition:\n opacity 150ms var(--ease-spring),\n transform 150ms var(--ease-spring);\n }\n\n @media (width <= 640px) {\n .panel {\n width: calc(100vw - var(--size-4));\n max-width: calc(100vw - var(--size-4));\n }\n\n dialog {\n padding-block-start: var(--size-4);\n }\n }\n\n /* =====================\n Search field\n ===================== */\n\n .search {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-3) var(--size-4);\n border-block-end: var(--border) solid var(--color-contrast-100);\n }\n\n .search-icon {\n display: inline-flex;\n flex-shrink: 0;\n color: var(--color-contrast-400);\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n padding: 0;\n font: inherit;\n font-size: var(--text-md);\n color: var(--color-contrast-900);\n outline: none;\n background: transparent;\n border: none;\n }\n\n .search-input::placeholder {\n color: var(--color-contrast-400);\n }\n\n .search-loader {\n display: inline-flex;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n border: 2px solid var(--color-contrast-300);\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: command-palette-spin var(--transition-loader) infinite;\n }\n\n .search-loader[hidden] {\n display: none;\n }\n\n @keyframes command-palette-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n /* =====================\n Listbox\n ===================== */\n\n .listbox {\n flex: 1;\n padding: var(--size-1);\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n }\n\n .empty {\n padding: var(--size-6) var(--size-3);\n font-size: var(--text-sm);\n color: var(--color-contrast-400);\n text-align: center;\n }\n\n .group-heading {\n padding: var(--size-2) var(--size-2-5) var(--size-1);\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-transform: uppercase;\n letter-spacing: var(--tracking-wide, 0.05em);\n }\n\n .item {\n display: flex;\n gap: var(--size-2-5);\n align-items: center;\n padding: var(--size-2) var(--size-2-5);\n font-size: var(--text-sm);\n line-height: var(--leading-normal);\n color: var(--color-contrast-800);\n cursor: pointer;\n border-radius: var(--rounded-md);\n transition: background var(--transition-fast);\n }\n\n .item:hover:not([data-disabled]) {\n background: var(--_option-hover-bg);\n }\n\n .item[data-focused]:not([data-disabled]) {\n background: var(--_option-focus-bg);\n }\n\n .item[data-disabled] {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .item-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n color: var(--color-contrast-500);\n }\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .item-shortcut {\n display: inline-flex;\n flex-shrink: 0;\n gap: var(--size-1);\n }\n\n .item-shortcut kbd {\n padding: var(--size-0-5) var(--size-1-5);\n font-family: var(--font-mono, monospace);\n font-size: var(--text-xs);\n color: var(--color-contrast-500);\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n border-bottom-width: calc(var(--border) + 1px);\n border-radius: var(--rounded-sm);\n }\n\n /* =====================\n Footer hints\n ===================== */\n\n .footer {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-4);\n align-items: center;\n padding: var(--size-2) var(--size-4);\n font-size: var(--text-xs);\n color: var(--color-contrast-500);\n border-block-start: var(--border) solid var(--color-contrast-100);\n }\n\n .footer-hint {\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n }\n\n .footer kbd {\n padding: var(--size-0-5) var(--size-1);\n font-family: inherit;\n font-size: var(--text-xs);\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n border-bottom-width: calc(var(--border) + 1px);\n border-radius: var(--rounded-sm);\n }\n\n /* Slotted item elements are pure data nodes — never rendered directly. */\n ::slotted(ore-command-palette-item) {\n display: none;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"command-palette.css.cjs","names":[],"sources":["../../../src/overlay/command-palette/command-palette.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --_radius: var(--command-palette-radius, var(--rounded-lg));\n --_max-width: var(--command-palette-max-width, 40rem);\n --_backdrop-bg: var(--command-palette-backdrop, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n --_panel-bg: var(--command-palette-bg, var(--color-canvas));\n --_panel-border-color: var(--command-palette-border-color, var(--color-divider));\n --_option-hover-bg: var(--command-palette-option-hover-bg, var(--color-contrast-100));\n --_option-focus-bg: var(\n --command-palette-option-focus-bg,\n color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100))\n );\n\n display: contents;\n }\n\n /* =====================\n Native <dialog> resets — see ore-dialog for the full rationale.\n ===================== */\n\n dialog {\n all: unset;\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n padding-block-start: min(14vh, var(--size-24));\n margin: 0;\n overflow: hidden;\n pointer-events: none;\n background: transparent;\n border: none;\n transition:\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n }\n\n dialog:not([open]) {\n display: none;\n }\n\n dialog:not([open]) .panel {\n display: none;\n }\n\n dialog[open] {\n pointer-events: auto;\n }\n\n dialog::backdrop {\n background: var(--_backdrop-bg);\n opacity: 1;\n backdrop-filter: blur(var(--blur-xs));\n transition:\n opacity var(--transition-normal),\n overlay var(--transition-normal) allow-discrete,\n display var(--transition-normal) allow-discrete;\n\n @starting-style {\n opacity: 0;\n }\n }\n\n dialog.closing::backdrop {\n opacity: 0;\n }\n\n /* =====================\n Panel\n ===================== */\n\n .panel {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--_max-width);\n max-width: calc(100vw - var(--size-8));\n max-height: min(28rem, calc(100dvh - var(--size-16)));\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--_radius);\n box-shadow: var(--command-palette-shadow, var(--shadow-2xl));\n opacity: 1;\n backdrop-filter: blur(var(--blur-md));\n transform: scale(1) translateY(0);\n transition:\n opacity 200ms var(--ease-spring),\n transform 200ms var(--ease-spring);\n\n @starting-style {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n }\n }\n\n dialog.closing .panel {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n transition:\n opacity 150ms var(--ease-spring),\n transform 150ms var(--ease-spring);\n }\n\n @media (width <= 640px) {\n .panel {\n width: calc(100vw - var(--size-4));\n max-width: calc(100vw - var(--size-4));\n }\n\n dialog {\n padding-block-start: var(--size-4);\n }\n }\n\n /* =====================\n Search field\n ===================== */\n\n .search {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-3) var(--size-4);\n border-block-end: var(--border) solid var(--color-contrast-100);\n }\n\n .search-icon {\n display: inline-flex;\n flex-shrink: 0;\n color: var(--color-contrast-400);\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n padding: 0;\n font: inherit;\n font-size: var(--text-md);\n color: var(--color-contrast-900);\n outline: none;\n background: transparent;\n border: none;\n }\n\n .search-input::placeholder {\n color: var(--color-contrast-400);\n }\n\n .search-loader {\n display: inline-flex;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n border: 2px solid var(--color-contrast-300);\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: command-palette-spin var(--transition-loader) infinite;\n }\n\n .search-loader[hidden] {\n display: none;\n }\n\n @keyframes command-palette-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n /* =====================\n Listbox\n ===================== */\n\n .listbox {\n flex: 1;\n padding: var(--size-1);\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n }\n\n .empty {\n padding: var(--size-6) var(--size-3);\n font-size: var(--text-sm);\n color: var(--color-contrast-400);\n text-align: center;\n }\n\n .group-heading {\n padding: var(--size-2) var(--size-2-5) var(--size-1);\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-transform: uppercase;\n letter-spacing: var(--tracking-wide, 0.05em);\n }\n\n .item {\n display: flex;\n gap: var(--size-2-5);\n align-items: center;\n padding: var(--size-2) var(--size-2-5);\n font-size: var(--text-sm);\n line-height: var(--leading-normal);\n color: var(--color-contrast-800);\n cursor: pointer;\n border-radius: var(--rounded-md);\n transition: background var(--transition-fast);\n }\n\n .item:hover:not([data-disabled]) {\n background: var(--_option-hover-bg);\n }\n\n .item[data-focused]:not([data-disabled]) {\n background: var(--_option-focus-bg);\n }\n\n .item[data-disabled] {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .item-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n color: var(--color-contrast-500);\n }\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .item-shortcut {\n display: inline-flex;\n flex-shrink: 0;\n gap: var(--size-1);\n }\n\n /* =====================\n Footer hints\n ===================== */\n\n .footer {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-4);\n align-items: center;\n padding: var(--size-2) var(--size-4);\n font-size: var(--text-xs);\n color: var(--color-contrast-500);\n border-block-start: var(--border) solid var(--color-contrast-100);\n }\n\n .footer-hint {\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n }\n\n .footer ore-keyboard-key {\n --keyboard-key-font-family: inherit;\n --keyboard-key-padding-inline: var(--size-1);\n }\n\n /* Slotted item elements are pure data nodes — never rendered directly. */\n ::slotted(ore-command-palette-item) {\n display: none;\n }\n}\n"],"mappings":""}
@@ -1,5 +1,5 @@
1
1
  //#region src/overlay/command-palette/command-palette.css?inline
2
- var e = "@layer refine.base{:host{--_radius:var(--command-palette-radius,var(--rounded-lg));--_max-width:var(--command-palette-max-width,40rem);--_backdrop-bg:var(--command-palette-backdrop,color-mix(in oklch, var(--color-canvas) 40%, transparent));--_panel-bg:var(--command-palette-bg,var(--color-canvas));--_panel-border-color:var(--command-palette-border-color,var(--color-divider));--_option-hover-bg:var(--command-palette-option-hover-bg,var(--color-contrast-100));--_option-focus-bg:var(--command-palette-option-focus-bg,color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100)));display:contents}dialog{all:unset;box-sizing:border-box;pointer-events:none;width:100%;max-width:100%;height:100%;max-height:100%;transition:display .2s allow-discrete, overlay .2s allow-discrete;padding-top:min(14vh, var(--size-24));background:0 0;border:none;justify-content:center;align-items:flex-start;margin:0;display:flex;position:fixed;inset:0;overflow:hidden}dialog:not([open]),dialog:not([open]) .panel{display:none}dialog[open]{pointer-events:auto}dialog::-ms-backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::-ms-backdrop{opacity:0}}dialog::backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::backdrop{opacity:0}}dialog.closing::-ms-backdrop{opacity:0}dialog.closing::backdrop{opacity:0}.panel{box-sizing:border-box;width:var(--_max-width);max-width:calc(100vw - var(--size-8));max-height:min(28rem, calc(100dvh - var(--size-16)));background:var(--_panel-bg);border:var(--border) solid var(--_panel-border-color);border-radius:var(--_radius);box-shadow:var(--command-palette-shadow,var(--shadow-2xl));opacity:1;-webkit-backdrop-filter:blur(var(--blur-md));backdrop-filter:blur(var(--blur-md));transition:opacity .2s var(--ease-spring), transform .2s var(--ease-spring);flex-direction:column;display:flex;position:relative;overflow:hidden;transform:scale(1)translateY(0)}@starting-style{.panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px)}}dialog.closing .panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px);transition:opacity .15s var(--ease-spring), transform .15s var(--ease-spring)}@media (width<=640px){.panel{width:calc(100vw - var(--size-4));max-width:calc(100vw - var(--size-4))}dialog{padding-top:var(--size-4)}}.search{gap:var(--size-2);padding:var(--size-3) var(--size-4);border-bottom:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.search-icon{color:var(--color-contrast-400);flex-shrink:0;display:inline-flex}.search-input{min-width:0;font:inherit;font-size:var(--text-md);color:var(--color-contrast-900);background:0 0;border:none;outline:none;flex:1;padding:0}.search-input::placeholder{color:var(--color-contrast-400)}.search-loader{border:2px solid var(--color-contrast-300);width:1em;height:1em;animation:command-palette-spin var(--transition-loader) infinite;border-radius:50%;flex-shrink:0;display:inline-flex}.search-loader:not(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))){border-right-color:#0000}.search-loader:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)){border-left-color:#0000}.search-loader[hidden]{display:none}@keyframes command-palette-spin{to{transform:rotate(360deg)}}.listbox{padding:var(--size-1);overscroll-behavior:contain;scrollbar-width:thin;flex:1;overflow-y:auto}.empty{padding:var(--size-6) var(--size-3);font-size:var(--text-sm);color:var(--color-contrast-400);text-align:center}.group-heading{padding:var(--size-2) var(--size-2-5) var(--size-1);font-size:var(--text-xs);font-weight:var(--font-semibold);color:var(--color-contrast-500);text-transform:uppercase;letter-spacing:var(--tracking-wide,.05em)}.item{gap:var(--size-2-5);padding:var(--size-2) var(--size-2-5);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--color-contrast-800);cursor:pointer;border-radius:var(--rounded-md);transition:background var(--transition-fast);align-items:center;display:flex}.item:hover:not([data-disabled]){background:var(--_option-hover-bg)}.item[data-focused]:not([data-disabled]){background:var(--_option-focus-bg)}.item[data-disabled]{color:var(--color-contrast-400);cursor:not-allowed;opacity:.6}.item-icon{color:var(--color-contrast-500);flex-shrink:0;align-items:center;display:inline-flex}.item-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.item-shortcut{gap:var(--size-1);flex-shrink:0;display:inline-flex}.item-shortcut kbd{padding:var(--size-0-5) var(--size-1-5);font-family:var(--font-mono,monospace);font-size:var(--text-xs);color:var(--color-contrast-500);background:var(--color-contrast-100);border:var(--border) solid var(--color-contrast-200);border-bottom-width:calc(var(--border) + 1px);border-radius:var(--rounded-sm)}.footer{gap:var(--size-4);padding:var(--size-2) var(--size-4);font-size:var(--text-xs);color:var(--color-contrast-500);border-top:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.footer-hint{gap:var(--size-1);align-items:center;display:inline-flex}.footer kbd{padding:var(--size-0-5) var(--size-1);font-family:inherit;font-size:var(--text-xs);background:var(--color-contrast-100);border:var(--border) solid var(--color-contrast-200);border-bottom-width:calc(var(--border) + 1px);border-radius:var(--rounded-sm)}::slotted(ore-command-palette-item){display:none}}";
2
+ var e = "@layer refine.base{:host{--_radius:var(--command-palette-radius,var(--rounded-lg));--_max-width:var(--command-palette-max-width,40rem);--_backdrop-bg:var(--command-palette-backdrop,color-mix(in oklch, var(--color-canvas) 40%, transparent));--_panel-bg:var(--command-palette-bg,var(--color-canvas));--_panel-border-color:var(--command-palette-border-color,var(--color-divider));--_option-hover-bg:var(--command-palette-option-hover-bg,var(--color-contrast-100));--_option-focus-bg:var(--command-palette-option-focus-bg,color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100)));display:contents}dialog{all:unset;box-sizing:border-box;pointer-events:none;width:100%;max-width:100%;height:100%;max-height:100%;transition:display .2s allow-discrete, overlay .2s allow-discrete;padding-top:min(14vh, var(--size-24));background:0 0;border:none;justify-content:center;align-items:flex-start;margin:0;display:flex;position:fixed;inset:0;overflow:hidden}dialog:not([open]),dialog:not([open]) .panel{display:none}dialog[open]{pointer-events:auto}dialog::-ms-backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::-ms-backdrop{opacity:0}}dialog::backdrop{background:var(--_backdrop-bg);opacity:1;-webkit-backdrop-filter:blur(var(--blur-xs));backdrop-filter:blur(var(--blur-xs));transition:opacity var(--transition-normal), overlay var(--transition-normal) allow-discrete, display var(--transition-normal) allow-discrete}@starting-style{dialog::backdrop{opacity:0}}dialog.closing::-ms-backdrop{opacity:0}dialog.closing::backdrop{opacity:0}.panel{box-sizing:border-box;width:var(--_max-width);max-width:calc(100vw - var(--size-8));max-height:min(28rem, calc(100dvh - var(--size-16)));background:var(--_panel-bg);border:var(--border) solid var(--_panel-border-color);border-radius:var(--_radius);box-shadow:var(--command-palette-shadow,var(--shadow-2xl));opacity:1;-webkit-backdrop-filter:blur(var(--blur-md));backdrop-filter:blur(var(--blur-md));transition:opacity .2s var(--ease-spring), transform .2s var(--ease-spring);flex-direction:column;display:flex;position:relative;overflow:hidden;transform:scale(1)translateY(0)}@starting-style{.panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px)}}dialog.closing .panel{opacity:0;transform:scale(var(--overlay-enter-scale-dialog)) translateY(-4px);transition:opacity .15s var(--ease-spring), transform .15s var(--ease-spring)}@media (width<=640px){.panel{width:calc(100vw - var(--size-4));max-width:calc(100vw - var(--size-4))}dialog{padding-top:var(--size-4)}}.search{gap:var(--size-2);padding:var(--size-3) var(--size-4);border-bottom:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.search-icon{color:var(--color-contrast-400);flex-shrink:0;display:inline-flex}.search-input{min-width:0;font:inherit;font-size:var(--text-md);color:var(--color-contrast-900);background:0 0;border:none;outline:none;flex:1;padding:0}.search-input::placeholder{color:var(--color-contrast-400)}.search-loader{border:2px solid var(--color-contrast-300);width:1em;height:1em;animation:command-palette-spin var(--transition-loader) infinite;border-radius:50%;flex-shrink:0;display:inline-flex}.search-loader:not(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))){border-right-color:#0000}.search-loader:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)){border-left-color:#0000}.search-loader[hidden]{display:none}@keyframes command-palette-spin{to{transform:rotate(360deg)}}.listbox{padding:var(--size-1);overscroll-behavior:contain;scrollbar-width:thin;flex:1;overflow-y:auto}.empty{padding:var(--size-6) var(--size-3);font-size:var(--text-sm);color:var(--color-contrast-400);text-align:center}.group-heading{padding:var(--size-2) var(--size-2-5) var(--size-1);font-size:var(--text-xs);font-weight:var(--font-semibold);color:var(--color-contrast-500);text-transform:uppercase;letter-spacing:var(--tracking-wide,.05em)}.item{gap:var(--size-2-5);padding:var(--size-2) var(--size-2-5);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--color-contrast-800);cursor:pointer;border-radius:var(--rounded-md);transition:background var(--transition-fast);align-items:center;display:flex}.item:hover:not([data-disabled]){background:var(--_option-hover-bg)}.item[data-focused]:not([data-disabled]){background:var(--_option-focus-bg)}.item[data-disabled]{color:var(--color-contrast-400);cursor:not-allowed;opacity:.6}.item-icon{color:var(--color-contrast-500);flex-shrink:0;align-items:center;display:inline-flex}.item-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.item-shortcut{gap:var(--size-1);flex-shrink:0;display:inline-flex}.footer{gap:var(--size-4);padding:var(--size-2) var(--size-4);font-size:var(--text-xs);color:var(--color-contrast-500);border-top:var(--border) solid var(--color-contrast-100);flex-shrink:0;align-items:center;display:flex}.footer-hint{gap:var(--size-1);align-items:center;display:inline-flex}.footer ore-keyboard-key{--keyboard-key-font-family:inherit;--keyboard-key-padding-inline:var(--size-1)}::slotted(ore-command-palette-item){display:none}}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.css.js","names":[],"sources":["../../../src/overlay/command-palette/command-palette.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --_radius: var(--command-palette-radius, var(--rounded-lg));\n --_max-width: var(--command-palette-max-width, 40rem);\n --_backdrop-bg: var(--command-palette-backdrop, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n --_panel-bg: var(--command-palette-bg, var(--color-canvas));\n --_panel-border-color: var(--command-palette-border-color, var(--color-divider));\n --_option-hover-bg: var(--command-palette-option-hover-bg, var(--color-contrast-100));\n --_option-focus-bg: var(\n --command-palette-option-focus-bg,\n color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100))\n );\n\n display: contents;\n }\n\n /* =====================\n Native <dialog> resets — see ore-dialog for the full rationale.\n ===================== */\n\n dialog {\n all: unset;\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n padding-block-start: min(14vh, var(--size-24));\n margin: 0;\n overflow: hidden;\n pointer-events: none;\n background: transparent;\n border: none;\n transition:\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n }\n\n dialog:not([open]) {\n display: none;\n }\n\n dialog:not([open]) .panel {\n display: none;\n }\n\n dialog[open] {\n pointer-events: auto;\n }\n\n dialog::backdrop {\n background: var(--_backdrop-bg);\n opacity: 1;\n backdrop-filter: blur(var(--blur-xs));\n transition:\n opacity var(--transition-normal),\n overlay var(--transition-normal) allow-discrete,\n display var(--transition-normal) allow-discrete;\n\n @starting-style {\n opacity: 0;\n }\n }\n\n dialog.closing::backdrop {\n opacity: 0;\n }\n\n /* =====================\n Panel\n ===================== */\n\n .panel {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--_max-width);\n max-width: calc(100vw - var(--size-8));\n max-height: min(28rem, calc(100dvh - var(--size-16)));\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--_radius);\n box-shadow: var(--command-palette-shadow, var(--shadow-2xl));\n opacity: 1;\n backdrop-filter: blur(var(--blur-md));\n transform: scale(1) translateY(0);\n transition:\n opacity 200ms var(--ease-spring),\n transform 200ms var(--ease-spring);\n\n @starting-style {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n }\n }\n\n dialog.closing .panel {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n transition:\n opacity 150ms var(--ease-spring),\n transform 150ms var(--ease-spring);\n }\n\n @media (width <= 640px) {\n .panel {\n width: calc(100vw - var(--size-4));\n max-width: calc(100vw - var(--size-4));\n }\n\n dialog {\n padding-block-start: var(--size-4);\n }\n }\n\n /* =====================\n Search field\n ===================== */\n\n .search {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-3) var(--size-4);\n border-block-end: var(--border) solid var(--color-contrast-100);\n }\n\n .search-icon {\n display: inline-flex;\n flex-shrink: 0;\n color: var(--color-contrast-400);\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n padding: 0;\n font: inherit;\n font-size: var(--text-md);\n color: var(--color-contrast-900);\n outline: none;\n background: transparent;\n border: none;\n }\n\n .search-input::placeholder {\n color: var(--color-contrast-400);\n }\n\n .search-loader {\n display: inline-flex;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n border: 2px solid var(--color-contrast-300);\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: command-palette-spin var(--transition-loader) infinite;\n }\n\n .search-loader[hidden] {\n display: none;\n }\n\n @keyframes command-palette-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n /* =====================\n Listbox\n ===================== */\n\n .listbox {\n flex: 1;\n padding: var(--size-1);\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n }\n\n .empty {\n padding: var(--size-6) var(--size-3);\n font-size: var(--text-sm);\n color: var(--color-contrast-400);\n text-align: center;\n }\n\n .group-heading {\n padding: var(--size-2) var(--size-2-5) var(--size-1);\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-transform: uppercase;\n letter-spacing: var(--tracking-wide, 0.05em);\n }\n\n .item {\n display: flex;\n gap: var(--size-2-5);\n align-items: center;\n padding: var(--size-2) var(--size-2-5);\n font-size: var(--text-sm);\n line-height: var(--leading-normal);\n color: var(--color-contrast-800);\n cursor: pointer;\n border-radius: var(--rounded-md);\n transition: background var(--transition-fast);\n }\n\n .item:hover:not([data-disabled]) {\n background: var(--_option-hover-bg);\n }\n\n .item[data-focused]:not([data-disabled]) {\n background: var(--_option-focus-bg);\n }\n\n .item[data-disabled] {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .item-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n color: var(--color-contrast-500);\n }\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .item-shortcut {\n display: inline-flex;\n flex-shrink: 0;\n gap: var(--size-1);\n }\n\n .item-shortcut kbd {\n padding: var(--size-0-5) var(--size-1-5);\n font-family: var(--font-mono, monospace);\n font-size: var(--text-xs);\n color: var(--color-contrast-500);\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n border-bottom-width: calc(var(--border) + 1px);\n border-radius: var(--rounded-sm);\n }\n\n /* =====================\n Footer hints\n ===================== */\n\n .footer {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-4);\n align-items: center;\n padding: var(--size-2) var(--size-4);\n font-size: var(--text-xs);\n color: var(--color-contrast-500);\n border-block-start: var(--border) solid var(--color-contrast-100);\n }\n\n .footer-hint {\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n }\n\n .footer kbd {\n padding: var(--size-0-5) var(--size-1);\n font-family: inherit;\n font-size: var(--text-xs);\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n border-bottom-width: calc(var(--border) + 1px);\n border-radius: var(--rounded-sm);\n }\n\n /* Slotted item elements are pure data nodes — never rendered directly. */\n ::slotted(ore-command-palette-item) {\n display: none;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"command-palette.css.js","names":[],"sources":["../../../src/overlay/command-palette/command-palette.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --_radius: var(--command-palette-radius, var(--rounded-lg));\n --_max-width: var(--command-palette-max-width, 40rem);\n --_backdrop-bg: var(--command-palette-backdrop, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n --_panel-bg: var(--command-palette-bg, var(--color-canvas));\n --_panel-border-color: var(--command-palette-border-color, var(--color-divider));\n --_option-hover-bg: var(--command-palette-option-hover-bg, var(--color-contrast-100));\n --_option-focus-bg: var(\n --command-palette-option-focus-bg,\n color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100))\n );\n\n display: contents;\n }\n\n /* =====================\n Native <dialog> resets — see ore-dialog for the full rationale.\n ===================== */\n\n dialog {\n all: unset;\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n padding-block-start: min(14vh, var(--size-24));\n margin: 0;\n overflow: hidden;\n pointer-events: none;\n background: transparent;\n border: none;\n transition:\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n }\n\n dialog:not([open]) {\n display: none;\n }\n\n dialog:not([open]) .panel {\n display: none;\n }\n\n dialog[open] {\n pointer-events: auto;\n }\n\n dialog::backdrop {\n background: var(--_backdrop-bg);\n opacity: 1;\n backdrop-filter: blur(var(--blur-xs));\n transition:\n opacity var(--transition-normal),\n overlay var(--transition-normal) allow-discrete,\n display var(--transition-normal) allow-discrete;\n\n @starting-style {\n opacity: 0;\n }\n }\n\n dialog.closing::backdrop {\n opacity: 0;\n }\n\n /* =====================\n Panel\n ===================== */\n\n .panel {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--_max-width);\n max-width: calc(100vw - var(--size-8));\n max-height: min(28rem, calc(100dvh - var(--size-16)));\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--_radius);\n box-shadow: var(--command-palette-shadow, var(--shadow-2xl));\n opacity: 1;\n backdrop-filter: blur(var(--blur-md));\n transform: scale(1) translateY(0);\n transition:\n opacity 200ms var(--ease-spring),\n transform 200ms var(--ease-spring);\n\n @starting-style {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n }\n }\n\n dialog.closing .panel {\n opacity: 0;\n transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n transition:\n opacity 150ms var(--ease-spring),\n transform 150ms var(--ease-spring);\n }\n\n @media (width <= 640px) {\n .panel {\n width: calc(100vw - var(--size-4));\n max-width: calc(100vw - var(--size-4));\n }\n\n dialog {\n padding-block-start: var(--size-4);\n }\n }\n\n /* =====================\n Search field\n ===================== */\n\n .search {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-3) var(--size-4);\n border-block-end: var(--border) solid var(--color-contrast-100);\n }\n\n .search-icon {\n display: inline-flex;\n flex-shrink: 0;\n color: var(--color-contrast-400);\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n padding: 0;\n font: inherit;\n font-size: var(--text-md);\n color: var(--color-contrast-900);\n outline: none;\n background: transparent;\n border: none;\n }\n\n .search-input::placeholder {\n color: var(--color-contrast-400);\n }\n\n .search-loader {\n display: inline-flex;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n border: 2px solid var(--color-contrast-300);\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: command-palette-spin var(--transition-loader) infinite;\n }\n\n .search-loader[hidden] {\n display: none;\n }\n\n @keyframes command-palette-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n /* =====================\n Listbox\n ===================== */\n\n .listbox {\n flex: 1;\n padding: var(--size-1);\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n }\n\n .empty {\n padding: var(--size-6) var(--size-3);\n font-size: var(--text-sm);\n color: var(--color-contrast-400);\n text-align: center;\n }\n\n .group-heading {\n padding: var(--size-2) var(--size-2-5) var(--size-1);\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-transform: uppercase;\n letter-spacing: var(--tracking-wide, 0.05em);\n }\n\n .item {\n display: flex;\n gap: var(--size-2-5);\n align-items: center;\n padding: var(--size-2) var(--size-2-5);\n font-size: var(--text-sm);\n line-height: var(--leading-normal);\n color: var(--color-contrast-800);\n cursor: pointer;\n border-radius: var(--rounded-md);\n transition: background var(--transition-fast);\n }\n\n .item:hover:not([data-disabled]) {\n background: var(--_option-hover-bg);\n }\n\n .item[data-focused]:not([data-disabled]) {\n background: var(--_option-focus-bg);\n }\n\n .item[data-disabled] {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .item-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n color: var(--color-contrast-500);\n }\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .item-shortcut {\n display: inline-flex;\n flex-shrink: 0;\n gap: var(--size-1);\n }\n\n /* =====================\n Footer hints\n ===================== */\n\n .footer {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-4);\n align-items: center;\n padding: var(--size-2) var(--size-4);\n font-size: var(--text-xs);\n color: var(--color-contrast-500);\n border-block-start: var(--border) solid var(--color-contrast-100);\n }\n\n .footer-hint {\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n }\n\n .footer ore-keyboard-key {\n --keyboard-key-font-family: inherit;\n --keyboard-key-padding-inline: var(--size-1);\n }\n\n /* Slotted item elements are pure data nodes — never rendered directly. */\n ::slotted(ore-command-palette-item) {\n display: none;\n }\n}\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import '../../content/keyboard-key/keyboard-key';
1
2
  import '../../content/icon/icon';
2
3
  export type { OreCommandPaletteEvents, OreCommandPaletteProps } from './command-palette.types';
3
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.d.ts","sourceRoot":"","sources":["../../../src/overlay/command-palette/command-palette.ts"],"names":[],"mappings":"AASA,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAK/F;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB,EAAG,0BAAmC,CAAC;AAO5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,mBAAmB,EAAG,qBAA8B,CAAC"}
1
+ {"version":3,"file":"command-palette.d.ts","sourceRoot":"","sources":["../../../src/overlay/command-palette/command-palette.ts"],"names":[],"mappings":"AAIA,OAAO,yCAAyC,CAAC;AAMjD,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAK/F;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB,EAAG,0BAAmC,CAAC;AAO5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,mBAAmB,EAAG,qBAA8B,CAAC"}
package/dist/progress.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./feedback/progress/progress.css.cjs");let i=require("@vielzeug/ore"),a=require("@vielzeug/ripple");var o=`ore-progress`;(0,i.define)(o,{props:{...n.themableBundle,...n.sizableBundle,"floating-label":i.prop.string(),indeterminate:i.prop.bool(!1),label:i.prop.string(),max:i.prop.number(100),title:i.prop.string(),type:i.prop.oneOf([`linear`,`circular`,`vertical`],`linear`),value:i.prop.number(0),"value-text":i.prop.string()},setup(e){let t=(0,i.getHost)(),n=i.watchEffect,r=2*Math.PI*45,o=(0,a.computed)(()=>`${Math.max(0,Math.min(Number(e.value.value),Number(e.max.value)))/Math.max(1,Number(e.max.value))*100}%`),s=(0,a.computed)(()=>{let t=Math.max(0,Math.min(Number(e.value.value),Number(e.max.value))),n=Math.max(1,Number(e.max.value));return r-t/n*r}),c=()=>e.indeterminate.value?null:String(e.value.value),l=()=>e.label.value??e.title.value??`Progress`,u=(0,i.styleMap)({"--_circ":`${r}px`}),d=()=>e.indeterminate.value?void 0:`${r}px`,f=()=>e.indeterminate.value?void 0:`${s.value}px`,p=(0,a.computed)(()=>e.type.value===`vertical`),m=(0,i.styleMap)({height:()=>!e.indeterminate.value&&p.value?o.value:null,width:()=>!e.indeterminate.value&&!p.value?o.value:null});n(()=>{t.style.setProperty(`--_percent`,e.indeterminate.value?`0%`:o.value)});let h=()=>i.html`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./feedback/progress/progress.css.cjs");let i=require("@vielzeug/ore"),a=require("@vielzeug/ripple");var o=`ore-progress`;(0,i.define)(o,{props:{...n.themableBundle,...n.sizableBundle,"floating-label":i.prop.string(),indeterminate:i.prop.bool(!1),label:i.prop.string(),max:i.prop.number(100),segments:i.prop.number(0),title:i.prop.string(),type:i.prop.oneOf([`linear`,`circular`,`vertical`],`linear`),value:i.prop.number(0),"value-text":i.prop.string()},setup(e){let t=(0,i.getHost)(),n=i.watchEffect,r=2*Math.PI*45,o=(0,a.computed)(()=>`${Math.max(0,Math.min(Number(e.value.value),Number(e.max.value)))/Math.max(1,Number(e.max.value))*100}%`),s=(0,a.computed)(()=>{let t=Math.max(0,Math.min(Number(e.value.value),Number(e.max.value))),n=Math.max(1,Number(e.max.value));return r-t/n*r}),c=()=>e.indeterminate.value?null:String(e.value.value),l=()=>e.label.value??e.title.value??`Progress`,u=(0,i.styleMap)({"--_circ":`${r}px`}),d=()=>e.indeterminate.value?void 0:`${r}px`,f=()=>e.indeterminate.value?void 0:`${s.value}px`,p=(0,a.computed)(()=>e.type.value===`vertical`),m=(0,a.computed)(()=>Math.max(0,Math.floor(Number(e.segments.value)||0))),h=(0,a.computed)(()=>m.value>0&&!e.indeterminate.value&&!p.value),g=(0,a.computed)(()=>{let t=Math.max(0,Math.min(Number(e.value.value),Number(e.max.value))),n=Math.max(1,Number(e.max.value));return Math.round(t/n*m.value)}),_=(0,i.styleMap)({"--_segments":()=>String(m.value)}),v=(0,i.styleMap)({height:()=>!e.indeterminate.value&&p.value?o.value:null,width:()=>!e.indeterminate.value&&!p.value?o.value:null});n(()=>{t.style.setProperty(`--_percent`,e.indeterminate.value?`0%`:o.value)});let y=()=>i.html`
2
2
  <div
3
3
  class="circular-track"
4
4
  role="progressbar"
@@ -23,7 +23,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
23
23
  <span class="circular-title">${()=>e.title.value??``}</span>
24
24
  </div>
25
25
  </div>
26
- `,g=()=>i.html`
26
+ `,b=()=>i.html`
27
27
  <div class="wrapper">
28
28
  <div class="header">
29
29
  <span class="progress-title">${()=>e.title.value??``}</span>
@@ -32,14 +32,22 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
32
32
  <div class=${()=>`bar-row${p.value?` bar-row-vertical`:``}`}>
33
33
  <div class="track-outer">
34
34
  <div
35
- class="track"
35
+ class=${()=>`track${h.value?` track-segmented`:``}`}
36
36
  role="progressbar"
37
37
  aria-valuenow="${c}"
38
38
  aria-valuemin="0"
39
39
  aria-valuemax="${e.max}"
40
40
  aria-label="${l}"
41
- aria-valuetext="${e[`value-text`]}">
42
- <div class="fill" part="fill" style="${m}"></div>
41
+ aria-valuetext="${e[`value-text`]}"
42
+ style="${_}">
43
+ ${()=>h.value?Array.from({length:m.value},(e,t)=>i.html`
44
+ <span
45
+ class="segment"
46
+ part="segment"
47
+ data-filled="${()=>t<g.value?``:null}"></span>
48
+ `):i.html`
49
+ <div class="fill" part="fill" style="${v}"></div>
50
+ `}
43
51
  </div>
44
52
  ${()=>p.value?null:i.html`
45
53
  <span class="floating-label">${e[`floating-label`]}</span>
@@ -49,6 +57,6 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
49
57
  </div>
50
58
  </div>
51
59
  `;return i.html`
52
- ${()=>e.type.value===`circular`?h():g()}
60
+ ${()=>e.type.value===`circular`?y():b()}
53
61
  `},styles:[t.colorThemeMixin,t.forcedColorsMixin,e.reducedMotionMixin,r.default]}),exports.PROGRESS_TAG=o;
54
62
  //# sourceMappingURL=progress.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"progress.cjs","names":[],"sources":["../src/feedback/progress/progress.ts"],"sourcesContent":["import { define, getHost, html, prop, styleMap, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default), 'circular', or 'vertical' */\n type?: 'linear' | 'circular' | 'vertical';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type - 'linear' (default) | 'circular' | 'vertical'\n *\n * @cssprop --progress-width - Bar width override (vertical only)\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n *\n * @part fill - Progress fill element.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n 'floating-label': prop.string(),\n indeterminate: prop.bool(false),\n label: prop.string(),\n max: prop.number(100),\n title: prop.string(),\n type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n value: prop.number(0),\n 'value-text': prop.string(),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n\n const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n const isVertical = computed(() => props.type.value === 'vertical');\n const linearFillStyle = styleMap({\n height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n });\n\n watch(() => {\n el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n });\n\n const circularTemplate = () => html`\n <div\n class=\"circular-track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${circularStyle}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n stroke-dasharray=\"${strokeDasharray}\"\n stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n </div>\n </div>\n `;\n\n const barTemplate = () => html`\n <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n </div>\n <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n <div class=\"track-outer\">\n <div\n class=\"track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\">\n <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n </div>\n ${() =>\n !isVertical.value\n ? html`\n <span class=\"floating-label\">${props['floating-label']}</span>\n `\n : null}\n </div>\n <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n </div>\n </div>\n `;\n\n return html`\n ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n `;\n },\n\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"6TAyEA,IAAa,EAAe,gBAC5B,EAAA,EAAA,OAAA,CAAyB,EAAc,CACrC,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,iBAAkB,EAAA,KAAK,OAAO,EAC9B,cAAe,EAAA,KAAK,KAAK,EAAK,EAC9B,MAAO,EAAA,KAAK,OAAO,EACnB,IAAK,EAAA,KAAK,OAAO,GAAG,EACpB,MAAO,EAAA,KAAK,OAAO,EACnB,KAAM,EAAA,KAAK,MAAM,CAAC,SAAU,WAAY,UAAU,EAAY,QAAQ,EACtE,MAAO,EAAA,KAAK,OAAO,CAAC,EACpB,aAAc,EAAA,KAAK,OAAO,CAC5B,EAEA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,EAAQ,EAAA,YAIR,EAAO,EAAI,KAAK,GAAK,GAErB,GAAA,EAAU,EAAA,SAAA,KAIP,GAHG,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAGtE,EAFD,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAE7B,EAAK,IAAI,EACzB,EAEK,GAAA,EAAa,EAAA,SAAA,KAAe,CAChC,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,EAC5E,EAAI,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,EAE7C,OAAO,EAAQ,EAAI,EAAK,CAC1B,CAAC,EAEK,MAAsB,EAAM,cAAc,MAAQ,KAAO,OAAO,EAAM,MAAM,KAAK,EACjF,MAAkB,EAAM,MAAM,OAAS,EAAM,MAAM,OAAS,WAC5D,GAAA,EAAgB,EAAA,SAAA,CAAS,CAAE,UAAW,GAAG,EAAK,GAAI,CAAC,EACnD,MAAyB,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAK,IACzE,MAA0B,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAW,MAAM,IACtF,GAAA,EAAa,EAAA,SAAA,KAAe,EAAM,KAAK,QAAU,UAAU,EAC3D,GAAA,EAAkB,EAAA,SAAA,CAAS,CAC/B,WAAe,CAAC,EAAM,cAAc,OAAS,EAAW,MAAQ,EAAQ,MAAQ,KAChF,UAAc,CAAC,EAAM,cAAc,OAAS,CAAC,EAAW,MAAQ,EAAQ,MAAQ,IAClF,CAAC,EAED,MAAY,CACV,EAAG,MAAM,YAAY,aAAc,EAAM,cAAc,MAAQ,KAAO,EAAQ,KAAK,CACrF,CAAC,EAED,IAAM,MAAyB,EAAA,IAAI;;;;yBAId,EAAa;;yBAEb,EAAM,IAAI;sBACb,EAAU;0BACN,EAAM,cAAc;iBAC7B,EAAc;;yDAE0B,GAAO;;;;;iBAK/C,GAAO;gCACQ,EAAgB;iCACf,EAAiB;;;6CAGH,EAAM,MAAM,OAAS,GAAG;6CACxB,EAAM,MAAM,OAAS,GAAG;;;MAK7D,MAAoB,EAAA,IAAI;;;6CAGa,EAAM,MAAM,OAAS,GAAG;qDAChB,EAAM,MAAM,OAAS,GAAG;;yBAEpD,UAAU,EAAW,MAAQ,oBAAsB,KAAK;;;;;+BAKpD,EAAa;;+BAEb,EAAM,IAAI;4BACb,EAAU;gCACN,EAAM,cAAc;qDACC,EAAgB;;kBAGtD,EAAW,MAIR,KAHA,EAAA,IAAI;mDAC6B,EAAM,kBAAkB;oBAEpD;;kDAE6B,EAAM,MAAM,OAAS,GAAG;;;MAKxE,MAAO,GAAA,IAAI;YACA,EAAM,KAAK,QAAU,WAAa,EAAiB,EAAI,EAAY,EAAG;KAEnF,EAEA,OAAQ,CAAC,EAAA,gBAAiB,EAAA,kBAAmB,EAAA,mBAAoB,EAAA,OAAe,CAClF,CAAC"}
1
+ {"version":3,"file":"progress.cjs","names":[],"sources":["../src/feedback/progress/progress.ts"],"sourcesContent":["import { define, getHost, html, prop, styleMap, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Split the linear bar into this many discrete blocks; blocks up to `value / max` are filled. Ignored when `indeterminate` or circular. */\n segments?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default), 'circular', or 'vertical' */\n type?: 'linear' | 'circular' | 'vertical';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type - 'linear' (default) | 'circular' | 'vertical'\n * @attr {number} segments - Split the linear bar into discrete blocks (tracks, steps, stages)\n *\n * @cssprop --progress-width - Bar width override (vertical only)\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n * @cssprop --progress-segment-gap - Gap between blocks when `segments` is set (default --size-1)\n *\n * @part fill - Progress fill element.\n * @part segment - One block when `segments` is set; carries `data-filled` once reached.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * <ore-progress value=\"2\" max=\"6\" segments=\"6\" label=\"Struggle\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n 'floating-label': prop.string(),\n indeterminate: prop.bool(false),\n label: prop.string(),\n max: prop.number(100),\n segments: prop.number(0),\n title: prop.string(),\n type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n value: prop.number(0),\n 'value-text': prop.string(),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n\n const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n const isVertical = computed(() => props.type.value === 'vertical');\n const segmentCount = computed(() => Math.max(0, Math.floor(Number(props.segments.value) || 0)));\n const isSegmented = computed(() => segmentCount.value > 0 && !props.indeterminate.value && !isVertical.value);\n const filledSegments = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return Math.round((v / m) * segmentCount.value);\n });\n const segmentStyle = styleMap({ '--_segments': () => String(segmentCount.value) });\n const linearFillStyle = styleMap({\n height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n });\n\n watch(() => {\n el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n });\n\n const circularTemplate = () => html`\n <div\n class=\"circular-track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${circularStyle}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n stroke-dasharray=\"${strokeDasharray}\"\n stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n </div>\n </div>\n `;\n\n const barTemplate = () => html`\n <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n </div>\n <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n <div class=\"track-outer\">\n <div\n class=${() => `track${isSegmented.value ? ' track-segmented' : ''}`}\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${segmentStyle}\">\n ${() =>\n isSegmented.value\n ? Array.from(\n { length: segmentCount.value },\n (_, i) => html`\n <span\n class=\"segment\"\n part=\"segment\"\n data-filled=\"${() => (i < filledSegments.value ? '' : null)}\"></span>\n `,\n )\n : html`\n <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n `}\n </div>\n ${() =>\n !isVertical.value\n ? html`\n <span class=\"floating-label\">${props['floating-label']}</span>\n `\n : null}\n </div>\n <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n </div>\n </div>\n `;\n\n return html`\n ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n `;\n },\n\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"6TA+EA,IAAa,EAAe,gBAC5B,EAAA,EAAA,OAAA,CAAyB,EAAc,CACrC,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,iBAAkB,EAAA,KAAK,OAAO,EAC9B,cAAe,EAAA,KAAK,KAAK,EAAK,EAC9B,MAAO,EAAA,KAAK,OAAO,EACnB,IAAK,EAAA,KAAK,OAAO,GAAG,EACpB,SAAU,EAAA,KAAK,OAAO,CAAC,EACvB,MAAO,EAAA,KAAK,OAAO,EACnB,KAAM,EAAA,KAAK,MAAM,CAAC,SAAU,WAAY,UAAU,EAAY,QAAQ,EACtE,MAAO,EAAA,KAAK,OAAO,CAAC,EACpB,aAAc,EAAA,KAAK,OAAO,CAC5B,EAEA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,EAAQ,EAAA,YAIR,EAAO,EAAI,KAAK,GAAK,GAErB,GAAA,EAAU,EAAA,SAAA,KAIP,GAHG,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAGtE,EAFD,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAE7B,EAAK,IAAI,EACzB,EAEK,GAAA,EAAa,EAAA,SAAA,KAAe,CAChC,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,EAC5E,EAAI,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,EAE7C,OAAO,EAAQ,EAAI,EAAK,CAC1B,CAAC,EAEK,MAAsB,EAAM,cAAc,MAAQ,KAAO,OAAO,EAAM,MAAM,KAAK,EACjF,MAAkB,EAAM,MAAM,OAAS,EAAM,MAAM,OAAS,WAC5D,GAAA,EAAgB,EAAA,SAAA,CAAS,CAAE,UAAW,GAAG,EAAK,GAAI,CAAC,EACnD,MAAyB,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAK,IACzE,MAA0B,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAW,MAAM,IACtF,GAAA,EAAa,EAAA,SAAA,KAAe,EAAM,KAAK,QAAU,UAAU,EAC3D,GAAA,EAAe,EAAA,SAAA,KAAe,KAAK,IAAI,EAAG,KAAK,MAAM,OAAO,EAAM,SAAS,KAAK,GAAK,CAAC,CAAC,CAAC,EACxF,GAAA,EAAc,EAAA,SAAA,KAAe,EAAa,MAAQ,GAAK,CAAC,EAAM,cAAc,OAAS,CAAC,EAAW,KAAK,EACtG,GAAA,EAAiB,EAAA,SAAA,KAAe,CACpC,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,EAC5E,EAAI,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,EAE7C,OAAO,KAAK,MAAO,EAAI,EAAK,EAAa,KAAK,CAChD,CAAC,EACK,GAAA,EAAe,EAAA,SAAA,CAAS,CAAE,kBAAqB,OAAO,EAAa,KAAK,CAAE,CAAC,EAC3E,GAAA,EAAkB,EAAA,SAAA,CAAS,CAC/B,WAAe,CAAC,EAAM,cAAc,OAAS,EAAW,MAAQ,EAAQ,MAAQ,KAChF,UAAc,CAAC,EAAM,cAAc,OAAS,CAAC,EAAW,MAAQ,EAAQ,MAAQ,IAClF,CAAC,EAED,MAAY,CACV,EAAG,MAAM,YAAY,aAAc,EAAM,cAAc,MAAQ,KAAO,EAAQ,KAAK,CACrF,CAAC,EAED,IAAM,MAAyB,EAAA,IAAI;;;;yBAId,EAAa;;yBAEb,EAAM,IAAI;sBACb,EAAU;0BACN,EAAM,cAAc;iBAC7B,EAAc;;yDAE0B,GAAO;;;;;iBAK/C,GAAO;gCACQ,EAAgB;iCACf,EAAiB;;;6CAGH,EAAM,MAAM,OAAS,GAAG;6CACxB,EAAM,MAAM,OAAS,GAAG;;;MAK7D,MAAoB,EAAA,IAAI;;;6CAGa,EAAM,MAAM,OAAS,GAAG;qDAChB,EAAM,MAAM,OAAS,GAAG;;yBAEpD,UAAU,EAAW,MAAQ,oBAAsB,KAAK;;;0BAGvD,QAAQ,EAAY,MAAQ,mBAAqB,KAAK;;+BAEnD,EAAa;;+BAEb,EAAM,IAAI;4BACb,EAAU;gCACN,EAAM,cAAc;uBAC7B,EAAa;oBAEpB,EAAY,MACR,MAAM,KACJ,CAAE,OAAQ,EAAa,KAAM,GAC5B,EAAG,IAAM,EAAA,IAAI;;;;6CAIY,EAAI,EAAe,MAAQ,GAAK,KAAM;uBAElE,EACA,EAAA,IAAI;6DACqC,EAAgB;sBACvD;;kBAGP,EAAW,MAIR,KAHA,EAAA,IAAI;mDAC6B,EAAM,kBAAkB;oBAEpD;;kDAE6B,EAAM,MAAM,OAAS,GAAG;;;MAKxE,MAAO,GAAA,IAAI;YACA,EAAM,KAAK,QAAU,WAAa,EAAiB,EAAI,EAAY,EAAG;KAEnF,EAEA,OAAQ,CAAC,EAAA,gBAAiB,EAAA,kBAAmB,EAAA,mBAAoB,EAAA,OAAe,CAClF,CAAC"}