@auronui/vue 1.0.12 → 1.0.14

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 (28) hide show
  1. package/dist/cjs/index.cjs +798 -723
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/components/autocomplete/Autocomplete.js.map +1 -1
  4. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js +22 -3
  5. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/combo-box/ComboBox.js.map +1 -1
  7. package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js +20 -2
  8. package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/select/Select.context.js.map +1 -1
  10. package/dist/components/select/Select.js.map +1 -1
  11. package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js +33 -5
  12. package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/select/SelectItem.js.map +1 -1
  14. package/dist/components/select/SelectItem.vue_vue_type_script_setup_true_lang.js +2 -2
  15. package/dist/components/select/SelectItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  16. package/dist/components/select/SelectOverflowChips.js.map +1 -1
  17. package/dist/components/select/SelectOverflowChips.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/select/SelectValue.js.map +1 -1
  19. package/dist/components/select/SelectValue.vue_vue_type_script_setup_true_lang.js +1 -1
  20. package/dist/components/select/SelectValue.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/tabs/TabList.js.map +1 -1
  22. package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js +15 -14
  23. package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/index.d.ts +49 -212
  25. package/dist/index.js +3 -3
  26. package/dist/utils/hasSlotComponent.js +26 -0
  27. package/dist/utils/hasSlotComponent.js.map +1 -0
  28. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"Select.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/Select.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, reactive, toRef, useAttrs, useId } from 'vue'\nimport { SelectRoot } from 'reka-ui'\nimport { selectVariants, type SelectVariants } from '@auronui/styles'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useSelectProvide } from './Select.context'\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: false,\n isRequired: false,\n multiple: false,\n modelValue: undefined,\n defaultValue: undefined,\n open: undefined,\n defaultOpen: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | string[]]\n 'update:open': [value: boolean]\n}>()\n\ntype Props = {\n /** Visual style of the field. @default 'flat' */\n variant?: SelectVariants['variant']\n /** Field height. @default 'md' */\n size?: SelectVariants['size']\n /** Accent color applied to focus ring + floating label. @default 'default' */\n color?: SelectVariants['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?: SelectVariants['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 /** Adds a required asterisk next to the label. @default false */\n isRequired?: boolean\n /** Placeholder shown when no value is selected. */\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?: string\n\n /* ─── Select-specific ─────────────────────────────────────── */\n /** Two-way bound selected value. */\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 /** Controls open state of the dropdown. */\n open?: boolean\n /** Initial open state of the dropdown (uncontrolled). */\n defaultOpen?: boolean\n}\n\nconst attrs = useAttrs()\nconst generatedId = useId()\nconst triggerId = computed(() => (attrs.id as string | undefined) ?? generatedId)\n\nconst hasLabel = computed(() => !!props.label)\n\n// Helper IDs / aria wiring\nconst descriptionId = computed(() => `${triggerId.value}-description`)\nconst errorMessageId = computed(() => `${triggerId.value}-error`)\nconst showError = computed(() => props.isInvalid && !!props.errorMessage)\nconst showDescription = computed(() => !!props.description && !showError.value)\nconst hasHelper = computed(() => showError.value || showDescription.value)\nconst ariaDescribedBy = computed(() => {\n if (showError.value) return errorMessageId.value\n if (showDescription.value) return descriptionId.value\n return undefined\n})\n\nconst slotFns = computed(() =>\n selectVariants({\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: props.isReadonly,\n hasLabel: hasLabel.value,\n labelPlacement: props.labelPlacement,\n }),\n)\n\nconst showOutsideLabel = computed(\n () => hasLabel.value && props.labelPlacement !== 'inside',\n)\n\n// Persistent item registry. SelectItem populates on first mount; entries\n// survive SelectContent unmount so SelectValue can render the label while\n// the popover is closed.\nconst itemRegistry = reactive(new Map<string, string>())\nconst registerItem = (value: string, label: string) => {\n itemRegistry.set(value, label)\n}\nconst itemLabel = (value: string | string[] | undefined | null): string => {\n if (value == null) return ''\n if (Array.isArray(value)) {\n return value.map(v => itemRegistry.get(v) ?? v).filter(Boolean).join(', ')\n }\n return itemRegistry.get(value) ?? value\n}\n\nfunction removeValue(value: string) {\n const current = Array.isArray(props.modelValue) ? props.modelValue : []\n emit('update:modelValue', current.filter(v => v !== value))\n}\n\nuseSelectProvide({\n isDisabled: toRef(props, 'isDisabled'),\n isInvalid: toRef(props, 'isInvalid'),\n isReadonly: toRef(props, 'isReadonly'),\n isRequired: toRef(props, 'isRequired'),\n fullWidth: toRef(props, 'fullWidth'),\n hasLabel,\n labelPlacement: toRef(props, 'labelPlacement'),\n triggerId,\n label: toRef(props, 'label'),\n ariaDescribedBy,\n slots: slotFns,\n multiple: toRef(props, 'multiple'),\n registerItem,\n itemLabel,\n removeValue,\n})\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.base(), props.class)\"\n :data-invalid=\"isInvalid || undefined\"\n :data-disabled=\"isDisabled || undefined\"\n :data-readonly=\"isReadonly || undefined\"\n :data-required=\"isRequired || undefined\"\n :data-has-label=\"hasLabel || undefined\"\n :data-has-helper=\"hasHelper || undefined\"\n >\n <label\n v-if=\"showOutsideLabel\"\n :for=\"triggerId\"\n :class=\"slotFns.label()\"\n >{{ label }}<span\n v-if=\"isRequired\"\n aria-hidden=\"true\"\n > *</span></label>\n\n <div :class=\"slotFns.mainWrapper()\">\n <SelectRoot\n :model-value=\"props.modelValue\"\n :default-value=\"props.defaultValue\"\n :multiple=\"props.multiple\"\n :open=\"props.open\"\n :default-open=\"props.defaultOpen\"\n :disabled=\"props.isDisabled\"\n :required=\"props.isRequired\"\n :name=\"props.name\"\n @update:model-value=\"emit('update:modelValue', $event as string | string[])\"\n @update:open=\"emit('update:open', $event)\"\n >\n <slot />\n </SelectRoot>\n\n <div\n v-if=\"hasHelper\"\n :class=\"slotFns.helperWrapper()\"\n >\n <div\n v-if=\"showError\"\n :id=\"errorMessageId\"\n :class=\"slotFns.errorMessage()\"\n >\n {{ errorMessage }}\n </div>\n <div\n v-else-if=\"showDescription\"\n :id=\"descriptionId\"\n :class=\"slotFns.description()\"\n >\n {{ description }}\n </div>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"Select.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/Select.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, reactive, toRef, useAttrs, useId, useSlots } from 'vue'\nimport { SelectRoot } from 'reka-ui'\nimport { selectVariants, type SelectVariants } from '@auronui/styles'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useSelectProvide, type SelectItemValue, type SelectItemData } from './Select.context'\nimport { hasSlotComponent } from '../../utils/hasSlotComponent'\nimport SelectTrigger from './SelectTrigger.vue'\nimport SelectValue from './SelectValue.vue'\nimport SelectContent from './SelectContent.vue'\nimport SelectItem from './SelectItem.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: false,\n isRequired: false,\n multiple: false,\n modelValue: undefined,\n defaultValue: undefined,\n open: undefined,\n defaultOpen: undefined,\n items: () => [],\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: SelectItemValue | SelectItemValue[]]\n 'update:open': [value: boolean]\n}>()\n\ntype Props = {\n /** Visual style of the field. @default 'flat' */\n variant?: SelectVariants['variant']\n /** Field height. @default 'md' */\n size?: SelectVariants['size']\n /** Accent color applied to focus ring + floating label. @default 'default' */\n color?: SelectVariants['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?: SelectVariants['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 /** Adds a required asterisk next to the label. @default false */\n isRequired?: boolean\n /** Placeholder shown when no value is selected. */\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?: string\n\n /* ─── Select-specific ─────────────────────────────────────── */\n /** Two-way bound selected value. Accepts string or numeric keys. */\n modelValue?: SelectItemValue | SelectItemValue[]\n /** Initial selected value (uncontrolled). Accepts string or numeric keys. */\n defaultValue?: SelectItemValue | SelectItemValue[]\n /** Allow selecting multiple values. modelValue becomes string[]. @default false */\n multiple?: boolean\n /** Controls open state of the dropdown. */\n open?: boolean\n /** Initial open state of the dropdown (uncontrolled). */\n defaultOpen?: boolean\n /**\n * Data-driven items for the terse API. When provided (and no SelectTrigger /\n * SelectContent is passed as a child), the trigger, value, and popover are\n * rendered internally. Use the `#item` slot to customize per-item rendering.\n */\n items?: SelectItemData[]\n}\n\nconst attrs = useAttrs()\nconst generatedId = useId()\nconst triggerId = computed(() => (attrs.id as string | undefined) ?? generatedId)\n\nconst hasLabel = computed(() => !!props.label)\n\nconst slots = useSlots()\n// Tier 3 (advanced): consumer supplied explicit compound chrome → pass through.\n// Tier 1/2 (terse): render trigger/value/content internally.\nconst usesCustomChrome = computed(() =>\n hasSlotComponent(slots.default?.(), [SelectTrigger, SelectContent]),\n)\n\n// Helper IDs / aria wiring\nconst descriptionId = computed(() => `${triggerId.value}-description`)\nconst errorMessageId = computed(() => `${triggerId.value}-error`)\nconst showError = computed(() => props.isInvalid && !!props.errorMessage)\nconst showDescription = computed(() => !!props.description && !showError.value)\nconst hasHelper = computed(() => showError.value || showDescription.value)\nconst ariaDescribedBy = computed(() => {\n if (showError.value) return errorMessageId.value\n if (showDescription.value) return descriptionId.value\n return undefined\n})\n\nconst slotFns = computed(() =>\n selectVariants({\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: props.isReadonly,\n hasLabel: hasLabel.value,\n labelPlacement: props.labelPlacement,\n }),\n)\n\nconst showOutsideLabel = computed(\n () => hasLabel.value && props.labelPlacement !== 'inside',\n)\n\n// Persistent item registry. SelectItem populates on first mount; entries\n// survive SelectContent unmount so SelectValue can render the label while\n// the popover is closed.\nconst itemRegistry = reactive(new Map<SelectItemValue, string>())\nconst registerItem = (value: SelectItemValue, label: string) => {\n itemRegistry.set(value, label)\n}\nconst itemLabel = (value: SelectItemValue | SelectItemValue[] | undefined | null): string => {\n if (value == null) return ''\n if (Array.isArray(value)) {\n // Fall back to the stringified value (handles numeric keys) when no label is\n // registered. Filter empty strings only — never use filter(Boolean), which\n // would drop a registered label for the numeric key 0.\n return value\n .map(v => String(itemRegistry.get(v) ?? v))\n .filter(s => s.length > 0)\n .join(', ')\n }\n return itemRegistry.get(value) ?? String(value)\n}\n\nfunction removeValue(value: SelectItemValue) {\n const current = Array.isArray(props.modelValue) ? props.modelValue : []\n emit('update:modelValue', current.filter(v => v !== value))\n}\n\nuseSelectProvide({\n isDisabled: toRef(props, 'isDisabled'),\n isInvalid: toRef(props, 'isInvalid'),\n isReadonly: toRef(props, 'isReadonly'),\n isRequired: toRef(props, 'isRequired'),\n fullWidth: toRef(props, 'fullWidth'),\n hasLabel,\n labelPlacement: toRef(props, 'labelPlacement'),\n triggerId,\n label: toRef(props, 'label'),\n ariaDescribedBy,\n slots: slotFns,\n multiple: toRef(props, 'multiple'),\n registerItem,\n itemLabel,\n removeValue,\n})\n</script>\n\n<template>\n <div\n :class=\"composeClassName(slotFns.base(), props.class)\"\n :data-invalid=\"isInvalid || undefined\"\n :data-disabled=\"isDisabled || undefined\"\n :data-readonly=\"isReadonly || undefined\"\n :data-required=\"isRequired || undefined\"\n :data-has-label=\"hasLabel || undefined\"\n :data-has-helper=\"hasHelper || undefined\"\n >\n <label\n v-if=\"showOutsideLabel\"\n :for=\"triggerId\"\n :class=\"slotFns.label()\"\n >{{ label }}<span\n v-if=\"isRequired\"\n aria-hidden=\"true\"\n > *</span></label>\n\n <div :class=\"slotFns.mainWrapper()\">\n <SelectRoot\n :model-value=\"props.modelValue\"\n :default-value=\"props.defaultValue\"\n :multiple=\"props.multiple\"\n :open=\"props.open\"\n :default-open=\"props.defaultOpen\"\n :disabled=\"props.isDisabled\"\n :required=\"props.isRequired\"\n :name=\"props.name\"\n @update:model-value=\"emit('update:modelValue', $event as SelectItemValue | SelectItemValue[])\"\n @update:open=\"emit('update:open', $event)\"\n >\n <!-- Tier 3: consumer-provided compound chrome -->\n <slot v-if=\"usesCustomChrome\" />\n <!-- Tier 1/2: internally rendered chrome -->\n <template v-else>\n <SelectTrigger>\n <SelectValue :placeholder=\"props.placeholder\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :text-value=\"item.textValue ?? item.label\"\n :is-disabled=\"item.isDisabled\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n >{{ item.label ?? String(item.value) }}</slot>\n </SelectItem>\n <slot />\n </SelectContent>\n </template>\n </SelectRoot>\n\n <div\n v-if=\"hasHelper\"\n :class=\"slotFns.helperWrapper()\"\n >\n <div\n v-if=\"showError\"\n :id=\"errorMessageId\"\n :class=\"slotFns.errorMessage()\"\n >\n {{ errorMessage }}\n </div>\n <div\n v-else-if=\"showDescription\"\n :id=\"descriptionId\"\n :class=\"slotFns.description()\"\n >\n {{ description }}\n </div>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SelectItem.js","names":[],"sources":["../../../src/components/select/SelectItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, useTemplateRef } from 'vue'\nimport { SelectItem, SelectItemText, SelectItemIndicator } from 'reka-ui'\nimport { useSelectInject } from './Select.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n /**\n * Explicit human-readable label for this item. When provided, the registry is\n * populated immediately at setup time (before the dropdown is ever opened),\n * so SelectValue can display the correct label for a pre-set modelValue.\n * When omitted, the label is read from slot DOM text on first mount.\n */\n textValue?: string\n isDisabled?: boolean\n class?: string\n}>(), {\n textValue: undefined,\n isDisabled: false,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\nconst textRef = useTemplateRef<HTMLElement>('textRef')\n\n// Register immediately with textValue if provided — this runs at setup time,\n// before mount, so SelectValue shows the correct label for a pre-set modelValue\n// even before the dropdown has ever been opened.\nif (props.textValue !== undefined) {\n ctx.registerItem(props.value, props.textValue)\n}\n\nonMounted(() => {\n // textRef points to the SelectItemText component instance (not a DOM element).\n // Access $el to get the underlying span element and read its text content.\n // This refines the registry entry with actual DOM text (handles slot-text items\n // that don't have an explicit textValue prop).\n const el = (textRef.value as { $el?: HTMLElement } | null)?.$el\n const label = props.textValue ?? el?.textContent?.trim() ?? props.value\n ctx.registerItem(props.value, label)\n})\n</script>\n\n<template>\n <SelectItem\n :value=\"props.value\"\n :disabled=\"props.isDisabled\"\n :text-value=\"props.textValue ?? props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <SelectItemText ref=\"textRef\">\n <slot />\n </SelectItemText>\n <SelectItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\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 </SelectItemIndicator>\n <slot name=\"endContent\" />\n </SelectItem>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"SelectItem.js","names":[],"sources":["../../../src/components/select/SelectItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, useTemplateRef } from 'vue'\nimport { SelectItem, SelectItemText, SelectItemIndicator } from 'reka-ui'\nimport { useSelectInject, type SelectItemValue } from './Select.context'\n\nconst props = withDefaults(defineProps<{\n value: SelectItemValue\n /**\n * Explicit human-readable label for this item. When provided, the registry is\n * populated immediately at setup time (before the dropdown is ever opened),\n * so SelectValue can display the correct label for a pre-set modelValue.\n * When omitted, the label is read from slot DOM text on first mount.\n */\n textValue?: string\n isDisabled?: boolean\n class?: string\n}>(), {\n textValue: undefined,\n isDisabled: false,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\nconst textRef = useTemplateRef<HTMLElement>('textRef')\n\n// Register immediately with textValue if provided — this runs at setup time,\n// before mount, so SelectValue shows the correct label for a pre-set modelValue\n// even before the dropdown has ever been opened.\nif (props.textValue !== undefined) {\n ctx.registerItem(props.value, props.textValue)\n}\n\nonMounted(() => {\n // textRef points to the SelectItemText component instance (not a DOM element).\n // Access $el to get the underlying span element and read its text content.\n // This refines the registry entry with actual DOM text (handles slot-text items\n // that don't have an explicit textValue prop).\n const el = (textRef.value as { $el?: HTMLElement } | null)?.$el\n const label = props.textValue ?? el?.textContent?.trim() ?? String(props.value)\n ctx.registerItem(props.value, label)\n})\n</script>\n\n<template>\n <SelectItem\n :value=\"props.value\"\n :disabled=\"props.isDisabled\"\n :text-value=\"props.textValue ?? String(props.value)\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <SelectItemText ref=\"textRef\">\n <slot />\n </SelectItemText>\n <SelectItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\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 </SelectItemIndicator>\n <slot name=\"endContent\" />\n </SelectItem>\n</template>\n"],"mappings":""}
@@ -20,14 +20,14 @@ var SelectItem_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
20
20
  if (props.textValue !== void 0) ctx.registerItem(props.value, props.textValue);
21
21
  onMounted(() => {
22
22
  const el = textRef.value?.$el;
23
- const label = props.textValue ?? el?.textContent?.trim() ?? props.value;
23
+ const label = props.textValue ?? el?.textContent?.trim() ?? String(props.value);
24
24
  ctx.registerItem(props.value, label);
25
25
  });
26
26
  return (_ctx, _cache) => {
27
27
  return openBlock(), createBlock(unref(SelectItem), {
28
28
  value: props.value,
29
29
  disabled: props.isDisabled,
30
- "text-value": props.textValue ?? props.value,
30
+ "text-value": props.textValue ?? String(props.value),
31
31
  class: "list-box-item list-box-item--default",
32
32
  "data-slot": "list-box-item"
33
33
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"SelectItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/SelectItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, useTemplateRef } from 'vue'\nimport { SelectItem, SelectItemText, SelectItemIndicator } from 'reka-ui'\nimport { useSelectInject } from './Select.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n /**\n * Explicit human-readable label for this item. When provided, the registry is\n * populated immediately at setup time (before the dropdown is ever opened),\n * so SelectValue can display the correct label for a pre-set modelValue.\n * When omitted, the label is read from slot DOM text on first mount.\n */\n textValue?: string\n isDisabled?: boolean\n class?: string\n}>(), {\n textValue: undefined,\n isDisabled: false,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\nconst textRef = useTemplateRef<HTMLElement>('textRef')\n\n// Register immediately with textValue if provided — this runs at setup time,\n// before mount, so SelectValue shows the correct label for a pre-set modelValue\n// even before the dropdown has ever been opened.\nif (props.textValue !== undefined) {\n ctx.registerItem(props.value, props.textValue)\n}\n\nonMounted(() => {\n // textRef points to the SelectItemText component instance (not a DOM element).\n // Access $el to get the underlying span element and read its text content.\n // This refines the registry entry with actual DOM text (handles slot-text items\n // that don't have an explicit textValue prop).\n const el = (textRef.value as { $el?: HTMLElement } | null)?.$el\n const label = props.textValue ?? el?.textContent?.trim() ?? props.value\n ctx.registerItem(props.value, label)\n})\n</script>\n\n<template>\n <SelectItem\n :value=\"props.value\"\n :disabled=\"props.isDisabled\"\n :text-value=\"props.textValue ?? props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <SelectItemText ref=\"textRef\">\n <slot />\n </SelectItemText>\n <SelectItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\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 </SelectItemIndicator>\n <slot name=\"endContent\" />\n </SelectItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EAiBd,MAAM,MAAM,iBAAgB;EAC5B,MAAM,UAAU,eAA4B,UAAS;AAKrD,MAAI,MAAM,cAAc,KAAA,EACtB,KAAI,aAAa,MAAM,OAAO,MAAM,UAAS;AAG/C,kBAAgB;GAKd,MAAM,KAAM,QAAQ,OAAwC;GAC5D,MAAM,QAAQ,MAAM,aAAa,IAAI,aAAa,MAAM,IAAI,MAAM;AAClE,OAAI,aAAa,MAAM,OAAO,MAAK;IACpC;;uBAIC,YAkCa,MAAA,WAAA,EAAA;IAjCV,OAAO,MAAM;IACb,UAAU,MAAM;IAChB,cAAY,MAAM,aAAa,MAAM;IACtC,OAAM;IACN,aAAU;;2BAEkB;KAA5B,WAA4B,KAAA,QAAA,eAAA;KAC5B,YAEiB,MAAA,eAAA,EAAA;eAFG;MAAJ,KAAI;;6BACV,CAAR,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA;;;KAEV,YAqBsB,MAAA,oBAAA,EAAA;MApBpB,OAAM;MACN,aAAU;;6BAkBH,CAhBP,WAgBO,KAAA,QAAA,gBAAA,EAAA,QAAA,CAAA,OAAA,OAAA,OAAA,KAfL,mBAcM,OAAA;OAbJ,OAAM;OACN,OAAM;OACN,QAAO;OACP,SAAQ;OACR,MAAK;OACL,QAAO;OACP,gBAAa;OACb,kBAAe;OACf,mBAAgB;OAChB,aAAU;OACV,eAAY;UAEZ,mBAAoC,YAAA,EAA1B,QAAO,kBAAgB,CAAA,CAAA,EAAA,GAAA,EAAA,CAAA,CAAA,CAAA;;;KAIvC,WAA0B,KAAA,QAAA,aAAA"}
1
+ {"version":3,"file":"SelectItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/SelectItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, useTemplateRef } from 'vue'\nimport { SelectItem, SelectItemText, SelectItemIndicator } from 'reka-ui'\nimport { useSelectInject, type SelectItemValue } from './Select.context'\n\nconst props = withDefaults(defineProps<{\n value: SelectItemValue\n /**\n * Explicit human-readable label for this item. When provided, the registry is\n * populated immediately at setup time (before the dropdown is ever opened),\n * so SelectValue can display the correct label for a pre-set modelValue.\n * When omitted, the label is read from slot DOM text on first mount.\n */\n textValue?: string\n isDisabled?: boolean\n class?: string\n}>(), {\n textValue: undefined,\n isDisabled: false,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\nconst textRef = useTemplateRef<HTMLElement>('textRef')\n\n// Register immediately with textValue if provided — this runs at setup time,\n// before mount, so SelectValue shows the correct label for a pre-set modelValue\n// even before the dropdown has ever been opened.\nif (props.textValue !== undefined) {\n ctx.registerItem(props.value, props.textValue)\n}\n\nonMounted(() => {\n // textRef points to the SelectItemText component instance (not a DOM element).\n // Access $el to get the underlying span element and read its text content.\n // This refines the registry entry with actual DOM text (handles slot-text items\n // that don't have an explicit textValue prop).\n const el = (textRef.value as { $el?: HTMLElement } | null)?.$el\n const label = props.textValue ?? el?.textContent?.trim() ?? String(props.value)\n ctx.registerItem(props.value, label)\n})\n</script>\n\n<template>\n <SelectItem\n :value=\"props.value\"\n :disabled=\"props.isDisabled\"\n :text-value=\"props.textValue ?? String(props.value)\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <SelectItemText ref=\"textRef\">\n <slot />\n </SelectItemText>\n <SelectItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\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 </SelectItemIndicator>\n <slot name=\"endContent\" />\n </SelectItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EAiBd,MAAM,MAAM,iBAAgB;EAC5B,MAAM,UAAU,eAA4B,UAAS;AAKrD,MAAI,MAAM,cAAc,KAAA,EACtB,KAAI,aAAa,MAAM,OAAO,MAAM,UAAS;AAG/C,kBAAgB;GAKd,MAAM,KAAM,QAAQ,OAAwC;GAC5D,MAAM,QAAQ,MAAM,aAAa,IAAI,aAAa,MAAM,IAAI,OAAO,MAAM,MAAK;AAC9E,OAAI,aAAa,MAAM,OAAO,MAAK;IACpC;;uBAIC,YAkCa,MAAA,WAAA,EAAA;IAjCV,OAAO,MAAM;IACb,UAAU,MAAM;IAChB,cAAY,MAAM,aAAa,OAAO,MAAM,MAAK;IAClD,OAAM;IACN,aAAU;;2BAEkB;KAA5B,WAA4B,KAAA,QAAA,eAAA;KAC5B,YAEiB,MAAA,eAAA,EAAA;eAFG;MAAJ,KAAI;;6BACV,CAAR,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA;;;KAEV,YAqBsB,MAAA,oBAAA,EAAA;MApBpB,OAAM;MACN,aAAU;;6BAkBH,CAhBP,WAgBO,KAAA,QAAA,gBAAA,EAAA,QAAA,CAAA,OAAA,OAAA,OAAA,KAfL,mBAcM,OAAA;OAbJ,OAAM;OACN,OAAM;OACN,QAAO;OACP,SAAQ;OACR,MAAK;OACL,QAAO;OACP,gBAAa;OACb,kBAAe;OACf,mBAAgB;OAChB,aAAU;OACV,eAAY;UAEZ,mBAAoC,YAAA,EAA1B,QAAO,kBAAgB,CAAA,CAAA,EAAA,GAAA,EAAA,CAAA,CAAA,CAAA;;;KAIvC,WAA0B,KAAA,QAAA,aAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SelectOverflowChips.js","names":[],"sources":["../../../src/components/select/SelectOverflowChips.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, useTemplateRef, onMounted, watch } from 'vue'\nimport { useResizeObserver } from '@vueuse/core'\nimport Chip from '../chip/Chip.vue'\n\nconst props = defineProps<{\n values: string[]\n getLabel: (value: string) => string\n}>()\n\nconst containerEl = useTemplateRef<HTMLElement>('container')\nconst visibleCount = ref(props.values.length)\nconst overflowCount = computed(() => Math.max(0, props.values.length - visibleCount.value))\n\n// Prevents re-entrant reflows while we are in the async measurement phase.\nlet measuring = false\n\nasync function reflow() {\n if (measuring) return\n measuring = true\n\n try {\n const el = containerEl.value\n if (!el) return\n\n // Phase 1: show all chips to measure their natural widths\n visibleCount.value = props.values.length\n await nextTick()\n\n const chips = [...el.querySelectorAll<HTMLElement>('[data-chip-item]')]\n if (!chips.length) return\n\n const containerW = el.offsetWidth\n if (!containerW) return\n\n // BADGE_W = estimated chip width (68px) + CSS gap before it (4px).\n // The sm Chip has px-2 (16px padding) so \"+N more\" fits in ~52–68px.\n const BADGE_W = 76\n\n let usedW = 0\n let n = 0\n\n for (let i = 0; i < chips.length; i++) {\n const gap = i > 0 ? 4 : 0\n const chipW = chips[i].offsetWidth\n const isLast = i === chips.length - 1\n // Last chip: use full budget (no badge needed if everything fits).\n // Earlier chips: reserve BADGE_W so the badge has room when we do overflow.\n const budget = isLast ? containerW : containerW - BADGE_W\n\n if (usedW + gap + chipW > budget) break\n usedW += gap + chipW\n n++\n }\n\n visibleCount.value = Math.max(1, n)\n } finally {\n measuring = false\n }\n}\n\nonMounted(reflow)\nuseResizeObserver(containerEl, reflow)\n\n// Watch a comma-joined string derived from the values — Vue uses Object.is for\n// primitives, so this only fires when the selection actually changes.\n//\n// WHY NOT { deep: true }: Vue's watch fires the callback whenever the effect\n// re-runs when deep=true (because `if (deep || hasChanged)` short-circuits).\n// Reka passes a new array reference for modelValue on every internal re-render\n// (optionsSet updates, dropdown open/close), so a deep or shallow ref watch\n// fires continuously, causing the reflow loop that produces the oscillation.\nwatch(\n () => props.values.join('\\x00'),\n () => reflow(),\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n ref=\"container\"\n style=\"display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; overflow: hidden; flex: 1; min-width: 0;\"\n >\n <Chip\n v-for=\"(val, i) in values\"\n :key=\"val\"\n data-chip-item\n size=\"sm\"\n :style=\"i >= visibleCount ? 'display: none' : undefined\"\n >\n {{ getLabel(val) }}\n </Chip>\n <Chip\n v-if=\"overflowCount > 0\"\n size=\"sm\"\n color=\"default\"\n >\n +{{ overflowCount }} more\n </Chip>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"SelectOverflowChips.js","names":[],"sources":["../../../src/components/select/SelectOverflowChips.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, useTemplateRef, onMounted, watch } from 'vue'\nimport { useResizeObserver } from '@vueuse/core'\nimport Chip from '../chip/Chip.vue'\nimport type { SelectItemValue } from './Select.context'\n\nconst props = defineProps<{\n values: SelectItemValue[]\n getLabel: (value: SelectItemValue) => string\n}>()\n\nconst containerEl = useTemplateRef<HTMLElement>('container')\nconst visibleCount = ref(props.values.length)\nconst overflowCount = computed(() => Math.max(0, props.values.length - visibleCount.value))\n\n// Prevents re-entrant reflows while we are in the async measurement phase.\nlet measuring = false\n\nasync function reflow() {\n if (measuring) return\n measuring = true\n\n try {\n const el = containerEl.value\n if (!el) return\n\n // Phase 1: show all chips to measure their natural widths\n visibleCount.value = props.values.length\n await nextTick()\n\n const chips = [...el.querySelectorAll<HTMLElement>('[data-chip-item]')]\n if (!chips.length) return\n\n const containerW = el.offsetWidth\n if (!containerW) return\n\n // BADGE_W = estimated chip width (68px) + CSS gap before it (4px).\n // The sm Chip has px-2 (16px padding) so \"+N more\" fits in ~52–68px.\n const BADGE_W = 76\n\n let usedW = 0\n let n = 0\n\n for (let i = 0; i < chips.length; i++) {\n const gap = i > 0 ? 4 : 0\n const chipW = chips[i].offsetWidth\n const isLast = i === chips.length - 1\n // Last chip: use full budget (no badge needed if everything fits).\n // Earlier chips: reserve BADGE_W so the badge has room when we do overflow.\n const budget = isLast ? containerW : containerW - BADGE_W\n\n if (usedW + gap + chipW > budget) break\n usedW += gap + chipW\n n++\n }\n\n visibleCount.value = Math.max(1, n)\n } finally {\n measuring = false\n }\n}\n\nonMounted(reflow)\nuseResizeObserver(containerEl, reflow)\n\n// Watch a comma-joined string derived from the values — Vue uses Object.is for\n// primitives, so this only fires when the selection actually changes.\n//\n// WHY NOT { deep: true }: Vue's watch fires the callback whenever the effect\n// re-runs when deep=true (because `if (deep || hasChanged)` short-circuits).\n// Reka passes a new array reference for modelValue on every internal re-render\n// (optionsSet updates, dropdown open/close), so a deep or shallow ref watch\n// fires continuously, causing the reflow loop that produces the oscillation.\nwatch(\n () => props.values.join('\\x00'),\n () => reflow(),\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n ref=\"container\"\n style=\"display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; overflow: hidden; flex: 1; min-width: 0;\"\n >\n <Chip\n v-for=\"(val, i) in values\"\n :key=\"val\"\n data-chip-item\n size=\"sm\"\n :style=\"i >= visibleCount ? 'display: none' : undefined\"\n >\n {{ getLabel(val) }}\n </Chip>\n <Chip\n v-if=\"overflowCount > 0\"\n size=\"sm\"\n color=\"default\"\n >\n +{{ overflowCount }} more\n </Chip>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"SelectOverflowChips.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/SelectOverflowChips.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, useTemplateRef, onMounted, watch } from 'vue'\nimport { useResizeObserver } from '@vueuse/core'\nimport Chip from '../chip/Chip.vue'\n\nconst props = defineProps<{\n values: string[]\n getLabel: (value: string) => string\n}>()\n\nconst containerEl = useTemplateRef<HTMLElement>('container')\nconst visibleCount = ref(props.values.length)\nconst overflowCount = computed(() => Math.max(0, props.values.length - visibleCount.value))\n\n// Prevents re-entrant reflows while we are in the async measurement phase.\nlet measuring = false\n\nasync function reflow() {\n if (measuring) return\n measuring = true\n\n try {\n const el = containerEl.value\n if (!el) return\n\n // Phase 1: show all chips to measure their natural widths\n visibleCount.value = props.values.length\n await nextTick()\n\n const chips = [...el.querySelectorAll<HTMLElement>('[data-chip-item]')]\n if (!chips.length) return\n\n const containerW = el.offsetWidth\n if (!containerW) return\n\n // BADGE_W = estimated chip width (68px) + CSS gap before it (4px).\n // The sm Chip has px-2 (16px padding) so \"+N more\" fits in ~52–68px.\n const BADGE_W = 76\n\n let usedW = 0\n let n = 0\n\n for (let i = 0; i < chips.length; i++) {\n const gap = i > 0 ? 4 : 0\n const chipW = chips[i].offsetWidth\n const isLast = i === chips.length - 1\n // Last chip: use full budget (no badge needed if everything fits).\n // Earlier chips: reserve BADGE_W so the badge has room when we do overflow.\n const budget = isLast ? containerW : containerW - BADGE_W\n\n if (usedW + gap + chipW > budget) break\n usedW += gap + chipW\n n++\n }\n\n visibleCount.value = Math.max(1, n)\n } finally {\n measuring = false\n }\n}\n\nonMounted(reflow)\nuseResizeObserver(containerEl, reflow)\n\n// Watch a comma-joined string derived from the values — Vue uses Object.is for\n// primitives, so this only fires when the selection actually changes.\n//\n// WHY NOT { deep: true }: Vue's watch fires the callback whenever the effect\n// re-runs when deep=true (because `if (deep || hasChanged)` short-circuits).\n// Reka passes a new array reference for modelValue on every internal re-render\n// (optionsSet updates, dropdown open/close), so a deep or shallow ref watch\n// fires continuously, causing the reflow loop that produces the oscillation.\nwatch(\n () => props.values.join('\\x00'),\n () => reflow(),\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n ref=\"container\"\n style=\"display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; overflow: hidden; flex: 1; min-width: 0;\"\n >\n <Chip\n v-for=\"(val, i) in values\"\n :key=\"val\"\n data-chip-item\n size=\"sm\"\n :style=\"i >= visibleCount ? 'display: none' : undefined\"\n >\n {{ getLabel(val) }}\n </Chip>\n <Chip\n v-if=\"overflowCount > 0\"\n size=\"sm\"\n color=\"default\"\n >\n +{{ overflowCount }} more\n </Chip>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EAKd,MAAM,cAAc,eAA4B,YAAW;EAC3D,MAAM,eAAe,IAAI,MAAM,OAAO,OAAM;EAC5C,MAAM,gBAAgB,eAAe,KAAK,IAAI,GAAG,MAAM,OAAO,SAAS,aAAa,MAAM,CAAA;EAG1F,IAAI,YAAY;EAEhB,eAAe,SAAS;AACtB,OAAI,UAAW;AACf,eAAY;AAEZ,OAAI;IACF,MAAM,KAAK,YAAY;AACvB,QAAI,CAAC,GAAI;AAGT,iBAAa,QAAQ,MAAM,OAAO;AAClC,UAAM,UAAS;IAEf,MAAM,QAAQ,CAAC,GAAG,GAAG,iBAA8B,mBAAmB,CAAA;AACtE,QAAI,CAAC,MAAM,OAAQ;IAEnB,MAAM,aAAa,GAAG;AACtB,QAAI,CAAC,WAAY;IAIjB,MAAM,UAAU;IAEhB,IAAI,QAAQ;IACZ,IAAI,IAAI;AAER,SAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;KACrC,MAAM,MAAM,IAAI,IAAI,IAAI;KACxB,MAAM,QAAQ,MAAM,GAAG;KAIvB,MAAM,SAHS,MAAM,MAAM,SAAS,IAGZ,aAAa,aAAa;AAElD,SAAI,QAAQ,MAAM,QAAQ,OAAQ;AAClC,cAAS,MAAM;AACf;;AAGF,iBAAa,QAAQ,KAAK,IAAI,GAAG,EAAC;aAC1B;AACR,gBAAY;;;AAIhB,YAAU,OAAM;AAChB,oBAAkB,aAAa,OAAM;AAUrC,cACQ,MAAM,OAAO,KAAK,KAAO,QACzB,QAAQ,EACd,EAAE,OAAO,QAAQ,CACnB;;uBAIE,mBAoBM,OApBN,YAoBM,EAAA,UAAA,KAAA,EAhBJ,mBAQO,UAAA,MAAA,WAPc,QAAA,SAAX,KAAK,MAAC;wBADhB,YAQO,cAAA;KANJ,KAAK;KACN,kBAAA;KACA,MAAK;KACJ,OAAK,eAAE,KAAK,aAAA,QAAY,kBAAqB,KAAA,EAAS;;4BAEpC,CAAA,gBAAA,gBAAhB,QAAA,SAAS,IAAG,CAAA,EAAA,EAAA,CAAA,CAAA;;;cAGT,cAAA,QAAa,KAAA,WAAA,EADrB,YAMO,cAAA;;IAJL,MAAK;IACL,OAAM;;2BAEL,CAAA,gBADF,OACE,gBAAG,cAAA,MAAa,GAAG,UACtB,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"SelectOverflowChips.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/SelectOverflowChips.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, useTemplateRef, onMounted, watch } from 'vue'\nimport { useResizeObserver } from '@vueuse/core'\nimport Chip from '../chip/Chip.vue'\nimport type { SelectItemValue } from './Select.context'\n\nconst props = defineProps<{\n values: SelectItemValue[]\n getLabel: (value: SelectItemValue) => string\n}>()\n\nconst containerEl = useTemplateRef<HTMLElement>('container')\nconst visibleCount = ref(props.values.length)\nconst overflowCount = computed(() => Math.max(0, props.values.length - visibleCount.value))\n\n// Prevents re-entrant reflows while we are in the async measurement phase.\nlet measuring = false\n\nasync function reflow() {\n if (measuring) return\n measuring = true\n\n try {\n const el = containerEl.value\n if (!el) return\n\n // Phase 1: show all chips to measure their natural widths\n visibleCount.value = props.values.length\n await nextTick()\n\n const chips = [...el.querySelectorAll<HTMLElement>('[data-chip-item]')]\n if (!chips.length) return\n\n const containerW = el.offsetWidth\n if (!containerW) return\n\n // BADGE_W = estimated chip width (68px) + CSS gap before it (4px).\n // The sm Chip has px-2 (16px padding) so \"+N more\" fits in ~52–68px.\n const BADGE_W = 76\n\n let usedW = 0\n let n = 0\n\n for (let i = 0; i < chips.length; i++) {\n const gap = i > 0 ? 4 : 0\n const chipW = chips[i].offsetWidth\n const isLast = i === chips.length - 1\n // Last chip: use full budget (no badge needed if everything fits).\n // Earlier chips: reserve BADGE_W so the badge has room when we do overflow.\n const budget = isLast ? containerW : containerW - BADGE_W\n\n if (usedW + gap + chipW > budget) break\n usedW += gap + chipW\n n++\n }\n\n visibleCount.value = Math.max(1, n)\n } finally {\n measuring = false\n }\n}\n\nonMounted(reflow)\nuseResizeObserver(containerEl, reflow)\n\n// Watch a comma-joined string derived from the values — Vue uses Object.is for\n// primitives, so this only fires when the selection actually changes.\n//\n// WHY NOT { deep: true }: Vue's watch fires the callback whenever the effect\n// re-runs when deep=true (because `if (deep || hasChanged)` short-circuits).\n// Reka passes a new array reference for modelValue on every internal re-render\n// (optionsSet updates, dropdown open/close), so a deep or shallow ref watch\n// fires continuously, causing the reflow loop that produces the oscillation.\nwatch(\n () => props.values.join('\\x00'),\n () => reflow(),\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n ref=\"container\"\n style=\"display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; overflow: hidden; flex: 1; min-width: 0;\"\n >\n <Chip\n v-for=\"(val, i) in values\"\n :key=\"val\"\n data-chip-item\n size=\"sm\"\n :style=\"i >= visibleCount ? 'display: none' : undefined\"\n >\n {{ getLabel(val) }}\n </Chip>\n <Chip\n v-if=\"overflowCount > 0\"\n size=\"sm\"\n color=\"default\"\n >\n +{{ overflowCount }} more\n </Chip>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAMA,MAAM,QAAQ;EAKd,MAAM,cAAc,eAA4B,YAAW;EAC3D,MAAM,eAAe,IAAI,MAAM,OAAO,OAAM;EAC5C,MAAM,gBAAgB,eAAe,KAAK,IAAI,GAAG,MAAM,OAAO,SAAS,aAAa,MAAM,CAAA;EAG1F,IAAI,YAAY;EAEhB,eAAe,SAAS;AACtB,OAAI,UAAW;AACf,eAAY;AAEZ,OAAI;IACF,MAAM,KAAK,YAAY;AACvB,QAAI,CAAC,GAAI;AAGT,iBAAa,QAAQ,MAAM,OAAO;AAClC,UAAM,UAAS;IAEf,MAAM,QAAQ,CAAC,GAAG,GAAG,iBAA8B,mBAAmB,CAAA;AACtE,QAAI,CAAC,MAAM,OAAQ;IAEnB,MAAM,aAAa,GAAG;AACtB,QAAI,CAAC,WAAY;IAIjB,MAAM,UAAU;IAEhB,IAAI,QAAQ;IACZ,IAAI,IAAI;AAER,SAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;KACrC,MAAM,MAAM,IAAI,IAAI,IAAI;KACxB,MAAM,QAAQ,MAAM,GAAG;KAIvB,MAAM,SAHS,MAAM,MAAM,SAAS,IAGZ,aAAa,aAAa;AAElD,SAAI,QAAQ,MAAM,QAAQ,OAAQ;AAClC,cAAS,MAAM;AACf;;AAGF,iBAAa,QAAQ,KAAK,IAAI,GAAG,EAAC;aAC1B;AACR,gBAAY;;;AAIhB,YAAU,OAAM;AAChB,oBAAkB,aAAa,OAAM;AAUrC,cACQ,MAAM,OAAO,KAAK,KAAO,QACzB,QAAQ,EACd,EAAE,OAAO,QAAQ,CACnB;;uBAIE,mBAoBM,OApBN,YAoBM,EAAA,UAAA,KAAA,EAhBJ,mBAQO,UAAA,MAAA,WAPc,QAAA,SAAX,KAAK,MAAC;wBADhB,YAQO,cAAA;KANJ,KAAK;KACN,kBAAA;KACA,MAAK;KACJ,OAAK,eAAE,KAAK,aAAA,QAAY,kBAAqB,KAAA,EAAS;;4BAEpC,CAAA,gBAAA,gBAAhB,QAAA,SAAS,IAAG,CAAA,EAAA,EAAA,CAAA,CAAA;;;cAGT,cAAA,QAAa,KAAA,WAAA,EADrB,YAMO,cAAA;;IAJL,MAAK;IACL,OAAM;;2BAEL,CAAA,gBADF,OACE,gBAAG,cAAA,MAAa,GAAG,UACtB,EAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SelectValue.js","names":[],"sources":["../../../src/components/select/SelectValue.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { SelectValue } from 'reka-ui'\nimport { useSelectInject } from './Select.context'\nimport SelectOverflowChips from './SelectOverflowChips.vue'\n\nconst props = withDefaults(defineProps<{\n placeholder?: string\n class?: string\n}>(), {\n placeholder: undefined,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\n</script>\n\n<template>\n <SelectValue\n :class=\"ctx.slots.value.value()\"\n :placeholder=\"props.placeholder\"\n data-slot=\"value\"\n >\n <template #default=\"{ selectedLabel, modelValue }\">\n <!-- Multiple mode: chips with overflow truncation -->\n <template v-if=\"ctx.multiple.value && Array.isArray(modelValue) && modelValue.length > 0\">\n <SelectOverflowChips\n :values=\"(modelValue as string[])\"\n :get-label=\"ctx.itemLabel\"\n />\n </template>\n <!-- Multiple mode: nothing selected yet -->\n <template v-else-if=\"ctx.multiple.value\">\n {{ props.placeholder }}\n </template>\n <!--\n Single mode label resolution:\n 1. Reka's native selectedLabel — populated via optionsSet once items mount\n 2. itemRegistry label — populated at setup time for items with explicit textValue\n 3. Placeholder when no value is selected\n -->\n <template v-else-if=\"selectedLabel && selectedLabel.length > 0\">\n {{ selectedLabel.join(', ') }}\n </template>\n <template v-else-if=\"modelValue != null && (Array.isArray(modelValue) ? modelValue.length > 0 : modelValue !== '')\">\n {{ ctx.itemLabel(Array.isArray(modelValue) ? modelValue : modelValue.toString()) }}\n </template>\n <template v-else>\n {{ props.placeholder }}\n </template>\n </template>\n </SelectValue>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"SelectValue.js","names":[],"sources":["../../../src/components/select/SelectValue.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { SelectValue } from 'reka-ui'\nimport { useSelectInject, type SelectItemValue } from './Select.context'\nimport SelectOverflowChips from './SelectOverflowChips.vue'\n\nconst props = withDefaults(defineProps<{\n placeholder?: string\n class?: string\n}>(), {\n placeholder: undefined,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\n</script>\n\n<template>\n <SelectValue\n :class=\"ctx.slots.value.value()\"\n :placeholder=\"props.placeholder\"\n data-slot=\"value\"\n >\n <template #default=\"{ selectedLabel, modelValue }\">\n <!-- Multiple mode: chips with overflow truncation -->\n <template v-if=\"ctx.multiple.value && Array.isArray(modelValue) && modelValue.length > 0\">\n <SelectOverflowChips\n :values=\"(modelValue as SelectItemValue[])\"\n :get-label=\"ctx.itemLabel\"\n />\n </template>\n <!-- Multiple mode: nothing selected yet -->\n <template v-else-if=\"ctx.multiple.value\">\n {{ props.placeholder }}\n </template>\n <!--\n Single mode label resolution:\n 1. Reka's native selectedLabel — populated via optionsSet once items mount\n 2. itemRegistry label — populated at setup time for items with explicit textValue\n 3. Placeholder when no value is selected\n -->\n <template v-else-if=\"selectedLabel && selectedLabel.length > 0\">\n {{ selectedLabel.join(', ') }}\n </template>\n <template v-else-if=\"modelValue != null && (Array.isArray(modelValue) ? modelValue.length > 0 : modelValue !== '')\">\n {{ ctx.itemLabel(modelValue as SelectItemValue | SelectItemValue[]) }}\n </template>\n <template v-else>\n {{ props.placeholder }}\n </template>\n </template>\n </SelectValue>\n</template>\n"],"mappings":""}
@@ -22,7 +22,7 @@ var SelectValue_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
22
22
  key: 0,
23
23
  values: modelValue,
24
24
  "get-label": unref(ctx).itemLabel
25
- }, null, 8, ["values", "get-label"])) : unref(ctx).multiple.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createTextVNode(toDisplayString(props.placeholder), 1)], 64)) : selectedLabel && selectedLabel.length > 0 ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createTextVNode(toDisplayString(selectedLabel.join(", ")), 1)], 64)) : modelValue != null && (Array.isArray(modelValue) ? modelValue.length > 0 : modelValue !== "") ? (openBlock(), createElementBlock(Fragment, { key: 3 }, [createTextVNode(toDisplayString(unref(ctx).itemLabel(Array.isArray(modelValue) ? modelValue : modelValue.toString())), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 4 }, [createTextVNode(toDisplayString(props.placeholder), 1)], 64))]),
25
+ }, null, 8, ["values", "get-label"])) : unref(ctx).multiple.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createTextVNode(toDisplayString(props.placeholder), 1)], 64)) : selectedLabel && selectedLabel.length > 0 ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createTextVNode(toDisplayString(selectedLabel.join(", ")), 1)], 64)) : modelValue != null && (Array.isArray(modelValue) ? modelValue.length > 0 : modelValue !== "") ? (openBlock(), createElementBlock(Fragment, { key: 3 }, [createTextVNode(toDisplayString(unref(ctx).itemLabel(modelValue)), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 4 }, [createTextVNode(toDisplayString(props.placeholder), 1)], 64))]),
26
26
  _: 1
27
27
  }, 8, ["class", "placeholder"]);
28
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SelectValue.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/SelectValue.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { SelectValue } from 'reka-ui'\nimport { useSelectInject } from './Select.context'\nimport SelectOverflowChips from './SelectOverflowChips.vue'\n\nconst props = withDefaults(defineProps<{\n placeholder?: string\n class?: string\n}>(), {\n placeholder: undefined,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\n</script>\n\n<template>\n <SelectValue\n :class=\"ctx.slots.value.value()\"\n :placeholder=\"props.placeholder\"\n data-slot=\"value\"\n >\n <template #default=\"{ selectedLabel, modelValue }\">\n <!-- Multiple mode: chips with overflow truncation -->\n <template v-if=\"ctx.multiple.value && Array.isArray(modelValue) && modelValue.length > 0\">\n <SelectOverflowChips\n :values=\"(modelValue as string[])\"\n :get-label=\"ctx.itemLabel\"\n />\n </template>\n <!-- Multiple mode: nothing selected yet -->\n <template v-else-if=\"ctx.multiple.value\">\n {{ props.placeholder }}\n </template>\n <!--\n Single mode label resolution:\n 1. Reka's native selectedLabel — populated via optionsSet once items mount\n 2. itemRegistry label — populated at setup time for items with explicit textValue\n 3. Placeholder when no value is selected\n -->\n <template v-else-if=\"selectedLabel && selectedLabel.length > 0\">\n {{ selectedLabel.join(', ') }}\n </template>\n <template v-else-if=\"modelValue != null && (Array.isArray(modelValue) ? modelValue.length > 0 : modelValue !== '')\">\n {{ ctx.itemLabel(Array.isArray(modelValue) ? modelValue : modelValue.toString()) }}\n </template>\n <template v-else>\n {{ props.placeholder }}\n </template>\n </template>\n </SelectValue>\n</template>\n"],"mappings":";;;;;;;;;;;;EAKA,MAAM,QAAQ;EAQd,MAAM,MAAM,iBAAgB;;uBAI1B,YAiCc,MAAA,YAAA,EAAA;IAhCX,OAAK,eAAE,MAAA,IAAG,CAAC,MAAM,MAAM,OAAK,CAAA;IAC5B,aAAa,MAAM;IACpB,aAAU;;IAEC,SAAO,SAOL,EAPS,eAAe,iBAAU,CAE7B,MAAA,IAAG,CAAC,SAAS,SAAS,MAAM,QAAQ,WAAU,IAAK,WAAW,SAAM,KAAA,WAAA,EAClF,YAGE,6BAAA;;KAFC,QAAS;KACT,aAAW,MAAA,IAAG,CAAC;4CAIC,MAAA,IAAG,CAAC,SAAS,SAAA,WAAA,EAAlC,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,MAAM,YAAW,EAAA,EAAA,CAAA,EAAA,GAAA,IAQD,iBAAiB,cAAc,SAAM,KAAA,WAAA,EAA1D,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,cAAc,KAAI,KAAA,CAAA,EAAA,EAAA,CAAA,EAAA,GAAA,IAEF,cAAU,SAAa,MAAM,QAAQ,WAAU,GAAI,WAAW,SAAM,IAAO,eAAU,OAAA,WAAA,EAA1G,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,MAAA,IAAG,CAAC,UAAU,MAAM,QAAQ,WAAU,GAAI,aAAa,WAAW,UAAQ,CAAA,CAAA,EAAA,EAAA,CAAA,EAAA,GAAA,KAAA,WAAA,EAE/E,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,MAAM,YAAW,EAAA,EAAA,CAAA,EAAA,GAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"SelectValue.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/select/SelectValue.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { SelectValue } from 'reka-ui'\nimport { useSelectInject, type SelectItemValue } from './Select.context'\nimport SelectOverflowChips from './SelectOverflowChips.vue'\n\nconst props = withDefaults(defineProps<{\n placeholder?: string\n class?: string\n}>(), {\n placeholder: undefined,\n class: undefined,\n})\n\nconst ctx = useSelectInject()\n</script>\n\n<template>\n <SelectValue\n :class=\"ctx.slots.value.value()\"\n :placeholder=\"props.placeholder\"\n data-slot=\"value\"\n >\n <template #default=\"{ selectedLabel, modelValue }\">\n <!-- Multiple mode: chips with overflow truncation -->\n <template v-if=\"ctx.multiple.value && Array.isArray(modelValue) && modelValue.length > 0\">\n <SelectOverflowChips\n :values=\"(modelValue as SelectItemValue[])\"\n :get-label=\"ctx.itemLabel\"\n />\n </template>\n <!-- Multiple mode: nothing selected yet -->\n <template v-else-if=\"ctx.multiple.value\">\n {{ props.placeholder }}\n </template>\n <!--\n Single mode label resolution:\n 1. Reka's native selectedLabel — populated via optionsSet once items mount\n 2. itemRegistry label — populated at setup time for items with explicit textValue\n 3. Placeholder when no value is selected\n -->\n <template v-else-if=\"selectedLabel && selectedLabel.length > 0\">\n {{ selectedLabel.join(', ') }}\n </template>\n <template v-else-if=\"modelValue != null && (Array.isArray(modelValue) ? modelValue.length > 0 : modelValue !== '')\">\n {{ ctx.itemLabel(modelValue as SelectItemValue | SelectItemValue[]) }}\n </template>\n <template v-else>\n {{ props.placeholder }}\n </template>\n </template>\n </SelectValue>\n</template>\n"],"mappings":";;;;;;;;;;;;EAKA,MAAM,QAAQ;EAQd,MAAM,MAAM,iBAAgB;;uBAI1B,YAiCc,MAAA,YAAA,EAAA;IAhCX,OAAK,eAAE,MAAA,IAAG,CAAC,MAAM,MAAM,OAAK,CAAA;IAC5B,aAAa,MAAM;IACpB,aAAU;;IAEC,SAAO,SAOL,EAPS,eAAe,iBAAU,CAE7B,MAAA,IAAG,CAAC,SAAS,SAAS,MAAM,QAAQ,WAAU,IAAK,WAAW,SAAM,KAAA,WAAA,EAClF,YAGE,6BAAA;;KAFC,QAAS;KACT,aAAW,MAAA,IAAG,CAAC;4CAIC,MAAA,IAAG,CAAC,SAAS,SAAA,WAAA,EAAlC,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,MAAM,YAAW,EAAA,EAAA,CAAA,EAAA,GAAA,IAQD,iBAAiB,cAAc,SAAM,KAAA,WAAA,EAA1D,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,cAAc,KAAI,KAAA,CAAA,EAAA,EAAA,CAAA,EAAA,GAAA,IAEF,cAAU,SAAa,MAAM,QAAQ,WAAU,GAAI,WAAW,SAAM,IAAO,eAAU,OAAA,WAAA,EAA1G,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,MAAA,IAAG,CAAC,UAAU,WAAU,CAAA,EAAA,EAAA,CAAA,EAAA,GAAA,KAAA,WAAA,EAE7B,mBAEW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,gBAAA,gBADN,MAAM,YAAW,EAAA,EAAA,CAAA,EAAA,GAAA,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, onMounted, watch } from 'vue'\nimport { useTemplateRef } from 'vue'\nimport { TabsList } from 'reka-ui'\nimport { useResizeObserver, onClickOutside } from '@vueuse/core'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\nimport Button from '../button/Button.vue'\n\nconst props = defineProps<{\n loop?: boolean\n overflow?: 'arrows' | 'dropdown'\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n\n// ── Arrows mode ─────────────────────────────────────────────────────────────\nconst scrollWrapperEl = useTemplateRef<HTMLElement>('scrollWrapperEl')\nconst canScrollLeft = ref(false)\nconst canScrollRight = ref(false)\n\nfunction updateScrollButtons() {\n const el = scrollWrapperEl.value\n if (!el) { canScrollLeft.value = false; canScrollRight.value = false; return }\n canScrollLeft.value = el.scrollLeft > 1\n canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction scrollTabs(dir: 'left' | 'right') {\n const el = scrollWrapperEl.value\n if (!el) return\n el.scrollBy({ left: dir === 'left' ? -200 : 200, behavior: 'smooth' })\n // Poll briefly after smooth scroll starts so button states update\n setTimeout(updateScrollButtons, 150)\n setTimeout(updateScrollButtons, 350)\n}\n\nwatch(scrollWrapperEl, (el, oldEl) => {\n if (oldEl) oldEl.removeEventListener('scroll', updateScrollButtons)\n if (el) {\n el.addEventListener('scroll', updateScrollButtons, { passive: true })\n nextTick(updateScrollButtons)\n }\n}, { immediate: true })\n\nuseResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons))\n\n// ── Dropdown mode ────────────────────────────────────────────────────────────\ninterface OverflowTab {\n value: string\n label: string\n disabled: boolean\n}\n\nconst containerEl = useTemplateRef<HTMLElement>('containerEl')\n// Button component ref — use .$el to reach the underlying DOM element for offsetWidth\nconst moreBtnEl = useTemplateRef<InstanceType<typeof Button>>('moreBtnEl')\nconst dropdownEl = useTemplateRef<HTMLElement>('dropdownEl')\n\nconst hiddenTabs = ref<OverflowTab[]>([])\nconst dropdownOpen = ref(false)\nconst hasOverflow = computed(() => hiddenTabs.value.length > 0)\n// Pre-measured natural width of the more button (measured once on mount before it's visible)\nlet moreBtnNaturalWidth = 48\n\nonClickOutside(dropdownEl, () => { dropdownOpen.value = false })\n\nfunction computeOverflow() {\n if (!containerEl.value) return\n\n const allTabs = Array.from(\n containerEl.value.querySelectorAll('[data-tab-value]'),\n ) as HTMLElement[]\n\n // Reveal all tabs first\n allTabs.forEach(t => t.removeAttribute('data-overflow-hidden'))\n\n // Tabs use w-full and shrink to share the container width, so offsetWidth after\n // a normal render would be containerWidth/n — useless for overflow detection.\n // Force each tab to its natural content width for measurement only (no paint flash:\n // all DOM reads/writes happen synchronously within this JS task before the next frame).\n const listEl = containerEl.value.querySelector('[role=\"tablist\"]') as HTMLElement | null\n if (listEl) {\n listEl.style.overflow = 'visible'\n allTabs.forEach(t => { t.style.flexShrink = '0'; t.style.width = 'auto' })\n void listEl.offsetWidth // force reflow so offsetWidth reads below are accurate\n }\n\n const containerWidth = containerEl.value.clientWidth\n const tabWidths = allTabs.map(t => t.offsetWidth)\n const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0)\n\n // Restore layout before any early-return so tabs always look correct\n if (listEl) {\n listEl.style.overflow = ''\n allTabs.forEach(t => { t.style.flexShrink = ''; t.style.width = '' })\n }\n\n if (totalWidth <= containerWidth) {\n hiddenTabs.value = []\n return\n }\n\n // More button is in-flow (display:none when no overflow, display:flex when visible).\n // Use the pre-measured natural width so the calculation is accurate on the first run\n // before the button becomes visible.\n const available = containerWidth - moreBtnNaturalWidth\n\n let accumulated = 0\n const newHidden: OverflowTab[] = []\n const visibleEls: HTMLElement[] = []\n\n for (let i = 0; i < allTabs.length; i++) {\n const tab = allTabs[i]\n const w = tabWidths[i]\n if (accumulated + w <= available) {\n accumulated += w\n visibleEls.push(tab)\n } else {\n newHidden.push({\n value: tab.getAttribute('data-tab-value') ?? '',\n label: tab.textContent?.trim() ?? '',\n disabled: tab.hasAttribute('data-disabled') || tab.getAttribute('aria-disabled') === 'true',\n })\n tab.setAttribute('data-overflow-hidden', '')\n }\n }\n\n // If the active tab ended up hidden, swap it with the last visible tab\n const activeValue = ctx.currentValue.value\n if (activeValue) {\n const hiddenActiveIdx = newHidden.findIndex(t => t.value === activeValue)\n if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {\n const displacedEl = visibleEls[visibleEls.length - 1]\n const activeEl = allTabs.find(t => t.getAttribute('data-tab-value') === activeValue)\n\n if (displacedEl && activeEl) {\n // Swap: make displaced tab hidden, active tab visible\n displacedEl.setAttribute('data-overflow-hidden', '')\n activeEl.removeAttribute('data-overflow-hidden')\n\n const displaced: OverflowTab = {\n value: displacedEl.getAttribute('data-tab-value') ?? '',\n label: displacedEl.textContent?.trim() ?? '',\n disabled: displacedEl.hasAttribute('data-disabled') || displacedEl.getAttribute('aria-disabled') === 'true',\n }\n newHidden.splice(hiddenActiveIdx, 1)\n newHidden.unshift(displaced)\n }\n }\n }\n\n hiddenTabs.value = newHidden\n}\n\nuseResizeObserver(containerEl, () => nextTick(computeOverflow))\nonMounted(() => {\n // Pre-measure the more button's natural width before it becomes visible (display:none).\n // Temporarily show it, read offsetWidth, then hide again — happens before first paint.\n const btnEl = (moreBtnEl.value as InstanceType<typeof Button> | null)?.$el as HTMLElement | null\n if (btnEl) {\n btnEl.style.display = 'flex'\n void btnEl.offsetWidth\n moreBtnNaturalWidth = btnEl.offsetWidth\n btnEl.style.display = ''\n }\n nextTick(computeOverflow)\n})\n\n// Recompute when the active tab changes so the active tab is always visible\nwatch(() => ctx.currentValue.value, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\n// When overflow state first transitions false→true the more button enters the flex flow,\n// narrowing the container. Re-run once so the tab count reflects the reduced available space.\nwatch(hasOverflow, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\nfunction selectOverflowTab(value: string) {\n ctx.changeTab(value)\n dropdownOpen.value = false\n}\n</script>\n\n<template>\n <!-- ── Default (no overflow behaviour) ───────────────────────────────────── -->\n <TabsList\n v-if=\"!props.overflow\"\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n class=\"tabs__list-container tabs__list-container--arrows\"\n :class=\"{ 'has-left': canScrollLeft, 'has-right': canScrollRight }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--left', canScrollLeft && 'is-visible')\"\n aria-label=\"Scroll tabs left\"\n tabindex=\"-1\"\n @click=\"scrollTabs('left')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M9 11L5 7L9 3\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div ref=\"scrollWrapperEl\" class=\"tabs__scroll-wrapper\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class)\"\n >\n <slot />\n </TabsList>\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--right', canScrollRight && 'is-visible')\"\n aria-label=\"Scroll tabs right\"\n tabindex=\"-1\"\n @click=\"scrollTabs('right')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5 3L9 7L5 11\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n </div>\n\n <!-- ── Dropdown mode ──────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'dropdown'\"\n ref=\"containerEl\"\n class=\"tabs__list-container tabs__list-container--dropdown\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n class=\"tabs__more\"\n :class=\"{ 'tabs__more--visible': hasOverflow }\"\n >\n <Button\n ref=\"moreBtnEl\"\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n class=\"tabs__more-btn\"\n :aria-expanded=\"dropdownOpen\"\n aria-haspopup=\"menu\"\n @click=\"dropdownOpen = !dropdownOpen\"\n >\n +{{ hiddenTabs.length }}\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 4L6 8L10 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div v-if=\"dropdownOpen\" class=\"tabs__overflow-menu\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n class=\"tabs__overflow-item\"\n role=\"menuitem\"\n :disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TabList.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, onMounted, watch } from 'vue'\nimport { useTemplateRef } from 'vue'\nimport { TabsList } from 'reka-ui'\nimport { useResizeObserver, onClickOutside } from '@vueuse/core'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\nimport Button from '../button/Button.vue'\n\nconst props = defineProps<{\n loop?: boolean\n overflow?: 'arrows' | 'dropdown'\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n\n// ── Arrows mode ─────────────────────────────────────────────────────────────\nconst scrollWrapperEl = useTemplateRef<HTMLElement>('scrollWrapperEl')\nconst canScrollLeft = ref(false)\nconst canScrollRight = ref(false)\n\nfunction updateScrollButtons() {\n const el = scrollWrapperEl.value\n if (!el) { canScrollLeft.value = false; canScrollRight.value = false; return }\n canScrollLeft.value = el.scrollLeft > 1\n canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction scrollTabs(dir: 'left' | 'right') {\n const el = scrollWrapperEl.value\n if (!el) return\n el.scrollBy({ left: dir === 'left' ? -200 : 200, behavior: 'smooth' })\n // Poll briefly after smooth scroll starts so button states update\n setTimeout(updateScrollButtons, 150)\n setTimeout(updateScrollButtons, 350)\n}\n\nwatch(scrollWrapperEl, (el, oldEl) => {\n if (oldEl) oldEl.removeEventListener('scroll', updateScrollButtons)\n if (el) {\n el.addEventListener('scroll', updateScrollButtons, { passive: true })\n nextTick(updateScrollButtons)\n }\n}, { immediate: true })\n\nuseResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons))\n\n// ── Dropdown mode ────────────────────────────────────────────────────────────\ninterface OverflowTab {\n value: string\n label: string\n disabled: boolean\n}\n\nconst containerEl = useTemplateRef<HTMLElement>('containerEl')\nconst dropdownEl = useTemplateRef<HTMLElement>('dropdownEl')\n\nconst hiddenTabs = ref<OverflowTab[]>([])\nconst dropdownOpen = ref(false)\nconst hasOverflow = computed(() => hiddenTabs.value.length > 0)\n\nonClickOutside(dropdownEl, () => { dropdownOpen.value = false })\n\nfunction computeOverflow() {\n if (!containerEl.value) return\n\n const allTabs = Array.from(\n containerEl.value.querySelectorAll('[data-tab-value]'),\n ) as HTMLElement[]\n\n // Reveal all tabs first\n allTabs.forEach(t => t.removeAttribute('data-overflow-hidden'))\n\n // Tabs use w-full and shrink to share the container width, so offsetWidth after\n // a normal render would be containerWidth/n — useless for overflow detection.\n // Force each tab to its natural content width for measurement only (no paint flash:\n // all DOM reads/writes happen synchronously within this JS task before the next frame).\n const listEl = containerEl.value.querySelector('[role=\"tablist\"]') as HTMLElement | null\n if (listEl) {\n listEl.style.overflow = 'visible'\n allTabs.forEach(t => { t.style.flexShrink = '0'; t.style.width = 'auto' })\n void listEl.offsetWidth // force reflow so offsetWidth reads below are accurate\n }\n\n // Measure the more button's real width by temporarily revealing its wrapper.\n // The wrapper is display:none when there's no overflow, so we can't rely on a\n // pre-measured value — measure it here while the (always-visible) container holds it.\n let moreWidth = 0\n const moreEl = dropdownEl.value\n if (moreEl) {\n const prevDisplay = moreEl.style.display\n moreEl.style.display = 'flex'\n void moreEl.offsetWidth\n moreWidth = moreEl.offsetWidth\n moreEl.style.display = prevDisplay\n }\n\n // clientWidth includes the container's horizontal padding; the flex children only\n // get the content box. Subtract padding so measurements compare against real space.\n const cs = getComputedStyle(containerEl.value)\n const padX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight)\n const gap = parseFloat(cs.columnGap) || 0\n const contentWidth = containerEl.value.clientWidth - padX\n\n const tabWidths = allTabs.map(t => t.offsetWidth)\n const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0)\n\n // Restore layout before any early-return so tabs always look correct\n if (listEl) {\n listEl.style.overflow = ''\n allTabs.forEach(t => { t.style.flexShrink = ''; t.style.width = '' })\n }\n\n if (totalWidth <= contentWidth) {\n hiddenTabs.value = []\n return\n }\n\n // When the more button is shown it sits beside the clipped list, separated by `gap`.\n // Reserve its width + the gap (+1px sub-pixel safety) so the last visible tab can\n // never extend under the button.\n const available = contentWidth - moreWidth - gap - 1\n\n let accumulated = 0\n const newHidden: OverflowTab[] = []\n const visibleEls: HTMLElement[] = []\n\n for (let i = 0; i < allTabs.length; i++) {\n const tab = allTabs[i]\n const w = tabWidths[i]\n if (accumulated + w <= available) {\n accumulated += w\n visibleEls.push(tab)\n } else {\n newHidden.push({\n value: tab.getAttribute('data-tab-value') ?? '',\n label: tab.textContent?.trim() ?? '',\n disabled: tab.hasAttribute('data-disabled') || tab.getAttribute('aria-disabled') === 'true',\n })\n tab.setAttribute('data-overflow-hidden', '')\n }\n }\n\n // If the active tab ended up hidden, swap it with the last visible tab\n const activeValue = ctx.currentValue.value\n if (activeValue) {\n const hiddenActiveIdx = newHidden.findIndex(t => t.value === activeValue)\n if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {\n const displacedEl = visibleEls[visibleEls.length - 1]\n const activeEl = allTabs.find(t => t.getAttribute('data-tab-value') === activeValue)\n\n if (displacedEl && activeEl) {\n // Swap: make displaced tab hidden, active tab visible\n displacedEl.setAttribute('data-overflow-hidden', '')\n activeEl.removeAttribute('data-overflow-hidden')\n\n const displaced: OverflowTab = {\n value: displacedEl.getAttribute('data-tab-value') ?? '',\n label: displacedEl.textContent?.trim() ?? '',\n disabled: displacedEl.hasAttribute('data-disabled') || displacedEl.getAttribute('aria-disabled') === 'true',\n }\n newHidden.splice(hiddenActiveIdx, 1)\n newHidden.unshift(displaced)\n }\n }\n }\n\n hiddenTabs.value = newHidden\n}\n\nuseResizeObserver(containerEl, () => nextTick(computeOverflow))\nonMounted(() => {\n nextTick(computeOverflow)\n})\n\n// Recompute when the active tab changes so the active tab is always visible\nwatch(() => ctx.currentValue.value, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\n// Safety re-check when overflow toggles. computeOverflow already reserves the more\n// button's width up front, so this is idempotent — it just guards against layout\n// settling (e.g. a scrollbar appearing) on the false→true transition.\nwatch(hasOverflow, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\nfunction selectOverflowTab(value: string) {\n ctx.changeTab(value)\n dropdownOpen.value = false\n}\n</script>\n\n<template>\n <!-- ── Default (no overflow behaviour) ───────────────────────────────────── -->\n <TabsList\n v-if=\"!props.overflow\"\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n class=\"tabs__list-container tabs__list-container--arrows\"\n :class=\"{ 'has-left': canScrollLeft, 'has-right': canScrollRight }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--left', canScrollLeft && 'is-visible')\"\n aria-label=\"Scroll tabs left\"\n tabindex=\"-1\"\n @click=\"scrollTabs('left')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M9 11L5 7L9 3\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div ref=\"scrollWrapperEl\" class=\"tabs__scroll-wrapper\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class)\"\n >\n <slot />\n </TabsList>\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--right', canScrollRight && 'is-visible')\"\n aria-label=\"Scroll tabs right\"\n tabindex=\"-1\"\n @click=\"scrollTabs('right')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5 3L9 7L5 11\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n </div>\n\n <!-- ── Dropdown mode ──────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'dropdown'\"\n ref=\"containerEl\"\n class=\"tabs__list-container tabs__list-container--dropdown\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n class=\"tabs__more\"\n :class=\"{ 'tabs__more--visible': hasOverflow }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n class=\"tabs__more-btn\"\n :aria-expanded=\"dropdownOpen\"\n aria-haspopup=\"menu\"\n @click=\"dropdownOpen = !dropdownOpen\"\n >\n +{{ hiddenTabs.length }}\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 4L6 8L10 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div v-if=\"dropdownOpen\" class=\"tabs__overflow-menu\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n class=\"tabs__overflow-item\"\n role=\"menuitem\"\n :disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -52,12 +52,10 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
52
52
  }, { immediate: true });
53
53
  useResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons));
54
54
  const containerEl = useTemplateRef("containerEl");
55
- const moreBtnEl = useTemplateRef("moreBtnEl");
56
55
  const dropdownEl = useTemplateRef("dropdownEl");
57
56
  const hiddenTabs = ref([]);
58
57
  const dropdownOpen = ref(false);
59
58
  const hasOverflow = computed(() => hiddenTabs.value.length > 0);
60
- let moreBtnNaturalWidth = 48;
61
59
  onClickOutside(dropdownEl, () => {
62
60
  dropdownOpen.value = false;
63
61
  });
@@ -74,7 +72,19 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
74
72
  });
75
73
  listEl.offsetWidth;
76
74
  }
77
- const containerWidth = containerEl.value.clientWidth;
75
+ let moreWidth = 0;
76
+ const moreEl = dropdownEl.value;
77
+ if (moreEl) {
78
+ const prevDisplay = moreEl.style.display;
79
+ moreEl.style.display = "flex";
80
+ moreEl.offsetWidth;
81
+ moreWidth = moreEl.offsetWidth;
82
+ moreEl.style.display = prevDisplay;
83
+ }
84
+ const cs = getComputedStyle(containerEl.value);
85
+ const padX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
86
+ const gap = parseFloat(cs.columnGap) || 0;
87
+ const contentWidth = containerEl.value.clientWidth - padX;
78
88
  const tabWidths = allTabs.map((t) => t.offsetWidth);
79
89
  const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0);
80
90
  if (listEl) {
@@ -84,11 +94,11 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
84
94
  t.style.width = "";
85
95
  });
86
96
  }
87
- if (totalWidth <= containerWidth) {
97
+ if (totalWidth <= contentWidth) {
88
98
  hiddenTabs.value = [];
89
99
  return;
90
100
  }
91
- const available = containerWidth - moreBtnNaturalWidth;
101
+ const available = contentWidth - moreWidth - gap - 1;
92
102
  let accumulated = 0;
93
103
  const newHidden = [];
94
104
  const visibleEls = [];
@@ -130,13 +140,6 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
130
140
  }
131
141
  useResizeObserver(containerEl, () => nextTick(computeOverflow));
132
142
  onMounted(() => {
133
- const btnEl = moreBtnEl.value?.$el;
134
- if (btnEl) {
135
- btnEl.style.display = "flex";
136
- btnEl.offsetWidth;
137
- moreBtnNaturalWidth = btnEl.offsetWidth;
138
- btnEl.style.display = "";
139
- }
140
143
  nextTick(computeOverflow);
141
144
  });
142
145
  watch(() => ctx.currentValue.value, () => {
@@ -241,8 +244,6 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
241
244
  ref: dropdownEl,
242
245
  class: normalizeClass(["tabs__more", { "tabs__more--visible": hasOverflow.value }])
243
246
  }, [createVNode(Button_default, {
244
- ref_key: "moreBtnEl",
245
- ref: moreBtnEl,
246
247
  variant: "secondary",
247
248
  size: "sm",
248
249
  radius: "full",
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, onMounted, watch } from 'vue'\nimport { useTemplateRef } from 'vue'\nimport { TabsList } from 'reka-ui'\nimport { useResizeObserver, onClickOutside } from '@vueuse/core'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\nimport Button from '../button/Button.vue'\n\nconst props = defineProps<{\n loop?: boolean\n overflow?: 'arrows' | 'dropdown'\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n\n// ── Arrows mode ─────────────────────────────────────────────────────────────\nconst scrollWrapperEl = useTemplateRef<HTMLElement>('scrollWrapperEl')\nconst canScrollLeft = ref(false)\nconst canScrollRight = ref(false)\n\nfunction updateScrollButtons() {\n const el = scrollWrapperEl.value\n if (!el) { canScrollLeft.value = false; canScrollRight.value = false; return }\n canScrollLeft.value = el.scrollLeft > 1\n canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction scrollTabs(dir: 'left' | 'right') {\n const el = scrollWrapperEl.value\n if (!el) return\n el.scrollBy({ left: dir === 'left' ? -200 : 200, behavior: 'smooth' })\n // Poll briefly after smooth scroll starts so button states update\n setTimeout(updateScrollButtons, 150)\n setTimeout(updateScrollButtons, 350)\n}\n\nwatch(scrollWrapperEl, (el, oldEl) => {\n if (oldEl) oldEl.removeEventListener('scroll', updateScrollButtons)\n if (el) {\n el.addEventListener('scroll', updateScrollButtons, { passive: true })\n nextTick(updateScrollButtons)\n }\n}, { immediate: true })\n\nuseResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons))\n\n// ── Dropdown mode ────────────────────────────────────────────────────────────\ninterface OverflowTab {\n value: string\n label: string\n disabled: boolean\n}\n\nconst containerEl = useTemplateRef<HTMLElement>('containerEl')\n// Button component ref — use .$el to reach the underlying DOM element for offsetWidth\nconst moreBtnEl = useTemplateRef<InstanceType<typeof Button>>('moreBtnEl')\nconst dropdownEl = useTemplateRef<HTMLElement>('dropdownEl')\n\nconst hiddenTabs = ref<OverflowTab[]>([])\nconst dropdownOpen = ref(false)\nconst hasOverflow = computed(() => hiddenTabs.value.length > 0)\n// Pre-measured natural width of the more button (measured once on mount before it's visible)\nlet moreBtnNaturalWidth = 48\n\nonClickOutside(dropdownEl, () => { dropdownOpen.value = false })\n\nfunction computeOverflow() {\n if (!containerEl.value) return\n\n const allTabs = Array.from(\n containerEl.value.querySelectorAll('[data-tab-value]'),\n ) as HTMLElement[]\n\n // Reveal all tabs first\n allTabs.forEach(t => t.removeAttribute('data-overflow-hidden'))\n\n // Tabs use w-full and shrink to share the container width, so offsetWidth after\n // a normal render would be containerWidth/n — useless for overflow detection.\n // Force each tab to its natural content width for measurement only (no paint flash:\n // all DOM reads/writes happen synchronously within this JS task before the next frame).\n const listEl = containerEl.value.querySelector('[role=\"tablist\"]') as HTMLElement | null\n if (listEl) {\n listEl.style.overflow = 'visible'\n allTabs.forEach(t => { t.style.flexShrink = '0'; t.style.width = 'auto' })\n void listEl.offsetWidth // force reflow so offsetWidth reads below are accurate\n }\n\n const containerWidth = containerEl.value.clientWidth\n const tabWidths = allTabs.map(t => t.offsetWidth)\n const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0)\n\n // Restore layout before any early-return so tabs always look correct\n if (listEl) {\n listEl.style.overflow = ''\n allTabs.forEach(t => { t.style.flexShrink = ''; t.style.width = '' })\n }\n\n if (totalWidth <= containerWidth) {\n hiddenTabs.value = []\n return\n }\n\n // More button is in-flow (display:none when no overflow, display:flex when visible).\n // Use the pre-measured natural width so the calculation is accurate on the first run\n // before the button becomes visible.\n const available = containerWidth - moreBtnNaturalWidth\n\n let accumulated = 0\n const newHidden: OverflowTab[] = []\n const visibleEls: HTMLElement[] = []\n\n for (let i = 0; i < allTabs.length; i++) {\n const tab = allTabs[i]\n const w = tabWidths[i]\n if (accumulated + w <= available) {\n accumulated += w\n visibleEls.push(tab)\n } else {\n newHidden.push({\n value: tab.getAttribute('data-tab-value') ?? '',\n label: tab.textContent?.trim() ?? '',\n disabled: tab.hasAttribute('data-disabled') || tab.getAttribute('aria-disabled') === 'true',\n })\n tab.setAttribute('data-overflow-hidden', '')\n }\n }\n\n // If the active tab ended up hidden, swap it with the last visible tab\n const activeValue = ctx.currentValue.value\n if (activeValue) {\n const hiddenActiveIdx = newHidden.findIndex(t => t.value === activeValue)\n if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {\n const displacedEl = visibleEls[visibleEls.length - 1]\n const activeEl = allTabs.find(t => t.getAttribute('data-tab-value') === activeValue)\n\n if (displacedEl && activeEl) {\n // Swap: make displaced tab hidden, active tab visible\n displacedEl.setAttribute('data-overflow-hidden', '')\n activeEl.removeAttribute('data-overflow-hidden')\n\n const displaced: OverflowTab = {\n value: displacedEl.getAttribute('data-tab-value') ?? '',\n label: displacedEl.textContent?.trim() ?? '',\n disabled: displacedEl.hasAttribute('data-disabled') || displacedEl.getAttribute('aria-disabled') === 'true',\n }\n newHidden.splice(hiddenActiveIdx, 1)\n newHidden.unshift(displaced)\n }\n }\n }\n\n hiddenTabs.value = newHidden\n}\n\nuseResizeObserver(containerEl, () => nextTick(computeOverflow))\nonMounted(() => {\n // Pre-measure the more button's natural width before it becomes visible (display:none).\n // Temporarily show it, read offsetWidth, then hide again — happens before first paint.\n const btnEl = (moreBtnEl.value as InstanceType<typeof Button> | null)?.$el as HTMLElement | null\n if (btnEl) {\n btnEl.style.display = 'flex'\n void btnEl.offsetWidth\n moreBtnNaturalWidth = btnEl.offsetWidth\n btnEl.style.display = ''\n }\n nextTick(computeOverflow)\n})\n\n// Recompute when the active tab changes so the active tab is always visible\nwatch(() => ctx.currentValue.value, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\n// When overflow state first transitions false→true the more button enters the flex flow,\n// narrowing the container. Re-run once so the tab count reflects the reduced available space.\nwatch(hasOverflow, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\nfunction selectOverflowTab(value: string) {\n ctx.changeTab(value)\n dropdownOpen.value = false\n}\n</script>\n\n<template>\n <!-- ── Default (no overflow behaviour) ───────────────────────────────────── -->\n <TabsList\n v-if=\"!props.overflow\"\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n class=\"tabs__list-container tabs__list-container--arrows\"\n :class=\"{ 'has-left': canScrollLeft, 'has-right': canScrollRight }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--left', canScrollLeft && 'is-visible')\"\n aria-label=\"Scroll tabs left\"\n tabindex=\"-1\"\n @click=\"scrollTabs('left')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M9 11L5 7L9 3\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div ref=\"scrollWrapperEl\" class=\"tabs__scroll-wrapper\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class)\"\n >\n <slot />\n </TabsList>\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--right', canScrollRight && 'is-visible')\"\n aria-label=\"Scroll tabs right\"\n tabindex=\"-1\"\n @click=\"scrollTabs('right')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5 3L9 7L5 11\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n </div>\n\n <!-- ── Dropdown mode ──────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'dropdown'\"\n ref=\"containerEl\"\n class=\"tabs__list-container tabs__list-container--dropdown\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n class=\"tabs__more\"\n :class=\"{ 'tabs__more--visible': hasOverflow }\"\n >\n <Button\n ref=\"moreBtnEl\"\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n class=\"tabs__more-btn\"\n :aria-expanded=\"dropdownOpen\"\n aria-haspopup=\"menu\"\n @click=\"dropdownOpen = !dropdownOpen\"\n >\n +{{ hiddenTabs.length }}\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 4L6 8L10 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div v-if=\"dropdownOpen\" class=\"tabs__overflow-menu\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n class=\"tabs__overflow-item\"\n role=\"menuitem\"\n :disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TabList.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, onMounted, watch } from 'vue'\nimport { useTemplateRef } from 'vue'\nimport { TabsList } from 'reka-ui'\nimport { useResizeObserver, onClickOutside } from '@vueuse/core'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\nimport Button from '../button/Button.vue'\n\nconst props = defineProps<{\n loop?: boolean\n overflow?: 'arrows' | 'dropdown'\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n\n// ── Arrows mode ─────────────────────────────────────────────────────────────\nconst scrollWrapperEl = useTemplateRef<HTMLElement>('scrollWrapperEl')\nconst canScrollLeft = ref(false)\nconst canScrollRight = ref(false)\n\nfunction updateScrollButtons() {\n const el = scrollWrapperEl.value\n if (!el) { canScrollLeft.value = false; canScrollRight.value = false; return }\n canScrollLeft.value = el.scrollLeft > 1\n canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction scrollTabs(dir: 'left' | 'right') {\n const el = scrollWrapperEl.value\n if (!el) return\n el.scrollBy({ left: dir === 'left' ? -200 : 200, behavior: 'smooth' })\n // Poll briefly after smooth scroll starts so button states update\n setTimeout(updateScrollButtons, 150)\n setTimeout(updateScrollButtons, 350)\n}\n\nwatch(scrollWrapperEl, (el, oldEl) => {\n if (oldEl) oldEl.removeEventListener('scroll', updateScrollButtons)\n if (el) {\n el.addEventListener('scroll', updateScrollButtons, { passive: true })\n nextTick(updateScrollButtons)\n }\n}, { immediate: true })\n\nuseResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons))\n\n// ── Dropdown mode ────────────────────────────────────────────────────────────\ninterface OverflowTab {\n value: string\n label: string\n disabled: boolean\n}\n\nconst containerEl = useTemplateRef<HTMLElement>('containerEl')\nconst dropdownEl = useTemplateRef<HTMLElement>('dropdownEl')\n\nconst hiddenTabs = ref<OverflowTab[]>([])\nconst dropdownOpen = ref(false)\nconst hasOverflow = computed(() => hiddenTabs.value.length > 0)\n\nonClickOutside(dropdownEl, () => { dropdownOpen.value = false })\n\nfunction computeOverflow() {\n if (!containerEl.value) return\n\n const allTabs = Array.from(\n containerEl.value.querySelectorAll('[data-tab-value]'),\n ) as HTMLElement[]\n\n // Reveal all tabs first\n allTabs.forEach(t => t.removeAttribute('data-overflow-hidden'))\n\n // Tabs use w-full and shrink to share the container width, so offsetWidth after\n // a normal render would be containerWidth/n — useless for overflow detection.\n // Force each tab to its natural content width for measurement only (no paint flash:\n // all DOM reads/writes happen synchronously within this JS task before the next frame).\n const listEl = containerEl.value.querySelector('[role=\"tablist\"]') as HTMLElement | null\n if (listEl) {\n listEl.style.overflow = 'visible'\n allTabs.forEach(t => { t.style.flexShrink = '0'; t.style.width = 'auto' })\n void listEl.offsetWidth // force reflow so offsetWidth reads below are accurate\n }\n\n // Measure the more button's real width by temporarily revealing its wrapper.\n // The wrapper is display:none when there's no overflow, so we can't rely on a\n // pre-measured value — measure it here while the (always-visible) container holds it.\n let moreWidth = 0\n const moreEl = dropdownEl.value\n if (moreEl) {\n const prevDisplay = moreEl.style.display\n moreEl.style.display = 'flex'\n void moreEl.offsetWidth\n moreWidth = moreEl.offsetWidth\n moreEl.style.display = prevDisplay\n }\n\n // clientWidth includes the container's horizontal padding; the flex children only\n // get the content box. Subtract padding so measurements compare against real space.\n const cs = getComputedStyle(containerEl.value)\n const padX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight)\n const gap = parseFloat(cs.columnGap) || 0\n const contentWidth = containerEl.value.clientWidth - padX\n\n const tabWidths = allTabs.map(t => t.offsetWidth)\n const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0)\n\n // Restore layout before any early-return so tabs always look correct\n if (listEl) {\n listEl.style.overflow = ''\n allTabs.forEach(t => { t.style.flexShrink = ''; t.style.width = '' })\n }\n\n if (totalWidth <= contentWidth) {\n hiddenTabs.value = []\n return\n }\n\n // When the more button is shown it sits beside the clipped list, separated by `gap`.\n // Reserve its width + the gap (+1px sub-pixel safety) so the last visible tab can\n // never extend under the button.\n const available = contentWidth - moreWidth - gap - 1\n\n let accumulated = 0\n const newHidden: OverflowTab[] = []\n const visibleEls: HTMLElement[] = []\n\n for (let i = 0; i < allTabs.length; i++) {\n const tab = allTabs[i]\n const w = tabWidths[i]\n if (accumulated + w <= available) {\n accumulated += w\n visibleEls.push(tab)\n } else {\n newHidden.push({\n value: tab.getAttribute('data-tab-value') ?? '',\n label: tab.textContent?.trim() ?? '',\n disabled: tab.hasAttribute('data-disabled') || tab.getAttribute('aria-disabled') === 'true',\n })\n tab.setAttribute('data-overflow-hidden', '')\n }\n }\n\n // If the active tab ended up hidden, swap it with the last visible tab\n const activeValue = ctx.currentValue.value\n if (activeValue) {\n const hiddenActiveIdx = newHidden.findIndex(t => t.value === activeValue)\n if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {\n const displacedEl = visibleEls[visibleEls.length - 1]\n const activeEl = allTabs.find(t => t.getAttribute('data-tab-value') === activeValue)\n\n if (displacedEl && activeEl) {\n // Swap: make displaced tab hidden, active tab visible\n displacedEl.setAttribute('data-overflow-hidden', '')\n activeEl.removeAttribute('data-overflow-hidden')\n\n const displaced: OverflowTab = {\n value: displacedEl.getAttribute('data-tab-value') ?? '',\n label: displacedEl.textContent?.trim() ?? '',\n disabled: displacedEl.hasAttribute('data-disabled') || displacedEl.getAttribute('aria-disabled') === 'true',\n }\n newHidden.splice(hiddenActiveIdx, 1)\n newHidden.unshift(displaced)\n }\n }\n }\n\n hiddenTabs.value = newHidden\n}\n\nuseResizeObserver(containerEl, () => nextTick(computeOverflow))\nonMounted(() => {\n nextTick(computeOverflow)\n})\n\n// Recompute when the active tab changes so the active tab is always visible\nwatch(() => ctx.currentValue.value, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\n// Safety re-check when overflow toggles. computeOverflow already reserves the more\n// button's width up front, so this is idempotent — it just guards against layout\n// settling (e.g. a scrollbar appearing) on the false→true transition.\nwatch(hasOverflow, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\nfunction selectOverflowTab(value: string) {\n ctx.changeTab(value)\n dropdownOpen.value = false\n}\n</script>\n\n<template>\n <!-- ── Default (no overflow behaviour) ───────────────────────────────────── -->\n <TabsList\n v-if=\"!props.overflow\"\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n class=\"tabs__list-container tabs__list-container--arrows\"\n :class=\"{ 'has-left': canScrollLeft, 'has-right': canScrollRight }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--left', canScrollLeft && 'is-visible')\"\n aria-label=\"Scroll tabs left\"\n tabindex=\"-1\"\n @click=\"scrollTabs('left')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M9 11L5 7L9 3\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div ref=\"scrollWrapperEl\" class=\"tabs__scroll-wrapper\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class)\"\n >\n <slot />\n </TabsList>\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--right', canScrollRight && 'is-visible')\"\n aria-label=\"Scroll tabs right\"\n tabindex=\"-1\"\n @click=\"scrollTabs('right')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5 3L9 7L5 11\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n </div>\n\n <!-- ── Dropdown mode ──────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'dropdown'\"\n ref=\"containerEl\"\n class=\"tabs__list-container tabs__list-container--dropdown\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n class=\"tabs__more\"\n :class=\"{ 'tabs__more--visible': hasOverflow }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n class=\"tabs__more-btn\"\n :aria-expanded=\"dropdownOpen\"\n aria-haspopup=\"menu\"\n @click=\"dropdownOpen = !dropdownOpen\"\n >\n +{{ hiddenTabs.length }}\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 4L6 8L10 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div v-if=\"dropdownOpen\" class=\"tabs__overflow-menu\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n class=\"tabs__overflow-item\"\n role=\"menuitem\"\n :disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}