@auronui/vue 1.0.22 → 1.0.23

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.
@@ -1,4 +1,4 @@
1
- import { Fragment, computed, createElementBlock, defineComponent, nextTick, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString, watch } from "vue";
1
+ import { Fragment, computed, createElementBlock, defineComponent, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString } from "vue";
2
2
  //#region src/components/date-time-picker/DateTimePickerTimeScroller.vue?vue&type=script&setup=true&lang.ts
3
3
  var _hoisted_1 = ["aria-label", "onScrollPassive"];
4
4
  var _hoisted_2 = [
@@ -6,6 +6,7 @@ var _hoisted_2 = [
6
6
  "aria-selected",
7
7
  "onClick"
8
8
  ];
9
+ var REPEAT = 3;
9
10
  var ITEM_H = 40;
10
11
  var DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
11
12
  __name: "DateTimePickerTimeScroller",
@@ -28,51 +29,62 @@ var DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default = /*
28
29
  const columns = computed(() => {
29
30
  const cols = [{
30
31
  key: "hour",
31
- items: hourItems.value
32
+ items: hourItems.value,
33
+ loop: true
32
34
  }, {
33
35
  key: "minute",
34
- items: minutes
36
+ items: minutes,
37
+ loop: true
35
38
  }];
36
39
  if (props.granularity === "second") cols.push({
37
40
  key: "second",
38
- items: seconds
41
+ items: seconds,
42
+ loop: true
39
43
  });
40
44
  if (props.hourCycle === 12) cols.push({
41
45
  key: "ampm",
42
- items: ampm
46
+ items: ampm,
47
+ loop: false
43
48
  });
44
49
  return cols;
45
50
  });
46
- function currentIndexFor(key) {
47
- const v = props.modelValue;
48
- if (key === "hour") {
49
- if (props.hourCycle === 12) {
50
- const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12;
51
- return hours12.indexOf(h12);
52
- }
53
- return v.hour;
54
- }
55
- if (key === "minute") return v.minute;
56
- if (key === "second") return v.second ?? 0;
57
- if (key === "ampm") return v.hour >= 12 ? 1 : 0;
58
- return 0;
59
- }
60
51
  const columnRefs = ref([]);
61
- function scrollColumnToIndex(colEl, index) {
62
- colEl.scrollTop = index * ITEM_H;
52
+ function renderItems(col) {
53
+ if (!col.loop) return col.items;
54
+ const out = [];
55
+ for (let r = 0; r < REPEAT; r++) out.push(...col.items);
56
+ return out;
57
+ }
58
+ function cycleHeight(col) {
59
+ return col.items.length * ITEM_H;
63
60
  }
64
- function syncScrollPositions() {
61
+ function onColumnScroll(i, colEl) {
62
+ const col = columns.value[i];
63
+ if (!col.loop) return;
64
+ const cycle = cycleHeight(col);
65
+ const total = cycle * REPEAT;
66
+ const recenter = (REPEAT - 2) * cycle;
67
+ if (colEl.scrollTop < cycle) colEl.scrollTop += recenter;
68
+ else if (colEl.scrollTop >= total - cycle) colEl.scrollTop -= recenter;
69
+ }
70
+ onMounted(() => {
65
71
  columns.value.forEach((col, i) => {
66
72
  const el = columnRefs.value[i];
67
- if (el) scrollColumnToIndex(el, currentIndexFor(col.key));
73
+ if (el && col.loop) el.scrollTop = cycleHeight(col) * Math.floor(REPEAT / 2);
68
74
  });
75
+ });
76
+ function isSelected(key, item) {
77
+ const v = props.modelValue;
78
+ if (key === "hour") {
79
+ if (props.hourCycle === 12) return item === (v.hour % 12 === 0 ? 12 : v.hour % 12);
80
+ return item === v.hour;
81
+ }
82
+ if (key === "minute") return item === v.minute;
83
+ if (key === "second") return item === (v.second ?? 0);
84
+ if (key === "ampm") return item === (v.hour >= 12 ? "PM" : "AM");
85
+ return false;
69
86
  }
70
- onMounted(() => nextTick(syncScrollPositions));
71
- watch(() => props.modelValue, () => nextTick(syncScrollPositions));
72
- function onColumnScroll(key, colEl) {
73
- const idx = Math.round(colEl.scrollTop / ITEM_H);
74
- const item = columns.value.find((c) => c.key === key).items[idx];
75
- if (item === void 0) return;
87
+ function onItemClick(key, item) {
76
88
  const v = props.modelValue;
77
89
  if (key === "hour") {
78
90
  let newHour;
@@ -89,35 +101,19 @@ var DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default = /*
89
101
  if (isPm !== v.hour >= 12) emit("update:modelValue", v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }));
90
102
  }
91
103
  }
92
- function onKeyDown(e, colEl) {
93
- if (e.key === "ArrowDown") {
94
- e.preventDefault();
95
- colEl.scrollTop += ITEM_H;
96
- } else if (e.key === "ArrowUp") {
97
- e.preventDefault();
98
- colEl.scrollTop -= ITEM_H;
99
- }
100
- }
101
- function onItemClick(colEl, idx) {
102
- colEl.scrollTo({
103
- top: idx * ITEM_H,
104
- behavior: "smooth"
105
- });
106
- }
107
104
  function columnLabel(key) {
108
105
  if (key === "hour") return "Hour";
109
106
  if (key === "minute") return "Minute";
110
107
  if (key === "second") return "Second";
111
108
  return "AM/PM";
112
109
  }
113
- function itemLabel(_key, item) {
110
+ function itemLabel(item) {
114
111
  if (typeof item === "string") return item;
115
112
  return String(item).padStart(2, "0");
116
113
  }
117
114
  __expose({
118
115
  columnRefs,
119
- columns,
120
- currentIndexFor
116
+ columns
121
117
  });
122
118
  return (_ctx, _cache) => {
123
119
  return openBlock(), createElementBlock("div", {
@@ -135,17 +131,16 @@ var DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default = /*
135
131
  "data-slot": "scroller-column",
136
132
  role: "listbox",
137
133
  tabindex: "0",
138
- onScrollPassive: ($event) => onColumnScroll(col.key, $event.currentTarget),
139
- onKeydown: _cache[0] || (_cache[0] = ($event) => onKeyDown($event, $event.currentTarget))
140
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(col.items, (item, idx) => {
134
+ onScrollPassive: ($event) => onColumnScroll(i, $event.currentTarget)
135
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(renderItems(col), (item, idx) => {
141
136
  return openBlock(), createElementBlock("div", {
142
137
  key: idx,
143
138
  class: "date-time-picker__scroller-item",
144
- "data-selected": idx === currentIndexFor(col.key) ? "true" : void 0,
145
- "aria-selected": idx === currentIndexFor(col.key),
139
+ "data-selected": isSelected(col.key, item) ? "true" : void 0,
140
+ "aria-selected": isSelected(col.key, item),
146
141
  role: "option",
147
- onClick: ($event) => onItemClick(columnRefs.value[i], idx)
148
- }, toDisplayString(itemLabel(col.key, item)), 9, _hoisted_2);
142
+ onClick: ($event) => onItemClick(col.key, item)
143
+ }, toDisplayString(itemLabel(item)), 9, _hoisted_2);
149
144
  }), 128))], 40, _hoisted_1);
150
145
  }), 128))], 2);
151
146
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePickerTimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/date-time-picker/DateTimePickerTimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport { CalendarDateTime } from '@internationalized/date'\n\nconst props = withDefaults(defineProps<{\n modelValue: 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: 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\nconst columns = computed(() => {\n const cols: Array<{ key: string; items: (number | string)[] }> = [\n { key: 'hour', items: hourItems.value },\n { key: 'minute', items: minutes },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds })\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm })\n return cols\n})\n\n// ─── Current index computation ───────────────────────────────────────────\n\nfunction currentIndexFor(key: string): number {\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 hours12.indexOf(h12)\n }\n return v.hour\n }\n if (key === 'minute') return v.minute\n if (key === 'second') return v.second ?? 0\n if (key === 'ampm') return v.hour >= 12 ? 1 : 0\n return 0\n}\n\n// ─── Scroll-to-selected ──────────────────────────────────────────────────\n\nconst columnRefs = ref<HTMLElement[]>([])\n\nconst ITEM_H = 40 // 2.5rem at 16px base\n\nfunction scrollColumnToIndex(colEl: HTMLElement, index: number) {\n colEl.scrollTop = index * ITEM_H\n}\n\nfunction syncScrollPositions() {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el) scrollColumnToIndex(el, currentIndexFor(col.key))\n })\n}\n\nonMounted(() => nextTick(syncScrollPositions))\nwatch(() => props.modelValue, () => nextTick(syncScrollPositions))\n\n// ─── Scroll value update ───────────────────────────────────────────────\n\nfunction onColumnScroll(key: string, colEl: HTMLElement) {\n const idx = Math.round(colEl.scrollTop / ITEM_H)\n const col = columns.value.find(c => c.key === key)!\n const item = col.items[idx]\n if (item === undefined) return\n\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// ─── Keyboard navigation ─────────────────────────────────────────────────\n\nfunction onKeyDown(e: KeyboardEvent, colEl: HTMLElement) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n colEl.scrollTop += ITEM_H\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n colEl.scrollTop -= ITEM_H\n }\n}\n\n// ─── Click-to-select ─────────────────────────────────────────────────────\n\nfunction onItemClick(colEl: HTMLElement, idx: number) {\n colEl.scrollTo({ top: idx * ITEM_H, behavior: 'smooth' })\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(_key: string, 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, currentIndexFor })\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(col.key, ($event.currentTarget as HTMLElement))\"\n @keydown=\"onKeyDown($event, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in col.items\"\n :key=\"idx\"\n class=\"date-time-picker__scroller-item\"\n :data-selected=\"idx === currentIndexFor(col.key) ? 'true' : undefined\"\n :aria-selected=\"idx === currentIndexFor(col.key)\"\n role=\"option\"\n @click=\"onItemClick(columnRefs[i]!, idx)\"\n >\n {{ itemLabel(col.key, item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePickerTimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/date-time-picker/DateTimePickerTimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { CalendarDateTime } from '@internationalized/date'\n\nconst props = withDefaults(defineProps<{\n modelValue: 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: 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 +1 @@
1
- {"version":3,"file":"ListBox.context.js","names":[],"sources":["../../../src/components/list-box/ListBox.context.ts"],"sourcesContent":["import { createContext } from '../../utils/context'\nimport type { Ref } from 'vue'\nimport type { ListBoxVariants } from '@auronui/styles'\nimport type { ListBoxItemVariants } from '@auronui/styles'\n\nexport interface ListBoxContext {\n variant: Ref<ListBoxVariants['variant']>\n itemVariant: Ref<ListBoxItemVariants['variant']>\n isDisabled: Ref<boolean>\n}\n\nexport const {\n useProvide: useListBoxProvide,\n useInject: useListBoxInject,\n key: listBoxContextKey,\n} = createContext<ListBoxContext>('ListBox')\n"],"mappings":";;AAWA,IAAa,EACX,YAAY,mBACZ,WAAW,kBACX,KAAK,sBACH,cAA8B,UAAU"}
1
+ {"version":3,"file":"ListBox.context.js","names":[],"sources":["../../../src/components/list-box/ListBox.context.ts"],"sourcesContent":["import { createContext } from '../../utils/context'\nimport type { Ref } from 'vue'\nimport type { ListBoxVariants } from '@auronui/styles'\nimport type { ListBoxItemVariants } from '@auronui/styles'\n\nexport interface ListBoxContext {\n variant: Ref<ListBoxVariants['variant']>\n itemVariant: Ref<ListBoxItemVariants['variant']>\n isDisabled: Ref<boolean>\n hideSelectedIcon: Ref<boolean>\n}\n\nexport const {\n useProvide: useListBoxProvide,\n useInject: useListBoxInject,\n key: listBoxContextKey,\n} = createContext<ListBoxContext>('ListBox')\n"],"mappings":";;AAYA,IAAa,EACX,YAAY,mBACZ,WAAW,kBACX,KAAK,sBACH,cAA8B,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"ListBox.js","names":[],"sources":["../../../src/components/list-box/ListBox.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, toRef, useAttrs } from 'vue'\nimport { ListboxRoot, ListboxContent } from 'reka-ui'\nimport { listboxVariants, type ListBoxVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useListBoxProvide } from './ListBox.context'\nimport ListBoxItem from './ListBoxItem.vue'\n\ntype ListBoxShorthandItem = { value: string; label?: string; disabled?: boolean; textValue?: string }\n\n// Disable Vue attribute fallthrough — we manually forward ARIA attrs to ListboxContent\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n modelValue?: string | string[]\n defaultValue?: string | string[]\n selectionMode?: 'single' | 'multiple'\n variant?: ListBoxVariants['variant']\n isDisabled?: boolean\n class?: ClassValue\n /**\n * Per-slot class overrides. Each key maps to a named slot in the anatomy;\n * the value is merged with the generated variant classes via `composeClassName`.\n */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render list items from an array instead of the compound slot API */\n items?: ListBoxShorthandItem[]\n /** Allow selecting multiple values (alias for selectionMode=\"multiple\"). */\n multiple?: boolean\n /** Orientation of the listbox for keyboard navigation. */\n orientation?: 'horizontal' | 'vertical'\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Selection behavior when multiple is true. */\n selectionBehavior?: 'toggle' | 'replace'\n /** Highlight item on hover. */\n highlightOnHover?: boolean\n /** Key used to compare items for equality. */\n by?: string\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 /** Form field name for native form submission. */\n name?: string\n /** Mark the field as required. */\n required?: boolean\n /** Render the ListboxContent as a different element. */\n contentAs?: string\n /** Merge content props onto child element. */\n contentAsChild?: boolean\n}>(), {\n modelValue: undefined,\n defaultValue: undefined,\n selectionMode: 'single',\n variant: 'default',\n isDisabled: false,\n class: undefined,\n multiple: undefined,\n orientation: undefined,\n dir: undefined,\n selectionBehavior: undefined,\n highlightOnHover: undefined,\n by: undefined,\n as: undefined,\n asChild: false,\n name: undefined,\n required: undefined,\n contentAs: undefined,\n contentAsChild: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined]\n 'highlight': [context: unknown]\n 'entry-focus': [event: Event]\n 'leave': [event: Event]\n}>()\n\nconst attrs = useAttrs()\n\n// Provide context for ListBoxItem and ListBoxSection children\nuseListBoxProvide({\n variant: toRef(props, 'variant'),\n itemVariant: toRef(props, 'variant'),\n isDisabled: toRef(props, 'isDisabled'),\n})\n\nconst slotFns = computed(() =>\n listboxVariants({ variant: props.variant })\n)\n</script>\n\n<template>\n <!-- ListboxRoot is an invisible wrapper that manages state; ListboxContent carries role=\"listbox\" -->\n <!-- We forward attrs (aria-label, aria-labelledby, etc.) to ListboxContent, not the root -->\n <ListboxRoot\n :model-value=\"props.modelValue == null ? undefined : ([] as string[]).concat(props.modelValue)\"\n :default-value=\"props.defaultValue == null ? undefined : ([] as string[]).concat(props.defaultValue)\"\n :multiple=\"props.multiple ?? props.selectionMode === 'multiple'\"\n :selection-behavior=\"props.selectionBehavior ?? (props.selectionMode === 'multiple' ? 'toggle' : 'replace')\"\n :disabled=\"props.isDisabled\"\n :orientation=\"props.orientation\"\n :dir=\"props.dir\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :by=\"props.by\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :name=\"props.name\"\n :required=\"props.required\"\n @update:model-value=\"emit('update:modelValue', props.selectionMode === 'single' ? (Array.isArray($event) ? ($event as string[])[0] : $event as string) : $event as string[])\"\n @highlight=\"emit('highlight', $event)\"\n @entry-focus=\"emit('entry-focus', $event)\"\n @leave=\"emit('leave', $event)\"\n >\n <ListboxContent\n v-bind=\"attrs\"\n :as=\"props.contentAs\"\n :as-child=\"props.contentAsChild\"\n :class=\"composeClassName(slotFns, props.class, props.classNames?.base)\"\n >\n <template v-if=\"props.items\">\n <ListBoxItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :text-value=\"item.textValue\"\n >{{ item.label ?? item.value }}</ListBoxItem>\n </template>\n <slot v-else />\n </ListboxContent>\n </ListboxRoot>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ListBox.js","names":[],"sources":["../../../src/components/list-box/ListBox.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, useAttrs, useTemplateRef } from 'vue'\nimport { useInfiniteScroll } from '@vueuse/core'\nimport { ListboxRoot, ListboxContent, ListboxVirtualizer } from 'reka-ui'\nimport { listboxVariants, type ListBoxVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useListBoxProvide } from './ListBox.context'\nimport ListBoxItem from './ListBoxItem.vue'\nimport Button from '../button/Button.vue'\n\ntype ListBoxShorthandItem = { value: string; label?: string; disabled?: boolean; textValue?: string }\n\n// Disable Vue attribute fallthrough — we manually forward ARIA attrs to ListboxContent\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n modelValue?: string | string[]\n defaultValue?: string | string[]\n selectionMode?: 'single' | 'multiple'\n variant?: ListBoxVariants['variant']\n isDisabled?: boolean\n class?: ClassValue\n /**\n * Per-slot class overrides. Each key maps to a named slot in the anatomy;\n * the value is merged with the generated variant classes via `composeClassName`.\n */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render list items from an array instead of the compound slot API */\n items?: ListBoxShorthandItem[]\n /** Allow selecting multiple values (alias for selectionMode=\"multiple\"). */\n multiple?: boolean\n /** Orientation of the listbox for keyboard navigation. */\n orientation?: 'horizontal' | 'vertical'\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Selection behavior when multiple is true. */\n selectionBehavior?: 'toggle' | 'replace'\n /** Highlight item on hover. */\n highlightOnHover?: boolean\n /** Key used to compare items for equality. */\n by?: string\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 /** Form field name for native form submission. */\n name?: string\n /** Mark the field as required. */\n required?: boolean\n /** Render the ListboxContent as a different element. */\n contentAs?: string\n /** Merge content props onto child element. */\n contentAsChild?: boolean\n /** Hide the selected checkmark on all items (forwarded via context). */\n hideSelectedIcon?: boolean\n /** Enable windowed rendering (opt-in). Renders from `items`. */\n virtualized?: boolean\n /** Estimated row height in px (or per-index fn) for the virtualizer. */\n estimateSize?: number | ((index: number) => number)\n /** Rows rendered outside the visible area. */\n overscan?: number\n /** Scroll-viewport height for the content when scrolling is active. */\n maxHeight?: string | number\n /** Whether more pages remain to load (gates load-more). */\n hasMore?: boolean\n /** A page is currently loading (gates load-more; drives #loading slot). */\n isLoading?: boolean\n /** Distance in px from the bottom that triggers load-more. */\n loadMoreDistance?: number\n /** How the next page is requested: auto on scroll, or a manual button. */\n loadMode?: 'scroll' | 'button'\n /** Label for the manual load-more button (loadMode=\"button\"). */\n loadMoreLabel?: string\n}>(), {\n modelValue: undefined,\n defaultValue: undefined,\n selectionMode: 'single',\n variant: 'default',\n isDisabled: false,\n class: undefined,\n multiple: undefined,\n orientation: undefined,\n dir: undefined,\n selectionBehavior: undefined,\n highlightOnHover: undefined,\n by: undefined,\n as: undefined,\n asChild: false,\n name: undefined,\n required: undefined,\n contentAs: undefined,\n contentAsChild: false,\n hideSelectedIcon: false,\n virtualized: false,\n estimateSize: 36,\n overscan: 12,\n maxHeight: '16rem',\n hasMore: false,\n isLoading: false,\n loadMoreDistance: 120,\n loadMode: 'scroll',\n loadMoreLabel: 'Load more',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined]\n 'highlight': [context: unknown]\n 'entry-focus': [event: Event]\n 'leave': [event: Event]\n 'load-more': []\n}>()\n\nconst attrs = useAttrs()\n\n// Provide context for ListBoxItem and ListBoxSection children\nuseListBoxProvide({\n variant: toRef(props, 'variant'),\n itemVariant: toRef(props, 'variant'),\n isDisabled: toRef(props, 'isDisabled'),\n hideSelectedIcon: toRef(props, 'hideSelectedIcon'),\n})\n\nconst slotFns = computed(() =>\n listboxVariants({ variant: props.variant })\n)\n\n// Bounded scroll viewport only when the content actually needs to scroll, so\n// default (non-virtualized) ListBoxes are visually unchanged.\n// useTemplateRef on a Reka component resolves to its instance; useInfiniteScroll's\n// internal unrefElement reads `.$el` to get the scroll DOM node.\nconst contentRef = useTemplateRef<HTMLElement>('content')\n\n// Re-arm latch. useInfiniteScroll keeps re-invoking onLoadMore while the scroll\n// element stays at the bottom and canLoadMore is true. Emitting `load-more` does\n// not itself flip hasMore/isLoading, so without this guard it fires in a tight\n// loop (unbounded emits → hang). We record the item count at the moment we ask\n// for a page and refuse to ask again until the dataset actually grows — i.e.\n// until the consumer has appended the next page.\nconst lastRequestedCount = ref(-1)\nuseInfiniteScroll(\n contentRef,\n () => {\n lastRequestedCount.value = props.items?.length ?? 0\n emit('load-more')\n },\n {\n // Read once at setup: useScroll consumes `offset.bottom` as a raw number\n // (no toValue), so a getter/ref here would break arrival math. Hot-swapping\n // loadMoreDistance after mount is not supported (not a real use case).\n distance: props.loadMoreDistance,\n canLoadMore: () =>\n props.loadMode === 'scroll'\n && props.hasMore\n && !props.isLoading\n && (props.items?.length ?? 0) !== lastRequestedCount.value,\n },\n)\n\n// Manual load-more (loadMode=\"button\"). User-driven, so no re-arm latch needed —\n// the hasMore/isLoading gate is enough (and the button is disabled while loading).\nfunction requestLoadMore() {\n if (props.hasMore && !props.isLoading) emit('load-more')\n}\n\nconst needsScroll = computed(() => props.virtualized)\nconst contentStyle = computed(() =>\n needsScroll.value\n ? { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight, overflowY: 'auto' as const }\n : undefined,\n)\n\n// Stable array references for Reka. Building a fresh array inline on every render\n// would retrigger Reka's `watch(modelValue)`, which re-highlights and\n// scrollIntoView's the selected/first item — making the list jump to the top on\n// any unrelated re-render (e.g. when isLoading toggles during load-more). A\n// computed is cached, so the reference only changes when the value really does.\nconst rekaModelValue = computed(() =>\n props.modelValue == null ? undefined : ([] as string[]).concat(props.modelValue),\n)\nconst rekaDefaultValue = computed(() =>\n props.defaultValue == null ? undefined : ([] as string[]).concat(props.defaultValue),\n)\n</script>\n\n<template>\n <!-- ListboxRoot is an invisible wrapper that manages state; ListboxContent carries role=\"listbox\" -->\n <!-- We forward attrs (aria-label, aria-labelledby, etc.) to ListboxContent, not the root -->\n <ListboxRoot\n :model-value=\"rekaModelValue\"\n :default-value=\"rekaDefaultValue\"\n :multiple=\"props.multiple ?? props.selectionMode === 'multiple'\"\n :selection-behavior=\"props.selectionBehavior ?? (props.selectionMode === 'multiple' ? 'toggle' : 'replace')\"\n :disabled=\"props.isDisabled\"\n :orientation=\"props.orientation\"\n :dir=\"props.dir\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :by=\"props.by\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :name=\"props.name\"\n :required=\"props.required\"\n @update:model-value=\"emit('update:modelValue', props.selectionMode === 'single' ? (Array.isArray($event) ? ($event as string[])[0] : $event as string) : $event as string[])\"\n @highlight=\"emit('highlight', $event)\"\n @entry-focus=\"emit('entry-focus', $event)\"\n @leave=\"emit('leave', $event)\"\n >\n <ListboxContent\n ref=\"content\"\n v-bind=\"attrs\"\n :as=\"props.contentAs\"\n :as-child=\"props.contentAsChild\"\n :style=\"contentStyle\"\n :class=\"composeClassName(slotFns, props.class, props.classNames?.base)\"\n >\n <ListboxVirtualizer\n v-if=\"props.virtualized && props.items\"\n :options=\"props.items\"\n :estimate-size=\"props.estimateSize\"\n :overscan=\"props.overscan\"\n :text-content=\"(o) => (o.label ?? o.value)\"\n >\n <template #default=\"{ option, virtualItem }\">\n <slot name=\"item\" :item=\"option\" :index=\"virtualItem.index\">\n <ListBoxItem\n :value=\"option.value\"\n :is-disabled=\"option.disabled\"\n :text-value=\"option.textValue\"\n >{{ option.label ?? option.value }}</ListBoxItem>\n </slot>\n </template>\n </ListboxVirtualizer>\n\n <template v-else-if=\"props.items\">\n <ListBoxItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :text-value=\"item.textValue\"\n >{{ item.label ?? item.value }}</ListBoxItem>\n </template>\n\n <slot v-else />\n </ListboxContent>\n\n <!-- Bottom area, rendered outside role=\"listbox\" so it does not violate\n aria-required-children. Scroll mode shows a loading row; button mode\n shows a manual \"Load more\" button (which conveys its own loading state). -->\n <div\n v-if=\"props.loadMode === 'scroll' && props.isLoading\"\n data-slot=\"list-box-loading\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <slot name=\"loading\">Loading…</slot>\n </div>\n\n <div\n v-if=\"props.loadMode === 'button' && props.hasMore\"\n class=\"flex justify-center p-2\"\n data-slot=\"list-box-load-more\"\n >\n <slot\n name=\"loadMore\"\n :load-more=\"requestLoadMore\"\n :is-loading=\"props.isLoading\"\n :has-more=\"props.hasMore\"\n >\n <Button\n size=\"sm\"\n :is-loading=\"props.isLoading\"\n :disabled=\"props.isLoading\"\n data-slot=\"load-more-button\"\n @click=\"requestLoadMore\"\n >\n {{ props.loadMoreLabel }}\n </Button>\n </slot>\n </div>\n </ListboxRoot>\n</template>\n"],"mappings":""}
@@ -1,10 +1,23 @@
1
1
  import { composeClassName } from "../../utils/composeClassName.js";
2
+ import Button_default from "../button/Button.js";
2
3
  import { useListBoxProvide } from "./ListBox.context.js";
3
4
  import ListBoxItem_default from "./ListBoxItem.js";
4
- import { Fragment, computed, createBlock, createElementBlock, createTextVNode, createVNode, defineComponent, mergeProps, openBlock, renderList, renderSlot, toDisplayString, toRef, unref, useAttrs, withCtx } from "vue";
5
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createTextVNode, createVNode, defineComponent, mergeProps, openBlock, ref, renderList, renderSlot, toDisplayString, toRef, unref, useAttrs, useTemplateRef, withCtx } from "vue";
6
+ import { useInfiniteScroll } from "@vueuse/core";
5
7
  import { listboxVariants } from "@auronui/styles";
6
- import { ListboxContent, ListboxRoot } from "reka-ui";
8
+ import { ListboxContent, ListboxRoot, ListboxVirtualizer } from "reka-ui";
7
9
  //#region src/components/list-box/ListBox.vue?vue&type=script&setup=true&lang.ts
10
+ var _hoisted_1 = {
11
+ key: 0,
12
+ "data-slot": "list-box-loading",
13
+ role: "status",
14
+ "aria-live": "polite"
15
+ };
16
+ var _hoisted_2 = {
17
+ key: 1,
18
+ class: "flex justify-center p-2",
19
+ "data-slot": "list-box-load-more"
20
+ };
8
21
  var ListBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
9
22
  inheritAttrs: false,
10
23
  __name: "ListBox",
@@ -55,13 +68,39 @@ var ListBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
55
68
  contentAsChild: {
56
69
  type: Boolean,
57
70
  default: false
58
- }
71
+ },
72
+ hideSelectedIcon: {
73
+ type: Boolean,
74
+ default: false
75
+ },
76
+ virtualized: {
77
+ type: Boolean,
78
+ default: false
79
+ },
80
+ estimateSize: {
81
+ type: [Number, Function],
82
+ default: 36
83
+ },
84
+ overscan: { default: 12 },
85
+ maxHeight: { default: "16rem" },
86
+ hasMore: {
87
+ type: Boolean,
88
+ default: false
89
+ },
90
+ isLoading: {
91
+ type: Boolean,
92
+ default: false
93
+ },
94
+ loadMoreDistance: { default: 120 },
95
+ loadMode: { default: "scroll" },
96
+ loadMoreLabel: { default: "Load more" }
59
97
  },
60
98
  emits: [
61
99
  "update:modelValue",
62
100
  "highlight",
63
101
  "entry-focus",
64
- "leave"
102
+ "leave",
103
+ "load-more"
65
104
  ],
66
105
  setup(__props, { emit: __emit }) {
67
106
  const props = __props;
@@ -70,13 +109,33 @@ var ListBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
70
109
  useListBoxProvide({
71
110
  variant: toRef(props, "variant"),
72
111
  itemVariant: toRef(props, "variant"),
73
- isDisabled: toRef(props, "isDisabled")
112
+ isDisabled: toRef(props, "isDisabled"),
113
+ hideSelectedIcon: toRef(props, "hideSelectedIcon")
74
114
  });
75
115
  const slotFns = computed(() => listboxVariants({ variant: props.variant }));
116
+ const contentRef = useTemplateRef("content");
117
+ const lastRequestedCount = ref(-1);
118
+ useInfiniteScroll(contentRef, () => {
119
+ lastRequestedCount.value = props.items?.length ?? 0;
120
+ emit("load-more");
121
+ }, {
122
+ distance: props.loadMoreDistance,
123
+ canLoadMore: () => props.loadMode === "scroll" && props.hasMore && !props.isLoading && (props.items?.length ?? 0) !== lastRequestedCount.value
124
+ });
125
+ function requestLoadMore() {
126
+ if (props.hasMore && !props.isLoading) emit("load-more");
127
+ }
128
+ const needsScroll = computed(() => props.virtualized);
129
+ const contentStyle = computed(() => needsScroll.value ? {
130
+ maxHeight: typeof props.maxHeight === "number" ? `${props.maxHeight}px` : props.maxHeight,
131
+ overflowY: "auto"
132
+ } : void 0);
133
+ const rekaModelValue = computed(() => props.modelValue == null ? void 0 : [].concat(props.modelValue));
134
+ const rekaDefaultValue = computed(() => props.defaultValue == null ? void 0 : [].concat(props.defaultValue));
76
135
  return (_ctx, _cache) => {
77
136
  return openBlock(), createBlock(unref(ListboxRoot), {
78
- "model-value": props.modelValue == null ? void 0 : [].concat(props.modelValue),
79
- "default-value": props.defaultValue == null ? void 0 : [].concat(props.defaultValue),
137
+ "model-value": rekaModelValue.value,
138
+ "default-value": rekaDefaultValue.value,
80
139
  multiple: props.multiple ?? props.selectionMode === "multiple",
81
140
  "selection-behavior": props.selectionBehavior ?? (props.selectionMode === "multiple" ? "toggle" : "replace"),
82
141
  disabled: props.isDisabled,
@@ -93,32 +152,79 @@ var ListBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
93
152
  onEntryFocus: _cache[2] || (_cache[2] = ($event) => emit("entry-focus", $event)),
94
153
  onLeave: _cache[3] || (_cache[3] = ($event) => emit("leave", $event))
95
154
  }, {
96
- default: withCtx(() => [createVNode(unref(ListboxContent), mergeProps(unref(attrs), {
97
- as: props.contentAs,
98
- "as-child": props.contentAsChild,
99
- class: unref(composeClassName)(slotFns.value, props.class, props.classNames?.base)
100
- }), {
101
- default: withCtx(() => [props.items ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(props.items, (item) => {
102
- return openBlock(), createBlock(ListBoxItem_default, {
103
- key: item.value,
104
- value: item.value,
105
- "is-disabled": item.disabled,
106
- "text-value": item.textValue
155
+ default: withCtx(() => [
156
+ createVNode(unref(ListboxContent), mergeProps({ ref: "content" }, unref(attrs), {
157
+ as: props.contentAs,
158
+ "as-child": props.contentAsChild,
159
+ style: contentStyle.value,
160
+ class: unref(composeClassName)(slotFns.value, props.class, props.classNames?.base)
161
+ }), {
162
+ default: withCtx(() => [props.virtualized && props.items ? (openBlock(), createBlock(unref(ListboxVirtualizer), {
163
+ key: 0,
164
+ options: props.items,
165
+ "estimate-size": props.estimateSize,
166
+ overscan: props.overscan,
167
+ "text-content": (o) => o.label ?? o.value
107
168
  }, {
108
- default: withCtx(() => [createTextVNode(toDisplayString(item.label ?? item.value), 1)]),
109
- _: 2
110
- }, 1032, [
111
- "value",
112
- "is-disabled",
113
- "text-value"
114
- ]);
115
- }), 128)) : renderSlot(_ctx.$slots, "default", { key: 1 })]),
116
- _: 3
117
- }, 16, [
118
- "as",
119
- "as-child",
120
- "class"
121
- ])]),
169
+ default: withCtx(({ option, virtualItem }) => [renderSlot(_ctx.$slots, "item", {
170
+ item: option,
171
+ index: virtualItem.index
172
+ }, () => [createVNode(ListBoxItem_default, {
173
+ value: option.value,
174
+ "is-disabled": option.disabled,
175
+ "text-value": option.textValue
176
+ }, {
177
+ default: withCtx(() => [createTextVNode(toDisplayString(option.label ?? option.value), 1)]),
178
+ _: 2
179
+ }, 1032, [
180
+ "value",
181
+ "is-disabled",
182
+ "text-value"
183
+ ])])]),
184
+ _: 3
185
+ }, 8, [
186
+ "options",
187
+ "estimate-size",
188
+ "overscan",
189
+ "text-content"
190
+ ])) : props.items ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(props.items, (item) => {
191
+ return openBlock(), createBlock(ListBoxItem_default, {
192
+ key: item.value,
193
+ value: item.value,
194
+ "is-disabled": item.disabled,
195
+ "text-value": item.textValue
196
+ }, {
197
+ default: withCtx(() => [createTextVNode(toDisplayString(item.label ?? item.value), 1)]),
198
+ _: 2
199
+ }, 1032, [
200
+ "value",
201
+ "is-disabled",
202
+ "text-value"
203
+ ]);
204
+ }), 128)) : renderSlot(_ctx.$slots, "default", { key: 2 })]),
205
+ _: 3
206
+ }, 16, [
207
+ "as",
208
+ "as-child",
209
+ "style",
210
+ "class"
211
+ ]),
212
+ props.loadMode === "scroll" && props.isLoading ? (openBlock(), createElementBlock("div", _hoisted_1, [renderSlot(_ctx.$slots, "loading", {}, () => [_cache[4] || (_cache[4] = createTextVNode("Loading…", -1))])])) : createCommentVNode("", true),
213
+ props.loadMode === "button" && props.hasMore ? (openBlock(), createElementBlock("div", _hoisted_2, [renderSlot(_ctx.$slots, "loadMore", {
214
+ loadMore: requestLoadMore,
215
+ isLoading: props.isLoading,
216
+ hasMore: props.hasMore
217
+ }, () => [createVNode(Button_default, {
218
+ size: "sm",
219
+ "is-loading": props.isLoading,
220
+ disabled: props.isLoading,
221
+ "data-slot": "load-more-button",
222
+ onClick: requestLoadMore
223
+ }, {
224
+ default: withCtx(() => [createTextVNode(toDisplayString(props.loadMoreLabel), 1)]),
225
+ _: 1
226
+ }, 8, ["is-loading", "disabled"])])])) : createCommentVNode("", true)
227
+ ]),
122
228
  _: 3
123
229
  }, 8, [
124
230
  "model-value",
@@ -1 +1 @@
1
- {"version":3,"file":"ListBox.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/list-box/ListBox.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, toRef, useAttrs } from 'vue'\nimport { ListboxRoot, ListboxContent } from 'reka-ui'\nimport { listboxVariants, type ListBoxVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useListBoxProvide } from './ListBox.context'\nimport ListBoxItem from './ListBoxItem.vue'\n\ntype ListBoxShorthandItem = { value: string; label?: string; disabled?: boolean; textValue?: string }\n\n// Disable Vue attribute fallthrough — we manually forward ARIA attrs to ListboxContent\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n modelValue?: string | string[]\n defaultValue?: string | string[]\n selectionMode?: 'single' | 'multiple'\n variant?: ListBoxVariants['variant']\n isDisabled?: boolean\n class?: ClassValue\n /**\n * Per-slot class overrides. Each key maps to a named slot in the anatomy;\n * the value is merged with the generated variant classes via `composeClassName`.\n */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render list items from an array instead of the compound slot API */\n items?: ListBoxShorthandItem[]\n /** Allow selecting multiple values (alias for selectionMode=\"multiple\"). */\n multiple?: boolean\n /** Orientation of the listbox for keyboard navigation. */\n orientation?: 'horizontal' | 'vertical'\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Selection behavior when multiple is true. */\n selectionBehavior?: 'toggle' | 'replace'\n /** Highlight item on hover. */\n highlightOnHover?: boolean\n /** Key used to compare items for equality. */\n by?: string\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 /** Form field name for native form submission. */\n name?: string\n /** Mark the field as required. */\n required?: boolean\n /** Render the ListboxContent as a different element. */\n contentAs?: string\n /** Merge content props onto child element. */\n contentAsChild?: boolean\n}>(), {\n modelValue: undefined,\n defaultValue: undefined,\n selectionMode: 'single',\n variant: 'default',\n isDisabled: false,\n class: undefined,\n multiple: undefined,\n orientation: undefined,\n dir: undefined,\n selectionBehavior: undefined,\n highlightOnHover: undefined,\n by: undefined,\n as: undefined,\n asChild: false,\n name: undefined,\n required: undefined,\n contentAs: undefined,\n contentAsChild: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined]\n 'highlight': [context: unknown]\n 'entry-focus': [event: Event]\n 'leave': [event: Event]\n}>()\n\nconst attrs = useAttrs()\n\n// Provide context for ListBoxItem and ListBoxSection children\nuseListBoxProvide({\n variant: toRef(props, 'variant'),\n itemVariant: toRef(props, 'variant'),\n isDisabled: toRef(props, 'isDisabled'),\n})\n\nconst slotFns = computed(() =>\n listboxVariants({ variant: props.variant })\n)\n</script>\n\n<template>\n <!-- ListboxRoot is an invisible wrapper that manages state; ListboxContent carries role=\"listbox\" -->\n <!-- We forward attrs (aria-label, aria-labelledby, etc.) to ListboxContent, not the root -->\n <ListboxRoot\n :model-value=\"props.modelValue == null ? undefined : ([] as string[]).concat(props.modelValue)\"\n :default-value=\"props.defaultValue == null ? undefined : ([] as string[]).concat(props.defaultValue)\"\n :multiple=\"props.multiple ?? props.selectionMode === 'multiple'\"\n :selection-behavior=\"props.selectionBehavior ?? (props.selectionMode === 'multiple' ? 'toggle' : 'replace')\"\n :disabled=\"props.isDisabled\"\n :orientation=\"props.orientation\"\n :dir=\"props.dir\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :by=\"props.by\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :name=\"props.name\"\n :required=\"props.required\"\n @update:model-value=\"emit('update:modelValue', props.selectionMode === 'single' ? (Array.isArray($event) ? ($event as string[])[0] : $event as string) : $event as string[])\"\n @highlight=\"emit('highlight', $event)\"\n @entry-focus=\"emit('entry-focus', $event)\"\n @leave=\"emit('leave', $event)\"\n >\n <ListboxContent\n v-bind=\"attrs\"\n :as=\"props.contentAs\"\n :as-child=\"props.contentAsChild\"\n :class=\"composeClassName(slotFns, props.class, props.classNames?.base)\"\n >\n <template v-if=\"props.items\">\n <ListBoxItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :text-value=\"item.textValue\"\n >{{ item.label ?? item.value }}</ListBoxItem>\n </template>\n <slot v-else />\n </ListboxContent>\n </ListboxRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAaA,MAAM,QAAQ;EA6Dd,MAAM,OAAO;EAOb,MAAM,QAAQ,UAAS;AAGvB,oBAAkB;GAChB,SAAS,MAAM,OAAO,UAAU;GAChC,aAAa,MAAM,OAAO,UAAU;GACpC,YAAY,MAAM,OAAO,aAAa;GACvC,CAAA;EAED,MAAM,UAAU,eACd,gBAAgB,EAAE,SAAS,MAAM,SAAS,CAAA,CAC5C;;uBAME,YAoCc,MAAA,YAAA,EAAA;IAnCX,eAAa,MAAM,cAAU,OAAW,KAAA,IAAS,EAAA,CAAoB,OAAO,MAAM,WAAU;IAC5F,iBAAe,MAAM,gBAAY,OAAW,KAAA,IAAS,EAAA,CAAoB,OAAO,MAAM,aAAY;IAClG,UAAU,MAAM,YAAY,MAAM,kBAAa;IAC/C,sBAAoB,MAAM,sBAAsB,MAAM,kBAAa,aAAA,WAAA;IACnE,UAAU,MAAM;IAChB,aAAa,MAAM;IACnB,KAAK,MAAM;IACX,sBAAoB,MAAM;IAC1B,IAAI,MAAM;IACV,IAAI,MAAM;IACV,YAAU,MAAM;IAChB,MAAM,MAAM;IACZ,UAAU,MAAM;IAChB,uBAAkB,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,qBAAsB,MAAM,kBAAa,WAAiB,MAAM,QAAQ,OAAM,GAAK,OAAM,KAAmB,SAAoB,OAAM;IAC9J,aAAS,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,aAAc,OAAM;IACnC,cAAW,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,eAAgB,OAAM;IACvC,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAU,OAAM;;2BAkBX,CAhBjB,YAgBiB,MAAA,eAAA,EAhBjB,WACU,MAeO,MAfF,EAAA;KACZ,IAAI,MAAM;KACV,YAAU,MAAM;KAChB,OAAO,MAAA,iBAAgB,CAAC,QAAA,OAAS,MAAM,OAAO,MAAM,YAAY,KAAI;;4BAU1D,CARK,MAAM,SAAA,UAAA,KAAA,EACpB,mBAM6C,UAAA,EAAA,KAAA,GAAA,EAAA,WAL5B,MAAM,QAAd,SAAI;0BADb,YAM6C,qBAAA;OAJ1C,KAAK,KAAK;OACV,OAAO,KAAK;OACZ,eAAa,KAAK;OAClB,cAAY,KAAK;;8BACW,CAAA,gBAAA,gBAA3B,KAAK,SAAS,KAAK,MAAK,EAAA,EAAA,CAAA,CAAA;;;;;;;iBAE9B,WAAe,KAAA,QAAA,WAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ListBox.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/list-box/ListBox.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, useAttrs, useTemplateRef } from 'vue'\nimport { useInfiniteScroll } from '@vueuse/core'\nimport { ListboxRoot, ListboxContent, ListboxVirtualizer } from 'reka-ui'\nimport { listboxVariants, type ListBoxVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useListBoxProvide } from './ListBox.context'\nimport ListBoxItem from './ListBoxItem.vue'\nimport Button from '../button/Button.vue'\n\ntype ListBoxShorthandItem = { value: string; label?: string; disabled?: boolean; textValue?: string }\n\n// Disable Vue attribute fallthrough — we manually forward ARIA attrs to ListboxContent\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n modelValue?: string | string[]\n defaultValue?: string | string[]\n selectionMode?: 'single' | 'multiple'\n variant?: ListBoxVariants['variant']\n isDisabled?: boolean\n class?: ClassValue\n /**\n * Per-slot class overrides. Each key maps to a named slot in the anatomy;\n * the value is merged with the generated variant classes via `composeClassName`.\n */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render list items from an array instead of the compound slot API */\n items?: ListBoxShorthandItem[]\n /** Allow selecting multiple values (alias for selectionMode=\"multiple\"). */\n multiple?: boolean\n /** Orientation of the listbox for keyboard navigation. */\n orientation?: 'horizontal' | 'vertical'\n /** Reading direction for the component. */\n dir?: 'ltr' | 'rtl'\n /** Selection behavior when multiple is true. */\n selectionBehavior?: 'toggle' | 'replace'\n /** Highlight item on hover. */\n highlightOnHover?: boolean\n /** Key used to compare items for equality. */\n by?: string\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 /** Form field name for native form submission. */\n name?: string\n /** Mark the field as required. */\n required?: boolean\n /** Render the ListboxContent as a different element. */\n contentAs?: string\n /** Merge content props onto child element. */\n contentAsChild?: boolean\n /** Hide the selected checkmark on all items (forwarded via context). */\n hideSelectedIcon?: boolean\n /** Enable windowed rendering (opt-in). Renders from `items`. */\n virtualized?: boolean\n /** Estimated row height in px (or per-index fn) for the virtualizer. */\n estimateSize?: number | ((index: number) => number)\n /** Rows rendered outside the visible area. */\n overscan?: number\n /** Scroll-viewport height for the content when scrolling is active. */\n maxHeight?: string | number\n /** Whether more pages remain to load (gates load-more). */\n hasMore?: boolean\n /** A page is currently loading (gates load-more; drives #loading slot). */\n isLoading?: boolean\n /** Distance in px from the bottom that triggers load-more. */\n loadMoreDistance?: number\n /** How the next page is requested: auto on scroll, or a manual button. */\n loadMode?: 'scroll' | 'button'\n /** Label for the manual load-more button (loadMode=\"button\"). */\n loadMoreLabel?: string\n}>(), {\n modelValue: undefined,\n defaultValue: undefined,\n selectionMode: 'single',\n variant: 'default',\n isDisabled: false,\n class: undefined,\n multiple: undefined,\n orientation: undefined,\n dir: undefined,\n selectionBehavior: undefined,\n highlightOnHover: undefined,\n by: undefined,\n as: undefined,\n asChild: false,\n name: undefined,\n required: undefined,\n contentAs: undefined,\n contentAsChild: false,\n hideSelectedIcon: false,\n virtualized: false,\n estimateSize: 36,\n overscan: 12,\n maxHeight: '16rem',\n hasMore: false,\n isLoading: false,\n loadMoreDistance: 120,\n loadMode: 'scroll',\n loadMoreLabel: 'Load more',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[] | undefined]\n 'highlight': [context: unknown]\n 'entry-focus': [event: Event]\n 'leave': [event: Event]\n 'load-more': []\n}>()\n\nconst attrs = useAttrs()\n\n// Provide context for ListBoxItem and ListBoxSection children\nuseListBoxProvide({\n variant: toRef(props, 'variant'),\n itemVariant: toRef(props, 'variant'),\n isDisabled: toRef(props, 'isDisabled'),\n hideSelectedIcon: toRef(props, 'hideSelectedIcon'),\n})\n\nconst slotFns = computed(() =>\n listboxVariants({ variant: props.variant })\n)\n\n// Bounded scroll viewport only when the content actually needs to scroll, so\n// default (non-virtualized) ListBoxes are visually unchanged.\n// useTemplateRef on a Reka component resolves to its instance; useInfiniteScroll's\n// internal unrefElement reads `.$el` to get the scroll DOM node.\nconst contentRef = useTemplateRef<HTMLElement>('content')\n\n// Re-arm latch. useInfiniteScroll keeps re-invoking onLoadMore while the scroll\n// element stays at the bottom and canLoadMore is true. Emitting `load-more` does\n// not itself flip hasMore/isLoading, so without this guard it fires in a tight\n// loop (unbounded emits → hang). We record the item count at the moment we ask\n// for a page and refuse to ask again until the dataset actually grows — i.e.\n// until the consumer has appended the next page.\nconst lastRequestedCount = ref(-1)\nuseInfiniteScroll(\n contentRef,\n () => {\n lastRequestedCount.value = props.items?.length ?? 0\n emit('load-more')\n },\n {\n // Read once at setup: useScroll consumes `offset.bottom` as a raw number\n // (no toValue), so a getter/ref here would break arrival math. Hot-swapping\n // loadMoreDistance after mount is not supported (not a real use case).\n distance: props.loadMoreDistance,\n canLoadMore: () =>\n props.loadMode === 'scroll'\n && props.hasMore\n && !props.isLoading\n && (props.items?.length ?? 0) !== lastRequestedCount.value,\n },\n)\n\n// Manual load-more (loadMode=\"button\"). User-driven, so no re-arm latch needed —\n// the hasMore/isLoading gate is enough (and the button is disabled while loading).\nfunction requestLoadMore() {\n if (props.hasMore && !props.isLoading) emit('load-more')\n}\n\nconst needsScroll = computed(() => props.virtualized)\nconst contentStyle = computed(() =>\n needsScroll.value\n ? { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight, overflowY: 'auto' as const }\n : undefined,\n)\n\n// Stable array references for Reka. Building a fresh array inline on every render\n// would retrigger Reka's `watch(modelValue)`, which re-highlights and\n// scrollIntoView's the selected/first item — making the list jump to the top on\n// any unrelated re-render (e.g. when isLoading toggles during load-more). A\n// computed is cached, so the reference only changes when the value really does.\nconst rekaModelValue = computed(() =>\n props.modelValue == null ? undefined : ([] as string[]).concat(props.modelValue),\n)\nconst rekaDefaultValue = computed(() =>\n props.defaultValue == null ? undefined : ([] as string[]).concat(props.defaultValue),\n)\n</script>\n\n<template>\n <!-- ListboxRoot is an invisible wrapper that manages state; ListboxContent carries role=\"listbox\" -->\n <!-- We forward attrs (aria-label, aria-labelledby, etc.) to ListboxContent, not the root -->\n <ListboxRoot\n :model-value=\"rekaModelValue\"\n :default-value=\"rekaDefaultValue\"\n :multiple=\"props.multiple ?? props.selectionMode === 'multiple'\"\n :selection-behavior=\"props.selectionBehavior ?? (props.selectionMode === 'multiple' ? 'toggle' : 'replace')\"\n :disabled=\"props.isDisabled\"\n :orientation=\"props.orientation\"\n :dir=\"props.dir\"\n :highlight-on-hover=\"props.highlightOnHover\"\n :by=\"props.by\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :name=\"props.name\"\n :required=\"props.required\"\n @update:model-value=\"emit('update:modelValue', props.selectionMode === 'single' ? (Array.isArray($event) ? ($event as string[])[0] : $event as string) : $event as string[])\"\n @highlight=\"emit('highlight', $event)\"\n @entry-focus=\"emit('entry-focus', $event)\"\n @leave=\"emit('leave', $event)\"\n >\n <ListboxContent\n ref=\"content\"\n v-bind=\"attrs\"\n :as=\"props.contentAs\"\n :as-child=\"props.contentAsChild\"\n :style=\"contentStyle\"\n :class=\"composeClassName(slotFns, props.class, props.classNames?.base)\"\n >\n <ListboxVirtualizer\n v-if=\"props.virtualized && props.items\"\n :options=\"props.items\"\n :estimate-size=\"props.estimateSize\"\n :overscan=\"props.overscan\"\n :text-content=\"(o) => (o.label ?? o.value)\"\n >\n <template #default=\"{ option, virtualItem }\">\n <slot name=\"item\" :item=\"option\" :index=\"virtualItem.index\">\n <ListBoxItem\n :value=\"option.value\"\n :is-disabled=\"option.disabled\"\n :text-value=\"option.textValue\"\n >{{ option.label ?? option.value }}</ListBoxItem>\n </slot>\n </template>\n </ListboxVirtualizer>\n\n <template v-else-if=\"props.items\">\n <ListBoxItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :text-value=\"item.textValue\"\n >{{ item.label ?? item.value }}</ListBoxItem>\n </template>\n\n <slot v-else />\n </ListboxContent>\n\n <!-- Bottom area, rendered outside role=\"listbox\" so it does not violate\n aria-required-children. Scroll mode shows a loading row; button mode\n shows a manual \"Load more\" button (which conveys its own loading state). -->\n <div\n v-if=\"props.loadMode === 'scroll' && props.isLoading\"\n data-slot=\"list-box-loading\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <slot name=\"loading\">Loading…</slot>\n </div>\n\n <div\n v-if=\"props.loadMode === 'button' && props.hasMore\"\n class=\"flex justify-center p-2\"\n data-slot=\"list-box-load-more\"\n >\n <slot\n name=\"loadMore\"\n :load-more=\"requestLoadMore\"\n :is-loading=\"props.isLoading\"\n :has-more=\"props.hasMore\"\n >\n <Button\n size=\"sm\"\n :is-loading=\"props.isLoading\"\n :disabled=\"props.isLoading\"\n data-slot=\"load-more-button\"\n @click=\"requestLoadMore\"\n >\n {{ props.loadMoreLabel }}\n </Button>\n </slot>\n </div>\n </ListboxRoot>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ListBoxItem.js","names":[],"sources":["../../../src/components/list-box/ListBoxItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ListboxItem, ListboxItemIndicator } from 'reka-ui'\nimport { listboxItemVariants, type ListBoxItemVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useListBoxInject } from './ListBox.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n textValue?: string\n isDisabled?: boolean\n variant?: ListBoxItemVariants['variant']\n class?: ClassValue\n /** Override classes for individual slots */\n classNames?: Partial<{\n item: ClassValue\n indicator: ClassValue\n }>\n /** Whether the item is disabled. Alias for isDisabled. */\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 /** Render the ListboxItemIndicator as a different element. */\n indicatorAs?: string\n /** Merge indicator props onto child element. */\n indicatorAsChild?: boolean\n}>(), {\n textValue: undefined,\n isDisabled: false,\n variant: undefined,\n class: undefined,\n classNames: undefined,\n disabled: undefined,\n as: undefined,\n asChild: false,\n indicatorAs: undefined,\n indicatorAsChild: false,\n})\n\nconst emit = defineEmits<{\n 'select': [event: Event]\n}>()\n\n// Inject context with fallback (standalone usage)\nconst ctx = useListBoxInject({\n variant: ref('default'),\n itemVariant: ref('default'),\n isDisabled: ref(false),\n})\n\nconst finalVariant = computed(() => props.variant ?? ctx.itemVariant.value)\nconst finalDisabled = computed(() => ctx.isDisabled.value || props.isDisabled)\n\nconst slotFns = computed(() =>\n listboxItemVariants({ variant: finalVariant.value as ListBoxItemVariants['variant'] })\n)\n</script>\n\n<template>\n <ListboxItem\n :value=\"props.value\"\n :disabled=\"props.disabled ?? finalDisabled\"\n :text-value=\"props.textValue ?? props.value\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.item(), props.class, props.classNames?.item)\"\n @select=\"emit('select', $event)\"\n >\n <slot name=\"startContent\" />\n <slot />\n <slot name=\"endContent\" />\n <ListboxItemIndicator\n :as=\"props.indicatorAs\"\n :as-child=\"props.indicatorAsChild\"\n :class=\"composeClassName(slotFns.indicator(), props.classNames?.indicator)\"\n >\n <slot name=\"selectedIcon\">\n <!-- Default check icon -->\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ListboxItemIndicator>\n </ListboxItem>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ListBoxItem.js","names":[],"sources":["../../../src/components/list-box/ListBoxItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ListboxItem, ListboxItemIndicator } from 'reka-ui'\nimport { listboxItemVariants, type ListBoxItemVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useListBoxInject } from './ListBox.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n textValue?: string\n isDisabled?: boolean\n variant?: ListBoxItemVariants['variant']\n class?: ClassValue\n /** Override classes for individual slots */\n classNames?: Partial<{\n item: ClassValue\n indicator: ClassValue\n }>\n /** Whether the item is disabled. Alias for isDisabled. */\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 /** Render the ListboxItemIndicator as a different element. */\n indicatorAs?: string\n /** Merge indicator props onto child element. */\n indicatorAsChild?: boolean\n /** Hide this item's selected indicator. Falls back to the ListBox setting. */\n hideSelectedIcon?: boolean\n}>(), {\n textValue: undefined,\n isDisabled: false,\n variant: undefined,\n class: undefined,\n classNames: undefined,\n disabled: undefined,\n as: undefined,\n asChild: false,\n indicatorAs: undefined,\n indicatorAsChild: false,\n hideSelectedIcon: undefined,\n})\n\nconst emit = defineEmits<{\n 'select': [event: Event]\n}>()\n\n// Inject context with fallback (standalone usage)\nconst ctx = useListBoxInject({\n variant: ref('default'),\n itemVariant: ref('default'),\n isDisabled: ref(false),\n hideSelectedIcon: ref(false),\n})\n\nconst finalVariant = computed(() => props.variant ?? ctx.itemVariant.value)\nconst finalDisabled = computed(() => ctx.isDisabled.value || props.isDisabled)\nconst finalHideSelectedIcon = computed(\n () => props.hideSelectedIcon ?? ctx.hideSelectedIcon.value,\n)\n\nconst slotFns = computed(() =>\n listboxItemVariants({ variant: finalVariant.value as ListBoxItemVariants['variant'] })\n)\n</script>\n\n<template>\n <ListboxItem\n :value=\"props.value\"\n :disabled=\"props.disabled ?? finalDisabled\"\n :text-value=\"props.textValue ?? props.value\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.item(), props.class, props.classNames?.item)\"\n @select=\"emit('select', $event)\"\n >\n <slot name=\"startContent\" />\n <slot />\n <slot name=\"endContent\" />\n <ListboxItemIndicator\n v-if=\"!finalHideSelectedIcon\"\n :as=\"props.indicatorAs\"\n :as-child=\"props.indicatorAsChild\"\n :class=\"composeClassName(slotFns.indicator(), props.classNames?.indicator)\"\n >\n <slot name=\"selectedIcon\">\n <!-- Default check icon -->\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ListboxItemIndicator>\n </ListboxItem>\n</template>\n"],"mappings":""}
@@ -1,6 +1,6 @@
1
1
  import { composeClassName } from "../../utils/composeClassName.js";
2
2
  import { useListBoxInject } from "./ListBox.context.js";
3
- import { computed, createBlock, createElementVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, renderSlot, unref, withCtx } from "vue";
3
+ import { computed, createBlock, createCommentVNode, createElementVNode, defineComponent, normalizeClass, openBlock, ref, renderSlot, unref, withCtx } from "vue";
4
4
  import { listboxItemVariants } from "@auronui/styles";
5
5
  import { ListboxItem, ListboxItemIndicator } from "reka-ui";
6
6
  //#region src/components/list-box/ListBoxItem.vue?vue&type=script&setup=true&lang.ts
@@ -38,6 +38,10 @@ var ListBoxItem_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
38
38
  indicatorAsChild: {
39
39
  type: Boolean,
40
40
  default: false
41
+ },
42
+ hideSelectedIcon: {
43
+ type: Boolean,
44
+ default: void 0
41
45
  }
42
46
  },
43
47
  emits: ["select"],
@@ -47,10 +51,12 @@ var ListBoxItem_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
47
51
  const ctx = useListBoxInject({
48
52
  variant: ref("default"),
49
53
  itemVariant: ref("default"),
50
- isDisabled: ref(false)
54
+ isDisabled: ref(false),
55
+ hideSelectedIcon: ref(false)
51
56
  });
52
57
  const finalVariant = computed(() => props.variant ?? ctx.itemVariant.value);
53
58
  const finalDisabled = computed(() => ctx.isDisabled.value || props.isDisabled);
59
+ const finalHideSelectedIcon = computed(() => props.hideSelectedIcon ?? ctx.hideSelectedIcon.value);
54
60
  const slotFns = computed(() => listboxItemVariants({ variant: finalVariant.value }));
55
61
  return (_ctx, _cache) => {
56
62
  return openBlock(), createBlock(unref(ListboxItem), {
@@ -66,7 +72,8 @@ var ListBoxItem_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
66
72
  renderSlot(_ctx.$slots, "startContent"),
67
73
  renderSlot(_ctx.$slots, "default"),
68
74
  renderSlot(_ctx.$slots, "endContent"),
69
- createVNode(unref(ListboxItemIndicator), {
75
+ !finalHideSelectedIcon.value ? (openBlock(), createBlock(unref(ListboxItemIndicator), {
76
+ key: 0,
70
77
  as: props.indicatorAs,
71
78
  "as-child": props.indicatorAsChild,
72
79
  class: normalizeClass(unref(composeClassName)(slotFns.value.indicator(), props.classNames?.indicator))
@@ -89,7 +96,7 @@ var ListBoxItem_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
89
96
  "as",
90
97
  "as-child",
91
98
  "class"
92
- ])
99
+ ])) : createCommentVNode("", true)
93
100
  ]),
94
101
  _: 3
95
102
  }, 8, [