@vielzeug/refine 26.10.10 → 26.10.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +2 -0
  2. package/THIRD_PARTY_NOTICES +116 -0
  3. package/dist/content/icon/icon.d.ts +8 -9
  4. package/dist/content/icon/icon.d.ts.map +1 -1
  5. package/dist/content/index.d.ts +6 -1
  6. package/dist/content/index.d.ts.map +1 -1
  7. package/dist/custom-elements.json +4481 -4035
  8. package/dist/icon.cjs +4 -4
  9. package/dist/icon.cjs.map +1 -1
  10. package/dist/icon.js +4 -4
  11. package/dist/icon.js.map +1 -1
  12. package/dist/icons/_iconify-map.cjs +2 -0
  13. package/dist/icons/_iconify-map.cjs.map +1 -0
  14. package/dist/icons/_iconify-map.d.ts +5 -0
  15. package/dist/icons/_iconify-map.d.ts.map +1 -0
  16. package/dist/icons/_iconify-map.js +2 -0
  17. package/dist/icons/_iconify-map.js.map +1 -0
  18. package/dist/icons/defaults.cjs +2 -0
  19. package/dist/icons/defaults.cjs.map +1 -0
  20. package/dist/icons/defaults.d.ts +2 -0
  21. package/dist/icons/defaults.d.ts.map +1 -0
  22. package/dist/icons/defaults.js +2 -0
  23. package/dist/icons/defaults.js.map +1 -0
  24. package/dist/icons/definition.d.ts +13 -0
  25. package/dist/icons/definition.d.ts.map +1 -0
  26. package/dist/icons/heroicons.cjs +2 -0
  27. package/dist/icons/heroicons.cjs.map +1 -0
  28. package/dist/icons/heroicons.d.ts +9 -0
  29. package/dist/icons/heroicons.d.ts.map +1 -0
  30. package/dist/icons/heroicons.js +2 -0
  31. package/dist/icons/heroicons.js.map +1 -0
  32. package/dist/icons/iconify.cjs +2 -0
  33. package/dist/icons/iconify.cjs.map +1 -0
  34. package/dist/icons/iconify.d.ts +34 -0
  35. package/dist/icons/iconify.d.ts.map +1 -0
  36. package/dist/icons/iconify.js +2 -0
  37. package/dist/icons/iconify.js.map +1 -0
  38. package/dist/icons/index.cjs +1 -0
  39. package/dist/icons/index.d.ts +3 -0
  40. package/dist/icons/index.d.ts.map +1 -0
  41. package/dist/icons/index.js +1 -0
  42. package/dist/icons/lucide/all.cjs +2 -0
  43. package/dist/icons/lucide/all.cjs.map +1 -0
  44. package/dist/icons/lucide/all.d.ts +2 -0
  45. package/dist/icons/lucide/all.d.ts.map +1 -0
  46. package/dist/icons/lucide/all.js +2 -0
  47. package/dist/icons/lucide/all.js.map +1 -0
  48. package/dist/icons/lucide.cjs +2 -0
  49. package/dist/icons/lucide.cjs.map +1 -0
  50. package/dist/icons/lucide.d.ts +5 -0
  51. package/dist/icons/lucide.d.ts.map +1 -0
  52. package/dist/icons/lucide.js +2 -0
  53. package/dist/icons/lucide.js.map +1 -0
  54. package/dist/icons/mdi.cjs +2 -0
  55. package/dist/icons/mdi.cjs.map +1 -0
  56. package/dist/icons/mdi.d.ts +9 -0
  57. package/dist/icons/mdi.d.ts.map +1 -0
  58. package/dist/icons/mdi.js +2 -0
  59. package/dist/icons/mdi.js.map +1 -0
  60. package/dist/icons/registry.cjs +2 -0
  61. package/dist/icons/registry.cjs.map +1 -0
  62. package/dist/icons/registry.d.ts +7 -0
  63. package/dist/icons/registry.d.ts.map +1 -0
  64. package/dist/icons/registry.js +2 -0
  65. package/dist/icons/registry.js.map +1 -0
  66. package/dist/icons/svg.cjs +2 -0
  67. package/dist/icons/svg.cjs.map +1 -0
  68. package/dist/icons/svg.d.ts +8 -0
  69. package/dist/icons/svg.d.ts.map +1 -0
  70. package/dist/icons/svg.js +2 -0
  71. package/dist/icons/svg.js.map +1 -0
  72. package/dist/icons/tabler.cjs +2 -0
  73. package/dist/icons/tabler.cjs.map +1 -0
  74. package/dist/icons/tabler.d.ts +9 -0
  75. package/dist/icons/tabler.d.ts.map +1 -0
  76. package/dist/icons/tabler.js +2 -0
  77. package/dist/icons/tabler.js.map +1 -0
  78. package/dist/index.cjs +1 -1
  79. package/dist/index.d.ts +2 -0
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +1 -1
  82. package/dist/inputs/message-composer/message-composer.d.ts +2 -2
  83. package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
  84. package/dist/inputs/select/select.d.ts +1 -1
  85. package/dist/inputs/select/select.d.ts.map +1 -1
  86. package/dist/layout/navbar/navbar.d.ts.map +1 -1
  87. package/dist/message-composer.cjs.map +1 -1
  88. package/dist/message-composer.js.map +1 -1
  89. package/dist/navbar.cjs +1 -1
  90. package/dist/navbar.cjs.map +1 -1
  91. package/dist/navbar.js +1 -1
  92. package/dist/navbar.js.map +1 -1
  93. package/dist/overlay/command-palette/command-palette.types.d.ts +1 -1
  94. package/dist/overlay/command-palette/command-palette.types.d.ts.map +1 -1
  95. package/dist/refine.cjs +153 -153
  96. package/dist/refine.cjs.map +1 -1
  97. package/dist/refine.iife.js +153 -153
  98. package/dist/refine.iife.js.map +1 -1
  99. package/dist/refine.js +129 -129
  100. package/dist/refine.js.map +1 -1
  101. package/dist/select.cjs.map +1 -1
  102. package/dist/select.js.map +1 -1
  103. package/dist/shared/prop-bundles.d.ts +3 -3
  104. package/package.json +81 -22
  105. package/dist/_virtual/_rolldown/runtime.cjs +0 -1
  106. package/dist/core/icon-registry.cjs +0 -2
  107. package/dist/core/icon-registry.cjs.map +0 -1
  108. package/dist/core/icon-registry.d.ts +0 -15
  109. package/dist/core/icon-registry.d.ts.map +0 -1
  110. package/dist/core/icon-registry.js +0 -2
  111. package/dist/core/icon-registry.js.map +0 -1
  112. package/dist/core/icons.cjs +0 -2
  113. package/dist/core/icons.cjs.map +0 -1
  114. package/dist/core/icons.d.ts +0 -2
  115. package/dist/core/icons.d.ts.map +0 -1
  116. package/dist/core/icons.js +0 -2
  117. package/dist/core/icons.js.map +0 -1
  118. package/dist/icon-lucide.cjs +0 -2
  119. package/dist/icon-lucide.cjs.map +0 -1
  120. package/dist/icon-lucide.d.ts +0 -2
  121. package/dist/icon-lucide.d.ts.map +0 -1
  122. package/dist/icon-lucide.js +0 -2
  123. package/dist/icon-lucide.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"select.cjs","names":[],"sources":["../src/inputs/select/select.ts"],"sourcesContent":["import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField, useSlots } from '@vielzeug/ore';\nimport { computed, effect, signal, watch } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail, OverlayOpenReason } from '../../core';\nimport { createChoiceField, createListboxDropdown, lifecycleSignal } from '../../core';\nimport type { SelectableFieldProps } from '../../shared';\nimport { disablableBundle, loadableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin } from '../../styles';\nimport { INPUT_VARIANTS, type InputVariant } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './select.css?inline';\n\nexport { ICON_TAG } from '../../content/icon/icon';\nexport { CHIP_TAG } from '../../feedback/chip/chip';\nexport { INPUT_TAG } from '../input/input';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\ntype OptionItem = {\n disabled: boolean;\n disabledReason?: string;\n group?: string;\n icons?: string[];\n label: string;\n value: string;\n};\n\nexport type OreSelectOptionInput = {\n disabled?: boolean;\n /** Explanation displayed and announced when the option is disabled. */\n disabledReason?: string;\n group?: string;\n /** Icon(s) rendered before the option label: lucide name(s) or image URL(s). */\n icon?: string | string[];\n label?: string;\n value: string;\n};\n\ntype FlatRow =\n | {\n idx: number;\n opt: OptionItem;\n type: 'option';\n }\n | {\n label: string;\n type: 'group';\n };\n\n/**\n * Icon sources containing a path separator or a `data:` scheme are treated as image URLs and\n * rendered as `<img>`; anything else is a lucide icon name rendered via `ore-icon`.\n */\nconst isIconImage = (icon: string): boolean => icon.includes('/') || icon.startsWith('data:');\n\n/** Normalizes an icon value: single name/URL, space-separated list, or array: to icon entries. */\nconst normalizeIcons = (icon: string | string[] | undefined): string[] | undefined => {\n const list = Array.isArray(icon) ? icon : icon?.split(' ');\n const icons = list?.map((entry) => entry.trim()).filter(Boolean);\n return icons?.length ? icons : undefined;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Component Props ─────────────────────────────────────────────────────────────\n\n/** Select component properties */\n\nexport type OreSelectEvents = {\n change: Event;\n input: Event;\n 'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreSelectProps = SelectableFieldProps<InputVariant> & {\n /** Hide the visible label while preserving the accessible name via `aria-label` */\n 'hide-label'?: boolean;\n /** Show loading state in dropdown */\n loading?: boolean;\n /** Allow selecting multiple options */\n multiple?: boolean;\n /** JS options array (alternative to slotted <option> elements) */\n options?: OreSelectOptionInput[];\n /** Mark the field as required */\n required?: boolean;\n};\n\n/**\n * A fully custom form-associated select dropdown with keyboard navigation and ARIA support.\n * Reads `<option>` and `<optgroup>` children from the default slot.\n *\n * @element ore-select\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {boolean} hide-label - Hide the visible label; the label text is exposed as `aria-label` on the trigger instead\n * @attr {string} value - Current selected value(s) (comma-separated for multiple)\n * @attr {string} placeholder - Placeholder when no option selected\n * @attr {string} name - Form field name\n * @attr {boolean} multiple - Enable multi-select\n * @attr {boolean} disabled - Disable the select\n * @attr {boolean} required - Required field\n * @attr {string} helper - Helper text below the select\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @fires input - Fired when selection changes.\n * @fires change - Fired when selection changes.\n * @fires open-change - Fired when the dropdown state changes. detail: { open, reason }\n *\n * @slot - `<option>` and `<optgroup>` elements\n *\n * @cssprop --select-bg - Background\n * @cssprop --select-border-color - Border color\n * @cssprop --select-min-width - Minimum width of the select; the trigger floors at it too, so the control never renders wider than its host\n * @cssprop --select-radius - Border radius\n * @cssprop --select-padding - Padding\n * @cssprop --select-font-size - Font size\n * @cssprop --select-placeholder-color - Placeholder text color\n *\n * @part trigger - The `ore-input` trigger element that opens the dropdown.\n * @part dropdown - The dropdown listbox panel container.\n *\n * @example\n * ```html\n * <ore-select label=\"Role\" value=\"admin\">\n * <option value=\"admin\">Administrator</option>\n * <option value=\"editor\">Editor</option>\n * <option value=\"viewer\">Viewer</option>\n * </ore-select>\n *\n * <ore-select label=\"Tags\" multiple color=\"primary\">\n * <optgroup label=\"Frontend\">\n * <option value=\"react\">React</option>\n * <option value=\"vue\">Vue</option>\n * </optgroup>\n * <optgroup label=\"Backend\">\n * <option value=\"node\">Node.js</option>\n * </optgroup>\n * </ore-select>\n * ```\n */\nexport const SELECT_TAG = 'ore-select' as const;\ndefine<OreSelectProps>(SELECT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...loadableBundle,\n ...roundableBundle,\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 multiple: prop.bool(false),\n name: prop.string(),\n options: prop.json(undefined as OreSelectOptionInput[] | undefined),\n placeholder: prop.string(),\n required: prop.bool(false),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.oneOf(INPUT_VARIANTS),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreSelectEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n // ────────────────────────────────────────────────────────────────\n // State & Context\n // ────────────────────────────────────────────────────────────────\n\n const slottedOptions = signal<OptionItem[]>([]);\n const isLoading = computed(() => Boolean(props.loading.value));\n\n // Merged options: explicit prop value overrides slotted options\n function normalizeOption(option: OreSelectOptionInput): OptionItem {\n return {\n disabled: Boolean(option.disabled),\n disabledReason: option.disabledReason,\n group: option.group,\n icons: normalizeIcons(option.icon),\n label: option.label ?? option.value,\n value: option.value,\n };\n }\n\n const options = computed(() => {\n const explicitOptions = props.options.value;\n\n return Array.isArray(explicitOptions) ? explicitOptions.map(normalizeOption) : slottedOptions.value;\n });\n let triggerEl: HTMLElement | null = null;\n let dropdownEl: HTMLElement | null = null;\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: 'select',\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const optionList = createListboxDropdown<OptionItem>({\n getBoundary: () => el,\n getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n getItems: () => options.value,\n getPanel: () => dropdownEl,\n getReference: () => triggerEl,\n getTrigger: () => triggerEl,\n isDisabled: () => choice.disabled.value,\n isItemDisabled: (option) => option.disabled,\n onClose: (reason) => {\n emit('open-change', { open: false, reason });\n choice.triggerValidation('blur');\n },\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n signal: abortSignal,\n });\n\n const { triggerValidation } = choice;\n const selectedValues = choice.selectedValues;\n const isDisabled = choice.disabled;\n\n defineFieldValue(\n el,\n () => choice.formValue.value,\n (value) => {\n choice.setValues(value ? value.split(',') : []);\n },\n );\n\n const { fieldId: selectId } = choice;\n const listboxId = `listbox-${selectId}`;\n const { focusedIndex, isOpen } = optionList;\n\n // Sync host attributes for CSS hooks\n bind({\n attr: {\n 'has-error': () => (props.error.value ? true : undefined),\n open: () => (isOpen.value ? true : undefined),\n size: props.size,\n variant: props.variant,\n },\n });\n\n // ────────────────────────────────────────────────────────────────\n // Option Reading from Slot\n // ────────────────────────────────────────────────────────────────\n\n function readOptions() {\n const slot = shadowRoot?.querySelector<HTMLSlotElement>('slot');\n\n if (!slot) return;\n\n const assigned = slot.assignedElements({ flatten: true });\n const items: OptionItem[] = [];\n\n for (const el of assigned) {\n if (el.tagName === 'OPTION') {\n const opt = el as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n } else if (el.tagName === 'OPTGROUP') {\n const group = el as HTMLOptGroupElement;\n const groupLabel = group.label;\n\n for (const child of Array.from(group.querySelectorAll('option'))) {\n const opt = child as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n group: groupLabel,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n }\n }\n }\n\n slottedOptions.value = items;\n }\n\n const displayLabel = computed(() => {\n if (selectedValues.value.length === 0) return '';\n\n if (props.multiple.value && selectedValues.value.length > 1) {\n return `${selectedValues.value.length} selected`;\n }\n\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.label ?? first;\n });\n const selectedIcons = computed(() => {\n if (props.multiple.value || selectedValues.value.length === 0) return undefined;\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.icons;\n });\n const selectedChipItems = computed(() => {\n if (!props.multiple.value) return [];\n\n return selectedValues.value.map((value) => ({\n label: options.value.find((o) => o.value === value)?.label ?? value,\n value,\n }));\n });\n const showChips = computed(() => props.multiple.value && selectedValues.value.length > 0);\n const triggerText = computed(() => displayLabel.value || props.placeholder.value || '');\n\n function buildFlatList(opts: OptionItem[]): FlatRow[] {\n const flat: FlatRow[] = [];\n const groups = new Map<string | undefined, OptionItem[]>();\n\n for (const opt of opts) {\n const key = opt.group;\n\n let group = groups.get(key);\n\n if (!group) {\n group = [];\n groups.set(key, group);\n }\n\n group.push(opt);\n }\n\n let globalIdx = 0;\n\n for (const [groupLabel, groupOpts] of groups) {\n if (groupLabel !== undefined) flat.push({ label: groupLabel, type: 'group' });\n\n for (const opt of groupOpts) flat.push({ idx: globalIdx++, opt, type: 'option' });\n }\n\n return flat;\n }\n\n const flatRows = computed(() => buildFlatList(options.value));\n\n function emitChange(): void {\n setFieldValue(el, choice.formValue.value);\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 choice.removeValue(value);\n emitChange();\n triggerValidation('change');\n }\n\n function openPopup(reason: OverlayOpenReason = 'programmatic') {\n // Show the popover before positioning so the positioner measures the element in the top\n // layer, not inside a possible ancestor containing block (a transformed dialog panel).\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n optionList.open(reason);\n\n requestAnimationFrame(() => {\n const selectedIndex =\n selectedValues.value.length > 0\n ? options.value.findIndex((option) => option.value === selectedValues.value[0])\n : -1;\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n\n return;\n }\n\n optionList.navigate('first');\n });\n }\n\n // Selection\n\n function selectOption(opt: OptionItem, _e?: Event) {\n if (opt.disabled) return;\n\n if (props.multiple.value) {\n choice.toggleValue(opt.value);\n } else {\n choice.selectValue(opt.value);\n optionList.close();\n }\n\n emitChange();\n triggerValidation('change');\n }\n\n // Keyboard navigation\n\n function handleTriggerKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n // Let optionList handle arrow key navigation\n if (optionList.handleKeydown(e)) return;\n\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault();\n\n if (isOpen.value) {\n const idx = focusedIndex.value;\n const opts = options.value;\n\n if (idx >= 0 && idx < opts.length) selectOption(opts[idx], e);\n } else {\n openPopup('keyboard');\n }\n\n break;\n case 'Tab':\n optionList.close();\n break;\n }\n }\n\n // ore-input prop helpers\n const inputValue = () => triggerText.value;\n const hideLabel = () => props['hide-label'].value;\n // When hide-label is set, suppress the visible label passed to ore-input (no inset\n // label renders, avoiding extra trigger height) but expose the label text as\n // aria-label on the trigger so the combobox retains its accessible name.\n const inputLabel = () => (hideLabel() ? '' : (props.label.value ?? ''));\n const triggerAriaLabel = () => (hideLabel() ? (props.label.value ?? '') : null);\n const inputPlaceholder = () => props.placeholder.value ?? '';\n const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\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 inputHelper = () => props.helper.value ?? '';\n const inputError = () => props.error.value ?? '';\n const inputDisabled = () => (isDisabled.value ? true : undefined);\n const inputRequired = () => (props.required.value ? true : undefined);\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n const tabIndexAttr = () => (isDisabled.value ? '-1' : '0');\n\n watch(slots.elements(), () => readOptions(), { immediate: true });\n\n const stopPopoverSync = effect(() => {\n if (isOpen.value) {\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n } else {\n if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n }\n });\n\n onCleanup(() => stopPopoverSync.dispose());\n\n onMounted(() => {\n let onTriggerClick: ((event: MouseEvent) => void) | null = null;\n let onTriggerKeydown: ((event: KeyboardEvent) => void) | null = null;\n\n if (triggerEl) {\n onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n if (isOpen.value) optionList.close('trigger');\n else openPopup('click');\n };\n onTriggerKeydown = (event: KeyboardEvent) => {\n handleTriggerKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n }\n\n return () => {\n if (triggerEl && onTriggerClick) triggerEl.removeEventListener('click', onTriggerClick);\n\n if (triggerEl && onTriggerKeydown) triggerEl.removeEventListener('keydown', onTriggerKeydown);\n };\n });\n\n return html`\n <slot style=\"display:none\"></slot>\n <ore-input\n class=\"trigger\"\n part=\"trigger\"\n readonly\n tabindex=\"${tabIndexAttr}\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-controls=\"${listboxId}\"\n aria-label=\"${triggerAriaLabel}\"\n aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n aria-expanded=\"${() => String(isOpen.value)}\"\n aria-invalid=\"${() => (props.error.value ? 'true' : null)}\"\n value=\"${inputValue}\"\n label=\"${inputLabel}\"\n placeholder=\"${inputPlaceholder}\"\n label-placement=\"${inputLabelPlacement}\"\n color=\"${inputColor}\"\n size=\"${inputSize}\"\n variant=\"${inputVariant}\"\n rounded=\"${inputRounded}\"\n helper=\"${inputHelper}\"\n error=\"${inputError}\"\n ?disabled=\"${inputDisabled}\"\n ?required=\"${inputRequired}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n ref=\"${(el: HTMLElement) => {\n triggerEl = el;\n }}\">\n ${() => {\n const icons = selectedIcons.value;\n\n if (!icons?.length) return html``;\n\n return html`<span class=\"trigger-selected-icons\" slot=\"prefix\">\n ${icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" aria-hidden=\"true\" class=\"trigger-selected-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon aria-hidden=\"true\" class=\"trigger-selected-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`;\n }}\n <div slot=\"prefix\" class=\"chips-row\" ?hidden=\"${() => !showChips.value}\">\n ${() =>\n selectedChipItems.value.map(\n (item) => html`\n <ore-chip\n value=\"${item.value}\"\n label=\"${item.label}\"\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=\"${props.color}\"\n @remove=\"${removeChip}\">\n ${item.label}\n </ore-chip>\n `,\n )}\n </div>\n <span slot=\"suffix\" class=\"trigger-suffix\" aria-hidden=\"true\">\n <span class=\"loader\"></span>\n <span class=\"trigger-icon\">\n <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </span>\n </ore-input>\n <div\n class=\"dropdown\"\n part=\"dropdown\"\n popover=\"manual\"\n ?data-open=\"${isOpen}\"\n role=\"listbox\"\n id=\"${listboxId}\"\n aria-label=\"Options\"\n ref=\"${(el: HTMLElement) => {\n dropdownEl = el;\n }}\">\n <div class=\"dropdown-loading\" ?hidden=\"${() => !isLoading.value}\">Loading…</div>\n <div class=\"dropdown-empty\" ?hidden=\"${() => isLoading.value || options.value.length > 0}\">No options</div>\n <div class=\"options-list\" ?hidden=\"${() => isLoading.value || options.value.length === 0}\">\n ${() =>\n flatRows.value.map((row) =>\n row.type === 'group'\n ? html`\n <div class=\"optgroup-label\" role=\"presentation\">${row.label}</div>\n `\n : html`\n <div\n class=\"option\"\n role=\"option\"\n id=\"${`${selectId}-opt-${row.idx}`}\"\n data-option-index=\"${String(row.idx)}\"\n data-option-value=\"${row.opt.value}\"\n aria-selected=\"${() => String(selectedValues.value.includes(row.opt.value))}\"\n aria-disabled=\"${() => String(row.opt.disabled)}\"\n ?data-focused=\"${() => focusedIndex.value === row.idx}\"\n ?data-selected=\"${() => selectedValues.value.includes(row.opt.value)}\"\n ?data-disabled=\"${() => row.opt.disabled}\"\n @click=\"${(e: MouseEvent) => {\n e.stopPropagation();\n selectOption(row.opt, e);\n }}\"\n @pointerenter=\"${() => {\n optionList.set(row.idx);\n }}\">\n ${\n row.opt.icons?.length\n ? html`<span class=\"option-icons\" aria-hidden=\"true\">\n ${row.opt.icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" class=\"option-icon option-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon class=\"option-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`\n : html``\n }\n <span>${row.opt.label}</span>\n ${\n row.opt.disabled && row.opt.disabledReason\n ? html`<small class=\"disabled-reason\" title=\"${row.opt.disabledReason}\">${row.opt.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 </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"select.cjs","names":[],"sources":["../src/inputs/select/select.ts"],"sourcesContent":["import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField, useSlots } from '@vielzeug/ore';\nimport { computed, effect, signal, watch } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail, OverlayOpenReason } from '../../core';\nimport { createChoiceField, createListboxDropdown, lifecycleSignal } from '../../core';\nimport type { SelectableFieldProps } from '../../shared';\nimport { disablableBundle, loadableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin } from '../../styles';\nimport { INPUT_VARIANTS, type InputVariant } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './select.css?inline';\n\nexport { ICON_TAG } from '../../content/icon/icon';\nexport { CHIP_TAG } from '../../feedback/chip/chip';\nexport { INPUT_TAG } from '../input/input';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\ntype OptionItem = {\n disabled: boolean;\n disabledReason?: string;\n group?: string;\n icons?: string[];\n label: string;\n value: string;\n};\n\nexport type OreSelectOptionInput = {\n disabled?: boolean;\n /** Explanation displayed and announced when the option is disabled. */\n disabledReason?: string;\n group?: string;\n /** Icon(s) rendered before the option label: registered name(s) or image URL(s). */\n icon?: string | string[];\n label?: string;\n value: string;\n};\n\ntype FlatRow =\n | {\n idx: number;\n opt: OptionItem;\n type: 'option';\n }\n | {\n label: string;\n type: 'group';\n };\n\n/**\n * Icon sources containing a path separator or a `data:` scheme are treated as image URLs and\n * rendered as `<img>`; anything else is a registered icon name rendered via `ore-icon`.\n */\nconst isIconImage = (icon: string): boolean => icon.includes('/') || icon.startsWith('data:');\n\n/** Normalizes an icon value: single name/URL, space-separated list, or array: to icon entries. */\nconst normalizeIcons = (icon: string | string[] | undefined): string[] | undefined => {\n const list = Array.isArray(icon) ? icon : icon?.split(' ');\n const icons = list?.map((entry) => entry.trim()).filter(Boolean);\n return icons?.length ? icons : undefined;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Component Props ─────────────────────────────────────────────────────────────\n\n/** Select component properties */\n\nexport type OreSelectEvents = {\n change: Event;\n input: Event;\n 'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreSelectProps = SelectableFieldProps<InputVariant> & {\n /** Hide the visible label while preserving the accessible name via `aria-label` */\n 'hide-label'?: boolean;\n /** Show loading state in dropdown */\n loading?: boolean;\n /** Allow selecting multiple options */\n multiple?: boolean;\n /** JS options array (alternative to slotted <option> elements) */\n options?: OreSelectOptionInput[];\n /** Mark the field as required */\n required?: boolean;\n};\n\n/**\n * A fully custom form-associated select dropdown with keyboard navigation and ARIA support.\n * Reads `<option>` and `<optgroup>` children from the default slot.\n *\n * @element ore-select\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {boolean} hide-label - Hide the visible label; the label text is exposed as `aria-label` on the trigger instead\n * @attr {string} value - Current selected value(s) (comma-separated for multiple)\n * @attr {string} placeholder - Placeholder when no option selected\n * @attr {string} name - Form field name\n * @attr {boolean} multiple - Enable multi-select\n * @attr {boolean} disabled - Disable the select\n * @attr {boolean} required - Required field\n * @attr {string} helper - Helper text below the select\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @fires input - Fired when selection changes.\n * @fires change - Fired when selection changes.\n * @fires open-change - Fired when the dropdown state changes. detail: { open, reason }\n *\n * @slot - `<option>` and `<optgroup>` elements\n *\n * @cssprop --select-bg - Background\n * @cssprop --select-border-color - Border color\n * @cssprop --select-min-width - Minimum width of the select; the trigger floors at it too, so the control never renders wider than its host\n * @cssprop --select-radius - Border radius\n * @cssprop --select-padding - Padding\n * @cssprop --select-font-size - Font size\n * @cssprop --select-placeholder-color - Placeholder text color\n *\n * @part trigger - The `ore-input` trigger element that opens the dropdown.\n * @part dropdown - The dropdown listbox panel container.\n *\n * @example\n * ```html\n * <ore-select label=\"Role\" value=\"admin\">\n * <option value=\"admin\">Administrator</option>\n * <option value=\"editor\">Editor</option>\n * <option value=\"viewer\">Viewer</option>\n * </ore-select>\n *\n * <ore-select label=\"Tags\" multiple color=\"primary\">\n * <optgroup label=\"Frontend\">\n * <option value=\"react\">React</option>\n * <option value=\"vue\">Vue</option>\n * </optgroup>\n * <optgroup label=\"Backend\">\n * <option value=\"node\">Node.js</option>\n * </optgroup>\n * </ore-select>\n * ```\n */\nexport const SELECT_TAG = 'ore-select' as const;\ndefine<OreSelectProps>(SELECT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...loadableBundle,\n ...roundableBundle,\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 multiple: prop.bool(false),\n name: prop.string(),\n options: prop.json(undefined as OreSelectOptionInput[] | undefined),\n placeholder: prop.string(),\n required: prop.bool(false),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.oneOf(INPUT_VARIANTS),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreSelectEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n // ────────────────────────────────────────────────────────────────\n // State & Context\n // ────────────────────────────────────────────────────────────────\n\n const slottedOptions = signal<OptionItem[]>([]);\n const isLoading = computed(() => Boolean(props.loading.value));\n\n // Merged options: explicit prop value overrides slotted options\n function normalizeOption(option: OreSelectOptionInput): OptionItem {\n return {\n disabled: Boolean(option.disabled),\n disabledReason: option.disabledReason,\n group: option.group,\n icons: normalizeIcons(option.icon),\n label: option.label ?? option.value,\n value: option.value,\n };\n }\n\n const options = computed(() => {\n const explicitOptions = props.options.value;\n\n return Array.isArray(explicitOptions) ? explicitOptions.map(normalizeOption) : slottedOptions.value;\n });\n let triggerEl: HTMLElement | null = null;\n let dropdownEl: HTMLElement | null = null;\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: 'select',\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const optionList = createListboxDropdown<OptionItem>({\n getBoundary: () => el,\n getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n getItems: () => options.value,\n getPanel: () => dropdownEl,\n getReference: () => triggerEl,\n getTrigger: () => triggerEl,\n isDisabled: () => choice.disabled.value,\n isItemDisabled: (option) => option.disabled,\n onClose: (reason) => {\n emit('open-change', { open: false, reason });\n choice.triggerValidation('blur');\n },\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n signal: abortSignal,\n });\n\n const { triggerValidation } = choice;\n const selectedValues = choice.selectedValues;\n const isDisabled = choice.disabled;\n\n defineFieldValue(\n el,\n () => choice.formValue.value,\n (value) => {\n choice.setValues(value ? value.split(',') : []);\n },\n );\n\n const { fieldId: selectId } = choice;\n const listboxId = `listbox-${selectId}`;\n const { focusedIndex, isOpen } = optionList;\n\n // Sync host attributes for CSS hooks\n bind({\n attr: {\n 'has-error': () => (props.error.value ? true : undefined),\n open: () => (isOpen.value ? true : undefined),\n size: props.size,\n variant: props.variant,\n },\n });\n\n // ────────────────────────────────────────────────────────────────\n // Option Reading from Slot\n // ────────────────────────────────────────────────────────────────\n\n function readOptions() {\n const slot = shadowRoot?.querySelector<HTMLSlotElement>('slot');\n\n if (!slot) return;\n\n const assigned = slot.assignedElements({ flatten: true });\n const items: OptionItem[] = [];\n\n for (const el of assigned) {\n if (el.tagName === 'OPTION') {\n const opt = el as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n } else if (el.tagName === 'OPTGROUP') {\n const group = el as HTMLOptGroupElement;\n const groupLabel = group.label;\n\n for (const child of Array.from(group.querySelectorAll('option'))) {\n const opt = child as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n group: groupLabel,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n }\n }\n }\n\n slottedOptions.value = items;\n }\n\n const displayLabel = computed(() => {\n if (selectedValues.value.length === 0) return '';\n\n if (props.multiple.value && selectedValues.value.length > 1) {\n return `${selectedValues.value.length} selected`;\n }\n\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.label ?? first;\n });\n const selectedIcons = computed(() => {\n if (props.multiple.value || selectedValues.value.length === 0) return undefined;\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.icons;\n });\n const selectedChipItems = computed(() => {\n if (!props.multiple.value) return [];\n\n return selectedValues.value.map((value) => ({\n label: options.value.find((o) => o.value === value)?.label ?? value,\n value,\n }));\n });\n const showChips = computed(() => props.multiple.value && selectedValues.value.length > 0);\n const triggerText = computed(() => displayLabel.value || props.placeholder.value || '');\n\n function buildFlatList(opts: OptionItem[]): FlatRow[] {\n const flat: FlatRow[] = [];\n const groups = new Map<string | undefined, OptionItem[]>();\n\n for (const opt of opts) {\n const key = opt.group;\n\n let group = groups.get(key);\n\n if (!group) {\n group = [];\n groups.set(key, group);\n }\n\n group.push(opt);\n }\n\n let globalIdx = 0;\n\n for (const [groupLabel, groupOpts] of groups) {\n if (groupLabel !== undefined) flat.push({ label: groupLabel, type: 'group' });\n\n for (const opt of groupOpts) flat.push({ idx: globalIdx++, opt, type: 'option' });\n }\n\n return flat;\n }\n\n const flatRows = computed(() => buildFlatList(options.value));\n\n function emitChange(): void {\n setFieldValue(el, choice.formValue.value);\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 choice.removeValue(value);\n emitChange();\n triggerValidation('change');\n }\n\n function openPopup(reason: OverlayOpenReason = 'programmatic') {\n // Show the popover before positioning so the positioner measures the element in the top\n // layer, not inside a possible ancestor containing block (a transformed dialog panel).\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n optionList.open(reason);\n\n requestAnimationFrame(() => {\n const selectedIndex =\n selectedValues.value.length > 0\n ? options.value.findIndex((option) => option.value === selectedValues.value[0])\n : -1;\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n\n return;\n }\n\n optionList.navigate('first');\n });\n }\n\n // Selection\n\n function selectOption(opt: OptionItem, _e?: Event) {\n if (opt.disabled) return;\n\n if (props.multiple.value) {\n choice.toggleValue(opt.value);\n } else {\n choice.selectValue(opt.value);\n optionList.close();\n }\n\n emitChange();\n triggerValidation('change');\n }\n\n // Keyboard navigation\n\n function handleTriggerKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n // Let optionList handle arrow key navigation\n if (optionList.handleKeydown(e)) return;\n\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault();\n\n if (isOpen.value) {\n const idx = focusedIndex.value;\n const opts = options.value;\n\n if (idx >= 0 && idx < opts.length) selectOption(opts[idx], e);\n } else {\n openPopup('keyboard');\n }\n\n break;\n case 'Tab':\n optionList.close();\n break;\n }\n }\n\n // ore-input prop helpers\n const inputValue = () => triggerText.value;\n const hideLabel = () => props['hide-label'].value;\n // When hide-label is set, suppress the visible label passed to ore-input (no inset\n // label renders, avoiding extra trigger height) but expose the label text as\n // aria-label on the trigger so the combobox retains its accessible name.\n const inputLabel = () => (hideLabel() ? '' : (props.label.value ?? ''));\n const triggerAriaLabel = () => (hideLabel() ? (props.label.value ?? '') : null);\n const inputPlaceholder = () => props.placeholder.value ?? '';\n const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\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 inputHelper = () => props.helper.value ?? '';\n const inputError = () => props.error.value ?? '';\n const inputDisabled = () => (isDisabled.value ? true : undefined);\n const inputRequired = () => (props.required.value ? true : undefined);\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n const tabIndexAttr = () => (isDisabled.value ? '-1' : '0');\n\n watch(slots.elements(), () => readOptions(), { immediate: true });\n\n const stopPopoverSync = effect(() => {\n if (isOpen.value) {\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n } else {\n if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n }\n });\n\n onCleanup(() => stopPopoverSync.dispose());\n\n onMounted(() => {\n let onTriggerClick: ((event: MouseEvent) => void) | null = null;\n let onTriggerKeydown: ((event: KeyboardEvent) => void) | null = null;\n\n if (triggerEl) {\n onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n if (isOpen.value) optionList.close('trigger');\n else openPopup('click');\n };\n onTriggerKeydown = (event: KeyboardEvent) => {\n handleTriggerKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n }\n\n return () => {\n if (triggerEl && onTriggerClick) triggerEl.removeEventListener('click', onTriggerClick);\n\n if (triggerEl && onTriggerKeydown) triggerEl.removeEventListener('keydown', onTriggerKeydown);\n };\n });\n\n return html`\n <slot style=\"display:none\"></slot>\n <ore-input\n class=\"trigger\"\n part=\"trigger\"\n readonly\n tabindex=\"${tabIndexAttr}\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-controls=\"${listboxId}\"\n aria-label=\"${triggerAriaLabel}\"\n aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n aria-expanded=\"${() => String(isOpen.value)}\"\n aria-invalid=\"${() => (props.error.value ? 'true' : null)}\"\n value=\"${inputValue}\"\n label=\"${inputLabel}\"\n placeholder=\"${inputPlaceholder}\"\n label-placement=\"${inputLabelPlacement}\"\n color=\"${inputColor}\"\n size=\"${inputSize}\"\n variant=\"${inputVariant}\"\n rounded=\"${inputRounded}\"\n helper=\"${inputHelper}\"\n error=\"${inputError}\"\n ?disabled=\"${inputDisabled}\"\n ?required=\"${inputRequired}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n ref=\"${(el: HTMLElement) => {\n triggerEl = el;\n }}\">\n ${() => {\n const icons = selectedIcons.value;\n\n if (!icons?.length) return html``;\n\n return html`<span class=\"trigger-selected-icons\" slot=\"prefix\">\n ${icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" aria-hidden=\"true\" class=\"trigger-selected-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon aria-hidden=\"true\" class=\"trigger-selected-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`;\n }}\n <div slot=\"prefix\" class=\"chips-row\" ?hidden=\"${() => !showChips.value}\">\n ${() =>\n selectedChipItems.value.map(\n (item) => html`\n <ore-chip\n value=\"${item.value}\"\n label=\"${item.label}\"\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=\"${props.color}\"\n @remove=\"${removeChip}\">\n ${item.label}\n </ore-chip>\n `,\n )}\n </div>\n <span slot=\"suffix\" class=\"trigger-suffix\" aria-hidden=\"true\">\n <span class=\"loader\"></span>\n <span class=\"trigger-icon\">\n <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </span>\n </ore-input>\n <div\n class=\"dropdown\"\n part=\"dropdown\"\n popover=\"manual\"\n ?data-open=\"${isOpen}\"\n role=\"listbox\"\n id=\"${listboxId}\"\n aria-label=\"Options\"\n ref=\"${(el: HTMLElement) => {\n dropdownEl = el;\n }}\">\n <div class=\"dropdown-loading\" ?hidden=\"${() => !isLoading.value}\">Loading…</div>\n <div class=\"dropdown-empty\" ?hidden=\"${() => isLoading.value || options.value.length > 0}\">No options</div>\n <div class=\"options-list\" ?hidden=\"${() => isLoading.value || options.value.length === 0}\">\n ${() =>\n flatRows.value.map((row) =>\n row.type === 'group'\n ? html`\n <div class=\"optgroup-label\" role=\"presentation\">${row.label}</div>\n `\n : html`\n <div\n class=\"option\"\n role=\"option\"\n id=\"${`${selectId}-opt-${row.idx}`}\"\n data-option-index=\"${String(row.idx)}\"\n data-option-value=\"${row.opt.value}\"\n aria-selected=\"${() => String(selectedValues.value.includes(row.opt.value))}\"\n aria-disabled=\"${() => String(row.opt.disabled)}\"\n ?data-focused=\"${() => focusedIndex.value === row.idx}\"\n ?data-selected=\"${() => selectedValues.value.includes(row.opt.value)}\"\n ?data-disabled=\"${() => row.opt.disabled}\"\n @click=\"${(e: MouseEvent) => {\n e.stopPropagation();\n selectOption(row.opt, e);\n }}\"\n @pointerenter=\"${() => {\n optionList.set(row.idx);\n }}\">\n ${\n row.opt.icons?.length\n ? html`<span class=\"option-icons\" aria-hidden=\"true\">\n ${row.opt.icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" class=\"option-icon option-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon class=\"option-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`\n : html``\n }\n <span>${row.opt.label}</span>\n ${\n row.opt.disabled && row.opt.disabledReason\n ? html`<small class=\"disabled-reason\" title=\"${row.opt.disabledReason}\">${row.opt.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 </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, componentStyles],\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","names":[],"sources":["../src/inputs/select/select.ts"],"sourcesContent":["import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField, useSlots } from '@vielzeug/ore';\nimport { computed, effect, signal, watch } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail, OverlayOpenReason } from '../../core';\nimport { createChoiceField, createListboxDropdown, lifecycleSignal } from '../../core';\nimport type { SelectableFieldProps } from '../../shared';\nimport { disablableBundle, loadableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin } from '../../styles';\nimport { INPUT_VARIANTS, type InputVariant } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './select.css?inline';\n\nexport { ICON_TAG } from '../../content/icon/icon';\nexport { CHIP_TAG } from '../../feedback/chip/chip';\nexport { INPUT_TAG } from '../input/input';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\ntype OptionItem = {\n disabled: boolean;\n disabledReason?: string;\n group?: string;\n icons?: string[];\n label: string;\n value: string;\n};\n\nexport type OreSelectOptionInput = {\n disabled?: boolean;\n /** Explanation displayed and announced when the option is disabled. */\n disabledReason?: string;\n group?: string;\n /** Icon(s) rendered before the option label: lucide name(s) or image URL(s). */\n icon?: string | string[];\n label?: string;\n value: string;\n};\n\ntype FlatRow =\n | {\n idx: number;\n opt: OptionItem;\n type: 'option';\n }\n | {\n label: string;\n type: 'group';\n };\n\n/**\n * Icon sources containing a path separator or a `data:` scheme are treated as image URLs and\n * rendered as `<img>`; anything else is a lucide icon name rendered via `ore-icon`.\n */\nconst isIconImage = (icon: string): boolean => icon.includes('/') || icon.startsWith('data:');\n\n/** Normalizes an icon value: single name/URL, space-separated list, or array: to icon entries. */\nconst normalizeIcons = (icon: string | string[] | undefined): string[] | undefined => {\n const list = Array.isArray(icon) ? icon : icon?.split(' ');\n const icons = list?.map((entry) => entry.trim()).filter(Boolean);\n return icons?.length ? icons : undefined;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Component Props ─────────────────────────────────────────────────────────────\n\n/** Select component properties */\n\nexport type OreSelectEvents = {\n change: Event;\n input: Event;\n 'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreSelectProps = SelectableFieldProps<InputVariant> & {\n /** Hide the visible label while preserving the accessible name via `aria-label` */\n 'hide-label'?: boolean;\n /** Show loading state in dropdown */\n loading?: boolean;\n /** Allow selecting multiple options */\n multiple?: boolean;\n /** JS options array (alternative to slotted <option> elements) */\n options?: OreSelectOptionInput[];\n /** Mark the field as required */\n required?: boolean;\n};\n\n/**\n * A fully custom form-associated select dropdown with keyboard navigation and ARIA support.\n * Reads `<option>` and `<optgroup>` children from the default slot.\n *\n * @element ore-select\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {boolean} hide-label - Hide the visible label; the label text is exposed as `aria-label` on the trigger instead\n * @attr {string} value - Current selected value(s) (comma-separated for multiple)\n * @attr {string} placeholder - Placeholder when no option selected\n * @attr {string} name - Form field name\n * @attr {boolean} multiple - Enable multi-select\n * @attr {boolean} disabled - Disable the select\n * @attr {boolean} required - Required field\n * @attr {string} helper - Helper text below the select\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @fires input - Fired when selection changes.\n * @fires change - Fired when selection changes.\n * @fires open-change - Fired when the dropdown state changes. detail: { open, reason }\n *\n * @slot - `<option>` and `<optgroup>` elements\n *\n * @cssprop --select-bg - Background\n * @cssprop --select-border-color - Border color\n * @cssprop --select-min-width - Minimum width of the select; the trigger floors at it too, so the control never renders wider than its host\n * @cssprop --select-radius - Border radius\n * @cssprop --select-padding - Padding\n * @cssprop --select-font-size - Font size\n * @cssprop --select-placeholder-color - Placeholder text color\n *\n * @part trigger - The `ore-input` trigger element that opens the dropdown.\n * @part dropdown - The dropdown listbox panel container.\n *\n * @example\n * ```html\n * <ore-select label=\"Role\" value=\"admin\">\n * <option value=\"admin\">Administrator</option>\n * <option value=\"editor\">Editor</option>\n * <option value=\"viewer\">Viewer</option>\n * </ore-select>\n *\n * <ore-select label=\"Tags\" multiple color=\"primary\">\n * <optgroup label=\"Frontend\">\n * <option value=\"react\">React</option>\n * <option value=\"vue\">Vue</option>\n * </optgroup>\n * <optgroup label=\"Backend\">\n * <option value=\"node\">Node.js</option>\n * </optgroup>\n * </ore-select>\n * ```\n */\nexport const SELECT_TAG = 'ore-select' as const;\ndefine<OreSelectProps>(SELECT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...loadableBundle,\n ...roundableBundle,\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 multiple: prop.bool(false),\n name: prop.string(),\n options: prop.json(undefined as OreSelectOptionInput[] | undefined),\n placeholder: prop.string(),\n required: prop.bool(false),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.oneOf(INPUT_VARIANTS),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreSelectEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n // ────────────────────────────────────────────────────────────────\n // State & Context\n // ────────────────────────────────────────────────────────────────\n\n const slottedOptions = signal<OptionItem[]>([]);\n const isLoading = computed(() => Boolean(props.loading.value));\n\n // Merged options: explicit prop value overrides slotted options\n function normalizeOption(option: OreSelectOptionInput): OptionItem {\n return {\n disabled: Boolean(option.disabled),\n disabledReason: option.disabledReason,\n group: option.group,\n icons: normalizeIcons(option.icon),\n label: option.label ?? option.value,\n value: option.value,\n };\n }\n\n const options = computed(() => {\n const explicitOptions = props.options.value;\n\n return Array.isArray(explicitOptions) ? explicitOptions.map(normalizeOption) : slottedOptions.value;\n });\n let triggerEl: HTMLElement | null = null;\n let dropdownEl: HTMLElement | null = null;\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: 'select',\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const optionList = createListboxDropdown<OptionItem>({\n getBoundary: () => el,\n getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n getItems: () => options.value,\n getPanel: () => dropdownEl,\n getReference: () => triggerEl,\n getTrigger: () => triggerEl,\n isDisabled: () => choice.disabled.value,\n isItemDisabled: (option) => option.disabled,\n onClose: (reason) => {\n emit('open-change', { open: false, reason });\n choice.triggerValidation('blur');\n },\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n signal: abortSignal,\n });\n\n const { triggerValidation } = choice;\n const selectedValues = choice.selectedValues;\n const isDisabled = choice.disabled;\n\n defineFieldValue(\n el,\n () => choice.formValue.value,\n (value) => {\n choice.setValues(value ? value.split(',') : []);\n },\n );\n\n const { fieldId: selectId } = choice;\n const listboxId = `listbox-${selectId}`;\n const { focusedIndex, isOpen } = optionList;\n\n // Sync host attributes for CSS hooks\n bind({\n attr: {\n 'has-error': () => (props.error.value ? true : undefined),\n open: () => (isOpen.value ? true : undefined),\n size: props.size,\n variant: props.variant,\n },\n });\n\n // ────────────────────────────────────────────────────────────────\n // Option Reading from Slot\n // ────────────────────────────────────────────────────────────────\n\n function readOptions() {\n const slot = shadowRoot?.querySelector<HTMLSlotElement>('slot');\n\n if (!slot) return;\n\n const assigned = slot.assignedElements({ flatten: true });\n const items: OptionItem[] = [];\n\n for (const el of assigned) {\n if (el.tagName === 'OPTION') {\n const opt = el as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n } else if (el.tagName === 'OPTGROUP') {\n const group = el as HTMLOptGroupElement;\n const groupLabel = group.label;\n\n for (const child of Array.from(group.querySelectorAll('option'))) {\n const opt = child as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n group: groupLabel,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n }\n }\n }\n\n slottedOptions.value = items;\n }\n\n const displayLabel = computed(() => {\n if (selectedValues.value.length === 0) return '';\n\n if (props.multiple.value && selectedValues.value.length > 1) {\n return `${selectedValues.value.length} selected`;\n }\n\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.label ?? first;\n });\n const selectedIcons = computed(() => {\n if (props.multiple.value || selectedValues.value.length === 0) return undefined;\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.icons;\n });\n const selectedChipItems = computed(() => {\n if (!props.multiple.value) return [];\n\n return selectedValues.value.map((value) => ({\n label: options.value.find((o) => o.value === value)?.label ?? value,\n value,\n }));\n });\n const showChips = computed(() => props.multiple.value && selectedValues.value.length > 0);\n const triggerText = computed(() => displayLabel.value || props.placeholder.value || '');\n\n function buildFlatList(opts: OptionItem[]): FlatRow[] {\n const flat: FlatRow[] = [];\n const groups = new Map<string | undefined, OptionItem[]>();\n\n for (const opt of opts) {\n const key = opt.group;\n\n let group = groups.get(key);\n\n if (!group) {\n group = [];\n groups.set(key, group);\n }\n\n group.push(opt);\n }\n\n let globalIdx = 0;\n\n for (const [groupLabel, groupOpts] of groups) {\n if (groupLabel !== undefined) flat.push({ label: groupLabel, type: 'group' });\n\n for (const opt of groupOpts) flat.push({ idx: globalIdx++, opt, type: 'option' });\n }\n\n return flat;\n }\n\n const flatRows = computed(() => buildFlatList(options.value));\n\n function emitChange(): void {\n setFieldValue(el, choice.formValue.value);\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 choice.removeValue(value);\n emitChange();\n triggerValidation('change');\n }\n\n function openPopup(reason: OverlayOpenReason = 'programmatic') {\n // Show the popover before positioning so the positioner measures the element in the top\n // layer, not inside a possible ancestor containing block (a transformed dialog panel).\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n optionList.open(reason);\n\n requestAnimationFrame(() => {\n const selectedIndex =\n selectedValues.value.length > 0\n ? options.value.findIndex((option) => option.value === selectedValues.value[0])\n : -1;\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n\n return;\n }\n\n optionList.navigate('first');\n });\n }\n\n // Selection\n\n function selectOption(opt: OptionItem, _e?: Event) {\n if (opt.disabled) return;\n\n if (props.multiple.value) {\n choice.toggleValue(opt.value);\n } else {\n choice.selectValue(opt.value);\n optionList.close();\n }\n\n emitChange();\n triggerValidation('change');\n }\n\n // Keyboard navigation\n\n function handleTriggerKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n // Let optionList handle arrow key navigation\n if (optionList.handleKeydown(e)) return;\n\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault();\n\n if (isOpen.value) {\n const idx = focusedIndex.value;\n const opts = options.value;\n\n if (idx >= 0 && idx < opts.length) selectOption(opts[idx], e);\n } else {\n openPopup('keyboard');\n }\n\n break;\n case 'Tab':\n optionList.close();\n break;\n }\n }\n\n // ore-input prop helpers\n const inputValue = () => triggerText.value;\n const hideLabel = () => props['hide-label'].value;\n // When hide-label is set, suppress the visible label passed to ore-input (no inset\n // label renders, avoiding extra trigger height) but expose the label text as\n // aria-label on the trigger so the combobox retains its accessible name.\n const inputLabel = () => (hideLabel() ? '' : (props.label.value ?? ''));\n const triggerAriaLabel = () => (hideLabel() ? (props.label.value ?? '') : null);\n const inputPlaceholder = () => props.placeholder.value ?? '';\n const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\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 inputHelper = () => props.helper.value ?? '';\n const inputError = () => props.error.value ?? '';\n const inputDisabled = () => (isDisabled.value ? true : undefined);\n const inputRequired = () => (props.required.value ? true : undefined);\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n const tabIndexAttr = () => (isDisabled.value ? '-1' : '0');\n\n watch(slots.elements(), () => readOptions(), { immediate: true });\n\n const stopPopoverSync = effect(() => {\n if (isOpen.value) {\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n } else {\n if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n }\n });\n\n onCleanup(() => stopPopoverSync.dispose());\n\n onMounted(() => {\n let onTriggerClick: ((event: MouseEvent) => void) | null = null;\n let onTriggerKeydown: ((event: KeyboardEvent) => void) | null = null;\n\n if (triggerEl) {\n onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n if (isOpen.value) optionList.close('trigger');\n else openPopup('click');\n };\n onTriggerKeydown = (event: KeyboardEvent) => {\n handleTriggerKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n }\n\n return () => {\n if (triggerEl && onTriggerClick) triggerEl.removeEventListener('click', onTriggerClick);\n\n if (triggerEl && onTriggerKeydown) triggerEl.removeEventListener('keydown', onTriggerKeydown);\n };\n });\n\n return html`\n <slot style=\"display:none\"></slot>\n <ore-input\n class=\"trigger\"\n part=\"trigger\"\n readonly\n tabindex=\"${tabIndexAttr}\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-controls=\"${listboxId}\"\n aria-label=\"${triggerAriaLabel}\"\n aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n aria-expanded=\"${() => String(isOpen.value)}\"\n aria-invalid=\"${() => (props.error.value ? 'true' : null)}\"\n value=\"${inputValue}\"\n label=\"${inputLabel}\"\n placeholder=\"${inputPlaceholder}\"\n label-placement=\"${inputLabelPlacement}\"\n color=\"${inputColor}\"\n size=\"${inputSize}\"\n variant=\"${inputVariant}\"\n rounded=\"${inputRounded}\"\n helper=\"${inputHelper}\"\n error=\"${inputError}\"\n ?disabled=\"${inputDisabled}\"\n ?required=\"${inputRequired}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n ref=\"${(el: HTMLElement) => {\n triggerEl = el;\n }}\">\n ${() => {\n const icons = selectedIcons.value;\n\n if (!icons?.length) return html``;\n\n return html`<span class=\"trigger-selected-icons\" slot=\"prefix\">\n ${icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" aria-hidden=\"true\" class=\"trigger-selected-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon aria-hidden=\"true\" class=\"trigger-selected-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`;\n }}\n <div slot=\"prefix\" class=\"chips-row\" ?hidden=\"${() => !showChips.value}\">\n ${() =>\n selectedChipItems.value.map(\n (item) => html`\n <ore-chip\n value=\"${item.value}\"\n label=\"${item.label}\"\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=\"${props.color}\"\n @remove=\"${removeChip}\">\n ${item.label}\n </ore-chip>\n `,\n )}\n </div>\n <span slot=\"suffix\" class=\"trigger-suffix\" aria-hidden=\"true\">\n <span class=\"loader\"></span>\n <span class=\"trigger-icon\">\n <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </span>\n </ore-input>\n <div\n class=\"dropdown\"\n part=\"dropdown\"\n popover=\"manual\"\n ?data-open=\"${isOpen}\"\n role=\"listbox\"\n id=\"${listboxId}\"\n aria-label=\"Options\"\n ref=\"${(el: HTMLElement) => {\n dropdownEl = el;\n }}\">\n <div class=\"dropdown-loading\" ?hidden=\"${() => !isLoading.value}\">Loading…</div>\n <div class=\"dropdown-empty\" ?hidden=\"${() => isLoading.value || options.value.length > 0}\">No options</div>\n <div class=\"options-list\" ?hidden=\"${() => isLoading.value || options.value.length === 0}\">\n ${() =>\n flatRows.value.map((row) =>\n row.type === 'group'\n ? html`\n <div class=\"optgroup-label\" role=\"presentation\">${row.label}</div>\n `\n : html`\n <div\n class=\"option\"\n role=\"option\"\n id=\"${`${selectId}-opt-${row.idx}`}\"\n data-option-index=\"${String(row.idx)}\"\n data-option-value=\"${row.opt.value}\"\n aria-selected=\"${() => String(selectedValues.value.includes(row.opt.value))}\"\n aria-disabled=\"${() => String(row.opt.disabled)}\"\n ?data-focused=\"${() => focusedIndex.value === row.idx}\"\n ?data-selected=\"${() => selectedValues.value.includes(row.opt.value)}\"\n ?data-disabled=\"${() => row.opt.disabled}\"\n @click=\"${(e: MouseEvent) => {\n e.stopPropagation();\n selectOption(row.opt, e);\n }}\"\n @pointerenter=\"${() => {\n optionList.set(row.idx);\n }}\">\n ${\n row.opt.icons?.length\n ? html`<span class=\"option-icons\" aria-hidden=\"true\">\n ${row.opt.icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" class=\"option-icon option-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon class=\"option-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`\n : html``\n }\n <span>${row.opt.label}</span>\n ${\n row.opt.disabled && row.opt.disabledReason\n ? html`<small class=\"disabled-reason\" title=\"${row.opt.disabledReason}\">${row.opt.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 </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"select.js","names":[],"sources":["../src/inputs/select/select.ts"],"sourcesContent":["import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField, useSlots } from '@vielzeug/ore';\nimport { computed, effect, signal, watch } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail, OverlayOpenReason } from '../../core';\nimport { createChoiceField, createListboxDropdown, lifecycleSignal } from '../../core';\nimport type { SelectableFieldProps } from '../../shared';\nimport { disablableBundle, loadableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin } from '../../styles';\nimport { INPUT_VARIANTS, type InputVariant } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './select.css?inline';\n\nexport { ICON_TAG } from '../../content/icon/icon';\nexport { CHIP_TAG } from '../../feedback/chip/chip';\nexport { INPUT_TAG } from '../input/input';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\ntype OptionItem = {\n disabled: boolean;\n disabledReason?: string;\n group?: string;\n icons?: string[];\n label: string;\n value: string;\n};\n\nexport type OreSelectOptionInput = {\n disabled?: boolean;\n /** Explanation displayed and announced when the option is disabled. */\n disabledReason?: string;\n group?: string;\n /** Icon(s) rendered before the option label: registered name(s) or image URL(s). */\n icon?: string | string[];\n label?: string;\n value: string;\n};\n\ntype FlatRow =\n | {\n idx: number;\n opt: OptionItem;\n type: 'option';\n }\n | {\n label: string;\n type: 'group';\n };\n\n/**\n * Icon sources containing a path separator or a `data:` scheme are treated as image URLs and\n * rendered as `<img>`; anything else is a registered icon name rendered via `ore-icon`.\n */\nconst isIconImage = (icon: string): boolean => icon.includes('/') || icon.startsWith('data:');\n\n/** Normalizes an icon value: single name/URL, space-separated list, or array: to icon entries. */\nconst normalizeIcons = (icon: string | string[] | undefined): string[] | undefined => {\n const list = Array.isArray(icon) ? icon : icon?.split(' ');\n const icons = list?.map((entry) => entry.trim()).filter(Boolean);\n return icons?.length ? icons : undefined;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Component Props ─────────────────────────────────────────────────────────────\n\n/** Select component properties */\n\nexport type OreSelectEvents = {\n change: Event;\n input: Event;\n 'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreSelectProps = SelectableFieldProps<InputVariant> & {\n /** Hide the visible label while preserving the accessible name via `aria-label` */\n 'hide-label'?: boolean;\n /** Show loading state in dropdown */\n loading?: boolean;\n /** Allow selecting multiple options */\n multiple?: boolean;\n /** JS options array (alternative to slotted <option> elements) */\n options?: OreSelectOptionInput[];\n /** Mark the field as required */\n required?: boolean;\n};\n\n/**\n * A fully custom form-associated select dropdown with keyboard navigation and ARIA support.\n * Reads `<option>` and `<optgroup>` children from the default slot.\n *\n * @element ore-select\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {boolean} hide-label - Hide the visible label; the label text is exposed as `aria-label` on the trigger instead\n * @attr {string} value - Current selected value(s) (comma-separated for multiple)\n * @attr {string} placeholder - Placeholder when no option selected\n * @attr {string} name - Form field name\n * @attr {boolean} multiple - Enable multi-select\n * @attr {boolean} disabled - Disable the select\n * @attr {boolean} required - Required field\n * @attr {string} helper - Helper text below the select\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @fires input - Fired when selection changes.\n * @fires change - Fired when selection changes.\n * @fires open-change - Fired when the dropdown state changes. detail: { open, reason }\n *\n * @slot - `<option>` and `<optgroup>` elements\n *\n * @cssprop --select-bg - Background\n * @cssprop --select-border-color - Border color\n * @cssprop --select-min-width - Minimum width of the select; the trigger floors at it too, so the control never renders wider than its host\n * @cssprop --select-radius - Border radius\n * @cssprop --select-padding - Padding\n * @cssprop --select-font-size - Font size\n * @cssprop --select-placeholder-color - Placeholder text color\n *\n * @part trigger - The `ore-input` trigger element that opens the dropdown.\n * @part dropdown - The dropdown listbox panel container.\n *\n * @example\n * ```html\n * <ore-select label=\"Role\" value=\"admin\">\n * <option value=\"admin\">Administrator</option>\n * <option value=\"editor\">Editor</option>\n * <option value=\"viewer\">Viewer</option>\n * </ore-select>\n *\n * <ore-select label=\"Tags\" multiple color=\"primary\">\n * <optgroup label=\"Frontend\">\n * <option value=\"react\">React</option>\n * <option value=\"vue\">Vue</option>\n * </optgroup>\n * <optgroup label=\"Backend\">\n * <option value=\"node\">Node.js</option>\n * </optgroup>\n * </ore-select>\n * ```\n */\nexport const SELECT_TAG = 'ore-select' as const;\ndefine<OreSelectProps>(SELECT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...loadableBundle,\n ...roundableBundle,\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 multiple: prop.bool(false),\n name: prop.string(),\n options: prop.json(undefined as OreSelectOptionInput[] | undefined),\n placeholder: prop.string(),\n required: prop.bool(false),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.oneOf(INPUT_VARIANTS),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreSelectEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n // ────────────────────────────────────────────────────────────────\n // State & Context\n // ────────────────────────────────────────────────────────────────\n\n const slottedOptions = signal<OptionItem[]>([]);\n const isLoading = computed(() => Boolean(props.loading.value));\n\n // Merged options: explicit prop value overrides slotted options\n function normalizeOption(option: OreSelectOptionInput): OptionItem {\n return {\n disabled: Boolean(option.disabled),\n disabledReason: option.disabledReason,\n group: option.group,\n icons: normalizeIcons(option.icon),\n label: option.label ?? option.value,\n value: option.value,\n };\n }\n\n const options = computed(() => {\n const explicitOptions = props.options.value;\n\n return Array.isArray(explicitOptions) ? explicitOptions.map(normalizeOption) : slottedOptions.value;\n });\n let triggerEl: HTMLElement | null = null;\n let dropdownEl: HTMLElement | null = null;\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: 'select',\n required: props.required,\n signal: abortSignal,\n value: props.value,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const optionList = createListboxDropdown<OptionItem>({\n getBoundary: () => el,\n getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n getItems: () => options.value,\n getPanel: () => dropdownEl,\n getReference: () => triggerEl,\n getTrigger: () => triggerEl,\n isDisabled: () => choice.disabled.value,\n isItemDisabled: (option) => option.disabled,\n onClose: (reason) => {\n emit('open-change', { open: false, reason });\n choice.triggerValidation('blur');\n },\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n signal: abortSignal,\n });\n\n const { triggerValidation } = choice;\n const selectedValues = choice.selectedValues;\n const isDisabled = choice.disabled;\n\n defineFieldValue(\n el,\n () => choice.formValue.value,\n (value) => {\n choice.setValues(value ? value.split(',') : []);\n },\n );\n\n const { fieldId: selectId } = choice;\n const listboxId = `listbox-${selectId}`;\n const { focusedIndex, isOpen } = optionList;\n\n // Sync host attributes for CSS hooks\n bind({\n attr: {\n 'has-error': () => (props.error.value ? true : undefined),\n open: () => (isOpen.value ? true : undefined),\n size: props.size,\n variant: props.variant,\n },\n });\n\n // ────────────────────────────────────────────────────────────────\n // Option Reading from Slot\n // ────────────────────────────────────────────────────────────────\n\n function readOptions() {\n const slot = shadowRoot?.querySelector<HTMLSlotElement>('slot');\n\n if (!slot) return;\n\n const assigned = slot.assignedElements({ flatten: true });\n const items: OptionItem[] = [];\n\n for (const el of assigned) {\n if (el.tagName === 'OPTION') {\n const opt = el as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n } else if (el.tagName === 'OPTGROUP') {\n const group = el as HTMLOptGroupElement;\n const groupLabel = group.label;\n\n for (const child of Array.from(group.querySelectorAll('option'))) {\n const opt = child as HTMLOptionElement;\n\n items.push({\n disabled: opt.disabled,\n disabledReason: opt.dataset.disabledReason,\n group: groupLabel,\n icons: normalizeIcons(opt.dataset.icon),\n label: opt.text || opt.value,\n value: opt.value,\n });\n }\n }\n }\n\n slottedOptions.value = items;\n }\n\n const displayLabel = computed(() => {\n if (selectedValues.value.length === 0) return '';\n\n if (props.multiple.value && selectedValues.value.length > 1) {\n return `${selectedValues.value.length} selected`;\n }\n\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.label ?? first;\n });\n const selectedIcons = computed(() => {\n if (props.multiple.value || selectedValues.value.length === 0) return undefined;\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.icons;\n });\n const selectedChipItems = computed(() => {\n if (!props.multiple.value) return [];\n\n return selectedValues.value.map((value) => ({\n label: options.value.find((o) => o.value === value)?.label ?? value,\n value,\n }));\n });\n const showChips = computed(() => props.multiple.value && selectedValues.value.length > 0);\n const triggerText = computed(() => displayLabel.value || props.placeholder.value || '');\n\n function buildFlatList(opts: OptionItem[]): FlatRow[] {\n const flat: FlatRow[] = [];\n const groups = new Map<string | undefined, OptionItem[]>();\n\n for (const opt of opts) {\n const key = opt.group;\n\n let group = groups.get(key);\n\n if (!group) {\n group = [];\n groups.set(key, group);\n }\n\n group.push(opt);\n }\n\n let globalIdx = 0;\n\n for (const [groupLabel, groupOpts] of groups) {\n if (groupLabel !== undefined) flat.push({ label: groupLabel, type: 'group' });\n\n for (const opt of groupOpts) flat.push({ idx: globalIdx++, opt, type: 'option' });\n }\n\n return flat;\n }\n\n const flatRows = computed(() => buildFlatList(options.value));\n\n function emitChange(): void {\n setFieldValue(el, choice.formValue.value);\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 choice.removeValue(value);\n emitChange();\n triggerValidation('change');\n }\n\n function openPopup(reason: OverlayOpenReason = 'programmatic') {\n // Show the popover before positioning so the positioner measures the element in the top\n // layer, not inside a possible ancestor containing block (a transformed dialog panel).\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n optionList.open(reason);\n\n requestAnimationFrame(() => {\n const selectedIndex =\n selectedValues.value.length > 0\n ? options.value.findIndex((option) => option.value === selectedValues.value[0])\n : -1;\n\n if (selectedIndex >= 0) {\n optionList.set(selectedIndex);\n\n return;\n }\n\n optionList.navigate('first');\n });\n }\n\n // Selection\n\n function selectOption(opt: OptionItem, _e?: Event) {\n if (opt.disabled) return;\n\n if (props.multiple.value) {\n choice.toggleValue(opt.value);\n } else {\n choice.selectValue(opt.value);\n optionList.close();\n }\n\n emitChange();\n triggerValidation('change');\n }\n\n // Keyboard navigation\n\n function handleTriggerKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n // Let optionList handle arrow key navigation\n if (optionList.handleKeydown(e)) return;\n\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault();\n\n if (isOpen.value) {\n const idx = focusedIndex.value;\n const opts = options.value;\n\n if (idx >= 0 && idx < opts.length) selectOption(opts[idx], e);\n } else {\n openPopup('keyboard');\n }\n\n break;\n case 'Tab':\n optionList.close();\n break;\n }\n }\n\n // ore-input prop helpers\n const inputValue = () => triggerText.value;\n const hideLabel = () => props['hide-label'].value;\n // When hide-label is set, suppress the visible label passed to ore-input (no inset\n // label renders, avoiding extra trigger height) but expose the label text as\n // aria-label on the trigger so the combobox retains its accessible name.\n const inputLabel = () => (hideLabel() ? '' : (props.label.value ?? ''));\n const triggerAriaLabel = () => (hideLabel() ? (props.label.value ?? '') : null);\n const inputPlaceholder = () => props.placeholder.value ?? '';\n const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\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 inputHelper = () => props.helper.value ?? '';\n const inputError = () => props.error.value ?? '';\n const inputDisabled = () => (isDisabled.value ? true : undefined);\n const inputRequired = () => (props.required.value ? true : undefined);\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n const tabIndexAttr = () => (isDisabled.value ? '-1' : '0');\n\n watch(slots.elements(), () => readOptions(), { immediate: true });\n\n const stopPopoverSync = effect(() => {\n if (isOpen.value) {\n if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n } else {\n if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n }\n });\n\n onCleanup(() => stopPopoverSync.dispose());\n\n onMounted(() => {\n let onTriggerClick: ((event: MouseEvent) => void) | null = null;\n let onTriggerKeydown: ((event: KeyboardEvent) => void) | null = null;\n\n if (triggerEl) {\n onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n if (isOpen.value) optionList.close('trigger');\n else openPopup('click');\n };\n onTriggerKeydown = (event: KeyboardEvent) => {\n handleTriggerKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n }\n\n return () => {\n if (triggerEl && onTriggerClick) triggerEl.removeEventListener('click', onTriggerClick);\n\n if (triggerEl && onTriggerKeydown) triggerEl.removeEventListener('keydown', onTriggerKeydown);\n };\n });\n\n return html`\n <slot style=\"display:none\"></slot>\n <ore-input\n class=\"trigger\"\n part=\"trigger\"\n readonly\n tabindex=\"${tabIndexAttr}\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-controls=\"${listboxId}\"\n aria-label=\"${triggerAriaLabel}\"\n aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n aria-expanded=\"${() => String(isOpen.value)}\"\n aria-invalid=\"${() => (props.error.value ? 'true' : null)}\"\n value=\"${inputValue}\"\n label=\"${inputLabel}\"\n placeholder=\"${inputPlaceholder}\"\n label-placement=\"${inputLabelPlacement}\"\n color=\"${inputColor}\"\n size=\"${inputSize}\"\n variant=\"${inputVariant}\"\n rounded=\"${inputRounded}\"\n helper=\"${inputHelper}\"\n error=\"${inputError}\"\n ?disabled=\"${inputDisabled}\"\n ?required=\"${inputRequired}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n ref=\"${(el: HTMLElement) => {\n triggerEl = el;\n }}\">\n ${() => {\n const icons = selectedIcons.value;\n\n if (!icons?.length) return html``;\n\n return html`<span class=\"trigger-selected-icons\" slot=\"prefix\">\n ${icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" aria-hidden=\"true\" class=\"trigger-selected-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon aria-hidden=\"true\" class=\"trigger-selected-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`;\n }}\n <div slot=\"prefix\" class=\"chips-row\" ?hidden=\"${() => !showChips.value}\">\n ${() =>\n selectedChipItems.value.map(\n (item) => html`\n <ore-chip\n value=\"${item.value}\"\n label=\"${item.label}\"\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=\"${props.color}\"\n @remove=\"${removeChip}\">\n ${item.label}\n </ore-chip>\n `,\n )}\n </div>\n <span slot=\"suffix\" class=\"trigger-suffix\" aria-hidden=\"true\">\n <span class=\"loader\"></span>\n <span class=\"trigger-icon\">\n <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </span>\n </ore-input>\n <div\n class=\"dropdown\"\n part=\"dropdown\"\n popover=\"manual\"\n ?data-open=\"${isOpen}\"\n role=\"listbox\"\n id=\"${listboxId}\"\n aria-label=\"Options\"\n ref=\"${(el: HTMLElement) => {\n dropdownEl = el;\n }}\">\n <div class=\"dropdown-loading\" ?hidden=\"${() => !isLoading.value}\">Loading…</div>\n <div class=\"dropdown-empty\" ?hidden=\"${() => isLoading.value || options.value.length > 0}\">No options</div>\n <div class=\"options-list\" ?hidden=\"${() => isLoading.value || options.value.length === 0}\">\n ${() =>\n flatRows.value.map((row) =>\n row.type === 'group'\n ? html`\n <div class=\"optgroup-label\" role=\"presentation\">${row.label}</div>\n `\n : html`\n <div\n class=\"option\"\n role=\"option\"\n id=\"${`${selectId}-opt-${row.idx}`}\"\n data-option-index=\"${String(row.idx)}\"\n data-option-value=\"${row.opt.value}\"\n aria-selected=\"${() => String(selectedValues.value.includes(row.opt.value))}\"\n aria-disabled=\"${() => String(row.opt.disabled)}\"\n ?data-focused=\"${() => focusedIndex.value === row.idx}\"\n ?data-selected=\"${() => selectedValues.value.includes(row.opt.value)}\"\n ?data-disabled=\"${() => row.opt.disabled}\"\n @click=\"${(e: MouseEvent) => {\n e.stopPropagation();\n selectOption(row.opt, e);\n }}\"\n @pointerenter=\"${() => {\n optionList.set(row.idx);\n }}\">\n ${\n row.opt.icons?.length\n ? html`<span class=\"option-icons\" aria-hidden=\"true\">\n ${row.opt.icons.map((icon) =>\n isIconImage(icon)\n ? html`<img alt=\"\" class=\"option-icon option-icon--image\" src=\"${icon}\" />`\n : html`<ore-icon class=\"option-icon\" name=\"${icon}\" size=\"14\"></ore-icon>`,\n )}\n </span>`\n : html``\n }\n <span>${row.opt.label}</span>\n ${\n row.opt.disabled && row.opt.disabledReason\n ? html`<small class=\"disabled-reason\" title=\"${row.opt.disabledReason}\">${row.opt.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 </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, componentStyles],\n});\n"],"mappings":"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"}
@@ -16,11 +16,11 @@ export declare const loadableBundle: {
16
16
  };
17
17
  /** Prop bundle for components with configurable border-radius. */
18
18
  export declare const roundableBundle: {
19
- rounded: import("@vielzeug/ore").PropDef<"sm" | "md" | "lg" | "none" | "xl" | "2xl" | "3xl" | "full" | undefined>;
19
+ rounded: import("@vielzeug/ore").PropDef<"none" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full" | undefined>;
20
20
  };
21
21
  /** Prop bundle for components with an elevation / box-shadow. */
22
22
  export declare const elevatableBundle: {
23
- elevation: import("@vielzeug/ore").PropDef<0 | 2 | 1 | 3 | 5 | 4 | undefined>;
23
+ elevation: import("@vielzeug/ore").PropDef<0 | 4 | 1 | 2 | 3 | 5 | undefined>;
24
24
  };
25
25
  /**
26
26
  * Convenience bundle combining the five most common interactive-component props:
@@ -35,7 +35,7 @@ export declare const elevatableBundle: {
35
35
  * ```
36
36
  */
37
37
  export declare const commonProps: {
38
- rounded: import("@vielzeug/ore").PropDef<"sm" | "md" | "lg" | "none" | "xl" | "2xl" | "3xl" | "full" | undefined>;
38
+ rounded: import("@vielzeug/ore").PropDef<"none" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full" | undefined>;
39
39
  loading: import("@vielzeug/ore").PropDef<boolean>;
40
40
  disabled: import("@vielzeug/ore").PropDef<boolean>;
41
41
  size: import("@vielzeug/ore").PropDef<"sm" | "md" | "lg" | undefined>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/refine",
3
- "version": "26.10.10",
3
+ "version": "26.10.11",
4
4
  "description": "Accessible, themeable web components built on ore",
5
5
  "keywords": [
6
6
  "web-components",
@@ -27,7 +27,8 @@
27
27
  "node": ">=22"
28
28
  },
29
29
  "files": [
30
- "dist"
30
+ "dist",
31
+ "THIRD_PARTY_NOTICES"
31
32
  ],
32
33
  "types": "./dist/index.d.ts",
33
34
  "exports": {
@@ -41,10 +42,25 @@
41
42
  "require": "./dist/theme.cjs",
42
43
  "types": "./dist/theme.d.ts"
43
44
  },
44
- "./icon-lucide": {
45
- "import": "./dist/icon-lucide.js",
46
- "require": "./dist/icon-lucide.cjs",
47
- "types": "./dist/icon-lucide.d.ts"
45
+ "./icons": {
46
+ "import": "./dist/icons/index.js",
47
+ "require": "./dist/icons/index.cjs",
48
+ "types": "./dist/icons/index.d.ts"
49
+ },
50
+ "./icons/lucide": {
51
+ "import": "./dist/icons/lucide.js",
52
+ "require": "./dist/icons/lucide.cjs",
53
+ "types": "./dist/icons/lucide.d.ts"
54
+ },
55
+ "./icons/lucide/all": {
56
+ "import": "./dist/icons/lucide/all.js",
57
+ "require": "./dist/icons/lucide/all.cjs",
58
+ "types": "./dist/icons/lucide/all.d.ts"
59
+ },
60
+ "./icons/iconify": {
61
+ "import": "./dist/icons/iconify.js",
62
+ "require": "./dist/icons/iconify.cjs",
63
+ "types": "./dist/icons/iconify.d.ts"
48
64
  },
49
65
  "./styles/animation.css": {
50
66
  "import": "./dist/styles/animation.css",
@@ -79,6 +95,21 @@
79
95
  "./frameworks/vue": {
80
96
  "types": "./dist/frameworks/vue.d.ts"
81
97
  },
98
+ "./icons/heroicons": {
99
+ "import": "./dist/icons/heroicons.js",
100
+ "require": "./dist/icons/heroicons.cjs",
101
+ "types": "./dist/icons/heroicons.d.ts"
102
+ },
103
+ "./icons/tabler": {
104
+ "import": "./dist/icons/tabler.js",
105
+ "require": "./dist/icons/tabler.cjs",
106
+ "types": "./dist/icons/tabler.d.ts"
107
+ },
108
+ "./icons/mdi": {
109
+ "import": "./dist/icons/mdi.js",
110
+ "require": "./dist/icons/mdi.cjs",
111
+ "types": "./dist/icons/mdi.d.ts"
112
+ },
82
113
  "./accordion": {
83
114
  "import": "./dist/accordion.js",
84
115
  "require": "./dist/accordion.cjs",
@@ -465,8 +496,17 @@
465
496
  "theme": [
466
497
  "dist/theme.d.ts"
467
498
  ],
468
- "icon-lucide": [
469
- "dist/icon-lucide.d.ts"
499
+ "icons": [
500
+ "dist/icons/index.d.ts"
501
+ ],
502
+ "icons/lucide": [
503
+ "dist/icons/lucide.d.ts"
504
+ ],
505
+ "icons/lucide/all": [
506
+ "dist/icons/lucide/all.d.ts"
507
+ ],
508
+ "icons/iconify": [
509
+ "dist/icons/iconify.d.ts"
470
510
  ],
471
511
  "frameworks/elements": [
472
512
  "dist/frameworks/elements.d.ts"
@@ -477,6 +517,15 @@
477
517
  "frameworks/vue": [
478
518
  "dist/frameworks/vue.d.ts"
479
519
  ],
520
+ "icons/heroicons": [
521
+ "dist/icons/heroicons.d.ts"
522
+ ],
523
+ "icons/tabler": [
524
+ "dist/icons/tabler.d.ts"
525
+ ],
526
+ "icons/mdi": [
527
+ "dist/icons/mdi.d.ts"
528
+ ],
480
529
  "accordion": [
481
530
  "dist/disclosure/accordion/accordion.d.ts"
482
531
  ],
@@ -711,9 +760,11 @@
711
760
  "./dist/*.js",
712
761
  "./dist/*.cjs",
713
762
  "./dist/core/*",
763
+ "./dist/icons/**",
714
764
  "./dist/styles/**",
715
- "./src/core/icons.ts",
716
- "./src/icon-lucide.ts"
765
+ "./src/icons/defaults.ts",
766
+ "./src/content/icon/icon.ts",
767
+ "./src/icons/lucide/all.ts"
717
768
  ],
718
769
  "scripts": {
719
770
  "analyze": "custom-elements-manifest analyze --config scripts/refine-manifest.mjs",
@@ -737,19 +788,26 @@
737
788
  "test:e2e": "playwright test"
738
789
  },
739
790
  "dependencies": {
740
- "@vielzeug/arsenal": "26.10.10",
741
- "@vielzeug/dnd": "26.10.10",
742
- "@vielzeug/focus": "26.10.10",
743
- "@vielzeug/gesture": "26.10.10",
744
- "@vielzeug/keymap": "26.10.10",
745
- "@vielzeug/orbit": "26.10.10",
746
- "@vielzeug/ore": "26.10.10",
747
- "@vielzeug/ripple": "26.10.10",
748
- "@vielzeug/sentinel": "26.10.10",
749
- "@vielzeug/sigil": "26.10.10",
750
- "@vielzeug/tempo": "26.10.10",
791
+ "@vielzeug/arsenal": "26.10.11",
792
+ "@vielzeug/dnd": "26.10.11",
793
+ "@vielzeug/focus": "26.10.11",
794
+ "@vielzeug/gesture": "26.10.11",
795
+ "@vielzeug/keymap": "26.10.11",
796
+ "@vielzeug/orbit": "26.10.11",
797
+ "@vielzeug/ore": "26.10.11",
798
+ "@vielzeug/ripple": "26.10.11",
799
+ "@vielzeug/sentinel": "26.10.11",
800
+ "@vielzeug/sigil": "26.10.11",
801
+ "@vielzeug/tempo": "26.10.11"
802
+ },
803
+ "peerDependencies": {
751
804
  "lucide": "^1.48.0"
752
805
  },
806
+ "peerDependenciesMeta": {
807
+ "lucide": {
808
+ "optional": true
809
+ }
810
+ },
753
811
  "devDependencies": {
754
812
  "@axe-core/playwright": "^4.13.0",
755
813
  "@biomejs/biome": "^2.5.14",
@@ -757,11 +815,12 @@
757
815
  "@playwright/test": "^1.63.0",
758
816
  "@types/culori": "^4.0.1",
759
817
  "@types/node": "^26.6.2",
760
- "@vielzeug/assay": "26.10.10",
818
+ "@vielzeug/assay": "26.10.11",
761
819
  "axe-core": "^4.13.0",
762
820
  "browserslist": "^4.29.0",
763
821
  "culori": "^4.0.2",
764
822
  "lightningcss": "^1.33.0",
823
+ "lucide": "^1.48.0",
765
824
  "typescript": "^6.0.3",
766
825
  "vite": "^8.3.0",
767
826
  "vitest": "^5.0.1"
@@ -1 +0,0 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,__copyProps=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},__toESM=(n,r,o)=>(o=n==null?{}:e(i(n)),__copyProps(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n));exports.__toESM=__toESM;
@@ -1,2 +0,0 @@
1
- var e=new Map;function registerIcons(t){for(let[n,r]of Object.entries(t))e.set(n,r)}var toPascalCase=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``),resolveIcon=t=>e.get(t)??e.get(toPascalCase(t));exports.registerIcons=registerIcons,exports.resolveIcon=resolveIcon;
2
- //# sourceMappingURL=icon-registry.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icon-registry.cjs","names":[],"sources":["../../src/core/icon-registry.ts"],"sourcesContent":["/**\n * The synchronous icon registry `ore-icon` resolves names from. Kept as a leaf\n * module (no component imports) so both `icon.ts` and icon-set modules can\n * import it without cycles. It starts with the icons refine's own components\n * render (`core/icons.ts`) and grows through `registerIcons()`.\n */\n\n/** One icon: SVG child tags with their attributes, in render order. */\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst registry = new Map<string, IconNode>();\n\n/**\n * Register icons (or override existing ones) by name. Keys may be kebab-case or\n * PascalCase: both resolve.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n for (const [name, node] of Object.entries(icons)) {\n registry.set(name, node);\n }\n}\n\nconst toPascalCase = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n\nexport const resolveIcon = (name: string): IconNode | undefined =>\n registry.get(name) ?? registry.get(toPascalCase(name));\n"],"mappings":"AAUA,IAAM,EAAW,IAAI,IAMrB,SAAgB,cAAc,EAAuC,CACnE,IAAK,GAAM,CAAC,EAAM,KAAS,OAAO,QAAQ,CAAK,EAC7C,EAAS,IAAI,EAAM,CAAI,CAE3B,CAEA,IAAM,aAAgB,GACpB,EACG,QAAQ,qBAAsB,OAAO,CAAC,CACtC,MAAM,eAAe,CAAC,CACtB,OAAO,OAAO,CAAC,CACf,IAAK,GAAM,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,EAAI,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAChE,KAAK,EAAE,EAEC,YAAe,GAC1B,EAAS,IAAI,CAAI,GAAK,EAAS,IAAI,aAAa,CAAI,CAAC"}
@@ -1,15 +0,0 @@
1
- /**
2
- * The synchronous icon registry `ore-icon` resolves names from. Kept as a leaf
3
- * module (no component imports) so both `icon.ts` and icon-set modules can
4
- * import it without cycles. It starts with the icons refine's own components
5
- * render (`core/icons.ts`) and grows through `registerIcons()`.
6
- */
7
- /** One icon: SVG child tags with their attributes, in render order. */
8
- export type IconNode = Array<[string, Record<string, string | number | undefined>]>;
9
- /**
10
- * Register icons (or override existing ones) by name. Keys may be kebab-case or
11
- * PascalCase: both resolve.
12
- */
13
- export declare function registerIcons(icons: Record<string, IconNode>): void;
14
- export declare const resolveIcon: (name: string) => IconNode | undefined;
15
- //# sourceMappingURL=icon-registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icon-registry.d.ts","sourceRoot":"","sources":["../../src/core/icon-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,uEAAuE;AACvE,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAIpF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAInE;AAUD,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,QAAQ,GAAG,SACE,CAAC"}
@@ -1,2 +0,0 @@
1
- var e=new Map;function registerIcons(t){for(let[n,r]of Object.entries(t))e.set(n,r)}var toPascalCase=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``),resolveIcon=t=>e.get(t)??e.get(toPascalCase(t));export{registerIcons,resolveIcon};
2
- //# sourceMappingURL=icon-registry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icon-registry.js","names":[],"sources":["../../src/core/icon-registry.ts"],"sourcesContent":["/**\n * The synchronous icon registry `ore-icon` resolves names from. Kept as a leaf\n * module (no component imports) so both `icon.ts` and icon-set modules can\n * import it without cycles. It starts with the icons refine's own components\n * render (`core/icons.ts`) and grows through `registerIcons()`.\n */\n\n/** One icon: SVG child tags with their attributes, in render order. */\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst registry = new Map<string, IconNode>();\n\n/**\n * Register icons (or override existing ones) by name. Keys may be kebab-case or\n * PascalCase: both resolve.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n for (const [name, node] of Object.entries(icons)) {\n registry.set(name, node);\n }\n}\n\nconst toPascalCase = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n\nexport const resolveIcon = (name: string): IconNode | undefined =>\n registry.get(name) ?? registry.get(toPascalCase(name));\n"],"mappings":"AAUA,IAAM,EAAW,IAAI,IAMrB,SAAgB,cAAc,EAAuC,CACnE,IAAK,GAAM,CAAC,EAAM,KAAS,OAAO,QAAQ,CAAK,EAC7C,EAAS,IAAI,EAAM,CAAI,CAE3B,CAEA,IAAM,aAAgB,GACpB,EACG,QAAQ,qBAAsB,OAAO,CAAC,CACtC,MAAM,eAAe,CAAC,CACtB,OAAO,OAAO,CAAC,CACf,IAAK,GAAM,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,EAAI,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAChE,KAAK,EAAE,EAEC,YAAe,GAC1B,EAAS,IAAI,CAAI,GAAK,EAAS,IAAI,aAAa,CAAI,CAAC"}
@@ -1,2 +0,0 @@
1
- const e=require("./icon-registry.cjs");let t=require("lucide");e.registerIcons({AlertCircle:t.AlertCircle,ArrowRight:t.ArrowRight,ArrowUpDown:t.ArrowUpDown,Calendar:t.Calendar,Camera:t.Camera,ChartLine:t.ChartLine,Check:t.Check,ChevronDown:t.ChevronDown,ChevronLeft:t.ChevronLeft,ChevronRight:t.ChevronRight,ChevronsLeft:t.ChevronsLeft,ChevronsRight:t.ChevronsRight,CircleAlert:t.CircleAlert,Clock:t.Clock,Columns2:t.Columns2,Copy:t.Copy,Eye:t.Eye,EyeOff:t.EyeOff,File:t.File,Filter:t.Filter,Gauge:t.Gauge,Loader2:t.Loader2,Mail:t.Mail,Menu:t.Menu,Minus:t.Minus,Package:t.Package,Pause:t.Pause,Play:t.Play,Plus:t.Plus,RefreshCw:t.RefreshCw,Save:t.Save,Search:t.Search,Square:t.Square,Star:t.Star,Trash2:t.Trash2,TriangleAlert:t.TriangleAlert,Upload:t.Upload,User:t.User,X:t.X,Zap:t.Zap});
2
- //# sourceMappingURL=icons.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icons.cjs","names":[],"sources":["../../src/core/icons.ts"],"sourcesContent":["/**\n * The icons refine's own components render: chevrons, close marks, spinners,\n * the icons inputs and overlays label themselves with. Imported by `icon.ts`\n * so they resolve wherever `ore-icon` is used. Apps needing more than this set\n * register their own via `registerIcons()` or import `@vielzeug/refine/icon-lucide`\n * for the complete Lucide library.\n */\nimport {\n AlertCircle,\n ArrowRight,\n ArrowUpDown,\n Calendar,\n Camera,\n ChartLine,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronsLeft,\n ChevronsRight,\n CircleAlert,\n Clock,\n Columns2,\n Copy,\n Eye,\n EyeOff,\n File,\n Filter,\n Gauge,\n Loader2,\n Mail,\n Menu,\n Minus,\n Package,\n Pause,\n Play,\n Plus,\n RefreshCw,\n Save,\n Search,\n Square,\n Star,\n Trash2,\n TriangleAlert,\n Upload,\n User,\n X,\n Zap,\n} from 'lucide';\nimport { registerIcons } from './icon-registry';\n\nregisterIcons({\n AlertCircle: AlertCircle,\n ArrowRight: ArrowRight,\n ArrowUpDown: ArrowUpDown,\n Calendar: Calendar,\n Camera: Camera,\n ChartLine: ChartLine,\n Check: Check,\n ChevronDown: ChevronDown,\n ChevronLeft: ChevronLeft,\n ChevronRight: ChevronRight,\n ChevronsLeft: ChevronsLeft,\n ChevronsRight: ChevronsRight,\n CircleAlert: CircleAlert,\n Clock: Clock,\n Columns2: Columns2,\n Copy: Copy,\n Eye: Eye,\n EyeOff: EyeOff,\n File: File,\n Filter: Filter,\n Gauge: Gauge,\n Loader2: Loader2,\n Mail: Mail,\n Menu: Menu,\n Minus: Minus,\n Package: Package,\n Pause: Pause,\n Play: Play,\n Plus: Plus,\n RefreshCw: RefreshCw,\n Save: Save,\n Search: Search,\n Square: Square,\n Star: Star,\n Trash2: Trash2,\n TriangleAlert: TriangleAlert,\n Upload: Upload,\n User: User,\n X: X,\n Zap: Zap,\n});\n"],"mappings":"+DAmDA,EAAA,cAAc,CACC,YAAA,EAAA,YACD,WAAA,EAAA,WACC,YAAA,EAAA,YACH,SAAA,EAAA,SACF,OAAA,EAAA,OACG,UAAA,EAAA,UACJ,MAAA,EAAA,MACM,YAAA,EAAA,YACA,YAAA,EAAA,YACC,aAAA,EAAA,aACA,aAAA,EAAA,aACC,cAAA,EAAA,cACF,YAAA,EAAA,YACN,MAAA,EAAA,MACG,SAAA,EAAA,SACJ,KAAA,EAAA,KACD,IAAA,EAAA,IACG,OAAA,EAAA,OACF,KAAA,EAAA,KACE,OAAA,EAAA,OACD,MAAA,EAAA,MACE,QAAA,EAAA,QACH,KAAA,EAAA,KACA,KAAA,EAAA,KACC,MAAA,EAAA,MACE,QAAA,EAAA,QACF,MAAA,EAAA,MACD,KAAA,EAAA,KACA,KAAA,EAAA,KACK,UAAA,EAAA,UACL,KAAA,EAAA,KACE,OAAA,EAAA,OACA,OAAA,EAAA,OACF,KAAA,EAAA,KACE,OAAA,EAAA,OACO,cAAA,EAAA,cACP,OAAA,EAAA,OACF,KAAA,EAAA,KACH,EAAA,EAAA,EACE,IAAA,EAAA,GACP,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=icons.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/core/icons.ts"],"names":[],"mappings":""}