@vielzeug/refine 2.4.0 → 3.0.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/README.md +5 -18
- package/dist/accordion-item.cjs.map +1 -1
- package/dist/accordion-item.js.map +1 -1
- package/dist/accordion.cjs.map +1 -1
- package/dist/accordion.js.map +1 -1
- package/dist/async.cjs +1 -1
- package/dist/async.cjs.map +1 -1
- package/dist/async.js +3 -3
- package/dist/async.js.map +1 -1
- package/dist/box.cjs.map +1 -1
- package/dist/box.js.map +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.cjs.map +1 -1
- package/dist/card.js +2 -2
- package/dist/card.js.map +1 -1
- package/dist/checkbox-group.cjs +1 -1
- package/dist/checkbox-group.cjs.map +1 -1
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.js.map +1 -1
- package/dist/combobox.cjs +2 -2
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +7 -3
- package/dist/combobox.js.map +1 -1
- package/dist/command-palette.cjs +1 -1
- package/dist/command-palette.cjs.map +1 -1
- package/dist/command-palette.js +6 -2
- package/dist/command-palette.js.map +1 -1
- package/dist/content/card/card.css.cjs +1 -1
- package/dist/content/card/card.css.cjs.map +1 -1
- package/dist/content/card/card.css.js +1 -1
- package/dist/content/card/card.css.js.map +1 -1
- package/dist/content/card/card.d.ts +2 -2
- package/dist/content/card/card.d.ts.map +1 -1
- package/dist/content/pagination/pagination.css.cjs +1 -1
- package/dist/content/pagination/pagination.css.cjs.map +1 -1
- package/dist/content/pagination/pagination.css.js +1 -1
- package/dist/content/pagination/pagination.css.js.map +1 -1
- package/dist/core/field-base.cjs +1 -1
- package/dist/core/field-base.cjs.map +1 -1
- package/dist/core/field-base.d.ts +1 -1
- package/dist/core/field-base.js +1 -1
- package/dist/core/field-base.js.map +1 -1
- package/dist/core/nav.cjs +1 -1
- package/dist/core/nav.cjs.map +1 -1
- package/dist/core/nav.d.ts +4 -1
- package/dist/core/nav.d.ts.map +1 -1
- package/dist/core/nav.js +41 -28
- package/dist/core/nav.js.map +1 -1
- package/dist/core/option-list.cjs +1 -1
- package/dist/core/option-list.cjs.map +1 -1
- package/dist/core/option-list.d.ts.map +1 -1
- package/dist/core/option-list.js +30 -28
- package/dist/core/option-list.js.map +1 -1
- package/dist/core/slider.cjs +1 -1
- package/dist/core/slider.cjs.map +1 -1
- package/dist/core/slider.js +1 -1
- package/dist/core/slider.js.map +1 -1
- package/dist/core/spinner.cjs +1 -1
- package/dist/core/spinner.cjs.map +1 -1
- package/dist/core/spinner.js +1 -1
- package/dist/core/spinner.js.map +1 -1
- package/dist/custom-elements.json +215 -17
- package/dist/datagrid.cjs +73 -73
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +331 -332
- package/dist/datagrid.js.map +1 -1
- package/dist/disclosure/accordion/accordion.css.cjs +1 -1
- package/dist/disclosure/accordion/accordion.css.cjs.map +1 -1
- package/dist/disclosure/accordion/accordion.css.js +1 -1
- package/dist/disclosure/accordion/accordion.css.js.map +1 -1
- package/dist/disclosure/accordion/accordion.d.ts +5 -5
- package/dist/disclosure/accordion/accordion.d.ts.map +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.cjs +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.cjs.map +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.js +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.js.map +1 -1
- package/dist/disclosure/accordion-item/accordion-item.d.ts +3 -3
- package/dist/disclosure/accordion-item/accordion-item.d.ts.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 -3
- 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 +5 -5
- package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
- package/dist/drawer.cjs +1 -1
- package/dist/drawer.cjs.map +1 -1
- package/dist/drawer.js +1 -1
- package/dist/drawer.js.map +1 -1
- package/dist/feedback/toast/toast.d.ts.map +1 -1
- package/dist/file-input.cjs +1 -1
- package/dist/file-input.cjs.map +1 -1
- package/dist/file-input.js +2 -2
- package/dist/file-input.js.map +1 -1
- package/dist/frameworks/elements.d.ts +4 -86
- package/dist/frameworks/react.d.ts +5 -4
- package/dist/frameworks/vue.d.ts +4 -4
- package/dist/grid.cjs +2 -2
- package/dist/grid.cjs.map +1 -1
- package/dist/grid.js +21 -18
- package/dist/grid.js.map +1 -1
- package/dist/inputs/combobox/combobox.d.ts +12 -1
- package/dist/inputs/combobox/combobox.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts +24 -32
- package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
- package/dist/inputs/file-input/file-input-upload.cjs +1 -1
- package/dist/inputs/file-input/file-input-upload.cjs.map +1 -1
- package/dist/inputs/file-input/file-input-upload.js +1 -1
- package/dist/inputs/file-input/file-input-upload.js.map +1 -1
- package/dist/inputs/index.d.ts +2 -3
- package/dist/inputs/index.d.ts.map +1 -1
- package/dist/inputs/shared/field-binding.cjs +1 -1
- package/dist/inputs/shared/field-binding.cjs.map +1 -1
- package/dist/inputs/shared/field-binding.js +6 -6
- package/dist/inputs/shared/field-binding.js.map +1 -1
- package/dist/layout/box/box.css.cjs +1 -1
- package/dist/layout/box/box.css.cjs.map +1 -1
- package/dist/layout/box/box.css.js +1 -1
- package/dist/layout/box/box.css.js.map +1 -1
- package/dist/layout/box/box.d.ts +3 -3
- package/dist/layout/box/box.d.ts.map +1 -1
- package/dist/layout/grid/grid.d.ts.map +1 -1
- package/dist/layout/navbar/navbar.css.cjs +1 -1
- package/dist/layout/navbar/navbar.css.cjs.map +1 -1
- package/dist/layout/navbar/navbar.css.js +1 -1
- package/dist/layout/navbar/navbar.css.js.map +1 -1
- package/dist/layout/navbar/navbar.d.ts +1 -1
- package/dist/layout/navbar/navbar.d.ts.map +1 -1
- package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +6 -6
- package/dist/menu.js.map +1 -1
- package/dist/navbar.cjs +1 -1
- package/dist/navbar.cjs.map +1 -1
- package/dist/navbar.js +87 -85
- 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/number-input.cjs +1 -1
- package/dist/number-input.cjs.map +1 -1
- package/dist/number-input.js +1 -1
- package/dist/number-input.js.map +1 -1
- package/dist/overlay/popover/popover.d.ts.map +1 -1
- package/dist/overlay/tooltip/tooltip.d.ts.map +1 -1
- package/dist/popover.cjs +1 -1
- package/dist/popover.cjs.map +1 -1
- package/dist/popover.js +6 -6
- package/dist/popover.js.map +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.cjs.map +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.js.map +1 -1
- package/dist/radio.cjs +1 -1
- package/dist/radio.cjs.map +1 -1
- package/dist/radio.js +5 -5
- 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 +207 -207
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +268 -268
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +222 -222
- package/dist/refine.js.map +1 -1
- package/dist/shared/types.d.ts +0 -2
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/sidebar.cjs +1 -1
- package/dist/sidebar.cjs.map +1 -1
- package/dist/sidebar.js +83 -83
- package/dist/sidebar.js.map +1 -1
- package/dist/skeleton.cjs +1 -1
- package/dist/skeleton.cjs.map +1 -1
- package/dist/skeleton.js +11 -9
- package/dist/skeleton.js.map +1 -1
- package/dist/slider.cjs +1 -1
- package/dist/slider.cjs.map +1 -1
- package/dist/slider.js +20 -20
- package/dist/slider.js.map +1 -1
- package/dist/stats.cjs +1 -1
- package/dist/stats.cjs.map +1 -1
- package/dist/stats.js +2 -2
- package/dist/stats.js.map +1 -1
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js.map +1 -1
- package/dist/tabs.cjs.map +1 -1
- package/dist/tabs.js.map +1 -1
- package/dist/toast.cjs +8 -8
- package/dist/toast.cjs.map +1 -1
- package/dist/toast.js +32 -33
- package/dist/toast.js.map +1 -1
- package/dist/tooltip.cjs +1 -1
- package/dist/tooltip.cjs.map +1 -1
- package/dist/tooltip.js +2 -2
- package/dist/tooltip.js.map +1 -1
- package/dist/types/elements.d.ts +207 -0
- package/package.json +12 -12
package/dist/checkbox-group.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/states.css.cjs"),t=require("./core/choice-field.cjs"),n=require("./core/light-dom.cjs"),r=require("./core/ore.cjs"),i=require("./shared/prop-bundles.cjs"),a=require("./inputs/checkbox-group/checkbox-group.css.cjs");let o=require("@vielzeug/ore"),s=require("@vielzeug/ripple");var c=(0,o.createContext)(`CheckboxGroupContext`),l=`ore-checkbox-group`;(0,o.define)(l,{formAssociated:!0,props:{...i.themableBundle,...i.sizableBundle,...i.disablableBundle,error:o.prop.string(),helper:o.prop.string(),label:o.prop.string(),name:o.prop.string(),orientation:o.prop.string(`vertical`),required:o.prop.bool(!1),values:{...o.prop.string(),reflect:!1}},setup(e){let i=(0,o.getHost)(),a=(0,o.useEmit)(),l=(0,o.useSlots)(),u=o.watchEffect,d=t.createChoiceField({disabled:e.disabled,error:e.error,helper:e.helper,multiple:(0,s.signal)(!0),prefix:`checkbox-group`,required:e.required,signal:r.lifecycleSignal(o.onCleanup),value:e.values});d.attachFormField((0,o.useField)({disabled:d.disabled,onReset:d.reset,toFormValue:e=>e,validationMessage:d.validationMessage,validity:d.validity,value:d.formValue}));let f=d.selectedValues,p=()=>n.getLightChildrenByTag(i,`ore-checkbox`),m=e=>n.getChoiceLabel(p(),e),h=e=>{let t=f.value,n=t.map(m);a(`change`,{labels:n,originalEvent:e,values:t})},g=(e,t)=>{d.toggleValue(e),d.triggerValidation(`change`),h(t)};(0,o.provide)(c,{color:e.color,disabled:(0,s.computed)(()=>!!e.disabled.value),size:e.size,toggle:g,values:f});let _=()=>{let t=f.value,n=e.color.value,r=e.size.value,i=e.disabled.value,a=p();for(let e of a){let a=e.getAttribute(`value`)??``;e.toggleAttribute(`checked`,t.includes(a)),n?e.setAttribute(`color`,n):e.removeAttribute(`color`),r?e.setAttribute(`size`,r):e.removeAttribute(`size`),e.toggleAttribute(`disabled`,!!i)}};u(()=>{l.elements().value,_()}),u(()=>{l.elements().value;let e=p().map(e=>{let t=t=>{t.stopPropagation();let n=(e.getAttribute(`value`)??``).trim();n&&g(n,t)};return e.addEventListener(`change`,t),()=>{e.removeEventListener(`change`,t)}});return()=>{for(let t of e)t()}});let v=(0,o.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/states.css.cjs"),t=require("./core/choice-field.cjs"),n=require("./core/light-dom.cjs"),r=require("./core/ore.cjs"),i=require("./shared/prop-bundles.cjs"),a=require("./inputs/checkbox-group/checkbox-group.css.cjs");let o=require("@vielzeug/ore"),s=require("@vielzeug/ripple");var c=(0,o.createContext)(`CheckboxGroupContext`),l=`ore-checkbox-group`;(0,o.define)(l,{formAssociated:!0,props:{...i.themableBundle,...i.sizableBundle,...i.disablableBundle,error:o.prop.string(),helper:o.prop.string(),label:o.prop.string(),name:o.prop.string(),orientation:o.prop.string(`vertical`),required:o.prop.bool(!1),values:{...o.prop.string(),reflect:!1}},setup(e){let i=(0,o.getHost)(),a=(0,o.useEmit)(),l=(0,o.useSlots)(),u=o.watchEffect,d=t.createChoiceField({disabled:e.disabled,error:e.error,helper:e.helper,multiple:(0,s.signal)(!0),prefix:`checkbox-group`,required:e.required,signal:r.lifecycleSignal(o.onCleanup),value:e.values});d.attachFormField((0,o.useField)({disabled:d.disabled,onReset:d.reset,toFormValue:e=>e,validationMessage:d.validationMessage,validity:d.validity,value:d.formValue}));let f=d.selectedValues,p=()=>n.getLightChildrenByTag(i,`ore-checkbox`),m=e=>n.getChoiceLabel(p(),e),h=e=>{let t=f.value,n=t.map(m);a(`change`,{labels:n,originalEvent:e,values:t})},g=(e,t)=>{d.toggleValue(e),d.triggerValidation(`change`),h(t)};(0,o.provide)(c,{color:e.color,disabled:(0,s.computed)(()=>!!e.disabled.value),size:e.size,toggle:g,values:f});let _=()=>{let t=f.value,n=e.color.value,r=e.size.value,i=e.disabled.value,a=p();for(let e of a){let a=e.getAttribute(`value`)??``;e.toggleAttribute(`checked`,t.includes(a)),n?e.setAttribute(`color`,n):e.removeAttribute(`color`),r?e.setAttribute(`size`,r):e.removeAttribute(`size`),e.toggleAttribute(`disabled`,!!i)}};u(()=>{l.elements().value,_()}),u(()=>{l.elements().value;let e=p().map(e=>{let t=t=>{t.stopPropagation();let n=(e.getAttribute(`value`)??``).trim();n&&g(n,t)};return e.addEventListener(`change`,t),()=>{e.removeEventListener(`change`,t)}});return()=>{for(let t of e)t()}});let v=(0,o.createId)(`checkbox-group-legend`),y=`${v}-error`,b=`${v}-helper`,x=()=>!!e.error.value,S=()=>!!e.helper.value&&!x();return(0,o.bind)({attr:{size:e.size,values:d.formValue}}),o.html`
|
|
2
2
|
<fieldset
|
|
3
3
|
role="group"
|
|
4
4
|
aria-required="${()=>String(!!e.required.value)}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox-group.cjs","names":[],"sources":["../src/inputs/checkbox-group/checkbox-group.ts"],"sourcesContent":["import {\n bind,\n createContext,\n createStableId,\n define,\n getHost,\n html,\n onCleanup,\n prop,\n provide,\n useEmit,\n useField,\n useSlots,\n watchEffect,\n when,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal } from '@vielzeug/ripple';\nimport {\n type ChoiceChangeDetail,\n createChoiceField,\n getChoiceLabel,\n getLightChildrenByTag,\n lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './checkbox-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type CheckboxGroupContext = {\n color: Readable<ThemeColor | undefined>;\n disabled: Readable<boolean>;\n size: Readable<ComponentSize | undefined>;\n toggle: (value: string, originalEvent?: Event) => void;\n values: Readable<string[]>;\n};\n\nexport const CHECKBOX_GROUP_CTX = createContext<CheckboxGroupContext>('CheckboxGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type OreCheckboxGroupProps = {\n /** Theme color — propagated to all child ore-checkbox elements */\n color?: ThemeColor;\n /** Disable all checkboxes in the group */\n disabled?: boolean;\n /** Error message shown below the group */\n error?: string;\n /** Helper text shown below the group */\n helper?: string;\n /** Legend / label for the fieldset. Required for accessibility. */\n label?: string;\n /** Form field name used during submission */\n name?: string;\n /** Layout direction of the checkbox options */\n orientation?: 'vertical' | 'horizontal';\n /** Mark the group as required */\n required?: boolean;\n /** Size — propagated to all child ore-checkbox elements */\n size?: ComponentSize;\n /** Comma-separated list of currently checked values */\n values?: string;\n};\n\nexport type OreCheckboxGroupEvents = {\n change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `ore-checkbox` elements, provides shared\n * `color` and `size` via context, and manages multi-value selection state.\n *\n * @element ore-checkbox-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} values - Comma-separated list of checked values\n * @attr {boolean} disabled - Disable all checkboxes in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-checkbox` elements here\n *\n * @cssprop --checkbox-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --checkbox-group-gap - Gap between checkbox items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-checkbox-group name=\"fruits\" label=\"Favourite fruits\" required>\n * <ore-checkbox value=\"apple\">Apple</ore-checkbox>\n * <ore-checkbox value=\"banana\">Banana</ore-checkbox>\n * <ore-checkbox value=\"cherry\">Cherry</ore-checkbox>\n * </ore-checkbox-group>\n * <ore-checkbox-group name=\"options\" orientation=\"horizontal\" color=\"primary\">\n * <ore-checkbox value=\"a\">Option A</ore-checkbox>\n * <ore-checkbox value=\"b\">Option B</ore-checkbox>\n * </ore-checkbox-group>\n * ```\n */\nexport const CHECKBOX_GROUP_TAG = 'ore-checkbox-group' as const;\ndefine<OreCheckboxGroupProps>(CHECKBOX_GROUP_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string(),\n name: prop.string(),\n orientation: prop.string('vertical'),\n required: prop.bool(false),\n // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n // (`choice.formValue`) is the single writer for this attribute, via `bind()` below;\n // letting `prop.string()`'s own default reflection also write the raw incoming value\n // would leave two effects racing to set the same attribute from different sources.\n values: { ...prop.string(), reflect: false },\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreCheckboxGroupEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n multiple: signal(true),\n prefix: 'checkbox-group',\n required: props.required,\n signal: lifecycleSignal(onCleanup),\n value: props.values,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const checkedValues = choice.selectedValues;\n\n const getCheckboxes = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-checkbox');\n const getLabelForValue = (value: string): string => getChoiceLabel(getCheckboxes(), value);\n const emitChange = (originalEvent?: Event) => {\n const values = checkedValues.value;\n\n const labels = values.map(getLabelForValue);\n\n emit('change', { labels, originalEvent, values });\n };\n\n const toggleCheckbox = (val: string, originalEvent?: Event) => {\n choice.toggleValue(val);\n choice.triggerValidation('change');\n emitChange(originalEvent);\n };\n\n provide(CHECKBOX_GROUP_CTX, {\n color: props.color,\n disabled: computed(() => Boolean(props.disabled.value)),\n size: props.size,\n toggle: toggleCheckbox,\n values: checkedValues,\n });\n\n // Sync checked state + color/size/disabled onto slotted ore-checkbox children\n const syncChildren = () => {\n const values = checkedValues.value;\n const color = props.color.value;\n const size = props.size.value;\n const disabled = props.disabled.value;\n const checkboxes = getCheckboxes();\n\n for (const checkbox of checkboxes) {\n const val = checkbox.getAttribute('value') ?? '';\n\n checkbox.toggleAttribute('checked', values.includes(val));\n\n if (color) checkbox.setAttribute('color', color);\n else checkbox.removeAttribute('color');\n\n if (size) checkbox.setAttribute('size', size);\n else checkbox.removeAttribute('size');\n\n checkbox.toggleAttribute('disabled', Boolean(disabled));\n }\n };\n\n watch(() => {\n void slots.elements().value;\n syncChildren();\n });\n\n watch(() => {\n void slots.elements().value;\n\n const listeners = getCheckboxes().map((checkbox) => {\n const handler = (event: Event) => {\n event.stopPropagation();\n\n const val = (checkbox.getAttribute('value') ?? '').trim();\n\n if (!val) return;\n\n toggleCheckbox(val, event);\n };\n\n checkbox.addEventListener('change', handler);\n\n return () => {\n checkbox.removeEventListener('change', handler);\n };\n });\n\n return () => {\n for (const dispose of listeners) dispose();\n };\n });\n\n const legendId = createStableId('checkbox-group-legend');\n const errorId = `${legendId}-error`;\n const helperId = `${legendId}-helper`;\n const hasError = () => Boolean(props.error.value);\n const hasHelper = () => Boolean(props.helper.value) && !hasError();\n\n // Reactive, not a one-off `el.setAttribute()` inside the click handler: the host's `values`\n // attribute must stay in sync with the selection regardless of *why* it changed (a click,\n // or `reset()` on ancestor form reset — neither of which should need its own copy of this).\n bind({ attr: { size: props.size, values: choice.formValue } });\n\n return html`\n <fieldset\n role=\"group\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${() => String(hasError())}\"\n aria-errormessage=\"${() => (hasError() ? errorId : null)}\"\n aria-describedby=\"${() => (hasError() ? errorId : hasHelper() ? helperId : null)}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${props.label}${when(\n () => Boolean(props.required.value),\n () => html`\n <span aria-hidden=\"true\">*</span>\n `,\n )}\n </legend>\n <div class=\"checkbox-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError()}>${props.error}</div>\n <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper()}>${props.helper}</div>\n </fieldset>\n `;\n },\n styles: [disabledStateMixin, componentStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"checkbox-group.cjs","names":[],"sources":["../src/inputs/checkbox-group/checkbox-group.ts"],"sourcesContent":["import {\n bind,\n createContext,\n createId,\n define,\n getHost,\n html,\n onCleanup,\n prop,\n provide,\n useEmit,\n useField,\n useSlots,\n watchEffect,\n when,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal } from '@vielzeug/ripple';\nimport {\n type ChoiceChangeDetail,\n createChoiceField,\n getChoiceLabel,\n getLightChildrenByTag,\n lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './checkbox-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type CheckboxGroupContext = {\n color: Readable<ThemeColor | undefined>;\n disabled: Readable<boolean>;\n size: Readable<ComponentSize | undefined>;\n toggle: (value: string, originalEvent?: Event) => void;\n values: Readable<string[]>;\n};\n\nexport const CHECKBOX_GROUP_CTX = createContext<CheckboxGroupContext>('CheckboxGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type OreCheckboxGroupProps = {\n /** Theme color — propagated to all child ore-checkbox elements */\n color?: ThemeColor;\n /** Disable all checkboxes in the group */\n disabled?: boolean;\n /** Error message shown below the group */\n error?: string;\n /** Helper text shown below the group */\n helper?: string;\n /** Legend / label for the fieldset. Required for accessibility. */\n label?: string;\n /** Form field name used during submission */\n name?: string;\n /** Layout direction of the checkbox options */\n orientation?: 'vertical' | 'horizontal';\n /** Mark the group as required */\n required?: boolean;\n /** Size — propagated to all child ore-checkbox elements */\n size?: ComponentSize;\n /** Comma-separated list of currently checked values */\n values?: string;\n};\n\nexport type OreCheckboxGroupEvents = {\n change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `ore-checkbox` elements, provides shared\n * `color` and `size` via context, and manages multi-value selection state.\n *\n * @element ore-checkbox-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} values - Comma-separated list of checked values\n * @attr {boolean} disabled - Disable all checkboxes in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-checkbox` elements here\n *\n * @cssprop --checkbox-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --checkbox-group-gap - Gap between checkbox items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-checkbox-group name=\"fruits\" label=\"Favourite fruits\" required>\n * <ore-checkbox value=\"apple\">Apple</ore-checkbox>\n * <ore-checkbox value=\"banana\">Banana</ore-checkbox>\n * <ore-checkbox value=\"cherry\">Cherry</ore-checkbox>\n * </ore-checkbox-group>\n * <ore-checkbox-group name=\"options\" orientation=\"horizontal\" color=\"primary\">\n * <ore-checkbox value=\"a\">Option A</ore-checkbox>\n * <ore-checkbox value=\"b\">Option B</ore-checkbox>\n * </ore-checkbox-group>\n * ```\n */\nexport const CHECKBOX_GROUP_TAG = 'ore-checkbox-group' as const;\ndefine<OreCheckboxGroupProps>(CHECKBOX_GROUP_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string(),\n name: prop.string(),\n orientation: prop.string('vertical'),\n required: prop.bool(false),\n // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n // (`choice.formValue`) is the single writer for this attribute, via `bind()` below;\n // letting `prop.string()`'s own default reflection also write the raw incoming value\n // would leave two effects racing to set the same attribute from different sources.\n values: { ...prop.string(), reflect: false },\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreCheckboxGroupEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n multiple: signal(true),\n prefix: 'checkbox-group',\n required: props.required,\n signal: lifecycleSignal(onCleanup),\n value: props.values,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const checkedValues = choice.selectedValues;\n\n const getCheckboxes = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-checkbox');\n const getLabelForValue = (value: string): string => getChoiceLabel(getCheckboxes(), value);\n const emitChange = (originalEvent?: Event) => {\n const values = checkedValues.value;\n\n const labels = values.map(getLabelForValue);\n\n emit('change', { labels, originalEvent, values });\n };\n\n const toggleCheckbox = (val: string, originalEvent?: Event) => {\n choice.toggleValue(val);\n choice.triggerValidation('change');\n emitChange(originalEvent);\n };\n\n provide(CHECKBOX_GROUP_CTX, {\n color: props.color,\n disabled: computed(() => Boolean(props.disabled.value)),\n size: props.size,\n toggle: toggleCheckbox,\n values: checkedValues,\n });\n\n // Sync checked state + color/size/disabled onto slotted ore-checkbox children\n const syncChildren = () => {\n const values = checkedValues.value;\n const color = props.color.value;\n const size = props.size.value;\n const disabled = props.disabled.value;\n const checkboxes = getCheckboxes();\n\n for (const checkbox of checkboxes) {\n const val = checkbox.getAttribute('value') ?? '';\n\n checkbox.toggleAttribute('checked', values.includes(val));\n\n if (color) checkbox.setAttribute('color', color);\n else checkbox.removeAttribute('color');\n\n if (size) checkbox.setAttribute('size', size);\n else checkbox.removeAttribute('size');\n\n checkbox.toggleAttribute('disabled', Boolean(disabled));\n }\n };\n\n watch(() => {\n void slots.elements().value;\n syncChildren();\n });\n\n watch(() => {\n void slots.elements().value;\n\n const listeners = getCheckboxes().map((checkbox) => {\n const handler = (event: Event) => {\n event.stopPropagation();\n\n const val = (checkbox.getAttribute('value') ?? '').trim();\n\n if (!val) return;\n\n toggleCheckbox(val, event);\n };\n\n checkbox.addEventListener('change', handler);\n\n return () => {\n checkbox.removeEventListener('change', handler);\n };\n });\n\n return () => {\n for (const dispose of listeners) dispose();\n };\n });\n\n const legendId = createId('checkbox-group-legend');\n const errorId = `${legendId}-error`;\n const helperId = `${legendId}-helper`;\n const hasError = () => Boolean(props.error.value);\n const hasHelper = () => Boolean(props.helper.value) && !hasError();\n\n // Reactive, not a one-off `el.setAttribute()` inside the click handler: the host's `values`\n // attribute must stay in sync with the selection regardless of *why* it changed (a click,\n // or `reset()` on ancestor form reset — neither of which should need its own copy of this).\n bind({ attr: { size: props.size, values: choice.formValue } });\n\n return html`\n <fieldset\n role=\"group\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${() => String(hasError())}\"\n aria-errormessage=\"${() => (hasError() ? errorId : null)}\"\n aria-describedby=\"${() => (hasError() ? errorId : hasHelper() ? helperId : null)}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${props.label}${when(\n () => Boolean(props.required.value),\n () => html`\n <span aria-hidden=\"true\">*</span>\n `,\n )}\n </legend>\n <div class=\"checkbox-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError()}>${props.error}</div>\n <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper()}>${props.helper}</div>\n </fieldset>\n `;\n },\n styles: [disabledStateMixin, componentStyles],\n});\n"],"mappings":"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"}
|
package/dist/checkbox-group.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getChoiceLabel as n, getLightChildrenByTag as r } from "./core/light-do
|
|
|
4
4
|
import { lifecycleSignal as i } from "./core/ore.js";
|
|
5
5
|
import { disablableBundle as a, sizableBundle as o, themableBundle as s } from "./shared/prop-bundles.js";
|
|
6
6
|
import c from "./inputs/checkbox-group/checkbox-group.css.js";
|
|
7
|
-
import { bind as l, createContext as u,
|
|
7
|
+
import { bind as l, createContext as u, createId as d, define as f, getHost as p, html as m, onCleanup as h, prop as g, provide as _, useEmit as v, useField as y, useSlots as b, watchEffect as x, when as S } from "@vielzeug/ore";
|
|
8
8
|
import { computed as C, signal as w } from "@vielzeug/ripple";
|
|
9
9
|
//#region src/inputs/checkbox-group/checkbox-group.ts
|
|
10
10
|
var T = u("CheckboxGroupContext"), E = "ore-checkbox-group";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox-group.js","names":[],"sources":["../src/inputs/checkbox-group/checkbox-group.ts"],"sourcesContent":["import {\n bind,\n createContext,\n createStableId,\n define,\n getHost,\n html,\n onCleanup,\n prop,\n provide,\n useEmit,\n useField,\n useSlots,\n watchEffect,\n when,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal } from '@vielzeug/ripple';\nimport {\n type ChoiceChangeDetail,\n createChoiceField,\n getChoiceLabel,\n getLightChildrenByTag,\n lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './checkbox-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type CheckboxGroupContext = {\n color: Readable<ThemeColor | undefined>;\n disabled: Readable<boolean>;\n size: Readable<ComponentSize | undefined>;\n toggle: (value: string, originalEvent?: Event) => void;\n values: Readable<string[]>;\n};\n\nexport const CHECKBOX_GROUP_CTX = createContext<CheckboxGroupContext>('CheckboxGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type OreCheckboxGroupProps = {\n /** Theme color — propagated to all child ore-checkbox elements */\n color?: ThemeColor;\n /** Disable all checkboxes in the group */\n disabled?: boolean;\n /** Error message shown below the group */\n error?: string;\n /** Helper text shown below the group */\n helper?: string;\n /** Legend / label for the fieldset. Required for accessibility. */\n label?: string;\n /** Form field name used during submission */\n name?: string;\n /** Layout direction of the checkbox options */\n orientation?: 'vertical' | 'horizontal';\n /** Mark the group as required */\n required?: boolean;\n /** Size — propagated to all child ore-checkbox elements */\n size?: ComponentSize;\n /** Comma-separated list of currently checked values */\n values?: string;\n};\n\nexport type OreCheckboxGroupEvents = {\n change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `ore-checkbox` elements, provides shared\n * `color` and `size` via context, and manages multi-value selection state.\n *\n * @element ore-checkbox-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} values - Comma-separated list of checked values\n * @attr {boolean} disabled - Disable all checkboxes in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-checkbox` elements here\n *\n * @cssprop --checkbox-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --checkbox-group-gap - Gap between checkbox items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-checkbox-group name=\"fruits\" label=\"Favourite fruits\" required>\n * <ore-checkbox value=\"apple\">Apple</ore-checkbox>\n * <ore-checkbox value=\"banana\">Banana</ore-checkbox>\n * <ore-checkbox value=\"cherry\">Cherry</ore-checkbox>\n * </ore-checkbox-group>\n * <ore-checkbox-group name=\"options\" orientation=\"horizontal\" color=\"primary\">\n * <ore-checkbox value=\"a\">Option A</ore-checkbox>\n * <ore-checkbox value=\"b\">Option B</ore-checkbox>\n * </ore-checkbox-group>\n * ```\n */\nexport const CHECKBOX_GROUP_TAG = 'ore-checkbox-group' as const;\ndefine<OreCheckboxGroupProps>(CHECKBOX_GROUP_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string(),\n name: prop.string(),\n orientation: prop.string('vertical'),\n required: prop.bool(false),\n // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n // (`choice.formValue`) is the single writer for this attribute, via `bind()` below;\n // letting `prop.string()`'s own default reflection also write the raw incoming value\n // would leave two effects racing to set the same attribute from different sources.\n values: { ...prop.string(), reflect: false },\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreCheckboxGroupEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n multiple: signal(true),\n prefix: 'checkbox-group',\n required: props.required,\n signal: lifecycleSignal(onCleanup),\n value: props.values,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const checkedValues = choice.selectedValues;\n\n const getCheckboxes = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-checkbox');\n const getLabelForValue = (value: string): string => getChoiceLabel(getCheckboxes(), value);\n const emitChange = (originalEvent?: Event) => {\n const values = checkedValues.value;\n\n const labels = values.map(getLabelForValue);\n\n emit('change', { labels, originalEvent, values });\n };\n\n const toggleCheckbox = (val: string, originalEvent?: Event) => {\n choice.toggleValue(val);\n choice.triggerValidation('change');\n emitChange(originalEvent);\n };\n\n provide(CHECKBOX_GROUP_CTX, {\n color: props.color,\n disabled: computed(() => Boolean(props.disabled.value)),\n size: props.size,\n toggle: toggleCheckbox,\n values: checkedValues,\n });\n\n // Sync checked state + color/size/disabled onto slotted ore-checkbox children\n const syncChildren = () => {\n const values = checkedValues.value;\n const color = props.color.value;\n const size = props.size.value;\n const disabled = props.disabled.value;\n const checkboxes = getCheckboxes();\n\n for (const checkbox of checkboxes) {\n const val = checkbox.getAttribute('value') ?? '';\n\n checkbox.toggleAttribute('checked', values.includes(val));\n\n if (color) checkbox.setAttribute('color', color);\n else checkbox.removeAttribute('color');\n\n if (size) checkbox.setAttribute('size', size);\n else checkbox.removeAttribute('size');\n\n checkbox.toggleAttribute('disabled', Boolean(disabled));\n }\n };\n\n watch(() => {\n void slots.elements().value;\n syncChildren();\n });\n\n watch(() => {\n void slots.elements().value;\n\n const listeners = getCheckboxes().map((checkbox) => {\n const handler = (event: Event) => {\n event.stopPropagation();\n\n const val = (checkbox.getAttribute('value') ?? '').trim();\n\n if (!val) return;\n\n toggleCheckbox(val, event);\n };\n\n checkbox.addEventListener('change', handler);\n\n return () => {\n checkbox.removeEventListener('change', handler);\n };\n });\n\n return () => {\n for (const dispose of listeners) dispose();\n };\n });\n\n const legendId = createStableId('checkbox-group-legend');\n const errorId = `${legendId}-error`;\n const helperId = `${legendId}-helper`;\n const hasError = () => Boolean(props.error.value);\n const hasHelper = () => Boolean(props.helper.value) && !hasError();\n\n // Reactive, not a one-off `el.setAttribute()` inside the click handler: the host's `values`\n // attribute must stay in sync with the selection regardless of *why* it changed (a click,\n // or `reset()` on ancestor form reset — neither of which should need its own copy of this).\n bind({ attr: { size: props.size, values: choice.formValue } });\n\n return html`\n <fieldset\n role=\"group\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${() => String(hasError())}\"\n aria-errormessage=\"${() => (hasError() ? errorId : null)}\"\n aria-describedby=\"${() => (hasError() ? errorId : hasHelper() ? helperId : null)}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${props.label}${when(\n () => Boolean(props.required.value),\n () => html`\n <span aria-hidden=\"true\">*</span>\n `,\n )}\n </legend>\n <div class=\"checkbox-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError()}>${props.error}</div>\n <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper()}>${props.helper}</div>\n </fieldset>\n `;\n },\n styles: [disabledStateMixin, componentStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"checkbox-group.js","names":[],"sources":["../src/inputs/checkbox-group/checkbox-group.ts"],"sourcesContent":["import {\n bind,\n createContext,\n createId,\n define,\n getHost,\n html,\n onCleanup,\n prop,\n provide,\n useEmit,\n useField,\n useSlots,\n watchEffect,\n when,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal } from '@vielzeug/ripple';\nimport {\n type ChoiceChangeDetail,\n createChoiceField,\n getChoiceLabel,\n getLightChildrenByTag,\n lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './checkbox-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type CheckboxGroupContext = {\n color: Readable<ThemeColor | undefined>;\n disabled: Readable<boolean>;\n size: Readable<ComponentSize | undefined>;\n toggle: (value: string, originalEvent?: Event) => void;\n values: Readable<string[]>;\n};\n\nexport const CHECKBOX_GROUP_CTX = createContext<CheckboxGroupContext>('CheckboxGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type OreCheckboxGroupProps = {\n /** Theme color — propagated to all child ore-checkbox elements */\n color?: ThemeColor;\n /** Disable all checkboxes in the group */\n disabled?: boolean;\n /** Error message shown below the group */\n error?: string;\n /** Helper text shown below the group */\n helper?: string;\n /** Legend / label for the fieldset. Required for accessibility. */\n label?: string;\n /** Form field name used during submission */\n name?: string;\n /** Layout direction of the checkbox options */\n orientation?: 'vertical' | 'horizontal';\n /** Mark the group as required */\n required?: boolean;\n /** Size — propagated to all child ore-checkbox elements */\n size?: ComponentSize;\n /** Comma-separated list of currently checked values */\n values?: string;\n};\n\nexport type OreCheckboxGroupEvents = {\n change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `ore-checkbox` elements, provides shared\n * `color` and `size` via context, and manages multi-value selection state.\n *\n * @element ore-checkbox-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} values - Comma-separated list of checked values\n * @attr {boolean} disabled - Disable all checkboxes in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-checkbox` elements here\n *\n * @cssprop --checkbox-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --checkbox-group-gap - Gap between checkbox items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-checkbox-group name=\"fruits\" label=\"Favourite fruits\" required>\n * <ore-checkbox value=\"apple\">Apple</ore-checkbox>\n * <ore-checkbox value=\"banana\">Banana</ore-checkbox>\n * <ore-checkbox value=\"cherry\">Cherry</ore-checkbox>\n * </ore-checkbox-group>\n * <ore-checkbox-group name=\"options\" orientation=\"horizontal\" color=\"primary\">\n * <ore-checkbox value=\"a\">Option A</ore-checkbox>\n * <ore-checkbox value=\"b\">Option B</ore-checkbox>\n * </ore-checkbox-group>\n * ```\n */\nexport const CHECKBOX_GROUP_TAG = 'ore-checkbox-group' as const;\ndefine<OreCheckboxGroupProps>(CHECKBOX_GROUP_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string(),\n name: prop.string(),\n orientation: prop.string('vertical'),\n required: prop.bool(false),\n // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n // (`choice.formValue`) is the single writer for this attribute, via `bind()` below;\n // letting `prop.string()`'s own default reflection also write the raw incoming value\n // would leave two effects racing to set the same attribute from different sources.\n values: { ...prop.string(), reflect: false },\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreCheckboxGroupEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n multiple: signal(true),\n prefix: 'checkbox-group',\n required: props.required,\n signal: lifecycleSignal(onCleanup),\n value: props.values,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const checkedValues = choice.selectedValues;\n\n const getCheckboxes = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-checkbox');\n const getLabelForValue = (value: string): string => getChoiceLabel(getCheckboxes(), value);\n const emitChange = (originalEvent?: Event) => {\n const values = checkedValues.value;\n\n const labels = values.map(getLabelForValue);\n\n emit('change', { labels, originalEvent, values });\n };\n\n const toggleCheckbox = (val: string, originalEvent?: Event) => {\n choice.toggleValue(val);\n choice.triggerValidation('change');\n emitChange(originalEvent);\n };\n\n provide(CHECKBOX_GROUP_CTX, {\n color: props.color,\n disabled: computed(() => Boolean(props.disabled.value)),\n size: props.size,\n toggle: toggleCheckbox,\n values: checkedValues,\n });\n\n // Sync checked state + color/size/disabled onto slotted ore-checkbox children\n const syncChildren = () => {\n const values = checkedValues.value;\n const color = props.color.value;\n const size = props.size.value;\n const disabled = props.disabled.value;\n const checkboxes = getCheckboxes();\n\n for (const checkbox of checkboxes) {\n const val = checkbox.getAttribute('value') ?? '';\n\n checkbox.toggleAttribute('checked', values.includes(val));\n\n if (color) checkbox.setAttribute('color', color);\n else checkbox.removeAttribute('color');\n\n if (size) checkbox.setAttribute('size', size);\n else checkbox.removeAttribute('size');\n\n checkbox.toggleAttribute('disabled', Boolean(disabled));\n }\n };\n\n watch(() => {\n void slots.elements().value;\n syncChildren();\n });\n\n watch(() => {\n void slots.elements().value;\n\n const listeners = getCheckboxes().map((checkbox) => {\n const handler = (event: Event) => {\n event.stopPropagation();\n\n const val = (checkbox.getAttribute('value') ?? '').trim();\n\n if (!val) return;\n\n toggleCheckbox(val, event);\n };\n\n checkbox.addEventListener('change', handler);\n\n return () => {\n checkbox.removeEventListener('change', handler);\n };\n });\n\n return () => {\n for (const dispose of listeners) dispose();\n };\n });\n\n const legendId = createId('checkbox-group-legend');\n const errorId = `${legendId}-error`;\n const helperId = `${legendId}-helper`;\n const hasError = () => Boolean(props.error.value);\n const hasHelper = () => Boolean(props.helper.value) && !hasError();\n\n // Reactive, not a one-off `el.setAttribute()` inside the click handler: the host's `values`\n // attribute must stay in sync with the selection regardless of *why* it changed (a click,\n // or `reset()` on ancestor form reset — neither of which should need its own copy of this).\n bind({ attr: { size: props.size, values: choice.formValue } });\n\n return html`\n <fieldset\n role=\"group\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${() => String(hasError())}\"\n aria-errormessage=\"${() => (hasError() ? errorId : null)}\"\n aria-describedby=\"${() => (hasError() ? errorId : hasHelper() ? helperId : null)}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${props.label}${when(\n () => Boolean(props.required.value),\n () => html`\n <span aria-hidden=\"true\">*</span>\n `,\n )}\n </legend>\n <div class=\"checkbox-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError()}>${props.error}</div>\n <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper()}>${props.helper}</div>\n </fieldset>\n `;\n },\n styles: [disabledStateMixin, componentStyles],\n});\n"],"mappings":"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"}
|
package/dist/combobox.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/shape.css.cjs"),n=require("./styles/mixins/theme.css.cjs"),r=require("./core/keyboard.cjs"),i=require("./core/choice-field.cjs"),a=require("./core/ore.cjs"),ee=require("./core/option-list.cjs"),o=require("./inputs/shared/native-field-event.cjs"),s=require("./inputs/combobox/combobox-options.cjs"),c=require("./inputs/combobox/combobox.css.cjs");let l=require("@vielzeug/ore"),u=require("@vielzeug/ripple");var d=`ore-combobox`;(0,l.define)(d,{formAssociated:!0,props:{autoclose:l.prop.bool(!1),color:l.prop.string(),creatable:l.prop.bool(!1),disabled:l.prop.bool(!1),error:l.prop.string(),fullwidth:l.prop.bool(!1),helper:l.prop.string(),"hide-label":l.prop.bool(!1),label:l.prop.string(),"label-placement":l.prop.oneOf([`inset`,`outside`],`inset`),loading:l.prop.bool(!1),multiple:l.prop.bool(!1),name:l.prop.string(),"no-filter":l.prop.bool(!1),options:l.prop.data(),placeholder:l.prop.string(`Select...`),required:l.prop.bool(!1),rounded:l.prop.string(),size:l.prop.string(),success:l.prop.bool(!1),value:l.prop.string(),variant:l.prop.string()},setup(e){let t=(0,l.getHost)(),n=(0,l.useEmit)(),c=l.watchEffect,d=(0,u.signal)(``),f=null,p=null,m=null,h=null,g=(0,l.ref)(),_=a.lifecycleSignal(l.onCleanup),v=i.createChoiceField({disabled:e.disabled,error:e.error,helper:e.helper,label:e.label,labelPlacement:e[`label-placement`],multiple:e.multiple,prefix:`combobox`,required:e.required,signal:_,value:e.value}),y=(0,u.signal)([]),b=ee.createListboxDropdown({getBoundary:()=>t,getFocusedOptionElement:()=>m?.querySelector(`[data-focused]`)??null,getItems:()=>y.value,getOptionId:e=>`${v.fieldId}-opt-${e}`,getPanel:()=>m,getReference:()=>p,getTrigger:()=>f,isDisabled:()=>v.disabled.value,isItemDisabled:e=>e.disabled,onClose:e=>{n(`open-change`,{open:!1,reason:e}),_.aborted||se(),v.triggerValidation(`blur`)},onOpen:e=>n(`open-change`,{open:!0,reason:e}),restoreFocus:!1,signal:_}),{disabled:x,fieldId:S,selectedValues:C,triggerValidation:w}=v;v.attachFormField((0,l.useField)({disabled:v.disabled,onReset:v.reset,toFormValue:e=>e,validationMessage:v.validationMessage,validity:v.validity,value:v.formValue}));let{focusedIndex:T,isOpen:E,scrollFocusedIntoView:te,updatePosition:ne}=b,D=()=>!!e.multiple.value,O=()=>!!e.creatable.value,k=()=>!!e[`no-filter`].value;(0,l.bind)({attr:{open:()=>E.value?!0:void 0,size:e.size,variant:e.variant}});let A=null,j=!1,M=(0,u.computed)(()=>C.value[0]??``);Object.defineProperty(t,"value",{configurable:!0,get:()=>v.formValue.value,set:e=>{let t=e;if(Array.isArray(t)){v.setValues(t.map(e=>String(e??``)));return}if(t==null||t===``){v.clear();return}v.setValues(D()?String(t).split(`,`):[String(t)])}});let re=()=>C.value.length>0;function N(){f?.focus()}let P=(0,u.signal)([]),F=(0,u.signal)([]),ie=()=>!!e.loading.value;function I(e){return{disabled:!!e.disabled,disabledReason:e.disabledReason,iconEl:e.iconEl??null,label:e.label??e.value,value:e.value}}let L=(0,u.computed)(()=>{let t=e.options.value,n=Array.isArray(t)?t.map(I):P.value;return F.value.length===0?n:[...n,...F.value]}),R={clear:()=>{v.clear()},remove:e=>{v.removeValue(e)},select:e=>{v.selectValue(e)},toggle:e=>{v.toggleValue(e)}};function z(e=Array.from(t.children)){if(P.value=s.parseSlottedOptions(e),!D()){let e=L.value.find(e=>e.value===M.value);d.value=e?.label??M.value}}z(),c(()=>{let e=s.filterOptions(L.value,d.value,k());y.value=D()?e.filter(e=>!C.value.includes(e.value)):e});let B=(0,u.computed)(()=>s.getCreatableLabel(d.value,O(),y.value)),ae=()=>D()&&C.value.length>0?``:e.placeholder.value||``;function V(){o.dispatchNativeFieldEvent(t,`input`),o.dispatchNativeFieldEvent(t,`change`)}function oe(e){e.stopPropagation();let t=e.detail?.value;t!==void 0&&(R.remove(t),V(),w(`change`))}function se(){if(!D()){let e=L.value.find(e=>e.value===M.value);j=!0,d.value=e?.label??``,Promise.resolve().then(()=>{j=!1});return}d.value=``}c(()=>{if(E.value&&!D()&&M.value&&T.value===-1&&d.value===``){let e=y.value.findIndex(e=>e.value===M.value);e>=0&&b.set(e)}});function H(e=!0,t=`programmatic`){if(e&&(A=d.value,d.value=``),!D()&&M.value){let e=s.filterOptions(L.value,``,k()).findIndex(e=>e.value===M.value);e>=0&&b.set(e)}b.open(t),!D()&&M.value&&T.value>=0&&requestAnimationFrame(()=>{te()})}function U(e=`programmatic`){b.close(e)}let ce=r.createInteraction({disabled:x,onPress:()=>{E.value||H(!0,`click`),N()}}),le=r.createInteraction({disabled:x,keys:[`Enter`],onPress:e=>{let t=y.value;E.value&&T.value>=0&&T.value<t.length?W(t[T.value],e):E.value&&T.value===-1&&B.value?Y(d.value,e):E.value||H(!0,`keyboard`)}});function W(t,n){t.disabled||(D()?(R.toggle(t.value),d.value=``,V(),w(`change`),e.autoclose.value&&U(),N(),requestAnimationFrame(()=>N())):(R.select(t.value),d.value=t.label,V(),w(`change`),U(),N()))}function G(e){let t=e.getAttribute(`data-option-index`),n=t?Number(t):-1;if(Number.isInteger(n)&&n>=0&&n<y.value.length)return y.value[n]??null;let r=e.getAttribute(`data-option-value`);if(r){let e=y.value.find(e=>e.value===r);if(e)return e}let i=e.querySelector(`span`)?.textContent?.trim()??e.textContent?.trim()??``;return i?y.value.find(e=>e.label===i||e.value===i)??null:null}function ue(e){e.stopPropagation(),R.clear(),d.value=``,V(),w(`change`),N()}function K(e){let t=e.target,r=t.value;if(!j&&r!==d.value){if(d.value=r,!D()){let e=C.value[0],t=e?L.value.find(t=>t.value===e)?.label??e:``;r===``&&A===t&&(A=null)}b.navigate(`first`),E.value||H(!1,`keyboard`),n(`search`,{query:t.value})}}function q(){}function J(e){if(!x.value&&!b.handleKeydown(e))switch(e.key){case`ArrowDown`:e.preventDefault(),E.value?b.navigate(`next`):(H(!0,`keyboard`),b.navigate(`first`));break;case`ArrowUp`:e.preventDefault(),E.value?b.navigate(`prev`):H(!0,`keyboard`);break;case`Backspace`:D()&&!d.value&&C.value.length>0&&(v.removeValue(C.value[C.value.length-1]??``),V(),w(`change`));break;case`Enter`:le.handleKeydown(e);break;case`Tab`:U(`programmatic`)}}function Y(e,t){let n=e.trim();if(!n)return;let r={disabled:!1,iconEl:null,label:n,value:s.makeCreatableValue(n)};F.value=[...F.value,r],W(r,t)}let de=(()=>{let e=new MutationObserver(()=>{z()});return e.observe(t,{attributeFilter:[`disabled`,`disabled-reason`,`label`,`value`],attributes:!0,childList:!0,subtree:!0}),()=>e.disconnect()})(),X=e=>{let t=e=>{let t=e.target;if(!(t instanceof Element))return;if(t.closest(`.no-results-create`)){e.preventDefault(),e.stopPropagation(),Y(d.value,e);return}let n=t.closest(`.option`);if(!n)return;e.preventDefault(),e.stopPropagation();let r=G(n);r&&!r.disabled&&W(r,e)},n=e=>{let t=e.target;if(!(t instanceof Element))return;let n=t.closest(`.option`);if(!n)return;let r=G(n);if(!r)return;let i=y.value.findIndex(e=>e.value===r.value);i>=0&&b.set(i)};return e.addEventListener(`click`,t),e.addEventListener(`pointermove`,n),()=>{e.removeEventListener(`click`,t),e.removeEventListener(`pointermove`,n)}},Z=null,Q=null,fe=e=>{h=e,Q!==e&&(Z?.(),Z=null,Q=null,e&&(Z=X(e),Q=e))},pe=()=>{h&&(Q===h&&Z||(Z?.(),Z=X(h),Q=h))};c(()=>{pe(),E.value?(m&&`showPopover`in m&&!m.matches(`:popover-open`)&&m.showPopover(),ne()):m&&`hidePopover`in m&&m.matches(`:popover-open`)&&m.hidePopover()}),(0,l.onElement)(g,e=>{p=e;let t=e.shadowRoot?.querySelector(`input`)??null;if(!t)return;f=t,t.setAttribute(`role`,`combobox`),t.setAttribute(`autocomplete`,`off`),t.setAttribute(`aria-autocomplete`,`list`),t.setAttribute(`aria-haspopup`,`listbox`),t.setAttribute(`spellcheck`,`false`),t.setAttribute(`aria-controls`,`${S}-listbox`);let n=()=>{E.value||H(!0,`click`),N()};return t.addEventListener(`input`,K),t.addEventListener(`keydown`,J),t.addEventListener(`focus`,q),t.addEventListener(`click`,n),()=>{f=null,p=null,t.removeEventListener(`input`,K),t.removeEventListener(`keydown`,J),t.removeEventListener(`focus`,q),t.removeEventListener(`click`,n)}}),c(()=>{if(!g.value)return;let t=f;t&&(t.setAttribute(`aria-expanded`,String(E.value)),x.value?t.setAttribute(`aria-disabled`,`true`):t.removeAttribute(`aria-disabled`),e.error.value?(t.setAttribute(`aria-invalid`,`true`),t.setAttribute(`aria-errormessage`,`${S}-error`)):(t.removeAttribute(`aria-invalid`),t.removeAttribute(`aria-errormessage`)))}),c(()=>{if(!g.value)return;let e=f;e&&e.value!==d.value&&(e.value=d.value)}),(0,l.onCleanup)(()=>{Z?.(),Z=null,Q=null,de()});let $=()=>e[`hide-label`].value;return l.html`
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/shape.css.cjs"),n=require("./styles/mixins/theme.css.cjs"),r=require("./core/keyboard.cjs"),i=require("./core/choice-field.cjs"),a=require("./core/ore.cjs"),ee=require("./core/option-list.cjs"),o=require("./inputs/shared/native-field-event.cjs"),s=require("./inputs/combobox/combobox-options.cjs"),c=require("./inputs/combobox/combobox.css.cjs");let l=require("@vielzeug/ore"),u=require("@vielzeug/ripple");var d=`ore-combobox-option`;(0,l.define)(d,{setup(){return l.html``}});var f=`ore-combobox`;(0,l.define)(f,{formAssociated:!0,props:{autoclose:l.prop.bool(!1),color:l.prop.string(),creatable:l.prop.bool(!1),disabled:l.prop.bool(!1),error:l.prop.string(),fullwidth:l.prop.bool(!1),helper:l.prop.string(),"hide-label":l.prop.bool(!1),label:l.prop.string(),"label-placement":l.prop.oneOf([`inset`,`outside`],`inset`),loading:l.prop.bool(!1),multiple:l.prop.bool(!1),name:l.prop.string(),"no-filter":l.prop.bool(!1),options:l.prop.data(),placeholder:l.prop.string(`Select...`),required:l.prop.bool(!1),rounded:l.prop.string(),size:l.prop.string(),success:l.prop.bool(!1),value:l.prop.string(),variant:l.prop.string()},setup(e){let t=(0,l.getHost)(),n=(0,l.useEmit)(),c=l.watchEffect,d=(0,u.signal)(``),f=null,p=null,m=null,h=null,g=(0,l.ref)(),_=a.lifecycleSignal(l.onCleanup),v=i.createChoiceField({disabled:e.disabled,error:e.error,helper:e.helper,label:e.label,labelPlacement:e[`label-placement`],multiple:e.multiple,prefix:`combobox`,required:e.required,signal:_,value:e.value}),y=(0,u.signal)([]),b=ee.createListboxDropdown({getBoundary:()=>t,getFocusedOptionElement:()=>m?.querySelector(`[data-focused]`)??null,getItems:()=>y.value,getOptionId:e=>`${v.fieldId}-opt-${e}`,getPanel:()=>m,getReference:()=>p,getTrigger:()=>f,isDisabled:()=>v.disabled.value,isItemDisabled:e=>e.disabled,onClose:e=>{n(`open-change`,{open:!1,reason:e}),_.aborted||se(),v.triggerValidation(`blur`)},onOpen:e=>n(`open-change`,{open:!0,reason:e}),restoreFocus:!1,signal:_}),{disabled:x,fieldId:S,selectedValues:C,triggerValidation:w}=v;v.attachFormField((0,l.useField)({disabled:v.disabled,onReset:v.reset,toFormValue:e=>e,validationMessage:v.validationMessage,validity:v.validity,value:v.formValue}));let{focusedIndex:T,isOpen:E,scrollFocusedIntoView:te,updatePosition:ne}=b,D=()=>!!e.multiple.value,O=()=>!!e.creatable.value,k=()=>!!e[`no-filter`].value;(0,l.bind)({attr:{open:()=>E.value?!0:void 0,size:e.size,variant:e.variant}});let A=null,j=!1,M=(0,u.computed)(()=>C.value[0]??``);Object.defineProperty(t,"value",{configurable:!0,get:()=>v.formValue.value,set:e=>{let t=e;if(Array.isArray(t)){v.setValues(t.map(e=>String(e??``)));return}if(t==null||t===``){v.clear();return}v.setValues(D()?String(t).split(`,`):[String(t)])}});let re=()=>C.value.length>0;function N(){f?.focus()}let P=(0,u.signal)([]),F=(0,u.signal)([]),ie=()=>!!e.loading.value;function I(e){return{disabled:!!e.disabled,disabledReason:e.disabledReason,iconEl:e.iconEl??null,label:e.label??e.value,value:e.value}}let L=(0,u.computed)(()=>{let t=e.options.value,n=Array.isArray(t)?t.map(I):P.value;return F.value.length===0?n:[...n,...F.value]}),R={clear:()=>{v.clear()},remove:e=>{v.removeValue(e)},select:e=>{v.selectValue(e)},toggle:e=>{v.toggleValue(e)}};function z(e=Array.from(t.children)){if(P.value=s.parseSlottedOptions(e),!D()){let e=L.value.find(e=>e.value===M.value);d.value=e?.label??M.value}}z(),c(()=>{let e=s.filterOptions(L.value,d.value,k());y.value=D()?e.filter(e=>!C.value.includes(e.value)):e});let B=(0,u.computed)(()=>s.getCreatableLabel(d.value,O(),y.value)),ae=()=>D()&&C.value.length>0?``:e.placeholder.value||``;function V(){o.dispatchNativeFieldEvent(t,`input`),o.dispatchNativeFieldEvent(t,`change`)}function oe(e){e.stopPropagation();let t=e.detail?.value;t!==void 0&&(R.remove(t),V(),w(`change`))}function se(){if(!D()){let e=L.value.find(e=>e.value===M.value);j=!0,d.value=e?.label??``,Promise.resolve().then(()=>{j=!1});return}d.value=``}c(()=>{if(E.value&&!D()&&M.value&&T.value===-1&&d.value===``){let e=y.value.findIndex(e=>e.value===M.value);e>=0&&b.set(e)}});function H(e=!0,t=`programmatic`){if(e&&(A=d.value,d.value=``),!D()&&M.value){let e=s.filterOptions(L.value,``,k()).findIndex(e=>e.value===M.value);e>=0&&b.set(e)}b.open(t),!D()&&M.value&&T.value>=0&&requestAnimationFrame(()=>{te()})}function U(e=`programmatic`){b.close(e)}let ce=r.createInteraction({disabled:x,onPress:()=>{E.value||H(!0,`click`),N()}}),le=r.createInteraction({disabled:x,keys:[`Enter`],onPress:e=>{let t=y.value;E.value&&T.value>=0&&T.value<t.length?W(t[T.value],e):E.value&&T.value===-1&&B.value?Y(d.value,e):E.value||H(!0,`keyboard`)}});function W(t,n){t.disabled||(D()?(R.toggle(t.value),d.value=``,V(),w(`change`),e.autoclose.value&&U(),N(),requestAnimationFrame(()=>N())):(R.select(t.value),d.value=t.label,V(),w(`change`),U(),N()))}function G(e){let t=e.getAttribute(`data-option-index`),n=t?Number(t):-1;if(Number.isInteger(n)&&n>=0&&n<y.value.length)return y.value[n]??null;let r=e.getAttribute(`data-option-value`);if(r){let e=y.value.find(e=>e.value===r);if(e)return e}let i=e.querySelector(`span`)?.textContent?.trim()??e.textContent?.trim()??``;return i?y.value.find(e=>e.label===i||e.value===i)??null:null}function ue(e){e.stopPropagation(),R.clear(),d.value=``,V(),w(`change`),N()}function K(e){let t=e.target,r=t.value;if(!j&&r!==d.value){if(d.value=r,!D()){let e=C.value[0],t=e?L.value.find(t=>t.value===e)?.label??e:``;r===``&&A===t&&(A=null)}b.navigate(`first`),E.value||H(!1,`keyboard`),n(`search`,{query:t.value})}}function q(){}function J(e){if(!x.value&&!b.handleKeydown(e))switch(e.key){case`ArrowDown`:e.preventDefault(),E.value?b.navigate(`next`):(H(!0,`keyboard`),b.navigate(`first`));break;case`ArrowUp`:e.preventDefault(),E.value?b.navigate(`prev`):H(!0,`keyboard`);break;case`Backspace`:D()&&!d.value&&C.value.length>0&&(v.removeValue(C.value[C.value.length-1]??``),V(),w(`change`));break;case`Enter`:le.handleKeydown(e);break;case`Tab`:U(`programmatic`)}}function Y(e,t){let n=e.trim();if(!n)return;let r={disabled:!1,iconEl:null,label:n,value:s.makeCreatableValue(n)};F.value=[...F.value,r],W(r,t)}let de=(()=>{let e=new MutationObserver(()=>{z()});return e.observe(t,{attributeFilter:[`disabled`,`disabled-reason`,`label`,`value`],attributes:!0,childList:!0,subtree:!0}),()=>e.disconnect()})(),X=e=>{let t=e=>{let t=e.target;if(!(t instanceof Element))return;if(t.closest(`.no-results-create`)){e.preventDefault(),e.stopPropagation(),Y(d.value,e);return}let n=t.closest(`.option`);if(!n)return;e.preventDefault(),e.stopPropagation();let r=G(n);r&&!r.disabled&&W(r,e)},n=e=>{let t=e.target;if(!(t instanceof Element))return;let n=t.closest(`.option`);if(!n)return;let r=G(n);if(!r)return;let i=y.value.findIndex(e=>e.value===r.value);i>=0&&b.set(i)};return e.addEventListener(`click`,t),e.addEventListener(`pointermove`,n),()=>{e.removeEventListener(`click`,t),e.removeEventListener(`pointermove`,n)}},Z=null,Q=null,fe=e=>{h=e,Q!==e&&(Z?.(),Z=null,Q=null,e&&(Z=X(e),Q=e))},pe=()=>{h&&(Q===h&&Z||(Z?.(),Z=X(h),Q=h))};c(()=>{pe(),E.value?(m&&`showPopover`in m&&!m.matches(`:popover-open`)&&m.showPopover(),ne()):m&&`hidePopover`in m&&m.matches(`:popover-open`)&&m.hidePopover()}),(0,l.onElement)(g,e=>{p=e;let t=e.shadowRoot?.querySelector(`input`)??null;if(!t)return;f=t,t.setAttribute(`role`,`combobox`),t.setAttribute(`autocomplete`,`off`),t.setAttribute(`aria-autocomplete`,`list`),t.setAttribute(`aria-haspopup`,`listbox`),t.setAttribute(`spellcheck`,`false`),t.setAttribute(`aria-controls`,`${S}-listbox`);let n=()=>{E.value||H(!0,`click`),N()};return t.addEventListener(`input`,K),t.addEventListener(`keydown`,J),t.addEventListener(`focus`,q),t.addEventListener(`click`,n),()=>{f=null,p=null,t.removeEventListener(`input`,K),t.removeEventListener(`keydown`,J),t.removeEventListener(`focus`,q),t.removeEventListener(`click`,n)}}),c(()=>{if(!g.value)return;let t=f;t&&(t.setAttribute(`aria-expanded`,String(E.value)),x.value?t.setAttribute(`aria-disabled`,`true`):t.removeAttribute(`aria-disabled`),e.error.value?(t.setAttribute(`aria-invalid`,`true`),t.setAttribute(`aria-errormessage`,`${S}-error`)):(t.removeAttribute(`aria-invalid`),t.removeAttribute(`aria-errormessage`)))}),c(()=>{if(!g.value)return;let e=f;e&&e.value!==d.value&&(e.value=d.value)}),(0,l.onCleanup)(()=>{Z?.(),Z=null,Q=null,de()});let $=()=>e[`hide-label`].value;return l.html`
|
|
2
2
|
<slot></slot>
|
|
3
3
|
<ore-input
|
|
4
4
|
class="trigger"
|
|
@@ -107,5 +107,5 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
107
107
|
`):``}
|
|
108
108
|
</div>
|
|
109
109
|
</div>
|
|
110
|
-
`},shadow:{delegatesFocus:!0},styles:[n.colorThemeMixin,e.reducedMotionMixin,t.roundedVariantMixin,e.srOnlyMixin,c.default]}),exports.COMBOBOX_TAG=
|
|
110
|
+
`},shadow:{delegatesFocus:!0},styles:[n.colorThemeMixin,e.reducedMotionMixin,t.roundedVariantMixin,e.srOnlyMixin,c.default]}),exports.COMBOBOX_OPTION_TAG=d,exports.COMBOBOX_TAG=f;
|
|
111
111
|
//# sourceMappingURL=combobox.cjs.map
|
package/dist/combobox.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.cjs","names":[],"sources":["../src/inputs/combobox/combobox.ts"],"sourcesContent":["import {\n bind,\n define,\n getHost,\n html,\n onCleanup,\n onElement,\n prop,\n ref,\n useEmit,\n useField,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport {\n createChoiceField,\n createInteraction,\n createListboxDropdown,\n type DropdownCloseReason,\n lifecycleSignal,\n type OverlayOpenReason,\n} from '../../core';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin, srOnlyMixin } from '../../styles';\nimport type { AddEventListeners, ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport { dispatchNativeFieldEvent } from '../shared/native-field-event';\nimport type { ComboboxOptionInput, ComboboxOptionItem, OreComboboxEvents, OreComboboxProps } from './combobox.types';\nimport { filterOptions, getCreatableLabel, makeCreatableValue, parseSlottedOptions } from './combobox-options';\nimport '../../feedback/chip/chip';\nimport '../input/input';\nimport componentStyles from './combobox.css?inline';\n\nexport type { OreComboboxEvents, OreComboboxProps } from './combobox.types';\n\n/**\n * A searchable select field with multiple selection, custom option creation, and large-list support.\n *\n * @element ore-combobox\n *\n * @attr {string} value - Selected value(s). Use comma-separated for multiple.\n * @attr {boolean} multiple - Enable multiple selection\n * @attr {boolean} creatable - Allow users to create custom options from search query\n * @attr {boolean} no-filter - Disable client-side filtering (useful for server-side search)\n * @attr {boolean} hide-label - Hide the visible label while retaining its accessible name\n * @attr {string} placeholder - Placeholder text\n * @attr {boolean} required - Require a non-blank selection for native form validation\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n *\n * @fires input - Emitted when the selection changes.\n * @fires change - Emitted when the selection changes.\n * @fires open-change - Emitted when the dropdown state changes. detail: { open, reason }\n * @fires {CustomEvent} search - Emitted when user types. detail: { query: string }\n *\n * @slot - Slotted combobox options and option groups\n * @cssprop --combobox-dropdown-bg - Dropdown panel background color\n * @cssprop --combobox-dropdown-border-color - Dropdown panel border color\n * @cssprop --combobox-option-hover-bg - Option background on hover\n * @cssprop --combobox-option-focus-bg - Option background when keyboard-focused\n * @cssprop --combobox-option-selected-bg - Option background when selected\n * @cssprop --combobox-option-selected-focus-bg - Option background when selected and focused\n * @cssprop --input-bg - Field background (passed through to ore-input)\n * @cssprop --input-border-color - Field border color (passed through to ore-input)\n *\n * @part wrapper - Root wrapper around the entire field\n * @part label - Label element shown inside or outside the field\n * @part field - Field container that holds the trigger input and clear button\n * @part input - Search input used to filter and select options\n * @part clear-btn - Button that clears the current selection/query\n * @part dropdown - Popup list container for options\n * @part helper-text - Helper text displayed below the field\n * @example\n * ```html\n * <ore-combobox label=\"Country\" name=\"country\">\n * <ore-combobox-option value=\"us\">United States</ore-combobox-option>\n * <ore-combobox-option value=\"gb\">United Kingdom</ore-combobox-option>\n * <ore-combobox-option value=\"de\" disabled>Germany</ore-combobox-option>\n * </ore-combobox>\n * ```\n */\nexport const COMBOBOX_TAG = 'ore-combobox' as const;\ndefine<OreComboboxProps>(COMBOBOX_TAG, {\n formAssociated: true,\n props: {\n autoclose: prop.bool(false),\n color: prop.string<ThemeColor>(),\n creatable: prop.bool(false),\n disabled: prop.bool(false),\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n 'hide-label': prop.bool(false),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n loading: prop.bool(false),\n multiple: prop.bool(false),\n name: prop.string(),\n 'no-filter': prop.bool(false),\n options: prop.data<ComboboxOptionInput[]>(),\n placeholder: prop.string('Select...'),\n required: prop.bool(false),\n rounded: prop.string<RoundedSize>(),\n size: prop.string<ComponentSize>(),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreComboboxEvents>();\n const watch = watchEffect;\n\n const query = signal('');\n\n // Element refs needed by the listbox dropdown.\n let inputEl: HTMLInputElement | null = null;\n let fieldEl: HTMLElement | null = null; // set to the ore-input host once it mounts\n let dropdownEl: HTMLElement | null = null;\n let listboxEl: HTMLElement | null = null;\n\n // Ref to the ore-input host; resolved when the template renders.\n const bitInputRef = ref<HTMLElement>();\n\n const abortSignal = lifecycleSignal(onCleanup);\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n label: props.label,\n labelPlacement: props['label-placement'],\n multiple: props.multiple,\n prefix: 'combobox',\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n // filteredOptions signal declared before optionList so the getItems getter\n // captures the live signal reference rather than needing a factory indirection.\n const filteredOptions = signal<ComboboxOptionItem[]>([]);\n\n const optionList = createListboxDropdown<ComboboxOptionItem>({\n getBoundary: () => el,\n getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n getItems: () => filteredOptions.value,\n getOptionId: (index) => `${choice.fieldId}-opt-${index}`,\n getPanel: () => dropdownEl,\n getReference: () => fieldEl,\n getTrigger: () => inputEl,\n isDisabled: () => choice.disabled.value,\n isItemDisabled: (option) => option.disabled,\n onClose: (reason) => {\n emit('open-change', { open: false, reason });\n\n if (!abortSignal.aborted) restoreQueryFromSelection();\n\n choice.triggerValidation('blur');\n },\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n restoreFocus: false,\n signal: abortSignal,\n });\n\n const { disabled: isDisabled, fieldId: comboId, selectedValues, triggerValidation } = choice;\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const { focusedIndex, isOpen, scrollFocusedIntoView, updatePosition } = optionList;\n // ── State ────────────────────────────────────────────────────────────────\n const isMultiple = () => Boolean(props.multiple.value);\n const isCreatable = () => Boolean(props.creatable.value);\n const isNoFilter = () => Boolean(props['no-filter'].value);\n\n bind({\n attr: {\n open: () => (isOpen.value ? true : undefined),\n size: props.size,\n variant: props.variant,\n },\n });\n\n let lastQueryBeforeClear: string | null = null;\n let isRestoringQuery = false;\n\n const selectedValue = computed(() => selectedValues.value[0] ?? '');\n\n // Expose a native-like, string-valued `.value` property on the host.\n Object.defineProperty(el, 'value', {\n configurable: true,\n get: () => choice.formValue.value,\n set: (val: unknown) => {\n const v = val as string | string[] | null | undefined;\n\n if (Array.isArray(v)) {\n choice.setValues(v.map((entry) => String(entry ?? '')));\n\n return;\n }\n\n if (v == null || v === '') {\n choice.clear();\n\n return;\n }\n\n choice.setValues(isMultiple() ? String(v).split(',') : [String(v)]);\n },\n });\n\n const hasValue = () => selectedValues.value.length > 0;\n\n function focusLiveInput() {\n inputEl?.focus();\n }\n\n // ── Options ──────────────────────────────────────────────────────────────\n const slottedOptions = signal<ComboboxOptionItem[]>([]);\n const createdOptions = signal<ComboboxOptionItem[]>([]);\n const isLoading = () => Boolean(props.loading.value);\n\n function normalizeOption(option: ComboboxOptionInput): ComboboxOptionItem {\n return {\n disabled: Boolean(option.disabled),\n disabledReason: option.disabledReason,\n iconEl: option.iconEl ?? null,\n label: option.label ?? option.value,\n value: option.value,\n };\n }\n\n // Merged options: explicit prop value overrides slotted options.\n const allOptions = computed<ComboboxOptionItem[]>(() => {\n const optionsProp = props.options.value;\n const base = Array.isArray(optionsProp) ? optionsProp.map(normalizeOption) : slottedOptions.value;\n\n if (createdOptions.value.length === 0) return base;\n\n return [...base, ...createdOptions.value];\n });\n\n const selectionController = {\n clear: () => {\n choice.clear();\n },\n remove: (key: string) => {\n choice.removeValue(key);\n },\n select: (key: string) => {\n choice.selectValue(key);\n },\n toggle: (key: string) => {\n choice.toggleValue(key);\n },\n };\n\n function readOptions(elements: Element[] = Array.from(el.children)) {\n slottedOptions.value = parseSlottedOptions(elements);\n\n if (!isMultiple()) {\n const match = allOptions.value.find((option) => option.value === selectedValue.value);\n\n query.value = match?.label ?? selectedValue.value;\n }\n }\n\n // Initialize from light DOM immediately; onMounted/observer keep this in sync afterwards.\n readOptions();\n\n watch(() => {\n const nextOptions = filterOptions(allOptions.value, query.value, isNoFilter());\n\n filteredOptions.value = isMultiple()\n ? nextOptions.filter((option) => !selectedValues.value.includes(option.value))\n : nextOptions;\n });\n\n // \"Create\" option shown when creatable + query doesn't match any existing option\n const creatableLabel = computed(() => {\n return getCreatableLabel(query.value, isCreatable(), filteredOptions.value);\n });\n const inputPlaceholder = () =>\n isMultiple() && selectedValues.value.length > 0 ? '' : props.placeholder.value || '';\n\n function emitChange() {\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n }\n\n function removeChip(event: Event): void {\n event.stopPropagation();\n\n const value = (event as CustomEvent<{ value?: string }>).detail?.value;\n\n if (value === undefined) return;\n\n selectionController.remove(value);\n emitChange();\n triggerValidation('change');\n }\n\n function restoreQueryFromSelection() {\n // Keep input text and selected value in sync whenever the popup closes.\n if (!isMultiple()) {\n const match = allOptions.value.find((option) => option.value === selectedValue.value);\n\n isRestoringQuery = true;\n query.value = match?.label ?? '';\n Promise.resolve().then(() => {\n isRestoringQuery = false;\n });\n\n return;\n }\n\n query.value = '';\n }\n\n watch(() => {\n if (isOpen.value && !isMultiple() && selectedValue.value && focusedIndex.value === -1 && query.value === '') {\n const selectedIndex = filteredOptions.value.findIndex((option) => option.value === selectedValue.value);\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n }\n }\n });\n\n // ── Open / Close ─────────────────────────────────────────────────────────\n function openPopup(clearFilter = true, reason: OverlayOpenReason = 'programmatic') {\n if (clearFilter) {\n lastQueryBeforeClear = query.value;\n query.value = '';\n }\n\n // Pre-compute focused index BEFORE opening so the first render has it set\n if (!isMultiple() && selectedValue.value) {\n const freshOptions = filterOptions(allOptions.value, '', isNoFilter());\n const selectedIndex = freshOptions.findIndex((option) => option.value === selectedValue.value);\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n }\n }\n\n optionList.open(reason);\n\n if (!isMultiple() && selectedValue.value && focusedIndex.value >= 0) {\n requestAnimationFrame(() => {\n scrollFocusedIntoView();\n });\n }\n }\n\n function closePopup(reason: DropdownCloseReason = 'programmatic') {\n optionList.close(reason);\n }\n\n const fieldPress = createInteraction({\n disabled: isDisabled,\n onPress: () => {\n if (!isOpen.value) openPopup(true, 'click');\n\n focusLiveInput();\n },\n });\n\n const enterPress = createInteraction({\n disabled: isDisabled,\n keys: ['Enter'],\n onPress: (originalEvent: Event) => {\n const opts = filteredOptions.value;\n\n if (isOpen.value && focusedIndex.value >= 0 && focusedIndex.value < opts.length) {\n selectOption(opts[focusedIndex.value], originalEvent);\n } else if (isOpen.value && focusedIndex.value === -1 && creatableLabel.value) {\n // Focused on the \"create\" item\n createOption(query.value, originalEvent);\n } else if (!isOpen.value) {\n openPopup(true, 'keyboard');\n }\n },\n });\n\n // ── Selection ────────────────────────────────────────────────────────────\n function selectOption(opt: ComboboxOptionItem, _originalEvent?: Event) {\n if (opt.disabled) return;\n\n if (isMultiple()) {\n selectionController.toggle(opt.value);\n query.value = '';\n emitChange();\n triggerValidation('change');\n\n if (props.autoclose.value) {\n closePopup();\n }\n\n // Keep dropdown open in multiple mode (unless autoclose is true)\n focusLiveInput();\n requestAnimationFrame(() => focusLiveInput());\n } else {\n selectionController.select(opt.value);\n query.value = opt.label;\n emitChange();\n triggerValidation('change');\n closePopup();\n focusLiveInput();\n }\n }\n function resolveOptionFromElement(optionEl: HTMLElement): ComboboxOptionItem | null {\n const indexAttr = optionEl.getAttribute('data-option-index');\n const index = indexAttr ? Number(indexAttr) : -1;\n\n if (Number.isInteger(index) && index >= 0 && index < filteredOptions.value.length) {\n return filteredOptions.value[index] ?? null;\n }\n\n const valueAttr = optionEl.getAttribute('data-option-value');\n\n if (valueAttr) {\n const byValue = filteredOptions.value.find((option) => option.value === valueAttr);\n\n if (byValue) return byValue;\n }\n\n const labelText = optionEl.querySelector('span')?.textContent?.trim() ?? optionEl.textContent?.trim() ?? '';\n\n if (!labelText) return null;\n\n return filteredOptions.value.find((option) => option.label === labelText || option.value === labelText) ?? null;\n }\n function clearValue(e: Event) {\n e.stopPropagation();\n selectionController.clear();\n query.value = '';\n emitChange();\n triggerValidation('change');\n focusLiveInput();\n }\n function handleInput(e: InputEvent) {\n const target = e.target as HTMLInputElement;\n const newValue = target.value;\n\n // Skip all input processing if we're in the middle of restoring the query\n // This prevents the clearing logic from firing during close/restore\n if (isRestoringQuery) {\n return;\n }\n\n if (newValue === query.value) return;\n\n query.value = newValue;\n\n if (!isMultiple()) {\n const currentItem = selectedValues.value[0];\n const currentLabel = currentItem\n ? (allOptions.value.find((o) => o.value === currentItem)?.label ?? currentItem)\n : '';\n\n // Preserve the current selection while typing. Selection should only\n // change when a new option is committed or when the user explicitly clears.\n const isJustOpening = newValue === '' && lastQueryBeforeClear === currentLabel;\n\n if (isJustOpening) {\n lastQueryBeforeClear = null;\n }\n }\n\n optionList.navigate('first');\n\n if (!isOpen.value) openPopup(false, 'keyboard');\n\n emit('search', { query: target.value });\n }\n function handleFocus() {\n // Intentionally no-op: open only on explicit click or keyboard.\n // Opening on every focus surprises users tabbing through a form.\n }\n\n // ── Keyboard Navigation ──────────────────────────────────────────────────\n function handleKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n if (optionList.handleKeydown(e)) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n\n if (!isOpen.value) {\n openPopup(true, 'keyboard');\n optionList.navigate('first');\n } else {\n optionList.navigate('next');\n }\n\n break;\n case 'ArrowUp':\n e.preventDefault();\n\n if (!isOpen.value) {\n openPopup(true, 'keyboard');\n } else {\n optionList.navigate('prev');\n }\n\n break;\n case 'Backspace':\n // In multiple mode, remove the last chip when the input is empty\n if (isMultiple() && !query.value && selectedValues.value.length > 0) {\n choice.removeValue(selectedValues.value[selectedValues.value.length - 1] ?? '');\n emitChange();\n triggerValidation('change');\n }\n\n break;\n case 'Enter':\n enterPress.handleKeydown(e);\n\n break;\n case 'Tab':\n closePopup('programmatic');\n break;\n default:\n break;\n }\n }\n\n // ── Create option ────────────────────────────────────────────────────────\n function createOption(rawQuery: string, originalEvent?: Event) {\n const actualLabel = rawQuery.trim();\n\n if (!actualLabel) return;\n\n const value = makeCreatableValue(actualLabel);\n const newOpt: ComboboxOptionItem = { disabled: false, iconEl: null, label: actualLabel, value };\n\n createdOptions.value = [...createdOptions.value, newOpt];\n selectOption(newOpt, originalEvent);\n }\n // ── Lifecycle ────────────────────────────────────────────────────────────\n\n const observeLightDomOptions = (): (() => void) => {\n const observer = new MutationObserver(() => {\n readOptions();\n });\n\n observer.observe(el, {\n attributeFilter: ['disabled', 'disabled-reason', 'label', 'value'],\n attributes: true,\n childList: true,\n subtree: true,\n });\n\n return () => observer.disconnect();\n };\n\n const stopObserving = observeLightDomOptions();\n\n const createListboxListeners = (listEl: HTMLElement): (() => void) => {\n const handleActivate = (event: Event) => {\n const target = event.target;\n\n if (!(target instanceof Element)) return;\n\n const createRow = target.closest<HTMLElement>('.no-results-create');\n\n if (createRow) {\n event.preventDefault();\n event.stopPropagation();\n createOption(query.value, event);\n\n return;\n }\n\n const optionEl = target.closest<HTMLElement>('.option');\n\n if (!optionEl) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n const option = resolveOptionFromElement(optionEl);\n\n if (!option || option.disabled) return;\n\n selectOption(option, event);\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n const target = event.target;\n\n if (!(target instanceof Element)) return;\n\n const optionEl = target.closest<HTMLElement>('.option');\n\n if (!optionEl) return;\n\n const option = resolveOptionFromElement(optionEl);\n\n if (!option) return;\n\n const focusedIdx = filteredOptions.value.findIndex((candidate) => candidate.value === option.value);\n\n if (focusedIdx >= 0) {\n optionList.set(focusedIdx);\n }\n };\n\n listEl.addEventListener('click', handleActivate);\n listEl.addEventListener('pointermove', handlePointerMove);\n\n return () => {\n listEl.removeEventListener('click', handleActivate);\n listEl.removeEventListener('pointermove', handlePointerMove);\n };\n };\n\n let stopListboxListeners: (() => void) | null = null;\n let listboxListenersTarget: HTMLElement | null = null;\n\n const setListboxElement = (el: HTMLElement | null): void => {\n listboxEl = el;\n\n if (listboxListenersTarget === el) return;\n\n stopListboxListeners?.();\n stopListboxListeners = null;\n listboxListenersTarget = null;\n\n if (!el) return;\n\n stopListboxListeners = createListboxListeners(el);\n listboxListenersTarget = el;\n };\n\n const ensureListboxListeners = (): void => {\n if (!listboxEl) return;\n\n if (listboxListenersTarget === listboxEl && stopListboxListeners) return;\n\n stopListboxListeners?.();\n stopListboxListeners = createListboxListeners(listboxEl);\n listboxListenersTarget = listboxEl;\n };\n\n watch(() => {\n ensureListboxListeners();\n\n if (isOpen.value) {\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n\n updatePosition();\n } else {\n if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n }\n });\n\n // Once ore-input is in the DOM, grab its inner <input> from its shadow root\n // and attach all combobox-specific ARIA + event handlers imperatively.\n // MUST be registered before the ARIA effects below so inputEl is set first\n // when bitInputRef fires (effects run in registration order).\n onElement(bitInputRef, (bitInputEl) => {\n fieldEl = bitInputEl;\n\n const rawInput = bitInputEl.shadowRoot?.querySelector<HTMLInputElement>('input') ?? null;\n\n if (!rawInput) return;\n\n inputEl = rawInput;\n\n rawInput.setAttribute('role', 'combobox');\n rawInput.setAttribute('autocomplete', 'off');\n rawInput.setAttribute('aria-autocomplete', 'list');\n rawInput.setAttribute('aria-haspopup', 'listbox');\n rawInput.setAttribute('spellcheck', 'false');\n rawInput.setAttribute('aria-controls', `${comboId}-listbox`);\n\n const handleInputClick = (): void => {\n if (!isOpen.value) openPopup(true, 'click');\n\n focusLiveInput();\n };\n\n rawInput.addEventListener('input', handleInput as EventListener);\n rawInput.addEventListener('keydown', handleKeydown as EventListener);\n rawInput.addEventListener('focus', handleFocus);\n rawInput.addEventListener('click', handleInputClick);\n\n return () => {\n inputEl = null;\n fieldEl = null;\n rawInput.removeEventListener('input', handleInput as EventListener);\n rawInput.removeEventListener('keydown', handleKeydown as EventListener);\n rawInput.removeEventListener('focus', handleFocus);\n rawInput.removeEventListener('click', handleInputClick);\n };\n });\n\n // Reactively sync combobox-specific ARIA attrs that ore-input doesn't manage.\n // Uses bitInputRef (a signal) as the gate so the effect re-runs when the\n // inner input mounts — inputEl is a plain variable and would not trigger re-runs.\n watch(() => {\n if (!bitInputRef.value) return;\n\n const el = inputEl;\n\n if (!el) return;\n\n el.setAttribute('aria-expanded', String(isOpen.value));\n\n if (isDisabled.value) {\n el.setAttribute('aria-disabled', 'true');\n } else {\n el.removeAttribute('aria-disabled');\n }\n\n if (props.error.value) {\n el.setAttribute('aria-invalid', 'true');\n el.setAttribute('aria-errormessage', `${comboId}-error`);\n } else {\n el.removeAttribute('aria-invalid');\n el.removeAttribute('aria-errormessage');\n }\n });\n\n // Reactively sync the query signal into the raw input value.\n watch(() => {\n if (!bitInputRef.value) return;\n\n const el = inputEl;\n\n if (!el) return;\n\n if (el.value !== query.value) el.value = query.value;\n });\n\n onCleanup(() => {\n stopListboxListeners?.();\n stopListboxListeners = null;\n listboxListenersTarget = null;\n stopObserving();\n });\n\n const hideLabel = () => props['hide-label'].value;\n const inputAriaLabel = () => (hideLabel() ? (props.label.value ?? '') : null);\n const inputLabel = () => (hideLabel() ? '' : (props.label.value ?? ''));\n const inputColor = () => props.color?.value ?? undefined;\n const inputSize = () => props.size?.value ?? undefined;\n const inputVariant = () => props.variant?.value ?? undefined;\n const inputRounded = () => props.rounded?.value ?? undefined;\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n return html`\n <slot></slot>\n <ore-input\n class=\"trigger\"\n ref=${bitInputRef}\n aria-label=\"${inputAriaLabel}\"\n label=\"${inputLabel}\"\n placeholder=\"${inputPlaceholder}\"\n label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n color=\"${inputColor}\"\n size=\"${inputSize}\"\n variant=\"${inputVariant}\"\n rounded=\"${inputRounded}\"\n helper=\"${() => props.helper.value ?? ''}\"\n error=\"${() => props.error.value ?? ''}\"\n ?disabled=\"${isDisabled}\"\n ?required=\"${() => false}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n name=\"${() => props.name.value ?? ''}\"\n @click=\"${(e: MouseEvent) => {\n fieldPress.handleClick(e);\n }}\"\n part=\"wrapper\">\n <div slot=\"prefix\" class=\"chips-row\">\n <!-- Keep chip list diffing isolated so input node identity stays stable. -->\n <span class=\"chips-list\">\n ${() =>\n (isMultiple() ? selectedValues.value : []).map(\n (value) => html`\n <ore-chip\n value=${value}\n label=${allOptions.value.find((option) => option.value === value)?.label ?? value}\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=\"${props.color}\"\n @remove=${removeChip}>\n ${allOptions.value.find((option) => option.value === value)?.label ?? value}\n </ore-chip>\n `,\n )}\n </span>\n </div>\n <span slot=\"suffix\" class=\"combobox-suffix\" aria-hidden=\"true\">\n <button\n class=\"clear-btn\"\n part=\"clear-btn\"\n type=\"button\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n ?hidden=${() => !hasValue()}\n @click=\"${clearValue}\">\n <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n <span class=\"combobox-suffix-end\">\n <span class=\"loader\"></span>\n <span class=\"chevron\">\n <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </span>\n </span>\n </ore-input>\n <span\n class=\"sr-only\"\n id=\"${() => `${comboId}-error`}\"\n role=\"alert\"\n aria-live=\"assertive\"\n ?hidden=\"${() => !props.error.value}\">\n ${() => props.error.value ?? ''}\n </span>\n <div\n class=\"dropdown\"\n part=\"dropdown\"\n id=\"${() => `${comboId}-dropdown`}\"\n popover=\"manual\"\n ?data-open=${() => isOpen.value}\n ref=${(el: HTMLElement | null) => {\n dropdownEl = el;\n }}>\n <div\n role=\"listbox\"\n id=\"${() => `${comboId}-listbox`}\"\n style=\"${() =>\n isOpen.value && filteredOptions.value.length > 0 ? `height:${filteredOptions.value.length * 36}px;` : ''}\"\n aria-label=\"${() => props.label.value || props.placeholder.value || 'Options'}\"\n ref=${(el: HTMLElement | null) => {\n setListboxElement(el);\n }}>\n ${() => {\n if (!isOpen.value) return '';\n\n if (isLoading()) {\n return html`\n <div class=\"dropdown-loading\">Loading...</div>\n `;\n }\n\n if (filteredOptions.value.length === 0) {\n if (creatableLabel.value) {\n return html`\n <button type=\"button\" class=\"no-results-create\" ?data-focused=${() => focusedIndex.value === -1}>\n ${creatableLabel.value}\n </button>\n `;\n }\n\n return html`\n <div class=\"no-results\" role=\"presentation\">No results found</div>\n `;\n }\n\n return filteredOptions.value.map((option, index) => {\n return html`\n <div\n class=\"option\"\n role=\"option\"\n id=\"${`${comboId}-opt-${index}`}\"\n data-option-index=\"${index}\"\n data-option-value=\"${option.value}\"\n aria-selected=\"${() =>\n String(\n isMultiple() ? selectedValues.value.includes(option.value) : selectedValue.value === option.value,\n )}\"\n aria-disabled=\"${String(option.disabled)}\"\n style=\"${`position:absolute;top:0;left:0;right:0;transform:translateY(${index * 36}px);`}\"\n ?data-focused=${() => focusedIndex.value === index}\n ?data-selected=${() =>\n isMultiple() ? selectedValues.value.includes(option.value) : selectedValue.value === option.value}\n ?data-disabled=${option.disabled}>\n <span>${option.label}</span>\n ${\n option.disabled && option.disabledReason\n ? html`<small class=\"disabled-reason\" title=\"${option.disabledReason}\">${option.disabledReason}</small>`\n : html``\n }\n <span class=\"option-check\" aria-hidden=\"true\">\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </span>\n </div>\n `;\n });\n }}\n </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, srOnlyMixin, componentStyles],\n}) as unknown as AddEventListeners<OreComboboxEvents>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"combobox.cjs","names":[],"sources":["../src/inputs/combobox/combobox.ts"],"sourcesContent":["import {\n bind,\n define,\n getHost,\n html,\n onCleanup,\n onElement,\n prop,\n ref,\n useEmit,\n useField,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport {\n createChoiceField,\n createInteraction,\n createListboxDropdown,\n type DropdownCloseReason,\n lifecycleSignal,\n type OverlayOpenReason,\n} from '../../core';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin, srOnlyMixin } from '../../styles';\nimport type { AddEventListeners, ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport { dispatchNativeFieldEvent } from '../shared/native-field-event';\nimport type {\n ComboboxOptionInput,\n ComboboxOptionItem,\n OreComboboxEvents,\n OreComboboxOptionProps,\n OreComboboxProps,\n} from './combobox.types';\nimport { filterOptions, getCreatableLabel, makeCreatableValue, parseSlottedOptions } from './combobox-options';\nimport '../../feedback/chip/chip';\nimport '../input/input';\nimport componentStyles from './combobox.css?inline';\n\nexport type {\n ComboboxOptionInput,\n OreComboboxEvents,\n OreComboboxOptionProps,\n OreComboboxProps,\n} from './combobox.types';\n\n/**\n * Declarative option data for `ore-combobox`.\n *\n * @element ore-combobox-option\n * @attr {string} value - Submitted option value\n * @attr {string} label - Label override; defaults to text content\n * @attr {boolean} disabled - Prevent selection\n * @attr {string} disabled-reason - Explanation shown for a disabled option\n * @slot icon - Leading option icon\n */\nexport const COMBOBOX_OPTION_TAG = 'ore-combobox-option' as const;\ndefine<OreComboboxOptionProps>(COMBOBOX_OPTION_TAG, {\n setup() {\n return html``;\n },\n});\n\n/**\n * A searchable select field with multiple selection, custom option creation, and large-list support.\n *\n * @element ore-combobox\n *\n * @attr {string} value - Selected value(s). Use comma-separated for multiple.\n * @attr {boolean} multiple - Enable multiple selection\n * @attr {boolean} creatable - Allow users to create custom options from search query\n * @attr {boolean} no-filter - Disable client-side filtering (useful for server-side search)\n * @attr {boolean} hide-label - Hide the visible label while retaining its accessible name\n * @attr {string} placeholder - Placeholder text\n * @attr {boolean} required - Require a non-blank selection for native form validation\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n *\n * @fires input - Emitted when the selection changes.\n * @fires change - Emitted when the selection changes.\n * @fires open-change - Emitted when the dropdown state changes. detail: { open, reason }\n * @fires {CustomEvent} search - Emitted when user types. detail: { query: string }\n *\n * @slot - Slotted combobox options and option groups\n * @cssprop --combobox-dropdown-bg - Dropdown panel background color\n * @cssprop --combobox-dropdown-border-color - Dropdown panel border color\n * @cssprop --combobox-option-hover-bg - Option background on hover\n * @cssprop --combobox-option-focus-bg - Option background when keyboard-focused\n * @cssprop --combobox-option-selected-bg - Option background when selected\n * @cssprop --combobox-option-selected-focus-bg - Option background when selected and focused\n * @cssprop --input-bg - Field background (passed through to ore-input)\n * @cssprop --input-border-color - Field border color (passed through to ore-input)\n *\n * @part wrapper - Root wrapper around the entire field\n * @part label - Label element shown inside or outside the field\n * @part field - Field container that holds the trigger input and clear button\n * @part input - Search input used to filter and select options\n * @part clear-btn - Button that clears the current selection/query\n * @part dropdown - Popup list container for options\n * @part helper-text - Helper text displayed below the field\n * @example\n * ```html\n * <ore-combobox label=\"Country\" name=\"country\">\n * <ore-combobox-option value=\"us\">United States</ore-combobox-option>\n * <ore-combobox-option value=\"gb\">United Kingdom</ore-combobox-option>\n * <ore-combobox-option value=\"de\" disabled>Germany</ore-combobox-option>\n * </ore-combobox>\n * ```\n */\nexport const COMBOBOX_TAG = 'ore-combobox' as const;\ndefine<OreComboboxProps>(COMBOBOX_TAG, {\n formAssociated: true,\n props: {\n autoclose: prop.bool(false),\n color: prop.string<ThemeColor>(),\n creatable: prop.bool(false),\n disabled: prop.bool(false),\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n 'hide-label': prop.bool(false),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n loading: prop.bool(false),\n multiple: prop.bool(false),\n name: prop.string(),\n 'no-filter': prop.bool(false),\n options: prop.data<ComboboxOptionInput[]>(),\n placeholder: prop.string('Select...'),\n required: prop.bool(false),\n rounded: prop.string<RoundedSize>(),\n size: prop.string<ComponentSize>(),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreComboboxEvents>();\n const watch = watchEffect;\n\n const query = signal('');\n\n // Element refs needed by the listbox dropdown.\n let inputEl: HTMLInputElement | null = null;\n let fieldEl: HTMLElement | null = null; // set to the ore-input host once it mounts\n let dropdownEl: HTMLElement | null = null;\n let listboxEl: HTMLElement | null = null;\n\n // Ref to the ore-input host; resolved when the template renders.\n const bitInputRef = ref<HTMLElement>();\n\n const abortSignal = lifecycleSignal(onCleanup);\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n label: props.label,\n labelPlacement: props['label-placement'],\n multiple: props.multiple,\n prefix: 'combobox',\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n // filteredOptions signal declared before optionList so the getItems getter\n // captures the live signal reference rather than needing a factory indirection.\n const filteredOptions = signal<ComboboxOptionItem[]>([]);\n\n const optionList = createListboxDropdown<ComboboxOptionItem>({\n getBoundary: () => el,\n getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n getItems: () => filteredOptions.value,\n getOptionId: (index) => `${choice.fieldId}-opt-${index}`,\n getPanel: () => dropdownEl,\n getReference: () => fieldEl,\n getTrigger: () => inputEl,\n isDisabled: () => choice.disabled.value,\n isItemDisabled: (option) => option.disabled,\n onClose: (reason) => {\n emit('open-change', { open: false, reason });\n\n if (!abortSignal.aborted) restoreQueryFromSelection();\n\n choice.triggerValidation('blur');\n },\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n restoreFocus: false,\n signal: abortSignal,\n });\n\n const { disabled: isDisabled, fieldId: comboId, selectedValues, triggerValidation } = choice;\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const { focusedIndex, isOpen, scrollFocusedIntoView, updatePosition } = optionList;\n // ── State ────────────────────────────────────────────────────────────────\n const isMultiple = () => Boolean(props.multiple.value);\n const isCreatable = () => Boolean(props.creatable.value);\n const isNoFilter = () => Boolean(props['no-filter'].value);\n\n bind({\n attr: {\n open: () => (isOpen.value ? true : undefined),\n size: props.size,\n variant: props.variant,\n },\n });\n\n let lastQueryBeforeClear: string | null = null;\n let isRestoringQuery = false;\n\n const selectedValue = computed(() => selectedValues.value[0] ?? '');\n\n // Expose a native-like, string-valued `.value` property on the host.\n Object.defineProperty(el, 'value', {\n configurable: true,\n get: () => choice.formValue.value,\n set: (val: unknown) => {\n const v = val as string | string[] | null | undefined;\n\n if (Array.isArray(v)) {\n choice.setValues(v.map((entry) => String(entry ?? '')));\n\n return;\n }\n\n if (v == null || v === '') {\n choice.clear();\n\n return;\n }\n\n choice.setValues(isMultiple() ? String(v).split(',') : [String(v)]);\n },\n });\n\n const hasValue = () => selectedValues.value.length > 0;\n\n function focusLiveInput() {\n inputEl?.focus();\n }\n\n // ── Options ──────────────────────────────────────────────────────────────\n const slottedOptions = signal<ComboboxOptionItem[]>([]);\n const createdOptions = signal<ComboboxOptionItem[]>([]);\n const isLoading = () => Boolean(props.loading.value);\n\n function normalizeOption(option: ComboboxOptionInput): ComboboxOptionItem {\n return {\n disabled: Boolean(option.disabled),\n disabledReason: option.disabledReason,\n iconEl: option.iconEl ?? null,\n label: option.label ?? option.value,\n value: option.value,\n };\n }\n\n // Merged options: explicit prop value overrides slotted options.\n const allOptions = computed<ComboboxOptionItem[]>(() => {\n const optionsProp = props.options.value;\n const base = Array.isArray(optionsProp) ? optionsProp.map(normalizeOption) : slottedOptions.value;\n\n if (createdOptions.value.length === 0) return base;\n\n return [...base, ...createdOptions.value];\n });\n\n const selectionController = {\n clear: () => {\n choice.clear();\n },\n remove: (key: string) => {\n choice.removeValue(key);\n },\n select: (key: string) => {\n choice.selectValue(key);\n },\n toggle: (key: string) => {\n choice.toggleValue(key);\n },\n };\n\n function readOptions(elements: Element[] = Array.from(el.children)) {\n slottedOptions.value = parseSlottedOptions(elements);\n\n if (!isMultiple()) {\n const match = allOptions.value.find((option) => option.value === selectedValue.value);\n\n query.value = match?.label ?? selectedValue.value;\n }\n }\n\n // Initialize from light DOM immediately; onMounted/observer keep this in sync afterwards.\n readOptions();\n\n watch(() => {\n const nextOptions = filterOptions(allOptions.value, query.value, isNoFilter());\n\n filteredOptions.value = isMultiple()\n ? nextOptions.filter((option) => !selectedValues.value.includes(option.value))\n : nextOptions;\n });\n\n // \"Create\" option shown when creatable + query doesn't match any existing option\n const creatableLabel = computed(() => {\n return getCreatableLabel(query.value, isCreatable(), filteredOptions.value);\n });\n const inputPlaceholder = () =>\n isMultiple() && selectedValues.value.length > 0 ? '' : props.placeholder.value || '';\n\n function emitChange() {\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n }\n\n function removeChip(event: Event): void {\n event.stopPropagation();\n\n const value = (event as CustomEvent<{ value?: string }>).detail?.value;\n\n if (value === undefined) return;\n\n selectionController.remove(value);\n emitChange();\n triggerValidation('change');\n }\n\n function restoreQueryFromSelection() {\n // Keep input text and selected value in sync whenever the popup closes.\n if (!isMultiple()) {\n const match = allOptions.value.find((option) => option.value === selectedValue.value);\n\n isRestoringQuery = true;\n query.value = match?.label ?? '';\n Promise.resolve().then(() => {\n isRestoringQuery = false;\n });\n\n return;\n }\n\n query.value = '';\n }\n\n watch(() => {\n if (isOpen.value && !isMultiple() && selectedValue.value && focusedIndex.value === -1 && query.value === '') {\n const selectedIndex = filteredOptions.value.findIndex((option) => option.value === selectedValue.value);\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n }\n }\n });\n\n // ── Open / Close ─────────────────────────────────────────────────────────\n function openPopup(clearFilter = true, reason: OverlayOpenReason = 'programmatic') {\n if (clearFilter) {\n lastQueryBeforeClear = query.value;\n query.value = '';\n }\n\n // Pre-compute focused index BEFORE opening so the first render has it set\n if (!isMultiple() && selectedValue.value) {\n const freshOptions = filterOptions(allOptions.value, '', isNoFilter());\n const selectedIndex = freshOptions.findIndex((option) => option.value === selectedValue.value);\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n }\n }\n\n optionList.open(reason);\n\n if (!isMultiple() && selectedValue.value && focusedIndex.value >= 0) {\n requestAnimationFrame(() => {\n scrollFocusedIntoView();\n });\n }\n }\n\n function closePopup(reason: DropdownCloseReason = 'programmatic') {\n optionList.close(reason);\n }\n\n const fieldPress = createInteraction({\n disabled: isDisabled,\n onPress: () => {\n if (!isOpen.value) openPopup(true, 'click');\n\n focusLiveInput();\n },\n });\n\n const enterPress = createInteraction({\n disabled: isDisabled,\n keys: ['Enter'],\n onPress: (originalEvent: Event) => {\n const opts = filteredOptions.value;\n\n if (isOpen.value && focusedIndex.value >= 0 && focusedIndex.value < opts.length) {\n selectOption(opts[focusedIndex.value], originalEvent);\n } else if (isOpen.value && focusedIndex.value === -1 && creatableLabel.value) {\n // Focused on the \"create\" item\n createOption(query.value, originalEvent);\n } else if (!isOpen.value) {\n openPopup(true, 'keyboard');\n }\n },\n });\n\n // ── Selection ────────────────────────────────────────────────────────────\n function selectOption(opt: ComboboxOptionItem, _originalEvent?: Event) {\n if (opt.disabled) return;\n\n if (isMultiple()) {\n selectionController.toggle(opt.value);\n query.value = '';\n emitChange();\n triggerValidation('change');\n\n if (props.autoclose.value) {\n closePopup();\n }\n\n // Keep dropdown open in multiple mode (unless autoclose is true)\n focusLiveInput();\n requestAnimationFrame(() => focusLiveInput());\n } else {\n selectionController.select(opt.value);\n query.value = opt.label;\n emitChange();\n triggerValidation('change');\n closePopup();\n focusLiveInput();\n }\n }\n function resolveOptionFromElement(optionEl: HTMLElement): ComboboxOptionItem | null {\n const indexAttr = optionEl.getAttribute('data-option-index');\n const index = indexAttr ? Number(indexAttr) : -1;\n\n if (Number.isInteger(index) && index >= 0 && index < filteredOptions.value.length) {\n return filteredOptions.value[index] ?? null;\n }\n\n const valueAttr = optionEl.getAttribute('data-option-value');\n\n if (valueAttr) {\n const byValue = filteredOptions.value.find((option) => option.value === valueAttr);\n\n if (byValue) return byValue;\n }\n\n const labelText = optionEl.querySelector('span')?.textContent?.trim() ?? optionEl.textContent?.trim() ?? '';\n\n if (!labelText) return null;\n\n return filteredOptions.value.find((option) => option.label === labelText || option.value === labelText) ?? null;\n }\n function clearValue(e: Event) {\n e.stopPropagation();\n selectionController.clear();\n query.value = '';\n emitChange();\n triggerValidation('change');\n focusLiveInput();\n }\n function handleInput(e: InputEvent) {\n const target = e.target as HTMLInputElement;\n const newValue = target.value;\n\n // Skip all input processing if we're in the middle of restoring the query\n // This prevents the clearing logic from firing during close/restore\n if (isRestoringQuery) {\n return;\n }\n\n if (newValue === query.value) return;\n\n query.value = newValue;\n\n if (!isMultiple()) {\n const currentItem = selectedValues.value[0];\n const currentLabel = currentItem\n ? (allOptions.value.find((o) => o.value === currentItem)?.label ?? currentItem)\n : '';\n\n // Preserve the current selection while typing. Selection should only\n // change when a new option is committed or when the user explicitly clears.\n const isJustOpening = newValue === '' && lastQueryBeforeClear === currentLabel;\n\n if (isJustOpening) {\n lastQueryBeforeClear = null;\n }\n }\n\n optionList.navigate('first');\n\n if (!isOpen.value) openPopup(false, 'keyboard');\n\n emit('search', { query: target.value });\n }\n function handleFocus() {\n // Intentionally no-op: open only on explicit click or keyboard.\n // Opening on every focus surprises users tabbing through a form.\n }\n\n // ── Keyboard Navigation ──────────────────────────────────────────────────\n function handleKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n if (optionList.handleKeydown(e)) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n\n if (!isOpen.value) {\n openPopup(true, 'keyboard');\n optionList.navigate('first');\n } else {\n optionList.navigate('next');\n }\n\n break;\n case 'ArrowUp':\n e.preventDefault();\n\n if (!isOpen.value) {\n openPopup(true, 'keyboard');\n } else {\n optionList.navigate('prev');\n }\n\n break;\n case 'Backspace':\n // In multiple mode, remove the last chip when the input is empty\n if (isMultiple() && !query.value && selectedValues.value.length > 0) {\n choice.removeValue(selectedValues.value[selectedValues.value.length - 1] ?? '');\n emitChange();\n triggerValidation('change');\n }\n\n break;\n case 'Enter':\n enterPress.handleKeydown(e);\n\n break;\n case 'Tab':\n closePopup('programmatic');\n break;\n default:\n break;\n }\n }\n\n // ── Create option ────────────────────────────────────────────────────────\n function createOption(rawQuery: string, originalEvent?: Event) {\n const actualLabel = rawQuery.trim();\n\n if (!actualLabel) return;\n\n const value = makeCreatableValue(actualLabel);\n const newOpt: ComboboxOptionItem = { disabled: false, iconEl: null, label: actualLabel, value };\n\n createdOptions.value = [...createdOptions.value, newOpt];\n selectOption(newOpt, originalEvent);\n }\n // ── Lifecycle ────────────────────────────────────────────────────────────\n\n const observeLightDomOptions = (): (() => void) => {\n const observer = new MutationObserver(() => {\n readOptions();\n });\n\n observer.observe(el, {\n attributeFilter: ['disabled', 'disabled-reason', 'label', 'value'],\n attributes: true,\n childList: true,\n subtree: true,\n });\n\n return () => observer.disconnect();\n };\n\n const stopObserving = observeLightDomOptions();\n\n const createListboxListeners = (listEl: HTMLElement): (() => void) => {\n const handleActivate = (event: Event) => {\n const target = event.target;\n\n if (!(target instanceof Element)) return;\n\n const createRow = target.closest<HTMLElement>('.no-results-create');\n\n if (createRow) {\n event.preventDefault();\n event.stopPropagation();\n createOption(query.value, event);\n\n return;\n }\n\n const optionEl = target.closest<HTMLElement>('.option');\n\n if (!optionEl) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n const option = resolveOptionFromElement(optionEl);\n\n if (!option || option.disabled) return;\n\n selectOption(option, event);\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n const target = event.target;\n\n if (!(target instanceof Element)) return;\n\n const optionEl = target.closest<HTMLElement>('.option');\n\n if (!optionEl) return;\n\n const option = resolveOptionFromElement(optionEl);\n\n if (!option) return;\n\n const focusedIdx = filteredOptions.value.findIndex((candidate) => candidate.value === option.value);\n\n if (focusedIdx >= 0) {\n optionList.set(focusedIdx);\n }\n };\n\n listEl.addEventListener('click', handleActivate);\n listEl.addEventListener('pointermove', handlePointerMove);\n\n return () => {\n listEl.removeEventListener('click', handleActivate);\n listEl.removeEventListener('pointermove', handlePointerMove);\n };\n };\n\n let stopListboxListeners: (() => void) | null = null;\n let listboxListenersTarget: HTMLElement | null = null;\n\n const setListboxElement = (el: HTMLElement | null): void => {\n listboxEl = el;\n\n if (listboxListenersTarget === el) return;\n\n stopListboxListeners?.();\n stopListboxListeners = null;\n listboxListenersTarget = null;\n\n if (!el) return;\n\n stopListboxListeners = createListboxListeners(el);\n listboxListenersTarget = el;\n };\n\n const ensureListboxListeners = (): void => {\n if (!listboxEl) return;\n\n if (listboxListenersTarget === listboxEl && stopListboxListeners) return;\n\n stopListboxListeners?.();\n stopListboxListeners = createListboxListeners(listboxEl);\n listboxListenersTarget = listboxEl;\n };\n\n watch(() => {\n ensureListboxListeners();\n\n if (isOpen.value) {\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n\n updatePosition();\n } else {\n if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n }\n });\n\n // Once ore-input is in the DOM, grab its inner <input> from its shadow root\n // and attach all combobox-specific ARIA + event handlers imperatively.\n // MUST be registered before the ARIA effects below so inputEl is set first\n // when bitInputRef fires (effects run in registration order).\n onElement(bitInputRef, (bitInputEl) => {\n fieldEl = bitInputEl;\n\n const rawInput = bitInputEl.shadowRoot?.querySelector<HTMLInputElement>('input') ?? null;\n\n if (!rawInput) return;\n\n inputEl = rawInput;\n\n rawInput.setAttribute('role', 'combobox');\n rawInput.setAttribute('autocomplete', 'off');\n rawInput.setAttribute('aria-autocomplete', 'list');\n rawInput.setAttribute('aria-haspopup', 'listbox');\n rawInput.setAttribute('spellcheck', 'false');\n rawInput.setAttribute('aria-controls', `${comboId}-listbox`);\n\n const handleInputClick = (): void => {\n if (!isOpen.value) openPopup(true, 'click');\n\n focusLiveInput();\n };\n\n rawInput.addEventListener('input', handleInput as EventListener);\n rawInput.addEventListener('keydown', handleKeydown as EventListener);\n rawInput.addEventListener('focus', handleFocus);\n rawInput.addEventListener('click', handleInputClick);\n\n return () => {\n inputEl = null;\n fieldEl = null;\n rawInput.removeEventListener('input', handleInput as EventListener);\n rawInput.removeEventListener('keydown', handleKeydown as EventListener);\n rawInput.removeEventListener('focus', handleFocus);\n rawInput.removeEventListener('click', handleInputClick);\n };\n });\n\n // Reactively sync combobox-specific ARIA attrs that ore-input doesn't manage.\n // Uses bitInputRef (a signal) as the gate so the effect re-runs when the\n // inner input mounts — inputEl is a plain variable and would not trigger re-runs.\n watch(() => {\n if (!bitInputRef.value) return;\n\n const el = inputEl;\n\n if (!el) return;\n\n el.setAttribute('aria-expanded', String(isOpen.value));\n\n if (isDisabled.value) {\n el.setAttribute('aria-disabled', 'true');\n } else {\n el.removeAttribute('aria-disabled');\n }\n\n if (props.error.value) {\n el.setAttribute('aria-invalid', 'true');\n el.setAttribute('aria-errormessage', `${comboId}-error`);\n } else {\n el.removeAttribute('aria-invalid');\n el.removeAttribute('aria-errormessage');\n }\n });\n\n // Reactively sync the query signal into the raw input value.\n watch(() => {\n if (!bitInputRef.value) return;\n\n const el = inputEl;\n\n if (!el) return;\n\n if (el.value !== query.value) el.value = query.value;\n });\n\n onCleanup(() => {\n stopListboxListeners?.();\n stopListboxListeners = null;\n listboxListenersTarget = null;\n stopObserving();\n });\n\n const hideLabel = () => props['hide-label'].value;\n const inputAriaLabel = () => (hideLabel() ? (props.label.value ?? '') : null);\n const inputLabel = () => (hideLabel() ? '' : (props.label.value ?? ''));\n const inputColor = () => props.color?.value ?? undefined;\n const inputSize = () => props.size?.value ?? undefined;\n const inputVariant = () => props.variant?.value ?? undefined;\n const inputRounded = () => props.rounded?.value ?? undefined;\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n return html`\n <slot></slot>\n <ore-input\n class=\"trigger\"\n ref=${bitInputRef}\n aria-label=\"${inputAriaLabel}\"\n label=\"${inputLabel}\"\n placeholder=\"${inputPlaceholder}\"\n label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n color=\"${inputColor}\"\n size=\"${inputSize}\"\n variant=\"${inputVariant}\"\n rounded=\"${inputRounded}\"\n helper=\"${() => props.helper.value ?? ''}\"\n error=\"${() => props.error.value ?? ''}\"\n ?disabled=\"${isDisabled}\"\n ?required=\"${() => false}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n name=\"${() => props.name.value ?? ''}\"\n @click=\"${(e: MouseEvent) => {\n fieldPress.handleClick(e);\n }}\"\n part=\"wrapper\">\n <div slot=\"prefix\" class=\"chips-row\">\n <!-- Keep chip list diffing isolated so input node identity stays stable. -->\n <span class=\"chips-list\">\n ${() =>\n (isMultiple() ? selectedValues.value : []).map(\n (value) => html`\n <ore-chip\n value=${value}\n label=${allOptions.value.find((option) => option.value === value)?.label ?? value}\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=\"${props.color}\"\n @remove=${removeChip}>\n ${allOptions.value.find((option) => option.value === value)?.label ?? value}\n </ore-chip>\n `,\n )}\n </span>\n </div>\n <span slot=\"suffix\" class=\"combobox-suffix\" aria-hidden=\"true\">\n <button\n class=\"clear-btn\"\n part=\"clear-btn\"\n type=\"button\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n ?hidden=${() => !hasValue()}\n @click=\"${clearValue}\">\n <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n <span class=\"combobox-suffix-end\">\n <span class=\"loader\"></span>\n <span class=\"chevron\">\n <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </span>\n </span>\n </ore-input>\n <span\n class=\"sr-only\"\n id=\"${() => `${comboId}-error`}\"\n role=\"alert\"\n aria-live=\"assertive\"\n ?hidden=\"${() => !props.error.value}\">\n ${() => props.error.value ?? ''}\n </span>\n <div\n class=\"dropdown\"\n part=\"dropdown\"\n id=\"${() => `${comboId}-dropdown`}\"\n popover=\"manual\"\n ?data-open=${() => isOpen.value}\n ref=${(el: HTMLElement | null) => {\n dropdownEl = el;\n }}>\n <div\n role=\"listbox\"\n id=\"${() => `${comboId}-listbox`}\"\n style=\"${() =>\n isOpen.value && filteredOptions.value.length > 0 ? `height:${filteredOptions.value.length * 36}px;` : ''}\"\n aria-label=\"${() => props.label.value || props.placeholder.value || 'Options'}\"\n ref=${(el: HTMLElement | null) => {\n setListboxElement(el);\n }}>\n ${() => {\n if (!isOpen.value) return '';\n\n if (isLoading()) {\n return html`\n <div class=\"dropdown-loading\">Loading...</div>\n `;\n }\n\n if (filteredOptions.value.length === 0) {\n if (creatableLabel.value) {\n return html`\n <button type=\"button\" class=\"no-results-create\" ?data-focused=${() => focusedIndex.value === -1}>\n ${creatableLabel.value}\n </button>\n `;\n }\n\n return html`\n <div class=\"no-results\" role=\"presentation\">No results found</div>\n `;\n }\n\n return filteredOptions.value.map((option, index) => {\n return html`\n <div\n class=\"option\"\n role=\"option\"\n id=\"${`${comboId}-opt-${index}`}\"\n data-option-index=\"${index}\"\n data-option-value=\"${option.value}\"\n aria-selected=\"${() =>\n String(\n isMultiple() ? selectedValues.value.includes(option.value) : selectedValue.value === option.value,\n )}\"\n aria-disabled=\"${String(option.disabled)}\"\n style=\"${`position:absolute;top:0;left:0;right:0;transform:translateY(${index * 36}px);`}\"\n ?data-focused=${() => focusedIndex.value === index}\n ?data-selected=${() =>\n isMultiple() ? selectedValues.value.includes(option.value) : selectedValue.value === option.value}\n ?data-disabled=${option.disabled}>\n <span>${option.label}</span>\n ${\n option.disabled && option.disabledReason\n ? html`<small class=\"disabled-reason\" title=\"${option.disabledReason}\">${option.disabledReason}</small>`\n : html``\n }\n <span class=\"option-check\" aria-hidden=\"true\">\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </span>\n </div>\n `;\n });\n }}\n </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, srOnlyMixin, componentStyles],\n}) as unknown as AddEventListeners<OreComboboxEvents>;\n"],"mappings":"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"}
|
package/dist/combobox.js
CHANGED
|
@@ -11,8 +11,12 @@ import s from "./inputs/combobox/combobox.css.js";
|
|
|
11
11
|
import { bind as oe, define as c, getHost as se, html as l, onCleanup as u, onElement as ce, prop as d, ref as le, useEmit as ue, useField as de, watchEffect as fe } from "@vielzeug/ore";
|
|
12
12
|
import { computed as f, signal as p } from "@vielzeug/ripple";
|
|
13
13
|
//#region src/inputs/combobox/combobox.ts
|
|
14
|
-
var m = "ore-combobox";
|
|
15
|
-
c(m, {
|
|
14
|
+
var m = "ore-combobox-option";
|
|
15
|
+
c(m, { setup() {
|
|
16
|
+
return l``;
|
|
17
|
+
} });
|
|
18
|
+
var h = "ore-combobox";
|
|
19
|
+
c(h, {
|
|
16
20
|
formAssociated: !0,
|
|
17
21
|
props: {
|
|
18
22
|
autoclose: d.bool(!1),
|
|
@@ -449,6 +453,6 @@ c(m, {
|
|
|
449
453
|
]
|
|
450
454
|
});
|
|
451
455
|
//#endregion
|
|
452
|
-
export { m as COMBOBOX_TAG };
|
|
456
|
+
export { m as COMBOBOX_OPTION_TAG, h as COMBOBOX_TAG };
|
|
453
457
|
|
|
454
458
|
//# sourceMappingURL=combobox.js.map
|