@auronui/vue 1.4.1 → 1.4.2

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 (120) hide show
  1. package/dist/cjs/index.cjs +719 -460
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/components/_shared/TimeScroller.js.map +1 -1
  4. package/dist/components/_shared/TimeScroller.vue_vue_type_script_setup_true_lang.js +11 -7
  5. package/dist/components/_shared/TimeScroller.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/accordion/Accordion.js.map +1 -1
  7. package/dist/components/accordion/Accordion.vue_vue_type_script_setup_true_lang.js +17 -6
  8. package/dist/components/accordion/Accordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/autocomplete/Autocomplete.js.map +1 -1
  10. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js +23 -3
  11. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/autocomplete/AutocompleteCreateItem.js.map +1 -1
  13. package/dist/components/autocomplete/AutocompleteCreateItem.vue_vue_type_script_setup_true_lang.js +11 -7
  14. package/dist/components/autocomplete/AutocompleteCreateItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  15. package/dist/components/autocomplete/AutocompleteInput.js.map +1 -1
  16. package/dist/components/autocomplete/AutocompleteInput.vue_vue_type_script_setup_true_lang.js +23 -11
  17. package/dist/components/autocomplete/AutocompleteInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/autocomplete/AutocompleteItem.js.map +1 -1
  19. package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js +25 -17
  20. package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/autocomplete/AutocompleteOverflowChips.js.map +1 -1
  22. package/dist/components/autocomplete/AutocompleteOverflowChips.vue_vue_type_script_setup_true_lang.js +11 -4
  23. package/dist/components/autocomplete/AutocompleteOverflowChips.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/avatar/Avatar.js.map +1 -1
  25. package/dist/components/avatar/Avatar.vue_vue_type_script_setup_true_lang.js +11 -13
  26. package/dist/components/avatar/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/components/avatar/AvatarGroup.js.map +1 -1
  28. package/dist/components/avatar/AvatarGroup.vue_vue_type_script_setup_true_lang.js +12 -8
  29. package/dist/components/avatar/AvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -1
  31. package/dist/components/breadcrumbs/Breadcrumbs.vue_vue_type_script_setup_true_lang.js +11 -2
  32. package/dist/components/breadcrumbs/Breadcrumbs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/button/ButtonGroup.js.map +1 -1
  34. package/dist/components/button/ButtonGroup.vue_vue_type_script_setup_true_lang.js +4 -2
  35. package/dist/components/button/ButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/calendar/Calendar.js.map +1 -1
  37. package/dist/components/calendar/Calendar.vue_vue_type_script_setup_true_lang.js +3 -1
  38. package/dist/components/calendar/Calendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  39. package/dist/components/checkbox/CheckboxGroup.js.map +1 -1
  40. package/dist/components/checkbox/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +32 -19
  41. package/dist/components/checkbox/CheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/collapsible/CollapsibleGroup.js.map +1 -1
  43. package/dist/components/collapsible/CollapsibleGroup.vue_vue_type_script_setup_true_lang.js +9 -3
  44. package/dist/components/collapsible/CollapsibleGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/color-field/ColorField.js.map +1 -1
  46. package/dist/components/color-field/ColorField.vue_vue_type_script_setup_true_lang.js +17 -17
  47. package/dist/components/color-field/ColorField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/components/color-input-group/ColorInputGroup.js.map +1 -1
  49. package/dist/components/color-input-group/ColorInputGroup.vue_vue_type_script_setup_true_lang.js +16 -18
  50. package/dist/components/color-input-group/ColorInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/components/combo-box/ComboBox.js.map +1 -1
  52. package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js +10 -2
  53. package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/combo-box/ComboBoxInput.js.map +1 -1
  55. package/dist/components/combo-box/ComboBoxInput.vue_vue_type_script_setup_true_lang.js +9 -4
  56. package/dist/components/combo-box/ComboBoxInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  57. package/dist/components/combo-box/ComboBoxItem.js.map +1 -1
  58. package/dist/components/combo-box/ComboBoxItem.vue_vue_type_script_setup_true_lang.js +15 -6
  59. package/dist/components/combo-box/ComboBoxItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/date-picker/DatePicker.js.map +1 -1
  61. package/dist/components/date-picker/DatePicker.vue_vue_type_script_setup_true_lang.js +8 -4
  62. package/dist/components/date-picker/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/date-time-picker/DateTimePicker.js.map +1 -1
  64. package/dist/components/date-time-picker/DateTimePicker.vue_vue_type_script_setup_true_lang.js +10 -4
  65. package/dist/components/date-time-picker/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/list-box/ListBox.js.map +1 -1
  67. package/dist/components/list-box/ListBox.vue_vue_type_script_setup_true_lang.js +14 -4
  68. package/dist/components/list-box/ListBox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  69. package/dist/components/modal/ModalContent.js.map +1 -1
  70. package/dist/components/modal/ModalContent.vue_vue_type_script_setup_true_lang.js +2 -3
  71. package/dist/components/modal/ModalContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/radio/RadioGroup.js.map +1 -1
  73. package/dist/components/radio/RadioGroup.vue_vue_type_script_setup_true_lang.js +32 -19
  74. package/dist/components/radio/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  75. package/dist/components/scroll-area/ScrollArea.js.map +1 -1
  76. package/dist/components/scroll-area/ScrollArea.vue_vue_type_script_setup_true_lang.js +30 -13
  77. package/dist/components/scroll-area/ScrollArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/select/Select.js.map +1 -1
  79. package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js +21 -5
  80. package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -1
  81. package/dist/components/select/SelectItem.js.map +1 -1
  82. package/dist/components/select/SelectItem.vue_vue_type_script_setup_true_lang.js +11 -6
  83. package/dist/components/select/SelectItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/select/SelectOverflowChips.js.map +1 -1
  85. package/dist/components/select/SelectOverflowChips.vue_vue_type_script_setup_true_lang.js +8 -5
  86. package/dist/components/select/SelectOverflowChips.vue_vue_type_script_setup_true_lang.js.map +1 -1
  87. package/dist/components/select/SelectTrigger.js.map +1 -1
  88. package/dist/components/select/SelectTrigger.vue_vue_type_script_setup_true_lang.js +7 -5
  89. package/dist/components/select/SelectTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/select/SelectValue.js.map +1 -1
  91. package/dist/components/select/SelectValue.vue_vue_type_script_setup_true_lang.js +11 -4
  92. package/dist/components/select/SelectValue.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/separator/Separator.js.map +1 -1
  94. package/dist/components/separator/Separator.vue_vue_type_script_setup_true_lang.js +9 -8
  95. package/dist/components/separator/Separator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  96. package/dist/components/stepper/Stepper.js.map +1 -1
  97. package/dist/components/stepper/Stepper.vue_vue_type_script_setup_true_lang.js +20 -10
  98. package/dist/components/stepper/Stepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  99. package/dist/components/switch/SwitchGroup.js.map +1 -1
  100. package/dist/components/switch/SwitchGroup.vue_vue_type_script_setup_true_lang.js +29 -15
  101. package/dist/components/switch/SwitchGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/table/Table.js.map +1 -1
  103. package/dist/components/table/Table.vue_vue_type_script_setup_true_lang.js +29 -9
  104. package/dist/components/table/Table.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/tabs/TabList.js.map +1 -1
  106. package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js +18 -15
  107. package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/tabs/Tabs.js.map +1 -1
  109. package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js +30 -7
  110. package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  111. package/dist/components/time-picker/TimePicker.js.map +1 -1
  112. package/dist/components/time-picker/TimePicker.vue_vue_type_script_setup_true_lang.js +6 -2
  113. package/dist/components/time-picker/TimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/toast/ToastViewport.js.map +1 -1
  115. package/dist/components/toast/ToastViewport.vue_vue_type_script_setup_true_lang.js +19 -6
  116. package/dist/components/toast/ToastViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/index.d.ts +363 -0
  118. package/dist/packages/styles/dist/components/modal/modal.styles.js +2 -1
  119. package/dist/packages/styles/dist/components/modal/modal.styles.js.map +1 -1
  120. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"TimeScroller.js","names":[],"sources":["../../../src/components/_shared/TimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/_shared/TimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport type { Time, CalendarDateTime } from '@internationalized/date'\n\nconst props = withDefaults(defineProps<{\n modelValue: Time | CalendarDateTime\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n class?: string\n}>(), {\n granularity: 'minute',\n hourCycle: 24,\n class: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Time | CalendarDateTime]\n}>()\n\n// ─── Column data ─────────────────────────────────────────────────────────\n\nconst hours24 = Array.from({ length: 24 }, (_, i) => i)\nconst hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)] // 12,1..11\nconst minutes = Array.from({ length: 60 }, (_, i) => i)\nconst seconds = Array.from({ length: 60 }, (_, i) => i)\nconst ampm = ['AM', 'PM']\n\nconst hourItems = computed(() =>\n props.hourCycle === 12 ? hours12 : hours24,\n)\n\ntype Column = { key: string; items: (number | string)[]; loop: boolean }\n\nconst columns = computed<Column[]>(() => {\n const cols: Column[] = [\n { key: 'hour', items: hourItems.value, loop: true },\n { key: 'minute', items: minutes, loop: true },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds, loop: true })\n // AM/PM is a short, finite column — it does not loop.\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm, loop: false })\n return cols\n})\n\n// ─── Infinite circular scroll ─────────────────────────────────────────────\n// Numeric columns repeat their list REPEAT times and start in the middle copy.\n// On scroll, whenever the position drifts out of the middle band we jump it\n// back by whole cycles — invisible because the content is identical — so the\n// wheel can be dragged endlessly in either direction.\n\n// Three copies is the minimum for a seamless loop: a buffer copy at each end\n// plus the middle copy the user actually sits in. More copies = needless DOM.\nconst REPEAT = 3\nconst ITEM_H = 40 // 2.5rem at 16px base\nconst columnRefs = ref<HTMLElement[]>([])\n\nfunction renderItems(col: Column): (number | string)[] {\n if (!col.loop) return col.items\n const out: (number | string)[] = []\n for (let r = 0; r < REPEAT; r++) out.push(...col.items)\n return out\n}\n\nfunction cycleHeight(col: Column): number {\n return col.items.length * ITEM_H\n}\n\n// Keep the scroll position inside the inner copies [cycle, total-cycle); when it\n// drifts into the first or last buffer copy, jump it by (REPEAT-2) cycles. The\n// content is identical, so the jump is invisible and the wheel feels endless.\nfunction onColumnScroll(i: number, colEl: HTMLElement) {\n const col = columns.value[i]\n if (!col.loop) return\n const cycle = cycleHeight(col)\n const total = cycle * REPEAT\n const recenter = (REPEAT - 2) * cycle\n if (colEl.scrollTop < cycle) {\n colEl.scrollTop += recenter\n } else if (colEl.scrollTop >= total - cycle) {\n colEl.scrollTop -= recenter\n }\n}\n\nonMounted(() => {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el && col.loop) el.scrollTop = cycleHeight(col) * Math.floor(REPEAT / 2)\n })\n})\n\n// ─── Selection (tap to select) ─────────────────────────────────────────────\n// Selection is by VALUE, so every repeated copy of the chosen number highlights.\n\nfunction isSelected(key: string, item: number | string): boolean {\n const v = props.modelValue\n if (key === 'hour') {\n if (props.hourCycle === 12) {\n const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12\n return item === h12\n }\n return item === v.hour\n }\n if (key === 'minute') return item === v.minute\n if (key === 'second') return item === (v.second ?? 0)\n if (key === 'ampm') return item === (v.hour >= 12 ? 'PM' : 'AM')\n return false\n}\n\nfunction onItemClick(key: string, item: number | string) {\n const v = props.modelValue\n if (key === 'hour') {\n let newHour: number\n if (props.hourCycle === 12) {\n const isPm = v.hour >= 12\n const h12 = item as number\n newHour = h12 === 12 ? (isPm ? 12 : 0) : isPm ? h12 + 12 : h12\n } else {\n newHour = item as number\n }\n emit('update:modelValue', v.set({ hour: newHour }))\n } else if (key === 'minute') {\n emit('update:modelValue', v.set({ minute: item as number }))\n } else if (key === 'second') {\n emit('update:modelValue', v.set({ second: item as number }))\n } else if (key === 'ampm') {\n const isPm = item === 'PM'\n const currentPm = v.hour >= 12\n if (isPm !== currentPm) {\n emit('update:modelValue', v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }))\n }\n }\n}\n\n// ─── Label helpers ───────────────────────────────────────────────────────\n\nfunction columnLabel(key: string): string {\n if (key === 'hour') return 'Hour'\n if (key === 'minute') return 'Minute'\n if (key === 'second') return 'Second'\n return 'AM/PM'\n}\n\nfunction itemLabel(item: number | string): string {\n if (typeof item === 'string') return item\n return String(item).padStart(2, '0')\n}\n\n// expose for testing\ndefineExpose({ columnRefs, columns })\n</script>\n\n<template>\n <div\n :class=\"['date-time-picker__scroller-wrap', props.class]\"\n data-slot=\"time-scroller\"\n >\n <div\n v-for=\"(col, i) in columns\"\n :key=\"col.key\"\n :ref=\"(el) => { if (el) columnRefs[i] = el as HTMLElement }\"\n class=\"date-time-picker__scroller-column\"\n :aria-label=\"columnLabel(col.key)\"\n data-slot=\"scroller-column\"\n role=\"listbox\"\n tabindex=\"0\"\n @scroll.passive=\"onColumnScroll(i, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in renderItems(col)\"\n :key=\"idx\"\n class=\"date-time-picker__scroller-item\"\n :data-selected=\"isSelected(col.key, item) ? 'true' : undefined\"\n :aria-selected=\"isSelected(col.key, item)\"\n role=\"option\"\n @click=\"onItemClick(col.key, item)\"\n >\n {{ itemLabel(item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TimeScroller.js","names":[],"sources":["../../../src/components/_shared/TimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/_shared/TimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport type { Time, CalendarDateTime } from '@internationalized/date'\nimport { dateTimePickerVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\n\nconst props = withDefaults(defineProps<{\n modelValue: Time | CalendarDateTime\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n class?: string\n /** Per-slot class overrides */\n classNames?: Partial<{\n scrollerWrap: ClassValue\n scrollerColumn: ClassValue\n scrollerItem: ClassValue\n }>\n}>(), {\n granularity: 'minute',\n hourCycle: 24,\n class: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Time | CalendarDateTime]\n}>()\n\n// ─── Column data ─────────────────────────────────────────────────────────\n\nconst hours24 = Array.from({ length: 24 }, (_, i) => i)\nconst hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)] // 12,1..11\nconst minutes = Array.from({ length: 60 }, (_, i) => i)\nconst seconds = Array.from({ length: 60 }, (_, i) => i)\nconst ampm = ['AM', 'PM']\n\nconst hourItems = computed(() =>\n props.hourCycle === 12 ? hours12 : hours24,\n)\n\ntype Column = { key: string; items: (number | string)[]; loop: boolean }\n\nconst columns = computed<Column[]>(() => {\n const cols: Column[] = [\n { key: 'hour', items: hourItems.value, loop: true },\n { key: 'minute', items: minutes, loop: true },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds, loop: true })\n // AM/PM is a short, finite column — it does not loop.\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm, loop: false })\n return cols\n})\n\n// ─── Infinite circular scroll ─────────────────────────────────────────────\n// Numeric columns repeat their list REPEAT times and start in the middle copy.\n// On scroll, whenever the position drifts out of the middle band we jump it\n// back by whole cycles — invisible because the content is identical — so the\n// wheel can be dragged endlessly in either direction.\n\n// Three copies is the minimum for a seamless loop: a buffer copy at each end\n// plus the middle copy the user actually sits in. More copies = needless DOM.\nconst REPEAT = 3\nconst ITEM_H = 40 // 2.5rem at 16px base\nconst columnRefs = ref<HTMLElement[]>([])\n\nfunction renderItems(col: Column): (number | string)[] {\n if (!col.loop) return col.items\n const out: (number | string)[] = []\n for (let r = 0; r < REPEAT; r++) out.push(...col.items)\n return out\n}\n\nfunction cycleHeight(col: Column): number {\n return col.items.length * ITEM_H\n}\n\n// Keep the scroll position inside the inner copies [cycle, total-cycle); when it\n// drifts into the first or last buffer copy, jump it by (REPEAT-2) cycles. The\n// content is identical, so the jump is invisible and the wheel feels endless.\nfunction onColumnScroll(i: number, colEl: HTMLElement) {\n const col = columns.value[i]\n if (!col.loop) return\n const cycle = cycleHeight(col)\n const total = cycle * REPEAT\n const recenter = (REPEAT - 2) * cycle\n if (colEl.scrollTop < cycle) {\n colEl.scrollTop += recenter\n } else if (colEl.scrollTop >= total - cycle) {\n colEl.scrollTop -= recenter\n }\n}\n\nonMounted(() => {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el && col.loop) el.scrollTop = cycleHeight(col) * Math.floor(REPEAT / 2)\n })\n})\n\n// ─── Selection (tap to select) ─────────────────────────────────────────────\n// Selection is by VALUE, so every repeated copy of the chosen number highlights.\n\nfunction isSelected(key: string, item: number | string): boolean {\n const v = props.modelValue\n if (key === 'hour') {\n if (props.hourCycle === 12) {\n const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12\n return item === h12\n }\n return item === v.hour\n }\n if (key === 'minute') return item === v.minute\n if (key === 'second') return item === (v.second ?? 0)\n if (key === 'ampm') return item === (v.hour >= 12 ? 'PM' : 'AM')\n return false\n}\n\nfunction onItemClick(key: string, item: number | string) {\n const v = props.modelValue\n if (key === 'hour') {\n let newHour: number\n if (props.hourCycle === 12) {\n const isPm = v.hour >= 12\n const h12 = item as number\n newHour = h12 === 12 ? (isPm ? 12 : 0) : isPm ? h12 + 12 : h12\n } else {\n newHour = item as number\n }\n emit('update:modelValue', v.set({ hour: newHour }))\n } else if (key === 'minute') {\n emit('update:modelValue', v.set({ minute: item as number }))\n } else if (key === 'second') {\n emit('update:modelValue', v.set({ second: item as number }))\n } else if (key === 'ampm') {\n const isPm = item === 'PM'\n const currentPm = v.hour >= 12\n if (isPm !== currentPm) {\n emit('update:modelValue', v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }))\n }\n }\n}\n\n// ─── Label helpers ───────────────────────────────────────────────────────\n\nfunction columnLabel(key: string): string {\n if (key === 'hour') return 'Hour'\n if (key === 'minute') return 'Minute'\n if (key === 'second') return 'Second'\n return 'AM/PM'\n}\n\nfunction itemLabel(item: number | string): string {\n if (typeof item === 'string') return item\n return String(item).padStart(2, '0')\n}\n\nconst slotFns = dateTimePickerVariants()\n\n// expose for testing\ndefineExpose({ columnRefs, columns })\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.scrollerWrap(), props.class, props.classNames?.scrollerWrap)\"\n data-slot=\"time-scroller\"\n >\n <div\n v-for=\"(col, i) in columns\"\n :key=\"col.key\"\n :ref=\"(el) => { if (el) columnRefs[i] = el as HTMLElement }\"\n :class=\"composeClassName(slotFns.scrollerColumn(), props.classNames?.scrollerColumn)\"\n :aria-label=\"columnLabel(col.key)\"\n data-slot=\"scroller-column\"\n role=\"listbox\"\n tabindex=\"0\"\n @scroll.passive=\"onColumnScroll(i, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in renderItems(col)\"\n :key=\"idx\"\n :class=\"composeClassName(slotFns.scrollerItem(), props.classNames?.scrollerItem)\"\n :data-selected=\"isSelected(col.key, item) ? 'true' : undefined\"\n :aria-selected=\"isSelected(col.key, item)\"\n role=\"option\"\n @click=\"onItemClick(col.key, item)\"\n >\n {{ itemLabel(item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -1,4 +1,6 @@
1
- import { Fragment, computed, createElementBlock, defineComponent, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString } from "vue";
1
+ import { composeClassName } from "../../utils/composeClassName.js";
2
+ import { Fragment, computed, createElementBlock, defineComponent, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString, unref } from "vue";
3
+ import { dateTimePickerVariants } from "@auronui/styles";
2
4
  //#region src/components/_shared/TimeScroller.vue?vue&type=script&setup=true&lang.ts
3
5
  var _hoisted_1 = ["aria-label", "onScrollPassive"];
4
6
  var _hoisted_2 = [
@@ -14,7 +16,8 @@ var TimeScroller_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
14
16
  modelValue: {},
15
17
  granularity: { default: "minute" },
16
18
  hourCycle: { default: 24 },
17
- class: { default: void 0 }
19
+ class: { default: void 0 },
20
+ classNames: {}
18
21
  },
19
22
  emits: ["update:modelValue"],
20
23
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -111,13 +114,14 @@ var TimeScroller_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
111
114
  if (typeof item === "string") return item;
112
115
  return String(item).padStart(2, "0");
113
116
  }
117
+ const slotFns = dateTimePickerVariants();
114
118
  __expose({
115
119
  columnRefs,
116
120
  columns
117
121
  });
118
122
  return (_ctx, _cache) => {
119
123
  return openBlock(), createElementBlock("div", {
120
- class: normalizeClass(["date-time-picker__scroller-wrap", props.class]),
124
+ class: normalizeClass(unref(composeClassName)(unref(slotFns).scrollerWrap(), props.class, props.classNames?.scrollerWrap)),
121
125
  "data-slot": "time-scroller"
122
126
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(columns.value, (col, i) => {
123
127
  return openBlock(), createElementBlock("div", {
@@ -126,7 +130,7 @@ var TimeScroller_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
126
130
  ref: (el) => {
127
131
  if (el) columnRefs.value[i] = el;
128
132
  },
129
- class: "date-time-picker__scroller-column",
133
+ class: normalizeClass(unref(composeClassName)(unref(slotFns).scrollerColumn(), props.classNames?.scrollerColumn)),
130
134
  "aria-label": columnLabel(col.key),
131
135
  "data-slot": "scroller-column",
132
136
  role: "listbox",
@@ -135,13 +139,13 @@ var TimeScroller_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
135
139
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(renderItems(col), (item, idx) => {
136
140
  return openBlock(), createElementBlock("div", {
137
141
  key: idx,
138
- class: "date-time-picker__scroller-item",
142
+ class: normalizeClass(unref(composeClassName)(unref(slotFns).scrollerItem(), props.classNames?.scrollerItem)),
139
143
  "data-selected": isSelected(col.key, item) ? "true" : void 0,
140
144
  "aria-selected": isSelected(col.key, item),
141
145
  role: "option",
142
146
  onClick: ($event) => onItemClick(col.key, item)
143
- }, toDisplayString(itemLabel(item)), 9, _hoisted_2);
144
- }), 128))], 40, _hoisted_1);
147
+ }, toDisplayString(itemLabel(item)), 11, _hoisted_2);
148
+ }), 128))], 42, _hoisted_1);
145
149
  }), 128))], 2);
146
150
  };
147
151
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TimeScroller.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/_shared/TimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/_shared/TimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport type { Time, CalendarDateTime } from '@internationalized/date'\n\nconst props = withDefaults(defineProps<{\n modelValue: Time | CalendarDateTime\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n class?: string\n}>(), {\n granularity: 'minute',\n hourCycle: 24,\n class: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Time | CalendarDateTime]\n}>()\n\n// ─── Column data ─────────────────────────────────────────────────────────\n\nconst hours24 = Array.from({ length: 24 }, (_, i) => i)\nconst hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)] // 12,1..11\nconst minutes = Array.from({ length: 60 }, (_, i) => i)\nconst seconds = Array.from({ length: 60 }, (_, i) => i)\nconst ampm = ['AM', 'PM']\n\nconst hourItems = computed(() =>\n props.hourCycle === 12 ? hours12 : hours24,\n)\n\ntype Column = { key: string; items: (number | string)[]; loop: boolean }\n\nconst columns = computed<Column[]>(() => {\n const cols: Column[] = [\n { key: 'hour', items: hourItems.value, loop: true },\n { key: 'minute', items: minutes, loop: true },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds, loop: true })\n // AM/PM is a short, finite column — it does not loop.\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm, loop: false })\n return cols\n})\n\n// ─── Infinite circular scroll ─────────────────────────────────────────────\n// Numeric columns repeat their list REPEAT times and start in the middle copy.\n// On scroll, whenever the position drifts out of the middle band we jump it\n// back by whole cycles — invisible because the content is identical — so the\n// wheel can be dragged endlessly in either direction.\n\n// Three copies is the minimum for a seamless loop: a buffer copy at each end\n// plus the middle copy the user actually sits in. More copies = needless DOM.\nconst REPEAT = 3\nconst ITEM_H = 40 // 2.5rem at 16px base\nconst columnRefs = ref<HTMLElement[]>([])\n\nfunction renderItems(col: Column): (number | string)[] {\n if (!col.loop) return col.items\n const out: (number | string)[] = []\n for (let r = 0; r < REPEAT; r++) out.push(...col.items)\n return out\n}\n\nfunction cycleHeight(col: Column): number {\n return col.items.length * ITEM_H\n}\n\n// Keep the scroll position inside the inner copies [cycle, total-cycle); when it\n// drifts into the first or last buffer copy, jump it by (REPEAT-2) cycles. The\n// content is identical, so the jump is invisible and the wheel feels endless.\nfunction onColumnScroll(i: number, colEl: HTMLElement) {\n const col = columns.value[i]\n if (!col.loop) return\n const cycle = cycleHeight(col)\n const total = cycle * REPEAT\n const recenter = (REPEAT - 2) * cycle\n if (colEl.scrollTop < cycle) {\n colEl.scrollTop += recenter\n } else if (colEl.scrollTop >= total - cycle) {\n colEl.scrollTop -= recenter\n }\n}\n\nonMounted(() => {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el && col.loop) el.scrollTop = cycleHeight(col) * Math.floor(REPEAT / 2)\n })\n})\n\n// ─── Selection (tap to select) ─────────────────────────────────────────────\n// Selection is by VALUE, so every repeated copy of the chosen number highlights.\n\nfunction isSelected(key: string, item: number | string): boolean {\n const v = props.modelValue\n if (key === 'hour') {\n if (props.hourCycle === 12) {\n const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12\n return item === h12\n }\n return item === v.hour\n }\n if (key === 'minute') return item === v.minute\n if (key === 'second') return item === (v.second ?? 0)\n if (key === 'ampm') return item === (v.hour >= 12 ? 'PM' : 'AM')\n return false\n}\n\nfunction onItemClick(key: string, item: number | string) {\n const v = props.modelValue\n if (key === 'hour') {\n let newHour: number\n if (props.hourCycle === 12) {\n const isPm = v.hour >= 12\n const h12 = item as number\n newHour = h12 === 12 ? (isPm ? 12 : 0) : isPm ? h12 + 12 : h12\n } else {\n newHour = item as number\n }\n emit('update:modelValue', v.set({ hour: newHour }))\n } else if (key === 'minute') {\n emit('update:modelValue', v.set({ minute: item as number }))\n } else if (key === 'second') {\n emit('update:modelValue', v.set({ second: item as number }))\n } else if (key === 'ampm') {\n const isPm = item === 'PM'\n const currentPm = v.hour >= 12\n if (isPm !== currentPm) {\n emit('update:modelValue', v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }))\n }\n }\n}\n\n// ─── Label helpers ───────────────────────────────────────────────────────\n\nfunction columnLabel(key: string): string {\n if (key === 'hour') return 'Hour'\n if (key === 'minute') return 'Minute'\n if (key === 'second') return 'Second'\n return 'AM/PM'\n}\n\nfunction itemLabel(item: number | string): string {\n if (typeof item === 'string') return item\n return String(item).padStart(2, '0')\n}\n\n// expose for testing\ndefineExpose({ columnRefs, columns })\n</script>\n\n<template>\n <div\n :class=\"['date-time-picker__scroller-wrap', props.class]\"\n data-slot=\"time-scroller\"\n >\n <div\n v-for=\"(col, i) in columns\"\n :key=\"col.key\"\n :ref=\"(el) => { if (el) columnRefs[i] = el as HTMLElement }\"\n class=\"date-time-picker__scroller-column\"\n :aria-label=\"columnLabel(col.key)\"\n data-slot=\"scroller-column\"\n role=\"listbox\"\n tabindex=\"0\"\n @scroll.passive=\"onColumnScroll(i, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in renderItems(col)\"\n :key=\"idx\"\n class=\"date-time-picker__scroller-item\"\n :data-selected=\"isSelected(col.key, item) ? 'true' : undefined\"\n :aria-selected=\"isSelected(col.key, item)\"\n role=\"option\"\n @click=\"onItemClick(col.key, item)\"\n >\n {{ itemLabel(item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TimeScroller.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/_shared/TimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/_shared/TimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport type { Time, CalendarDateTime } from '@internationalized/date'\nimport { dateTimePickerVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\n\nconst props = withDefaults(defineProps<{\n modelValue: Time | CalendarDateTime\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n class?: string\n /** Per-slot class overrides */\n classNames?: Partial<{\n scrollerWrap: ClassValue\n scrollerColumn: ClassValue\n scrollerItem: ClassValue\n }>\n}>(), {\n granularity: 'minute',\n hourCycle: 24,\n class: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Time | CalendarDateTime]\n}>()\n\n// ─── Column data ─────────────────────────────────────────────────────────\n\nconst hours24 = Array.from({ length: 24 }, (_, i) => i)\nconst hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)] // 12,1..11\nconst minutes = Array.from({ length: 60 }, (_, i) => i)\nconst seconds = Array.from({ length: 60 }, (_, i) => i)\nconst ampm = ['AM', 'PM']\n\nconst hourItems = computed(() =>\n props.hourCycle === 12 ? hours12 : hours24,\n)\n\ntype Column = { key: string; items: (number | string)[]; loop: boolean }\n\nconst columns = computed<Column[]>(() => {\n const cols: Column[] = [\n { key: 'hour', items: hourItems.value, loop: true },\n { key: 'minute', items: minutes, loop: true },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds, loop: true })\n // AM/PM is a short, finite column — it does not loop.\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm, loop: false })\n return cols\n})\n\n// ─── Infinite circular scroll ─────────────────────────────────────────────\n// Numeric columns repeat their list REPEAT times and start in the middle copy.\n// On scroll, whenever the position drifts out of the middle band we jump it\n// back by whole cycles — invisible because the content is identical — so the\n// wheel can be dragged endlessly in either direction.\n\n// Three copies is the minimum for a seamless loop: a buffer copy at each end\n// plus the middle copy the user actually sits in. More copies = needless DOM.\nconst REPEAT = 3\nconst ITEM_H = 40 // 2.5rem at 16px base\nconst columnRefs = ref<HTMLElement[]>([])\n\nfunction renderItems(col: Column): (number | string)[] {\n if (!col.loop) return col.items\n const out: (number | string)[] = []\n for (let r = 0; r < REPEAT; r++) out.push(...col.items)\n return out\n}\n\nfunction cycleHeight(col: Column): number {\n return col.items.length * ITEM_H\n}\n\n// Keep the scroll position inside the inner copies [cycle, total-cycle); when it\n// drifts into the first or last buffer copy, jump it by (REPEAT-2) cycles. The\n// content is identical, so the jump is invisible and the wheel feels endless.\nfunction onColumnScroll(i: number, colEl: HTMLElement) {\n const col = columns.value[i]\n if (!col.loop) return\n const cycle = cycleHeight(col)\n const total = cycle * REPEAT\n const recenter = (REPEAT - 2) * cycle\n if (colEl.scrollTop < cycle) {\n colEl.scrollTop += recenter\n } else if (colEl.scrollTop >= total - cycle) {\n colEl.scrollTop -= recenter\n }\n}\n\nonMounted(() => {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el && col.loop) el.scrollTop = cycleHeight(col) * Math.floor(REPEAT / 2)\n })\n})\n\n// ─── Selection (tap to select) ─────────────────────────────────────────────\n// Selection is by VALUE, so every repeated copy of the chosen number highlights.\n\nfunction isSelected(key: string, item: number | string): boolean {\n const v = props.modelValue\n if (key === 'hour') {\n if (props.hourCycle === 12) {\n const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12\n return item === h12\n }\n return item === v.hour\n }\n if (key === 'minute') return item === v.minute\n if (key === 'second') return item === (v.second ?? 0)\n if (key === 'ampm') return item === (v.hour >= 12 ? 'PM' : 'AM')\n return false\n}\n\nfunction onItemClick(key: string, item: number | string) {\n const v = props.modelValue\n if (key === 'hour') {\n let newHour: number\n if (props.hourCycle === 12) {\n const isPm = v.hour >= 12\n const h12 = item as number\n newHour = h12 === 12 ? (isPm ? 12 : 0) : isPm ? h12 + 12 : h12\n } else {\n newHour = item as number\n }\n emit('update:modelValue', v.set({ hour: newHour }))\n } else if (key === 'minute') {\n emit('update:modelValue', v.set({ minute: item as number }))\n } else if (key === 'second') {\n emit('update:modelValue', v.set({ second: item as number }))\n } else if (key === 'ampm') {\n const isPm = item === 'PM'\n const currentPm = v.hour >= 12\n if (isPm !== currentPm) {\n emit('update:modelValue', v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }))\n }\n }\n}\n\n// ─── Label helpers ───────────────────────────────────────────────────────\n\nfunction columnLabel(key: string): string {\n if (key === 'hour') return 'Hour'\n if (key === 'minute') return 'Minute'\n if (key === 'second') return 'Second'\n return 'AM/PM'\n}\n\nfunction itemLabel(item: number | string): string {\n if (typeof item === 'string') return item\n return String(item).padStart(2, '0')\n}\n\nconst slotFns = dateTimePickerVariants()\n\n// expose for testing\ndefineExpose({ columnRefs, columns })\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.scrollerWrap(), props.class, props.classNames?.scrollerWrap)\"\n data-slot=\"time-scroller\"\n >\n <div\n v-for=\"(col, i) in columns\"\n :key=\"col.key\"\n :ref=\"(el) => { if (el) columnRefs[i] = el as HTMLElement }\"\n :class=\"composeClassName(slotFns.scrollerColumn(), props.classNames?.scrollerColumn)\"\n :aria-label=\"columnLabel(col.key)\"\n data-slot=\"scroller-column\"\n role=\"listbox\"\n tabindex=\"0\"\n @scroll.passive=\"onColumnScroll(i, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in renderItems(col)\"\n :key=\"idx\"\n :class=\"composeClassName(slotFns.scrollerItem(), props.classNames?.scrollerItem)\"\n :data-selected=\"isSelected(col.key, item) ? 'true' : undefined\"\n :aria-selected=\"isSelected(col.key, item)\"\n role=\"option\"\n @click=\"onItemClick(col.key, item)\"\n >\n {{ itemLabel(item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;AA6DA,IAAM,SAAS;AACf,IAAM,SAAS;;;;;;;;;;;;EAvDf,MAAM,QAAQ;EAiBd,MAAM,OAAO;EAMb,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,GAAG,MAAM,EAAC;EACtD,MAAM,UAAU,CAAC,IAAI,GAAG,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;EACpE,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,GAAG,MAAM,EAAC;EACtD,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,GAAG,MAAM,EAAC;EACtD,MAAM,OAAO,CAAC,MAAM,KAAI;EAExB,MAAM,YAAY,eAChB,MAAM,cAAc,KAAK,UAAU,QACrC;EAIA,MAAM,UAAU,eAAyB;GACvC,MAAM,OAAiB,CACrB;IAAE,KAAK;IAAQ,OAAO,UAAU;IAAO,MAAM;IAAM,EACnD;IAAE,KAAK;IAAU,OAAO;IAAS,MAAM;IAAM,CAC/C;AACA,OAAI,MAAM,gBAAgB,SAAU,MAAK,KAAK;IAAE,KAAK;IAAU,OAAO;IAAS,MAAM;IAAM,CAAA;AAE3F,OAAI,MAAM,cAAc,GAAI,MAAK,KAAK;IAAE,KAAK;IAAQ,OAAO;IAAM,MAAM;IAAO,CAAA;AAC/E,UAAO;IACR;EAYD,MAAM,aAAa,IAAmB,EAAE,CAAA;EAExC,SAAS,YAAY,KAAkC;AACrD,OAAI,CAAC,IAAI,KAAM,QAAO,IAAI;GAC1B,MAAM,MAA2B,EAAC;AAClC,QAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAAK,KAAI,KAAK,GAAG,IAAI,MAAK;AACtD,UAAO;;EAGT,SAAS,YAAY,KAAqB;AACxC,UAAO,IAAI,MAAM,SAAS;;EAM5B,SAAS,eAAe,GAAW,OAAoB;GACrD,MAAM,MAAM,QAAQ,MAAM;AAC1B,OAAI,CAAC,IAAI,KAAM;GACf,MAAM,QAAQ,YAAY,IAAG;GAC7B,MAAM,QAAQ,QAAQ;GACtB,MAAM,YAAY,SAAS,KAAK;AAChC,OAAI,MAAM,YAAY,MACpB,OAAM,aAAa;YACV,MAAM,aAAa,QAAQ,MACpC,OAAM,aAAa;;AAIvB,kBAAgB;AACd,WAAQ,MAAM,SAAS,KAAK,MAAM;IAChC,MAAM,KAAK,WAAW,MAAM;AAC5B,QAAI,MAAM,IAAI,KAAM,IAAG,YAAY,YAAY,IAAI,GAAG,KAAK,MAAM,SAAS,EAAC;KAC5E;IACF;EAKD,SAAS,WAAW,KAAa,MAAgC;GAC/D,MAAM,IAAI,MAAM;AAChB,OAAI,QAAQ,QAAQ;AAClB,QAAI,MAAM,cAAc,GAEtB,QAAO,UADK,EAAE,OAAO,OAAO,IAAI,KAAK,EAAE,OAAO;AAGhD,WAAO,SAAS,EAAE;;AAEpB,OAAI,QAAQ,SAAU,QAAO,SAAS,EAAE;AACxC,OAAI,QAAQ,SAAU,QAAO,UAAU,EAAE,UAAU;AACnD,OAAI,QAAQ,OAAQ,QAAO,UAAU,EAAE,QAAQ,KAAK,OAAO;AAC3D,UAAO;;EAGT,SAAS,YAAY,KAAa,MAAuB;GACvD,MAAM,IAAI,MAAM;AAChB,OAAI,QAAQ,QAAQ;IAClB,IAAI;AACJ,QAAI,MAAM,cAAc,IAAI;KAC1B,MAAM,OAAO,EAAE,QAAQ;KACvB,MAAM,MAAM;AACZ,eAAU,QAAQ,KAAM,OAAO,KAAK,IAAK,OAAO,MAAM,KAAK;UAE3D,WAAU;AAEZ,SAAK,qBAAqB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC,CAAA;cACzC,QAAQ,SACjB,MAAK,qBAAqB,EAAE,IAAI,EAAE,QAAQ,MAAgB,CAAC,CAAA;YAClD,QAAQ,SACjB,MAAK,qBAAqB,EAAE,IAAI,EAAE,QAAQ,MAAgB,CAAC,CAAA;YAClD,QAAQ,QAAQ;IACzB,MAAM,OAAO,SAAS;AAEtB,QAAI,SADc,EAAE,QAAQ,GAE1B,MAAK,qBAAqB,EAAE,IAAI,EAAE,MAAM,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,IAAI,CAAC,CAAA;;;EAOjF,SAAS,YAAY,KAAqB;AACxC,OAAI,QAAQ,OAAQ,QAAO;AAC3B,OAAI,QAAQ,SAAU,QAAO;AAC7B,OAAI,QAAQ,SAAU,QAAO;AAC7B,UAAO;;EAGT,SAAS,UAAU,MAA+B;AAChD,OAAI,OAAO,SAAS,SAAU,QAAO;AACrC,UAAO,OAAO,KAAK,CAAC,SAAS,GAAG,IAAG;;EAGrC,MAAM,UAAU,wBAAuB;AAGvC,WAAa;GAAE;GAAY;GAAS,CAAA;;uBAIlC,mBA2BM,OAAA;IA1BH,OAAK,eAAE,MAAA,iBAAgB,CAAC,MAAA,QAAO,CAAC,cAAY,EAAI,MAAM,OAAO,MAAM,YAAY,aAAY,CAAA;IAC5F,aAAU;yBAEV,mBAsBM,UAAA,MAAA,WArBe,QAAA,QAAX,KAAK,MAAC;wBADhB,mBAsBM,OAAA;KApBH,KAAK,IAAI;;KACT,MAAM,OAAE;AAAA,UAAW,GAAI,YAAA,MAAW,KAAK;;KACvC,OAAK,eAAE,MAAA,iBAAgB,CAAC,MAAA,QAAO,CAAC,gBAAc,EAAI,MAAM,YAAY,eAAc,CAAA;KAClF,cAAY,YAAY,IAAI,IAAG;KAChC,aAAU;KACV,MAAK;KACL,UAAS;kCACQ,eAAe,GAAI,OAAO,cAAa;0BAExD,mBAUM,UAAA,MAAA,WATkB,YAAY,IAAG,GAA7B,MAAM,QAAG;yBADnB,mBAUM,OAAA;MARH,KAAK;MACL,OAAK,eAAE,MAAA,iBAAgB,CAAC,MAAA,QAAO,CAAC,cAAY,EAAI,MAAM,YAAY,aAAY,CAAA;MAC9E,iBAAe,WAAW,IAAI,KAAK,KAAI,GAAA,SAAa,KAAA;MACpD,iBAAe,WAAW,IAAI,KAAK,KAAI;MACxC,MAAK;MACJ,UAAK,WAAE,YAAY,IAAI,KAAK,KAAI;wBAE9B,UAAU,KAAI,CAAA,EAAA,IAAA,WAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.js","names":[],"sources":["../../../src/components/accordion/Accordion.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AccordionRoot } from 'reka-ui'\nimport { accordionVariants, type AccordionVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useAccordionProvide } from './accordion.context'\nimport AccordionItem from './AccordionItem.vue'\nimport AccordionHeader from './AccordionHeader.vue'\nimport AccordionTrigger from './AccordionTrigger.vue'\nimport AccordionContent from './AccordionContent.vue'\n\ntype SingleValue = string\ntype MultipleValue = string[]\ntype AccordionShorthandItem = { value: string; title: string; content?: string; disabled?: boolean }\n\nconst props = withDefaults(defineProps<{\n type: 'single' | 'multiple'\n modelValue?: SingleValue | MultipleValue\n defaultValue?: SingleValue | MultipleValue\n collapsible?: boolean\n isDisabled?: boolean\n /** @deprecated Use isDisabled instead. */\n disabled?: boolean\n dir?: 'ltr' | 'rtl'\n orientation?: 'horizontal' | 'vertical'\n unmountOnHide?: boolean\n as?: string\n asChild?: boolean\n variant?: AccordionVariants['variant']\n size?: AccordionVariants['size']\n class?: ClassValue\n /** Override classes for any slot */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render items from an array instead of the compound slot API */\n items?: AccordionShorthandItem[]\n}>(), {\n\n collapsible: true,\n isDisabled: undefined,\n disabled: undefined,\n variant: 'default',\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: SingleValue | MultipleValue]\n}>()\n\nconst isDisabled = useDeprecatedBooleanProp(\n 'Accordion', 'isDisabled', () => props.isDisabled, 'disabled', () => props.disabled,\n)\n\nconst slotFns = computed(() => accordionVariants({ variant: props.variant, size: props.size }))\n\nuseAccordionProvide({ slotFns })\n</script>\n\n<template>\n <AccordionRoot\n :type=\"props.type\"\n :model-value=\"props.modelValue\"\n :default-value=\"props.defaultValue\"\n :collapsible=\"props.collapsible\"\n :disabled=\"isDisabled\"\n :dir=\"props.dir\"\n :orientation=\"props.orientation\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n @update:model-value=\"(v: SingleValue | MultipleValue | undefined) => { if (v !== undefined) emit('update:modelValue', v) }\"\n >\n <template v-if=\"props.items\">\n <AccordionItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n >\n <AccordionHeader>\n <AccordionTrigger>{{ item.title }}</AccordionTrigger>\n </AccordionHeader>\n <AccordionContent>{{ item.content }}</AccordionContent>\n </AccordionItem>\n </template>\n <slot v-else />\n </AccordionRoot>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Accordion.js","names":[],"sources":["../../../src/components/accordion/Accordion.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AccordionRoot } from 'reka-ui'\nimport { accordionVariants, type AccordionVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useAccordionProvide } from './accordion.context'\nimport AccordionItem from './AccordionItem.vue'\nimport AccordionHeader from './AccordionHeader.vue'\nimport AccordionTrigger from './AccordionTrigger.vue'\nimport AccordionContent from './AccordionContent.vue'\n\ntype SingleValue = string\ntype MultipleValue = string[]\ntype AccordionShorthandItem = { value: string; title: string; content?: string; disabled?: boolean }\n\nconst props = withDefaults(defineProps<{\n type: 'single' | 'multiple'\n modelValue?: SingleValue | MultipleValue\n defaultValue?: SingleValue | MultipleValue\n collapsible?: boolean\n isDisabled?: boolean\n /** @deprecated Use isDisabled instead. */\n disabled?: boolean\n dir?: 'ltr' | 'rtl'\n orientation?: 'horizontal' | 'vertical'\n unmountOnHide?: boolean\n as?: string\n asChild?: boolean\n variant?: AccordionVariants['variant']\n size?: AccordionVariants['size']\n class?: ClassValue\n /** Override classes for any slot */\n classNames?: Partial<{\n base: ClassValue\n item: ClassValue\n trigger: ClassValue\n indicator: ClassValue\n body: ClassValue\n bodyInner: ClassValue\n }>\n /** Shorthand API: render items from an array instead of the compound slot API */\n items?: AccordionShorthandItem[]\n}>(), {\n\n collapsible: true,\n isDisabled: undefined,\n disabled: undefined,\n variant: 'default',\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: SingleValue | MultipleValue]\n}>()\n\nconst isDisabled = useDeprecatedBooleanProp(\n 'Accordion', 'isDisabled', () => props.isDisabled, 'disabled', () => props.disabled,\n)\n\nconst slotFns = computed(() => accordionVariants({ variant: props.variant, size: props.size }))\n\nuseAccordionProvide({ slotFns })\n</script>\n\n<template>\n <AccordionRoot\n :type=\"props.type\"\n :model-value=\"props.modelValue\"\n :default-value=\"props.defaultValue\"\n :collapsible=\"props.collapsible\"\n :disabled=\"isDisabled\"\n :dir=\"props.dir\"\n :orientation=\"props.orientation\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n @update:model-value=\"(v: SingleValue | MultipleValue | undefined) => { if (v !== undefined) emit('update:modelValue', v) }\"\n >\n <template v-if=\"props.items\">\n <AccordionItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :class-names=\"{ item: props.classNames?.item }\"\n >\n <AccordionHeader>\n <AccordionTrigger :class-names=\"{ trigger: props.classNames?.trigger, indicator: props.classNames?.indicator }\">{{ item.title }}</AccordionTrigger>\n </AccordionHeader>\n <AccordionContent :class-names=\"{ body: props.classNames?.body, bodyInner: props.classNames?.bodyInner }\">{{ item.content }}</AccordionContent>\n </AccordionItem>\n </template>\n <slot v-else />\n </AccordionRoot>\n</template>\n"],"mappings":""}
@@ -75,20 +75,31 @@ var Accordion_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
75
75
  return openBlock(), createBlock(AccordionItem_default, {
76
76
  key: item.value,
77
77
  value: item.value,
78
- "is-disabled": item.disabled
78
+ "is-disabled": item.disabled,
79
+ "class-names": { item: props.classNames?.item }
79
80
  }, {
80
81
  default: withCtx(() => [createVNode(AccordionHeader_default, null, {
81
- default: withCtx(() => [createVNode(AccordionTrigger_default, null, {
82
+ default: withCtx(() => [createVNode(AccordionTrigger_default, { "class-names": {
83
+ trigger: props.classNames?.trigger,
84
+ indicator: props.classNames?.indicator
85
+ } }, {
82
86
  default: withCtx(() => [createTextVNode(toDisplayString(item.title), 1)]),
83
87
  _: 2
84
- }, 1024)]),
88
+ }, 1032, ["class-names"])]),
85
89
  _: 2
86
- }, 1024), createVNode(AccordionContent_default, null, {
90
+ }, 1024), createVNode(AccordionContent_default, { "class-names": {
91
+ body: props.classNames?.body,
92
+ bodyInner: props.classNames?.bodyInner
93
+ } }, {
87
94
  default: withCtx(() => [createTextVNode(toDisplayString(item.content), 1)]),
88
95
  _: 2
89
- }, 1024)]),
96
+ }, 1032, ["class-names"])]),
90
97
  _: 2
91
- }, 1032, ["value", "is-disabled"]);
98
+ }, 1032, [
99
+ "value",
100
+ "is-disabled",
101
+ "class-names"
102
+ ]);
92
103
  }), 128)) : renderSlot(_ctx.$slots, "default", { key: 1 })]),
93
104
  _: 3
94
105
  }, 8, [
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/accordion/Accordion.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AccordionRoot } from 'reka-ui'\nimport { accordionVariants, type AccordionVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useAccordionProvide } from './accordion.context'\nimport AccordionItem from './AccordionItem.vue'\nimport AccordionHeader from './AccordionHeader.vue'\nimport AccordionTrigger from './AccordionTrigger.vue'\nimport AccordionContent from './AccordionContent.vue'\n\ntype SingleValue = string\ntype MultipleValue = string[]\ntype AccordionShorthandItem = { value: string; title: string; content?: string; disabled?: boolean }\n\nconst props = withDefaults(defineProps<{\n type: 'single' | 'multiple'\n modelValue?: SingleValue | MultipleValue\n defaultValue?: SingleValue | MultipleValue\n collapsible?: boolean\n isDisabled?: boolean\n /** @deprecated Use isDisabled instead. */\n disabled?: boolean\n dir?: 'ltr' | 'rtl'\n orientation?: 'horizontal' | 'vertical'\n unmountOnHide?: boolean\n as?: string\n asChild?: boolean\n variant?: AccordionVariants['variant']\n size?: AccordionVariants['size']\n class?: ClassValue\n /** Override classes for any slot */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render items from an array instead of the compound slot API */\n items?: AccordionShorthandItem[]\n}>(), {\n\n collapsible: true,\n isDisabled: undefined,\n disabled: undefined,\n variant: 'default',\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: SingleValue | MultipleValue]\n}>()\n\nconst isDisabled = useDeprecatedBooleanProp(\n 'Accordion', 'isDisabled', () => props.isDisabled, 'disabled', () => props.disabled,\n)\n\nconst slotFns = computed(() => accordionVariants({ variant: props.variant, size: props.size }))\n\nuseAccordionProvide({ slotFns })\n</script>\n\n<template>\n <AccordionRoot\n :type=\"props.type\"\n :model-value=\"props.modelValue\"\n :default-value=\"props.defaultValue\"\n :collapsible=\"props.collapsible\"\n :disabled=\"isDisabled\"\n :dir=\"props.dir\"\n :orientation=\"props.orientation\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n @update:model-value=\"(v: SingleValue | MultipleValue | undefined) => { if (v !== undefined) emit('update:modelValue', v) }\"\n >\n <template v-if=\"props.items\">\n <AccordionItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n >\n <AccordionHeader>\n <AccordionTrigger>{{ item.title }}</AccordionTrigger>\n </AccordionHeader>\n <AccordionContent>{{ item.content }}</AccordionContent>\n </AccordionItem>\n </template>\n <slot v-else />\n </AccordionRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,QAAQ;EA+Bd,MAAM,OAAO;EAIb,MAAM,aAAa,yBACjB,aAAa,oBAAoB,MAAM,YAAY,kBAAkB,MAAM,SAC7E;EAEA,MAAM,UAAU,eAAe,kBAAkB;GAAE,SAAS,MAAM;GAAS,MAAM,MAAM;GAAM,CAAC,CAAA;AAE9F,sBAAoB,EAAE,SAAS,CAAA;;uBAI7B,YA4BgB,MAAA,cAAA,EAAA;IA3Bb,MAAM,MAAM;IACZ,eAAa,MAAM;IACnB,iBAAe,MAAM;IACrB,aAAa,MAAM;IACnB,UAAU,MAAA,WAAU;IACpB,KAAK,MAAM;IACX,aAAa,MAAM;IACnB,mBAAiB,MAAM;IACvB,IAAI,MAAM;IACV,YAAU,MAAM;IAChB,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,MAAI,EAAI,MAAM,OAAO,MAAM,YAAY,KAAI,CAAA;IAC3E,uBAAkB,OAAA,OAAA,OAAA,MAAG,MAA0C;AAAA,SAAW,MAAM,KAAA,EAAW,MAAI,qBAAsB,EAAC;;;2BAc5G,CAZK,MAAM,SAAA,UAAA,KAAA,EACpB,mBAUgB,UAAA,EAAA,KAAA,GAAA,EAAA,WATC,MAAM,QAAd,SAAI;yBADb,YAUgB,uBAAA;MARb,KAAK,KAAK;MACV,OAAO,KAAK;MACZ,eAAa,KAAK;;6BAID,CAFlB,YAEkB,yBAAA,MAAA;8BADqC,CAArD,YAAqD,0BAAA,MAAA;+BAAnB,CAAA,gBAAA,gBAAb,KAAK,MAAK,EAAA,EAAA,CAAA,CAAA;;;;gBAEjC,YAAuD,0BAAA,MAAA;8BAAnB,CAAA,gBAAA,gBAAf,KAAK,QAAO,EAAA,EAAA,CAAA,CAAA;;;;;gBAGrC,WAAe,KAAA,QAAA,WAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"Accordion.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/accordion/Accordion.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AccordionRoot } from 'reka-ui'\nimport { accordionVariants, type AccordionVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useAccordionProvide } from './accordion.context'\nimport AccordionItem from './AccordionItem.vue'\nimport AccordionHeader from './AccordionHeader.vue'\nimport AccordionTrigger from './AccordionTrigger.vue'\nimport AccordionContent from './AccordionContent.vue'\n\ntype SingleValue = string\ntype MultipleValue = string[]\ntype AccordionShorthandItem = { value: string; title: string; content?: string; disabled?: boolean }\n\nconst props = withDefaults(defineProps<{\n type: 'single' | 'multiple'\n modelValue?: SingleValue | MultipleValue\n defaultValue?: SingleValue | MultipleValue\n collapsible?: boolean\n isDisabled?: boolean\n /** @deprecated Use isDisabled instead. */\n disabled?: boolean\n dir?: 'ltr' | 'rtl'\n orientation?: 'horizontal' | 'vertical'\n unmountOnHide?: boolean\n as?: string\n asChild?: boolean\n variant?: AccordionVariants['variant']\n size?: AccordionVariants['size']\n class?: ClassValue\n /** Override classes for any slot */\n classNames?: Partial<{\n base: ClassValue\n item: ClassValue\n trigger: ClassValue\n indicator: ClassValue\n body: ClassValue\n bodyInner: ClassValue\n }>\n /** Shorthand API: render items from an array instead of the compound slot API */\n items?: AccordionShorthandItem[]\n}>(), {\n\n collapsible: true,\n isDisabled: undefined,\n disabled: undefined,\n variant: 'default',\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: SingleValue | MultipleValue]\n}>()\n\nconst isDisabled = useDeprecatedBooleanProp(\n 'Accordion', 'isDisabled', () => props.isDisabled, 'disabled', () => props.disabled,\n)\n\nconst slotFns = computed(() => accordionVariants({ variant: props.variant, size: props.size }))\n\nuseAccordionProvide({ slotFns })\n</script>\n\n<template>\n <AccordionRoot\n :type=\"props.type\"\n :model-value=\"props.modelValue\"\n :default-value=\"props.defaultValue\"\n :collapsible=\"props.collapsible\"\n :disabled=\"isDisabled\"\n :dir=\"props.dir\"\n :orientation=\"props.orientation\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n @update:model-value=\"(v: SingleValue | MultipleValue | undefined) => { if (v !== undefined) emit('update:modelValue', v) }\"\n >\n <template v-if=\"props.items\">\n <AccordionItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :class-names=\"{ item: props.classNames?.item }\"\n >\n <AccordionHeader>\n <AccordionTrigger :class-names=\"{ trigger: props.classNames?.trigger, indicator: props.classNames?.indicator }\">{{ item.title }}</AccordionTrigger>\n </AccordionHeader>\n <AccordionContent :class-names=\"{ body: props.classNames?.body, bodyInner: props.classNames?.bodyInner }\">{{ item.content }}</AccordionContent>\n </AccordionItem>\n </template>\n <slot v-else />\n </AccordionRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,QAAQ;EAoCd,MAAM,OAAO;EAIb,MAAM,aAAa,yBACjB,aAAa,oBAAoB,MAAM,YAAY,kBAAkB,MAAM,SAC7E;EAEA,MAAM,UAAU,eAAe,kBAAkB;GAAE,SAAS,MAAM;GAAS,MAAM,MAAM;GAAM,CAAC,CAAA;AAE9F,sBAAoB,EAAE,SAAS,CAAA;;uBAI7B,YA6BgB,MAAA,cAAA,EAAA;IA5Bb,MAAM,MAAM;IACZ,eAAa,MAAM;IACnB,iBAAe,MAAM;IACrB,aAAa,MAAM;IACnB,UAAU,MAAA,WAAU;IACpB,KAAK,MAAM;IACX,aAAa,MAAM;IACnB,mBAAiB,MAAM;IACvB,IAAI,MAAM;IACV,YAAU,MAAM;IAChB,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,MAAI,EAAI,MAAM,OAAO,MAAM,YAAY,KAAI,CAAA;IAC3E,uBAAkB,OAAA,OAAA,OAAA,MAAG,MAA0C;AAAA,SAAW,MAAM,KAAA,EAAW,MAAI,qBAAsB,EAAC;;;2BAe5G,CAbK,MAAM,SAAA,UAAA,KAAA,EACpB,mBAWgB,UAAA,EAAA,KAAA,GAAA,EAAA,WAVC,MAAM,QAAd,SAAI;yBADb,YAWgB,uBAAA;MATb,KAAK,KAAK;MACV,OAAO,KAAK;MACZ,eAAa,KAAK;MAClB,eAAW,EAAA,MAAU,MAAM,YAAY,MAAI;;6BAI1B,CAFlB,YAEkB,yBAAA,MAAA;8BADmI,CAAnJ,YAAmJ,0BAAA,EAAhI,eAAW;QAAA,SAAa,MAAM,YAAY;QAAO,WAAa,MAAM,YAAY;QAAS,EAAA,EAAA;+BAAoB,CAAA,gBAAA,gBAAb,KAAK,MAAK,EAAA,EAAA,CAAA,CAAA;;;;gBAE/H,YAA+I,0BAAA,EAA5H,eAAW;OAAA,MAAU,MAAM,YAAY;OAAI,WAAa,MAAM,YAAY;OAAS,EAAA,EAAA;8BAAsB,CAAA,gBAAA,gBAAf,KAAK,QAAO,EAAA,EAAA,CAAA,CAAA;;;;;;;;;gBAG7H,WAAe,KAAA,QAAA,WAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.js","names":[],"sources":["../../../src/components/autocomplete/Autocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, toRef, useAttrs, useId, watch, useSlots, type ComputedRef } from 'vue'\nimport { AutocompleteRoot } from 'reka-ui'\nimport { autocompleteVariants, type AutocompleteVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useAutocompleteProvide } from './Autocomplete.context'\nimport { hasSlotComponent } from '../../utils/hasSlotComponent'\nimport AutocompleteInput from './AutocompleteInput.vue'\nimport AutocompleteContent from './AutocompleteContent.vue'\nimport AutocompleteItem from './AutocompleteItem.vue'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useFormField } from '../../composables/useFormField'\nimport FieldLabel from '../_shared/FieldLabel.vue'\nimport FormFieldHelper from '../_shared/FormFieldHelper.vue'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<Props>(), {\n variant: 'flat',\n size: 'md',\n color: 'default',\n labelPlacement: 'inside',\n fullWidth: false,\n isInvalid: false,\n isDisabled: false,\n isReadOnly: undefined,\n isReadonly: undefined,\n isRequired: false,\n multiple: false,\n multipleOverflow: 'wrap',\n modelValue: undefined,\n defaultValue: undefined,\n open: undefined,\n defaultOpen: undefined,\n items: () => [],\n loadItems: undefined,\n debounceMs: 200,\n filterOnOpen: false,\n truncateItems: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[]]\n 'update:open': [value: boolean]\n /** Fired when the user creates a new value via `creatable` or `<AutocompleteCreateItem>`. */\n 'create': [value: string]\n /** Fired when an item is highlighted. */\n 'highlight': [context: { ref: Element; value: string } | undefined]\n}>()\n\nconst isReadOnly = useDeprecatedBooleanProp(\n 'Autocomplete', 'isReadOnly', () => props.isReadOnly, 'isReadonly', () => props.isReadonly,\n)\n\nexport interface AutocompleteItem {\n value: string\n label?: string\n textValue?: string\n isDisabled?: boolean\n}\n\ntype Props = {\n /** Visual style of the field. @default 'flat' */\n variant?: AutocompleteVariants['variant']\n /** Field height. @default 'md' */\n size?: AutocompleteVariants['size']\n /** Accent color applied to focus ring + floating label. @default 'default' */\n color?: AutocompleteVariants['color']\n /**\n * Where the `label` is rendered relative to the field.\n * - `inside`: floats above the trigger (shrinks when focused/filled)\n * - `outside`: sits above the field, static\n * - `outside-left`: sits to the left, horizontal layout\n * @default 'inside'\n */\n labelPlacement?: AutocompleteVariants['labelPlacement']\n /** Stretches root wrapper to 100% width. @default false */\n fullWidth?: boolean\n /** Marks the field as invalid. Triggers danger styling and enables `errorMessage`. @default false */\n isInvalid?: boolean\n /** Disables the field. @default false */\n isDisabled?: boolean\n /** Makes the field read-only. @default false */\n isReadOnly?: boolean\n /** @deprecated Use isReadOnly instead. */\n isReadonly?: boolean\n /** Adds a required asterisk next to the label. @default false */\n isRequired?: boolean\n /** Placeholder shown when empty. */\n placeholder?: string\n /** Form field name, for native form submission. */\n name?: string\n /** Field label. When omitted, the floating-label behavior is skipped. */\n label?: string\n /** Helper text displayed below the field. Suppressed when `isInvalid && errorMessage` is shown. */\n description?: string\n /** Error text displayed below the field. Only rendered when `isInvalid` is also true. */\n errorMessage?: string\n /** Extra classes merged onto the root wrapper via `composeClassName`. */\n class?: ClassValue\n /** Per-slot class overrides. Keys correspond to internal slot names (`base`, `label`, `mainWrapper`, `helperWrapper`, `errorMessage`, `description`). */\n classNames?: Partial<{\n base: ClassValue\n label: ClassValue\n mainWrapper: ClassValue\n helperWrapper: ClassValue\n errorMessage: ClassValue\n description: ClassValue\n }>\n\n /* ─── Reka AutocompleteRoot pass-through props ───────────────────── */\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Reset the search term when the trigger loses focus. */\n resetSearchTermOnBlur?: boolean\n /** Open the dropdown when the input gains focus. */\n openOnFocus?: boolean\n /** Open the dropdown when the input is clicked. */\n openOnClick?: boolean\n /** Disable Reka's built-in filter; handle filtering externally. */\n ignoreFilter?: boolean\n /** Highlight the matching item on hover. */\n highlightOnHover?: boolean\n /** Render as a different element or component. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n\n /* ─── Autocomplete-specific ─────────────────────────────────────── */\n /** Two-way bound selected value. string in single mode, string[] in multiple mode. */\n modelValue?: string | string[]\n /** Initial selected value (uncontrolled). */\n defaultValue?: string | string[]\n /** Allow selecting multiple values. modelValue becomes string[]. @default false */\n multiple?: boolean\n /**\n * Controls how chips overflow in multiple mode.\n * - `wrap`: trigger grows in height, chips wrap to new lines (default)\n * - `collapse`: fixed height, overflowing chips are hidden behind \"+N more\"\n * @default 'wrap'\n */\n multipleOverflow?: 'wrap' | 'collapse'\n /** Controls open state of the dropdown. */\n open?: boolean\n /** Initial open state of the dropdown (uncontrolled). */\n defaultOpen?: boolean\n /** Static items list — used when no loadItems is provided. */\n items?: AutocompleteItem[]\n /** Async data source: called on every query change. */\n loadItems?: (query: string) => Promise<AutocompleteItem[]>\n /** Debounce delay for loadItems calls (ms). 0 = no debounce. */\n debounceMs?: number\n /** Apply filter immediately on open (default: false — show all items until user types). */\n filterOnOpen?: boolean\n /**\n * Truncate item text with an ellipsis when it overflows the dropdown width.\n * Set to `false` to show full text — the dropdown will widen to fit.\n * @default true\n */\n truncateItems?: boolean\n}\n\nconst attrs = useAttrs()\nconst generatedId = useId()\nconst inputId = computed(() => (attrs.id as string | undefined) ?? generatedId)\n\nconst {\n descriptionId,\n errorMessageId,\n showError,\n showDescription,\n hasHelper,\n ariaDescribedBy,\n hasLabel,\n showOutsideLabel,\n rootDataAttrs,\n} = useFormField({\n fieldId: () => inputId.value,\n label: () => props.label,\n description: () => props.description,\n errorMessage: () => props.errorMessage,\n isInvalid: () => props.isInvalid,\n isDisabled: () => props.isDisabled,\n isReadOnly: () => isReadOnly.value,\n isRequired: () => props.isRequired,\n labelPlacement: () => props.labelPlacement,\n})\n\nconst slots = useSlots()\n// Compound chrome present → pass slot through (advanced). Otherwise render the\n// input/content/items internally (short-form).\nconst usesCustomChrome: ComputedRef<boolean> = computed(() =>\n hasSlotComponent(slots.default?.({ isLoading: false, items: [] }), [AutocompleteInput, AutocompleteContent]),\n)\n\n// Registry for slot-rendered items: value → label (populated by AutocompleteItem at mount).\n// Replaced with a new Map instance on each mutation so Vue's ref() reactivity tracks changes.\nconst slotItemRegistry = ref(new Map<string, string>())\n\nfunction registerItem(value: string, label: string) {\n const next = new Map(slotItemRegistry.value)\n next.set(value, label)\n slotItemRegistry.value = next\n}\n\nfunction unregisterItem(value: string) {\n const next = new Map(slotItemRegistry.value)\n next.delete(value)\n slotItemRegistry.value = next\n}\n\n// Internal async state\nconst isLoading = ref(false)\nconst internalItems = ref<AutocompleteItem[]>([...props.items])\n\n// ── Multiple-mode state ────────────────────────────────────────────────────\n// Tracks selected values as an array. Only meaningful when props.multiple=true.\nconst selectedValues = ref<string[]>(\n props.multiple && Array.isArray(props.modelValue) ? [...props.modelValue] : [],\n)\n\n// Controlled open state used in multiple mode to prevent the dropdown closing\n// after each item selection (Reka would normally close on selection).\nconst internalOpen = ref(props.defaultOpen ?? false)\n\n// Flag set by onMultipleSelect so handleOpenChange can distinguish item\n// selection from Escape/outside-click close.\nlet selectingItem = false\n\n// ── Open-state tracking ────────────────────────────────────────────────────\nconst isOpen = ref(props.defaultOpen ?? false)\nconst termAtOpen = ref('')\nconst isUserTyping = ref(false)\n// Controlled open state for single mode (mirrors multiple mode's internalOpen).\n// Driving open ourselves lets handleOpenChange gate spurious reopens — e.g. the\n// focus bounce caused when a create handler mutates the items list.\nconst singleOpen = ref(props.open ?? props.defaultOpen ?? false)\n// When true, handleOpenChange ignores open=true requests. Set briefly after a\n// single-mode create so the post-create re-render can't reopen the menu.\nlet blockReopen = false\nlet blockReopenTimer: ReturnType<typeof setTimeout> | undefined\nconst effectiveIgnoreFilter = computed(() => {\n if (props.loadItems) return true\n if (!props.filterOnOpen && isOpen.value && !isUserTyping.value) return true\n return false\n})\n\n// ── Label/value bridge ─────────────────────────────────────────────────────\n// Priority: items prop entry > slot registry > identity fallback\nfunction labelFor(value: string | undefined): string {\n if (value == null || value === '') return ''\n const match = internalItems.value.find((i) => i.value === value)\n if (match) return match.label ?? match.textValue ?? value\n return slotItemRegistry.value.get(value) ?? value\n}\nfunction valueFor(displayed: string): string {\n if (!displayed) return ''\n const match = internalItems.value.find(\n (i) => (i.label ?? i.textValue ?? i.value) === displayed,\n )\n if (match) return match.value\n for (const [value, label] of slotItemRegistry.value) {\n if (label === displayed) return value\n }\n return displayed\n}\n\nconst singleModelValue = computed(() =>\n props.multiple ? undefined : (props.modelValue as string | undefined),\n)\n\nconst searchTerm = ref(labelFor(singleModelValue.value))\n\nconst isFilled = computed(() =>\n props.multiple\n ? selectedValues.value.length > 0 || !!searchTerm.value\n : !!searchTerm.value,\n)\nconst hasItems = computed(() => internalItems.value.length > 0)\n\nconst selectedLabels = computed(() =>\n selectedValues.value.map(v => ({ value: v, label: labelFor(v) || v })),\n)\n\n// ── Watchers ───────────────────────────────────────────────────────────────\n\n// Parent → internal: sync controlled modelValue into local state\nwatch(() => props.modelValue, (val) => {\n if (props.multiple) {\n if (Array.isArray(val)) selectedValues.value = [...val]\n } else {\n const next = labelFor(val as string | undefined)\n if (searchTerm.value !== next) searchTerm.value = next\n }\n})\n\n// Parent → internal: sync consumer-controlled open into our single-mode state\nwatch(() => props.open, (val) => {\n if (!props.multiple && val !== undefined) singleOpen.value = val\n})\n\n// Internal → parent: single mode only — multiple mode emits inside onMultipleSelect\nwatch(searchTerm, (displayed) => {\n if (props.multiple) {\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n return\n }\n const next = valueFor(displayed)\n if (next !== (singleModelValue.value ?? '')) emit('update:modelValue', next)\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n})\n\nfunction handleOpenChange(val: boolean) {\n if (props.multiple) {\n isOpen.value = val\n // Suppress close when triggered by item selection; allow Escape/outside-click\n internalOpen.value = (!val && selectingItem) ? true : val\n selectingItem = false\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n return\n }\n\n // Single mode: ignore spurious reopen requests right after a create — the\n // create handler's re-render bounces focus back to the input, which would\n // otherwise reopen the menu via openOnFocus.\n if (val && blockReopen) return\n\n isOpen.value = val\n singleOpen.value = val\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n}\n\n// ── Multiple-mode actions ──────────────────────────────────────────────────\n\nfunction onMultipleSelect(value: string) {\n selectingItem = true\n const idx = selectedValues.value.indexOf(value)\n selectedValues.value = idx === -1\n ? [...selectedValues.value, value]\n : selectedValues.value.filter((_, i) => i !== idx)\n // Clear the input and drop out of \"typing\" mode so the filter is ignored and\n // the full list shows again (effectiveIgnoreFilter depends on !isUserTyping).\n searchTerm.value = ''\n isUserTyping.value = false\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction removeValue(value: string) {\n selectedValues.value = selectedValues.value.filter(v => v !== value)\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction clearAll() {\n selectedValues.value = []\n emit('update:modelValue', [])\n}\n\nfunction isSelected(value: string): boolean {\n return selectedValues.value.includes(value)\n}\n\n// ── Creatable ──────────────────────────────────────────────────────────────\n\nconst hasExactMatch = computed(() => {\n const term = searchTerm.value.trim().toLowerCase()\n if (!term) return false\n const inItems = internalItems.value.some(\n i => (i.label ?? i.textValue ?? i.value).toLowerCase() === term,\n )\n if (inItems) return true\n for (const label of slotItemRegistry.value.values()) {\n if (label.toLowerCase() === term) return true\n }\n return false\n})\n\nfunction onCreateValue(value: string) {\n const trimmed = value.trim()\n if (!trimmed) return\n if (props.multiple) {\n // We own selection state; add the value, then reset input + filter for the\n // next entry (dropdown is kept open and refocused by AutocompleteCreateItem).\n if (!selectedValues.value.includes(trimmed)) {\n selectingItem = true\n selectedValues.value = [...selectedValues.value, trimmed]\n emit('update:modelValue', selectedValues.value)\n }\n searchTerm.value = ''\n isUserTyping.value = false\n } else {\n // Single mode: set the value ourselves and close the (controlled) dropdown.\n searchTerm.value = trimmed\n emit('update:modelValue', trimmed)\n isOpen.value = false\n singleOpen.value = false\n // The create handler (parent @create) typically mutates the items list, which\n // re-renders and bounces focus back to the input — that fires openOnFocus and\n // would reopen the menu. Block reopen requests briefly so the close sticks.\n blockReopen = true\n clearTimeout(blockReopenTimer)\n blockReopenTimer = setTimeout(() => { blockReopen = false }, 300)\n }\n emit('create', trimmed)\n}\n\n// ── Async loading ──────────────────────────────────────────────────────────\nlet debounceTimer: ReturnType<typeof setTimeout> | undefined\n\nasync function runLoadItems(query: string) {\n if (!props.loadItems) return\n isLoading.value = true\n try {\n internalItems.value = await props.loadItems(query)\n } finally {\n isLoading.value = false\n }\n}\n\nfunction scheduleLoad(query: string) {\n if (!props.loadItems) return\n clearTimeout(debounceTimer)\n if (props.debounceMs === 0) {\n void runLoadItems(query)\n } else {\n debounceTimer = setTimeout(() => void runLoadItems(query), props.debounceMs)\n }\n}\n\nonMounted(() => {\n if (props.loadItems) void runLoadItems(searchTerm.value)\n})\n\nwatch(searchTerm, (q) => {\n if (props.loadItems) scheduleLoad(q)\n})\n\nwatch(() => props.items, (newItems) => {\n if (!props.loadItems) internalItems.value = [...newItems]\n})\n\nwatch(internalItems, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\nwatch(slotItemRegistry, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\n// ── Styles / context ───────────────────────────────────────────────────────\n\nconst slotFns = computed(() =>\n autocompleteVariants({\n variant: props.variant,\n size: props.size,\n color: props.color,\n fullWidth: props.fullWidth,\n isInvalid: props.isInvalid,\n isDisabled: props.isDisabled,\n isReadonly: isReadOnly.value,\n hasLabel: hasLabel.value,\n labelPlacement: props.labelPlacement,\n }),\n)\n\nuseAutocompleteProvide({\n isDisabled: toRef(props, 'isDisabled'),\n isInvalid: toRef(props, 'isInvalid'),\n isReadonly: isReadOnly,\n isRequired: toRef(props, 'isRequired'),\n isLoading,\n isFilled,\n fullWidth: toRef(props, 'fullWidth'),\n hasLabel,\n labelPlacement: toRef(props, 'labelPlacement'),\n inputId,\n label: toRef(props, 'label'),\n ariaDescribedBy,\n truncateItems: toRef(props, 'truncateItems'),\n hasItems,\n slots: slotFns,\n multiple: toRef(props, 'multiple'),\n multipleOverflow: toRef(props, 'multipleOverflow'),\n selectedValues,\n selectedLabels,\n onMultipleSelect,\n removeValue,\n clearAll,\n isSelected,\n registerItem,\n unregisterItem,\n searchTerm,\n hasExactMatch,\n onCreateValue,\n})\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n v-bind=\"rootDataAttrs\"\n >\n <FieldLabel\n v-if=\"showOutsideLabel\"\n :for=\"inputId\"\n :label=\"label\"\n :is-required=\"isRequired\"\n :class=\"composeClassName(slotFns.label(), props.classNames?.label)\"\n />\n\n <div :class=\"composeClassName(slotFns.mainWrapper(), props.classNames?.mainWrapper)\">\n <AutocompleteRoot\n v-model:model-value=\"searchTerm\"\n :open=\"props.multiple ? internalOpen : singleOpen\"\n :disabled=\"props.isDisabled\"\n :required=\"props.isRequired\"\n :name=\"props.name\"\n :dir=\"props.dir\"\n :ignore-filter=\"effectiveIgnoreFilter\"\n :open-on-focus=\"props.openOnFocus ?? true\"\n :open-on-click=\"props.openOnClick\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :reset-search-term-on-blur=\"props.resetSearchTermOnBlur\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n @update:open=\"handleOpenChange\"\n @highlight=\"emit('highlight', $event)\"\n >\n <slot\n v-if=\"usesCustomChrome\"\n :is-loading=\"isLoading\"\n :items=\"internalItems\"\n />\n <template v-else>\n <AutocompleteInput :placeholder=\"props.placeholder\" />\n <AutocompleteContent>\n <AutocompleteItem\n v-for=\"item in internalItems\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.isDisabled\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n >{{ item.label ?? item.textValue ?? item.value }}</slot>\n </AutocompleteItem>\n </AutocompleteContent>\n </template>\n </AutocompleteRoot>\n\n <FormFieldHelper\n :has-helper=\"hasHelper\"\n :show-error=\"showError\"\n :show-description=\"showDescription\"\n :error-message=\"errorMessage\"\n :description=\"description\"\n :error-message-id=\"errorMessageId\"\n :description-id=\"descriptionId\"\n :wrapper-class=\"composeClassName(slotFns.helperWrapper(), props.classNames?.helperWrapper)\"\n :error-class=\"composeClassName(slotFns.errorMessage(), props.classNames?.errorMessage)\"\n :description-class=\"composeClassName(slotFns.description(), props.classNames?.description)\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Autocomplete.js","names":[],"sources":["../../../src/components/autocomplete/Autocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, toRef, useAttrs, useId, watch, useSlots, type ComputedRef } from 'vue'\nimport { AutocompleteRoot } from 'reka-ui'\nimport { autocompleteVariants, type AutocompleteVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useAutocompleteProvide } from './Autocomplete.context'\nimport { hasSlotComponent } from '../../utils/hasSlotComponent'\nimport AutocompleteInput from './AutocompleteInput.vue'\nimport AutocompleteContent from './AutocompleteContent.vue'\nimport AutocompleteItem from './AutocompleteItem.vue'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useFormField } from '../../composables/useFormField'\nimport FieldLabel from '../_shared/FieldLabel.vue'\nimport FormFieldHelper from '../_shared/FormFieldHelper.vue'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<Props>(), {\n variant: 'flat',\n size: 'md',\n color: 'default',\n labelPlacement: 'inside',\n fullWidth: false,\n isInvalid: false,\n isDisabled: false,\n isReadOnly: undefined,\n isReadonly: undefined,\n isRequired: false,\n multiple: false,\n multipleOverflow: 'wrap',\n modelValue: undefined,\n defaultValue: undefined,\n open: undefined,\n defaultOpen: undefined,\n items: () => [],\n loadItems: undefined,\n debounceMs: 200,\n filterOnOpen: false,\n truncateItems: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[]]\n 'update:open': [value: boolean]\n /** Fired when the user creates a new value via `creatable` or `<AutocompleteCreateItem>`. */\n 'create': [value: string]\n /** Fired when an item is highlighted. */\n 'highlight': [context: { ref: Element; value: string } | undefined]\n}>()\n\nconst isReadOnly = useDeprecatedBooleanProp(\n 'Autocomplete', 'isReadOnly', () => props.isReadOnly, 'isReadonly', () => props.isReadonly,\n)\n\nexport interface AutocompleteItem {\n value: string\n label?: string\n textValue?: string\n isDisabled?: boolean\n}\n\ntype Props = {\n /** Visual style of the field. @default 'flat' */\n variant?: AutocompleteVariants['variant']\n /** Field height. @default 'md' */\n size?: AutocompleteVariants['size']\n /** Accent color applied to focus ring + floating label. @default 'default' */\n color?: AutocompleteVariants['color']\n /**\n * Where the `label` is rendered relative to the field.\n * - `inside`: floats above the trigger (shrinks when focused/filled)\n * - `outside`: sits above the field, static\n * - `outside-left`: sits to the left, horizontal layout\n * @default 'inside'\n */\n labelPlacement?: AutocompleteVariants['labelPlacement']\n /** Stretches root wrapper to 100% width. @default false */\n fullWidth?: boolean\n /** Marks the field as invalid. Triggers danger styling and enables `errorMessage`. @default false */\n isInvalid?: boolean\n /** Disables the field. @default false */\n isDisabled?: boolean\n /** Makes the field read-only. @default false */\n isReadOnly?: boolean\n /** @deprecated Use isReadOnly instead. */\n isReadonly?: boolean\n /** Adds a required asterisk next to the label. @default false */\n isRequired?: boolean\n /** Placeholder shown when empty. */\n placeholder?: string\n /** Form field name, for native form submission. */\n name?: string\n /** Field label. When omitted, the floating-label behavior is skipped. */\n label?: string\n /** Helper text displayed below the field. Suppressed when `isInvalid && errorMessage` is shown. */\n description?: string\n /** Error text displayed below the field. Only rendered when `isInvalid` is also true. */\n errorMessage?: string\n /** Extra classes merged onto the root wrapper via `composeClassName`. */\n class?: ClassValue\n /** Per-slot class overrides. Keys correspond to internal slot names (`base`, `label`, `mainWrapper`, `helperWrapper`, `errorMessage`, `description`). */\n classNames?: Partial<{\n base: ClassValue\n label: ClassValue\n mainWrapper: ClassValue\n helperWrapper: ClassValue\n errorMessage: ClassValue\n description: ClassValue\n item: ClassValue\n text: ClassValue\n indicator: ClassValue\n trigger: ClassValue\n startContent: ClassValue\n input: ClassValue\n clearButton: ClassValue\n /** The loading-spinner/chevron indicator inside the input (distinct from `indicator`, which styles each item's checkmark). */\n triggerIndicator: ClassValue\n chip: Partial<{\n base: ClassValue\n dot: ClassValue\n startContent: ClassValue\n label: ClassValue\n endContent: ClassValue\n closeButton: ClassValue\n }>\n }>\n\n /* ─── Reka AutocompleteRoot pass-through props ───────────────────── */\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Reset the search term when the trigger loses focus. */\n resetSearchTermOnBlur?: boolean\n /** Open the dropdown when the input gains focus. */\n openOnFocus?: boolean\n /** Open the dropdown when the input is clicked. */\n openOnClick?: boolean\n /** Disable Reka's built-in filter; handle filtering externally. */\n ignoreFilter?: boolean\n /** Highlight the matching item on hover. */\n highlightOnHover?: boolean\n /** Render as a different element or component. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n\n /* ─── Autocomplete-specific ─────────────────────────────────────── */\n /** Two-way bound selected value. string in single mode, string[] in multiple mode. */\n modelValue?: string | string[]\n /** Initial selected value (uncontrolled). */\n defaultValue?: string | string[]\n /** Allow selecting multiple values. modelValue becomes string[]. @default false */\n multiple?: boolean\n /**\n * Controls how chips overflow in multiple mode.\n * - `wrap`: trigger grows in height, chips wrap to new lines (default)\n * - `collapse`: fixed height, overflowing chips are hidden behind \"+N more\"\n * @default 'wrap'\n */\n multipleOverflow?: 'wrap' | 'collapse'\n /** Controls open state of the dropdown. */\n open?: boolean\n /** Initial open state of the dropdown (uncontrolled). */\n defaultOpen?: boolean\n /** Static items list — used when no loadItems is provided. */\n items?: AutocompleteItem[]\n /** Async data source: called on every query change. */\n loadItems?: (query: string) => Promise<AutocompleteItem[]>\n /** Debounce delay for loadItems calls (ms). 0 = no debounce. */\n debounceMs?: number\n /** Apply filter immediately on open (default: false — show all items until user types). */\n filterOnOpen?: boolean\n /**\n * Truncate item text with an ellipsis when it overflows the dropdown width.\n * Set to `false` to show full text — the dropdown will widen to fit.\n * @default true\n */\n truncateItems?: boolean\n}\n\nconst attrs = useAttrs()\nconst generatedId = useId()\nconst inputId = computed(() => (attrs.id as string | undefined) ?? generatedId)\n\nconst {\n descriptionId,\n errorMessageId,\n showError,\n showDescription,\n hasHelper,\n ariaDescribedBy,\n hasLabel,\n showOutsideLabel,\n rootDataAttrs,\n} = useFormField({\n fieldId: () => inputId.value,\n label: () => props.label,\n description: () => props.description,\n errorMessage: () => props.errorMessage,\n isInvalid: () => props.isInvalid,\n isDisabled: () => props.isDisabled,\n isReadOnly: () => isReadOnly.value,\n isRequired: () => props.isRequired,\n labelPlacement: () => props.labelPlacement,\n})\n\nconst slots = useSlots()\n// Compound chrome present → pass slot through (advanced). Otherwise render the\n// input/content/items internally (short-form).\nconst usesCustomChrome: ComputedRef<boolean> = computed(() =>\n hasSlotComponent(slots.default?.({ isLoading: false, items: [] }), [AutocompleteInput, AutocompleteContent]),\n)\n\n// Registry for slot-rendered items: value → label (populated by AutocompleteItem at mount).\n// Replaced with a new Map instance on each mutation so Vue's ref() reactivity tracks changes.\nconst slotItemRegistry = ref(new Map<string, string>())\n\nfunction registerItem(value: string, label: string) {\n const next = new Map(slotItemRegistry.value)\n next.set(value, label)\n slotItemRegistry.value = next\n}\n\nfunction unregisterItem(value: string) {\n const next = new Map(slotItemRegistry.value)\n next.delete(value)\n slotItemRegistry.value = next\n}\n\n// Internal async state\nconst isLoading = ref(false)\nconst internalItems = ref<AutocompleteItem[]>([...props.items])\n\n// ── Multiple-mode state ────────────────────────────────────────────────────\n// Tracks selected values as an array. Only meaningful when props.multiple=true.\nconst selectedValues = ref<string[]>(\n props.multiple && Array.isArray(props.modelValue) ? [...props.modelValue] : [],\n)\n\n// Controlled open state used in multiple mode to prevent the dropdown closing\n// after each item selection (Reka would normally close on selection).\nconst internalOpen = ref(props.defaultOpen ?? false)\n\n// Flag set by onMultipleSelect so handleOpenChange can distinguish item\n// selection from Escape/outside-click close.\nlet selectingItem = false\n\n// ── Open-state tracking ────────────────────────────────────────────────────\nconst isOpen = ref(props.defaultOpen ?? false)\nconst termAtOpen = ref('')\nconst isUserTyping = ref(false)\n// Controlled open state for single mode (mirrors multiple mode's internalOpen).\n// Driving open ourselves lets handleOpenChange gate spurious reopens — e.g. the\n// focus bounce caused when a create handler mutates the items list.\nconst singleOpen = ref(props.open ?? props.defaultOpen ?? false)\n// When true, handleOpenChange ignores open=true requests. Set briefly after a\n// single-mode create so the post-create re-render can't reopen the menu.\nlet blockReopen = false\nlet blockReopenTimer: ReturnType<typeof setTimeout> | undefined\nconst effectiveIgnoreFilter = computed(() => {\n if (props.loadItems) return true\n if (!props.filterOnOpen && isOpen.value && !isUserTyping.value) return true\n return false\n})\n\n// ── Label/value bridge ─────────────────────────────────────────────────────\n// Priority: items prop entry > slot registry > identity fallback\nfunction labelFor(value: string | undefined): string {\n if (value == null || value === '') return ''\n const match = internalItems.value.find((i) => i.value === value)\n if (match) return match.label ?? match.textValue ?? value\n return slotItemRegistry.value.get(value) ?? value\n}\nfunction valueFor(displayed: string): string {\n if (!displayed) return ''\n const match = internalItems.value.find(\n (i) => (i.label ?? i.textValue ?? i.value) === displayed,\n )\n if (match) return match.value\n for (const [value, label] of slotItemRegistry.value) {\n if (label === displayed) return value\n }\n return displayed\n}\n\nconst singleModelValue = computed(() =>\n props.multiple ? undefined : (props.modelValue as string | undefined),\n)\n\nconst searchTerm = ref(labelFor(singleModelValue.value))\n\nconst isFilled = computed(() =>\n props.multiple\n ? selectedValues.value.length > 0 || !!searchTerm.value\n : !!searchTerm.value,\n)\nconst hasItems = computed(() => internalItems.value.length > 0)\n\nconst selectedLabels = computed(() =>\n selectedValues.value.map(v => ({ value: v, label: labelFor(v) || v })),\n)\n\n// ── Watchers ───────────────────────────────────────────────────────────────\n\n// Parent → internal: sync controlled modelValue into local state\nwatch(() => props.modelValue, (val) => {\n if (props.multiple) {\n if (Array.isArray(val)) selectedValues.value = [...val]\n } else {\n const next = labelFor(val as string | undefined)\n if (searchTerm.value !== next) searchTerm.value = next\n }\n})\n\n// Parent → internal: sync consumer-controlled open into our single-mode state\nwatch(() => props.open, (val) => {\n if (!props.multiple && val !== undefined) singleOpen.value = val\n})\n\n// Internal → parent: single mode only — multiple mode emits inside onMultipleSelect\nwatch(searchTerm, (displayed) => {\n if (props.multiple) {\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n return\n }\n const next = valueFor(displayed)\n if (next !== (singleModelValue.value ?? '')) emit('update:modelValue', next)\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n})\n\nfunction handleOpenChange(val: boolean) {\n if (props.multiple) {\n isOpen.value = val\n // Suppress close when triggered by item selection; allow Escape/outside-click\n internalOpen.value = (!val && selectingItem) ? true : val\n selectingItem = false\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n return\n }\n\n // Single mode: ignore spurious reopen requests right after a create — the\n // create handler's re-render bounces focus back to the input, which would\n // otherwise reopen the menu via openOnFocus.\n if (val && blockReopen) return\n\n isOpen.value = val\n singleOpen.value = val\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n}\n\n// ── Multiple-mode actions ──────────────────────────────────────────────────\n\nfunction onMultipleSelect(value: string) {\n selectingItem = true\n const idx = selectedValues.value.indexOf(value)\n selectedValues.value = idx === -1\n ? [...selectedValues.value, value]\n : selectedValues.value.filter((_, i) => i !== idx)\n // Clear the input and drop out of \"typing\" mode so the filter is ignored and\n // the full list shows again (effectiveIgnoreFilter depends on !isUserTyping).\n searchTerm.value = ''\n isUserTyping.value = false\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction removeValue(value: string) {\n selectedValues.value = selectedValues.value.filter(v => v !== value)\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction clearAll() {\n selectedValues.value = []\n emit('update:modelValue', [])\n}\n\nfunction isSelected(value: string): boolean {\n return selectedValues.value.includes(value)\n}\n\n// ── Creatable ──────────────────────────────────────────────────────────────\n\nconst hasExactMatch = computed(() => {\n const term = searchTerm.value.trim().toLowerCase()\n if (!term) return false\n const inItems = internalItems.value.some(\n i => (i.label ?? i.textValue ?? i.value).toLowerCase() === term,\n )\n if (inItems) return true\n for (const label of slotItemRegistry.value.values()) {\n if (label.toLowerCase() === term) return true\n }\n return false\n})\n\nfunction onCreateValue(value: string) {\n const trimmed = value.trim()\n if (!trimmed) return\n if (props.multiple) {\n // We own selection state; add the value, then reset input + filter for the\n // next entry (dropdown is kept open and refocused by AutocompleteCreateItem).\n if (!selectedValues.value.includes(trimmed)) {\n selectingItem = true\n selectedValues.value = [...selectedValues.value, trimmed]\n emit('update:modelValue', selectedValues.value)\n }\n searchTerm.value = ''\n isUserTyping.value = false\n } else {\n // Single mode: set the value ourselves and close the (controlled) dropdown.\n searchTerm.value = trimmed\n emit('update:modelValue', trimmed)\n isOpen.value = false\n singleOpen.value = false\n // The create handler (parent @create) typically mutates the items list, which\n // re-renders and bounces focus back to the input — that fires openOnFocus and\n // would reopen the menu. Block reopen requests briefly so the close sticks.\n blockReopen = true\n clearTimeout(blockReopenTimer)\n blockReopenTimer = setTimeout(() => { blockReopen = false }, 300)\n }\n emit('create', trimmed)\n}\n\n// ── Async loading ──────────────────────────────────────────────────────────\nlet debounceTimer: ReturnType<typeof setTimeout> | undefined\n\nasync function runLoadItems(query: string) {\n if (!props.loadItems) return\n isLoading.value = true\n try {\n internalItems.value = await props.loadItems(query)\n } finally {\n isLoading.value = false\n }\n}\n\nfunction scheduleLoad(query: string) {\n if (!props.loadItems) return\n clearTimeout(debounceTimer)\n if (props.debounceMs === 0) {\n void runLoadItems(query)\n } else {\n debounceTimer = setTimeout(() => void runLoadItems(query), props.debounceMs)\n }\n}\n\nonMounted(() => {\n if (props.loadItems) void runLoadItems(searchTerm.value)\n})\n\nwatch(searchTerm, (q) => {\n if (props.loadItems) scheduleLoad(q)\n})\n\nwatch(() => props.items, (newItems) => {\n if (!props.loadItems) internalItems.value = [...newItems]\n})\n\nwatch(internalItems, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\nwatch(slotItemRegistry, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\n// ── Styles / context ───────────────────────────────────────────────────────\n\nconst slotFns = computed(() =>\n autocompleteVariants({\n variant: props.variant,\n size: props.size,\n color: props.color,\n fullWidth: props.fullWidth,\n isInvalid: props.isInvalid,\n isDisabled: props.isDisabled,\n isReadonly: isReadOnly.value,\n hasLabel: hasLabel.value,\n labelPlacement: props.labelPlacement,\n }),\n)\n\nuseAutocompleteProvide({\n isDisabled: toRef(props, 'isDisabled'),\n isInvalid: toRef(props, 'isInvalid'),\n isReadonly: isReadOnly,\n isRequired: toRef(props, 'isRequired'),\n isLoading,\n isFilled,\n fullWidth: toRef(props, 'fullWidth'),\n hasLabel,\n labelPlacement: toRef(props, 'labelPlacement'),\n inputId,\n label: toRef(props, 'label'),\n ariaDescribedBy,\n truncateItems: toRef(props, 'truncateItems'),\n hasItems,\n slots: slotFns,\n multiple: toRef(props, 'multiple'),\n multipleOverflow: toRef(props, 'multipleOverflow'),\n selectedValues,\n selectedLabels,\n onMultipleSelect,\n removeValue,\n clearAll,\n isSelected,\n registerItem,\n unregisterItem,\n searchTerm,\n hasExactMatch,\n onCreateValue,\n})\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n v-bind=\"rootDataAttrs\"\n >\n <FieldLabel\n v-if=\"showOutsideLabel\"\n :for=\"inputId\"\n :label=\"label\"\n :is-required=\"isRequired\"\n :class=\"composeClassName(slotFns.label(), props.classNames?.label)\"\n />\n\n <div :class=\"composeClassName(slotFns.mainWrapper(), props.classNames?.mainWrapper)\">\n <AutocompleteRoot\n v-model:model-value=\"searchTerm\"\n :open=\"props.multiple ? internalOpen : singleOpen\"\n :disabled=\"props.isDisabled\"\n :required=\"props.isRequired\"\n :name=\"props.name\"\n :dir=\"props.dir\"\n :ignore-filter=\"effectiveIgnoreFilter\"\n :open-on-focus=\"props.openOnFocus ?? true\"\n :open-on-click=\"props.openOnClick\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :reset-search-term-on-blur=\"props.resetSearchTermOnBlur\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n @update:open=\"handleOpenChange\"\n @highlight=\"emit('highlight', $event)\"\n >\n <slot\n v-if=\"usesCustomChrome\"\n :is-loading=\"isLoading\"\n :items=\"internalItems\"\n />\n <template v-else>\n <AutocompleteInput\n :placeholder=\"props.placeholder\"\n :class-names=\"{\n chip: props.classNames?.chip,\n trigger: props.classNames?.trigger,\n label: props.classNames?.label,\n startContent: props.classNames?.startContent,\n input: props.classNames?.input,\n clearButton: props.classNames?.clearButton,\n indicator: props.classNames?.triggerIndicator,\n }\"\n />\n <AutocompleteContent>\n <AutocompleteItem\n v-for=\"item in internalItems\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.isDisabled\"\n :class-names=\"{ item: props.classNames?.item, text: props.classNames?.text, indicator: props.classNames?.indicator }\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n >{{ item.label ?? item.textValue ?? item.value }}</slot>\n </AutocompleteItem>\n </AutocompleteContent>\n </template>\n </AutocompleteRoot>\n\n <FormFieldHelper\n :has-helper=\"hasHelper\"\n :show-error=\"showError\"\n :show-description=\"showDescription\"\n :error-message=\"errorMessage\"\n :description=\"description\"\n :error-message-id=\"errorMessageId\"\n :description-id=\"descriptionId\"\n :wrapper-class=\"composeClassName(slotFns.helperWrapper(), props.classNames?.helperWrapper)\"\n :error-class=\"composeClassName(slotFns.errorMessage(), props.classNames?.errorMessage)\"\n :description-class=\"composeClassName(slotFns.description(), props.classNames?.description)\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -373,16 +373,36 @@ var Autocomplete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
373
373
  key: 0,
374
374
  isLoading: isLoading.value,
375
375
  items: internalItems.value
376
- }) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createVNode(AutocompleteInput_default, { placeholder: props.placeholder }, null, 8, ["placeholder"]), createVNode(AutocompleteContent_default, null, {
376
+ }) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createVNode(AutocompleteInput_default, {
377
+ placeholder: props.placeholder,
378
+ "class-names": {
379
+ chip: props.classNames?.chip,
380
+ trigger: props.classNames?.trigger,
381
+ label: props.classNames?.label,
382
+ startContent: props.classNames?.startContent,
383
+ input: props.classNames?.input,
384
+ clearButton: props.classNames?.clearButton,
385
+ indicator: props.classNames?.triggerIndicator
386
+ }
387
+ }, null, 8, ["placeholder", "class-names"]), createVNode(AutocompleteContent_default, null, {
377
388
  default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(internalItems.value, (item) => {
378
389
  return openBlock(), createBlock(AutocompleteItem_default, {
379
390
  key: item.value,
380
391
  value: item.value,
381
- "is-disabled": item.isDisabled
392
+ "is-disabled": item.isDisabled,
393
+ "class-names": {
394
+ item: props.classNames?.item,
395
+ text: props.classNames?.text,
396
+ indicator: props.classNames?.indicator
397
+ }
382
398
  }, {
383
399
  default: withCtx(() => [renderSlot(_ctx.$slots, "item", { item }, () => [createTextVNode(toDisplayString(item.label ?? item.textValue ?? item.value), 1)])]),
384
400
  _: 2
385
- }, 1032, ["value", "is-disabled"]);
401
+ }, 1032, [
402
+ "value",
403
+ "is-disabled",
404
+ "class-names"
405
+ ]);
386
406
  }), 128))]),
387
407
  _: 3
388
408
  })], 64))]),
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/autocomplete/Autocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, toRef, useAttrs, useId, watch, useSlots, type ComputedRef } from 'vue'\nimport { AutocompleteRoot } from 'reka-ui'\nimport { autocompleteVariants, type AutocompleteVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useAutocompleteProvide } from './Autocomplete.context'\nimport { hasSlotComponent } from '../../utils/hasSlotComponent'\nimport AutocompleteInput from './AutocompleteInput.vue'\nimport AutocompleteContent from './AutocompleteContent.vue'\nimport AutocompleteItem from './AutocompleteItem.vue'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useFormField } from '../../composables/useFormField'\nimport FieldLabel from '../_shared/FieldLabel.vue'\nimport FormFieldHelper from '../_shared/FormFieldHelper.vue'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<Props>(), {\n variant: 'flat',\n size: 'md',\n color: 'default',\n labelPlacement: 'inside',\n fullWidth: false,\n isInvalid: false,\n isDisabled: false,\n isReadOnly: undefined,\n isReadonly: undefined,\n isRequired: false,\n multiple: false,\n multipleOverflow: 'wrap',\n modelValue: undefined,\n defaultValue: undefined,\n open: undefined,\n defaultOpen: undefined,\n items: () => [],\n loadItems: undefined,\n debounceMs: 200,\n filterOnOpen: false,\n truncateItems: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[]]\n 'update:open': [value: boolean]\n /** Fired when the user creates a new value via `creatable` or `<AutocompleteCreateItem>`. */\n 'create': [value: string]\n /** Fired when an item is highlighted. */\n 'highlight': [context: { ref: Element; value: string } | undefined]\n}>()\n\nconst isReadOnly = useDeprecatedBooleanProp(\n 'Autocomplete', 'isReadOnly', () => props.isReadOnly, 'isReadonly', () => props.isReadonly,\n)\n\nexport interface AutocompleteItem {\n value: string\n label?: string\n textValue?: string\n isDisabled?: boolean\n}\n\ntype Props = {\n /** Visual style of the field. @default 'flat' */\n variant?: AutocompleteVariants['variant']\n /** Field height. @default 'md' */\n size?: AutocompleteVariants['size']\n /** Accent color applied to focus ring + floating label. @default 'default' */\n color?: AutocompleteVariants['color']\n /**\n * Where the `label` is rendered relative to the field.\n * - `inside`: floats above the trigger (shrinks when focused/filled)\n * - `outside`: sits above the field, static\n * - `outside-left`: sits to the left, horizontal layout\n * @default 'inside'\n */\n labelPlacement?: AutocompleteVariants['labelPlacement']\n /** Stretches root wrapper to 100% width. @default false */\n fullWidth?: boolean\n /** Marks the field as invalid. Triggers danger styling and enables `errorMessage`. @default false */\n isInvalid?: boolean\n /** Disables the field. @default false */\n isDisabled?: boolean\n /** Makes the field read-only. @default false */\n isReadOnly?: boolean\n /** @deprecated Use isReadOnly instead. */\n isReadonly?: boolean\n /** Adds a required asterisk next to the label. @default false */\n isRequired?: boolean\n /** Placeholder shown when empty. */\n placeholder?: string\n /** Form field name, for native form submission. */\n name?: string\n /** Field label. When omitted, the floating-label behavior is skipped. */\n label?: string\n /** Helper text displayed below the field. Suppressed when `isInvalid && errorMessage` is shown. */\n description?: string\n /** Error text displayed below the field. Only rendered when `isInvalid` is also true. */\n errorMessage?: string\n /** Extra classes merged onto the root wrapper via `composeClassName`. */\n class?: ClassValue\n /** Per-slot class overrides. Keys correspond to internal slot names (`base`, `label`, `mainWrapper`, `helperWrapper`, `errorMessage`, `description`). */\n classNames?: Partial<{\n base: ClassValue\n label: ClassValue\n mainWrapper: ClassValue\n helperWrapper: ClassValue\n errorMessage: ClassValue\n description: ClassValue\n }>\n\n /* ─── Reka AutocompleteRoot pass-through props ───────────────────── */\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Reset the search term when the trigger loses focus. */\n resetSearchTermOnBlur?: boolean\n /** Open the dropdown when the input gains focus. */\n openOnFocus?: boolean\n /** Open the dropdown when the input is clicked. */\n openOnClick?: boolean\n /** Disable Reka's built-in filter; handle filtering externally. */\n ignoreFilter?: boolean\n /** Highlight the matching item on hover. */\n highlightOnHover?: boolean\n /** Render as a different element or component. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n\n /* ─── Autocomplete-specific ─────────────────────────────────────── */\n /** Two-way bound selected value. string in single mode, string[] in multiple mode. */\n modelValue?: string | string[]\n /** Initial selected value (uncontrolled). */\n defaultValue?: string | string[]\n /** Allow selecting multiple values. modelValue becomes string[]. @default false */\n multiple?: boolean\n /**\n * Controls how chips overflow in multiple mode.\n * - `wrap`: trigger grows in height, chips wrap to new lines (default)\n * - `collapse`: fixed height, overflowing chips are hidden behind \"+N more\"\n * @default 'wrap'\n */\n multipleOverflow?: 'wrap' | 'collapse'\n /** Controls open state of the dropdown. */\n open?: boolean\n /** Initial open state of the dropdown (uncontrolled). */\n defaultOpen?: boolean\n /** Static items list — used when no loadItems is provided. */\n items?: AutocompleteItem[]\n /** Async data source: called on every query change. */\n loadItems?: (query: string) => Promise<AutocompleteItem[]>\n /** Debounce delay for loadItems calls (ms). 0 = no debounce. */\n debounceMs?: number\n /** Apply filter immediately on open (default: false — show all items until user types). */\n filterOnOpen?: boolean\n /**\n * Truncate item text with an ellipsis when it overflows the dropdown width.\n * Set to `false` to show full text — the dropdown will widen to fit.\n * @default true\n */\n truncateItems?: boolean\n}\n\nconst attrs = useAttrs()\nconst generatedId = useId()\nconst inputId = computed(() => (attrs.id as string | undefined) ?? generatedId)\n\nconst {\n descriptionId,\n errorMessageId,\n showError,\n showDescription,\n hasHelper,\n ariaDescribedBy,\n hasLabel,\n showOutsideLabel,\n rootDataAttrs,\n} = useFormField({\n fieldId: () => inputId.value,\n label: () => props.label,\n description: () => props.description,\n errorMessage: () => props.errorMessage,\n isInvalid: () => props.isInvalid,\n isDisabled: () => props.isDisabled,\n isReadOnly: () => isReadOnly.value,\n isRequired: () => props.isRequired,\n labelPlacement: () => props.labelPlacement,\n})\n\nconst slots = useSlots()\n// Compound chrome present → pass slot through (advanced). Otherwise render the\n// input/content/items internally (short-form).\nconst usesCustomChrome: ComputedRef<boolean> = computed(() =>\n hasSlotComponent(slots.default?.({ isLoading: false, items: [] }), [AutocompleteInput, AutocompleteContent]),\n)\n\n// Registry for slot-rendered items: value → label (populated by AutocompleteItem at mount).\n// Replaced with a new Map instance on each mutation so Vue's ref() reactivity tracks changes.\nconst slotItemRegistry = ref(new Map<string, string>())\n\nfunction registerItem(value: string, label: string) {\n const next = new Map(slotItemRegistry.value)\n next.set(value, label)\n slotItemRegistry.value = next\n}\n\nfunction unregisterItem(value: string) {\n const next = new Map(slotItemRegistry.value)\n next.delete(value)\n slotItemRegistry.value = next\n}\n\n// Internal async state\nconst isLoading = ref(false)\nconst internalItems = ref<AutocompleteItem[]>([...props.items])\n\n// ── Multiple-mode state ────────────────────────────────────────────────────\n// Tracks selected values as an array. Only meaningful when props.multiple=true.\nconst selectedValues = ref<string[]>(\n props.multiple && Array.isArray(props.modelValue) ? [...props.modelValue] : [],\n)\n\n// Controlled open state used in multiple mode to prevent the dropdown closing\n// after each item selection (Reka would normally close on selection).\nconst internalOpen = ref(props.defaultOpen ?? false)\n\n// Flag set by onMultipleSelect so handleOpenChange can distinguish item\n// selection from Escape/outside-click close.\nlet selectingItem = false\n\n// ── Open-state tracking ────────────────────────────────────────────────────\nconst isOpen = ref(props.defaultOpen ?? false)\nconst termAtOpen = ref('')\nconst isUserTyping = ref(false)\n// Controlled open state for single mode (mirrors multiple mode's internalOpen).\n// Driving open ourselves lets handleOpenChange gate spurious reopens — e.g. the\n// focus bounce caused when a create handler mutates the items list.\nconst singleOpen = ref(props.open ?? props.defaultOpen ?? false)\n// When true, handleOpenChange ignores open=true requests. Set briefly after a\n// single-mode create so the post-create re-render can't reopen the menu.\nlet blockReopen = false\nlet blockReopenTimer: ReturnType<typeof setTimeout> | undefined\nconst effectiveIgnoreFilter = computed(() => {\n if (props.loadItems) return true\n if (!props.filterOnOpen && isOpen.value && !isUserTyping.value) return true\n return false\n})\n\n// ── Label/value bridge ─────────────────────────────────────────────────────\n// Priority: items prop entry > slot registry > identity fallback\nfunction labelFor(value: string | undefined): string {\n if (value == null || value === '') return ''\n const match = internalItems.value.find((i) => i.value === value)\n if (match) return match.label ?? match.textValue ?? value\n return slotItemRegistry.value.get(value) ?? value\n}\nfunction valueFor(displayed: string): string {\n if (!displayed) return ''\n const match = internalItems.value.find(\n (i) => (i.label ?? i.textValue ?? i.value) === displayed,\n )\n if (match) return match.value\n for (const [value, label] of slotItemRegistry.value) {\n if (label === displayed) return value\n }\n return displayed\n}\n\nconst singleModelValue = computed(() =>\n props.multiple ? undefined : (props.modelValue as string | undefined),\n)\n\nconst searchTerm = ref(labelFor(singleModelValue.value))\n\nconst isFilled = computed(() =>\n props.multiple\n ? selectedValues.value.length > 0 || !!searchTerm.value\n : !!searchTerm.value,\n)\nconst hasItems = computed(() => internalItems.value.length > 0)\n\nconst selectedLabels = computed(() =>\n selectedValues.value.map(v => ({ value: v, label: labelFor(v) || v })),\n)\n\n// ── Watchers ───────────────────────────────────────────────────────────────\n\n// Parent → internal: sync controlled modelValue into local state\nwatch(() => props.modelValue, (val) => {\n if (props.multiple) {\n if (Array.isArray(val)) selectedValues.value = [...val]\n } else {\n const next = labelFor(val as string | undefined)\n if (searchTerm.value !== next) searchTerm.value = next\n }\n})\n\n// Parent → internal: sync consumer-controlled open into our single-mode state\nwatch(() => props.open, (val) => {\n if (!props.multiple && val !== undefined) singleOpen.value = val\n})\n\n// Internal → parent: single mode only — multiple mode emits inside onMultipleSelect\nwatch(searchTerm, (displayed) => {\n if (props.multiple) {\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n return\n }\n const next = valueFor(displayed)\n if (next !== (singleModelValue.value ?? '')) emit('update:modelValue', next)\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n})\n\nfunction handleOpenChange(val: boolean) {\n if (props.multiple) {\n isOpen.value = val\n // Suppress close when triggered by item selection; allow Escape/outside-click\n internalOpen.value = (!val && selectingItem) ? true : val\n selectingItem = false\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n return\n }\n\n // Single mode: ignore spurious reopen requests right after a create — the\n // create handler's re-render bounces focus back to the input, which would\n // otherwise reopen the menu via openOnFocus.\n if (val && blockReopen) return\n\n isOpen.value = val\n singleOpen.value = val\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n}\n\n// ── Multiple-mode actions ──────────────────────────────────────────────────\n\nfunction onMultipleSelect(value: string) {\n selectingItem = true\n const idx = selectedValues.value.indexOf(value)\n selectedValues.value = idx === -1\n ? [...selectedValues.value, value]\n : selectedValues.value.filter((_, i) => i !== idx)\n // Clear the input and drop out of \"typing\" mode so the filter is ignored and\n // the full list shows again (effectiveIgnoreFilter depends on !isUserTyping).\n searchTerm.value = ''\n isUserTyping.value = false\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction removeValue(value: string) {\n selectedValues.value = selectedValues.value.filter(v => v !== value)\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction clearAll() {\n selectedValues.value = []\n emit('update:modelValue', [])\n}\n\nfunction isSelected(value: string): boolean {\n return selectedValues.value.includes(value)\n}\n\n// ── Creatable ──────────────────────────────────────────────────────────────\n\nconst hasExactMatch = computed(() => {\n const term = searchTerm.value.trim().toLowerCase()\n if (!term) return false\n const inItems = internalItems.value.some(\n i => (i.label ?? i.textValue ?? i.value).toLowerCase() === term,\n )\n if (inItems) return true\n for (const label of slotItemRegistry.value.values()) {\n if (label.toLowerCase() === term) return true\n }\n return false\n})\n\nfunction onCreateValue(value: string) {\n const trimmed = value.trim()\n if (!trimmed) return\n if (props.multiple) {\n // We own selection state; add the value, then reset input + filter for the\n // next entry (dropdown is kept open and refocused by AutocompleteCreateItem).\n if (!selectedValues.value.includes(trimmed)) {\n selectingItem = true\n selectedValues.value = [...selectedValues.value, trimmed]\n emit('update:modelValue', selectedValues.value)\n }\n searchTerm.value = ''\n isUserTyping.value = false\n } else {\n // Single mode: set the value ourselves and close the (controlled) dropdown.\n searchTerm.value = trimmed\n emit('update:modelValue', trimmed)\n isOpen.value = false\n singleOpen.value = false\n // The create handler (parent @create) typically mutates the items list, which\n // re-renders and bounces focus back to the input — that fires openOnFocus and\n // would reopen the menu. Block reopen requests briefly so the close sticks.\n blockReopen = true\n clearTimeout(blockReopenTimer)\n blockReopenTimer = setTimeout(() => { blockReopen = false }, 300)\n }\n emit('create', trimmed)\n}\n\n// ── Async loading ──────────────────────────────────────────────────────────\nlet debounceTimer: ReturnType<typeof setTimeout> | undefined\n\nasync function runLoadItems(query: string) {\n if (!props.loadItems) return\n isLoading.value = true\n try {\n internalItems.value = await props.loadItems(query)\n } finally {\n isLoading.value = false\n }\n}\n\nfunction scheduleLoad(query: string) {\n if (!props.loadItems) return\n clearTimeout(debounceTimer)\n if (props.debounceMs === 0) {\n void runLoadItems(query)\n } else {\n debounceTimer = setTimeout(() => void runLoadItems(query), props.debounceMs)\n }\n}\n\nonMounted(() => {\n if (props.loadItems) void runLoadItems(searchTerm.value)\n})\n\nwatch(searchTerm, (q) => {\n if (props.loadItems) scheduleLoad(q)\n})\n\nwatch(() => props.items, (newItems) => {\n if (!props.loadItems) internalItems.value = [...newItems]\n})\n\nwatch(internalItems, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\nwatch(slotItemRegistry, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\n// ── Styles / context ───────────────────────────────────────────────────────\n\nconst slotFns = computed(() =>\n autocompleteVariants({\n variant: props.variant,\n size: props.size,\n color: props.color,\n fullWidth: props.fullWidth,\n isInvalid: props.isInvalid,\n isDisabled: props.isDisabled,\n isReadonly: isReadOnly.value,\n hasLabel: hasLabel.value,\n labelPlacement: props.labelPlacement,\n }),\n)\n\nuseAutocompleteProvide({\n isDisabled: toRef(props, 'isDisabled'),\n isInvalid: toRef(props, 'isInvalid'),\n isReadonly: isReadOnly,\n isRequired: toRef(props, 'isRequired'),\n isLoading,\n isFilled,\n fullWidth: toRef(props, 'fullWidth'),\n hasLabel,\n labelPlacement: toRef(props, 'labelPlacement'),\n inputId,\n label: toRef(props, 'label'),\n ariaDescribedBy,\n truncateItems: toRef(props, 'truncateItems'),\n hasItems,\n slots: slotFns,\n multiple: toRef(props, 'multiple'),\n multipleOverflow: toRef(props, 'multipleOverflow'),\n selectedValues,\n selectedLabels,\n onMultipleSelect,\n removeValue,\n clearAll,\n isSelected,\n registerItem,\n unregisterItem,\n searchTerm,\n hasExactMatch,\n onCreateValue,\n})\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n v-bind=\"rootDataAttrs\"\n >\n <FieldLabel\n v-if=\"showOutsideLabel\"\n :for=\"inputId\"\n :label=\"label\"\n :is-required=\"isRequired\"\n :class=\"composeClassName(slotFns.label(), props.classNames?.label)\"\n />\n\n <div :class=\"composeClassName(slotFns.mainWrapper(), props.classNames?.mainWrapper)\">\n <AutocompleteRoot\n v-model:model-value=\"searchTerm\"\n :open=\"props.multiple ? internalOpen : singleOpen\"\n :disabled=\"props.isDisabled\"\n :required=\"props.isRequired\"\n :name=\"props.name\"\n :dir=\"props.dir\"\n :ignore-filter=\"effectiveIgnoreFilter\"\n :open-on-focus=\"props.openOnFocus ?? true\"\n :open-on-click=\"props.openOnClick\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :reset-search-term-on-blur=\"props.resetSearchTermOnBlur\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n @update:open=\"handleOpenChange\"\n @highlight=\"emit('highlight', $event)\"\n >\n <slot\n v-if=\"usesCustomChrome\"\n :is-loading=\"isLoading\"\n :items=\"internalItems\"\n />\n <template v-else>\n <AutocompleteInput :placeholder=\"props.placeholder\" />\n <AutocompleteContent>\n <AutocompleteItem\n v-for=\"item in internalItems\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.isDisabled\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n >{{ item.label ?? item.textValue ?? item.value }}</slot>\n </AutocompleteItem>\n </AutocompleteContent>\n </template>\n </AutocompleteRoot>\n\n <FormFieldHelper\n :has-helper=\"hasHelper\"\n :show-error=\"showError\"\n :show-description=\"showDescription\"\n :error-message=\"errorMessage\"\n :description=\"description\"\n :error-message-id=\"errorMessageId\"\n :description-id=\"descriptionId\"\n :wrapper-class=\"composeClassName(slotFns.helperWrapper(), props.classNames?.helperWrapper)\"\n :error-class=\"composeClassName(slotFns.errorMessage(), props.classNames?.errorMessage)\"\n :description-class=\"composeClassName(slotFns.description(), props.classNames?.description)\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"Autocomplete.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/autocomplete/Autocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, toRef, useAttrs, useId, watch, useSlots, type ComputedRef } from 'vue'\nimport { AutocompleteRoot } from 'reka-ui'\nimport { autocompleteVariants, type AutocompleteVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useAutocompleteProvide } from './Autocomplete.context'\nimport { hasSlotComponent } from '../../utils/hasSlotComponent'\nimport AutocompleteInput from './AutocompleteInput.vue'\nimport AutocompleteContent from './AutocompleteContent.vue'\nimport AutocompleteItem from './AutocompleteItem.vue'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\nimport { useFormField } from '../../composables/useFormField'\nimport FieldLabel from '../_shared/FieldLabel.vue'\nimport FormFieldHelper from '../_shared/FormFieldHelper.vue'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<Props>(), {\n variant: 'flat',\n size: 'md',\n color: 'default',\n labelPlacement: 'inside',\n fullWidth: false,\n isInvalid: false,\n isDisabled: false,\n isReadOnly: undefined,\n isReadonly: undefined,\n isRequired: false,\n multiple: false,\n multipleOverflow: 'wrap',\n modelValue: undefined,\n defaultValue: undefined,\n open: undefined,\n defaultOpen: undefined,\n items: () => [],\n loadItems: undefined,\n debounceMs: 200,\n filterOnOpen: false,\n truncateItems: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[]]\n 'update:open': [value: boolean]\n /** Fired when the user creates a new value via `creatable` or `<AutocompleteCreateItem>`. */\n 'create': [value: string]\n /** Fired when an item is highlighted. */\n 'highlight': [context: { ref: Element; value: string } | undefined]\n}>()\n\nconst isReadOnly = useDeprecatedBooleanProp(\n 'Autocomplete', 'isReadOnly', () => props.isReadOnly, 'isReadonly', () => props.isReadonly,\n)\n\nexport interface AutocompleteItem {\n value: string\n label?: string\n textValue?: string\n isDisabled?: boolean\n}\n\ntype Props = {\n /** Visual style of the field. @default 'flat' */\n variant?: AutocompleteVariants['variant']\n /** Field height. @default 'md' */\n size?: AutocompleteVariants['size']\n /** Accent color applied to focus ring + floating label. @default 'default' */\n color?: AutocompleteVariants['color']\n /**\n * Where the `label` is rendered relative to the field.\n * - `inside`: floats above the trigger (shrinks when focused/filled)\n * - `outside`: sits above the field, static\n * - `outside-left`: sits to the left, horizontal layout\n * @default 'inside'\n */\n labelPlacement?: AutocompleteVariants['labelPlacement']\n /** Stretches root wrapper to 100% width. @default false */\n fullWidth?: boolean\n /** Marks the field as invalid. Triggers danger styling and enables `errorMessage`. @default false */\n isInvalid?: boolean\n /** Disables the field. @default false */\n isDisabled?: boolean\n /** Makes the field read-only. @default false */\n isReadOnly?: boolean\n /** @deprecated Use isReadOnly instead. */\n isReadonly?: boolean\n /** Adds a required asterisk next to the label. @default false */\n isRequired?: boolean\n /** Placeholder shown when empty. */\n placeholder?: string\n /** Form field name, for native form submission. */\n name?: string\n /** Field label. When omitted, the floating-label behavior is skipped. */\n label?: string\n /** Helper text displayed below the field. Suppressed when `isInvalid && errorMessage` is shown. */\n description?: string\n /** Error text displayed below the field. Only rendered when `isInvalid` is also true. */\n errorMessage?: string\n /** Extra classes merged onto the root wrapper via `composeClassName`. */\n class?: ClassValue\n /** Per-slot class overrides. Keys correspond to internal slot names (`base`, `label`, `mainWrapper`, `helperWrapper`, `errorMessage`, `description`). */\n classNames?: Partial<{\n base: ClassValue\n label: ClassValue\n mainWrapper: ClassValue\n helperWrapper: ClassValue\n errorMessage: ClassValue\n description: ClassValue\n item: ClassValue\n text: ClassValue\n indicator: ClassValue\n trigger: ClassValue\n startContent: ClassValue\n input: ClassValue\n clearButton: ClassValue\n /** The loading-spinner/chevron indicator inside the input (distinct from `indicator`, which styles each item's checkmark). */\n triggerIndicator: ClassValue\n chip: Partial<{\n base: ClassValue\n dot: ClassValue\n startContent: ClassValue\n label: ClassValue\n endContent: ClassValue\n closeButton: ClassValue\n }>\n }>\n\n /* ─── Reka AutocompleteRoot pass-through props ───────────────────── */\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Reset the search term when the trigger loses focus. */\n resetSearchTermOnBlur?: boolean\n /** Open the dropdown when the input gains focus. */\n openOnFocus?: boolean\n /** Open the dropdown when the input is clicked. */\n openOnClick?: boolean\n /** Disable Reka's built-in filter; handle filtering externally. */\n ignoreFilter?: boolean\n /** Highlight the matching item on hover. */\n highlightOnHover?: boolean\n /** Render as a different element or component. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n\n /* ─── Autocomplete-specific ─────────────────────────────────────── */\n /** Two-way bound selected value. string in single mode, string[] in multiple mode. */\n modelValue?: string | string[]\n /** Initial selected value (uncontrolled). */\n defaultValue?: string | string[]\n /** Allow selecting multiple values. modelValue becomes string[]. @default false */\n multiple?: boolean\n /**\n * Controls how chips overflow in multiple mode.\n * - `wrap`: trigger grows in height, chips wrap to new lines (default)\n * - `collapse`: fixed height, overflowing chips are hidden behind \"+N more\"\n * @default 'wrap'\n */\n multipleOverflow?: 'wrap' | 'collapse'\n /** Controls open state of the dropdown. */\n open?: boolean\n /** Initial open state of the dropdown (uncontrolled). */\n defaultOpen?: boolean\n /** Static items list — used when no loadItems is provided. */\n items?: AutocompleteItem[]\n /** Async data source: called on every query change. */\n loadItems?: (query: string) => Promise<AutocompleteItem[]>\n /** Debounce delay for loadItems calls (ms). 0 = no debounce. */\n debounceMs?: number\n /** Apply filter immediately on open (default: false — show all items until user types). */\n filterOnOpen?: boolean\n /**\n * Truncate item text with an ellipsis when it overflows the dropdown width.\n * Set to `false` to show full text — the dropdown will widen to fit.\n * @default true\n */\n truncateItems?: boolean\n}\n\nconst attrs = useAttrs()\nconst generatedId = useId()\nconst inputId = computed(() => (attrs.id as string | undefined) ?? generatedId)\n\nconst {\n descriptionId,\n errorMessageId,\n showError,\n showDescription,\n hasHelper,\n ariaDescribedBy,\n hasLabel,\n showOutsideLabel,\n rootDataAttrs,\n} = useFormField({\n fieldId: () => inputId.value,\n label: () => props.label,\n description: () => props.description,\n errorMessage: () => props.errorMessage,\n isInvalid: () => props.isInvalid,\n isDisabled: () => props.isDisabled,\n isReadOnly: () => isReadOnly.value,\n isRequired: () => props.isRequired,\n labelPlacement: () => props.labelPlacement,\n})\n\nconst slots = useSlots()\n// Compound chrome present → pass slot through (advanced). Otherwise render the\n// input/content/items internally (short-form).\nconst usesCustomChrome: ComputedRef<boolean> = computed(() =>\n hasSlotComponent(slots.default?.({ isLoading: false, items: [] }), [AutocompleteInput, AutocompleteContent]),\n)\n\n// Registry for slot-rendered items: value → label (populated by AutocompleteItem at mount).\n// Replaced with a new Map instance on each mutation so Vue's ref() reactivity tracks changes.\nconst slotItemRegistry = ref(new Map<string, string>())\n\nfunction registerItem(value: string, label: string) {\n const next = new Map(slotItemRegistry.value)\n next.set(value, label)\n slotItemRegistry.value = next\n}\n\nfunction unregisterItem(value: string) {\n const next = new Map(slotItemRegistry.value)\n next.delete(value)\n slotItemRegistry.value = next\n}\n\n// Internal async state\nconst isLoading = ref(false)\nconst internalItems = ref<AutocompleteItem[]>([...props.items])\n\n// ── Multiple-mode state ────────────────────────────────────────────────────\n// Tracks selected values as an array. Only meaningful when props.multiple=true.\nconst selectedValues = ref<string[]>(\n props.multiple && Array.isArray(props.modelValue) ? [...props.modelValue] : [],\n)\n\n// Controlled open state used in multiple mode to prevent the dropdown closing\n// after each item selection (Reka would normally close on selection).\nconst internalOpen = ref(props.defaultOpen ?? false)\n\n// Flag set by onMultipleSelect so handleOpenChange can distinguish item\n// selection from Escape/outside-click close.\nlet selectingItem = false\n\n// ── Open-state tracking ────────────────────────────────────────────────────\nconst isOpen = ref(props.defaultOpen ?? false)\nconst termAtOpen = ref('')\nconst isUserTyping = ref(false)\n// Controlled open state for single mode (mirrors multiple mode's internalOpen).\n// Driving open ourselves lets handleOpenChange gate spurious reopens — e.g. the\n// focus bounce caused when a create handler mutates the items list.\nconst singleOpen = ref(props.open ?? props.defaultOpen ?? false)\n// When true, handleOpenChange ignores open=true requests. Set briefly after a\n// single-mode create so the post-create re-render can't reopen the menu.\nlet blockReopen = false\nlet blockReopenTimer: ReturnType<typeof setTimeout> | undefined\nconst effectiveIgnoreFilter = computed(() => {\n if (props.loadItems) return true\n if (!props.filterOnOpen && isOpen.value && !isUserTyping.value) return true\n return false\n})\n\n// ── Label/value bridge ─────────────────────────────────────────────────────\n// Priority: items prop entry > slot registry > identity fallback\nfunction labelFor(value: string | undefined): string {\n if (value == null || value === '') return ''\n const match = internalItems.value.find((i) => i.value === value)\n if (match) return match.label ?? match.textValue ?? value\n return slotItemRegistry.value.get(value) ?? value\n}\nfunction valueFor(displayed: string): string {\n if (!displayed) return ''\n const match = internalItems.value.find(\n (i) => (i.label ?? i.textValue ?? i.value) === displayed,\n )\n if (match) return match.value\n for (const [value, label] of slotItemRegistry.value) {\n if (label === displayed) return value\n }\n return displayed\n}\n\nconst singleModelValue = computed(() =>\n props.multiple ? undefined : (props.modelValue as string | undefined),\n)\n\nconst searchTerm = ref(labelFor(singleModelValue.value))\n\nconst isFilled = computed(() =>\n props.multiple\n ? selectedValues.value.length > 0 || !!searchTerm.value\n : !!searchTerm.value,\n)\nconst hasItems = computed(() => internalItems.value.length > 0)\n\nconst selectedLabels = computed(() =>\n selectedValues.value.map(v => ({ value: v, label: labelFor(v) || v })),\n)\n\n// ── Watchers ───────────────────────────────────────────────────────────────\n\n// Parent → internal: sync controlled modelValue into local state\nwatch(() => props.modelValue, (val) => {\n if (props.multiple) {\n if (Array.isArray(val)) selectedValues.value = [...val]\n } else {\n const next = labelFor(val as string | undefined)\n if (searchTerm.value !== next) searchTerm.value = next\n }\n})\n\n// Parent → internal: sync consumer-controlled open into our single-mode state\nwatch(() => props.open, (val) => {\n if (!props.multiple && val !== undefined) singleOpen.value = val\n})\n\n// Internal → parent: single mode only — multiple mode emits inside onMultipleSelect\nwatch(searchTerm, (displayed) => {\n if (props.multiple) {\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n return\n }\n const next = valueFor(displayed)\n if (next !== (singleModelValue.value ?? '')) emit('update:modelValue', next)\n if (isOpen.value && displayed !== termAtOpen.value) isUserTyping.value = true\n})\n\nfunction handleOpenChange(val: boolean) {\n if (props.multiple) {\n isOpen.value = val\n // Suppress close when triggered by item selection; allow Escape/outside-click\n internalOpen.value = (!val && selectingItem) ? true : val\n selectingItem = false\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n return\n }\n\n // Single mode: ignore spurious reopen requests right after a create — the\n // create handler's re-render bounces focus back to the input, which would\n // otherwise reopen the menu via openOnFocus.\n if (val && blockReopen) return\n\n isOpen.value = val\n singleOpen.value = val\n if (val) { termAtOpen.value = searchTerm.value; isUserTyping.value = false }\n else { isUserTyping.value = false }\n emit('update:open', val)\n}\n\n// ── Multiple-mode actions ──────────────────────────────────────────────────\n\nfunction onMultipleSelect(value: string) {\n selectingItem = true\n const idx = selectedValues.value.indexOf(value)\n selectedValues.value = idx === -1\n ? [...selectedValues.value, value]\n : selectedValues.value.filter((_, i) => i !== idx)\n // Clear the input and drop out of \"typing\" mode so the filter is ignored and\n // the full list shows again (effectiveIgnoreFilter depends on !isUserTyping).\n searchTerm.value = ''\n isUserTyping.value = false\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction removeValue(value: string) {\n selectedValues.value = selectedValues.value.filter(v => v !== value)\n emit('update:modelValue', selectedValues.value)\n}\n\nfunction clearAll() {\n selectedValues.value = []\n emit('update:modelValue', [])\n}\n\nfunction isSelected(value: string): boolean {\n return selectedValues.value.includes(value)\n}\n\n// ── Creatable ──────────────────────────────────────────────────────────────\n\nconst hasExactMatch = computed(() => {\n const term = searchTerm.value.trim().toLowerCase()\n if (!term) return false\n const inItems = internalItems.value.some(\n i => (i.label ?? i.textValue ?? i.value).toLowerCase() === term,\n )\n if (inItems) return true\n for (const label of slotItemRegistry.value.values()) {\n if (label.toLowerCase() === term) return true\n }\n return false\n})\n\nfunction onCreateValue(value: string) {\n const trimmed = value.trim()\n if (!trimmed) return\n if (props.multiple) {\n // We own selection state; add the value, then reset input + filter for the\n // next entry (dropdown is kept open and refocused by AutocompleteCreateItem).\n if (!selectedValues.value.includes(trimmed)) {\n selectingItem = true\n selectedValues.value = [...selectedValues.value, trimmed]\n emit('update:modelValue', selectedValues.value)\n }\n searchTerm.value = ''\n isUserTyping.value = false\n } else {\n // Single mode: set the value ourselves and close the (controlled) dropdown.\n searchTerm.value = trimmed\n emit('update:modelValue', trimmed)\n isOpen.value = false\n singleOpen.value = false\n // The create handler (parent @create) typically mutates the items list, which\n // re-renders and bounces focus back to the input — that fires openOnFocus and\n // would reopen the menu. Block reopen requests briefly so the close sticks.\n blockReopen = true\n clearTimeout(blockReopenTimer)\n blockReopenTimer = setTimeout(() => { blockReopen = false }, 300)\n }\n emit('create', trimmed)\n}\n\n// ── Async loading ──────────────────────────────────────────────────────────\nlet debounceTimer: ReturnType<typeof setTimeout> | undefined\n\nasync function runLoadItems(query: string) {\n if (!props.loadItems) return\n isLoading.value = true\n try {\n internalItems.value = await props.loadItems(query)\n } finally {\n isLoading.value = false\n }\n}\n\nfunction scheduleLoad(query: string) {\n if (!props.loadItems) return\n clearTimeout(debounceTimer)\n if (props.debounceMs === 0) {\n void runLoadItems(query)\n } else {\n debounceTimer = setTimeout(() => void runLoadItems(query), props.debounceMs)\n }\n}\n\nonMounted(() => {\n if (props.loadItems) void runLoadItems(searchTerm.value)\n})\n\nwatch(searchTerm, (q) => {\n if (props.loadItems) scheduleLoad(q)\n})\n\nwatch(() => props.items, (newItems) => {\n if (!props.loadItems) internalItems.value = [...newItems]\n})\n\nwatch(internalItems, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\nwatch(slotItemRegistry, () => {\n if (props.multiple) return\n const next = labelFor(singleModelValue.value)\n if (next && searchTerm.value !== next && valueFor(searchTerm.value) === (singleModelValue.value ?? '')) {\n searchTerm.value = next\n }\n})\n\n// ── Styles / context ───────────────────────────────────────────────────────\n\nconst slotFns = computed(() =>\n autocompleteVariants({\n variant: props.variant,\n size: props.size,\n color: props.color,\n fullWidth: props.fullWidth,\n isInvalid: props.isInvalid,\n isDisabled: props.isDisabled,\n isReadonly: isReadOnly.value,\n hasLabel: hasLabel.value,\n labelPlacement: props.labelPlacement,\n }),\n)\n\nuseAutocompleteProvide({\n isDisabled: toRef(props, 'isDisabled'),\n isInvalid: toRef(props, 'isInvalid'),\n isReadonly: isReadOnly,\n isRequired: toRef(props, 'isRequired'),\n isLoading,\n isFilled,\n fullWidth: toRef(props, 'fullWidth'),\n hasLabel,\n labelPlacement: toRef(props, 'labelPlacement'),\n inputId,\n label: toRef(props, 'label'),\n ariaDescribedBy,\n truncateItems: toRef(props, 'truncateItems'),\n hasItems,\n slots: slotFns,\n multiple: toRef(props, 'multiple'),\n multipleOverflow: toRef(props, 'multipleOverflow'),\n selectedValues,\n selectedLabels,\n onMultipleSelect,\n removeValue,\n clearAll,\n isSelected,\n registerItem,\n unregisterItem,\n searchTerm,\n hasExactMatch,\n onCreateValue,\n})\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n v-bind=\"rootDataAttrs\"\n >\n <FieldLabel\n v-if=\"showOutsideLabel\"\n :for=\"inputId\"\n :label=\"label\"\n :is-required=\"isRequired\"\n :class=\"composeClassName(slotFns.label(), props.classNames?.label)\"\n />\n\n <div :class=\"composeClassName(slotFns.mainWrapper(), props.classNames?.mainWrapper)\">\n <AutocompleteRoot\n v-model:model-value=\"searchTerm\"\n :open=\"props.multiple ? internalOpen : singleOpen\"\n :disabled=\"props.isDisabled\"\n :required=\"props.isRequired\"\n :name=\"props.name\"\n :dir=\"props.dir\"\n :ignore-filter=\"effectiveIgnoreFilter\"\n :open-on-focus=\"props.openOnFocus ?? true\"\n :open-on-click=\"props.openOnClick\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :reset-search-term-on-blur=\"props.resetSearchTermOnBlur\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n @update:open=\"handleOpenChange\"\n @highlight=\"emit('highlight', $event)\"\n >\n <slot\n v-if=\"usesCustomChrome\"\n :is-loading=\"isLoading\"\n :items=\"internalItems\"\n />\n <template v-else>\n <AutocompleteInput\n :placeholder=\"props.placeholder\"\n :class-names=\"{\n chip: props.classNames?.chip,\n trigger: props.classNames?.trigger,\n label: props.classNames?.label,\n startContent: props.classNames?.startContent,\n input: props.classNames?.input,\n clearButton: props.classNames?.clearButton,\n indicator: props.classNames?.triggerIndicator,\n }\"\n />\n <AutocompleteContent>\n <AutocompleteItem\n v-for=\"item in internalItems\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.isDisabled\"\n :class-names=\"{ item: props.classNames?.item, text: props.classNames?.text, indicator: props.classNames?.indicator }\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n >{{ item.label ?? item.textValue ?? item.value }}</slot>\n </AutocompleteItem>\n </AutocompleteContent>\n </template>\n </AutocompleteRoot>\n\n <FormFieldHelper\n :has-helper=\"hasHelper\"\n :show-error=\"showError\"\n :show-description=\"showDescription\"\n :error-message=\"errorMessage\"\n :description=\"description\"\n :error-message-id=\"errorMessageId\"\n :description-id=\"descriptionId\"\n :wrapper-class=\"composeClassName(slotFns.helperWrapper(), props.classNames?.helperWrapper)\"\n :error-class=\"composeClassName(slotFns.errorMessage(), props.classNames?.errorMessage)\"\n :description-class=\"composeClassName(slotFns.description(), props.classNames?.description)\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AutocompleteCreateItem.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteCreateItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AutocompleteItem as RekaAutocompleteItem, injectComboboxRootContext } from 'reka-ui'\nimport { useAutocompleteInject } from './Autocomplete.context'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\n\nconst props = withDefaults(defineProps<{\n /**\n * Label for the create item. Accepts a static string or a function receiving\n * the current search term. Defaults to `Create \"${term}\"`.\n */\n label?: string | ((term: string) => string)\n class?: string\n /** The value of this item when selected. Defaults to the current search term. */\n value?: string\n /** A string value that represents this item during typeahead navigation. */\n textValue?: string\n isDisabled?: boolean\n /** Whether this item is disabled. @deprecated Use isDisabled instead. */\n disabled?: boolean\n /** Render as a different element or component. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n}>(), {\n label: undefined,\n class: undefined,\n value: undefined,\n textValue: undefined,\n isDisabled: undefined,\n disabled: undefined,\n as: undefined,\n asChild: false,\n})\n\nconst emit = defineEmits<{\n 'select': [event: Event]\n}>()\n\nconst isDisabled = useDeprecatedBooleanProp(\n 'AutocompleteCreateItem', 'isDisabled', () => props.isDisabled, 'disabled', () => props.disabled,\n)\n\nconst ctx = useAutocompleteInject()\n// Reka's combobox context (provided by AutocompleteRoot) — used to drive the\n// open state and input focus directly, since this item's value equals the\n// current search term and Reka's native select path is unreliable for it.\nconst comboboxCtx = injectComboboxRootContext()\n\nconst term = computed(() => ctx.searchTerm.value.trim())\n\nconst isVisible = computed(() => !!term.value && !ctx.hasExactMatch.value)\n\nconst displayLabel = computed(() => {\n if (typeof props.label === 'function') return props.label(term.value)\n return props.label ?? `Create \"${term.value}\"`\n})\n\nfunction handleSelect(event: Event) {\n emit('select', event)\n // Always manage the creation ourselves — this item's value equals the current\n // search term, so Reka's native select (set-value + close) is unreliable here.\n event.preventDefault()\n ctx.onCreateValue(term.value)\n if (ctx.multiple.value) {\n // Keep the dropdown open for the next entry and restore input focus.\n comboboxCtx.inputElement.value?.focus()\n } else {\n // Single mode: close the dropdown, like selecting a regular item.\n comboboxCtx.onOpenChange(false)\n }\n}\n</script>\n\n<template>\n <RekaAutocompleteItem\n v-if=\"isVisible\"\n :key=\"term\"\n :value=\"props.value ?? term\"\n :text-value=\"props.textValue ?? term\"\n :disabled=\"isDisabled\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"['list-box-item list-box-item--default', props.class]\"\n data-slot=\"list-box-item\"\n data-create-item\n @select=\"handleSelect\"\n >\n <slot :term=\"term\">\n <span\n class=\"autocomplete-item__text\"\n data-slot=\"item-text\"\n >\n {{ displayLabel }}\n </span>\n </slot>\n </RekaAutocompleteItem>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"AutocompleteCreateItem.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteCreateItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { AutocompleteItem as RekaAutocompleteItem, injectComboboxRootContext } from 'reka-ui'\nimport { listboxItemVariants, autocompleteVariants } from '@auronui/styles'\nimport { composeClassName, type ClassValue } from '../../utils/composeClassName'\nimport { useAutocompleteInject } from './Autocomplete.context'\nimport { useDeprecatedBooleanProp } from '../../composables/useDeprecatedBooleanProp'\n\nconst props = withDefaults(defineProps<{\n /**\n * Label for the create item. Accepts a static string or a function receiving\n * the current search term. Defaults to `Create \"${term}\"`.\n */\n label?: string | ((term: string) => string)\n class?: string\n /** The value of this item when selected. Defaults to the current search term. */\n value?: string\n /** A string value that represents this item during typeahead navigation. */\n textValue?: string\n isDisabled?: boolean\n /** Whether this item is disabled. @deprecated Use isDisabled instead. */\n disabled?: boolean\n /** Render as a different element or component. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n /** Per-slot class overrides */\n classNames?: Partial<{\n item: ClassValue\n text: ClassValue\n }>\n}>(), {\n label: undefined,\n class: undefined,\n value: undefined,\n textValue: undefined,\n isDisabled: undefined,\n disabled: undefined,\n as: undefined,\n asChild: false,\n})\n\nconst emit = defineEmits<{\n 'select': [event: Event]\n}>()\n\nconst isDisabled = useDeprecatedBooleanProp(\n 'AutocompleteCreateItem', 'isDisabled', () => props.isDisabled, 'disabled', () => props.disabled,\n)\n\nconst ctx = useAutocompleteInject()\n// Reka's combobox context (provided by AutocompleteRoot) — used to drive the\n// open state and input focus directly, since this item's value equals the\n// current search term and Reka's native select path is unreliable for it.\nconst comboboxCtx = injectComboboxRootContext()\n\nconst itemSlots = listboxItemVariants()\nconst itemTextClass = computed(() => autocompleteVariants().itemText())\n\nconst term = computed(() => ctx.searchTerm.value.trim())\n\nconst isVisible = computed(() => !!term.value && !ctx.hasExactMatch.value)\n\nconst displayLabel = computed(() => {\n if (typeof props.label === 'function') return props.label(term.value)\n return props.label ?? `Create \"${term.value}\"`\n})\n\nfunction handleSelect(event: Event) {\n emit('select', event)\n // Always manage the creation ourselves — this item's value equals the current\n // search term, so Reka's native select (set-value + close) is unreliable here.\n event.preventDefault()\n ctx.onCreateValue(term.value)\n if (ctx.multiple.value) {\n // Keep the dropdown open for the next entry and restore input focus.\n comboboxCtx.inputElement.value?.focus()\n } else {\n // Single mode: close the dropdown, like selecting a regular item.\n comboboxCtx.onOpenChange(false)\n }\n}\n</script>\n\n<template>\n <RekaAutocompleteItem\n v-if=\"isVisible\"\n :key=\"term\"\n :value=\"props.value ?? term\"\n :text-value=\"props.textValue ?? term\"\n :disabled=\"isDisabled\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(itemSlots.item(), props.classNames?.item, props.class)\"\n data-slot=\"list-box-item\"\n data-create-item\n @select=\"handleSelect\"\n >\n <slot :term=\"term\">\n <span\n :class=\"composeClassName(itemTextClass, props.classNames?.text)\"\n data-slot=\"item-text\"\n >\n {{ displayLabel }}\n </span>\n </slot>\n </RekaAutocompleteItem>\n</template>\n"],"mappings":""}