@vielzeug/refine 2.3.0 → 2.4.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.
- package/dist/accordion-item.cjs +1 -1
- package/dist/accordion-item.cjs.map +1 -1
- package/dist/accordion-item.js +1 -1
- package/dist/accordion-item.js.map +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.cjs.map +1 -1
- package/dist/card.js +1 -1
- package/dist/card.js.map +1 -1
- package/dist/chat-message.cjs +1 -1
- package/dist/chat-message.cjs.map +1 -1
- package/dist/chat-message.js +1 -1
- package/dist/chat-message.js.map +1 -1
- package/dist/combobox.cjs +9 -7
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +55 -48
- package/dist/combobox.js.map +1 -1
- package/dist/content/index.d.ts +2 -0
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/list/list-item.css.cjs +1 -1
- package/dist/content/list/list-item.css.cjs.map +1 -1
- package/dist/content/list/list-item.css.js +1 -1
- package/dist/content/list/list-item.css.js.map +1 -1
- package/dist/content/list/list-item.d.ts +9 -0
- package/dist/content/list/list-item.d.ts.map +1 -1
- package/dist/content/stats/stats.css.cjs +2 -0
- package/dist/content/stats/stats.css.cjs.map +1 -0
- package/dist/content/stats/stats.css.js +6 -0
- package/dist/content/stats/stats.css.js.map +1 -0
- package/dist/content/stats/stats.d.ts +72 -0
- package/dist/content/stats/stats.d.ts.map +1 -0
- package/dist/core/auto-resize.cjs +1 -1
- package/dist/core/auto-resize.cjs.map +1 -1
- package/dist/core/auto-resize.js +1 -1
- package/dist/core/auto-resize.js.map +1 -1
- package/dist/custom-elements.json +5087 -4791
- package/dist/datagrid.cjs +199 -179
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +435 -321
- package/dist/datagrid.js.map +1 -1
- package/dist/disclosure/tab-item/tab-item.css.cjs +1 -1
- package/dist/disclosure/tab-item/tab-item.css.cjs.map +1 -1
- package/dist/disclosure/tab-item/tab-item.css.js +1 -1
- package/dist/disclosure/tab-item/tab-item.css.js.map +1 -1
- package/dist/disclosure/tab-item/tab-item.d.ts +3 -0
- package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
- package/dist/disclosure/tabs/tabs.css.cjs +1 -1
- package/dist/disclosure/tabs/tabs.css.cjs.map +1 -1
- package/dist/disclosure/tabs/tabs.css.js +1 -1
- package/dist/disclosure/tabs/tabs.css.js.map +1 -1
- package/dist/disclosure/tabs/tabs.d.ts +4 -0
- package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
- package/dist/frameworks/elements.d.ts +2 -1
- package/dist/icon.cjs +1 -1
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js +1 -1
- package/dist/icon.js.map +1 -1
- package/dist/input.cjs +5 -4
- package/dist/input.cjs.map +1 -1
- package/dist/input.js +14 -8
- package/dist/input.js.map +1 -1
- package/dist/inputs/combobox/combobox-options.cjs +1 -1
- package/dist/inputs/combobox/combobox-options.cjs.map +1 -1
- package/dist/inputs/combobox/combobox-options.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox-options.js +1 -0
- package/dist/inputs/combobox/combobox-options.js.map +1 -1
- package/dist/inputs/combobox/combobox.css.cjs +1 -1
- package/dist/inputs/combobox/combobox.css.cjs.map +1 -1
- package/dist/inputs/combobox/combobox.css.js +1 -1
- package/dist/inputs/combobox/combobox.css.js.map +1 -1
- package/dist/inputs/combobox/combobox.d.ts +1 -0
- package/dist/inputs/combobox/combobox.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox.types.d.ts +7 -0
- package/dist/inputs/combobox/combobox.types.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.d.ts +17 -3
- package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.js +93 -70
- package/dist/inputs/datagrid/datagrid-model.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.css.cjs +1 -1
- package/dist/inputs/datagrid/datagrid.css.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid.css.js +1 -1
- package/dist/inputs/datagrid/datagrid.css.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts +54 -4
- package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
- package/dist/inputs/index.d.ts +1 -1
- package/dist/inputs/index.d.ts.map +1 -1
- package/dist/inputs/input/input.css.cjs +1 -1
- package/dist/inputs/input/input.css.cjs.map +1 -1
- package/dist/inputs/input/input.css.js +1 -1
- package/dist/inputs/input/input.css.js.map +1 -1
- package/dist/inputs/input/input.d.ts +3 -0
- package/dist/inputs/input/input.d.ts.map +1 -1
- package/dist/inputs/select/select.css.cjs +1 -1
- package/dist/inputs/select/select.css.cjs.map +1 -1
- package/dist/inputs/select/select.css.js +1 -1
- package/dist/inputs/select/select.css.js.map +1 -1
- package/dist/inputs/select/select.d.ts +5 -0
- package/dist/inputs/select/select.d.ts.map +1 -1
- package/dist/layout/navbar/navbar.d.ts +2 -0
- package/dist/layout/navbar/navbar.d.ts.map +1 -1
- package/dist/layout/sidebar/sidebar.css.cjs +1 -1
- package/dist/layout/sidebar/sidebar.css.cjs.map +1 -1
- package/dist/layout/sidebar/sidebar.css.js +1 -1
- package/dist/layout/sidebar/sidebar.css.js.map +1 -1
- package/dist/layout/sidebar/sidebar.d.ts +8 -0
- package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
- package/dist/list-item.cjs +6 -5
- package/dist/list-item.cjs.map +1 -1
- package/dist/list-item.js +23 -17
- package/dist/list-item.js.map +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.cjs.map +1 -1
- package/dist/list.js +1 -1
- package/dist/list.js.map +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +1 -1
- package/dist/menu.js.map +1 -1
- package/dist/navbar.cjs +2 -2
- package/dist/navbar.cjs.map +1 -1
- package/dist/navbar.js +7 -5
- package/dist/navbar.js.map +1 -1
- package/dist/navigation-menu.cjs +1 -1
- package/dist/navigation-menu.cjs.map +1 -1
- package/dist/navigation-menu.js +1 -1
- package/dist/navigation-menu.js.map +1 -1
- package/dist/overlay/popover/popover.css.cjs +1 -1
- package/dist/overlay/popover/popover.css.cjs.map +1 -1
- package/dist/overlay/popover/popover.css.js +1 -1
- package/dist/overlay/popover/popover.css.js.map +1 -1
- package/dist/overlay/popover/popover.d.ts +1 -0
- package/dist/overlay/popover/popover.d.ts.map +1 -1
- package/dist/overlay/shared/use-dialog.cjs +1 -1
- package/dist/overlay/shared/use-dialog.cjs.map +1 -1
- package/dist/overlay/shared/use-dialog.js +1 -1
- package/dist/overlay/shared/use-dialog.js.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.cjs +1 -1
- package/dist/overlay/shared/use-floating-trigger.cjs.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.js +1 -1
- package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
- package/dist/popover.cjs.map +1 -1
- package/dist/popover.js.map +1 -1
- package/dist/radio.cjs +1 -1
- package/dist/radio.cjs.map +1 -1
- package/dist/radio.js +10 -8
- package/dist/radio.js.map +1 -1
- package/dist/rating.cjs +1 -1
- package/dist/rating.cjs.map +1 -1
- package/dist/rating.js +1 -1
- package/dist/rating.js.map +1 -1
- package/dist/refine.cjs +372 -323
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +372 -323
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +402 -353
- package/dist/refine.js.map +1 -1
- package/dist/select.cjs +16 -14
- package/dist/select.cjs.map +1 -1
- package/dist/select.js +118 -112
- package/dist/select.js.map +1 -1
- package/dist/sidebar.cjs +28 -23
- package/dist/sidebar.cjs.map +1 -1
- package/dist/sidebar.js +112 -77
- package/dist/sidebar.js.map +1 -1
- package/dist/slider.cjs +1 -1
- package/dist/slider.cjs.map +1 -1
- package/dist/slider.js +1 -1
- package/dist/slider.js.map +1 -1
- package/dist/stats.cjs +18 -0
- package/dist/stats.cjs.map +1 -0
- package/dist/stats.js +88 -0
- package/dist/stats.js.map +1 -0
- package/dist/stepper.cjs +1 -1
- package/dist/stepper.cjs.map +1 -1
- package/dist/stepper.js +1 -1
- package/dist/stepper.js.map +1 -1
- package/dist/styles/mixins/animation.css.cjs +2 -0
- package/dist/styles/mixins/animation.css.cjs.map +1 -1
- package/dist/styles/mixins/animation.css.d.ts.map +1 -1
- package/dist/styles/mixins/animation.css.js +2 -0
- package/dist/styles/mixins/animation.css.js.map +1 -1
- package/dist/tab-item.cjs +1 -1
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js +3 -2
- package/dist/tab-item.js.map +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.cjs.map +1 -1
- package/dist/tabs.js +3 -1
- package/dist/tabs.js.map +1 -1
- package/dist/toast.cjs.map +1 -1
- package/dist/toast.js.map +1 -1
- package/package.json +64 -56
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=`@layer refine.base{:host{--tabs-transition:var(--transition-normal);--tabs-radius:var(--rounded-lg);flex-direction:column;width:100%;height:100%;display:flex}.tablist-wrapper{flex-shrink:0;position:relative}[role=tablist]{gap:var(--tabs-tab-gap,var(--size-1));scrollbar-width:none;align-items:stretch;display:flex;position:relative;overflow-x:auto}[role=tablist]::-webkit-scrollbar{display:none}.indicator{pointer-events:none;background:var(--tabs-indicator-color,var(--_theme-base));border-radius:var(--rounded-full);height:2px;transition:transform var(--tabs-transition);position:absolute;bottom:0;left:0}.panels{flex-direction:column;flex:1;min-height:0;display:flex}}@layer refine.orientation{:host([orientation=vertical]){flex-direction:row;align-items:flex-start}:host([orientation=vertical]) .tablist-wrapper{flex-shrink:0;display:flex}:host([orientation=vertical]) [role=tablist]{width:max-content;overflow-x:unset;flex-direction:column;overflow-y:auto}:host([orientation=vertical]) .indicator{top:0;bottom:unset;width:2px;height:unset;transition:transform var(--tabs-transition)}:host([orientation=vertical]) .indicator: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))){left:0}:host([orientation=vertical]) .indicator: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)){right:0}}@layer refine.variants{:host,:host([variant=solid]){--tabs-tab-gap:var(--size-1);--_tablist-bg:var(--tabs-tablist-bg,var(--color-contrast-100));--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host [role=tablist],:host([variant=solid]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius)}:host .indicator,:host([variant=solid]) .indicator{display:none}:host([variant=flat]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200));background:var(--tabs-bg,var(--color-contrast-100));border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--inset-shadow-xs), var(--shadow-2xs);overflow:hidden}:host([variant=flat]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:none;border-bottom:var(--border) solid var(--_tablist-border-color);background:0 0;border-radius:0}:host([variant=flat]) .indicator{display:none}:host([variant=bordered]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host([variant=bordered]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) var(--tabs-radius) 0 0;background:0 0;border-bottom:none}:host([variant=bordered]) .indicator{display:none}:host([variant=bordered]) .panels{border:var(--border) solid var(--_tablist-border-color);border-radius:0 0 var(--tabs-radius) var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) [role=tablist]{border-right:none;border-bottom:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) 0 0 var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) .panels{border-radius:0 var(--tabs-radius) var(--tabs-radius) 0}:host([variant=ghost]) [role=tablist]{gap:var(--size-1);background:0 0;border:none;border-radius:0;padding:0}:host([variant=ghost]) .indicator{display:none}:host([variant=glass]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-secondary) 20%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent))}:host([variant=glass]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05);backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05)}:host([variant=glass]) .indicator{display:none}:host([variant=frost]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-canvas) 55%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-contrast-300) 50%, transparent))}:host([variant=frost]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%);backdrop-filter:blur(var(--blur-lg)) saturate(180%)}:host([variant=frost]) .indicator{display:none}}`;exports.default=e;
|
|
1
|
+
var e=`@layer refine.base{:host{--tabs-transition:var(--transition-normal);--tabs-radius:var(--rounded-lg);flex-direction:column;width:100%;height:100%;display:flex}.tablist-wrapper{flex-shrink:0;position:relative}[role=tablist]{gap:var(--tabs-tab-gap,var(--size-1));scrollbar-width:none;align-items:stretch;display:flex;position:relative;overflow-x:auto}[role=tablist]::-webkit-scrollbar{display:none}.indicator{pointer-events:none;background:var(--tabs-indicator-color,var(--_theme-base));border-radius:var(--rounded-full);height:2px;transition:transform var(--tabs-transition);position:absolute;bottom:0;left:0}.panels{flex-direction:column;flex:1;min-height:0;display:flex}}@layer refine.orientation{:host([orientation=vertical]){flex-direction:row;align-items:flex-start}:host([orientation=vertical]) .tablist-wrapper{flex-shrink:0;display:flex}:host([orientation=vertical]) [role=tablist]{width:max-content;overflow-x:unset;flex-direction:column;overflow-y:auto}:host([orientation=vertical]) .indicator{top:0;bottom:unset;width:2px;height:unset;transition:transform var(--tabs-transition)}:host([orientation=vertical]) .indicator: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))){left:0}:host([orientation=vertical]) .indicator: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)){right:0}}@layer refine.variants{:host,:host([variant=solid]){--tabs-tab-gap:var(--size-1);--_tablist-bg:var(--tabs-tablist-bg,var(--color-contrast-100));--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host [role=tablist],:host([variant=solid]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius)}:host .indicator,:host([variant=solid]) .indicator{display:none}:host([variant=flat]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200));background:var(--tabs-bg,var(--color-contrast-100));border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--inset-shadow-xs), var(--shadow-2xs);overflow:hidden}:host([variant=flat]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:none;border-bottom:var(--border) solid var(--_tablist-border-color);background:0 0;border-radius:0}:host([variant=flat]) .indicator{display:none}:host([variant=bordered]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host([variant=bordered]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) var(--tabs-radius) 0 0;background:0 0;border-bottom:none}:host([variant=bordered]) .indicator{display:none}:host([variant=bordered]) .panels{border:var(--border) solid var(--_tablist-border-color);border-radius:0 0 var(--tabs-radius) var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) [role=tablist]{border-right:none;border-bottom:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) 0 0 var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) .panels{border-radius:0 var(--tabs-radius) var(--tabs-radius) 0}:host([variant=ghost]) [role=tablist]{gap:var(--size-1);background:0 0;border:none;border-radius:0;padding:0}:host([variant=ghost]) .indicator{display:none}:host([variant=glass]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-secondary) 20%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent))}:host([variant=glass]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05);backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05)}:host([variant=glass]) .indicator{display:none}:host([variant=frost]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-canvas) 55%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-contrast-300) 50%, transparent))}:host([variant=frost]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%);backdrop-filter:blur(var(--blur-lg)) saturate(180%)}:host([variant=frost]) .indicator{display:none}}@layer refine.density{:host([density=compact]){--tabs-radius:var(--rounded-md);height:auto}:host([density=compact]) [role=tablist]{gap:var(--size-1);padding:var(--size-1)}:host([density=compact][variant=ghost]) [role=tablist]{padding:0}}`;exports.default=e;
|
|
2
2
|
//# sourceMappingURL=tabs.css.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.css.cjs","names":[],"sources":["../../../src/disclosure/tabs/tabs.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --tabs-transition: var(--transition-normal);\n --tabs-radius: var(--rounded-lg);\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .tablist-wrapper {\n position: relative;\n flex-shrink: 0;\n }\n\n [role='tablist'] {\n position: relative;\n display: flex;\n gap: var(--tabs-tab-gap, var(--size-1));\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n [role='tablist']::-webkit-scrollbar {\n display: none;\n }\n\n .indicator {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 2px;\n pointer-events: none;\n background: var(--tabs-indicator-color, var(--_theme-base));\n border-radius: var(--rounded-full);\n transition: transform var(--tabs-transition);\n }\n\n .panels {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n}\n\n@layer refine.orientation {\n /* ─── vertical orientation ─── */\n :host([orientation='vertical']) {\n flex-direction: row;\n align-items: flex-start;\n }\n\n :host([orientation='vertical']) .tablist-wrapper {\n display: flex;\n flex-shrink: 0;\n }\n\n :host([orientation='vertical']) [role='tablist'] {\n flex-direction: column;\n width: max-content;\n overflow-x: unset;\n overflow-y: auto;\n }\n\n :host([orientation='vertical']) .indicator {\n inset-inline-start: 0;\n top: 0;\n\n /* Reposition indicator to inline-start side for vertical */\n bottom: unset;\n width: 2px;\n height: unset;\n transition: transform var(--tabs-transition);\n }\n}\n\n@layer refine.variants {\n /* ─── solid (default) ─── */\n :host,\n :host([variant='solid']) {\n --tabs-tab-gap: var(--size-1);\n --_tablist-bg: var(--tabs-tablist-bg, var(--color-contrast-100));\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host [role='tablist'],\n :host([variant='solid']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n }\n\n :host .indicator,\n :host([variant='solid']) .indicator {\n display: none;\n }\n\n /* ─── flat ─── */\n :host([variant='flat']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n\n overflow: hidden;\n background: var(--tabs-bg, var(--color-contrast-100));\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n }\n\n :host([variant='flat']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: 0;\n }\n\n :host([variant='flat']) .indicator {\n display: none;\n }\n\n /* ─── bordered ─── */\n :host([variant='bordered']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host([variant='bordered']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: var(--border) solid var(--_tablist-border-color);\n border-bottom: none;\n border-radius: var(--tabs-radius) var(--tabs-radius) 0 0;\n }\n\n :host([variant='bordered']) .indicator {\n display: none;\n }\n\n :host([variant='bordered']) .panels {\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: 0 0 var(--tabs-radius) var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) [role='tablist'] {\n border-right: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius) 0 0 var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) .panels {\n border-radius: 0 var(--tabs-radius) var(--tabs-radius) 0;\n }\n\n /* ─── ghost ─── */\n :host([variant='ghost']) [role='tablist'] {\n gap: var(--size-1);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n\n :host([variant='ghost']) .indicator {\n display: none;\n }\n\n /* ─── glass ─── */\n :host([variant='glass']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-secondary) 20%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent)\n );\n }\n\n :host([variant='glass']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n :host([variant='glass']) .indicator {\n display: none;\n }\n\n /* ─── frost ─── */\n :host([variant='frost']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-canvas) 55%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-contrast-300) 50%, transparent)\n );\n }\n\n :host([variant='frost']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n :host([variant='frost']) .indicator {\n display: none;\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"tabs.css.cjs","names":[],"sources":["../../../src/disclosure/tabs/tabs.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --tabs-transition: var(--transition-normal);\n --tabs-radius: var(--rounded-lg);\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .tablist-wrapper {\n position: relative;\n flex-shrink: 0;\n }\n\n [role='tablist'] {\n position: relative;\n display: flex;\n gap: var(--tabs-tab-gap, var(--size-1));\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n [role='tablist']::-webkit-scrollbar {\n display: none;\n }\n\n .indicator {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 2px;\n pointer-events: none;\n background: var(--tabs-indicator-color, var(--_theme-base));\n border-radius: var(--rounded-full);\n transition: transform var(--tabs-transition);\n }\n\n .panels {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n}\n\n@layer refine.orientation {\n /* ─── vertical orientation ─── */\n :host([orientation='vertical']) {\n flex-direction: row;\n align-items: flex-start;\n }\n\n :host([orientation='vertical']) .tablist-wrapper {\n display: flex;\n flex-shrink: 0;\n }\n\n :host([orientation='vertical']) [role='tablist'] {\n flex-direction: column;\n width: max-content;\n overflow-x: unset;\n overflow-y: auto;\n }\n\n :host([orientation='vertical']) .indicator {\n inset-inline-start: 0;\n top: 0;\n\n /* Reposition indicator to inline-start side for vertical */\n bottom: unset;\n width: 2px;\n height: unset;\n transition: transform var(--tabs-transition);\n }\n}\n\n@layer refine.variants {\n /* ─── solid (default) ─── */\n :host,\n :host([variant='solid']) {\n --tabs-tab-gap: var(--size-1);\n --_tablist-bg: var(--tabs-tablist-bg, var(--color-contrast-100));\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host [role='tablist'],\n :host([variant='solid']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n }\n\n :host .indicator,\n :host([variant='solid']) .indicator {\n display: none;\n }\n\n /* ─── flat ─── */\n :host([variant='flat']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n\n overflow: hidden;\n background: var(--tabs-bg, var(--color-contrast-100));\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n }\n\n :host([variant='flat']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: 0;\n }\n\n :host([variant='flat']) .indicator {\n display: none;\n }\n\n /* ─── bordered ─── */\n :host([variant='bordered']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host([variant='bordered']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: var(--border) solid var(--_tablist-border-color);\n border-bottom: none;\n border-radius: var(--tabs-radius) var(--tabs-radius) 0 0;\n }\n\n :host([variant='bordered']) .indicator {\n display: none;\n }\n\n :host([variant='bordered']) .panels {\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: 0 0 var(--tabs-radius) var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) [role='tablist'] {\n border-right: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius) 0 0 var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) .panels {\n border-radius: 0 var(--tabs-radius) var(--tabs-radius) 0;\n }\n\n /* ─── ghost ─── */\n :host([variant='ghost']) [role='tablist'] {\n gap: var(--size-1);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n\n :host([variant='ghost']) .indicator {\n display: none;\n }\n\n /* ─── glass ─── */\n :host([variant='glass']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-secondary) 20%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent)\n );\n }\n\n :host([variant='glass']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n :host([variant='glass']) .indicator {\n display: none;\n }\n\n /* ─── frost ─── */\n :host([variant='frost']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-canvas) 55%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-contrast-300) 50%, transparent)\n );\n }\n\n :host([variant='frost']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n :host([variant='frost']) .indicator {\n display: none;\n }\n}\n\n@layer refine.density {\n :host([density='compact']) {\n --tabs-radius: var(--rounded-md);\n\n height: auto;\n }\n\n :host([density='compact']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n }\n\n :host([density='compact'][variant='ghost']) [role='tablist'] {\n padding: 0;\n }\n}\n"],"mappings":""}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/disclosure/tabs/tabs.css?inline
|
|
2
|
-
var e = "@layer refine.base{:host{--tabs-transition:var(--transition-normal);--tabs-radius:var(--rounded-lg);flex-direction:column;width:100%;height:100%;display:flex}.tablist-wrapper{flex-shrink:0;position:relative}[role=tablist]{gap:var(--tabs-tab-gap,var(--size-1));scrollbar-width:none;align-items:stretch;display:flex;position:relative;overflow-x:auto}[role=tablist]::-webkit-scrollbar{display:none}.indicator{pointer-events:none;background:var(--tabs-indicator-color,var(--_theme-base));border-radius:var(--rounded-full);height:2px;transition:transform var(--tabs-transition);position:absolute;bottom:0;left:0}.panels{flex-direction:column;flex:1;min-height:0;display:flex}}@layer refine.orientation{:host([orientation=vertical]){flex-direction:row;align-items:flex-start}:host([orientation=vertical]) .tablist-wrapper{flex-shrink:0;display:flex}:host([orientation=vertical]) [role=tablist]{width:max-content;overflow-x:unset;flex-direction:column;overflow-y:auto}:host([orientation=vertical]) .indicator{top:0;bottom:unset;width:2px;height:unset;transition:transform var(--tabs-transition)}:host([orientation=vertical]) .indicator: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))){left:0}:host([orientation=vertical]) .indicator: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)){right:0}}@layer refine.variants{:host,:host([variant=solid]){--tabs-tab-gap:var(--size-1);--_tablist-bg:var(--tabs-tablist-bg,var(--color-contrast-100));--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host [role=tablist],:host([variant=solid]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius)}:host .indicator,:host([variant=solid]) .indicator{display:none}:host([variant=flat]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200));background:var(--tabs-bg,var(--color-contrast-100));border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--inset-shadow-xs), var(--shadow-2xs);overflow:hidden}:host([variant=flat]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:none;border-bottom:var(--border) solid var(--_tablist-border-color);background:0 0;border-radius:0}:host([variant=flat]) .indicator{display:none}:host([variant=bordered]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host([variant=bordered]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) var(--tabs-radius) 0 0;background:0 0;border-bottom:none}:host([variant=bordered]) .indicator{display:none}:host([variant=bordered]) .panels{border:var(--border) solid var(--_tablist-border-color);border-radius:0 0 var(--tabs-radius) var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) [role=tablist]{border-right:none;border-bottom:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) 0 0 var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) .panels{border-radius:0 var(--tabs-radius) var(--tabs-radius) 0}:host([variant=ghost]) [role=tablist]{gap:var(--size-1);background:0 0;border:none;border-radius:0;padding:0}:host([variant=ghost]) .indicator{display:none}:host([variant=glass]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-secondary) 20%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent))}:host([variant=glass]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05);backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05)}:host([variant=glass]) .indicator{display:none}:host([variant=frost]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-canvas) 55%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-contrast-300) 50%, transparent))}:host([variant=frost]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%);backdrop-filter:blur(var(--blur-lg)) saturate(180%)}:host([variant=frost]) .indicator{display:none}}";
|
|
2
|
+
var e = "@layer refine.base{:host{--tabs-transition:var(--transition-normal);--tabs-radius:var(--rounded-lg);flex-direction:column;width:100%;height:100%;display:flex}.tablist-wrapper{flex-shrink:0;position:relative}[role=tablist]{gap:var(--tabs-tab-gap,var(--size-1));scrollbar-width:none;align-items:stretch;display:flex;position:relative;overflow-x:auto}[role=tablist]::-webkit-scrollbar{display:none}.indicator{pointer-events:none;background:var(--tabs-indicator-color,var(--_theme-base));border-radius:var(--rounded-full);height:2px;transition:transform var(--tabs-transition);position:absolute;bottom:0;left:0}.panels{flex-direction:column;flex:1;min-height:0;display:flex}}@layer refine.orientation{:host([orientation=vertical]){flex-direction:row;align-items:flex-start}:host([orientation=vertical]) .tablist-wrapper{flex-shrink:0;display:flex}:host([orientation=vertical]) [role=tablist]{width:max-content;overflow-x:unset;flex-direction:column;overflow-y:auto}:host([orientation=vertical]) .indicator{top:0;bottom:unset;width:2px;height:unset;transition:transform var(--tabs-transition)}:host([orientation=vertical]) .indicator: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))){left:0}:host([orientation=vertical]) .indicator: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)){right:0}}@layer refine.variants{:host,:host([variant=solid]){--tabs-tab-gap:var(--size-1);--_tablist-bg:var(--tabs-tablist-bg,var(--color-contrast-100));--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host [role=tablist],:host([variant=solid]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius)}:host .indicator,:host([variant=solid]) .indicator{display:none}:host([variant=flat]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200));background:var(--tabs-bg,var(--color-contrast-100));border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--inset-shadow-xs), var(--shadow-2xs);overflow:hidden}:host([variant=flat]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:none;border-bottom:var(--border) solid var(--_tablist-border-color);background:0 0;border-radius:0}:host([variant=flat]) .indicator{display:none}:host([variant=bordered]){--_tablist-border-color:var(--tabs-tablist-border-color,var(--color-contrast-200))}:host([variant=bordered]) [role=tablist]{gap:var(--size-1);padding:var(--size-1);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) var(--tabs-radius) 0 0;background:0 0;border-bottom:none}:host([variant=bordered]) .indicator{display:none}:host([variant=bordered]) .panels{border:var(--border) solid var(--_tablist-border-color);border-radius:0 0 var(--tabs-radius) var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) [role=tablist]{border-right:none;border-bottom:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius) 0 0 var(--tabs-radius)}:host([variant=bordered][orientation=vertical]) .panels{border-radius:0 var(--tabs-radius) var(--tabs-radius) 0}:host([variant=ghost]) [role=tablist]{gap:var(--size-1);background:0 0;border:none;border-radius:0;padding:0}:host([variant=ghost]) .indicator{display:none}:host([variant=glass]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-secondary) 20%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent))}:host([variant=glass]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05);backdrop-filter:blur(var(--blur-lg)) saturate(180%) brightness(1.05)}:host([variant=glass]) .indicator{display:none}:host([variant=frost]){--_tablist-bg:var(--tabs-tablist-bg,color-mix(in oklch, var(--color-canvas) 55%, transparent));--_tablist-border-color:var(--tabs-tablist-border-color,color-mix(in oklch, var(--color-contrast-300) 50%, transparent))}:host([variant=frost]) [role=tablist]{padding:var(--size-1);background:var(--_tablist-bg);border:var(--border) solid var(--_tablist-border-color);border-radius:var(--tabs-radius);box-shadow:var(--shadow-md), var(--inset-shadow-xs);-webkit-backdrop-filter:blur(var(--blur-lg)) saturate(180%);backdrop-filter:blur(var(--blur-lg)) saturate(180%)}:host([variant=frost]) .indicator{display:none}}@layer refine.density{:host([density=compact]){--tabs-radius:var(--rounded-md);height:auto}:host([density=compact]) [role=tablist]{gap:var(--size-1);padding:var(--size-1)}:host([density=compact][variant=ghost]) [role=tablist]{padding:0}}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.css.js","names":[],"sources":["../../../src/disclosure/tabs/tabs.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --tabs-transition: var(--transition-normal);\n --tabs-radius: var(--rounded-lg);\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .tablist-wrapper {\n position: relative;\n flex-shrink: 0;\n }\n\n [role='tablist'] {\n position: relative;\n display: flex;\n gap: var(--tabs-tab-gap, var(--size-1));\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n [role='tablist']::-webkit-scrollbar {\n display: none;\n }\n\n .indicator {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 2px;\n pointer-events: none;\n background: var(--tabs-indicator-color, var(--_theme-base));\n border-radius: var(--rounded-full);\n transition: transform var(--tabs-transition);\n }\n\n .panels {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n}\n\n@layer refine.orientation {\n /* ─── vertical orientation ─── */\n :host([orientation='vertical']) {\n flex-direction: row;\n align-items: flex-start;\n }\n\n :host([orientation='vertical']) .tablist-wrapper {\n display: flex;\n flex-shrink: 0;\n }\n\n :host([orientation='vertical']) [role='tablist'] {\n flex-direction: column;\n width: max-content;\n overflow-x: unset;\n overflow-y: auto;\n }\n\n :host([orientation='vertical']) .indicator {\n inset-inline-start: 0;\n top: 0;\n\n /* Reposition indicator to inline-start side for vertical */\n bottom: unset;\n width: 2px;\n height: unset;\n transition: transform var(--tabs-transition);\n }\n}\n\n@layer refine.variants {\n /* ─── solid (default) ─── */\n :host,\n :host([variant='solid']) {\n --tabs-tab-gap: var(--size-1);\n --_tablist-bg: var(--tabs-tablist-bg, var(--color-contrast-100));\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host [role='tablist'],\n :host([variant='solid']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n }\n\n :host .indicator,\n :host([variant='solid']) .indicator {\n display: none;\n }\n\n /* ─── flat ─── */\n :host([variant='flat']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n\n overflow: hidden;\n background: var(--tabs-bg, var(--color-contrast-100));\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n }\n\n :host([variant='flat']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: 0;\n }\n\n :host([variant='flat']) .indicator {\n display: none;\n }\n\n /* ─── bordered ─── */\n :host([variant='bordered']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host([variant='bordered']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: var(--border) solid var(--_tablist-border-color);\n border-bottom: none;\n border-radius: var(--tabs-radius) var(--tabs-radius) 0 0;\n }\n\n :host([variant='bordered']) .indicator {\n display: none;\n }\n\n :host([variant='bordered']) .panels {\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: 0 0 var(--tabs-radius) var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) [role='tablist'] {\n border-right: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius) 0 0 var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) .panels {\n border-radius: 0 var(--tabs-radius) var(--tabs-radius) 0;\n }\n\n /* ─── ghost ─── */\n :host([variant='ghost']) [role='tablist'] {\n gap: var(--size-1);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n\n :host([variant='ghost']) .indicator {\n display: none;\n }\n\n /* ─── glass ─── */\n :host([variant='glass']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-secondary) 20%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent)\n );\n }\n\n :host([variant='glass']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n :host([variant='glass']) .indicator {\n display: none;\n }\n\n /* ─── frost ─── */\n :host([variant='frost']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-canvas) 55%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-contrast-300) 50%, transparent)\n );\n }\n\n :host([variant='frost']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n :host([variant='frost']) .indicator {\n display: none;\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"tabs.css.js","names":[],"sources":["../../../src/disclosure/tabs/tabs.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --tabs-transition: var(--transition-normal);\n --tabs-radius: var(--rounded-lg);\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .tablist-wrapper {\n position: relative;\n flex-shrink: 0;\n }\n\n [role='tablist'] {\n position: relative;\n display: flex;\n gap: var(--tabs-tab-gap, var(--size-1));\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n [role='tablist']::-webkit-scrollbar {\n display: none;\n }\n\n .indicator {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 2px;\n pointer-events: none;\n background: var(--tabs-indicator-color, var(--_theme-base));\n border-radius: var(--rounded-full);\n transition: transform var(--tabs-transition);\n }\n\n .panels {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n}\n\n@layer refine.orientation {\n /* ─── vertical orientation ─── */\n :host([orientation='vertical']) {\n flex-direction: row;\n align-items: flex-start;\n }\n\n :host([orientation='vertical']) .tablist-wrapper {\n display: flex;\n flex-shrink: 0;\n }\n\n :host([orientation='vertical']) [role='tablist'] {\n flex-direction: column;\n width: max-content;\n overflow-x: unset;\n overflow-y: auto;\n }\n\n :host([orientation='vertical']) .indicator {\n inset-inline-start: 0;\n top: 0;\n\n /* Reposition indicator to inline-start side for vertical */\n bottom: unset;\n width: 2px;\n height: unset;\n transition: transform var(--tabs-transition);\n }\n}\n\n@layer refine.variants {\n /* ─── solid (default) ─── */\n :host,\n :host([variant='solid']) {\n --tabs-tab-gap: var(--size-1);\n --_tablist-bg: var(--tabs-tablist-bg, var(--color-contrast-100));\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host [role='tablist'],\n :host([variant='solid']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n }\n\n :host .indicator,\n :host([variant='solid']) .indicator {\n display: none;\n }\n\n /* ─── flat ─── */\n :host([variant='flat']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n\n overflow: hidden;\n background: var(--tabs-bg, var(--color-contrast-100));\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n }\n\n :host([variant='flat']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: 0;\n }\n\n :host([variant='flat']) .indicator {\n display: none;\n }\n\n /* ─── bordered ─── */\n :host([variant='bordered']) {\n --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n }\n\n :host([variant='bordered']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: var(--border) solid var(--_tablist-border-color);\n border-bottom: none;\n border-radius: var(--tabs-radius) var(--tabs-radius) 0 0;\n }\n\n :host([variant='bordered']) .indicator {\n display: none;\n }\n\n :host([variant='bordered']) .panels {\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: 0 0 var(--tabs-radius) var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) [role='tablist'] {\n border-right: none;\n border-bottom: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius) 0 0 var(--tabs-radius);\n }\n\n :host([variant='bordered'][orientation='vertical']) .panels {\n border-radius: 0 var(--tabs-radius) var(--tabs-radius) 0;\n }\n\n /* ─── ghost ─── */\n :host([variant='ghost']) [role='tablist'] {\n gap: var(--size-1);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n\n :host([variant='ghost']) .indicator {\n display: none;\n }\n\n /* ─── glass ─── */\n :host([variant='glass']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-secondary) 20%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent)\n );\n }\n\n :host([variant='glass']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n :host([variant='glass']) .indicator {\n display: none;\n }\n\n /* ─── frost ─── */\n :host([variant='frost']) {\n --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-canvas) 55%, transparent));\n --_tablist-border-color: var(\n --tabs-tablist-border-color,\n color-mix(in oklch, var(--color-contrast-300) 50%, transparent)\n );\n }\n\n :host([variant='frost']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--_tablist-bg);\n border: var(--border) solid var(--_tablist-border-color);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n :host([variant='frost']) .indicator {\n display: none;\n }\n}\n\n@layer refine.density {\n :host([density='compact']) {\n --tabs-radius: var(--rounded-md);\n\n height: auto;\n }\n\n :host([density='compact']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n }\n\n :host([density='compact'][variant='ghost']) [role='tablist'] {\n padding: 0;\n }\n}\n"],"mappings":""}
|
|
@@ -3,6 +3,7 @@ import type { ComponentSize, SurfaceVariant, ThemeColor } from '../../types';
|
|
|
3
3
|
/** Context provided by ore-tabs to its ore-tab-item and ore-tab-panel children. */
|
|
4
4
|
export type TabsContext = {
|
|
5
5
|
color: Readable<ThemeColor | undefined>;
|
|
6
|
+
density: Readable<'compact' | 'default'>;
|
|
6
7
|
orientation: Readable<'horizontal' | 'vertical'>;
|
|
7
8
|
size: Readable<ComponentSize | undefined>;
|
|
8
9
|
value: Readable<string | undefined>;
|
|
@@ -24,6 +25,8 @@ export type OreTabsProps = {
|
|
|
24
25
|
activation?: 'auto' | 'manual';
|
|
25
26
|
/** Theme color */
|
|
26
27
|
color?: ThemeColor;
|
|
28
|
+
/** Spatial density; compact renders a 24px tab control for dense interfaces. */
|
|
29
|
+
density?: 'compact' | 'default';
|
|
27
30
|
/** Accessible label for the tablist (passed as aria-label). Use when there is no visible heading labelling the tabs. */
|
|
28
31
|
label?: string;
|
|
29
32
|
/** Tab list orientation */
|
|
@@ -45,6 +48,7 @@ export type OreTabsProps = {
|
|
|
45
48
|
* @attr {string} value - The value of the currently selected tab
|
|
46
49
|
* @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'ghost' | 'glass' | 'frost'
|
|
47
50
|
* @attr {string} size - Size: 'sm' | 'md' | 'lg'
|
|
51
|
+
* @attr {string} density - Spatial density: 'default' | 'compact'
|
|
48
52
|
* @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'
|
|
49
53
|
*
|
|
50
54
|
* @fires change - Emitted when the active tab changes with detail: { value: string }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/disclosure/tabs/tabs.ts"],"names":[],"mappings":"AAaA,OAAO,EAAY,KAAK,QAAQ,EAAiB,MAAM,kBAAkB,CAAC;AAI1E,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG7E,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACxC,WAAW,EAAE,QAAQ,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC;IACjD,IAAI,EAAE,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IAC1C,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACpC,OAAO,EAAE,QAAQ,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;CAC/C,CAAC;AACF,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,mDAA4C,CAAC;AAElE,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,kBAAkB;IAClB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,wHAAwH;IACxH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,qBAAqB;IACrB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/disclosure/tabs/tabs.ts"],"names":[],"mappings":"AAaA,OAAO,EAAY,KAAK,QAAQ,EAAiB,MAAM,kBAAkB,CAAC;AAI1E,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG7E,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACxC,OAAO,EAAE,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IACzC,WAAW,EAAE,QAAQ,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC;IACjD,IAAI,EAAE,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IAC1C,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACpC,OAAO,EAAE,QAAQ,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;CAC/C,CAAC;AACF,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,mDAA4C,CAAC;AAElE,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,kBAAkB;IAClB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,gFAAgF;IAChF,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,wHAAwH;IACxH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,qBAAqB;IACrB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,QAAQ,EAAG,UAAmB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Generated from dist/custom-elements.json. Do not edit directly.
|
|
2
|
-
export type RefineElementTag = 'ore-accordion' | 'ore-accordion-item' | 'ore-alert' | 'ore-async' | 'ore-avatar' | 'ore-avatar-group' | 'ore-badge' | 'ore-box' | 'ore-breadcrumb' | 'ore-breadcrumb-item' | 'ore-button' | 'ore-button-group' | 'ore-calendar' | 'ore-card' | 'ore-carousel' | 'ore-chat-message' | 'ore-checkbox' | 'ore-checkbox-group' | 'ore-chip' | 'ore-code-window' | 'ore-command-palette' | 'ore-command-palette-item' | 'ore-copy-command' | 'ore-date-picker' | 'ore-dialog' | 'ore-drawer' | 'ore-file-input' | 'ore-grid' | 'ore-grid-item' | 'ore-icon' | 'ore-input' | 'ore-list' | 'ore-list-item' | 'ore-marquee' | 'ore-menu' | 'ore-menu-item' | 'ore-menu-separator' | 'ore-message-composer' | 'ore-navbar' | 'ore-navbar-item' | 'ore-navigation-menu' | 'ore-navigation-menu-item' | 'ore-navigation-menu-panel' | 'ore-number-input' | 'ore-otp-input' | 'ore-pagination' | 'ore-password-strength' | 'ore-popover' | 'ore-progress' | 'ore-radio' | 'ore-radio-group' | 'ore-rating' | 'ore-select' | 'ore-separator' | 'ore-sidebar' | 'ore-sidebar-group' | 'ore-sidebar-item' | 'ore-skeleton' | 'ore-slider' | 'ore-step' | 'ore-stepper' | 'ore-switch' | 'ore-tab-item' | 'ore-tab-panel' | 'ore-table' | 'ore-tabs' | 'ore-td' | 'ore-text' | 'ore-textarea' | 'ore-th' | 'ore-time-picker' | 'ore-toast' | 'ore-tooltip' | 'ore-tr' | 'ore-typing-indicator';
|
|
2
|
+
export type RefineElementTag = 'ore-accordion' | 'ore-accordion-item' | 'ore-alert' | 'ore-async' | 'ore-avatar' | 'ore-avatar-group' | 'ore-badge' | 'ore-box' | 'ore-breadcrumb' | 'ore-breadcrumb-item' | 'ore-button' | 'ore-button-group' | 'ore-calendar' | 'ore-card' | 'ore-carousel' | 'ore-chat-message' | 'ore-checkbox' | 'ore-checkbox-group' | 'ore-chip' | 'ore-code-window' | 'ore-command-palette' | 'ore-command-palette-item' | 'ore-copy-command' | 'ore-date-picker' | 'ore-dialog' | 'ore-drawer' | 'ore-file-input' | 'ore-grid' | 'ore-grid-item' | 'ore-icon' | 'ore-input' | 'ore-list' | 'ore-list-item' | 'ore-marquee' | 'ore-menu' | 'ore-menu-item' | 'ore-menu-separator' | 'ore-message-composer' | 'ore-navbar' | 'ore-navbar-item' | 'ore-navigation-menu' | 'ore-navigation-menu-item' | 'ore-navigation-menu-panel' | 'ore-number-input' | 'ore-otp-input' | 'ore-pagination' | 'ore-password-strength' | 'ore-popover' | 'ore-progress' | 'ore-radio' | 'ore-radio-group' | 'ore-rating' | 'ore-select' | 'ore-separator' | 'ore-sidebar' | 'ore-sidebar-group' | 'ore-sidebar-item' | 'ore-skeleton' | 'ore-slider' | 'ore-stats' | 'ore-step' | 'ore-stepper' | 'ore-switch' | 'ore-tab-item' | 'ore-tab-panel' | 'ore-table' | 'ore-tabs' | 'ore-td' | 'ore-text' | 'ore-textarea' | 'ore-th' | 'ore-time-picker' | 'ore-toast' | 'ore-tooltip' | 'ore-tr' | 'ore-typing-indicator';
|
|
3
3
|
|
|
4
4
|
export interface RefineElementMap {
|
|
5
5
|
'ore-accordion': HTMLElement;
|
|
@@ -61,6 +61,7 @@ export interface RefineElementMap {
|
|
|
61
61
|
'ore-sidebar-item': HTMLElement;
|
|
62
62
|
'ore-skeleton': HTMLElement;
|
|
63
63
|
'ore-slider': HTMLElement;
|
|
64
|
+
'ore-stats': HTMLElement;
|
|
64
65
|
'ore-step': HTMLElement;
|
|
65
66
|
'ore-stepper': HTMLElement;
|
|
66
67
|
'ore-switch': HTMLElement;
|
package/dist/icon.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./_virtual/_rolldown/runtime.cjs");require("./_dev.cjs");const t=require("./content/icon/icon.css.cjs");let n=require("@vielzeug/ore"),r=require("@vielzeug/ripple"),i=require("lucide");i=e.__toESM(i,1);var a=16,o=2,s=24,c=`http://www.w3.org/2000/svg`,l=new Set([`circle`,`clipPath`,`defs`,`ellipse`,`g`,`line`,`linearGradient`,`mask`,`path`,`polygon`,`polyline`,`radialGradient`,`rect`,`stop`,`symbol`,`use`]),u=/^[a-zA-Z][a-zA-Z0-9:_-]*$/,d=/^(on|xlink:|xml:|href$)/i,f=new Map(Object.entries(i.icons));function p(e){for(let[t,n]of Object.entries(e))f.set(t,n)}var m=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``),h=e=>{if(e==null||e===``)return a;let t=Number(e);return Number.isFinite(t)&&t>0&&/^\d+(\.\d+)?$/.test(e.trim())?t:e},g=e=>f.get(e)??f.get(m(e)),_=(e,t)=>{if(!l.has(e))return null;let n=document.createElementNS(c,e);for(let[e,r]of Object.entries(t))r!==void 0&&
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./_virtual/_rolldown/runtime.cjs");require("./_dev.cjs");const t=require("./content/icon/icon.css.cjs");let n=require("@vielzeug/ore"),r=require("@vielzeug/ripple"),i=require("lucide");i=e.__toESM(i,1);var a=16,o=2,s=24,c=`http://www.w3.org/2000/svg`,l=new Set([`circle`,`clipPath`,`defs`,`ellipse`,`g`,`line`,`linearGradient`,`mask`,`path`,`polygon`,`polyline`,`radialGradient`,`rect`,`stop`,`symbol`,`use`]),u=/^[a-zA-Z][a-zA-Z0-9:_-]*$/,d=/^(on|xlink:|xml:|href$)/i,f=new Map(Object.entries(i.icons));function p(e){for(let[t,n]of Object.entries(e))f.set(t,n)}var m=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``),h=e=>{if(e==null||e===``)return a;let t=Number(e);return Number.isFinite(t)&&t>0&&/^\d+(\.\d+)?$/.test(e.trim())?t:e},g=e=>f.get(e)??f.get(m(e)),_=(e,t)=>{if(!l.has(e))return null;let n=document.createElementNS(c,e);for(let[e,r]of Object.entries(t))r!==void 0&&u.test(e)&&!d.test(e)&&n.setAttribute(e,String(r));return n},v=`ore-icon`;(0,n.define)(v,{props:{absoluteStrokeWidth:n.prop.bool(),label:n.prop.string(),name:n.prop.string(),size:{default:a,parse:h,reflect:!1},solid:n.prop.bool(),strokeWidth:n.prop.number(o)},setup(e){(0,n.bind)({attr:{"aria-hidden":()=>(e.label.value??``).trim()?null:`true`,"aria-label":()=>(e.label.value??``).trim()||null,role:()=>(e.label.value??``).trim()?`img`:null},style:{"--_size-px":()=>{let t=e.size.value;return typeof t==`number`?`${t}px`:String(t)}}});let t=(0,n.ref)(),i=(0,r.computed)(()=>{let t=(e.name.value??``).trim();if(!t)return;let n=g(t);return n||`${t.slice(0,64)}`,n});return(0,n.watchEffect)(()=>{let n=t.value,r=i.value;if(!n||!r)return;let a=e.size.value,o=typeof a==`number`?a:s,c=e.absoluteStrokeWidth.value&&!e.solid.value?e.strokeWidth.value*(s/o):e.strokeWidth.value;n.setAttribute(`fill`,e.solid.value?`currentColor`:`none`),n.setAttribute(`stroke`,e.solid.value?`none`:`currentColor`),n.setAttribute(`stroke-linecap`,`round`),n.setAttribute(`stroke-linejoin`,`round`),n.setAttribute(`stroke-width`,String(e.solid.value?0:c)),n.setAttribute(`viewBox`,`0 0 24 24`);let l=r.map(([e,t])=>_(e,t)).filter(e=>!!e);n.replaceChildren(...l)}),n.html`
|
|
2
2
|
${(0,n.when)(()=>!!i.value,()=>n.html`
|
|
3
3
|
<svg ref="${t}" part="svg" style="width:100%;height:100%"></svg>
|
|
4
4
|
`)}
|
package/dist/icon.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.cjs","names":[],"sources":["../src/content/icon/icon.ts"],"sourcesContent":["import { bind, define, html, prop, ref, watchEffect, when } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport * as lucideModule from 'lucide';\n\nimport { warn } from '../../_dev';\nimport styles from './icon.css?inline';\n\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst LUCIDE_VIEWBOX_SIZE = 24;\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Allowlisted SVG shape/structure element names. Only these tags are permitted\n * when building the SVG DOM from an IconNode, preventing arbitrary element\n * injection (e.g. <script>, event-handler-bearing elements).\n */\nconst ALLOWED_SVG_TAGS = new Set([\n 'circle',\n 'clipPath',\n 'defs',\n 'ellipse',\n 'g',\n 'line',\n 'linearGradient',\n 'mask',\n 'path',\n 'polygon',\n 'polyline',\n 'radialGradient',\n 'rect',\n 'stop',\n 'symbol',\n 'use',\n]);\n\n/**\n * Allowlisted SVG presentation / structural attribute names.\n * Event handler attributes (on*) and \"xlink:href\" are excluded.\n */\nconst ATTR_KEY_RE = /^[a-zA-Z][a-zA-Z0-9:_-]*$/;\nconst BLOCKED_ATTR_RE = /^(on|xlink:|xml:|href$)/i;\n\n// Sync registry seeded from lucide at module load; extend at any time via registerIcons()\nconst registry = new Map<string, IconNode>(\n Object.entries((lucideModule as unknown as { icons: Record<string, IconNode> }).icons),\n);\n\n/**\n * Register additional icons (or override existing ones) by name.\n * Keys may be kebab-case or PascalCase — both are accepted by `ore-icon`.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n for (const [name, node] of Object.entries(icons)) {\n registry.set(name, node);\n }\n}\n\nconst toPascalCase = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n\nconst parseSize = (value: string | null): number | string => {\n if (value == null || value === '') return DEFAULT_SIZE;\n\n const n = Number(value);\n\n return Number.isFinite(n) && n > 0 && /^\\d+(\\.\\d+)?$/.test(value.trim()) ? n : value;\n};\n\nconst resolveIcon = (name: string): IconNode | undefined => registry.get(name) ?? registry.get(toPascalCase(name));\n\n/**\n * Builds an allowlisted SVG child element via `createElementNS` — real DOM construction, not\n * HTML-string parsing, so this never touches Ore's `unsafeHtml()` directive (and its \"unsanitized\n * HTML\" dev warning) at all. `iconNode` entries come from the bundled Lucide icon set or\n * `registerIcons()` (a developer/build-time API, never runtime user input), but the tag/attr\n * allowlist stays as defense in depth regardless of where the data originated.\n */\nconst createSvgChild = (tag: string, attrs: Record<string, string | number | undefined>): SVGElement | null => {\n if (!ALLOWED_SVG_TAGS.has(tag)) return null;\n\n const el = document.createElementNS(SVG_NS, tag);\n\n for (const [key, value] of Object.entries(attrs)) {\n if (value === undefined) continue;\n\n if (!ATTR_KEY_RE.test(key) || BLOCKED_ATTR_RE.test(key)) continue;\n\n el.setAttribute(key, String(value));\n }\n\n return el;\n};\n\n/** Icon component properties */\nexport type OreIconProps = {\n /** Keep stroke width visually consistent when icon size changes */\n absoluteStrokeWidth?: boolean;\n /** Accessible text label. Decorative icons should omit this. */\n label?: string;\n /** Lucide icon name, e.g. `search` or `chevron-right` */\n name?: string;\n /** Icon width/height in px by default. Accepts CSS lengths. */\n size?: number | string;\n /** Render as a filled/solid shape instead of a stroked outline */\n solid?: boolean;\n /** SVG stroke width */\n strokeWidth?: number;\n};\n\n/**\n * Icon wrapper for consistent Lucide rendering across Block.\n *\n * @element ore-icon\n *\n * @attr {string} name - Lucide icon name, e.g. `search` or `chevron-right`\n * @attr {number|string} size - Width/height (default: 16)\n * @attr {number} stroke-width - SVG stroke width (default: 2)\n * @attr {boolean} absolute-stroke-width - Keep stroke width visually stable across icon sizes\n * @attr {boolean} solid - Render as filled shape instead of stroked outline\n * @attr {string} label - Accessible label; when omitted the icon is decorative\n *\n * @csspart svg - Internal SVG element\n *\n * @example\n * ```html\n * <ore-icon name=\"search\"></ore-icon>\n * <ore-icon name=\"chevron-right\" size=\"18\"></ore-icon>\n * <ore-icon name=\"trash-2\" label=\"Delete\"></ore-icon>\n * <ore-icon name=\"star\" solid></ore-icon>\n * ```\n */\nexport const ICON_TAG = 'ore-icon' as const;\ndefine<OreIconProps>(ICON_TAG, {\n props: {\n absoluteStrokeWidth: prop.bool(),\n label: prop.string(),\n name: prop.string(),\n size: { default: DEFAULT_SIZE as number | string, parse: parseSize, reflect: false },\n solid: prop.bool(),\n strokeWidth: prop.number(DEFAULT_STROKE_WIDTH),\n },\n setup(props) {\n bind({\n attr: {\n 'aria-hidden': () => ((props.label.value ?? '').trim() ? null : 'true'),\n 'aria-label': () => (props.label.value ?? '').trim() || null,\n role: () => ((props.label.value ?? '').trim() ? 'img' : null),\n },\n style: {\n '--_size-px': () => {\n const s = props.size.value;\n\n return typeof s === 'number' ? `${s}px` : String(s);\n },\n },\n });\n\n const svgRef = ref<SVGSVGElement>();\n\n // Memoized so an unknown icon name only warns once per change, not once per reactive read.\n const iconNode = computed(() => {\n const name = (props.name.value ?? '').trim();\n\n if (!name) return undefined;\n\n const node = resolveIcon(name);\n\n if (!node) warn(`ore-icon: icon not found: \"${name.slice(0, 64)}\"`);\n\n return node;\n });\n\n // Real DOM construction (createElementNS), not the unsafeHtml() directive — see createSvgChild's\n // doc comment. Rebuilds the <svg>'s attributes and children whenever the icon name, size,\n // or presentation props change, or when `svgRef` first attaches (a fresh element mounts\n // every time `when()`'s branch below flips truthy).\n watchEffect(() => {\n const svg = svgRef.value;\n const node = iconNode.value;\n\n if (!svg || !node) return;\n\n const size = props.size.value;\n const numericSize = typeof size === 'number' ? size : LUCIDE_VIEWBOX_SIZE;\n const strokeWidth =\n props.absoluteStrokeWidth.value && !props.solid.value\n ? props.strokeWidth.value! * (LUCIDE_VIEWBOX_SIZE / numericSize)\n : props.strokeWidth.value!;\n\n svg.setAttribute('fill', props.solid.value ? 'currentColor' : 'none');\n svg.setAttribute('stroke', props.solid.value ? 'none' : 'currentColor');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n svg.setAttribute('stroke-width', String(props.solid.value ? 0 : strokeWidth));\n svg.setAttribute('viewBox', '0 0 24 24');\n\n const children = node.map(([tag, attrs]) => createSvgChild(tag, attrs)).filter((el): el is SVGElement => !!el);\n\n svg.replaceChildren(...children);\n });\n\n return html`\n ${when(\n () => !!iconNode.value,\n () => html`\n <svg ref=\"${svgRef}\" part=\"svg\" style=\"width:100%;height:100%\"></svg>\n `,\n )}\n `;\n },\n styles: [styles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"icon.cjs","names":[],"sources":["../src/content/icon/icon.ts"],"sourcesContent":["import { bind, define, html, prop, ref, watchEffect, when } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport * as lucideModule from 'lucide';\n\nimport { warn } from '../../_dev';\nimport styles from './icon.css?inline';\n\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst LUCIDE_VIEWBOX_SIZE = 24;\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Allowlisted SVG shape/structure element names. Only these tags are permitted\n * when building the SVG DOM from an IconNode, preventing arbitrary element\n * injection (e.g. <script>, event-handler-bearing elements).\n */\nconst ALLOWED_SVG_TAGS = new Set([\n 'circle',\n 'clipPath',\n 'defs',\n 'ellipse',\n 'g',\n 'line',\n 'linearGradient',\n 'mask',\n 'path',\n 'polygon',\n 'polyline',\n 'radialGradient',\n 'rect',\n 'stop',\n 'symbol',\n 'use',\n]);\n\n/**\n * Allowlisted SVG presentation / structural attribute names.\n * Event handler attributes (on*) and \"xlink:href\" are excluded.\n */\nconst ATTR_KEY_RE = /^[a-zA-Z][a-zA-Z0-9:_-]*$/;\nconst BLOCKED_ATTR_RE = /^(on|xlink:|xml:|href$)/i;\n\n// Sync registry seeded from lucide at module load; extend at any time via registerIcons()\nconst registry = new Map<string, IconNode>(\n Object.entries((lucideModule as unknown as { icons: Record<string, IconNode> }).icons),\n);\n\n/**\n * Register additional icons (or override existing ones) by name.\n * Keys may be kebab-case or PascalCase — both are accepted by `ore-icon`.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n for (const [name, node] of Object.entries(icons)) {\n registry.set(name, node);\n }\n}\n\nconst toPascalCase = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n\nconst parseSize = (value: string | null): number | string => {\n if (value == null || value === '') return DEFAULT_SIZE;\n\n const n = Number(value);\n\n return Number.isFinite(n) && n > 0 && /^\\d+(\\.\\d+)?$/.test(value.trim()) ? n : value;\n};\n\nconst resolveIcon = (name: string): IconNode | undefined => registry.get(name) ?? registry.get(toPascalCase(name));\n\n/**\n * Builds an allowlisted SVG child element via `createElementNS` — real DOM construction, not\n * HTML-string parsing, so this never touches Ore's `unsafeHtml()` directive (and its \"unsanitized\n * HTML\" dev warning) at all. `iconNode` entries come from the bundled Lucide icon set or\n * `registerIcons()` (a developer/build-time API, never runtime user input), but the tag/attr\n * allowlist stays as defense in depth regardless of where the data originated.\n */\nconst createSvgChild = (tag: string, attrs: Record<string, string | number | undefined>): SVGElement | null => {\n if (!ALLOWED_SVG_TAGS.has(tag)) return null;\n\n const el = document.createElementNS(SVG_NS, tag);\n\n for (const [key, value] of Object.entries(attrs)) {\n if (value === undefined) continue;\n\n if (!ATTR_KEY_RE.test(key) || BLOCKED_ATTR_RE.test(key)) continue;\n\n el.setAttribute(key, String(value));\n }\n\n return el;\n};\n\n/** Icon component properties */\nexport type OreIconProps = {\n /** Keep stroke width visually consistent when icon size changes */\n absoluteStrokeWidth?: boolean;\n /** Accessible text label. Decorative icons should omit this. */\n label?: string;\n /** Lucide icon name, e.g. `search` or `chevron-right` */\n name?: string;\n /** Icon width/height in px by default. Accepts CSS lengths. */\n size?: number | string;\n /** Render as a filled/solid shape instead of a stroked outline */\n solid?: boolean;\n /** SVG stroke width */\n strokeWidth?: number;\n};\n\n/**\n * Icon wrapper for consistent Lucide rendering across Block.\n *\n * @element ore-icon\n *\n * @attr {string} name - Lucide icon name, e.g. `search` or `chevron-right`\n * @attr {number|string} size - Width/height (default: 16)\n * @attr {number} stroke-width - SVG stroke width (default: 2)\n * @attr {boolean} absolute-stroke-width - Keep stroke width visually stable across icon sizes\n * @attr {boolean} solid - Render as filled shape instead of stroked outline\n * @attr {string} label - Accessible label; when omitted the icon is decorative\n *\n * @csspart svg - Internal SVG element\n *\n * @example\n * ```html\n * <ore-icon name=\"search\"></ore-icon>\n * <ore-icon name=\"chevron-right\" size=\"18\"></ore-icon>\n * <ore-icon name=\"trash-2\" label=\"Delete\"></ore-icon>\n * <ore-icon name=\"star\" solid></ore-icon>\n * ```\n */\nexport const ICON_TAG = 'ore-icon' as const;\ndefine<OreIconProps>(ICON_TAG, {\n props: {\n absoluteStrokeWidth: prop.bool(),\n label: prop.string(),\n name: prop.string(),\n size: { default: DEFAULT_SIZE as number | string, parse: parseSize, reflect: false },\n solid: prop.bool(),\n strokeWidth: prop.number(DEFAULT_STROKE_WIDTH),\n },\n setup(props) {\n bind({\n attr: {\n 'aria-hidden': () => ((props.label.value ?? '').trim() ? null : 'true'),\n 'aria-label': () => (props.label.value ?? '').trim() || null,\n role: () => ((props.label.value ?? '').trim() ? 'img' : null),\n },\n style: {\n '--_size-px': () => {\n const s = props.size.value;\n\n return typeof s === 'number' ? `${s}px` : String(s);\n },\n },\n });\n\n const svgRef = ref<SVGSVGElement>();\n\n // Memoized so an unknown icon name only warns once per change, not once per reactive read.\n const iconNode = computed(() => {\n const name = (props.name.value ?? '').trim();\n\n if (!name) return undefined;\n\n const node = resolveIcon(name);\n\n if (!node) warn(`ore-icon: icon not found: \"${name.slice(0, 64)}\"`);\n\n return node;\n });\n\n // Real DOM construction (createElementNS), not the unsafeHtml() directive — see createSvgChild's\n // doc comment. Rebuilds the <svg>'s attributes and children whenever the icon name, size,\n // or presentation props change, or when `svgRef` first attaches (a fresh element mounts\n // every time `when()`'s branch below flips truthy).\n watchEffect(() => {\n const svg = svgRef.value;\n const node = iconNode.value;\n\n if (!svg || !node) return;\n\n const size = props.size.value;\n const numericSize = typeof size === 'number' ? size : LUCIDE_VIEWBOX_SIZE;\n const strokeWidth =\n props.absoluteStrokeWidth.value && !props.solid.value\n ? props.strokeWidth.value! * (LUCIDE_VIEWBOX_SIZE / numericSize)\n : props.strokeWidth.value!;\n\n svg.setAttribute('fill', props.solid.value ? 'currentColor' : 'none');\n svg.setAttribute('stroke', props.solid.value ? 'none' : 'currentColor');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n svg.setAttribute('stroke-width', String(props.solid.value ? 0 : strokeWidth));\n svg.setAttribute('viewBox', '0 0 24 24');\n\n const children = node.map(([tag, attrs]) => createSvgChild(tag, attrs)).filter((el): el is SVGElement => !!el);\n\n svg.replaceChildren(...children);\n });\n\n return html`\n ${when(\n () => !!iconNode.value,\n () => html`\n <svg ref=\"${svgRef}\" part=\"svg\" style=\"width:100%;height:100%\"></svg>\n `,\n )}\n `;\n },\n styles: [styles],\n});\n"],"mappings":"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"}
|
package/dist/icon.js
CHANGED
|
@@ -32,7 +32,7 @@ var y = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").split(/[^a-zA-Z0-9]+/).f
|
|
|
32
32
|
}, x = (e) => _.get(e) ?? _.get(y(e)), S = (e, t) => {
|
|
33
33
|
if (!m.has(e)) return null;
|
|
34
34
|
let n = document.createElementNS(p, e);
|
|
35
|
-
for (let [e, r] of Object.entries(t)) r !== void 0 &&
|
|
35
|
+
for (let [e, r] of Object.entries(t)) r !== void 0 && h.test(e) && !g.test(e) && n.setAttribute(e, String(r));
|
|
36
36
|
return n;
|
|
37
37
|
}, C = "ore-icon";
|
|
38
38
|
n(C, {
|
package/dist/icon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.js","names":[],"sources":["../src/content/icon/icon.ts"],"sourcesContent":["import { bind, define, html, prop, ref, watchEffect, when } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport * as lucideModule from 'lucide';\n\nimport { warn } from '../../_dev';\nimport styles from './icon.css?inline';\n\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst LUCIDE_VIEWBOX_SIZE = 24;\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Allowlisted SVG shape/structure element names. Only these tags are permitted\n * when building the SVG DOM from an IconNode, preventing arbitrary element\n * injection (e.g. <script>, event-handler-bearing elements).\n */\nconst ALLOWED_SVG_TAGS = new Set([\n 'circle',\n 'clipPath',\n 'defs',\n 'ellipse',\n 'g',\n 'line',\n 'linearGradient',\n 'mask',\n 'path',\n 'polygon',\n 'polyline',\n 'radialGradient',\n 'rect',\n 'stop',\n 'symbol',\n 'use',\n]);\n\n/**\n * Allowlisted SVG presentation / structural attribute names.\n * Event handler attributes (on*) and \"xlink:href\" are excluded.\n */\nconst ATTR_KEY_RE = /^[a-zA-Z][a-zA-Z0-9:_-]*$/;\nconst BLOCKED_ATTR_RE = /^(on|xlink:|xml:|href$)/i;\n\n// Sync registry seeded from lucide at module load; extend at any time via registerIcons()\nconst registry = new Map<string, IconNode>(\n Object.entries((lucideModule as unknown as { icons: Record<string, IconNode> }).icons),\n);\n\n/**\n * Register additional icons (or override existing ones) by name.\n * Keys may be kebab-case or PascalCase — both are accepted by `ore-icon`.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n for (const [name, node] of Object.entries(icons)) {\n registry.set(name, node);\n }\n}\n\nconst toPascalCase = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n\nconst parseSize = (value: string | null): number | string => {\n if (value == null || value === '') return DEFAULT_SIZE;\n\n const n = Number(value);\n\n return Number.isFinite(n) && n > 0 && /^\\d+(\\.\\d+)?$/.test(value.trim()) ? n : value;\n};\n\nconst resolveIcon = (name: string): IconNode | undefined => registry.get(name) ?? registry.get(toPascalCase(name));\n\n/**\n * Builds an allowlisted SVG child element via `createElementNS` — real DOM construction, not\n * HTML-string parsing, so this never touches Ore's `unsafeHtml()` directive (and its \"unsanitized\n * HTML\" dev warning) at all. `iconNode` entries come from the bundled Lucide icon set or\n * `registerIcons()` (a developer/build-time API, never runtime user input), but the tag/attr\n * allowlist stays as defense in depth regardless of where the data originated.\n */\nconst createSvgChild = (tag: string, attrs: Record<string, string | number | undefined>): SVGElement | null => {\n if (!ALLOWED_SVG_TAGS.has(tag)) return null;\n\n const el = document.createElementNS(SVG_NS, tag);\n\n for (const [key, value] of Object.entries(attrs)) {\n if (value === undefined) continue;\n\n if (!ATTR_KEY_RE.test(key) || BLOCKED_ATTR_RE.test(key)) continue;\n\n el.setAttribute(key, String(value));\n }\n\n return el;\n};\n\n/** Icon component properties */\nexport type OreIconProps = {\n /** Keep stroke width visually consistent when icon size changes */\n absoluteStrokeWidth?: boolean;\n /** Accessible text label. Decorative icons should omit this. */\n label?: string;\n /** Lucide icon name, e.g. `search` or `chevron-right` */\n name?: string;\n /** Icon width/height in px by default. Accepts CSS lengths. */\n size?: number | string;\n /** Render as a filled/solid shape instead of a stroked outline */\n solid?: boolean;\n /** SVG stroke width */\n strokeWidth?: number;\n};\n\n/**\n * Icon wrapper for consistent Lucide rendering across Block.\n *\n * @element ore-icon\n *\n * @attr {string} name - Lucide icon name, e.g. `search` or `chevron-right`\n * @attr {number|string} size - Width/height (default: 16)\n * @attr {number} stroke-width - SVG stroke width (default: 2)\n * @attr {boolean} absolute-stroke-width - Keep stroke width visually stable across icon sizes\n * @attr {boolean} solid - Render as filled shape instead of stroked outline\n * @attr {string} label - Accessible label; when omitted the icon is decorative\n *\n * @csspart svg - Internal SVG element\n *\n * @example\n * ```html\n * <ore-icon name=\"search\"></ore-icon>\n * <ore-icon name=\"chevron-right\" size=\"18\"></ore-icon>\n * <ore-icon name=\"trash-2\" label=\"Delete\"></ore-icon>\n * <ore-icon name=\"star\" solid></ore-icon>\n * ```\n */\nexport const ICON_TAG = 'ore-icon' as const;\ndefine<OreIconProps>(ICON_TAG, {\n props: {\n absoluteStrokeWidth: prop.bool(),\n label: prop.string(),\n name: prop.string(),\n size: { default: DEFAULT_SIZE as number | string, parse: parseSize, reflect: false },\n solid: prop.bool(),\n strokeWidth: prop.number(DEFAULT_STROKE_WIDTH),\n },\n setup(props) {\n bind({\n attr: {\n 'aria-hidden': () => ((props.label.value ?? '').trim() ? null : 'true'),\n 'aria-label': () => (props.label.value ?? '').trim() || null,\n role: () => ((props.label.value ?? '').trim() ? 'img' : null),\n },\n style: {\n '--_size-px': () => {\n const s = props.size.value;\n\n return typeof s === 'number' ? `${s}px` : String(s);\n },\n },\n });\n\n const svgRef = ref<SVGSVGElement>();\n\n // Memoized so an unknown icon name only warns once per change, not once per reactive read.\n const iconNode = computed(() => {\n const name = (props.name.value ?? '').trim();\n\n if (!name) return undefined;\n\n const node = resolveIcon(name);\n\n if (!node) warn(`ore-icon: icon not found: \"${name.slice(0, 64)}\"`);\n\n return node;\n });\n\n // Real DOM construction (createElementNS), not the unsafeHtml() directive — see createSvgChild's\n // doc comment. Rebuilds the <svg>'s attributes and children whenever the icon name, size,\n // or presentation props change, or when `svgRef` first attaches (a fresh element mounts\n // every time `when()`'s branch below flips truthy).\n watchEffect(() => {\n const svg = svgRef.value;\n const node = iconNode.value;\n\n if (!svg || !node) return;\n\n const size = props.size.value;\n const numericSize = typeof size === 'number' ? size : LUCIDE_VIEWBOX_SIZE;\n const strokeWidth =\n props.absoluteStrokeWidth.value && !props.solid.value\n ? props.strokeWidth.value! * (LUCIDE_VIEWBOX_SIZE / numericSize)\n : props.strokeWidth.value!;\n\n svg.setAttribute('fill', props.solid.value ? 'currentColor' : 'none');\n svg.setAttribute('stroke', props.solid.value ? 'none' : 'currentColor');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n svg.setAttribute('stroke-width', String(props.solid.value ? 0 : strokeWidth));\n svg.setAttribute('viewBox', '0 0 24 24');\n\n const children = node.map(([tag, attrs]) => createSvgChild(tag, attrs)).filter((el): el is SVGElement => !!el);\n\n svg.replaceChildren(...children);\n });\n\n return html`\n ${when(\n () => !!iconNode.value,\n () => html`\n <svg ref=\"${svgRef}\" part=\"svg\" style=\"width:100%;height:100%\"></svg>\n `,\n )}\n `;\n },\n styles: [styles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"icon.js","names":[],"sources":["../src/content/icon/icon.ts"],"sourcesContent":["import { bind, define, html, prop, ref, watchEffect, when } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport * as lucideModule from 'lucide';\n\nimport { warn } from '../../_dev';\nimport styles from './icon.css?inline';\n\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst LUCIDE_VIEWBOX_SIZE = 24;\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Allowlisted SVG shape/structure element names. Only these tags are permitted\n * when building the SVG DOM from an IconNode, preventing arbitrary element\n * injection (e.g. <script>, event-handler-bearing elements).\n */\nconst ALLOWED_SVG_TAGS = new Set([\n 'circle',\n 'clipPath',\n 'defs',\n 'ellipse',\n 'g',\n 'line',\n 'linearGradient',\n 'mask',\n 'path',\n 'polygon',\n 'polyline',\n 'radialGradient',\n 'rect',\n 'stop',\n 'symbol',\n 'use',\n]);\n\n/**\n * Allowlisted SVG presentation / structural attribute names.\n * Event handler attributes (on*) and \"xlink:href\" are excluded.\n */\nconst ATTR_KEY_RE = /^[a-zA-Z][a-zA-Z0-9:_-]*$/;\nconst BLOCKED_ATTR_RE = /^(on|xlink:|xml:|href$)/i;\n\n// Sync registry seeded from lucide at module load; extend at any time via registerIcons()\nconst registry = new Map<string, IconNode>(\n Object.entries((lucideModule as unknown as { icons: Record<string, IconNode> }).icons),\n);\n\n/**\n * Register additional icons (or override existing ones) by name.\n * Keys may be kebab-case or PascalCase — both are accepted by `ore-icon`.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n for (const [name, node] of Object.entries(icons)) {\n registry.set(name, node);\n }\n}\n\nconst toPascalCase = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n\nconst parseSize = (value: string | null): number | string => {\n if (value == null || value === '') return DEFAULT_SIZE;\n\n const n = Number(value);\n\n return Number.isFinite(n) && n > 0 && /^\\d+(\\.\\d+)?$/.test(value.trim()) ? n : value;\n};\n\nconst resolveIcon = (name: string): IconNode | undefined => registry.get(name) ?? registry.get(toPascalCase(name));\n\n/**\n * Builds an allowlisted SVG child element via `createElementNS` — real DOM construction, not\n * HTML-string parsing, so this never touches Ore's `unsafeHtml()` directive (and its \"unsanitized\n * HTML\" dev warning) at all. `iconNode` entries come from the bundled Lucide icon set or\n * `registerIcons()` (a developer/build-time API, never runtime user input), but the tag/attr\n * allowlist stays as defense in depth regardless of where the data originated.\n */\nconst createSvgChild = (tag: string, attrs: Record<string, string | number | undefined>): SVGElement | null => {\n if (!ALLOWED_SVG_TAGS.has(tag)) return null;\n\n const el = document.createElementNS(SVG_NS, tag);\n\n for (const [key, value] of Object.entries(attrs)) {\n if (value === undefined) continue;\n\n if (!ATTR_KEY_RE.test(key) || BLOCKED_ATTR_RE.test(key)) continue;\n\n el.setAttribute(key, String(value));\n }\n\n return el;\n};\n\n/** Icon component properties */\nexport type OreIconProps = {\n /** Keep stroke width visually consistent when icon size changes */\n absoluteStrokeWidth?: boolean;\n /** Accessible text label. Decorative icons should omit this. */\n label?: string;\n /** Lucide icon name, e.g. `search` or `chevron-right` */\n name?: string;\n /** Icon width/height in px by default. Accepts CSS lengths. */\n size?: number | string;\n /** Render as a filled/solid shape instead of a stroked outline */\n solid?: boolean;\n /** SVG stroke width */\n strokeWidth?: number;\n};\n\n/**\n * Icon wrapper for consistent Lucide rendering across Block.\n *\n * @element ore-icon\n *\n * @attr {string} name - Lucide icon name, e.g. `search` or `chevron-right`\n * @attr {number|string} size - Width/height (default: 16)\n * @attr {number} stroke-width - SVG stroke width (default: 2)\n * @attr {boolean} absolute-stroke-width - Keep stroke width visually stable across icon sizes\n * @attr {boolean} solid - Render as filled shape instead of stroked outline\n * @attr {string} label - Accessible label; when omitted the icon is decorative\n *\n * @csspart svg - Internal SVG element\n *\n * @example\n * ```html\n * <ore-icon name=\"search\"></ore-icon>\n * <ore-icon name=\"chevron-right\" size=\"18\"></ore-icon>\n * <ore-icon name=\"trash-2\" label=\"Delete\"></ore-icon>\n * <ore-icon name=\"star\" solid></ore-icon>\n * ```\n */\nexport const ICON_TAG = 'ore-icon' as const;\ndefine<OreIconProps>(ICON_TAG, {\n props: {\n absoluteStrokeWidth: prop.bool(),\n label: prop.string(),\n name: prop.string(),\n size: { default: DEFAULT_SIZE as number | string, parse: parseSize, reflect: false },\n solid: prop.bool(),\n strokeWidth: prop.number(DEFAULT_STROKE_WIDTH),\n },\n setup(props) {\n bind({\n attr: {\n 'aria-hidden': () => ((props.label.value ?? '').trim() ? null : 'true'),\n 'aria-label': () => (props.label.value ?? '').trim() || null,\n role: () => ((props.label.value ?? '').trim() ? 'img' : null),\n },\n style: {\n '--_size-px': () => {\n const s = props.size.value;\n\n return typeof s === 'number' ? `${s}px` : String(s);\n },\n },\n });\n\n const svgRef = ref<SVGSVGElement>();\n\n // Memoized so an unknown icon name only warns once per change, not once per reactive read.\n const iconNode = computed(() => {\n const name = (props.name.value ?? '').trim();\n\n if (!name) return undefined;\n\n const node = resolveIcon(name);\n\n if (!node) warn(`ore-icon: icon not found: \"${name.slice(0, 64)}\"`);\n\n return node;\n });\n\n // Real DOM construction (createElementNS), not the unsafeHtml() directive — see createSvgChild's\n // doc comment. Rebuilds the <svg>'s attributes and children whenever the icon name, size,\n // or presentation props change, or when `svgRef` first attaches (a fresh element mounts\n // every time `when()`'s branch below flips truthy).\n watchEffect(() => {\n const svg = svgRef.value;\n const node = iconNode.value;\n\n if (!svg || !node) return;\n\n const size = props.size.value;\n const numericSize = typeof size === 'number' ? size : LUCIDE_VIEWBOX_SIZE;\n const strokeWidth =\n props.absoluteStrokeWidth.value && !props.solid.value\n ? props.strokeWidth.value! * (LUCIDE_VIEWBOX_SIZE / numericSize)\n : props.strokeWidth.value!;\n\n svg.setAttribute('fill', props.solid.value ? 'currentColor' : 'none');\n svg.setAttribute('stroke', props.solid.value ? 'none' : 'currentColor');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n svg.setAttribute('stroke-width', String(props.solid.value ? 0 : strokeWidth));\n svg.setAttribute('viewBox', '0 0 24 24');\n\n const children = node.map(([tag, attrs]) => createSvgChild(tag, attrs)).filter((el): el is SVGElement => !!el);\n\n svg.replaceChildren(...children);\n });\n\n return html`\n ${when(\n () => !!iconNode.value,\n () => html`\n <svg ref=\"${svgRef}\" part=\"svg\" style=\"width:100%;height:100%\"></svg>\n `,\n )}\n `;\n },\n styles: [styles],\n});\n"],"mappings":";;;;;;AASA,IAAM,IAAe,IACf,IAAuB,GACvB,IAAsB,IACtB,IAAS,8BAOT,oBAAmB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,GAMK,IAAc,6BACd,IAAkB,4BAGlB,IAAW,IAAI,IACnB,OAAO,QAAS,EAAgE,KAAK,CACvF;AAMA,SAAgB,EAAc,GAAuC;CACnE,KAAK,IAAM,CAAC,GAAM,MAAS,OAAO,QAAQ,CAAK,GAC7C,EAAS,IAAI,GAAM,CAAI;AAE3B;AAEA,IAAM,KAAgB,MACpB,EACG,QAAQ,sBAAsB,OAAO,CAAC,CACtC,MAAM,eAAe,CAAC,CACtB,OAAO,OAAO,CAAC,CACf,KAAK,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAChE,KAAK,EAAE,GAEN,KAAa,MAA0C;CAC3D,IAAI,KAAS,QAAQ,MAAU,IAAI,OAAO;CAE1C,IAAM,IAAI,OAAO,CAAK;CAEtB,OAAO,OAAO,SAAS,CAAC,KAAK,IAAI,KAAK,gBAAgB,KAAK,EAAM,KAAK,CAAC,IAAI,IAAI;AACjF,GAEM,KAAe,MAAuC,EAAS,IAAI,CAAI,KAAK,EAAS,IAAI,EAAa,CAAI,CAAC,GAS3G,KAAkB,GAAa,MAA0E;CAC7G,IAAI,CAAC,EAAiB,IAAI,CAAG,GAAG,OAAO;CAEvC,IAAM,IAAK,SAAS,gBAAgB,GAAQ,CAAG;CAE/C,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAK,GACzC,MAAU,KAAA,KAET,EAAY,KAAK,CAAG,KAAK,GAAgB,KAAK,CAAG,KAEtD,EAAG,aAAa,GAAK,OAAO,CAAK,CAAC;CAGpC,OAAO;AACT,GAwCa,IAAW;AACxB,EAAqB,GAAU;CAC7B,OAAO;EACL,qBAAqB,EAAK,KAAK;EAC/B,OAAO,EAAK,OAAO;EACnB,MAAM,EAAK,OAAO;EAClB,MAAM;GAAE,SAAS;GAAiC,OAAO;GAAW,SAAS;EAAM;EACnF,OAAO,EAAK,KAAK;EACjB,aAAa,EAAK,OAAO,CAAoB;CAC/C;CACA,MAAM,GAAO;EACX,EAAK;GACH,MAAM;IACJ,sBAAuB,EAAM,MAAM,SAAS,GAAA,CAAI,KAAK,IAAI,OAAO;IAChE,qBAAqB,EAAM,MAAM,SAAS,GAAA,CAAI,KAAK,KAAK;IACxD,aAAc,EAAM,MAAM,SAAS,GAAA,CAAI,KAAK,IAAI,QAAQ;GAC1D;GACA,OAAO,EACL,oBAAoB;IAClB,IAAM,IAAI,EAAM,KAAK;IAErB,OAAO,OAAO,KAAM,WAAW,GAAG,EAAE,MAAM,OAAO,CAAC;GACpD,EACF;EACF,CAAC;EAED,IAAM,IAAS,EAAmB,GAG5B,IAAW,QAAe;GAC9B,IAAM,KAAQ,EAAM,KAAK,SAAS,GAAA,CAAI,KAAK;GAE3C,IAAI,CAAC,GAAM;GAEX,IAAM,IAAO,EAAY,CAAI;GAI7B,OAFK,KAAW,GAA8B,EAAK,MAAM,GAAG,EAAE,EAA9C,GAET;EACT,CAAC;EA+BD,OAzBA,QAAkB;GAChB,IAAM,IAAM,EAAO,OACb,IAAO,EAAS;GAEtB,IAAI,CAAC,KAAO,CAAC,GAAM;GAEnB,IAAM,IAAO,EAAM,KAAK,OAClB,IAAc,OAAO,KAAS,WAAW,IAAO,GAChD,IACJ,EAAM,oBAAoB,SAAS,CAAC,EAAM,MAAM,QAC5C,EAAM,YAAY,SAAU,IAAsB,KAClD,EAAM,YAAY;GAOxB,AALA,EAAI,aAAa,QAAQ,EAAM,MAAM,QAAQ,iBAAiB,MAAM,GACpE,EAAI,aAAa,UAAU,EAAM,MAAM,QAAQ,SAAS,cAAc,GACtE,EAAI,aAAa,kBAAkB,OAAO,GAC1C,EAAI,aAAa,mBAAmB,OAAO,GAC3C,EAAI,aAAa,gBAAgB,OAAO,EAAM,MAAM,QAAQ,IAAI,CAAW,CAAC,GAC5E,EAAI,aAAa,WAAW,WAAW;GAEvC,IAAM,IAAW,EAAK,KAAK,CAAC,GAAK,OAAW,EAAe,GAAK,CAAK,CAAC,CAAC,CAAC,QAAQ,MAAyB,CAAC,CAAC,CAAE;GAE7G,EAAI,gBAAgB,GAAG,CAAQ;EACjC,CAAC,GAEM,CAAI;QACP,QACM,CAAC,CAAC,EAAS,aACX,CAAI;sBACI,EAAO;SAEvB,EAAE;;CAEN;CACA,QAAQ,CAAC,CAAM;AACjB,CAAC"}
|
package/dist/input.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/field-variants.css.cjs"),n=require("./styles/mixins/shape.css.cjs"),r=require("./styles/mixins/states.css.cjs"),i=require("./styles/mixins/theme.css.cjs"),a=require("./core/ore.cjs"),o=require("./core/ref-callback.cjs"),s=require("./core/text-field.cjs"),c=require("./shared/prop-bundles.cjs"),l=require("./shared/size-presets.cjs"),u=require("./inputs/shared/field-binding.cjs"),d=require("./inputs/shared/templates.cjs"),f=require("./inputs/shared/native-field-event.cjs"),p=require("./inputs/input/input.css.cjs");let m=require("@vielzeug/ore"),h=require("@vielzeug/ripple");var g=[`text`,`email`,`password`,`search`,`url`,`tel`,`number`,`date`,`time`,`datetime-local`,`month`,`week`],_=`ore-input`;(0,m.define)(_,{formAssociated:!0,props:{...c.themableBundle,...c.sizableBundle,...c.disablableBundle,...c.roundableBundle,autocomplete:m.prop.string(),clearable:m.prop.bool(!1),error:m.prop.string(),fullwidth:m.prop.bool(!1),helper:m.prop.string(),inputmode:m.prop.string(),label:m.prop.string(),"label-placement":m.prop.oneOf([`inset`,`outside`],`inset`),loading:m.prop.bool(!1),maxlength:m.prop.json(void 0),minlength:m.prop.json(void 0),name:m.prop.string(),pattern:m.prop.string(),placeholder:m.prop.string(),readonly:m.prop.bool(!1),ref:m.prop.data(),required:m.prop.bool(!1),success:m.prop.bool(!1),type:m.prop.oneOf(g,`text`),value:m.prop.string(),variant:m.prop.string()},setup(e){let t=(0,m.getHost)(),n=(0,m.useSlots)(),r=(0,h.signal)(!1),i=(0,m.ref)(),c=(0,h.computed)(()=>!!e.label.value||n.has(`label`).value),l=(0,h.computed)(()=>e.disabled.value||e.loading.value),p=a.lifecycleSignal(m.onCleanup),g=s.createTextField({disabled:l,error:e.error,hasLabel:c,helper:e.helper,label:e.label,labelPlacement:e[`label-placement`],maxLength:e.maxlength,onChange:(e,n)=>{f.setFieldValue(t,n),f.dispatchNativeFieldEvent(t,`change`)},onInput:(e,n)=>{f.setFieldValue(t,n),f.dispatchNativeFieldEvent(t,`input`)},prefix:`input`,readonly:e.readonly,required:e.required,signal:p,value:e.value});f.defineFieldValue(t,()=>g.value.value,e=>{g.value.value=e}),g.attachFormField((0,m.useField)({disabled:g.disabled,onReset:g.reset,toFormValue:e=>e,validationMessage:g.validationMessage,validity:g.validity,value:g.value}));let{ariaDescribedBy:_,ariaErrorMessage:v,ariaInvalid:y,ariaLabelledBy:b,assistiveId:x,clear:S,counter:C,errorId:w,errorText:T,fieldId:E,helperText:D,labelId:O,labelVisible:k,value:A,wire:j}=g;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/field-variants.css.cjs"),n=require("./styles/mixins/shape.css.cjs"),r=require("./styles/mixins/states.css.cjs"),i=require("./styles/mixins/theme.css.cjs"),a=require("./core/ore.cjs"),o=require("./core/ref-callback.cjs"),s=require("./core/text-field.cjs"),c=require("./shared/prop-bundles.cjs"),l=require("./shared/size-presets.cjs"),u=require("./inputs/shared/field-binding.cjs"),d=require("./inputs/shared/templates.cjs"),f=require("./inputs/shared/native-field-event.cjs"),p=require("./inputs/input/input.css.cjs");let m=require("@vielzeug/ore"),h=require("@vielzeug/ripple");var g=[`text`,`email`,`password`,`search`,`url`,`tel`,`number`,`date`,`time`,`datetime-local`,`month`,`week`],_=`ore-input`;(0,m.define)(_,{formAssociated:!0,props:{...c.themableBundle,...c.sizableBundle,...c.disablableBundle,...c.roundableBundle,"aria-label":m.prop.string(),autocomplete:m.prop.string(),clearable:m.prop.bool(!1),error:m.prop.string(),fullwidth:m.prop.bool(!1),helper:m.prop.string(),inputmode:m.prop.string(),label:m.prop.string(),"label-placement":m.prop.oneOf([`inset`,`outside`],`inset`),loading:m.prop.bool(!1),maxlength:m.prop.json(void 0),minlength:m.prop.json(void 0),name:m.prop.string(),pattern:m.prop.string(),placeholder:m.prop.string(),readonly:m.prop.bool(!1),ref:m.prop.data(),required:m.prop.bool(!1),success:m.prop.bool(!1),type:m.prop.oneOf(g,`text`),value:m.prop.string(),variant:m.prop.string()},setup(e){let t=(0,m.getHost)(),n=(0,m.useSlots)(),r=(0,h.signal)(!1),i=(0,m.ref)(),c=(0,h.computed)(()=>!!e.label.value||n.has(`label`).value),l=(0,h.computed)(()=>e.disabled.value||e.loading.value),p=a.lifecycleSignal(m.onCleanup),g=s.createTextField({disabled:l,error:e.error,hasLabel:c,helper:e.helper,label:e.label,labelPlacement:e[`label-placement`],maxLength:e.maxlength,onChange:(e,n)=>{f.setFieldValue(t,n),f.dispatchNativeFieldEvent(t,`change`)},onInput:(e,n)=>{f.setFieldValue(t,n),f.dispatchNativeFieldEvent(t,`input`)},prefix:`input`,readonly:e.readonly,required:e.required,signal:p,value:e.value});f.defineFieldValue(t,()=>g.value.value,e=>{g.value.value=e}),g.attachFormField((0,m.useField)({disabled:g.disabled,onReset:g.reset,toFormValue:e=>e,validationMessage:g.validationMessage,validity:g.validity,value:g.value}));let{ariaDescribedBy:_,ariaErrorMessage:v,ariaInvalid:y,ariaLabelledBy:b,assistiveId:x,clear:S,counter:C,errorId:w,errorText:T,fieldId:E,helperText:D,labelId:O,labelVisible:k,value:A,wire:j}=g;(0,m.onElement)(i,t=>{j(t,p);let n=o.bindRefCallback(e.ref,t);return()=>{n()}});let M=e=>{S(e),i.value?.focus()},N=()=>e.type.value===`password`&&r.value?`text`:e.type.value??`text`;(0,m.bind)({attr:{error:u.errorAttr(T),"has-value":()=>A.value?!0:void 0,size:e.size,success:()=>e.success.value&&!T.value?!0:void 0,variant:e.variant}});let P=()=>!k.value;return m.html`
|
|
2
2
|
<div class="input-wrapper" part="wrapper">
|
|
3
|
-
<label class="label" for="${E}" id="${O}" part="label" ?hidden="${
|
|
3
|
+
<label class="label" for="${()=>P()?null:E}" id="${O}" part="label" ?hidden="${P}">
|
|
4
4
|
<slot name="label">${e.label}</slot>
|
|
5
5
|
</label>
|
|
6
6
|
<div class="field" part="field">
|
|
@@ -9,7 +9,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
9
9
|
<input
|
|
10
10
|
part="input"
|
|
11
11
|
id="${E}"
|
|
12
|
-
type="${
|
|
12
|
+
type="${N}"
|
|
13
13
|
name="${e.name}"
|
|
14
14
|
placeholder="${e.placeholder}"
|
|
15
15
|
autocomplete="${e.autocomplete}"
|
|
@@ -21,6 +21,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
21
21
|
?readonly="${e.readonly}"
|
|
22
22
|
?required="${e.required}"
|
|
23
23
|
value="${(0,m.live)(A)}"
|
|
24
|
+
aria-label="${e[`aria-label`]}"
|
|
24
25
|
aria-labelledby="${b}"
|
|
25
26
|
aria-describedby="${_}"
|
|
26
27
|
aria-errormessage="${v}"
|
|
@@ -50,7 +51,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
50
51
|
part="clear"
|
|
51
52
|
type="button"
|
|
52
53
|
tabindex="${()=>A.value?`0`:`-1`}"
|
|
53
|
-
@click="${
|
|
54
|
+
@click="${M}">
|
|
54
55
|
<ore-icon aria-hidden="true" name="x" size="12" stroke-width="2.5"></ore-icon>
|
|
55
56
|
</button>
|
|
56
57
|
</div>
|
package/dist/input.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.cjs","names":[],"sources":["../src/inputs/input/input.ts"],"sourcesContent":["import { bind, define, getHost, html, live, onCleanup, onElement, prop, ref, useField, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { bindRefCallback, createTextField, lifecycleSignal } from '../../core';\nimport type { TextFieldProps } from '../../shared';\nimport { disablableBundle, FIELD_SIZE_PRESET, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { InputType, VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport {\n coarsePointerMixin,\n colorThemeMixin,\n disabledLoadingMixin,\n fieldVariantMixin,\n forcedColorsFocusMixin,\n reducedMotionMixin,\n roundedVariantMixin,\n sizeVariantMixin,\n} from '../../styles';\nimport { errorAttr } from '../shared/field-binding';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderStatusIcon } from '../shared/templates';\nimport componentStyles from './input.css?inline';\n\n/** Input component properties */\n\nexport type OreInputEvents = {\n change: Event;\n input: InputEvent;\n};\n\nexport type OreInputProps = TextFieldProps<Exclude<VisualVariant, 'frost'>> & {\n /** Autocomplete hint */\n autocomplete?: string;\n /** Show a clear (×) button when the field has a value */\n clearable?: boolean;\n /** Virtual keyboard hint for mobile devices */\n inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';\n /**\n * Shows an inline spinner inside the field and forces the inner `<input>` into\n * `disabled` for the duration — use while an async validation/submission request\n * is in flight (e.g. checking username availability) to prevent double-submits.\n */\n loading?: boolean;\n /** Maximum character length — shows a counter below the input */\n maxlength?: number;\n /** Minimum character length */\n minlength?: number;\n /** HTML pattern attribute for client-side validation */\n pattern?: string;\n /**\n * JS-only callback fired with the inner `<input>` element when it mounts,\n * and with `null` when it unmounts. Intended for composed components that\n * need imperative access to the raw input element.\n * Set as a JS property: `bitInput.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLInputElement | null) => void) | null;\n /** HTML input type */\n type?: InputType;\n};\n\nconst VALID_INPUT_TYPES = [\n 'text',\n 'email',\n 'password',\n 'search',\n 'url',\n 'tel',\n 'number',\n 'date',\n 'time',\n 'datetime-local',\n 'month',\n 'week',\n] as const;\n\n/**\n * A customizable text input component with multiple variants, label placements, and form features.\n *\n * @element ore-input\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - Label placement: 'inset' | 'outside'\n * @attr {string} type - HTML input type: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search'\n * @attr {string} value - Current input value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {string} helper - Helper text displayed below the input (fallback when the `helper` slot is empty)\n * @attr {string} error - Error message — marks the field as invalid (fallback when the `error` slot is empty)\n * @attr {boolean} disabled - Disable input interaction\n * @attr {boolean} readonly - Make the input read-only\n * @attr {boolean} required - Mark the field as required\n * @attr {boolean} loading - Show an inline spinner and force the field disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Input size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Emitted when input value changes (on every keystroke).\n * @fires change - Emitted when input loses focus with changed value.\n *\n * @slot prefix - Content before the input (e.g., icons)\n * @slot suffix - Content after the input (e.g., clear button, validation icon)\n * @slot label - Replaces the label text — slotted content takes precedence over the `label` prop\n * @slot helper - Replaces the helper text — slotted content takes precedence over the `helper` prop\n * @slot error - Replaces the error text — slotted content takes precedence over the `error` prop\n *\n * @part wrapper - The input wrapper element\n * @part label - The label element (inset or outside)\n * @part field - The field container element\n * @part input-row - The input row container element\n * @part input - The input element\n * @part status-icon - The inline error/success icon shown inside the field\n * @part spinner - The inline loading spinner shown inside the field while `loading`\n * @part helper - The helper text element\n *\n * @cssprop --input-bg - Background color\n * @cssprop --input-color - Text color\n * @cssprop --input-border-color - Border color\n * @cssprop --input-placeholder-color - Placeholder text color\n * @cssprop --input-radius - Border radius\n * @cssprop --input-padding - Inner padding (block inline)\n * @cssprop --input-label-block-inset - Inset from the field block start for an inset label\n * @cssprop --input-label-inset - Inset from the field inline start for an inset label\n * @cssprop --input-gap - Gap between prefix/suffix icons and input text\n * @cssprop --input-font-size - Font size\n * @cssprop --input-height - Field height\n * @cssprop --input-hover-bg - Field background on hover (flat/ghost variants)\n * @cssprop --input-hover-border-color - Field border on hover (flat/bordered variants)\n * @cssprop --input-focus-bg - Field background when focused (flat variant)\n * @cssprop --input-focus-border-color - Field border when focused (flat/text variants)\n *\n * @example\n * ```html\n * <ore-input type=\"email\" label=\"Email\" placeholder=\"you@example.com\" />\n * <ore-input label=\"Name\" variant=\"bordered\" color=\"primary\" />\n * <ore-input label=\"Username\" error=\"That username is taken\" />\n * <ore-input label=\"Username\" success />\n * <ore-input label=\"Username\" loading />\n * ```\n */\nexport const INPUT_TAG = 'ore-input' as const;\ndefine<OreInputProps>(INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n autocomplete: prop.string(),\n clearable: prop.bool(false),\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n inputmode: prop.string<'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'>(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n loading: prop.bool(false),\n maxlength: prop.json(undefined as number | undefined),\n minlength: prop.json(undefined as number | undefined),\n name: prop.string(),\n pattern: prop.string(),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n required: prop.bool(false),\n success: prop.bool(false),\n type: prop.oneOf(VALID_INPUT_TYPES, 'text'),\n value: prop.string(),\n variant: prop.string<'flat' | 'text' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n\n const showPassword = signal(false);\n const inputRef = ref<HTMLInputElement>();\n\n const hasLabel = computed(() => !!props.label.value || slots.has('label').value);\n // `loading` behaves like a temporary `disabled` — forces the inner <input> out of\n // constraint validation and interaction for the duration, layered on top of any real\n // `loading` is layered on top of the consumer's explicit `disabled` prop.\n const isDisabled = computed(() => props.disabled.value || props.loading.value);\n\n const abortSignal = lifecycleSignal(onCleanup);\n const tf = createTextField({\n disabled: isDisabled,\n error: props.error,\n hasLabel,\n helper: props.helper,\n label: props.label,\n labelPlacement: props['label-placement'],\n maxLength: props.maxlength,\n onChange: (_event: Event, value: string) => {\n setFieldValue(el, value);\n dispatchNativeFieldEvent(el, 'change');\n },\n onInput: (_event: Event, value: string) => {\n setFieldValue(el, value);\n dispatchNativeFieldEvent(el, 'input');\n },\n prefix: 'input',\n readonly: props.readonly,\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n defineFieldValue(\n el,\n () => tf.value.value,\n (value) => {\n tf.value.value = value;\n },\n );\n\n tf.attachFormField(\n useField<string>({\n disabled: tf.disabled,\n onReset: tf.reset,\n toFormValue: (v) => v,\n validationMessage: tf.validationMessage,\n validity: tf.validity,\n value: tf.value,\n }),\n );\n\n const {\n ariaDescribedBy,\n ariaErrorMessage,\n ariaInvalid,\n ariaLabelledBy,\n assistiveId,\n clear: clearValue,\n counter,\n errorId,\n errorText,\n fieldId: inputId,\n helperText,\n labelId,\n labelVisible,\n value: fieldValue,\n wire,\n } = tf;\n\n onElement(inputRef, (el) => {\n wire(el, abortSignal);\n\n const unwireRef = bindRefCallback(props.ref, el);\n\n return () => {\n unwireRef();\n };\n });\n\n const clear = (event?: Event): void => {\n clearValue(event);\n inputRef.value?.focus();\n };\n\n const resolvedInputType = (): string =>\n props.type.value === 'password' && showPassword.value ? 'text' : (props.type.value ?? 'text');\n\n bind({\n attr: {\n error: errorAttr(errorText),\n 'has-value': () => (fieldValue.value ? true : undefined),\n size: props.size,\n // Reflects `success` only once `error` is confirmed empty — keeps the two host\n // attributes mutually exclusive even if a consumer sets both props at once.\n success: () => (props.success.value && !errorText.value ? true : undefined),\n variant: props.variant,\n },\n });\n\n const labelHidden = () => !labelVisible.value;\n const passwordToggleLabel = () => (showPassword.value ? 'Hide password' : 'Show password');\n const passwordTogglePressed = () => String(showPassword.value);\n const passwordToggleIcon = () =>\n showPassword.value\n ? html`\n <ore-icon name=\"eye-off\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n `\n : html`\n <ore-icon name=\"eye\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n `;\n const helperHidden = () => !!errorText.value || !helperText.value;\n const errorHidden = () => !errorText.value;\n const counterNearLimit = () => (counter?.value.counterNearLimit && !counter?.value.counterAtLimit ? '' : null);\n const counterAtLimit = () => (counter?.value.counterAtLimit ? '' : null);\n const counterHidden = () => !counter;\n const counterText = () => counter?.value.counterText ?? '';\n\n const clearTabIndex = () => (fieldValue.value ? '0' : '-1');\n const pwdToggleTabIndex = () => (props.type.value === 'password' ? '0' : '-1');\n\n const togglePassword = () => {\n showPassword.value = !showPassword.value;\n inputRef.value?.focus();\n };\n\n return html`\n <div class=\"input-wrapper\" part=\"wrapper\">\n <label class=\"label\" for=\"${inputId}\" id=\"${labelId}\" part=\"label\" ?hidden=\"${labelHidden}\">\n <slot name=\"label\">${props.label}</slot>\n </label>\n <div class=\"field\" part=\"field\">\n <div class=\"input-row\" part=\"input-row\">\n <slot name=\"prefix\"></slot>\n <input\n part=\"input\"\n id=\"${inputId}\"\n type=\"${resolvedInputType}\"\n name=\"${props.name}\"\n placeholder=\"${props.placeholder}\"\n autocomplete=\"${props.autocomplete}\"\n inputmode=\"${props.inputmode}\"\n maxlength=\"${props.maxlength}\"\n minlength=\"${props.minlength}\"\n pattern=\"${props.pattern}\"\n ?disabled=\"${isDisabled}\"\n ?readonly=\"${props.readonly}\"\n ?required=\"${props.required}\"\n value=\"${live(fieldValue)}\"\n aria-labelledby=\"${ariaLabelledBy}\"\n aria-describedby=\"${ariaDescribedBy}\"\n aria-errormessage=\"${ariaErrorMessage}\"\n aria-invalid=\"${ariaInvalid}\"\n aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"\n ref=\"${inputRef}\" />\n <slot name=\"suffix\"></slot>\n ${renderStatusIcon(errorText)}\n <span class=\"field-spinner\" part=\"spinner\" role=\"status\" aria-label=\"Loading\"></span>\n <button\n class=\"pwd-toggle-btn\"\n part=\"pwd-toggle\"\n type=\"button\"\n aria-label=\"${passwordToggleLabel}\"\n aria-pressed=\"${passwordTogglePressed}\"\n tabindex=\"${pwdToggleTabIndex}\"\n @click=\"${togglePassword}\">\n ${passwordToggleIcon}\n </button>\n <button\n aria-label=\"Clear\"\n class=\"clear-btn\"\n part=\"clear\"\n type=\"button\"\n tabindex=\"${clearTabIndex}\"\n @click=\"${clear}\">\n <ore-icon aria-hidden=\"true\" name=\"x\" size=\"12\" stroke-width=\"2.5\"></ore-icon>\n </button>\n </div>\n </div>\n <div class=\"helper-text\" aria-live=\"polite\" id=\"${assistiveId}\" part=\"helper\" ?hidden=\"${helperHidden}\">\n <slot name=\"helper\">${() => helperText.value}</slot>\n </div>\n <div class=\"helper-text\" id=\"${errorId}\" role=\"alert\" part=\"error\" ?hidden=\"${errorHidden}\">\n <slot name=\"error\">${() => errorText.value}</slot>\n </div>\n <div\n class=\"char-counter\"\n part=\"char-counter\"\n data-near-limit=\"${counterNearLimit}\"\n data-at-limit=\"${counterAtLimit}\"\n ?hidden=\"${counterHidden}\">\n ${counterText}\n </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n colorThemeMixin,\n coarsePointerMixin,\n reducedMotionMixin,\n roundedVariantMixin,\n disabledLoadingMixin,\n sizeVariantMixin(FIELD_SIZE_PRESET),\n forcedColorsFocusMixin('input'),\n componentStyles,\n // Must come after `componentStyles` — `@layer` precedence is fixed by which layer name is\n // *first* referenced across this whole array, and `componentStyles` is what establishes\n // `refine.base` (the unconditional `--_bg`/`--_border-color` defaults this mixin's\n // `refine.variants` rules need to win over). Placed earlier, `refine.variants` would end up\n // registered as the *lower*-priority layer, and every variant would silently render as the\n // base default — exactly the bug this ordering fixes.\n fieldVariantMixin({ container: '.field', text: 'input', tokenPrefix: 'input' }),\n ],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input.cjs","names":[],"sources":["../src/inputs/input/input.ts"],"sourcesContent":["import { bind, define, getHost, html, live, onCleanup, onElement, prop, ref, useField, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { bindRefCallback, createTextField, lifecycleSignal } from '../../core';\nimport type { TextFieldProps } from '../../shared';\nimport { disablableBundle, FIELD_SIZE_PRESET, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { InputType, VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport {\n coarsePointerMixin,\n colorThemeMixin,\n disabledLoadingMixin,\n fieldVariantMixin,\n forcedColorsFocusMixin,\n reducedMotionMixin,\n roundedVariantMixin,\n sizeVariantMixin,\n} from '../../styles';\nimport { errorAttr } from '../shared/field-binding';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderStatusIcon } from '../shared/templates';\nimport componentStyles from './input.css?inline';\n\n/** Input component properties */\n\nexport type OreInputEvents = {\n change: Event;\n input: InputEvent;\n};\n\nexport type OreInputProps = TextFieldProps<Exclude<VisualVariant, 'frost'>> & {\n /** Accessible name used when no visible label is rendered. */\n 'aria-label'?: string;\n /** Autocomplete hint */\n autocomplete?: string;\n /** Show a clear (×) button when the field has a value */\n clearable?: boolean;\n /** Virtual keyboard hint for mobile devices */\n inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';\n /**\n * Shows an inline spinner inside the field and forces the inner `<input>` into\n * `disabled` for the duration — use while an async validation/submission request\n * is in flight (e.g. checking username availability) to prevent double-submits.\n */\n loading?: boolean;\n /** Maximum character length — shows a counter below the input */\n maxlength?: number;\n /** Minimum character length */\n minlength?: number;\n /** HTML pattern attribute for client-side validation */\n pattern?: string;\n /**\n * JS-only callback fired with the inner `<input>` element when it mounts,\n * and with `null` when it unmounts. Intended for composed components that\n * need imperative access to the raw input element.\n * Set as a JS property: `bitInput.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLInputElement | null) => void) | null;\n /** HTML input type */\n type?: InputType;\n};\n\nconst VALID_INPUT_TYPES = [\n 'text',\n 'email',\n 'password',\n 'search',\n 'url',\n 'tel',\n 'number',\n 'date',\n 'time',\n 'datetime-local',\n 'month',\n 'week',\n] as const;\n\n/**\n * A customizable text input component with multiple variants, label placements, and form features.\n *\n * @element ore-input\n *\n * @attr {string} aria-label - Accessible name used when no visible label is rendered\n * @attr {string} label - Label text\n * @attr {string} label-placement - Label placement: 'inset' | 'outside'\n * @attr {string} type - HTML input type: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search'\n * @attr {string} value - Current input value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {string} helper - Helper text displayed below the input (fallback when the `helper` slot is empty)\n * @attr {string} error - Error message — marks the field as invalid (fallback when the `error` slot is empty)\n * @attr {boolean} disabled - Disable input interaction\n * @attr {boolean} readonly - Make the input read-only\n * @attr {boolean} required - Mark the field as required\n * @attr {boolean} loading - Show an inline spinner and force the field disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Input size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Emitted when input value changes (on every keystroke).\n * @fires change - Emitted when input loses focus with changed value.\n *\n * @slot prefix - Content before the input (e.g., icons)\n * @slot suffix - Content after the input (e.g., clear button, validation icon)\n * @slot label - Replaces the label text — slotted content takes precedence over the `label` prop\n * @slot helper - Replaces the helper text — slotted content takes precedence over the `helper` prop\n * @slot error - Replaces the error text — slotted content takes precedence over the `error` prop\n *\n * @part wrapper - The input wrapper element\n * @part label - The label element (inset or outside)\n * @part field - The field container element\n * @part input-row - The input row container element\n * @part input - The input element\n * @part status-icon - The inline error/success icon shown inside the field\n * @part spinner - The inline loading spinner shown inside the field while `loading`\n * @part helper - The helper text element\n *\n * @cssprop --input-bg - Background color\n * @cssprop --input-color - Text color\n * @cssprop --input-border-color - Border color\n * @cssprop --input-placeholder-color - Placeholder text color\n * @cssprop --input-radius - Border radius\n * @cssprop --input-padding - Inner padding (block inline)\n * @cssprop --input-label-block-inset - Inset from the field block start for an inset label\n * @cssprop --input-label-inset - Inset from the field inline start for an inset label\n * @cssprop --input-gap - Gap between prefix/suffix icons and input text\n * @cssprop --input-font-size - Font size\n * @cssprop --input-height - Field height\n * @cssprop --input-hover-bg - Field background on hover (flat/ghost variants)\n * @cssprop --input-hover-border-color - Field border on hover (flat/bordered variants)\n * @cssprop --input-focus-bg - Field background when focused (flat variant)\n * @cssprop --input-focus-border-color - Field border when focused (flat/text variants)\n *\n * @example\n * ```html\n * <ore-input type=\"email\" label=\"Email\" placeholder=\"you@example.com\" />\n * <ore-input label=\"Name\" variant=\"bordered\" color=\"primary\" />\n * <ore-input label=\"Username\" error=\"That username is taken\" />\n * <ore-input label=\"Username\" success />\n * <ore-input label=\"Username\" loading />\n * ```\n */\nexport const INPUT_TAG = 'ore-input' as const;\ndefine<OreInputProps>(INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n 'aria-label': prop.string(),\n autocomplete: prop.string(),\n clearable: prop.bool(false),\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n inputmode: prop.string<'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'>(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n loading: prop.bool(false),\n maxlength: prop.json(undefined as number | undefined),\n minlength: prop.json(undefined as number | undefined),\n name: prop.string(),\n pattern: prop.string(),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n required: prop.bool(false),\n success: prop.bool(false),\n type: prop.oneOf(VALID_INPUT_TYPES, 'text'),\n value: prop.string(),\n variant: prop.string<'flat' | 'text' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n\n const showPassword = signal(false);\n const inputRef = ref<HTMLInputElement>();\n\n const hasLabel = computed(() => !!props.label.value || slots.has('label').value);\n // `loading` behaves like a temporary `disabled` — forces the inner <input> out of\n // constraint validation and interaction for the duration, layered on top of any real\n // `loading` is layered on top of the consumer's explicit `disabled` prop.\n const isDisabled = computed(() => props.disabled.value || props.loading.value);\n\n const abortSignal = lifecycleSignal(onCleanup);\n const tf = createTextField({\n disabled: isDisabled,\n error: props.error,\n hasLabel,\n helper: props.helper,\n label: props.label,\n labelPlacement: props['label-placement'],\n maxLength: props.maxlength,\n onChange: (_event: Event, value: string) => {\n setFieldValue(el, value);\n dispatchNativeFieldEvent(el, 'change');\n },\n onInput: (_event: Event, value: string) => {\n setFieldValue(el, value);\n dispatchNativeFieldEvent(el, 'input');\n },\n prefix: 'input',\n readonly: props.readonly,\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n defineFieldValue(\n el,\n () => tf.value.value,\n (value) => {\n tf.value.value = value;\n },\n );\n\n tf.attachFormField(\n useField<string>({\n disabled: tf.disabled,\n onReset: tf.reset,\n toFormValue: (v) => v,\n validationMessage: tf.validationMessage,\n validity: tf.validity,\n value: tf.value,\n }),\n );\n\n const {\n ariaDescribedBy,\n ariaErrorMessage,\n ariaInvalid,\n ariaLabelledBy,\n assistiveId,\n clear: clearValue,\n counter,\n errorId,\n errorText,\n fieldId: inputId,\n helperText,\n labelId,\n labelVisible,\n value: fieldValue,\n wire,\n } = tf;\n\n onElement(inputRef, (el) => {\n wire(el, abortSignal);\n\n const unwireRef = bindRefCallback(props.ref, el);\n\n return () => {\n unwireRef();\n };\n });\n\n const clear = (event?: Event): void => {\n clearValue(event);\n inputRef.value?.focus();\n };\n\n const resolvedInputType = (): string =>\n props.type.value === 'password' && showPassword.value ? 'text' : (props.type.value ?? 'text');\n\n bind({\n attr: {\n error: errorAttr(errorText),\n 'has-value': () => (fieldValue.value ? true : undefined),\n size: props.size,\n // Reflects `success` only once `error` is confirmed empty — keeps the two host\n // attributes mutually exclusive even if a consumer sets both props at once.\n success: () => (props.success.value && !errorText.value ? true : undefined),\n variant: props.variant,\n },\n });\n\n const labelHidden = () => !labelVisible.value;\n const passwordToggleLabel = () => (showPassword.value ? 'Hide password' : 'Show password');\n const passwordTogglePressed = () => String(showPassword.value);\n const passwordToggleIcon = () =>\n showPassword.value\n ? html`\n <ore-icon name=\"eye-off\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n `\n : html`\n <ore-icon name=\"eye\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n `;\n const helperHidden = () => !!errorText.value || !helperText.value;\n const errorHidden = () => !errorText.value;\n const counterNearLimit = () => (counter?.value.counterNearLimit && !counter?.value.counterAtLimit ? '' : null);\n const counterAtLimit = () => (counter?.value.counterAtLimit ? '' : null);\n const counterHidden = () => !counter;\n const counterText = () => counter?.value.counterText ?? '';\n\n const clearTabIndex = () => (fieldValue.value ? '0' : '-1');\n const pwdToggleTabIndex = () => (props.type.value === 'password' ? '0' : '-1');\n\n const togglePassword = () => {\n showPassword.value = !showPassword.value;\n inputRef.value?.focus();\n };\n\n return html`\n <div class=\"input-wrapper\" part=\"wrapper\">\n <label class=\"label\" for=\"${() => (labelHidden() ? null : inputId)}\" id=\"${labelId}\" part=\"label\" ?hidden=\"${labelHidden}\">\n <slot name=\"label\">${props.label}</slot>\n </label>\n <div class=\"field\" part=\"field\">\n <div class=\"input-row\" part=\"input-row\">\n <slot name=\"prefix\"></slot>\n <input\n part=\"input\"\n id=\"${inputId}\"\n type=\"${resolvedInputType}\"\n name=\"${props.name}\"\n placeholder=\"${props.placeholder}\"\n autocomplete=\"${props.autocomplete}\"\n inputmode=\"${props.inputmode}\"\n maxlength=\"${props.maxlength}\"\n minlength=\"${props.minlength}\"\n pattern=\"${props.pattern}\"\n ?disabled=\"${isDisabled}\"\n ?readonly=\"${props.readonly}\"\n ?required=\"${props.required}\"\n value=\"${live(fieldValue)}\"\n aria-label=\"${props['aria-label']}\"\n aria-labelledby=\"${ariaLabelledBy}\"\n aria-describedby=\"${ariaDescribedBy}\"\n aria-errormessage=\"${ariaErrorMessage}\"\n aria-invalid=\"${ariaInvalid}\"\n aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"\n ref=\"${inputRef}\" />\n <slot name=\"suffix\"></slot>\n ${renderStatusIcon(errorText)}\n <span class=\"field-spinner\" part=\"spinner\" role=\"status\" aria-label=\"Loading\"></span>\n <button\n class=\"pwd-toggle-btn\"\n part=\"pwd-toggle\"\n type=\"button\"\n aria-label=\"${passwordToggleLabel}\"\n aria-pressed=\"${passwordTogglePressed}\"\n tabindex=\"${pwdToggleTabIndex}\"\n @click=\"${togglePassword}\">\n ${passwordToggleIcon}\n </button>\n <button\n aria-label=\"Clear\"\n class=\"clear-btn\"\n part=\"clear\"\n type=\"button\"\n tabindex=\"${clearTabIndex}\"\n @click=\"${clear}\">\n <ore-icon aria-hidden=\"true\" name=\"x\" size=\"12\" stroke-width=\"2.5\"></ore-icon>\n </button>\n </div>\n </div>\n <div class=\"helper-text\" aria-live=\"polite\" id=\"${assistiveId}\" part=\"helper\" ?hidden=\"${helperHidden}\">\n <slot name=\"helper\">${() => helperText.value}</slot>\n </div>\n <div class=\"helper-text\" id=\"${errorId}\" role=\"alert\" part=\"error\" ?hidden=\"${errorHidden}\">\n <slot name=\"error\">${() => errorText.value}</slot>\n </div>\n <div\n class=\"char-counter\"\n part=\"char-counter\"\n data-near-limit=\"${counterNearLimit}\"\n data-at-limit=\"${counterAtLimit}\"\n ?hidden=\"${counterHidden}\">\n ${counterText}\n </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n colorThemeMixin,\n coarsePointerMixin,\n reducedMotionMixin,\n roundedVariantMixin,\n disabledLoadingMixin,\n sizeVariantMixin(FIELD_SIZE_PRESET),\n forcedColorsFocusMixin('input'),\n componentStyles,\n // Must come after `componentStyles` — `@layer` precedence is fixed by which layer name is\n // *first* referenced across this whole array, and `componentStyles` is what establishes\n // `refine.base` (the unconditional `--_bg`/`--_border-color` defaults this mixin's\n // `refine.variants` rules need to win over). Placed earlier, `refine.variants` would end up\n // registered as the *lower*-priority layer, and every variant would silently render as the\n // base default — exactly the bug this ordering fixes.\n fieldVariantMixin({ container: '.field', text: 'input', tokenPrefix: 'input' }),\n ],\n});\n"],"mappings":"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"}
|
package/dist/input.js
CHANGED
|
@@ -36,6 +36,7 @@ C(I, {
|
|
|
36
36
|
...p,
|
|
37
37
|
...d,
|
|
38
38
|
...f,
|
|
39
|
+
"aria-label": k.string(),
|
|
39
40
|
autocomplete: k.string(),
|
|
40
41
|
clearable: k.bool(!1),
|
|
41
42
|
error: k.string(),
|
|
@@ -90,21 +91,27 @@ C(I, {
|
|
|
90
91
|
value: d.value
|
|
91
92
|
}));
|
|
92
93
|
let { ariaDescribedBy: f, ariaErrorMessage: p, ariaInvalid: m, ariaLabelledBy: h, assistiveId: x, clear: C, counter: k, errorId: F, errorText: I, fieldId: L, helperText: R, labelId: z, labelVisible: B, value: V, wire: H } = d;
|
|
93
|
-
|
|
94
|
+
O(i, (t) => {
|
|
94
95
|
H(t, s);
|
|
95
96
|
let n = l(e.ref, t);
|
|
96
97
|
return () => {
|
|
97
98
|
n();
|
|
98
99
|
};
|
|
99
|
-
})
|
|
100
|
+
});
|
|
101
|
+
let U = (e) => {
|
|
102
|
+
C(e), i.value?.focus();
|
|
103
|
+
}, W = () => e.type.value === "password" && r.value ? "text" : e.type.value ?? "text";
|
|
104
|
+
S({ attr: {
|
|
100
105
|
error: g(I),
|
|
101
106
|
"has-value": () => V.value ? !0 : void 0,
|
|
102
107
|
size: e.size,
|
|
103
108
|
success: () => e.success.value && !I.value ? !0 : void 0,
|
|
104
109
|
variant: e.variant
|
|
105
|
-
} })
|
|
110
|
+
} });
|
|
111
|
+
let G = () => !B.value;
|
|
112
|
+
return T`
|
|
106
113
|
<div class="input-wrapper" part="wrapper">
|
|
107
|
-
<label class="label" for="${L}" id="${z}" part="label" ?hidden="${
|
|
114
|
+
<label class="label" for="${() => G() ? null : L}" id="${z}" part="label" ?hidden="${G}">
|
|
108
115
|
<slot name="label">${e.label}</slot>
|
|
109
116
|
</label>
|
|
110
117
|
<div class="field" part="field">
|
|
@@ -113,7 +120,7 @@ C(I, {
|
|
|
113
120
|
<input
|
|
114
121
|
part="input"
|
|
115
122
|
id="${L}"
|
|
116
|
-
type="${
|
|
123
|
+
type="${W}"
|
|
117
124
|
name="${e.name}"
|
|
118
125
|
placeholder="${e.placeholder}"
|
|
119
126
|
autocomplete="${e.autocomplete}"
|
|
@@ -125,6 +132,7 @@ C(I, {
|
|
|
125
132
|
?readonly="${e.readonly}"
|
|
126
133
|
?required="${e.required}"
|
|
127
134
|
value="${E(V)}"
|
|
135
|
+
aria-label="${e["aria-label"]}"
|
|
128
136
|
aria-labelledby="${h}"
|
|
129
137
|
aria-describedby="${f}"
|
|
130
138
|
aria-errormessage="${p}"
|
|
@@ -156,9 +164,7 @@ C(I, {
|
|
|
156
164
|
part="clear"
|
|
157
165
|
type="button"
|
|
158
166
|
tabindex="${() => V.value ? "0" : "-1"}"
|
|
159
|
-
@click="${
|
|
160
|
-
C(e), i.value?.focus();
|
|
161
|
-
}}">
|
|
167
|
+
@click="${U}">
|
|
162
168
|
<ore-icon aria-hidden="true" name="x" size="12" stroke-width="2.5"></ore-icon>
|
|
163
169
|
</button>
|
|
164
170
|
</div>
|