@auronui/vue 1.4.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/cjs/index.cjs +719 -460
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/components/_shared/TimeScroller.js.map +1 -1
  4. package/dist/components/_shared/TimeScroller.vue_vue_type_script_setup_true_lang.js +11 -7
  5. package/dist/components/_shared/TimeScroller.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/accordion/Accordion.js.map +1 -1
  7. package/dist/components/accordion/Accordion.vue_vue_type_script_setup_true_lang.js +17 -6
  8. package/dist/components/accordion/Accordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/autocomplete/Autocomplete.js.map +1 -1
  10. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js +23 -3
  11. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/autocomplete/AutocompleteCreateItem.js.map +1 -1
  13. package/dist/components/autocomplete/AutocompleteCreateItem.vue_vue_type_script_setup_true_lang.js +11 -7
  14. package/dist/components/autocomplete/AutocompleteCreateItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  15. package/dist/components/autocomplete/AutocompleteInput.js.map +1 -1
  16. package/dist/components/autocomplete/AutocompleteInput.vue_vue_type_script_setup_true_lang.js +23 -11
  17. package/dist/components/autocomplete/AutocompleteInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/autocomplete/AutocompleteItem.js.map +1 -1
  19. package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js +25 -17
  20. package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/autocomplete/AutocompleteOverflowChips.js.map +1 -1
  22. package/dist/components/autocomplete/AutocompleteOverflowChips.vue_vue_type_script_setup_true_lang.js +11 -4
  23. package/dist/components/autocomplete/AutocompleteOverflowChips.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/avatar/Avatar.js.map +1 -1
  25. package/dist/components/avatar/Avatar.vue_vue_type_script_setup_true_lang.js +11 -13
  26. package/dist/components/avatar/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/components/avatar/AvatarGroup.js.map +1 -1
  28. package/dist/components/avatar/AvatarGroup.vue_vue_type_script_setup_true_lang.js +12 -8
  29. package/dist/components/avatar/AvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -1
  31. package/dist/components/breadcrumbs/Breadcrumbs.vue_vue_type_script_setup_true_lang.js +11 -2
  32. package/dist/components/breadcrumbs/Breadcrumbs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/button/ButtonGroup.js.map +1 -1
  34. package/dist/components/button/ButtonGroup.vue_vue_type_script_setup_true_lang.js +4 -2
  35. package/dist/components/button/ButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/calendar/Calendar.js.map +1 -1
  37. package/dist/components/calendar/Calendar.vue_vue_type_script_setup_true_lang.js +3 -1
  38. package/dist/components/calendar/Calendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  39. package/dist/components/checkbox/CheckboxGroup.js.map +1 -1
  40. package/dist/components/checkbox/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +32 -19
  41. package/dist/components/checkbox/CheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/collapsible/CollapsibleGroup.js.map +1 -1
  43. package/dist/components/collapsible/CollapsibleGroup.vue_vue_type_script_setup_true_lang.js +9 -3
  44. package/dist/components/collapsible/CollapsibleGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/color-field/ColorField.js.map +1 -1
  46. package/dist/components/color-field/ColorField.vue_vue_type_script_setup_true_lang.js +17 -17
  47. package/dist/components/color-field/ColorField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/components/color-input-group/ColorInputGroup.js.map +1 -1
  49. package/dist/components/color-input-group/ColorInputGroup.vue_vue_type_script_setup_true_lang.js +16 -18
  50. package/dist/components/color-input-group/ColorInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/components/combo-box/ComboBox.js.map +1 -1
  52. package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js +10 -2
  53. package/dist/components/combo-box/ComboBox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/combo-box/ComboBoxInput.js.map +1 -1
  55. package/dist/components/combo-box/ComboBoxInput.vue_vue_type_script_setup_true_lang.js +9 -4
  56. package/dist/components/combo-box/ComboBoxInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  57. package/dist/components/combo-box/ComboBoxItem.js.map +1 -1
  58. package/dist/components/combo-box/ComboBoxItem.vue_vue_type_script_setup_true_lang.js +15 -6
  59. package/dist/components/combo-box/ComboBoxItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/date-picker/DatePicker.js.map +1 -1
  61. package/dist/components/date-picker/DatePicker.vue_vue_type_script_setup_true_lang.js +8 -4
  62. package/dist/components/date-picker/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/date-time-picker/DateTimePicker.js.map +1 -1
  64. package/dist/components/date-time-picker/DateTimePicker.vue_vue_type_script_setup_true_lang.js +10 -4
  65. package/dist/components/date-time-picker/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/list-box/ListBox.js.map +1 -1
  67. package/dist/components/list-box/ListBox.vue_vue_type_script_setup_true_lang.js +14 -4
  68. package/dist/components/list-box/ListBox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  69. package/dist/components/modal/ModalContent.js.map +1 -1
  70. package/dist/components/modal/ModalContent.vue_vue_type_script_setup_true_lang.js +2 -3
  71. package/dist/components/modal/ModalContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/radio/RadioGroup.js.map +1 -1
  73. package/dist/components/radio/RadioGroup.vue_vue_type_script_setup_true_lang.js +32 -19
  74. package/dist/components/radio/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  75. package/dist/components/scroll-area/ScrollArea.js.map +1 -1
  76. package/dist/components/scroll-area/ScrollArea.vue_vue_type_script_setup_true_lang.js +30 -13
  77. package/dist/components/scroll-area/ScrollArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/select/Select.js.map +1 -1
  79. package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js +21 -5
  80. package/dist/components/select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -1
  81. package/dist/components/select/SelectItem.js.map +1 -1
  82. package/dist/components/select/SelectItem.vue_vue_type_script_setup_true_lang.js +11 -6
  83. package/dist/components/select/SelectItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/select/SelectOverflowChips.js.map +1 -1
  85. package/dist/components/select/SelectOverflowChips.vue_vue_type_script_setup_true_lang.js +8 -5
  86. package/dist/components/select/SelectOverflowChips.vue_vue_type_script_setup_true_lang.js.map +1 -1
  87. package/dist/components/select/SelectTrigger.js.map +1 -1
  88. package/dist/components/select/SelectTrigger.vue_vue_type_script_setup_true_lang.js +7 -5
  89. package/dist/components/select/SelectTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/select/SelectValue.js.map +1 -1
  91. package/dist/components/select/SelectValue.vue_vue_type_script_setup_true_lang.js +11 -4
  92. package/dist/components/select/SelectValue.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/separator/Separator.js.map +1 -1
  94. package/dist/components/separator/Separator.vue_vue_type_script_setup_true_lang.js +9 -8
  95. package/dist/components/separator/Separator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  96. package/dist/components/stepper/Stepper.js.map +1 -1
  97. package/dist/components/stepper/Stepper.vue_vue_type_script_setup_true_lang.js +20 -10
  98. package/dist/components/stepper/Stepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  99. package/dist/components/switch/SwitchGroup.js.map +1 -1
  100. package/dist/components/switch/SwitchGroup.vue_vue_type_script_setup_true_lang.js +29 -15
  101. package/dist/components/switch/SwitchGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/table/Table.js.map +1 -1
  103. package/dist/components/table/Table.vue_vue_type_script_setup_true_lang.js +29 -9
  104. package/dist/components/table/Table.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/tabs/TabList.js.map +1 -1
  106. package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js +18 -15
  107. package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/tabs/Tabs.js.map +1 -1
  109. package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js +30 -7
  110. package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  111. package/dist/components/time-picker/TimePicker.js.map +1 -1
  112. package/dist/components/time-picker/TimePicker.vue_vue_type_script_setup_true_lang.js +6 -2
  113. package/dist/components/time-picker/TimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/toast/ToastViewport.js.map +1 -1
  115. package/dist/components/toast/ToastViewport.vue_vue_type_script_setup_true_lang.js +19 -6
  116. package/dist/components/toast/ToastViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/index.d.ts +363 -0
  118. package/dist/packages/styles/dist/components/modal/modal.styles.js +2 -1
  119. package/dist/packages/styles/dist/components/modal/modal.styles.js.map +1 -1
  120. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"Table.js","names":[],"sources":["../../../src/components/table/Table.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"TData extends RowData = RowData\">\nimport { computed, ref, watch, useTemplateRef, h } from 'vue'\nimport {\n useVueTable,\n getCoreRowModel,\n getSortedRowModel,\n type ColumnDef,\n type SortingState,\n type RowSelectionState,\n type Table as TableInstance,\n type RowData,\n type Row,\n} from '@tanstack/vue-table'\nimport { tableVariants, type TableVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTableProvide } from './table.context'\nimport { useTableKeyboardNav } from './useTableKeyboardNav'\nimport TableHeader from './TableHeader.vue'\nimport TableBody from './TableBody.vue'\nimport TableVirtualBody from './TableVirtualBody.vue'\nimport TableFooter from './TableFooter.vue'\nimport TableCheckboxCell from './TableCheckboxCell.vue'\n\ntype SelectionMode = 'none' | 'single' | 'multiple'\n\nconst props = withDefaults(\n defineProps<{\n columns: ColumnDef<TData, any>[]\n data: TData[]\n variant?: TableVariants['variant']\n ariaLabel?: string\n /** Row selection mode. 'single' = radio-style; 'multiple' = checkbox + shift+click; 'none' = disabled */\n selection?: SelectionMode\n /** Controlled row selection state (Record<rowId, boolean>). Use v-model:rowSelection */\n rowSelection?: RowSelectionState\n /**\n * Opt-in row virtualization via @tanstack/vue-virtual.\n * - false (default): all rows render in a standard <tbody>\n * - true: always render via TableVirtualBody (only visible rows in DOM)\n * - number N: auto-enable virtualization when data.length > N\n */\n virtualRows?: boolean | number\n /** Estimated row height in px used by the virtualizer (default: 44) */\n estimatedRowHeight?: number\n /** Extra rows to render outside the visible viewport (default: 8) */\n virtualizerOverscan?: number\n /** Per-slot CSS class overrides */\n classNames?: Partial<{\n base: ClassValue\n scrollContainer: ClassValue\n }>\n }>(),\n {\n variant: 'primary',\n ariaLabel: undefined,\n selection: 'none',\n rowSelection: undefined,\n virtualRows: false,\n estimatedRowHeight: 44,\n virtualizerOverscan: 8,\n }\n)\n\nconst emit = defineEmits<{\n 'update:rowSelection': [value: RowSelectionState]\n}>()\n\n// --- Sorting state ----------------------------------------------------\nconst sorting = ref<SortingState>([])\n\n// --- Row selection state (controlled/uncontrolled) -------------------\nconst internalRowSelection = ref<RowSelectionState>(props.rowSelection ?? {})\nwatch(\n () => props.rowSelection,\n (next) => {\n if (next !== undefined) internalRowSelection.value = next\n },\n { deep: true }\n)\n\nfunction updateRowSelection(\n updater: RowSelectionState | ((old: RowSelectionState) => RowSelectionState)\n) {\n const next = typeof updater === 'function' ? updater(internalRowSelection.value) : updater\n internalRowSelection.value = next\n emit('update:rowSelection', next)\n}\n\n// --- Selection column injected at position 0 when enabled -----------\nconst selectionColumn: ColumnDef<TData, any> = {\n id: '__select__',\n size: 44,\n enableSorting: false,\n // TableCheckboxCell is invoked here via h() (a runtime call, not a compiled\n // template), which — like @vue/test-utils' mount() — does not infer a generic\n // SFC's type parameter from the props passed. It always resolves to the\n // component's default (RowData). Casting through RowData (not TData) here\n // matches what h() actually expects; this is the one narrower assertion the\n // design spec anticipated keeping.\n header: ({ table: t }) =>\n props.selection === 'multiple'\n ? h(TableCheckboxCell, { table: t as unknown as TableInstance<RowData> })\n : '',\n cell: ({ row: r }) => h(TableCheckboxCell, { row: r as unknown as Row<RowData> }),\n}\n\nconst effectiveColumns = computed<ColumnDef<TData, any>[]>(() => {\n if (props.selection === 'none') return props.columns\n return [selectionColumn, ...props.columns]\n})\n\n// --- useVueTable instance ---------------------------------------------\n// Use getters so @tanstack/vue-table tracks prop reactivity.\nconst table = useVueTable({\n get data() {\n return props.data\n },\n get columns() {\n return effectiveColumns.value as ColumnDef<TData, unknown>[]\n },\n state: {\n get sorting() {\n return sorting.value\n },\n get rowSelection() {\n return internalRowSelection.value\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n },\n onRowSelectionChange: updateRowSelection,\n get enableRowSelection() {\n return props.selection !== 'none'\n },\n get enableMultiRowSelection() {\n return props.selection === 'multiple'\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n})\n\n// --- Virtualization ---------------------------------------------------\n/** Whether to use TableVirtualBody instead of TableBody */\nconst useVirtual = computed<boolean>(() => {\n if (props.virtualRows === false) return false\n if (props.virtualRows === true) return true\n if (typeof props.virtualRows === 'number') return props.data.length > props.virtualRows\n return false\n})\n\n// The scroll container wrapping the <table> — passed to the virtualizer\nconst scrollContainerRef = useTemplateRef<HTMLElement>('scrollContainerRef')\n\n// Ref to TableVirtualBody instance so keyboard nav can call scrollToIndex.\n// InstanceType<typeof TableVirtualBody> no longer resolves now that\n// TableVirtualBody is a generic SFC (its exported type is a generic factory\n// function, not a plain constructor) — declare the exposed shape by hand\n// instead, matching what TableVirtualBody.vue's defineExpose actually provides.\ninterface TableVirtualBodyExpose {\n scrollToIndex: (index: number) => void\n}\nconst virtualBodyRef = ref<TableVirtualBodyExpose | null>(null)\n\n// --- Keyboard navigation ----------------------------------------------\nconst rootRef = useTemplateRef<HTMLElement>('rootRef')\n\nconst rowCount = computed(() => props.data.length)\nconst columnCount = computed(() => {\n const firstGroup = table.getHeaderGroups()[0]\n return firstGroup ? firstGroup.headers.length : 0\n})\n\nfunction getCellElement(rowIndex: number, columnIndex: number): HTMLElement | null {\n const root = rootRef.value\n if (!root) return null\n // In virtualized mode, scroll the row into view first so the DOM node exists.\n // The queueMicrotask in useTableKeyboardNav.move() gives Vue one tick to\n // flush the virtualizer's render before focus is attempted.\n if (useVirtual.value && virtualBodyRef.value) {\n virtualBodyRef.value.scrollToIndex(rowIndex)\n }\n return root.querySelector<HTMLElement>(\n `[data-row-index=\"${rowIndex}\"][data-col-index=\"${columnIndex}\"]`\n )\n}\n\nconst keyboardNav = useTableKeyboardNav({ rowCount, columnCount, getCellElement })\n\n// --- Selection context helpers ----------------------------------------\nconst selectionEnabled = computed(() => props.selection !== 'none')\nconst selectionMode = computed(() => props.selection ?? 'none')\n\n// Track last-clicked row index for Shift+Click range selection\nconst lastClickedRowIndex = ref<number | null>(null)\n\nfunction handleRowClick(rowIndex: number, event: MouseEvent) {\n if (props.selection === 'none') return\n const rows = table.getRowModel().rows\n if (props.selection === 'multiple' && event.shiftKey && lastClickedRowIndex.value !== null) {\n const [start, end] = [lastClickedRowIndex.value, rowIndex].sort((a, b) => a - b)\n const next: RowSelectionState = { ...internalRowSelection.value }\n for (let i = start; i <= end; i++) {\n const r = rows[i]\n if (r) next[r.id] = true\n }\n updateRowSelection(next)\n }\n lastClickedRowIndex.value = rowIndex\n}\n\n// --- Context provision -------------------------------------------------\nconst variantRef = computed(() => props.variant ?? 'primary')\nconst activeCell = keyboardNav.activeCell\n\nuseTableProvide({\n table,\n activeCell,\n selectionEnabled,\n selectionMode,\n variant: variantRef,\n handleRowClick,\n})\n\n// --- Slot class derivation -------------------------------------------\nconst slotFns = computed(() => tableVariants({ variant: variantRef.value }))\n\ndefineExpose({ table, keyboardNav, handleRowClick })\n</script>\n\n<template>\n <div :class=\"composeClassName(slotFns.base(), $attrs.class as string, props.classNames?.base)\">\n <!--\n scroll container: when virtualized, needs a fixed height + overflow:auto\n so the virtualizer can measure the viewport. Consumers should override\n the inline height via a wrapping container or CSS for production use.\n -->\n <div\n ref=\"scrollContainerRef\"\n :class=\"composeClassName(slotFns.scrollContainer(), props.classNames?.scrollContainer)\"\n :style=\"useVirtual ? { height: '400px', overflow: 'auto' } : undefined\"\n >\n <table\n class=\"table\"\n ref=\"rootRef\"\n role=\"grid\"\n :aria-label=\"ariaLabel\"\n :aria-rowcount=\"rowCount\"\n :aria-colcount=\"columnCount\"\n @keydown=\"keyboardNav.onKeydown\"\n >\n <TableHeader />\n <TableBody v-if=\"!useVirtual\">\n <template #cell=\"slotProps\">\n <slot\n name=\"cell\"\n v-bind=\"slotProps\"\n />\n </template>\n </TableBody>\n <TableVirtualBody\n v-else\n ref=\"virtualBodyRef\"\n :scroll-element=\"scrollContainerRef\"\n :estimated-row-height=\"estimatedRowHeight\"\n :overscan=\"virtualizerOverscan\"\n />\n <TableFooter v-if=\"$slots.footer\">\n <slot name=\"footer\" />\n </TableFooter>\n </table>\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Table.js","names":[],"sources":["../../../src/components/table/Table.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"TData extends RowData = RowData\">\nimport { computed, ref, watch, useTemplateRef, h } from 'vue'\nimport {\n useVueTable,\n getCoreRowModel,\n getSortedRowModel,\n type ColumnDef,\n type SortingState,\n type RowSelectionState,\n type Table as TableInstance,\n type RowData,\n type Row,\n} from '@tanstack/vue-table'\nimport { tableVariants, type TableVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTableProvide } from './table.context'\nimport { useTableKeyboardNav } from './useTableKeyboardNav'\nimport TableHeader from './TableHeader.vue'\nimport TableBody from './TableBody.vue'\nimport TableVirtualBody from './TableVirtualBody.vue'\nimport TableFooter from './TableFooter.vue'\nimport TableCheckboxCell from './TableCheckboxCell.vue'\n\ntype SelectionMode = 'none' | 'single' | 'multiple'\n\nconst props = withDefaults(\n defineProps<{\n columns: ColumnDef<TData, any>[]\n data: TData[]\n variant?: TableVariants['variant']\n ariaLabel?: string\n /** Row selection mode. 'single' = radio-style; 'multiple' = checkbox + shift+click; 'none' = disabled */\n selection?: SelectionMode\n /** Controlled row selection state (Record<rowId, boolean>). Use v-model:rowSelection */\n rowSelection?: RowSelectionState\n /**\n * Opt-in row virtualization via @tanstack/vue-virtual.\n * - false (default): all rows render in a standard <tbody>\n * - true: always render via TableVirtualBody (only visible rows in DOM)\n * - number N: auto-enable virtualization when data.length > N\n */\n virtualRows?: boolean | number\n /** Estimated row height in px used by the virtualizer (default: 44) */\n estimatedRowHeight?: number\n /** Extra rows to render outside the visible viewport (default: 8) */\n virtualizerOverscan?: number\n /** Per-slot CSS class overrides */\n classNames?: Partial<{\n base: ClassValue\n scrollContainer: ClassValue\n content: ClassValue\n header: ClassValue\n row: ClassValue\n column: ClassValue\n body: ClassValue\n cell: ClassValue\n footer: ClassValue\n }>\n }>(),\n {\n variant: 'primary',\n ariaLabel: undefined,\n selection: 'none',\n rowSelection: undefined,\n virtualRows: false,\n estimatedRowHeight: 44,\n virtualizerOverscan: 8,\n }\n)\n\nconst emit = defineEmits<{\n 'update:rowSelection': [value: RowSelectionState]\n}>()\n\n// --- Sorting state ----------------------------------------------------\nconst sorting = ref<SortingState>([])\n\n// --- Row selection state (controlled/uncontrolled) -------------------\nconst internalRowSelection = ref<RowSelectionState>(props.rowSelection ?? {})\nwatch(\n () => props.rowSelection,\n (next) => {\n if (next !== undefined) internalRowSelection.value = next\n },\n { deep: true }\n)\n\nfunction updateRowSelection(\n updater: RowSelectionState | ((old: RowSelectionState) => RowSelectionState)\n) {\n const next = typeof updater === 'function' ? updater(internalRowSelection.value) : updater\n internalRowSelection.value = next\n emit('update:rowSelection', next)\n}\n\n// --- Selection column injected at position 0 when enabled -----------\nconst selectionColumn: ColumnDef<TData, any> = {\n id: '__select__',\n size: 44,\n enableSorting: false,\n // TableCheckboxCell is invoked here via h() (a runtime call, not a compiled\n // template), which — like @vue/test-utils' mount() — does not infer a generic\n // SFC's type parameter from the props passed. It always resolves to the\n // component's default (RowData). Casting through RowData (not TData) here\n // matches what h() actually expects; this is the one narrower assertion the\n // design spec anticipated keeping.\n header: ({ table: t }) =>\n props.selection === 'multiple'\n ? h(TableCheckboxCell, { table: t as unknown as TableInstance<RowData> })\n : '',\n cell: ({ row: r }) => h(TableCheckboxCell, { row: r as unknown as Row<RowData> }),\n}\n\nconst effectiveColumns = computed<ColumnDef<TData, any>[]>(() => {\n if (props.selection === 'none') return props.columns\n return [selectionColumn, ...props.columns]\n})\n\n// --- useVueTable instance ---------------------------------------------\n// Use getters so @tanstack/vue-table tracks prop reactivity.\nconst table = useVueTable({\n get data() {\n return props.data\n },\n get columns() {\n return effectiveColumns.value as ColumnDef<TData, unknown>[]\n },\n state: {\n get sorting() {\n return sorting.value\n },\n get rowSelection() {\n return internalRowSelection.value\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n },\n onRowSelectionChange: updateRowSelection,\n get enableRowSelection() {\n return props.selection !== 'none'\n },\n get enableMultiRowSelection() {\n return props.selection === 'multiple'\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n})\n\n// --- Virtualization ---------------------------------------------------\n/** Whether to use TableVirtualBody instead of TableBody */\nconst useVirtual = computed<boolean>(() => {\n if (props.virtualRows === false) return false\n if (props.virtualRows === true) return true\n if (typeof props.virtualRows === 'number') return props.data.length > props.virtualRows\n return false\n})\n\n// The scroll container wrapping the <table> — passed to the virtualizer\nconst scrollContainerRef = useTemplateRef<HTMLElement>('scrollContainerRef')\n\n// Ref to TableVirtualBody instance so keyboard nav can call scrollToIndex.\n// InstanceType<typeof TableVirtualBody> no longer resolves now that\n// TableVirtualBody is a generic SFC (its exported type is a generic factory\n// function, not a plain constructor) — declare the exposed shape by hand\n// instead, matching what TableVirtualBody.vue's defineExpose actually provides.\ninterface TableVirtualBodyExpose {\n scrollToIndex: (index: number) => void\n}\nconst virtualBodyRef = ref<TableVirtualBodyExpose | null>(null)\n\n// --- Keyboard navigation ----------------------------------------------\nconst rootRef = useTemplateRef<HTMLElement>('rootRef')\n\nconst rowCount = computed(() => props.data.length)\nconst columnCount = computed(() => {\n const firstGroup = table.getHeaderGroups()[0]\n return firstGroup ? firstGroup.headers.length : 0\n})\n\nfunction getCellElement(rowIndex: number, columnIndex: number): HTMLElement | null {\n const root = rootRef.value\n if (!root) return null\n // In virtualized mode, scroll the row into view first so the DOM node exists.\n // The queueMicrotask in useTableKeyboardNav.move() gives Vue one tick to\n // flush the virtualizer's render before focus is attempted.\n if (useVirtual.value && virtualBodyRef.value) {\n virtualBodyRef.value.scrollToIndex(rowIndex)\n }\n return root.querySelector<HTMLElement>(\n `[data-row-index=\"${rowIndex}\"][data-col-index=\"${columnIndex}\"]`\n )\n}\n\nconst keyboardNav = useTableKeyboardNav({ rowCount, columnCount, getCellElement })\n\n// --- Selection context helpers ----------------------------------------\nconst selectionEnabled = computed(() => props.selection !== 'none')\nconst selectionMode = computed(() => props.selection ?? 'none')\n\n// Track last-clicked row index for Shift+Click range selection\nconst lastClickedRowIndex = ref<number | null>(null)\n\nfunction handleRowClick(rowIndex: number, event: MouseEvent) {\n if (props.selection === 'none') return\n const rows = table.getRowModel().rows\n if (props.selection === 'multiple' && event.shiftKey && lastClickedRowIndex.value !== null) {\n const [start, end] = [lastClickedRowIndex.value, rowIndex].sort((a, b) => a - b)\n const next: RowSelectionState = { ...internalRowSelection.value }\n for (let i = start; i <= end; i++) {\n const r = rows[i]\n if (r) next[r.id] = true\n }\n updateRowSelection(next)\n }\n lastClickedRowIndex.value = rowIndex\n}\n\n// --- Context provision -------------------------------------------------\nconst variantRef = computed(() => props.variant ?? 'primary')\nconst activeCell = keyboardNav.activeCell\n\nuseTableProvide({\n table,\n activeCell,\n selectionEnabled,\n selectionMode,\n variant: variantRef,\n handleRowClick,\n})\n\n// --- Slot class derivation -------------------------------------------\nconst slotFns = computed(() => tableVariants({ variant: variantRef.value }))\n\ndefineExpose({ table, keyboardNav, handleRowClick })\n</script>\n\n<template>\n <div :class=\"composeClassName(slotFns.base(), $attrs.class as string, props.classNames?.base)\">\n <!--\n scroll container: when virtualized, needs a fixed height + overflow:auto\n so the virtualizer can measure the viewport. Consumers should override\n the inline height via a wrapping container or CSS for production use.\n -->\n <div\n ref=\"scrollContainerRef\"\n :class=\"composeClassName(slotFns.scrollContainer(), props.classNames?.scrollContainer)\"\n :style=\"useVirtual ? { height: '400px', overflow: 'auto' } : undefined\"\n >\n <table\n :class=\"composeClassName(slotFns.content(), props.classNames?.content)\"\n ref=\"rootRef\"\n role=\"grid\"\n :aria-label=\"ariaLabel\"\n :aria-rowcount=\"rowCount\"\n :aria-colcount=\"columnCount\"\n @keydown=\"keyboardNav.onKeydown\"\n >\n <TableHeader\n :class-names=\"{ header: props.classNames?.header, row: props.classNames?.row, column: props.classNames?.column }\"\n />\n <TableBody\n v-if=\"!useVirtual\"\n :class-names=\"{ body: props.classNames?.body, row: props.classNames?.row, cell: props.classNames?.cell }\"\n >\n <template #cell=\"slotProps\">\n <slot\n name=\"cell\"\n v-bind=\"slotProps\"\n />\n </template>\n </TableBody>\n <TableVirtualBody\n v-else\n ref=\"virtualBodyRef\"\n :scroll-element=\"scrollContainerRef\"\n :estimated-row-height=\"estimatedRowHeight\"\n :overscan=\"virtualizerOverscan\"\n :class-names=\"{ body: props.classNames?.body, row: props.classNames?.row, cell: props.classNames?.cell }\"\n />\n <TableFooter\n v-if=\"$slots.footer\"\n :class-names=\"{ footer: props.classNames?.footer }\"\n >\n <slot name=\"footer\" />\n </TableFooter>\n </table>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -155,7 +155,7 @@ var Table_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
155
155
  overflow: "auto"
156
156
  } : void 0)
157
157
  }, [createElementVNode("table", {
158
- class: "table",
158
+ class: normalizeClass(unref(composeClassName)(slotFns.value.content(), props.classNames?.content)),
159
159
  ref_key: "rootRef",
160
160
  ref: rootRef,
161
161
  role: "grid",
@@ -164,27 +164,47 @@ var Table_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
164
164
  "aria-colcount": columnCount.value,
165
165
  onKeydown: _cache[0] || (_cache[0] = (...args) => unref(keyboardNav).onKeydown && unref(keyboardNav).onKeydown(...args))
166
166
  }, [
167
- createVNode(TableHeader_default),
168
- !useVirtual.value ? (openBlock(), createBlock(TableBody_default, { key: 0 }, {
167
+ createVNode(TableHeader_default, { "class-names": {
168
+ header: props.classNames?.header,
169
+ row: props.classNames?.row,
170
+ column: props.classNames?.column
171
+ } }, null, 8, ["class-names"]),
172
+ !useVirtual.value ? (openBlock(), createBlock(TableBody_default, {
173
+ key: 0,
174
+ "class-names": {
175
+ body: props.classNames?.body,
176
+ row: props.classNames?.row,
177
+ cell: props.classNames?.cell
178
+ }
179
+ }, {
169
180
  cell: withCtx((slotProps) => [renderSlot(_ctx.$slots, "cell", normalizeProps(guardReactiveProps(slotProps)))]),
170
181
  _: 3
171
- })) : (openBlock(), createBlock(TableVirtualBody_default, {
182
+ }, 8, ["class-names"])) : (openBlock(), createBlock(TableVirtualBody_default, {
172
183
  key: 1,
173
184
  ref_key: "virtualBodyRef",
174
185
  ref: virtualBodyRef,
175
186
  "scroll-element": scrollContainerRef.value,
176
187
  "estimated-row-height": __props.estimatedRowHeight,
177
- overscan: __props.virtualizerOverscan
188
+ overscan: __props.virtualizerOverscan,
189
+ "class-names": {
190
+ body: props.classNames?.body,
191
+ row: props.classNames?.row,
192
+ cell: props.classNames?.cell
193
+ }
178
194
  }, null, 8, [
179
195
  "scroll-element",
180
196
  "estimated-row-height",
181
- "overscan"
197
+ "overscan",
198
+ "class-names"
182
199
  ])),
183
- _ctx.$slots.footer ? (openBlock(), createBlock(TableFooter_default, { key: 2 }, {
200
+ _ctx.$slots.footer ? (openBlock(), createBlock(TableFooter_default, {
201
+ key: 2,
202
+ "class-names": { footer: props.classNames?.footer }
203
+ }, {
184
204
  default: withCtx(() => [renderSlot(_ctx.$slots, "footer")]),
185
205
  _: 3
186
- })) : createCommentVNode("", true)
187
- ], 40, _hoisted_1)], 6)], 2);
206
+ }, 8, ["class-names"])) : createCommentVNode("", true)
207
+ ], 42, _hoisted_1)], 6)], 2);
188
208
  };
189
209
  }
190
210
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Table.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../src/components/table/Table.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"TData extends RowData = RowData\">\nimport { computed, ref, watch, useTemplateRef, h } from 'vue'\nimport {\n useVueTable,\n getCoreRowModel,\n getSortedRowModel,\n type ColumnDef,\n type SortingState,\n type RowSelectionState,\n type Table as TableInstance,\n type RowData,\n type Row,\n} from '@tanstack/vue-table'\nimport { tableVariants, type TableVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTableProvide } from './table.context'\nimport { useTableKeyboardNav } from './useTableKeyboardNav'\nimport TableHeader from './TableHeader.vue'\nimport TableBody from './TableBody.vue'\nimport TableVirtualBody from './TableVirtualBody.vue'\nimport TableFooter from './TableFooter.vue'\nimport TableCheckboxCell from './TableCheckboxCell.vue'\n\ntype SelectionMode = 'none' | 'single' | 'multiple'\n\nconst props = withDefaults(\n defineProps<{\n columns: ColumnDef<TData, any>[]\n data: TData[]\n variant?: TableVariants['variant']\n ariaLabel?: string\n /** Row selection mode. 'single' = radio-style; 'multiple' = checkbox + shift+click; 'none' = disabled */\n selection?: SelectionMode\n /** Controlled row selection state (Record<rowId, boolean>). Use v-model:rowSelection */\n rowSelection?: RowSelectionState\n /**\n * Opt-in row virtualization via @tanstack/vue-virtual.\n * - false (default): all rows render in a standard <tbody>\n * - true: always render via TableVirtualBody (only visible rows in DOM)\n * - number N: auto-enable virtualization when data.length > N\n */\n virtualRows?: boolean | number\n /** Estimated row height in px used by the virtualizer (default: 44) */\n estimatedRowHeight?: number\n /** Extra rows to render outside the visible viewport (default: 8) */\n virtualizerOverscan?: number\n /** Per-slot CSS class overrides */\n classNames?: Partial<{\n base: ClassValue\n scrollContainer: ClassValue\n }>\n }>(),\n {\n variant: 'primary',\n ariaLabel: undefined,\n selection: 'none',\n rowSelection: undefined,\n virtualRows: false,\n estimatedRowHeight: 44,\n virtualizerOverscan: 8,\n }\n)\n\nconst emit = defineEmits<{\n 'update:rowSelection': [value: RowSelectionState]\n}>()\n\n// --- Sorting state ----------------------------------------------------\nconst sorting = ref<SortingState>([])\n\n// --- Row selection state (controlled/uncontrolled) -------------------\nconst internalRowSelection = ref<RowSelectionState>(props.rowSelection ?? {})\nwatch(\n () => props.rowSelection,\n (next) => {\n if (next !== undefined) internalRowSelection.value = next\n },\n { deep: true }\n)\n\nfunction updateRowSelection(\n updater: RowSelectionState | ((old: RowSelectionState) => RowSelectionState)\n) {\n const next = typeof updater === 'function' ? updater(internalRowSelection.value) : updater\n internalRowSelection.value = next\n emit('update:rowSelection', next)\n}\n\n// --- Selection column injected at position 0 when enabled -----------\nconst selectionColumn: ColumnDef<TData, any> = {\n id: '__select__',\n size: 44,\n enableSorting: false,\n // TableCheckboxCell is invoked here via h() (a runtime call, not a compiled\n // template), which — like @vue/test-utils' mount() — does not infer a generic\n // SFC's type parameter from the props passed. It always resolves to the\n // component's default (RowData). Casting through RowData (not TData) here\n // matches what h() actually expects; this is the one narrower assertion the\n // design spec anticipated keeping.\n header: ({ table: t }) =>\n props.selection === 'multiple'\n ? h(TableCheckboxCell, { table: t as unknown as TableInstance<RowData> })\n : '',\n cell: ({ row: r }) => h(TableCheckboxCell, { row: r as unknown as Row<RowData> }),\n}\n\nconst effectiveColumns = computed<ColumnDef<TData, any>[]>(() => {\n if (props.selection === 'none') return props.columns\n return [selectionColumn, ...props.columns]\n})\n\n// --- useVueTable instance ---------------------------------------------\n// Use getters so @tanstack/vue-table tracks prop reactivity.\nconst table = useVueTable({\n get data() {\n return props.data\n },\n get columns() {\n return effectiveColumns.value as ColumnDef<TData, unknown>[]\n },\n state: {\n get sorting() {\n return sorting.value\n },\n get rowSelection() {\n return internalRowSelection.value\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n },\n onRowSelectionChange: updateRowSelection,\n get enableRowSelection() {\n return props.selection !== 'none'\n },\n get enableMultiRowSelection() {\n return props.selection === 'multiple'\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n})\n\n// --- Virtualization ---------------------------------------------------\n/** Whether to use TableVirtualBody instead of TableBody */\nconst useVirtual = computed<boolean>(() => {\n if (props.virtualRows === false) return false\n if (props.virtualRows === true) return true\n if (typeof props.virtualRows === 'number') return props.data.length > props.virtualRows\n return false\n})\n\n// The scroll container wrapping the <table> — passed to the virtualizer\nconst scrollContainerRef = useTemplateRef<HTMLElement>('scrollContainerRef')\n\n// Ref to TableVirtualBody instance so keyboard nav can call scrollToIndex.\n// InstanceType<typeof TableVirtualBody> no longer resolves now that\n// TableVirtualBody is a generic SFC (its exported type is a generic factory\n// function, not a plain constructor) — declare the exposed shape by hand\n// instead, matching what TableVirtualBody.vue's defineExpose actually provides.\ninterface TableVirtualBodyExpose {\n scrollToIndex: (index: number) => void\n}\nconst virtualBodyRef = ref<TableVirtualBodyExpose | null>(null)\n\n// --- Keyboard navigation ----------------------------------------------\nconst rootRef = useTemplateRef<HTMLElement>('rootRef')\n\nconst rowCount = computed(() => props.data.length)\nconst columnCount = computed(() => {\n const firstGroup = table.getHeaderGroups()[0]\n return firstGroup ? firstGroup.headers.length : 0\n})\n\nfunction getCellElement(rowIndex: number, columnIndex: number): HTMLElement | null {\n const root = rootRef.value\n if (!root) return null\n // In virtualized mode, scroll the row into view first so the DOM node exists.\n // The queueMicrotask in useTableKeyboardNav.move() gives Vue one tick to\n // flush the virtualizer's render before focus is attempted.\n if (useVirtual.value && virtualBodyRef.value) {\n virtualBodyRef.value.scrollToIndex(rowIndex)\n }\n return root.querySelector<HTMLElement>(\n `[data-row-index=\"${rowIndex}\"][data-col-index=\"${columnIndex}\"]`\n )\n}\n\nconst keyboardNav = useTableKeyboardNav({ rowCount, columnCount, getCellElement })\n\n// --- Selection context helpers ----------------------------------------\nconst selectionEnabled = computed(() => props.selection !== 'none')\nconst selectionMode = computed(() => props.selection ?? 'none')\n\n// Track last-clicked row index for Shift+Click range selection\nconst lastClickedRowIndex = ref<number | null>(null)\n\nfunction handleRowClick(rowIndex: number, event: MouseEvent) {\n if (props.selection === 'none') return\n const rows = table.getRowModel().rows\n if (props.selection === 'multiple' && event.shiftKey && lastClickedRowIndex.value !== null) {\n const [start, end] = [lastClickedRowIndex.value, rowIndex].sort((a, b) => a - b)\n const next: RowSelectionState = { ...internalRowSelection.value }\n for (let i = start; i <= end; i++) {\n const r = rows[i]\n if (r) next[r.id] = true\n }\n updateRowSelection(next)\n }\n lastClickedRowIndex.value = rowIndex\n}\n\n// --- Context provision -------------------------------------------------\nconst variantRef = computed(() => props.variant ?? 'primary')\nconst activeCell = keyboardNav.activeCell\n\nuseTableProvide({\n table,\n activeCell,\n selectionEnabled,\n selectionMode,\n variant: variantRef,\n handleRowClick,\n})\n\n// --- Slot class derivation -------------------------------------------\nconst slotFns = computed(() => tableVariants({ variant: variantRef.value }))\n\ndefineExpose({ table, keyboardNav, handleRowClick })\n</script>\n\n<template>\n <div :class=\"composeClassName(slotFns.base(), $attrs.class as string, props.classNames?.base)\">\n <!--\n scroll container: when virtualized, needs a fixed height + overflow:auto\n so the virtualizer can measure the viewport. Consumers should override\n the inline height via a wrapping container or CSS for production use.\n -->\n <div\n ref=\"scrollContainerRef\"\n :class=\"composeClassName(slotFns.scrollContainer(), props.classNames?.scrollContainer)\"\n :style=\"useVirtual ? { height: '400px', overflow: 'auto' } : undefined\"\n >\n <table\n class=\"table\"\n ref=\"rootRef\"\n role=\"grid\"\n :aria-label=\"ariaLabel\"\n :aria-rowcount=\"rowCount\"\n :aria-colcount=\"columnCount\"\n @keydown=\"keyboardNav.onKeydown\"\n >\n <TableHeader />\n <TableBody v-if=\"!useVirtual\">\n <template #cell=\"slotProps\">\n <slot\n name=\"cell\"\n v-bind=\"slotProps\"\n />\n </template>\n </TableBody>\n <TableVirtualBody\n v-else\n ref=\"virtualBodyRef\"\n :scroll-element=\"scrollContainerRef\"\n :estimated-row-height=\"estimatedRowHeight\"\n :overscan=\"virtualizerOverscan\"\n />\n <TableFooter v-if=\"$slots.footer\">\n <slot name=\"footer\" />\n </TableFooter>\n </table>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"Table.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../src/components/table/Table.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"TData extends RowData = RowData\">\nimport { computed, ref, watch, useTemplateRef, h } from 'vue'\nimport {\n useVueTable,\n getCoreRowModel,\n getSortedRowModel,\n type ColumnDef,\n type SortingState,\n type RowSelectionState,\n type Table as TableInstance,\n type RowData,\n type Row,\n} from '@tanstack/vue-table'\nimport { tableVariants, type TableVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTableProvide } from './table.context'\nimport { useTableKeyboardNav } from './useTableKeyboardNav'\nimport TableHeader from './TableHeader.vue'\nimport TableBody from './TableBody.vue'\nimport TableVirtualBody from './TableVirtualBody.vue'\nimport TableFooter from './TableFooter.vue'\nimport TableCheckboxCell from './TableCheckboxCell.vue'\n\ntype SelectionMode = 'none' | 'single' | 'multiple'\n\nconst props = withDefaults(\n defineProps<{\n columns: ColumnDef<TData, any>[]\n data: TData[]\n variant?: TableVariants['variant']\n ariaLabel?: string\n /** Row selection mode. 'single' = radio-style; 'multiple' = checkbox + shift+click; 'none' = disabled */\n selection?: SelectionMode\n /** Controlled row selection state (Record<rowId, boolean>). Use v-model:rowSelection */\n rowSelection?: RowSelectionState\n /**\n * Opt-in row virtualization via @tanstack/vue-virtual.\n * - false (default): all rows render in a standard <tbody>\n * - true: always render via TableVirtualBody (only visible rows in DOM)\n * - number N: auto-enable virtualization when data.length > N\n */\n virtualRows?: boolean | number\n /** Estimated row height in px used by the virtualizer (default: 44) */\n estimatedRowHeight?: number\n /** Extra rows to render outside the visible viewport (default: 8) */\n virtualizerOverscan?: number\n /** Per-slot CSS class overrides */\n classNames?: Partial<{\n base: ClassValue\n scrollContainer: ClassValue\n content: ClassValue\n header: ClassValue\n row: ClassValue\n column: ClassValue\n body: ClassValue\n cell: ClassValue\n footer: ClassValue\n }>\n }>(),\n {\n variant: 'primary',\n ariaLabel: undefined,\n selection: 'none',\n rowSelection: undefined,\n virtualRows: false,\n estimatedRowHeight: 44,\n virtualizerOverscan: 8,\n }\n)\n\nconst emit = defineEmits<{\n 'update:rowSelection': [value: RowSelectionState]\n}>()\n\n// --- Sorting state ----------------------------------------------------\nconst sorting = ref<SortingState>([])\n\n// --- Row selection state (controlled/uncontrolled) -------------------\nconst internalRowSelection = ref<RowSelectionState>(props.rowSelection ?? {})\nwatch(\n () => props.rowSelection,\n (next) => {\n if (next !== undefined) internalRowSelection.value = next\n },\n { deep: true }\n)\n\nfunction updateRowSelection(\n updater: RowSelectionState | ((old: RowSelectionState) => RowSelectionState)\n) {\n const next = typeof updater === 'function' ? updater(internalRowSelection.value) : updater\n internalRowSelection.value = next\n emit('update:rowSelection', next)\n}\n\n// --- Selection column injected at position 0 when enabled -----------\nconst selectionColumn: ColumnDef<TData, any> = {\n id: '__select__',\n size: 44,\n enableSorting: false,\n // TableCheckboxCell is invoked here via h() (a runtime call, not a compiled\n // template), which — like @vue/test-utils' mount() — does not infer a generic\n // SFC's type parameter from the props passed. It always resolves to the\n // component's default (RowData). Casting through RowData (not TData) here\n // matches what h() actually expects; this is the one narrower assertion the\n // design spec anticipated keeping.\n header: ({ table: t }) =>\n props.selection === 'multiple'\n ? h(TableCheckboxCell, { table: t as unknown as TableInstance<RowData> })\n : '',\n cell: ({ row: r }) => h(TableCheckboxCell, { row: r as unknown as Row<RowData> }),\n}\n\nconst effectiveColumns = computed<ColumnDef<TData, any>[]>(() => {\n if (props.selection === 'none') return props.columns\n return [selectionColumn, ...props.columns]\n})\n\n// --- useVueTable instance ---------------------------------------------\n// Use getters so @tanstack/vue-table tracks prop reactivity.\nconst table = useVueTable({\n get data() {\n return props.data\n },\n get columns() {\n return effectiveColumns.value as ColumnDef<TData, unknown>[]\n },\n state: {\n get sorting() {\n return sorting.value\n },\n get rowSelection() {\n return internalRowSelection.value\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n },\n onRowSelectionChange: updateRowSelection,\n get enableRowSelection() {\n return props.selection !== 'none'\n },\n get enableMultiRowSelection() {\n return props.selection === 'multiple'\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n})\n\n// --- Virtualization ---------------------------------------------------\n/** Whether to use TableVirtualBody instead of TableBody */\nconst useVirtual = computed<boolean>(() => {\n if (props.virtualRows === false) return false\n if (props.virtualRows === true) return true\n if (typeof props.virtualRows === 'number') return props.data.length > props.virtualRows\n return false\n})\n\n// The scroll container wrapping the <table> — passed to the virtualizer\nconst scrollContainerRef = useTemplateRef<HTMLElement>('scrollContainerRef')\n\n// Ref to TableVirtualBody instance so keyboard nav can call scrollToIndex.\n// InstanceType<typeof TableVirtualBody> no longer resolves now that\n// TableVirtualBody is a generic SFC (its exported type is a generic factory\n// function, not a plain constructor) — declare the exposed shape by hand\n// instead, matching what TableVirtualBody.vue's defineExpose actually provides.\ninterface TableVirtualBodyExpose {\n scrollToIndex: (index: number) => void\n}\nconst virtualBodyRef = ref<TableVirtualBodyExpose | null>(null)\n\n// --- Keyboard navigation ----------------------------------------------\nconst rootRef = useTemplateRef<HTMLElement>('rootRef')\n\nconst rowCount = computed(() => props.data.length)\nconst columnCount = computed(() => {\n const firstGroup = table.getHeaderGroups()[0]\n return firstGroup ? firstGroup.headers.length : 0\n})\n\nfunction getCellElement(rowIndex: number, columnIndex: number): HTMLElement | null {\n const root = rootRef.value\n if (!root) return null\n // In virtualized mode, scroll the row into view first so the DOM node exists.\n // The queueMicrotask in useTableKeyboardNav.move() gives Vue one tick to\n // flush the virtualizer's render before focus is attempted.\n if (useVirtual.value && virtualBodyRef.value) {\n virtualBodyRef.value.scrollToIndex(rowIndex)\n }\n return root.querySelector<HTMLElement>(\n `[data-row-index=\"${rowIndex}\"][data-col-index=\"${columnIndex}\"]`\n )\n}\n\nconst keyboardNav = useTableKeyboardNav({ rowCount, columnCount, getCellElement })\n\n// --- Selection context helpers ----------------------------------------\nconst selectionEnabled = computed(() => props.selection !== 'none')\nconst selectionMode = computed(() => props.selection ?? 'none')\n\n// Track last-clicked row index for Shift+Click range selection\nconst lastClickedRowIndex = ref<number | null>(null)\n\nfunction handleRowClick(rowIndex: number, event: MouseEvent) {\n if (props.selection === 'none') return\n const rows = table.getRowModel().rows\n if (props.selection === 'multiple' && event.shiftKey && lastClickedRowIndex.value !== null) {\n const [start, end] = [lastClickedRowIndex.value, rowIndex].sort((a, b) => a - b)\n const next: RowSelectionState = { ...internalRowSelection.value }\n for (let i = start; i <= end; i++) {\n const r = rows[i]\n if (r) next[r.id] = true\n }\n updateRowSelection(next)\n }\n lastClickedRowIndex.value = rowIndex\n}\n\n// --- Context provision -------------------------------------------------\nconst variantRef = computed(() => props.variant ?? 'primary')\nconst activeCell = keyboardNav.activeCell\n\nuseTableProvide({\n table,\n activeCell,\n selectionEnabled,\n selectionMode,\n variant: variantRef,\n handleRowClick,\n})\n\n// --- Slot class derivation -------------------------------------------\nconst slotFns = computed(() => tableVariants({ variant: variantRef.value }))\n\ndefineExpose({ table, keyboardNav, handleRowClick })\n</script>\n\n<template>\n <div :class=\"composeClassName(slotFns.base(), $attrs.class as string, props.classNames?.base)\">\n <!--\n scroll container: when virtualized, needs a fixed height + overflow:auto\n so the virtualizer can measure the viewport. Consumers should override\n the inline height via a wrapping container or CSS for production use.\n -->\n <div\n ref=\"scrollContainerRef\"\n :class=\"composeClassName(slotFns.scrollContainer(), props.classNames?.scrollContainer)\"\n :style=\"useVirtual ? { height: '400px', overflow: 'auto' } : undefined\"\n >\n <table\n :class=\"composeClassName(slotFns.content(), props.classNames?.content)\"\n ref=\"rootRef\"\n role=\"grid\"\n :aria-label=\"ariaLabel\"\n :aria-rowcount=\"rowCount\"\n :aria-colcount=\"columnCount\"\n @keydown=\"keyboardNav.onKeydown\"\n >\n <TableHeader\n :class-names=\"{ header: props.classNames?.header, row: props.classNames?.row, column: props.classNames?.column }\"\n />\n <TableBody\n v-if=\"!useVirtual\"\n :class-names=\"{ body: props.classNames?.body, row: props.classNames?.row, cell: props.classNames?.cell }\"\n >\n <template #cell=\"slotProps\">\n <slot\n name=\"cell\"\n v-bind=\"slotProps\"\n />\n </template>\n </TableBody>\n <TableVirtualBody\n v-else\n ref=\"virtualBodyRef\"\n :scroll-element=\"scrollContainerRef\"\n :estimated-row-height=\"estimatedRowHeight\"\n :overscan=\"virtualizerOverscan\"\n :class-names=\"{ body: props.classNames?.body, row: props.classNames?.row, cell: props.classNames?.cell }\"\n />\n <TableFooter\n v-if=\"$slots.footer\"\n :class-names=\"{ footer: props.classNames?.footer }\"\n >\n <slot name=\"footer\" />\n </TableFooter>\n </table>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBA,MAAM,QAAQ;EA6Cd,MAAM,OAAO;EAKb,MAAM,UAAU,IAAkB,EAAE,CAAA;EAGpC,MAAM,uBAAuB,IAAuB,MAAM,gBAAgB,EAAE,CAAA;AAC5E,cACQ,MAAM,eACX,SAAS;AACR,OAAI,SAAS,KAAA,EAAW,sBAAqB,QAAQ;KAEvD,EAAE,MAAM,MAAK,CACf;EAEA,SAAS,mBACP,SACA;GACA,MAAM,OAAO,OAAO,YAAY,aAAa,QAAQ,qBAAqB,MAAM,GAAG;AACnF,wBAAqB,QAAQ;AAC7B,QAAK,uBAAuB,KAAI;;EAIlC,MAAM,kBAAyC;GAC7C,IAAI;GACJ,MAAM;GACN,eAAe;GAOf,SAAS,EAAE,OAAO,QAChB,MAAM,cAAc,aAChB,EAAE,2BAAmB,EAAE,OAAO,GAAwC,CAAA,GACtE;GACN,OAAO,EAAE,KAAK,QAAQ,EAAE,2BAAmB,EAAE,KAAK,GAA8B,CAAC;GACnF;EAEA,MAAM,mBAAmB,eAAwC;AAC/D,OAAI,MAAM,cAAc,OAAQ,QAAO,MAAM;AAC7C,UAAO,CAAC,iBAAiB,GAAG,MAAM,QAAO;IAC1C;EAID,MAAM,QAAQ,YAAY;GACxB,IAAI,OAAO;AACT,WAAO,MAAM;;GAEf,IAAI,UAAU;AACZ,WAAO,iBAAiB;;GAE1B,OAAO;IACL,IAAI,UAAU;AACZ,YAAO,QAAQ;;IAEjB,IAAI,eAAe;AACjB,YAAO,qBAAqB;;IAE/B;GACD,kBAAkB,YAAY;AAC5B,YAAQ,QAAQ,OAAO,YAAY,aAAa,QAAQ,QAAQ,MAAM,GAAG;;GAE3E,sBAAsB;GACtB,IAAI,qBAAqB;AACvB,WAAO,MAAM,cAAc;;GAE7B,IAAI,0BAA0B;AAC5B,WAAO,MAAM,cAAc;;GAE7B,iBAAiB,iBAAiB;GAClC,mBAAmB,mBAAmB;GACvC,CAAA;;EAID,MAAM,aAAa,eAAwB;AACzC,OAAI,MAAM,gBAAgB,MAAO,QAAO;AACxC,OAAI,MAAM,gBAAgB,KAAM,QAAO;AACvC,OAAI,OAAO,MAAM,gBAAgB,SAAU,QAAO,MAAM,KAAK,SAAS,MAAM;AAC5E,UAAO;IACR;EAGD,MAAM,qBAAqB,eAA4B,qBAAoB;EAU3E,MAAM,iBAAiB,IAAmC,KAAI;EAG9D,MAAM,UAAU,eAA4B,UAAS;EAErD,MAAM,WAAW,eAAe,MAAM,KAAK,OAAM;EACjD,MAAM,cAAc,eAAe;GACjC,MAAM,aAAa,MAAM,iBAAiB,CAAC;AAC3C,UAAO,aAAa,WAAW,QAAQ,SAAS;IACjD;EAED,SAAS,eAAe,UAAkB,aAAyC;GACjF,MAAM,OAAO,QAAQ;AACrB,OAAI,CAAC,KAAM,QAAO;AAIlB,OAAI,WAAW,SAAS,eAAe,MACrC,gBAAe,MAAM,cAAc,SAAQ;AAE7C,UAAO,KAAK,cACV,oBAAoB,SAAS,qBAAqB,YAAY,IAChE;;EAGF,MAAM,cAAc,oBAAoB;GAAE;GAAU;GAAa;GAAgB,CAAA;EAGjF,MAAM,mBAAmB,eAAe,MAAM,cAAc,OAAM;EAClE,MAAM,gBAAgB,eAAe,MAAM,aAAa,OAAM;EAG9D,MAAM,sBAAsB,IAAmB,KAAI;EAEnD,SAAS,eAAe,UAAkB,OAAmB;AAC3D,OAAI,MAAM,cAAc,OAAQ;GAChC,MAAM,OAAO,MAAM,aAAa,CAAC;AACjC,OAAI,MAAM,cAAc,cAAc,MAAM,YAAY,oBAAoB,UAAU,MAAM;IAC1F,MAAM,CAAC,OAAO,OAAO,CAAC,oBAAoB,OAAO,SAAS,CAAC,MAAM,GAAG,MAAM,IAAI,EAAC;IAC/E,MAAM,OAA0B,EAAE,GAAG,qBAAqB,OAAM;AAChE,SAAK,IAAI,IAAI,OAAO,KAAK,KAAK,KAAK;KACjC,MAAM,IAAI,KAAK;AACf,SAAI,EAAG,MAAK,EAAE,MAAM;;AAEtB,uBAAmB,KAAI;;AAEzB,uBAAoB,QAAQ;;EAI9B,MAAM,aAAa,eAAe,MAAM,WAAW,UAAS;EAC5D,MAAM,aAAa,YAAY;AAE/B,kBAAgB;GACd;GACA;GACA;GACA;GACA,SAAS;GACT;GACD,CAAA;EAGD,MAAM,UAAU,eAAe,cAAc,EAAE,SAAS,WAAW,OAAO,CAAC,CAAA;AAE3E,WAAa;GAAE;GAAO;GAAa;GAAgB,CAAA;;uBAIjD,mBAkDM,OAAA,EAlDA,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,MAAI,EAAIA,KAAAA,OAAO,OAAiB,MAAM,YAAY,KAAI,CAAA,EAAA,EAAA,CAM1F,mBA2CM,OAAA;aA1CA;IAAJ,KAAI;IACH,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,iBAAe,EAAI,MAAM,YAAY,gBAAe,CAAA;IACpF,OAAK,eAAE,WAAA,QAAU;KAAA,QAAA;KAAA,UAAA;KAAA,GAA2C,KAAA,EAAS;OAEtE,mBAqCQ,SAAA;IApCL,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,SAAO,EAAI,MAAM,YAAY,QAAO,CAAA;aACjE;IAAJ,KAAI;IACJ,MAAK;IACJ,cAAY,QAAA;IACZ,iBAAe,SAAA;IACf,iBAAe,YAAA;IACf,WAAO,OAAA,OAAA,OAAA,MAAA,GAAA,SAAE,MAAA,YAAW,CAAC,aAAZ,MAAA,YAAW,CAAC,UAAS,GAAA,KAAA;;IAE/B,YAEE,qBAAA,EADC,eAAW;KAAA,QAAY,MAAM,YAAY;KAAM,KAAO,MAAM,YAAY;KAAG,QAAU,MAAM,YAAY;KAAM,EAAA,EAAA,MAAA,GAAA,CAAA,cAAA,CAAA;KAGvG,WAAA,SAAA,WAAA,EADT,YAUY,mBAAA;;KART,eAAW;MAAA,MAAU,MAAM,YAAY;MAAI,KAAO,MAAM,YAAY;MAAG,MAAQ,MAAM,YAAY;MAAI;;KAE3F,MAAI,SAAE,cAAS,CACxB,WAGE,KAAA,QAAA,QAAA,eAAA,mBADQ,UAAS,CAAA,CAAA,CAAA,CAAA;;4CAIvB,YAOE,0BAAA;;cALI;KAAJ,KAAI;KACH,kBAAgB,mBAAA;KAChB,wBAAsB,QAAA;KACtB,UAAU,QAAA;KACV,eAAW;MAAA,MAAU,MAAM,YAAY;MAAI,KAAO,MAAM,YAAY;MAAG,MAAQ,MAAM,YAAY;MAAI;;;;;;;IAGhGC,KAAAA,OAAO,UAAA,WAAA,EADf,YAKc,qBAAA;;KAHX,eAAW,EAAA,QAAY,MAAM,YAAY,QAAM;;4BAE1B,CAAtB,WAAsB,KAAA,QAAA,SAAA,CAAA,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 , type ClassValue} 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?: ClassValue\n /** Override classes on individual slots */\n classNames?: Partial<{\n tabList: ClassValue\n }>\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class, props.classNames?.tabList)\"\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class, props.classNames?.tabList)\"\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class, props.classNames?.tabList)\"\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 :is-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 , type ClassValue} 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?: ClassValue\n /** Override classes on individual slots */\n classNames?: Partial<{\n tabList: ClassValue\n }>\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class, props.classNames?.tabList)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n :class=\"[composeClassName(ctx.slotFns.value.tabListContainer(), 'tabs__list-container--arrows'), { '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=\"ctx.slotFns.value.scrollWrapper()\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class, props.classNames?.tabList)\"\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=\"composeClassName(ctx.slotFns.value.tabListContainer(), 'tabs__list-container--dropdown')\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class, props.classNames?.tabList)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n :class=\"[ctx.slotFns.value.more(), { 'tabs__more--visible': hasOverflow }]\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :class=\"ctx.slotFns.value.moreBtn()\"\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=\"ctx.slotFns.value.overflowMenu()\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n :class=\"ctx.slotFns.value.overflowItem()\"\n role=\"menuitem\"\n :is-disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -5,11 +5,6 @@ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock
5
5
  import { onClickOutside, useResizeObserver } from "@vueuse/core";
6
6
  import { TabsList } from "reka-ui";
7
7
  //#region src/components/tabs/TabList.vue?vue&type=script&setup=true&lang.ts
8
- var _hoisted_1 = {
9
- key: 0,
10
- class: "tabs__overflow-menu",
11
- role: "menu"
12
- };
13
8
  var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
14
9
  __name: "TabList",
15
10
  props: {
@@ -178,7 +173,7 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
178
173
  "class"
179
174
  ])) : props.overflow === "arrows" ? (openBlock(), createElementBlock("div", {
180
175
  key: 1,
181
- class: normalizeClass(["tabs__list-container tabs__list-container--arrows", {
176
+ class: normalizeClass([unref(composeClassName)(unref(ctx).slotFns.value.tabListContainer(), "tabs__list-container--arrows"), {
182
177
  "has-left": canScrollLeft.value,
183
178
  "has-right": canScrollRight.value
184
179
  }])
@@ -211,7 +206,7 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
211
206
  createElementVNode("div", {
212
207
  ref_key: "scrollWrapperEl",
213
208
  ref: scrollWrapperEl,
214
- class: "tabs__scroll-wrapper"
209
+ class: normalizeClass(unref(ctx).slotFns.value.scrollWrapper())
215
210
  }, [createVNode(unref(TabsList), {
216
211
  loop: props.loop ?? true,
217
212
  as: props.as,
@@ -225,7 +220,7 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
225
220
  "as",
226
221
  "as-child",
227
222
  "class"
228
- ])], 512),
223
+ ])], 2),
229
224
  createVNode(Button_default, {
230
225
  variant: "secondary",
231
226
  size: "sm",
@@ -255,7 +250,7 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
255
250
  key: 2,
256
251
  ref_key: "containerEl",
257
252
  ref: containerEl,
258
- class: "tabs__list-container tabs__list-container--dropdown"
253
+ class: normalizeClass(unref(composeClassName)(unref(ctx).slotFns.value.tabListContainer(), "tabs__list-container--dropdown"))
259
254
  }, [createVNode(unref(TabsList), {
260
255
  loop: props.loop ?? true,
261
256
  as: props.as,
@@ -272,12 +267,12 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
272
267
  ]), createElementVNode("div", {
273
268
  ref_key: "dropdownEl",
274
269
  ref: dropdownEl,
275
- class: normalizeClass(["tabs__more", { "tabs__more--visible": hasOverflow.value }])
270
+ class: normalizeClass([unref(ctx).slotFns.value.more(), { "tabs__more--visible": hasOverflow.value }])
276
271
  }, [createVNode(Button_default, {
277
272
  variant: "secondary",
278
273
  size: "sm",
279
274
  radius: "full",
280
- class: "tabs__more-btn",
275
+ class: normalizeClass(unref(ctx).slotFns.value.moreBtn()),
281
276
  "aria-expanded": dropdownOpen.value,
282
277
  "aria-haspopup": "menu",
283
278
  onClick: _cache[2] || (_cache[2] = ($event) => dropdownOpen.value = !dropdownOpen.value)
@@ -296,20 +291,28 @@ var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
296
291
  "stroke-linejoin": "round"
297
292
  })], -1))]),
298
293
  _: 1
299
- }, 8, ["aria-expanded"]), dropdownOpen.value ? (openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(hiddenTabs.value, (tab) => {
294
+ }, 8, ["class", "aria-expanded"]), dropdownOpen.value ? (openBlock(), createElementBlock("div", {
295
+ key: 0,
296
+ class: normalizeClass(unref(ctx).slotFns.value.overflowMenu()),
297
+ role: "menu"
298
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(hiddenTabs.value, (tab) => {
300
299
  return openBlock(), createBlock(Button_default, {
301
300
  key: tab.value,
302
301
  variant: "ghost",
303
302
  radius: "lg",
304
- class: "tabs__overflow-item",
303
+ class: normalizeClass(unref(ctx).slotFns.value.overflowItem()),
305
304
  role: "menuitem",
306
305
  "is-disabled": tab.disabled,
307
306
  onClick: ($event) => selectOverflowTab(tab.value)
308
307
  }, {
309
308
  default: withCtx(() => [createTextVNode(toDisplayString(tab.label), 1)]),
310
309
  _: 2
311
- }, 1032, ["is-disabled", "onClick"]);
312
- }), 128))])) : createCommentVNode("", true)], 2)], 512)) : createCommentVNode("", true);
310
+ }, 1032, [
311
+ "class",
312
+ "is-disabled",
313
+ "onClick"
314
+ ]);
315
+ }), 128))], 2)) : createCommentVNode("", true)], 2)], 2)) : createCommentVNode("", true);
313
316
  };
314
317
  }
315
318
  });
@@ -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 , type ClassValue} 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?: ClassValue\n /** Override classes on individual slots */\n classNames?: Partial<{\n tabList: ClassValue\n }>\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class, props.classNames?.tabList)\"\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class, props.classNames?.tabList)\"\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class, props.classNames?.tabList)\"\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 :is-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 , type ClassValue} 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?: ClassValue\n /** Override classes on individual slots */\n classNames?: Partial<{\n tabList: ClassValue\n }>\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\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 :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class, props.classNames?.tabList)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n :class=\"[composeClassName(ctx.slotFns.value.tabListContainer(), 'tabs__list-container--arrows'), { '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=\"ctx.slotFns.value.scrollWrapper()\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class, props.classNames?.tabList)\"\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=\"composeClassName(ctx.slotFns.value.tabListContainer(), 'tabs__list-container--dropdown')\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class, props.classNames?.tabList)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n :class=\"[ctx.slotFns.value.more(), { 'tabs__more--visible': hasOverflow }]\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :class=\"ctx.slotFns.value.moreBtn()\"\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=\"ctx.slotFns.value.overflowMenu()\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n :class=\"ctx.slotFns.value.overflowItem()\"\n role=\"menuitem\"\n :is-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 +1 @@
1
- {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/tabs/Tabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, watch } from 'vue'\nimport { TabsRoot } from 'reka-ui'\nimport { tabsVariants, type TabsVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTabsProvide } from './tabs.context'\nimport TabList from './TabList.vue'\nimport Tab from './Tab.vue'\nimport TabPanel from './TabPanel.vue'\n\ntype TabShorthandItem = { value: string; label: string; content?: string; disabled?: boolean }\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n defaultValue?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: TabsVariants['variant']\n activationMode?: 'automatic' | 'manual'\n class?: ClassValue\n /** Override classes for individual slots */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render tabs from an array instead of the compound slot API */\n items?: TabShorthandItem[]\n /** Reading direction of the tabs. */\n dir?: 'ltr' | 'rtl'\n /** Whether to unmount tab panels when they are hidden. */\n unmountOnHide?: boolean\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n}>(), {\n orientation: 'horizontal',\n variant: 'primary',\n activationMode: 'automatic',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst internalValue = ref<string | undefined>(props.modelValue ?? props.defaultValue)\n\nwatch(() => props.modelValue, (v) => {\n if (v !== undefined) internalValue.value = v\n})\n\nwatch(\n () => props.items,\n (items) => {\n if (items && items.length > 0 && !props.modelValue && !props.defaultValue && internalValue.value === undefined) {\n internalValue.value = items[0].value\n }\n },\n { immediate: true },\n)\n\nfunction changeTab(value: string) {\n internalValue.value = value\n emit('update:modelValue', value)\n}\n\nconst slotFns = computed(() => tabsVariants({ variant: props.variant }))\n\nuseTabsProvide({\n slotFns,\n orientation: toRef(props, 'orientation'),\n currentValue: internalValue,\n changeTab,\n})\n</script>\n\n<template>\n <TabsRoot\n :model-value=\"internalValue\"\n :orientation=\"props.orientation\"\n :activation-mode=\"props.activationMode\"\n :dir=\"props.dir\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n :data-orientation=\"props.orientation\"\n @update:model-value=\"changeTab\"\n >\n <template v-if=\"props.items\">\n <TabList>\n <Tab\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n >{{ item.label }}</Tab>\n </TabList>\n <TabPanel\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n >{{ item.content }}</TabPanel>\n </template>\n <slot v-else />\n </TabsRoot>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/tabs/Tabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, watch } from 'vue'\nimport { TabsRoot } from 'reka-ui'\nimport { tabsVariants, type TabsVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTabsProvide } from './tabs.context'\nimport TabList from './TabList.vue'\nimport Tab from './Tab.vue'\nimport TabPanel from './TabPanel.vue'\n\ntype TabShorthandItem = {\n value: string\n label: string\n content?: string\n disabled?: boolean\n class?: ClassValue\n classNames?: Partial<{ tab: ClassValue }>\n panelClass?: ClassValue\n panelClassNames?: Partial<{ tabPanel: ClassValue }>\n}\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n defaultValue?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: TabsVariants['variant']\n activationMode?: 'automatic' | 'manual'\n class?: ClassValue\n /** Override classes for individual slots */\n classNames?: Partial<{\n base: ClassValue\n tabList: ClassValue\n }>\n /** Shorthand API: render tabs from an array instead of the compound slot API */\n items?: TabShorthandItem[]\n /** Reading direction of the tabs. */\n dir?: 'ltr' | 'rtl'\n /** Whether to unmount tab panels when they are hidden. */\n unmountOnHide?: boolean\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n /** Whether keyboard navigation loops from last to first tab. Forwarded to the shorthand-rendered TabList. */\n loop?: boolean\n /** Overflow behaviour for the shorthand-rendered TabList. */\n overflow?: 'arrows' | 'dropdown'\n}>(), {\n orientation: 'horizontal',\n variant: 'primary',\n activationMode: 'automatic',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst internalValue = ref<string | undefined>(props.modelValue ?? props.defaultValue)\n\nwatch(() => props.modelValue, (v) => {\n if (v !== undefined) internalValue.value = v\n})\n\nwatch(\n () => props.items,\n (items) => {\n if (items && items.length > 0 && !props.modelValue && !props.defaultValue && internalValue.value === undefined) {\n internalValue.value = items[0].value\n }\n },\n { immediate: true },\n)\n\nfunction changeTab(value: string) {\n internalValue.value = value\n emit('update:modelValue', value)\n}\n\nconst slotFns = computed(() => tabsVariants({ variant: props.variant }))\n\nuseTabsProvide({\n slotFns,\n orientation: toRef(props, 'orientation'),\n currentValue: internalValue,\n changeTab,\n})\n</script>\n\n<template>\n <TabsRoot\n :model-value=\"internalValue\"\n :orientation=\"props.orientation\"\n :activation-mode=\"props.activationMode\"\n :dir=\"props.dir\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n :data-orientation=\"props.orientation\"\n @update:model-value=\"changeTab\"\n >\n <template v-if=\"props.items\">\n <TabList\n :loop=\"props.loop\"\n :overflow=\"props.overflow\"\n :class-names=\"{ tabList: props.classNames?.tabList }\"\n >\n <Tab\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :class=\"item.class\"\n :class-names=\"item.classNames\"\n >{{ item.label }}</Tab>\n </TabList>\n <TabPanel\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :class=\"item.panelClass\"\n :class-names=\"item.panelClassNames\"\n >{{ item.content }}</TabPanel>\n </template>\n <slot v-else />\n </TabsRoot>\n</template>\n"],"mappings":""}
@@ -27,7 +27,9 @@ var Tabs_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
27
27
  dir: {},
28
28
  unmountOnHide: { type: Boolean },
29
29
  as: {},
30
- asChild: { type: Boolean }
30
+ asChild: { type: Boolean },
31
+ loop: { type: Boolean },
32
+ overflow: {}
31
33
  },
32
34
  emits: ["update:modelValue"],
33
35
  setup(__props, { emit: __emit }) {
@@ -64,26 +66,47 @@ var Tabs_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
64
66
  "data-orientation": props.orientation,
65
67
  "onUpdate:modelValue": changeTab
66
68
  }, {
67
- default: withCtx(() => [props.items ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(TabList_default, null, {
69
+ default: withCtx(() => [props.items ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(TabList_default, {
70
+ loop: props.loop,
71
+ overflow: props.overflow,
72
+ "class-names": { tabList: props.classNames?.tabList }
73
+ }, {
68
74
  default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(props.items, (item) => {
69
75
  return openBlock(), createBlock(Tab_default, {
70
76
  key: item.value,
71
77
  value: item.value,
72
- "is-disabled": item.disabled
78
+ "is-disabled": item.disabled,
79
+ class: normalizeClass(item.class),
80
+ "class-names": item.classNames
73
81
  }, {
74
82
  default: withCtx(() => [createTextVNode(toDisplayString(item.label), 1)]),
75
83
  _: 2
76
- }, 1032, ["value", "is-disabled"]);
84
+ }, 1032, [
85
+ "value",
86
+ "is-disabled",
87
+ "class",
88
+ "class-names"
89
+ ]);
77
90
  }), 128))]),
78
91
  _: 1
79
- }), (openBlock(true), createElementBlock(Fragment, null, renderList(props.items, (item) => {
92
+ }, 8, [
93
+ "loop",
94
+ "overflow",
95
+ "class-names"
96
+ ]), (openBlock(true), createElementBlock(Fragment, null, renderList(props.items, (item) => {
80
97
  return openBlock(), createBlock(TabPanel_default, {
81
98
  key: item.value,
82
- value: item.value
99
+ value: item.value,
100
+ class: normalizeClass(item.panelClass),
101
+ "class-names": item.panelClassNames
83
102
  }, {
84
103
  default: withCtx(() => [createTextVNode(toDisplayString(item.content), 1)]),
85
104
  _: 2
86
- }, 1032, ["value"]);
105
+ }, 1032, [
106
+ "value",
107
+ "class",
108
+ "class-names"
109
+ ]);
87
110
  }), 128))], 64)) : renderSlot(_ctx.$slots, "default", { key: 1 })]),
88
111
  _: 3
89
112
  }, 8, [
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/Tabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, watch } from 'vue'\nimport { TabsRoot } from 'reka-ui'\nimport { tabsVariants, type TabsVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTabsProvide } from './tabs.context'\nimport TabList from './TabList.vue'\nimport Tab from './Tab.vue'\nimport TabPanel from './TabPanel.vue'\n\ntype TabShorthandItem = { value: string; label: string; content?: string; disabled?: boolean }\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n defaultValue?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: TabsVariants['variant']\n activationMode?: 'automatic' | 'manual'\n class?: ClassValue\n /** Override classes for individual slots */\n classNames?: Partial<{\n base: ClassValue\n }>\n /** Shorthand API: render tabs from an array instead of the compound slot API */\n items?: TabShorthandItem[]\n /** Reading direction of the tabs. */\n dir?: 'ltr' | 'rtl'\n /** Whether to unmount tab panels when they are hidden. */\n unmountOnHide?: boolean\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n}>(), {\n orientation: 'horizontal',\n variant: 'primary',\n activationMode: 'automatic',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst internalValue = ref<string | undefined>(props.modelValue ?? props.defaultValue)\n\nwatch(() => props.modelValue, (v) => {\n if (v !== undefined) internalValue.value = v\n})\n\nwatch(\n () => props.items,\n (items) => {\n if (items && items.length > 0 && !props.modelValue && !props.defaultValue && internalValue.value === undefined) {\n internalValue.value = items[0].value\n }\n },\n { immediate: true },\n)\n\nfunction changeTab(value: string) {\n internalValue.value = value\n emit('update:modelValue', value)\n}\n\nconst slotFns = computed(() => tabsVariants({ variant: props.variant }))\n\nuseTabsProvide({\n slotFns,\n orientation: toRef(props, 'orientation'),\n currentValue: internalValue,\n changeTab,\n})\n</script>\n\n<template>\n <TabsRoot\n :model-value=\"internalValue\"\n :orientation=\"props.orientation\"\n :activation-mode=\"props.activationMode\"\n :dir=\"props.dir\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n :data-orientation=\"props.orientation\"\n @update:model-value=\"changeTab\"\n >\n <template v-if=\"props.items\">\n <TabList>\n <Tab\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n >{{ item.label }}</Tab>\n </TabList>\n <TabPanel\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n >{{ item.content }}</TabPanel>\n </template>\n <slot v-else />\n </TabsRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYA,MAAM,QAAQ;EA2Bd,MAAM,OAAO;EAIb,MAAM,gBAAgB,IAAwB,MAAM,cAAc,MAAM,aAAY;AAEpF,cAAY,MAAM,aAAa,MAAM;AACnC,OAAI,MAAM,KAAA,EAAW,eAAc,QAAQ;IAC5C;AAED,cACQ,MAAM,QACX,UAAU;AACT,OAAI,SAAS,MAAM,SAAS,KAAK,CAAC,MAAM,cAAc,CAAC,MAAM,gBAAgB,cAAc,UAAU,KAAA,EACnG,eAAc,QAAQ,MAAM,GAAG;KAGnC,EAAE,WAAW,MAAM,CACrB;EAEA,SAAS,UAAU,OAAe;AAChC,iBAAc,QAAQ;AACtB,QAAK,qBAAqB,MAAK;;EAGjC,MAAM,UAAU,eAAe,aAAa,EAAE,SAAS,MAAM,SAAS,CAAC,CAAA;AAEvE,iBAAe;GACb;GACA,aAAa,MAAM,OAAO,cAAc;GACxC,cAAc;GACd;GACD,CAAA;;uBAIC,YA4BW,MAAA,SAAA,EAAA;IA3BR,eAAa,cAAA;IACb,aAAa,MAAM;IACnB,mBAAiB,MAAM;IACvB,KAAK,MAAM;IACX,mBAAiB,MAAM;IACvB,IAAI,MAAM;IACV,YAAU,MAAM;IAChB,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,MAAI,EAAI,MAAM,OAAO,MAAM,YAAY,KAAI,CAAA;IAC3E,oBAAkB,MAAM;IACxB,uBAAoB;;2BAgBV,CAdK,MAAM,SAAA,WAAA,EAAtB,mBAcW,UAAA,EAAA,KAAA,GAAA,EAAA,CAbT,YAOU,iBAAA,MAAA;4BALqB,EAAA,UAAA,KAAA,EAD7B,mBAKuB,UAAA,MAAA,WAJN,MAAM,QAAd,SAAI;0BADb,YAKuB,aAAA;OAHpB,KAAK,KAAK;OACV,OAAO,KAAK;OACZ,eAAa,KAAK;;8BACJ,CAAA,gBAAA,gBAAb,KAAK,MAAK,EAAA,EAAA,CAAA,CAAA;;;;;0BAEhB,mBAI8B,UAAA,MAAA,WAHb,MAAM,QAAd,SAAI;yBADb,YAI8B,kBAAA;MAF3B,KAAK,KAAK;MACV,OAAO,KAAK;;6BACI,CAAA,gBAAA,gBAAf,KAAK,QAAO,EAAA,EAAA,CAAA,CAAA;;;uBAElB,WAAe,KAAA,QAAA,WAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"Tabs.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/Tabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, watch } from 'vue'\nimport { TabsRoot } from 'reka-ui'\nimport { tabsVariants, type TabsVariants } from '@auronui/styles'\nimport { composeClassName , type ClassValue} from '../../utils/composeClassName'\nimport { useTabsProvide } from './tabs.context'\nimport TabList from './TabList.vue'\nimport Tab from './Tab.vue'\nimport TabPanel from './TabPanel.vue'\n\ntype TabShorthandItem = {\n value: string\n label: string\n content?: string\n disabled?: boolean\n class?: ClassValue\n classNames?: Partial<{ tab: ClassValue }>\n panelClass?: ClassValue\n panelClassNames?: Partial<{ tabPanel: ClassValue }>\n}\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n defaultValue?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: TabsVariants['variant']\n activationMode?: 'automatic' | 'manual'\n class?: ClassValue\n /** Override classes for individual slots */\n classNames?: Partial<{\n base: ClassValue\n tabList: ClassValue\n }>\n /** Shorthand API: render tabs from an array instead of the compound slot API */\n items?: TabShorthandItem[]\n /** Reading direction of the tabs. */\n dir?: 'ltr' | 'rtl'\n /** Whether to unmount tab panels when they are hidden. */\n unmountOnHide?: boolean\n /** Render as a different element type. */\n as?: string\n /** Merge props onto child element instead of rendering a wrapper. */\n asChild?: boolean\n /** Whether keyboard navigation loops from last to first tab. Forwarded to the shorthand-rendered TabList. */\n loop?: boolean\n /** Overflow behaviour for the shorthand-rendered TabList. */\n overflow?: 'arrows' | 'dropdown'\n}>(), {\n orientation: 'horizontal',\n variant: 'primary',\n activationMode: 'automatic',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst internalValue = ref<string | undefined>(props.modelValue ?? props.defaultValue)\n\nwatch(() => props.modelValue, (v) => {\n if (v !== undefined) internalValue.value = v\n})\n\nwatch(\n () => props.items,\n (items) => {\n if (items && items.length > 0 && !props.modelValue && !props.defaultValue && internalValue.value === undefined) {\n internalValue.value = items[0].value\n }\n },\n { immediate: true },\n)\n\nfunction changeTab(value: string) {\n internalValue.value = value\n emit('update:modelValue', value)\n}\n\nconst slotFns = computed(() => tabsVariants({ variant: props.variant }))\n\nuseTabsProvide({\n slotFns,\n orientation: toRef(props, 'orientation'),\n currentValue: internalValue,\n changeTab,\n})\n</script>\n\n<template>\n <TabsRoot\n :model-value=\"internalValue\"\n :orientation=\"props.orientation\"\n :activation-mode=\"props.activationMode\"\n :dir=\"props.dir\"\n :unmount-on-hide=\"props.unmountOnHide\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"composeClassName(slotFns.base(), props.class, props.classNames?.base)\"\n :data-orientation=\"props.orientation\"\n @update:model-value=\"changeTab\"\n >\n <template v-if=\"props.items\">\n <TabList\n :loop=\"props.loop\"\n :overflow=\"props.overflow\"\n :class-names=\"{ tabList: props.classNames?.tabList }\"\n >\n <Tab\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :is-disabled=\"item.disabled\"\n :class=\"item.class\"\n :class-names=\"item.classNames\"\n >{{ item.label }}</Tab>\n </TabList>\n <TabPanel\n v-for=\"item in props.items\"\n :key=\"item.value\"\n :value=\"item.value\"\n :class=\"item.panelClass\"\n :class-names=\"item.panelClassNames\"\n >{{ item.content }}</TabPanel>\n </template>\n <slot v-else />\n </TabsRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBA,MAAM,QAAQ;EAgCd,MAAM,OAAO;EAIb,MAAM,gBAAgB,IAAwB,MAAM,cAAc,MAAM,aAAY;AAEpF,cAAY,MAAM,aAAa,MAAM;AACnC,OAAI,MAAM,KAAA,EAAW,eAAc,QAAQ;IAC5C;AAED,cACQ,MAAM,QACX,UAAU;AACT,OAAI,SAAS,MAAM,SAAS,KAAK,CAAC,MAAM,cAAc,CAAC,MAAM,gBAAgB,cAAc,UAAU,KAAA,EACnG,eAAc,QAAQ,MAAM,GAAG;KAGnC,EAAE,WAAW,MAAM,CACrB;EAEA,SAAS,UAAU,OAAe;AAChC,iBAAc,QAAQ;AACtB,QAAK,qBAAqB,MAAK;;EAGjC,MAAM,UAAU,eAAe,aAAa,EAAE,SAAS,MAAM,SAAS,CAAC,CAAA;AAEvE,iBAAe;GACb;GACA,aAAa,MAAM,OAAO,cAAc;GACxC,cAAc;GACd;GACD,CAAA;;uBAIC,YAoCW,MAAA,SAAA,EAAA;IAnCR,eAAa,cAAA;IACb,aAAa,MAAM;IACnB,mBAAiB,MAAM;IACvB,KAAK,MAAM;IACX,mBAAiB,MAAM;IACvB,IAAI,MAAM;IACV,YAAU,MAAM;IAChB,OAAK,eAAE,MAAA,iBAAgB,CAAC,QAAA,MAAQ,MAAI,EAAI,MAAM,OAAO,MAAM,YAAY,KAAI,CAAA;IAC3E,oBAAkB,MAAM;IACxB,uBAAoB;;2BAwBV,CAtBK,MAAM,SAAA,WAAA,EAAtB,mBAsBW,UAAA,EAAA,KAAA,GAAA,EAAA,CArBT,YAaU,iBAAA;KAZP,MAAM,MAAM;KACZ,UAAU,MAAM;KAChB,eAAW,EAAA,SAAa,MAAM,YAAY,SAAO;;4BAGrB,EAAA,UAAA,KAAA,EAD7B,mBAOuB,UAAA,MAAA,WANN,MAAM,QAAd,SAAI;0BADb,YAOuB,aAAA;OALpB,KAAK,KAAK;OACV,OAAO,KAAK;OACZ,eAAa,KAAK;OAClB,OAAK,eAAE,KAAK,MAAK;OACjB,eAAa,KAAK;;8BACJ,CAAA,gBAAA,gBAAb,KAAK,MAAK,EAAA,EAAA,CAAA,CAAA;;;;;;;;;;;;;;0BAEhB,mBAM8B,UAAA,MAAA,WALb,MAAM,QAAd,SAAI;yBADb,YAM8B,kBAAA;MAJ3B,KAAK,KAAK;MACV,OAAO,KAAK;MACZ,OAAK,eAAE,KAAK,WAAU;MACtB,eAAa,KAAK;;6BACF,CAAA,gBAAA,gBAAf,KAAK,QAAO,EAAA,EAAA,CAAA,CAAA;;;;;;;uBAElB,WAAe,KAAA,QAAA,WAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}