@myghf/ui 0.1.0 → 0.2.0

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["$attrs","$slots","$attrs"],"sources":["../src/lib/cn.ts","../src/lib/date.ts","../src/lib/icons.ts","../src/components/icon/Icon.vue","../src/components/icon/Icon.vue","../src/components/button/Button.vue","../src/components/button/Button.vue","../src/components/input/Input.vue","../src/components/input/Input.vue","../src/components/textarea/Textarea.vue","../src/components/textarea/Textarea.vue","../src/components/password/Password.vue","../src/components/password/Password.vue","../src/components/checkbox/Checkbox.vue","../src/components/checkbox/Checkbox.vue","../src/components/tag/Tag.vue","../src/components/tag/Tag.vue","../src/components/tabs/Tabs.vue","../src/components/tabs/Tabs.vue","../src/components/tabs/TabsList.vue","../src/components/tabs/TabsList.vue","../src/components/tabs/TabsTrigger.vue","../src/components/tabs/TabsTrigger.vue","../src/components/tabs/TabsContent.vue","../src/components/tabs/TabsContent.vue","../src/components/select/Select.vue","../src/components/select/Select.vue","../src/components/select-button/SelectButton.vue","../src/components/select-button/SelectButton.vue","../src/components/date-picker/DatePicker.vue","../src/components/date-picker/DatePicker.vue","../src/components/dialog/Dialog.vue","../src/components/dialog/Dialog.vue","../src/components/dropdown-menu/DropdownMenu.vue","../src/components/dropdown-menu/DropdownMenu.vue","../src/components/dropdown-menu/DropdownMenuTrigger.vue","../src/components/dropdown-menu/DropdownMenuTrigger.vue","../src/components/dropdown-menu/DropdownMenuContent.vue","../src/components/dropdown-menu/DropdownMenuContent.vue","../src/components/dropdown-menu/DropdownMenuItem.vue","../src/components/dropdown-menu/DropdownMenuItem.vue","../src/components/transfer-list/TransferList.vue","../src/components/transfer-list/TransferList.vue","../src/components/table/Table.vue","../src/components/table/Table.vue","../src/components/table/TableHeader.vue","../src/components/table/TableBody.vue","../src/components/table/TableRow.vue","../src/components/table/TableRow.vue","../src/components/table/TableHead.vue","../src/components/table/TableHead.vue","../src/components/table/TableCell.vue","../src/components/table/TableCell.vue","../src/components/table/TableEmpty.vue","../src/components/table/TableEmpty.vue","../src/lib/pagination.ts","../src/components/table/TablePagination.vue","../src/components/table/TablePagination.vue","../src/lib/table.ts","../src/lib/tableInteractions.ts","../src/components/data-table/DataTable.vue","../src/components/data-table/DataTable.vue","../src/lib/tree.ts","../src/components/tree-table/TreeTable.vue","../src/components/tree-table/TreeTable.vue","../src/components/tree-select/TreeSelect.vue","../src/components/tree-select/TreeSelect.vue"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { CalendarDate, CalendarDateTime, getLocalTimeZone, type DateValue } from '@internationalized/date'\n\nexport function dateToValue(d: Date): CalendarDate {\n return new CalendarDate(d.getFullYear(), d.getMonth() + 1, d.getDate())\n}\n\nexport function valueToDate(v: DateValue): Date {\n if (v instanceof CalendarDateTime) return v.toDate(getLocalTimeZone())\n return new Date(v.year, v.month - 1, v.day)\n}\n\nexport function toMinutes(time: string): number {\n const [h, m] = time.split(':').map(Number)\n return h * 60 + (m || 0)\n}\n\nexport function toTime(minutes: number): string {\n const h = Math.floor(minutes / 60)\n const m = minutes % 60\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`\n}\n\nexport function clampTime(d: Date, time: string): Date {\n const out = new Date(d)\n out.setHours(Math.floor(toMinutes(time) / 60), toMinutes(time) % 60, 0, 0)\n return out\n}\n\nexport function sortRange(a: Date, b: Date): [Date, Date]\nexport function sortRange(a: Date | null, b: Date | null): [Date | null, Date | null]\nexport function sortRange(a: Date | null, b: Date | null): [Date | null, Date | null] {\n if (!a || !b) return [a, b]\n return a.getTime() <= b.getTime() ? [a, b] : [b, a]\n}\n\nexport function toISODate(d: Date): string {\n const m = d.getMonth() + 1\n const day = d.getDate()\n return `${d.getFullYear()}-${String(m).padStart(2, '0')}-${String(day).padStart(2, '0')}`\n}\n","export function toPascalCase(name: string): string {\n return name\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\nconst FALLBACK_ICON = 'circle'\n\n/**\n * Normalises a lucide icon reference to a kebab-case name: accepts `heart`,\n * `chart-line` or `ChevronDown`. An empty name falls back to a circle rather\n * than rendering nothing, so a gap is visible instead of silent.\n */\nexport function resolveIconName(name: string): string {\n const trimmed = name.trim()\n if (!trimmed) return FALLBACK_ICON\n return trimmed\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport * as Lucide from 'lucide-vue-next'\nimport { resolveIconName, toPascalCase } from '../../lib/icons'\n\nconst props = withDefaults(defineProps<{ name: string; size?: number }>(), { size: 16 })\n\nconst resolved = computed(() => {\n const lucide = Lucide as unknown as Record<string, unknown>\n const pascal = toPascalCase(resolveIconName(props.name))\n return (lucide[pascal] as typeof Lucide.Circle | undefined) ?? Lucide.Circle\n})\n</script>\n\n<template>\n <component :is=\"resolved\" :size=\"size\" aria-hidden=\"true\" data-icon :name=\"name\" />\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport * as Lucide from 'lucide-vue-next'\nimport { resolveIconName, toPascalCase } from '../../lib/icons'\n\nconst props = withDefaults(defineProps<{ name: string; size?: number }>(), { size: 16 })\n\nconst resolved = computed(() => {\n const lucide = Lucide as unknown as Record<string, unknown>\n const pascal = toPascalCase(resolveIconName(props.name))\n return (lucide[pascal] as typeof Lucide.Circle | undefined) ?? Lucide.Circle\n})\n</script>\n\n<template>\n <component :is=\"resolved\" :size=\"size\" aria-hidden=\"true\" data-icon :name=\"name\" />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst buttonVariants = tv({\n base: 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 data-[loading=true]:cursor-not-allowed',\n variants: {\n variant: {\n default: 'bg-primary-500 text-white hover:bg-primary-600',\n secondary: 'bg-secondary-500 text-white hover:bg-secondary-600',\n destructive: 'bg-error-500 text-white hover:bg-error-600',\n outline: 'border border-border bg-surface text-foreground hover:bg-surface-muted',\n ghost: 'text-foreground hover:bg-surface-muted',\n },\n size: {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n icon: 'size-9',\n 'icon-sm': 'size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n})\n\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof buttonVariants>['variant']\n size?: VariantProps<typeof buttonVariants>['size']\n type?: 'button' | 'submit' | 'reset'\n disabled?: boolean\n loading?: boolean\n /** Text label; equivalent to slot content. PrimeVue parity for the app migration. */\n label?: string\n }>(),\n { variant: 'default', size: 'default', type: 'button', disabled: false, loading: false },\n)\n\nconst attrs = useAttrs()\nconst isDisabled = computed(() => props.disabled || props.loading || Boolean(attrs.disabled))\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"isDisabled\"\n :data-loading=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <span v-if=\"loading\" class=\"size-4 animate-spin rounded-full border-2 border-current border-t-transparent\" aria-hidden=\"true\" />\n <slot v-else>{{ label }}</slot>\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst buttonVariants = tv({\n base: 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 data-[loading=true]:cursor-not-allowed',\n variants: {\n variant: {\n default: 'bg-primary-500 text-white hover:bg-primary-600',\n secondary: 'bg-secondary-500 text-white hover:bg-secondary-600',\n destructive: 'bg-error-500 text-white hover:bg-error-600',\n outline: 'border border-border bg-surface text-foreground hover:bg-surface-muted',\n ghost: 'text-foreground hover:bg-surface-muted',\n },\n size: {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n icon: 'size-9',\n 'icon-sm': 'size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n})\n\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof buttonVariants>['variant']\n size?: VariantProps<typeof buttonVariants>['size']\n type?: 'button' | 'submit' | 'reset'\n disabled?: boolean\n loading?: boolean\n /** Text label; equivalent to slot content. PrimeVue parity for the app migration. */\n label?: string\n }>(),\n { variant: 'default', size: 'default', type: 'button', disabled: false, loading: false },\n)\n\nconst attrs = useAttrs()\nconst isDisabled = computed(() => props.disabled || props.loading || Boolean(attrs.disabled))\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"isDisabled\"\n :data-loading=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <span v-if=\"loading\" class=\"size-4 animate-spin rounded-full border-2 border-current border-t-transparent\" aria-hidden=\"true\" />\n <slot v-else>{{ label }}</slot>\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n leadingIcon?: string\n trailingIcon?: string\n size?: 'sm' | 'default' | 'lg'\n }>(),\n { size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\n\ndefineExpose({ focus: () => inputRef.value?.focus() })\n</script>\n\n<template>\n <div class=\"relative w-full\">\n <Icon v-if=\"leadingIcon\" :name=\"leadingIcon\" class=\"pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n <input\n ref=\"inputRef\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n leadingIcon ? 'ps-9' : 'ps-3',\n trailingIcon ? 'pe-9' : 'pe-3',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <Icon v-if=\"trailingIcon\" :name=\"trailingIcon\" class=\"pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n leadingIcon?: string\n trailingIcon?: string\n size?: 'sm' | 'default' | 'lg'\n }>(),\n { size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\n\ndefineExpose({ focus: () => inputRef.value?.focus() })\n</script>\n\n<template>\n <div class=\"relative w-full\">\n <Icon v-if=\"leadingIcon\" :name=\"leadingIcon\" class=\"pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n <input\n ref=\"inputRef\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n leadingIcon ? 'ps-9' : 'ps-3',\n trailingIcon ? 'pe-9' : 'pe-3',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <Icon v-if=\"trailingIcon\" :name=\"trailingIcon\" class=\"pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useAttrs } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n }>(),\n { rows: 3 },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\n</script>\n\n<template>\n <textarea\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :class=\"[\n 'w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { useAttrs } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n }>(),\n { rows: 3 },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\n</script>\n\n<template>\n <textarea\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :class=\"[\n 'w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { Eye, EyeOff } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n feedback?: boolean\n /** Applied to the inner input so an external <label for> still matches. */\n id?: string\n }>(),\n { feedback: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst visible = ref(false)\nconst inputType = computed(() => (visible.value ? 'text' : 'password'))\n\nconst strength = computed(() => {\n const v = props.modelValue ?? ''\n if (v.length === 0) return 0\n let score = 0\n if (v.length >= 8) score++\n if (v.length >= 12) score++\n if (/[A-Z]/.test(v) && /[a-z]/.test(v)) score++\n if (/\\d/.test(v)) score++\n if (/[^A-Za-z0-9]/.test(v)) score++\n return Math.max(1, Math.min(4, Math.ceil((score / 5) * 4)))\n})\n</script>\n\n<template>\n <div class=\"w-full\">\n <div class=\"relative w-full\">\n <input\n :id=\"id\"\n :type=\"inputType\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex h-9 w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n 'pe-10',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <button\n type=\"button\"\n :disabled=\"disabled\"\n aria-label=\"Toggle password visibility\"\n class=\"absolute end-2 top-1/2 -translate-y-1/2 rounded p-1 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"visible = !visible\"\n >\n <EyeOff v-if=\"visible\" class=\"size-4\" />\n <Eye v-else class=\"size-4\" />\n </button>\n </div>\n <div v-if=\"feedback && modelValue\" class=\"mt-1.5 flex items-center gap-1.5\" aria-hidden=\"true\">\n <span\n v-for=\"i in 4\"\n :key=\"i\"\n class=\"h-1 flex-1 rounded-full transition-colors\"\n :class=\"i <= strength ? 'bg-success-500' : 'bg-surface-muted'\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { Eye, EyeOff } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n feedback?: boolean\n /** Applied to the inner input so an external <label for> still matches. */\n id?: string\n }>(),\n { feedback: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst visible = ref(false)\nconst inputType = computed(() => (visible.value ? 'text' : 'password'))\n\nconst strength = computed(() => {\n const v = props.modelValue ?? ''\n if (v.length === 0) return 0\n let score = 0\n if (v.length >= 8) score++\n if (v.length >= 12) score++\n if (/[A-Z]/.test(v) && /[a-z]/.test(v)) score++\n if (/\\d/.test(v)) score++\n if (/[^A-Za-z0-9]/.test(v)) score++\n return Math.max(1, Math.min(4, Math.ceil((score / 5) * 4)))\n})\n</script>\n\n<template>\n <div class=\"w-full\">\n <div class=\"relative w-full\">\n <input\n :id=\"id\"\n :type=\"inputType\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex h-9 w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n 'pe-10',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <button\n type=\"button\"\n :disabled=\"disabled\"\n aria-label=\"Toggle password visibility\"\n class=\"absolute end-2 top-1/2 -translate-y-1/2 rounded p-1 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"visible = !visible\"\n >\n <EyeOff v-if=\"visible\" class=\"size-4\" />\n <Eye v-else class=\"size-4\" />\n </button>\n </div>\n <div v-if=\"feedback && modelValue\" class=\"mt-1.5 flex items-center gap-1.5\" aria-hidden=\"true\">\n <span\n v-for=\"i in 4\"\n :key=\"i\"\n class=\"h-1 flex-1 rounded-full transition-colors\"\n :class=\"i <= strength ? 'bg-success-500' : 'bg-surface-muted'\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { CheckboxIndicator, CheckboxRoot } from 'reka-ui'\nimport { Check } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean\n disabled?: boolean\n id?: string\n }>(),\n { modelValue: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()\n</script>\n\n<template>\n <CheckboxRoot\n :id=\"id\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"peer size-4 shrink-0 rounded border border-border bg-surface shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 data-[state=checked]:border-primary-500 data-[state=checked]:bg-primary-500 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n @update:model-value=\"emit('update:modelValue', $event as boolean)\"\n >\n <CheckboxIndicator class=\"flex items-center justify-center text-white\">\n <Check class=\"size-3.5\" />\n </CheckboxIndicator>\n </CheckboxRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { CheckboxIndicator, CheckboxRoot } from 'reka-ui'\nimport { Check } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean\n disabled?: boolean\n id?: string\n }>(),\n { modelValue: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()\n</script>\n\n<template>\n <CheckboxRoot\n :id=\"id\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"peer size-4 shrink-0 rounded border border-border bg-surface shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 data-[state=checked]:border-primary-500 data-[state=checked]:bg-primary-500 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n @update:model-value=\"emit('update:modelValue', $event as boolean)\"\n >\n <CheckboxIndicator class=\"flex items-center justify-center text-white\">\n <Check class=\"size-3.5\" />\n </CheckboxIndicator>\n </CheckboxRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\nimport { X } from 'lucide-vue-next'\nimport Icon from '../icon/Icon.vue'\n\nconst tagVariants = tv({\n base: 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n variants: {\n tone: {\n info: 'bg-primary-100 text-primary-800',\n success: 'bg-success-100 text-success-800',\n warning: 'bg-warning-100 text-warning-800',\n danger: 'bg-error-100 text-error-800',\n secondary: 'bg-surface-muted text-foreground',\n },\n },\n defaultVariants: { tone: 'secondary' },\n})\n\nwithDefaults(\n defineProps<{\n tone?: VariantProps<typeof tagVariants>['tone']\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = NonNullable<VariantProps<typeof tagVariants>['tone']>\n</script>\n\n<template>\n <span :class=\"tagVariants({ tone })\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-3\" />\n <slot />\n <button\n v-if=\"removable\"\n type=\"button\"\n :aria-label=\"removeLabel\"\n class=\"-me-0.5 ms-0.5 rounded-full p-0.5 transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"emit('remove')\"\n >\n <X class=\"size-3\" />\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\nimport { X } from 'lucide-vue-next'\nimport Icon from '../icon/Icon.vue'\n\nconst tagVariants = tv({\n base: 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n variants: {\n tone: {\n info: 'bg-primary-100 text-primary-800',\n success: 'bg-success-100 text-success-800',\n warning: 'bg-warning-100 text-warning-800',\n danger: 'bg-error-100 text-error-800',\n secondary: 'bg-surface-muted text-foreground',\n },\n },\n defaultVariants: { tone: 'secondary' },\n})\n\nwithDefaults(\n defineProps<{\n tone?: VariantProps<typeof tagVariants>['tone']\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = NonNullable<VariantProps<typeof tagVariants>['tone']>\n</script>\n\n<template>\n <span :class=\"tagVariants({ tone })\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-3\" />\n <slot />\n <button\n v-if=\"removable\"\n type=\"button\"\n :aria-label=\"removeLabel\"\n class=\"-me-0.5 ms-0.5 rounded-full p-0.5 transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"emit('remove')\"\n >\n <X class=\"size-3\" />\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsRoot } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ modelValue?: string }>(), {})\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n</script>\n\n<template>\n <TabsRoot :model-value=\"modelValue\" @update:model-value=\"emit('update:modelValue', $event as string)\">\n <slot />\n </TabsRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsRoot } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ modelValue?: string }>(), {})\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n</script>\n\n<template>\n <TabsRoot :model-value=\"modelValue\" @update:model-value=\"emit('update:modelValue', $event as string)\">\n <slot />\n </TabsRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsList as RekaTabsList } from 'reka-ui'\n</script>\n\n<template>\n <RekaTabsList class=\"inline-flex h-9 w-full items-center justify-start gap-1 rounded-lg bg-surface-muted p-1 text-muted\">\n <slot />\n </RekaTabsList>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsList as RekaTabsList } from 'reka-ui'\n</script>\n\n<template>\n <RekaTabsList class=\"inline-flex h-9 w-full items-center justify-start gap-1 rounded-lg bg-surface-muted p-1 text-muted\">\n <slot />\n </RekaTabsList>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsTrigger as RekaTabsTrigger } from 'reka-ui'\n\ndefineProps<{ value: string; disabled?: boolean }>()\n</script>\n\n<template>\n <RekaTabsTrigger\n :value=\"value\"\n :disabled=\"disabled\"\n class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[disabled]:opacity-50\"\n >\n <slot />\n </RekaTabsTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsTrigger as RekaTabsTrigger } from 'reka-ui'\n\ndefineProps<{ value: string; disabled?: boolean }>()\n</script>\n\n<template>\n <RekaTabsTrigger\n :value=\"value\"\n :disabled=\"disabled\"\n class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[disabled]:opacity-50\"\n >\n <slot />\n </RekaTabsTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsContent as RekaTabsContent } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ value: string; padding?: boolean }>(), { padding: true })\n</script>\n\n<template>\n <RekaTabsContent :value=\"value\" :class=\"['focus-visible:outline-none', padding ? 'pt-4' : '']\">\n <slot />\n </RekaTabsContent>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsContent as RekaTabsContent } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ value: string; padding?: boolean }>(), { padding: true })\n</script>\n\n<template>\n <RekaTabsContent :value=\"value\" :class=\"['focus-visible:outline-none', padding ? 'pt-4' : '']\">\n <slot />\n </RekaTabsContent>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n SelectContent,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectRoot,\n SelectTrigger,\n SelectValue,\n type AcceptableValue,\n} from 'reka-ui'\nimport { Check, ChevronDown, X } from 'lucide-vue-next'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue | AcceptableValue[]\n options?: unknown[]\n optionLabel?: string\n optionValue?: string\n placeholder?: string\n clearable?: boolean\n disabled?: boolean\n multiple?: boolean\n size?: 'sm' | 'default'\n invalid?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst open = ref(false)\n\n/** Options may be objects (optionLabel/optionValue) or primitives, as PrimeVue allowed. */\nfunction valueOf(opt: unknown): AcceptableValue {\n if (opt && typeof opt === 'object' && props.optionValue) {\n return ((opt as Record<string, unknown>)[props.optionValue] ?? opt) as AcceptableValue\n }\n return opt as AcceptableValue\n}\nfunction labelOf(opt: unknown): string {\n if (opt && typeof opt === 'object' && props.optionLabel) {\n return String((opt as Record<string, unknown>)[props.optionLabel] ?? '')\n }\n return opt == null ? '' : String(opt)\n}\n\nconst display = computed(() => {\n if (props.multiple) {\n const sel = (Array.isArray(props.modelValue) ? props.modelValue : []) as unknown[]\n return sel\n .map((v) => labelOf(props.options?.find((o) => valueOf(o) === v)))\n .filter(Boolean)\n .join(', ')\n }\n return props.modelValue == null\n ? ''\n : labelOf(props.options?.find((o) => valueOf(o) === props.modelValue))\n})\n\nconst hasValue = computed(() =>\n props.multiple && Array.isArray(props.modelValue)\n ? (props.modelValue as unknown[]).length > 0\n : props.modelValue != null,\n)\n\nfunction onClear() {\n emit('update:modelValue', props.multiple ? [] : null)\n}\n</script>\n\n<template>\n <SelectRoot\n v-model:open=\"open\"\n :model-value=\"modelValue\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <SelectTrigger\n :class=\"cn(\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n $attrs.class as string || '',\n )\"\n v-bind=\"$attrs\"\n >\n <SelectValue :placeholder=\"placeholder\">\n <span class=\"truncate\">{{ display || placeholder }}</span>\n </SelectValue>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">\n <button\n v-if=\"clearable && hasValue\"\n type=\"button\"\n aria-label=\"Clear selection\"\n class=\"rounded p-0.5 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"onClear\"\n >\n <X class=\"size-3.5\" />\n </button>\n <ChevronDown class=\"size-4 opacity-50\" />\n </span>\n </SelectTrigger>\n <!-- reka-ui keeps an empty placeholder <div> in the DOM while the select is\n closed. In any `gap-*` flex container that extra zero-size item adds a\n gap, which vanishes when the popper opens — shifting sibling labels and\n controls. Rendering the content only while open drops the placeholder. -->\n <SelectContent\n v-if=\"open\"\n position=\"popper\"\n :side-offset=\"4\"\n class=\"z-50 min-w-[--reka-select-trigger-width] rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <SelectItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n class=\"relative flex cursor-pointer select-none items-center rounded px-2 py-1.5 pr-8 text-sm text-foreground outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[disabled]:opacity-50\"\n >\n <SelectItemText>{{ labelOf(opt) }}</SelectItemText>\n <SelectItemIndicator class=\"absolute end-2 flex items-center justify-center text-primary-600\">\n <Check class=\"size-4\" />\n </SelectItemIndicator>\n </SelectItem>\n </SelectContent>\n </SelectRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n SelectContent,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectRoot,\n SelectTrigger,\n SelectValue,\n type AcceptableValue,\n} from 'reka-ui'\nimport { Check, ChevronDown, X } from 'lucide-vue-next'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue | AcceptableValue[]\n options?: unknown[]\n optionLabel?: string\n optionValue?: string\n placeholder?: string\n clearable?: boolean\n disabled?: boolean\n multiple?: boolean\n size?: 'sm' | 'default'\n invalid?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst open = ref(false)\n\n/** Options may be objects (optionLabel/optionValue) or primitives, as PrimeVue allowed. */\nfunction valueOf(opt: unknown): AcceptableValue {\n if (opt && typeof opt === 'object' && props.optionValue) {\n return ((opt as Record<string, unknown>)[props.optionValue] ?? opt) as AcceptableValue\n }\n return opt as AcceptableValue\n}\nfunction labelOf(opt: unknown): string {\n if (opt && typeof opt === 'object' && props.optionLabel) {\n return String((opt as Record<string, unknown>)[props.optionLabel] ?? '')\n }\n return opt == null ? '' : String(opt)\n}\n\nconst display = computed(() => {\n if (props.multiple) {\n const sel = (Array.isArray(props.modelValue) ? props.modelValue : []) as unknown[]\n return sel\n .map((v) => labelOf(props.options?.find((o) => valueOf(o) === v)))\n .filter(Boolean)\n .join(', ')\n }\n return props.modelValue == null\n ? ''\n : labelOf(props.options?.find((o) => valueOf(o) === props.modelValue))\n})\n\nconst hasValue = computed(() =>\n props.multiple && Array.isArray(props.modelValue)\n ? (props.modelValue as unknown[]).length > 0\n : props.modelValue != null,\n)\n\nfunction onClear() {\n emit('update:modelValue', props.multiple ? [] : null)\n}\n</script>\n\n<template>\n <SelectRoot\n v-model:open=\"open\"\n :model-value=\"modelValue\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <SelectTrigger\n :class=\"cn(\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n $attrs.class as string || '',\n )\"\n v-bind=\"$attrs\"\n >\n <SelectValue :placeholder=\"placeholder\">\n <span class=\"truncate\">{{ display || placeholder }}</span>\n </SelectValue>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">\n <button\n v-if=\"clearable && hasValue\"\n type=\"button\"\n aria-label=\"Clear selection\"\n class=\"rounded p-0.5 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"onClear\"\n >\n <X class=\"size-3.5\" />\n </button>\n <ChevronDown class=\"size-4 opacity-50\" />\n </span>\n </SelectTrigger>\n <!-- reka-ui keeps an empty placeholder <div> in the DOM while the select is\n closed. In any `gap-*` flex container that extra zero-size item adds a\n gap, which vanishes when the popper opens — shifting sibling labels and\n controls. Rendering the content only while open drops the placeholder. -->\n <SelectContent\n v-if=\"open\"\n position=\"popper\"\n :side-offset=\"4\"\n class=\"z-50 min-w-[--reka-select-trigger-width] rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <SelectItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n class=\"relative flex cursor-pointer select-none items-center rounded px-2 py-1.5 pr-8 text-sm text-foreground outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[disabled]:opacity-50\"\n >\n <SelectItemText>{{ labelOf(opt) }}</SelectItemText>\n <SelectItemIndicator class=\"absolute end-2 flex items-center justify-center text-primary-600\">\n <Check class=\"size-4\" />\n </SelectItemIndicator>\n </SelectItem>\n </SelectContent>\n </SelectRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { RadioGroupIndicator, RadioGroupItem, RadioGroupRoot, type AcceptableValue } from 'reka-ui'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue\n options?: Record<string, unknown>[]\n optionLabel?: string\n optionValue?: string\n disabled?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst rootEl = ref<InstanceType<typeof RadioGroupRoot> | null>(null)\nconst indicator = ref({ left: 0, top: 0, width: 0, height: 0, ready: false })\nlet frame = 0\n\nfunction valueOf(opt: Record<string, unknown> | undefined): AcceptableValue {\n return (opt?.[props.optionValue as string] ?? opt) as AcceptableValue\n}\nfunction labelOf(opt: Record<string, unknown> | undefined): string {\n return String(opt?.[props.optionLabel as string] ?? opt ?? '')\n}\n\nfunction measure() {\n const root = rootEl.value?.$el as HTMLElement | undefined\n const checked = root?.querySelector<HTMLElement>('[role=\"radio\"][data-state=\"checked\"]')\n if (!checked) {\n indicator.value.ready = false\n return\n }\n indicator.value = {\n left: checked.offsetLeft,\n top: checked.offsetTop,\n width: checked.offsetWidth,\n height: checked.offsetHeight,\n ready: true,\n }\n}\n\nfunction scheduleMeasure() {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n}\n\nlet observer: ResizeObserver | undefined\n\nonMounted(() => {\n scheduleMeasure()\n if (typeof ResizeObserver !== 'undefined' && rootEl.value?.$el) {\n observer = new ResizeObserver(scheduleMeasure)\n observer.observe(rootEl.value.$el as HTMLElement)\n }\n window.addEventListener('resize', scheduleMeasure)\n})\n\nonBeforeUnmount(() => {\n cancelAnimationFrame(frame)\n observer?.disconnect()\n window.removeEventListener('resize', scheduleMeasure)\n})\n\nwatch(() => props.modelValue, scheduleMeasure)\nwatch(() => props.options, scheduleMeasure, { deep: true })\n</script>\n\n<template>\n <RadioGroupRoot\n ref=\"rootEl\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"relative inline-flex flex-wrap items-center gap-1 rounded-md border border-border bg-surface p-1\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <span\n v-show=\"indicator.ready\"\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute rounded bg-primary-500 transition-all duration-200 ease-out motion-reduce:transition-none\"\n :style=\"{\n left: `${indicator.left}px`,\n top: `${indicator.top}px`,\n width: `${indicator.width}px`,\n height: `${indicator.height}px`,\n }\"\n />\n <RadioGroupItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n :disabled=\"disabled\"\n class=\"relative inline-flex items-center justify-center rounded px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=checked]:text-white data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n >\n <RadioGroupIndicator class=\"hidden\" />\n {{ labelOf(opt) }}\n </RadioGroupItem>\n </RadioGroupRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { RadioGroupIndicator, RadioGroupItem, RadioGroupRoot, type AcceptableValue } from 'reka-ui'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue\n options?: Record<string, unknown>[]\n optionLabel?: string\n optionValue?: string\n disabled?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst rootEl = ref<InstanceType<typeof RadioGroupRoot> | null>(null)\nconst indicator = ref({ left: 0, top: 0, width: 0, height: 0, ready: false })\nlet frame = 0\n\nfunction valueOf(opt: Record<string, unknown> | undefined): AcceptableValue {\n return (opt?.[props.optionValue as string] ?? opt) as AcceptableValue\n}\nfunction labelOf(opt: Record<string, unknown> | undefined): string {\n return String(opt?.[props.optionLabel as string] ?? opt ?? '')\n}\n\nfunction measure() {\n const root = rootEl.value?.$el as HTMLElement | undefined\n const checked = root?.querySelector<HTMLElement>('[role=\"radio\"][data-state=\"checked\"]')\n if (!checked) {\n indicator.value.ready = false\n return\n }\n indicator.value = {\n left: checked.offsetLeft,\n top: checked.offsetTop,\n width: checked.offsetWidth,\n height: checked.offsetHeight,\n ready: true,\n }\n}\n\nfunction scheduleMeasure() {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n}\n\nlet observer: ResizeObserver | undefined\n\nonMounted(() => {\n scheduleMeasure()\n if (typeof ResizeObserver !== 'undefined' && rootEl.value?.$el) {\n observer = new ResizeObserver(scheduleMeasure)\n observer.observe(rootEl.value.$el as HTMLElement)\n }\n window.addEventListener('resize', scheduleMeasure)\n})\n\nonBeforeUnmount(() => {\n cancelAnimationFrame(frame)\n observer?.disconnect()\n window.removeEventListener('resize', scheduleMeasure)\n})\n\nwatch(() => props.modelValue, scheduleMeasure)\nwatch(() => props.options, scheduleMeasure, { deep: true })\n</script>\n\n<template>\n <RadioGroupRoot\n ref=\"rootEl\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"relative inline-flex flex-wrap items-center gap-1 rounded-md border border-border bg-surface p-1\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <span\n v-show=\"indicator.ready\"\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute rounded bg-primary-500 transition-all duration-200 ease-out motion-reduce:transition-none\"\n :style=\"{\n left: `${indicator.left}px`,\n top: `${indicator.top}px`,\n width: `${indicator.width}px`,\n height: `${indicator.height}px`,\n }\"\n />\n <RadioGroupItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n :disabled=\"disabled\"\n class=\"relative inline-flex items-center justify-center rounded px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=checked]:text-white data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n >\n <RadioGroupIndicator class=\"hidden\" />\n {{ labelOf(opt) }}\n </RadioGroupItem>\n </RadioGroupRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport { clampTime, sortRange, toISODate, toTime } from '../../lib/date'\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n size?: 'sm' | 'default'\n /** Applied to the trigger button so an external <label for> still matches. */\n inputId?: string\n }>(),\n { mode: 'date', placeholder: 'Select date', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst open = ref(false)\nconst viewDate = ref(new Date())\nconst start = ref<Date | null>(null)\nconst end = ref<Date | null>(null)\nconst time = ref('09:00')\n\nconst WEEKDAYS = [0, 1, 2, 3, 4, 5, 6]\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (Array.isArray(v)) {\n start.value = v[0] ?? null\n end.value = v[1] ?? null\n } else if (v instanceof Date) {\n start.value = v\n end.value = null\n } else {\n start.value = null\n end.value = null\n }\n },\n { immediate: true },\n)\n\nconst grid = computed(() => {\n const first = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), 1)\n const lead = (first.getDay() + 6) % 7 // Monday-first\n const cells: (Date | null)[] = Array.from({ length: lead }, () => null)\n const days = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + 1, 0).getDate()\n for (let d = 1; d <= days; d++) cells.push(new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), d))\n return cells\n})\n\nfunction inRange(d: Date): boolean {\n if (!start.value || !end.value) return false\n const [s, e] = sortRange(start.value, end.value)\n return d.getTime() >= s.getTime() && d.getTime() <= e.getTime()\n}\n\nfunction monthLabel(): string {\n return viewDate.value.toLocaleString('en', { month: 'long', year: 'numeric' })\n}\n\nfunction shiftMonth(n: number) {\n viewDate.value = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + n, 1)\n}\n\nfunction hasValue(): boolean {\n return props.mode === 'range' ? Boolean(start.value && end.value) : Boolean(start.value)\n}\n\nfunction pick(d: Date) {\n if (props.mode === 'range') {\n if (!start.value || end.value) {\n start.value = d\n end.value = null\n } else {\n const [s, e] = sortRange(start.value, d)\n start.value = s\n end.value = e\n }\n return\n }\n start.value = d\n if (props.mode === 'datetime') return // wait for Apply\n commit()\n open.value = false\n}\n\nfunction commit() {\n if (!start.value) return\n if (props.mode === 'range') {\n if (!end.value) return\n emit('update:modelValue', [start.value, end.value])\n } else if (props.mode === 'datetime') {\n emit('update:modelValue', clampTime(start.value, time.value))\n } else {\n emit('update:modelValue', start.value)\n }\n}\n\nfunction clear() {\n start.value = null\n end.value = null\n emit('update:modelValue', null)\n open.value = false\n}\n\nconst display = computed(() => {\n if (props.mode === 'range') {\n if (!start.value || !end.value) return ''\n const [s, e] = sortRange(start.value, end.value)\n return `${toISODate(s)} – ${toISODate(e)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n return `${toISODate(d)}${props.mode === 'datetime' ? ' ' + toTime(d.getHours() * 60 + d.getMinutes()) : ''}`\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n :id=\"inputId\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50 data-[state=open]:border-primary-500',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500' : '',\n ]\"\n >\n <span :class=\"['truncate', display ? 'text-foreground' : 'text-muted']\">{{ display || placeholder }}</span>\n <CalendarIcon class=\"size-4 shrink-0 text-muted\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n :side-offset=\"4\"\n class=\"z-50 rounded-md border border-border bg-surface p-3 shadow-popover\"\n >\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(-1)\"\n >\n <ChevronLeft class=\"size-4\" />\n </button>\n <span class=\"text-sm font-medium\">{{ monthLabel() }}</span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(1)\"\n >\n <ChevronRight class=\"size-4\" />\n </button>\n </div>\n\n <div class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"d in WEEKDAYS\" :key=\"d\" class=\"py-1 font-medium text-muted\">\n {{ new Date(2026, 0, 5 + d).toLocaleDateString('en', { weekday: 'short' }) }}\n </span>\n <template v-for=\"(cell, i) in grid\" :key=\"i\">\n <span v-if=\"!cell\" />\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'flex h-8 items-center justify-center rounded-md text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',\n inRange(cell) ? 'bg-primary-100 text-primary-800' : 'hover:bg-surface-muted',\n start && start.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n end && end.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n ]\"\n @click=\"pick(cell)\"\n >\n {{ cell.getDate() }}\n </button>\n </template>\n </div>\n\n <div v-if=\"mode === 'datetime'\" class=\"mt-3 flex items-center justify-between gap-2 border-t border-border pt-3\">\n <label class=\"flex items-center gap-2 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <input v-model=\"time\" type=\"time\" class=\"rounded border border-border bg-surface px-2 py-1 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\" />\n </label>\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n :disabled=\"!start\"\n class=\"rounded bg-primary-500 px-3 py-1 text-sm text-white transition-colors hover:bg-primary-600 disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"commit(); open = false\"\n >\n Apply\n </button>\n </div>\n </div>\n\n <div v-else-if=\"hasValue()\" class=\"mt-3 flex justify-end border-t border-border pt-3\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport { clampTime, sortRange, toISODate, toTime } from '../../lib/date'\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n size?: 'sm' | 'default'\n /** Applied to the trigger button so an external <label for> still matches. */\n inputId?: string\n }>(),\n { mode: 'date', placeholder: 'Select date', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst open = ref(false)\nconst viewDate = ref(new Date())\nconst start = ref<Date | null>(null)\nconst end = ref<Date | null>(null)\nconst time = ref('09:00')\n\nconst WEEKDAYS = [0, 1, 2, 3, 4, 5, 6]\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (Array.isArray(v)) {\n start.value = v[0] ?? null\n end.value = v[1] ?? null\n } else if (v instanceof Date) {\n start.value = v\n end.value = null\n } else {\n start.value = null\n end.value = null\n }\n },\n { immediate: true },\n)\n\nconst grid = computed(() => {\n const first = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), 1)\n const lead = (first.getDay() + 6) % 7 // Monday-first\n const cells: (Date | null)[] = Array.from({ length: lead }, () => null)\n const days = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + 1, 0).getDate()\n for (let d = 1; d <= days; d++) cells.push(new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), d))\n return cells\n})\n\nfunction inRange(d: Date): boolean {\n if (!start.value || !end.value) return false\n const [s, e] = sortRange(start.value, end.value)\n return d.getTime() >= s.getTime() && d.getTime() <= e.getTime()\n}\n\nfunction monthLabel(): string {\n return viewDate.value.toLocaleString('en', { month: 'long', year: 'numeric' })\n}\n\nfunction shiftMonth(n: number) {\n viewDate.value = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + n, 1)\n}\n\nfunction hasValue(): boolean {\n return props.mode === 'range' ? Boolean(start.value && end.value) : Boolean(start.value)\n}\n\nfunction pick(d: Date) {\n if (props.mode === 'range') {\n if (!start.value || end.value) {\n start.value = d\n end.value = null\n } else {\n const [s, e] = sortRange(start.value, d)\n start.value = s\n end.value = e\n }\n return\n }\n start.value = d\n if (props.mode === 'datetime') return // wait for Apply\n commit()\n open.value = false\n}\n\nfunction commit() {\n if (!start.value) return\n if (props.mode === 'range') {\n if (!end.value) return\n emit('update:modelValue', [start.value, end.value])\n } else if (props.mode === 'datetime') {\n emit('update:modelValue', clampTime(start.value, time.value))\n } else {\n emit('update:modelValue', start.value)\n }\n}\n\nfunction clear() {\n start.value = null\n end.value = null\n emit('update:modelValue', null)\n open.value = false\n}\n\nconst display = computed(() => {\n if (props.mode === 'range') {\n if (!start.value || !end.value) return ''\n const [s, e] = sortRange(start.value, end.value)\n return `${toISODate(s)} – ${toISODate(e)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n return `${toISODate(d)}${props.mode === 'datetime' ? ' ' + toTime(d.getHours() * 60 + d.getMinutes()) : ''}`\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n :id=\"inputId\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50 data-[state=open]:border-primary-500',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500' : '',\n ]\"\n >\n <span :class=\"['truncate', display ? 'text-foreground' : 'text-muted']\">{{ display || placeholder }}</span>\n <CalendarIcon class=\"size-4 shrink-0 text-muted\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n :side-offset=\"4\"\n class=\"z-50 rounded-md border border-border bg-surface p-3 shadow-popover\"\n >\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(-1)\"\n >\n <ChevronLeft class=\"size-4\" />\n </button>\n <span class=\"text-sm font-medium\">{{ monthLabel() }}</span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(1)\"\n >\n <ChevronRight class=\"size-4\" />\n </button>\n </div>\n\n <div class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"d in WEEKDAYS\" :key=\"d\" class=\"py-1 font-medium text-muted\">\n {{ new Date(2026, 0, 5 + d).toLocaleDateString('en', { weekday: 'short' }) }}\n </span>\n <template v-for=\"(cell, i) in grid\" :key=\"i\">\n <span v-if=\"!cell\" />\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'flex h-8 items-center justify-center rounded-md text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',\n inRange(cell) ? 'bg-primary-100 text-primary-800' : 'hover:bg-surface-muted',\n start && start.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n end && end.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n ]\"\n @click=\"pick(cell)\"\n >\n {{ cell.getDate() }}\n </button>\n </template>\n </div>\n\n <div v-if=\"mode === 'datetime'\" class=\"mt-3 flex items-center justify-between gap-2 border-t border-border pt-3\">\n <label class=\"flex items-center gap-2 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <input v-model=\"time\" type=\"time\" class=\"rounded border border-border bg-surface px-2 py-1 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\" />\n </label>\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n :disabled=\"!start\"\n class=\"rounded bg-primary-500 px-3 py-1 text-sm text-white transition-colors hover:bg-primary-600 disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"commit(); open = false\"\n >\n Apply\n </button>\n </div>\n </div>\n\n <div v-else-if=\"hasValue()\" class=\"mt-3 flex justify-end border-t border-border pt-3\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n DialogTrigger,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n visible?: boolean\n title?: string\n description?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n }>(),\n { size: 'md' },\n)\n\nconst emit = defineEmits<{ 'update:visible': [value: boolean]; close: [] }>()\n\nconst open = computed({\n get: () => props.visible ?? false,\n set: (v: boolean) => emit('update:visible', v),\n})\n\nconst widths: Record<string, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-2xl',\n xl: 'max-w-4xl',\n}\n\nfunction onOpenChange(v: boolean) {\n emit('update:visible', v)\n if (!v) emit('close')\n}\n</script>\n\n<template>\n <DialogRoot :open=\"open\" @update:open=\"onOpenChange\">\n <DialogTrigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" />\n </DialogTrigger>\n <DialogPortal>\n <DialogOverlay class=\"fixed inset-0 z-50 bg-black/50\" />\n <DialogContent\n :class=\"[\n 'fixed left-1/2 top-1/2 z-50 w-full max-h-[85vh] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border border-border bg-surface shadow-dialog focus-visible:outline-none',\n widths[size],\n ]\"\n >\n <div class=\"flex items-start justify-between gap-4 border-b border-border p-5 pb-4\">\n <div class=\"min-w-0\">\n <DialogTitle v-if=\"title || $slots.header\" class=\"text-lg font-semibold text-foreground\">\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription v-if=\"description || $slots.description\" class=\"mt-1 text-sm text-muted\">\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n class=\"rounded-md p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n aria-label=\"Close\"\n >\n <X class=\"size-4\" />\n </DialogClose>\n </div>\n <div class=\"overflow-y-auto bg-surface p-5\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"flex justify-end gap-2 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </div>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n DialogTrigger,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n visible?: boolean\n title?: string\n description?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n }>(),\n { size: 'md' },\n)\n\nconst emit = defineEmits<{ 'update:visible': [value: boolean]; close: [] }>()\n\nconst open = computed({\n get: () => props.visible ?? false,\n set: (v: boolean) => emit('update:visible', v),\n})\n\nconst widths: Record<string, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-2xl',\n xl: 'max-w-4xl',\n}\n\nfunction onOpenChange(v: boolean) {\n emit('update:visible', v)\n if (!v) emit('close')\n}\n</script>\n\n<template>\n <DialogRoot :open=\"open\" @update:open=\"onOpenChange\">\n <DialogTrigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" />\n </DialogTrigger>\n <DialogPortal>\n <DialogOverlay class=\"fixed inset-0 z-50 bg-black/50\" />\n <DialogContent\n :class=\"[\n 'fixed left-1/2 top-1/2 z-50 w-full max-h-[85vh] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border border-border bg-surface shadow-dialog focus-visible:outline-none',\n widths[size],\n ]\"\n >\n <div class=\"flex items-start justify-between gap-4 border-b border-border p-5 pb-4\">\n <div class=\"min-w-0\">\n <DialogTitle v-if=\"title || $slots.header\" class=\"text-lg font-semibold text-foreground\">\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription v-if=\"description || $slots.description\" class=\"mt-1 text-sm text-muted\">\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n class=\"rounded-md p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n aria-label=\"Close\"\n >\n <X class=\"size-4\" />\n </DialogClose>\n </div>\n <div class=\"overflow-y-auto bg-surface p-5\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"flex justify-end gap-2 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </div>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuRoot } from 'reka-ui'\n\nconst emit = defineEmits<{ 'update:open': [value: boolean] }>()\n</script>\n\n<template>\n <DropdownMenuRoot v-bind=\"$attrs\" @update:open=\"emit('update:open', $event as boolean)\">\n <slot />\n </DropdownMenuRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuRoot } from 'reka-ui'\n\nconst emit = defineEmits<{ 'update:open': [value: boolean] }>()\n</script>\n\n<template>\n <DropdownMenuRoot v-bind=\"$attrs\" @update:open=\"emit('update:open', $event as boolean)\">\n <slot />\n </DropdownMenuRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuTrigger as RekaTrigger } from 'reka-ui'\n</script>\n\n<template>\n <RekaTrigger as-child focus-on-select>\n <slot />\n </RekaTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuTrigger as RekaTrigger } from 'reka-ui'\n</script>\n\n<template>\n <RekaTrigger as-child focus-on-select>\n <slot />\n </RekaTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuContent as RekaContent, DropdownMenuPortal as RekaPortal } from 'reka-ui'\n\nwithDefaults(\n defineProps<{\n align?: 'start' | 'center' | 'end'\n side?: 'top' | 'right' | 'bottom' | 'left'\n sideOffset?: number\n }>(),\n { align: 'start', side: 'bottom', sideOffset: 4 },\n)\n</script>\n\n<template>\n <RekaPortal>\n <RekaContent\n :align=\"align\"\n :side=\"side\"\n :side-offset=\"sideOffset\"\n class=\"z-50 min-w-40 rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <slot />\n </RekaContent>\n </RekaPortal>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuContent as RekaContent, DropdownMenuPortal as RekaPortal } from 'reka-ui'\n\nwithDefaults(\n defineProps<{\n align?: 'start' | 'center' | 'end'\n side?: 'top' | 'right' | 'bottom' | 'left'\n sideOffset?: number\n }>(),\n { align: 'start', side: 'bottom', sideOffset: 4 },\n)\n</script>\n\n<template>\n <RekaPortal>\n <RekaContent\n :align=\"align\"\n :side=\"side\"\n :side-offset=\"sideOffset\"\n class=\"z-50 min-w-40 rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <slot />\n </RekaContent>\n </RekaPortal>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuItem as RekaItem } from 'reka-ui'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst itemVariants = tv({\n base: 'relative flex w-full cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n variants: {\n variant: {\n default: 'text-foreground',\n destructive: 'text-error-600',\n },\n },\n defaultVariants: { variant: 'default' },\n})\n\ndefineProps<{ variant?: VariantProps<typeof itemVariants>['variant'] }>()\nconst emit = defineEmits<{ select: [] }>()\n</script>\n\n<template>\n <RekaItem :class=\"itemVariants({ variant })\" @select=\"emit('select')\">\n <slot />\n </RekaItem>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuItem as RekaItem } from 'reka-ui'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst itemVariants = tv({\n base: 'relative flex w-full cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n variants: {\n variant: {\n default: 'text-foreground',\n destructive: 'text-error-600',\n },\n },\n defaultVariants: { variant: 'default' },\n})\n\ndefineProps<{ variant?: VariantProps<typeof itemVariants>['variant'] }>()\nconst emit = defineEmits<{ select: [] }>()\n</script>\n\n<template>\n <RekaItem :class=\"itemVariants({ variant })\" @select=\"emit('select')\">\n <slot />\n </RekaItem>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport Checkbox from '../checkbox/Checkbox.vue'\n\nconst props = withDefaults(\n defineProps<{\n options: { value: string; label: string }[]\n modelValue?: string[]\n sourceLabel?: string\n targetLabel?: string\n disabled?: boolean\n }>(),\n { sourceLabel: 'Available', targetLabel: 'Selected', disabled: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst selected = ref(new Set<string>(props.modelValue ?? []))\nconst sourceSel = ref(new Set<string>())\nconst targetSel = ref(new Set<string>())\n\nconst left = computed(() => props.options.filter((o) => !selected.value.has(o.value)))\nconst right = computed(() => props.options.filter((o) => selected.value.has(o.value)))\n\nfunction sync() {\n emit('update:modelValue', right.value.map((o) => o.value))\n}\n\nfunction toggle(set: Set<string>, value: string) {\n const next = new Set(set)\n if (next.has(value)) next.delete(value)\n else next.add(value)\n set.clear()\n for (const v of next) set.add(v)\n}\n\nfunction moveToTarget() {\n for (const v of sourceSel.value) selected.value.add(v)\n sourceSel.value.clear()\n sync()\n}\nfunction moveToSource() {\n for (const v of targetSel.value) selected.value.delete(v)\n targetSel.value.clear()\n sync()\n}\nfunction moveAllTarget() {\n for (const o of props.options) selected.value.add(o.value)\n sourceSel.value.clear()\n sync()\n}\nfunction moveAllSource() {\n selected.value.clear()\n targetSel.value.clear()\n sync()\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2 sm:flex-row sm:items-stretch\">\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"source-header\">{{ sourceLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in left\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(sourceSel, o.value)\"\n >\n <Checkbox :model-value=\"sourceSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(sourceSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"left.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n\n <div class=\"flex flex-row items-center justify-center gap-1 sm:flex-col\">\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || sourceSel.size === 0\" aria-label=\"Move selected to target\" @click=\"moveToTarget\">\n <ChevronRight class=\"size-4\" />\n </Button>\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || targetSel.size === 0\" aria-label=\"Move selected to source\" @click=\"moveToSource\">\n <ChevronLeft class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to target\" @click=\"moveAllTarget\">\n <ChevronsRight class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to source\" @click=\"moveAllSource\">\n <ChevronsLeft class=\"size-4\" />\n </Button>\n </div>\n\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"target-header\">{{ targetLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in right\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(targetSel, o.value)\"\n >\n <Checkbox :model-value=\"targetSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(targetSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"right.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport Checkbox from '../checkbox/Checkbox.vue'\n\nconst props = withDefaults(\n defineProps<{\n options: { value: string; label: string }[]\n modelValue?: string[]\n sourceLabel?: string\n targetLabel?: string\n disabled?: boolean\n }>(),\n { sourceLabel: 'Available', targetLabel: 'Selected', disabled: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst selected = ref(new Set<string>(props.modelValue ?? []))\nconst sourceSel = ref(new Set<string>())\nconst targetSel = ref(new Set<string>())\n\nconst left = computed(() => props.options.filter((o) => !selected.value.has(o.value)))\nconst right = computed(() => props.options.filter((o) => selected.value.has(o.value)))\n\nfunction sync() {\n emit('update:modelValue', right.value.map((o) => o.value))\n}\n\nfunction toggle(set: Set<string>, value: string) {\n const next = new Set(set)\n if (next.has(value)) next.delete(value)\n else next.add(value)\n set.clear()\n for (const v of next) set.add(v)\n}\n\nfunction moveToTarget() {\n for (const v of sourceSel.value) selected.value.add(v)\n sourceSel.value.clear()\n sync()\n}\nfunction moveToSource() {\n for (const v of targetSel.value) selected.value.delete(v)\n targetSel.value.clear()\n sync()\n}\nfunction moveAllTarget() {\n for (const o of props.options) selected.value.add(o.value)\n sourceSel.value.clear()\n sync()\n}\nfunction moveAllSource() {\n selected.value.clear()\n targetSel.value.clear()\n sync()\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2 sm:flex-row sm:items-stretch\">\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"source-header\">{{ sourceLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in left\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(sourceSel, o.value)\"\n >\n <Checkbox :model-value=\"sourceSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(sourceSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"left.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n\n <div class=\"flex flex-row items-center justify-center gap-1 sm:flex-col\">\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || sourceSel.size === 0\" aria-label=\"Move selected to target\" @click=\"moveToTarget\">\n <ChevronRight class=\"size-4\" />\n </Button>\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || targetSel.size === 0\" aria-label=\"Move selected to source\" @click=\"moveToSource\">\n <ChevronLeft class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to target\" @click=\"moveAllTarget\">\n <ChevronsRight class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to source\" @click=\"moveAllSource\">\n <ChevronsLeft class=\"size-4\" />\n </Button>\n </div>\n\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"target-header\">{{ targetLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in right\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(targetSel, o.value)\"\n >\n <Checkbox :model-value=\"targetSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(targetSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"right.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ striped?: boolean; size?: 'sm' | 'default'; contained?: boolean }>(),\n { size: 'default', contained: true },\n)\n\nconst classes = computed(() =>\n cn(\n 'w-full border-collapse text-start text-sm text-foreground',\n props.size === 'sm' ? 'text-xs' : 'text-sm',\n props.striped && '[&_tbody>tr:nth-child(even)]:bg-surface-muted/40',\n props.contained && 'overflow-hidden rounded-md border border-border bg-surface',\n ),\n)\n</script>\n\n<template>\n <table :class=\"classes\">\n <slot />\n </table>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ striped?: boolean; size?: 'sm' | 'default'; contained?: boolean }>(),\n { size: 'default', contained: true },\n)\n\nconst classes = computed(() =>\n cn(\n 'w-full border-collapse text-start text-sm text-foreground',\n props.size === 'sm' ? 'text-xs' : 'text-sm',\n props.striped && '[&_tbody>tr:nth-child(even)]:bg-surface-muted/40',\n props.contained && 'overflow-hidden rounded-md border border-border bg-surface',\n ),\n)\n</script>\n\n<template>\n <table :class=\"classes\">\n <slot />\n </table>\n</template>\n","<template>\n <thead class=\"border-b border-border bg-surface-muted/60 text-xs font-medium text-muted\">\n <slot />\n </thead>\n</template>\n","<template>\n <tbody>\n <slot />\n </tbody>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(defineProps<{ clickable?: boolean }>(), { clickable: false })\n</script>\n\n<template>\n <tr\n :class=\"[\n 'border-b border-border/60 last:border-b-0',\n clickable && 'cursor-pointer transition-colors hover:bg-surface-muted/50',\n ]\"\n >\n <slot />\n </tr>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(defineProps<{ clickable?: boolean }>(), { clickable: false })\n</script>\n\n<template>\n <tr\n :class=\"[\n 'border-b border-border/60 last:border-b-0',\n clickable && 'cursor-pointer transition-colors hover:bg-surface-muted/50',\n ]\"\n >\n <slot />\n </tr>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n sortDirection?: 'ascending' | 'descending' | 'none'\n width?: string\n align?: 'start' | 'center' | 'end'\n }>(),\n { align: 'start' },\n)\n\nconst ariaSort = computed(() =>\n props.sortDirection && props.sortDirection !== 'none' ? props.sortDirection : undefined,\n)\n</script>\n\n<template>\n <th\n scope=\"col\"\n :aria-sort=\"ariaSort\"\n :style=\"width ? { width } : undefined\"\n :class=\"cn(\n 'px-3 py-2 font-medium',\n align === 'center' && 'text-center',\n align === 'end' && 'text-end',\n )\"\n >\n <slot />\n </th>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n sortDirection?: 'ascending' | 'descending' | 'none'\n width?: string\n align?: 'start' | 'center' | 'end'\n }>(),\n { align: 'start' },\n)\n\nconst ariaSort = computed(() =>\n props.sortDirection && props.sortDirection !== 'none' ? props.sortDirection : undefined,\n)\n</script>\n\n<template>\n <th\n scope=\"col\"\n :aria-sort=\"ariaSort\"\n :style=\"width ? { width } : undefined\"\n :class=\"cn(\n 'px-3 py-2 font-medium',\n align === 'center' && 'text-center',\n align === 'end' && 'text-end',\n )\"\n >\n <slot />\n </th>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ align?: 'start' | 'center' | 'end'; truncate?: boolean }>(),\n { align: 'start' },\n)\n\nconst classes = computed(() =>\n cn(\n 'px-3 py-2 align-middle',\n props.align === 'center' && 'text-center',\n props.align === 'end' && 'text-end',\n props.truncate && 'max-w-0 truncate',\n ),\n)\n</script>\n\n<template>\n <td :class=\"classes\">\n <slot />\n </td>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ align?: 'start' | 'center' | 'end'; truncate?: boolean }>(),\n { align: 'start' },\n)\n\nconst classes = computed(() =>\n cn(\n 'px-3 py-2 align-middle',\n props.align === 'center' && 'text-center',\n props.align === 'end' && 'text-end',\n props.truncate && 'max-w-0 truncate',\n ),\n)\n</script>\n\n<template>\n <td :class=\"classes\">\n <slot />\n </td>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{ columns: number; label?: string }>()\n</script>\n\n<template>\n <tr>\n <td :colspan=\"columns\" class=\"px-3 py-8 text-center text-sm text-muted\">\n <slot>{{ label }}</slot>\n </td>\n </tr>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{ columns: number; label?: string }>()\n</script>\n\n<template>\n <tr>\n <td :colspan=\"columns\" class=\"px-3 py-8 text-center text-sm text-muted\">\n <slot>{{ label }}</slot>\n </td>\n </tr>\n</template>\n","export interface PageRange {\n /** 1-based index of the first visible row, 0 when there is no row. */\n from: number\n /** 1-based index of the last visible row, 0 when there is no row. */\n to: number\n total: number\n}\n\nexport function pageRange(pageIndex: number, pageSize: number, total: number): PageRange {\n if (total <= 0 || pageSize <= 0) return { from: 0, to: 0, total: Math.max(0, total) }\n const from = pageIndex * pageSize + 1\n const to = Math.min(total, from + pageSize - 1)\n return from > total ? { from: 0, to: 0, total } : { from, to, total }\n}\n\nexport function totalPages(total: number, pageSize: number): number {\n if (pageSize <= 0) return 1\n return Math.max(1, Math.ceil(total / pageSize))\n}\n\n/** 1-based page numbers, clamped to the window and to the bounds. */\nexport function pageWindow(pageIndex: number, pageCount: number, size = 5): number[] {\n if (pageCount <= 0) return []\n const half = Math.floor(size / 2)\n const start = Math.max(0, Math.min(pageIndex - half, pageCount - size))\n const from = Math.max(0, start)\n return Array.from({ length: Math.min(size, pageCount - from) }, (_, i) => from + i + 1)\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport { pageRange, pageWindow, totalPages } from '../../lib/pagination'\n\nconst props = withDefaults(\n defineProps<{\n pageIndex: number\n pageSize: number\n total: number\n pageSizeOptions?: number[]\n rowsPerPageLabel?: string\n ofLabel?: string\n previousLabel?: string\n nextLabel?: string\n }>(),\n {\n pageSizeOptions: () => [5, 10, 20],\n rowsPerPageLabel: 'Rows per page',\n ofLabel: 'of',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n },\n)\n\nconst emit = defineEmits<{\n 'update:pageIndex': [value: number]\n 'update:pageSize': [value: number]\n}>()\n\nconst pageCount = computed(() => totalPages(props.total, props.pageSize))\nconst range = computed(() => pageRange(props.pageIndex, props.pageSize, props.total))\nconst pages = computed(() => pageWindow(props.pageIndex, pageCount.value))\n\nfunction goTo(index: number) {\n emit('update:pageIndex', Math.max(0, Math.min(index, pageCount.value - 1)))\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap items-center justify-between gap-3 px-3 py-2 text-sm text-muted\">\n <div class=\"flex items-center gap-2\">\n <span>{{ rowsPerPageLabel }}</span>\n <select\n :value=\"pageSize\"\n class=\"rounded-md border border-border bg-surface px-2 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @change=\"emit('update:pageSize', Number(($event.target as HTMLSelectElement).value))\"\n >\n <option v-for=\"option in pageSizeOptions\" :key=\"option\" :value=\"option\">{{ option }}</option>\n </select>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span>{{ range.from }}–{{ range.to }} {{ ofLabel }} {{ range.total }}</span>\n <div class=\"flex items-center gap-1\">\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex <= 0\" :aria-label=\"previousLabel\" @click=\"goTo(pageIndex - 1)\">\n <ChevronLeft class=\"size-4 rtl:rotate-180\" />\n </Button>\n <Button\n v-for=\"page in pages\"\n :key=\"page\"\n :variant=\"page - 1 === pageIndex ? 'default' : 'ghost'\"\n size=\"icon-sm\"\n :aria-current=\"page - 1 === pageIndex ? 'page' : undefined\"\n @click=\"goTo(page - 1)\"\n >\n {{ page }}\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex >= pageCount - 1\" :aria-label=\"nextLabel\" @click=\"goTo(pageIndex + 1)\">\n <ChevronRight class=\"size-4 rtl:rotate-180\" />\n </Button>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport { pageRange, pageWindow, totalPages } from '../../lib/pagination'\n\nconst props = withDefaults(\n defineProps<{\n pageIndex: number\n pageSize: number\n total: number\n pageSizeOptions?: number[]\n rowsPerPageLabel?: string\n ofLabel?: string\n previousLabel?: string\n nextLabel?: string\n }>(),\n {\n pageSizeOptions: () => [5, 10, 20],\n rowsPerPageLabel: 'Rows per page',\n ofLabel: 'of',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n },\n)\n\nconst emit = defineEmits<{\n 'update:pageIndex': [value: number]\n 'update:pageSize': [value: number]\n}>()\n\nconst pageCount = computed(() => totalPages(props.total, props.pageSize))\nconst range = computed(() => pageRange(props.pageIndex, props.pageSize, props.total))\nconst pages = computed(() => pageWindow(props.pageIndex, pageCount.value))\n\nfunction goTo(index: number) {\n emit('update:pageIndex', Math.max(0, Math.min(index, pageCount.value - 1)))\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap items-center justify-between gap-3 px-3 py-2 text-sm text-muted\">\n <div class=\"flex items-center gap-2\">\n <span>{{ rowsPerPageLabel }}</span>\n <select\n :value=\"pageSize\"\n class=\"rounded-md border border-border bg-surface px-2 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @change=\"emit('update:pageSize', Number(($event.target as HTMLSelectElement).value))\"\n >\n <option v-for=\"option in pageSizeOptions\" :key=\"option\" :value=\"option\">{{ option }}</option>\n </select>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span>{{ range.from }}–{{ range.to }} {{ ofLabel }} {{ range.total }}</span>\n <div class=\"flex items-center gap-1\">\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex <= 0\" :aria-label=\"previousLabel\" @click=\"goTo(pageIndex - 1)\">\n <ChevronLeft class=\"size-4 rtl:rotate-180\" />\n </Button>\n <Button\n v-for=\"page in pages\"\n :key=\"page\"\n :variant=\"page - 1 === pageIndex ? 'default' : 'ghost'\"\n size=\"icon-sm\"\n :aria-current=\"page - 1 === pageIndex ? 'page' : undefined\"\n @click=\"goTo(page - 1)\"\n >\n {{ page }}\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex >= pageCount - 1\" :aria-label=\"nextLabel\" @click=\"goTo(pageIndex + 1)\">\n <ChevronRight class=\"size-4 rtl:rotate-180\" />\n </Button>\n </div>\n </div>\n </div>\n</template>\n","import {\n createExpandedRowModel,\n createPaginatedRowModel,\n createSortedRowModel,\n rowExpandingFeature,\n rowPaginationFeature,\n rowSortingFeature,\n sortFns,\n tableFeatures,\n} from '@tanstack/vue-table'\n\n/**\n * Single registration point for the suite's engine.\n * Add a feature here only when a DataTable consumer needs it — v9 tree-shakes\n * whatever is not registered.\n */\nexport const dataTableFeatures = tableFeatures({\n rowSortingFeature,\n rowPaginationFeature,\n rowExpandingFeature,\n sortedRowModel: createSortedRowModel(),\n paginatedRowModel: createPaginatedRowModel(),\n expandedRowModel: createExpandedRowModel(),\n sortFns,\n})\n\nexport type DataTableFeatures = typeof dataTableFeatures\n","/** Structural type so the guard is unit-testable in node env (no DOM). */\nexport interface ClosestHost {\n closest: (selector: string) => unknown\n}\n\nconst INTERACTIVE_SELECTOR = [\n 'a[href]',\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'label',\n '[role=\"checkbox\"]',\n '[role=\"switch\"]',\n '[role=\"combobox\"]',\n '[role=\"menu\"]',\n '[data-row-toggle-ignore]',\n].join(',')\n\n/**\n * Replaces the app's `closest('.p-select, .p-button, ...')` guard: any click\n * landing inside a real interactive element (or an element opted out with\n * `data-row-toggle-ignore`) never toggles the row.\n *\n * The parameter is `unknown` on purpose — DOM `EventTarget` has no `closest`,\n * and callers pass `event.target` straight through.\n */\nexport function shouldIgnoreRowToggle(target: unknown): boolean {\n const host = target as ClosestHost | null | undefined\n if (!host || typeof host.closest !== 'function') return false\n return host.closest(INTERACTIVE_SELECTOR) !== null\n}\n\n/** Single-row expansion map, keyed by row id, as used by `v-model:expanded`. */\nexport function toggleExpandedRow(\n expanded: Record<string, boolean>,\n rowId: string,\n): Record<string, boolean> {\n return expanded[rowId] ? {} : { [rowId]: true }\n}\n","<script setup lang=\"ts\" generic=\"T extends RowData\">\nimport { computed, ref, useSlots } from 'vue'\nimport { FlexRender, useTable, type ColumnDef, type RowData, type SortingState } from '@tanstack/vue-table'\nimport { ChevronDown, ChevronUp, ChevronsUpDown } from 'lucide-vue-next'\nimport { dataTableFeatures } from '../../lib/table'\nimport { shouldIgnoreRowToggle, toggleExpandedRow } from '../../lib/tableInteractions'\nimport Table from '../table/Table.vue'\nimport TableBody from '../table/TableBody.vue'\nimport TableCell from '../table/TableCell.vue'\nimport TableEmpty from '../table/TableEmpty.vue'\nimport TableHead from '../table/TableHead.vue'\nimport TableHeader from '../table/TableHeader.vue'\nimport TableRow from '../table/TableRow.vue'\n\nconst props = withDefaults(\n defineProps<{\n data: T[]\n columns: ColumnDef<typeof dataTableFeatures, T>[]\n getRowId?: (row: T) => string\n striped?: boolean\n size?: 'sm' | 'default'\n emptyLabel?: string\n sortable?: boolean\n expandable?: boolean\n expanded?: Record<string, boolean>\n stopRowToggleOnInteractiveCells?: boolean\n maxHeight?: string\n }>(),\n {\n size: 'default',\n striped: false,\n sortable: true,\n emptyLabel: 'No results',\n expandable: false,\n expanded: () => ({}),\n stopRowToggleOnInteractiveCells: true,\n },\n)\n\nconst emit = defineEmits<{\n 'update:sorting': [value: { id: string; desc: boolean }[]]\n 'update:expanded': [value: Record<string, boolean>]\n 'row-click': [row: unknown]\n}>()\nconst slots = useSlots()\n\nconst sorting = ref<SortingState>([])\nconst getRowId = props.getRowId ? (row: T) => props.getRowId!(row) : undefined\n\nconst table = useTable({\n features: dataTableFeatures,\n get columns() {\n return props.columns\n },\n get data() {\n return props.data\n },\n getRowId,\n getRowCanExpand: () => props.expandable,\n state: {\n get sorting() {\n return sorting.value\n },\n get expanded() {\n return props.expanded\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n emit(\n 'update:sorting',\n sorting.value.map((s) => ({ id: s.id, desc: s.desc })),\n )\n },\n onExpandedChange: (updater) => {\n const next = typeof updater === 'function' ? updater(props.expanded) : updater\n // ExpandedState may be `true` (expand all); the suite only models per-row ids.\n emit('update:expanded', next === true ? {} : next)\n },\n})\n\nconst rows = computed(() => table.getRowModel().rows)\nconst columnCount = computed(() => table.getAllLeafColumns().length)\n\nfunction sortDirection(columnId: string): 'ascending' | 'descending' | 'none' {\n const column = table.getColumn(columnId)\n if (!column?.getIsSorted()) return 'none'\n return column.getIsSorted() === 'desc' ? 'descending' : 'ascending'\n}\n\nconst hasCellSlot = (columnId: string) => Boolean(slots[`cell-${columnId}`])\n\n/** `size` only exists on ColumnDef when columnSizingFeature is registered, so read it structurally. */\nconst widthOf = (columnDef: unknown) => {\n const size = (columnDef as { size?: number }).size\n return size ? `${size}px` : undefined\n}\n\nfunction onRowClick(event: MouseEvent, rowId: string) {\n emit('row-click', rows.value.find((row) => row.id === rowId)?.original)\n if (!props.expandable) return\n if (props.stopRowToggleOnInteractiveCells && shouldIgnoreRowToggle(event.target)) return\n emit('update:expanded', toggleExpandedRow(props.expanded, rowId))\n}\n</script>\n\n<template>\n <div :class=\"maxHeight ? 'overflow-auto' : undefined\" :style=\"maxHeight ? { maxHeight } : undefined\">\n <Table :striped=\"striped\" :size=\"size\">\n <TableHeader>\n <TableRow>\n <TableHead\n v-for=\"header in table.getHeaderGroups()[0]?.headers ?? []\"\n :key=\"header.id\"\n :width=\"widthOf(header.column.columnDef)\"\n :sort-direction=\"header.column.getCanSort() ? sortDirection(header.column.id) : undefined\"\n >\n <button\n v-if=\"sortable && header.column.getCanSort()\"\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"header.column.toggleSorting()\"\n >\n <FlexRender :header=\"header\" />\n <ChevronDown v-if=\"sortDirection(header.column.id) === 'descending'\" class=\"size-3.5\" />\n <ChevronUp v-else-if=\"sortDirection(header.column.id) === 'ascending'\" class=\"size-3.5\" />\n <ChevronsUpDown v-else class=\"size-3.5 opacity-40\" />\n </button>\n <FlexRender v-else :header=\"header\" />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <TableEmpty v-if=\"rows.length === 0\" :columns=\"columnCount\">\n <slot name=\"empty\">{{ emptyLabel }}</slot>\n </TableEmpty>\n <template v-for=\"row in rows\" :key=\"row.id\">\n <TableRow\n :clickable=\"expandable\"\n :data-row-id=\"row.id\"\n :data-state=\"row.getIsExpanded() ? 'expanded' : undefined\"\n @click=\"onRowClick($event, row.id)\"\n >\n <TableCell v-for=\"cell in row.getAllCells()\" :key=\"cell.id\">\n <slot\n v-if=\"hasCellSlot(cell.column.id)\"\n :name=\"`cell-${cell.column.id}`\"\n :row=\"row\"\n :cell=\"cell\"\n :value=\"cell.getValue()\"\n />\n <FlexRender v-else :cell=\"cell\" />\n </TableCell>\n </TableRow>\n <TableRow v-if=\"row.getIsExpanded()\" class=\"bg-surface-muted/30\">\n <TableCell :colspan=\"columnCount\">\n <slot name=\"expansion\" :row=\"row\" />\n </TableCell>\n </TableRow>\n </template>\n </TableBody>\n </Table>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T extends RowData\">\nimport { computed, ref, useSlots } from 'vue'\nimport { FlexRender, useTable, type ColumnDef, type RowData, type SortingState } from '@tanstack/vue-table'\nimport { ChevronDown, ChevronUp, ChevronsUpDown } from 'lucide-vue-next'\nimport { dataTableFeatures } from '../../lib/table'\nimport { shouldIgnoreRowToggle, toggleExpandedRow } from '../../lib/tableInteractions'\nimport Table from '../table/Table.vue'\nimport TableBody from '../table/TableBody.vue'\nimport TableCell from '../table/TableCell.vue'\nimport TableEmpty from '../table/TableEmpty.vue'\nimport TableHead from '../table/TableHead.vue'\nimport TableHeader from '../table/TableHeader.vue'\nimport TableRow from '../table/TableRow.vue'\n\nconst props = withDefaults(\n defineProps<{\n data: T[]\n columns: ColumnDef<typeof dataTableFeatures, T>[]\n getRowId?: (row: T) => string\n striped?: boolean\n size?: 'sm' | 'default'\n emptyLabel?: string\n sortable?: boolean\n expandable?: boolean\n expanded?: Record<string, boolean>\n stopRowToggleOnInteractiveCells?: boolean\n maxHeight?: string\n }>(),\n {\n size: 'default',\n striped: false,\n sortable: true,\n emptyLabel: 'No results',\n expandable: false,\n expanded: () => ({}),\n stopRowToggleOnInteractiveCells: true,\n },\n)\n\nconst emit = defineEmits<{\n 'update:sorting': [value: { id: string; desc: boolean }[]]\n 'update:expanded': [value: Record<string, boolean>]\n 'row-click': [row: unknown]\n}>()\nconst slots = useSlots()\n\nconst sorting = ref<SortingState>([])\nconst getRowId = props.getRowId ? (row: T) => props.getRowId!(row) : undefined\n\nconst table = useTable({\n features: dataTableFeatures,\n get columns() {\n return props.columns\n },\n get data() {\n return props.data\n },\n getRowId,\n getRowCanExpand: () => props.expandable,\n state: {\n get sorting() {\n return sorting.value\n },\n get expanded() {\n return props.expanded\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n emit(\n 'update:sorting',\n sorting.value.map((s) => ({ id: s.id, desc: s.desc })),\n )\n },\n onExpandedChange: (updater) => {\n const next = typeof updater === 'function' ? updater(props.expanded) : updater\n // ExpandedState may be `true` (expand all); the suite only models per-row ids.\n emit('update:expanded', next === true ? {} : next)\n },\n})\n\nconst rows = computed(() => table.getRowModel().rows)\nconst columnCount = computed(() => table.getAllLeafColumns().length)\n\nfunction sortDirection(columnId: string): 'ascending' | 'descending' | 'none' {\n const column = table.getColumn(columnId)\n if (!column?.getIsSorted()) return 'none'\n return column.getIsSorted() === 'desc' ? 'descending' : 'ascending'\n}\n\nconst hasCellSlot = (columnId: string) => Boolean(slots[`cell-${columnId}`])\n\n/** `size` only exists on ColumnDef when columnSizingFeature is registered, so read it structurally. */\nconst widthOf = (columnDef: unknown) => {\n const size = (columnDef as { size?: number }).size\n return size ? `${size}px` : undefined\n}\n\nfunction onRowClick(event: MouseEvent, rowId: string) {\n emit('row-click', rows.value.find((row) => row.id === rowId)?.original)\n if (!props.expandable) return\n if (props.stopRowToggleOnInteractiveCells && shouldIgnoreRowToggle(event.target)) return\n emit('update:expanded', toggleExpandedRow(props.expanded, rowId))\n}\n</script>\n\n<template>\n <div :class=\"maxHeight ? 'overflow-auto' : undefined\" :style=\"maxHeight ? { maxHeight } : undefined\">\n <Table :striped=\"striped\" :size=\"size\">\n <TableHeader>\n <TableRow>\n <TableHead\n v-for=\"header in table.getHeaderGroups()[0]?.headers ?? []\"\n :key=\"header.id\"\n :width=\"widthOf(header.column.columnDef)\"\n :sort-direction=\"header.column.getCanSort() ? sortDirection(header.column.id) : undefined\"\n >\n <button\n v-if=\"sortable && header.column.getCanSort()\"\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"header.column.toggleSorting()\"\n >\n <FlexRender :header=\"header\" />\n <ChevronDown v-if=\"sortDirection(header.column.id) === 'descending'\" class=\"size-3.5\" />\n <ChevronUp v-else-if=\"sortDirection(header.column.id) === 'ascending'\" class=\"size-3.5\" />\n <ChevronsUpDown v-else class=\"size-3.5 opacity-40\" />\n </button>\n <FlexRender v-else :header=\"header\" />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <TableEmpty v-if=\"rows.length === 0\" :columns=\"columnCount\">\n <slot name=\"empty\">{{ emptyLabel }}</slot>\n </TableEmpty>\n <template v-for=\"row in rows\" :key=\"row.id\">\n <TableRow\n :clickable=\"expandable\"\n :data-row-id=\"row.id\"\n :data-state=\"row.getIsExpanded() ? 'expanded' : undefined\"\n @click=\"onRowClick($event, row.id)\"\n >\n <TableCell v-for=\"cell in row.getAllCells()\" :key=\"cell.id\">\n <slot\n v-if=\"hasCellSlot(cell.column.id)\"\n :name=\"`cell-${cell.column.id}`\"\n :row=\"row\"\n :cell=\"cell\"\n :value=\"cell.getValue()\"\n />\n <FlexRender v-else :cell=\"cell\" />\n </TableCell>\n </TableRow>\n <TableRow v-if=\"row.getIsExpanded()\" class=\"bg-surface-muted/30\">\n <TableCell :colspan=\"columnCount\">\n <slot name=\"expansion\" :row=\"row\" />\n </TableCell>\n </TableRow>\n </template>\n </TableBody>\n </Table>\n </div>\n</template>\n","export interface TreeNode<T = unknown> {\n /** Stable key; also the value emitted by TreeSelect and TreeTable. */\n value: string\n label?: string\n disabled?: boolean\n children?: TreeNode<T>[]\n data?: T\n}\n\nexport interface FlatTreeRow<T = unknown> {\n node: TreeNode<T>\n key: string\n level: number\n parentKey: string | null\n hasChildren: boolean\n}\n\nexport function flattenVisible<T>(\n nodes: TreeNode<T>[],\n expanded: string[],\n level = 1,\n parentKey: string | null = null,\n): FlatTreeRow<T>[] {\n return nodes.flatMap((node) => {\n const row: FlatTreeRow<T> = {\n node,\n key: node.value,\n level,\n parentKey,\n hasChildren: Boolean(node.children?.length),\n }\n if (!row.hasChildren || !expanded.includes(node.value)) return [row]\n return [row, ...flattenVisible(node.children!, expanded, level + 1, node.value)]\n })\n}\n\nexport function findNode<T>(nodes: TreeNode<T>[], key: string): TreeNode<T> | undefined {\n for (const node of nodes) {\n if (node.value === key) return node\n const hit = node.children ? findNode(node.children, key) : undefined\n if (hit) return hit\n }\n return undefined\n}\n\nexport function leafKeys<T>(nodes: TreeNode<T>[]): string[] {\n return nodes.flatMap((node) =>\n node.children?.length ? leafKeys(node.children) : [node.value],\n )\n}\n\nexport type CheckedState = 'checked' | 'indeterminate' | 'unchecked'\n\n/**\n * Replaces the app's `Record<key, { checked, partialChecked }>` store shape:\n * the package contract is the flat list of selected leaf keys, and this derives\n * per-node state from it.\n */\nexport function checkedStateOf<T>(node: TreeNode<T>, selectedLeafKeys: string[]): CheckedState {\n const leaves = node.children?.length ? leafKeys([node]) : [node.value]\n const selected = leaves.filter((key) => selectedLeafKeys.includes(key)).length\n if (selected === 0) return 'unchecked'\n return selected === leaves.length ? 'checked' : 'indeterminate'\n}\n\n/** Keeps a node when it matches or any descendant does; drops empty branches. */\nexport function filterTree<T>(\n nodes: TreeNode<T>[],\n query: string,\n labelOf: (node: TreeNode<T>) => string = (node) => node.label ?? '',\n): TreeNode<T>[] {\n const needle = query.trim().toLowerCase()\n if (!needle) return nodes\n return nodes.reduce<TreeNode<T>[]>((acc, node) => {\n const children = node.children ? filterTree(node.children, query, labelOf) : undefined\n const matches = labelOf(node).toLowerCase().includes(needle)\n if (!matches && (!children || children.length === 0)) return acc\n acc.push({ ...node, children })\n return acc\n }, [])\n}\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed } from 'vue'\nimport { TreeItem, TreeRoot } from 'reka-ui'\nimport { ChevronRight } from 'lucide-vue-next'\nimport { flattenVisible, type TreeNode } from '../../lib/tree'\n\nexport interface TreeTableColumn {\n key: string\n header: string\n width?: string\n align?: 'start' | 'center' | 'end'\n}\n\nconst props = withDefaults(\n defineProps<{\n nodes: TreeNode<T>[]\n columns: TreeTableColumn[]\n expanded?: string[]\n rowLabel?: (node: TreeNode<T>) => string\n rowColumnHeader?: string\n }>(),\n {\n expanded: () => [],\n rowLabel: (node: TreeNode<T>) => node.label ?? node.value,\n rowColumnHeader: 'Name',\n },\n)\n\nconst emit = defineEmits<{ 'update:expanded': [value: string[]] }>()\n\nconst gridTemplate = computed(\n () => `minmax(12rem, 1fr) ${props.columns.map((column) => column.width ?? 'minmax(6rem, 1fr)').join(' ')}`,\n)\nconst flat = computed(() => flattenVisible(props.nodes, props.expanded))\n</script>\n\n<template>\n <div class=\"overflow-hidden rounded-md border border-border bg-surface\">\n <div\n class=\"grid border-b border-border bg-surface-muted/60 text-xs font-medium text-muted\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"px-3 py-2\">\n <slot name=\"header\">{{ rowColumnHeader }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n {{ column.header }}\n </div>\n </div>\n\n <TreeRoot\n :items=\"nodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n :expanded=\"expanded\"\n @update:expanded=\"emit('update:expanded', $event as string[])\"\n >\n <TreeItem\n v-for=\"row in flat\"\n :key=\"row.key\"\n v-slot=\"{ isExpanded, handleToggle }\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"grid items-center border-b border-border/60 text-sm last:border-b-0 data-[selected]:bg-surface-muted/30\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"flex items-center gap-1 px-3 py-2\" :style=\"{ paddingInlineStart: `calc(0.75rem + ${(row.level - 1) * 1.25}rem)` }\">\n <button\n v-if=\"row.hasChildren\"\n type=\"button\"\n :aria-label=\"rowLabel(row.node)\"\n class=\"rounded p-0.5 text-muted transition-transform hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n :class=\"isExpanded && 'rotate-90'\"\n @click.stop=\"handleToggle\"\n >\n <ChevronRight class=\"size-3.5 rtl:rotate-180\" />\n </button>\n <span v-else class=\"inline-block size-4\" />\n <slot name=\"row-label\" :node=\"row.node\" :level=\"row.level\">{{ rowLabel(row.node) }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :node=\"row.node\"\n :row=\"row\"\n :is-expanded=\"isExpanded\"\n :has-children=\"row.hasChildren\"\n :handle-toggle=\"handleToggle\"\n />\n </div>\n </TreeItem>\n </TreeRoot>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed } from 'vue'\nimport { TreeItem, TreeRoot } from 'reka-ui'\nimport { ChevronRight } from 'lucide-vue-next'\nimport { flattenVisible, type TreeNode } from '../../lib/tree'\n\nexport interface TreeTableColumn {\n key: string\n header: string\n width?: string\n align?: 'start' | 'center' | 'end'\n}\n\nconst props = withDefaults(\n defineProps<{\n nodes: TreeNode<T>[]\n columns: TreeTableColumn[]\n expanded?: string[]\n rowLabel?: (node: TreeNode<T>) => string\n rowColumnHeader?: string\n }>(),\n {\n expanded: () => [],\n rowLabel: (node: TreeNode<T>) => node.label ?? node.value,\n rowColumnHeader: 'Name',\n },\n)\n\nconst emit = defineEmits<{ 'update:expanded': [value: string[]] }>()\n\nconst gridTemplate = computed(\n () => `minmax(12rem, 1fr) ${props.columns.map((column) => column.width ?? 'minmax(6rem, 1fr)').join(' ')}`,\n)\nconst flat = computed(() => flattenVisible(props.nodes, props.expanded))\n</script>\n\n<template>\n <div class=\"overflow-hidden rounded-md border border-border bg-surface\">\n <div\n class=\"grid border-b border-border bg-surface-muted/60 text-xs font-medium text-muted\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"px-3 py-2\">\n <slot name=\"header\">{{ rowColumnHeader }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n {{ column.header }}\n </div>\n </div>\n\n <TreeRoot\n :items=\"nodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n :expanded=\"expanded\"\n @update:expanded=\"emit('update:expanded', $event as string[])\"\n >\n <TreeItem\n v-for=\"row in flat\"\n :key=\"row.key\"\n v-slot=\"{ isExpanded, handleToggle }\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"grid items-center border-b border-border/60 text-sm last:border-b-0 data-[selected]:bg-surface-muted/30\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"flex items-center gap-1 px-3 py-2\" :style=\"{ paddingInlineStart: `calc(0.75rem + ${(row.level - 1) * 1.25}rem)` }\">\n <button\n v-if=\"row.hasChildren\"\n type=\"button\"\n :aria-label=\"rowLabel(row.node)\"\n class=\"rounded p-0.5 text-muted transition-transform hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n :class=\"isExpanded && 'rotate-90'\"\n @click.stop=\"handleToggle\"\n >\n <ChevronRight class=\"size-3.5 rtl:rotate-180\" />\n </button>\n <span v-else class=\"inline-block size-4\" />\n <slot name=\"row-label\" :node=\"row.node\" :level=\"row.level\">{{ rowLabel(row.node) }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :node=\"row.node\"\n :row=\"row\"\n :is-expanded=\"isExpanded\"\n :has-children=\"row.hasChildren\"\n :handle-toggle=\"handleToggle\"\n />\n </div>\n </TreeItem>\n </TreeRoot>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed, ref } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger, TreeItem, TreeRoot } from 'reka-ui'\nimport { Check, ChevronDown, Search, X } from 'lucide-vue-next'\nimport Tag from '../tag/Tag.vue'\nimport {\n checkedStateOf,\n filterTree,\n findNode,\n flattenVisible,\n leafKeys,\n type TreeNode,\n} from '../../lib/tree'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[]\n nodes: TreeNode<T>[]\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n disabled?: boolean\n /** Only leaf nodes are selectable (the classification case: parents are groups). */\n leafOnly?: boolean\n size?: 'sm' | 'default'\n }>(),\n {\n modelValue: () => [],\n placeholder: 'Select',\n filterable: true,\n filterPlaceholder: 'Search',\n leafOnly: true,\n size: 'default',\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst open = ref(false)\nconst query = ref('')\nconst expanded = ref<string[]>([])\n\nconst visibleNodes = computed(() => filterTree(props.nodes, query.value))\nconst rows = computed(() => flattenVisible(visibleNodes.value, expanded.value))\nconst leaves = computed(() => leafKeys(props.nodes))\nconst selectedItems = computed(() =>\n props.modelValue\n .map((key) => findNode(props.nodes, key))\n .filter((node): node is TreeNode<T> => Boolean(node)),\n)\n\n/** Derived from the selected leaf keys, so partially selected parents read correctly. */\nfunction stateOf(node: TreeNode<T>) {\n return checkedStateOf(node, props.modelValue)\n}\n\nfunction onUpdateItems(value: unknown) {\n const items = Array.isArray(value) ? (value as TreeNode<T>[]) : []\n const keys = items.map((item) => item.value)\n emit('update:modelValue', props.leafOnly ? keys.filter((key) => leaves.value.includes(key)) : keys)\n}\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child :disabled=\"disabled\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-start text-sm text-foreground shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'min-h-8 py-1 text-xs' : 'min-h-9 py-1.5',\n ]\"\n >\n <span v-if=\"selectedItems.length === 0\" class=\"truncate text-muted\">{{ placeholder }}</span>\n <span v-else class=\"flex flex-wrap items-center gap-1\">\n <Tag v-for=\"node in selectedItems\" :key=\"node.value\" tone=\"secondary\">{{ node.label ?? node.value }}</Tag>\n </span>\n <ChevronDown class=\"size-4 shrink-0 opacity-50\" />\n </button>\n </PopoverTrigger>\n\n <PopoverContent :side-offset=\"4\" class=\"z-50 w-72 rounded-md border border-border bg-surface p-2 shadow-popover\">\n <div v-if=\"filterable\" class=\"relative mb-2\">\n <Search class=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-muted\" />\n <input\n v-model=\"query\"\n :placeholder=\"filterPlaceholder\"\n class=\"w-full rounded-md border border-border bg-surface py-1.5 pe-2 ps-7 text-sm placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n />\n </div>\n\n <TreeRoot\n :model-value=\"selectedItems\"\n :items=\"visibleNodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n v-model:expanded=\"expanded\"\n multiple\n bubble-select\n @update:model-value=\"onUpdateItems\"\n >\n <TreeItem\n v-for=\"row in rows\"\n :key=\"row.key\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"flex items-center gap-2 rounded py-1.5 text-sm text-foreground data-[selected]:bg-surface-muted/50\"\n :style=\"{ paddingInlineStart: `calc(0.5rem + ${(row.level - 1) * 1}rem)` }\"\n >\n <span\n class=\"flex size-4 shrink-0 items-center justify-center rounded border border-border\"\n :class=\"stateOf(row.node) !== 'unchecked' && 'border-primary-500 bg-primary-500 text-white'\"\n aria-hidden=\"true\"\n >\n <Check v-if=\"stateOf(row.node) === 'checked'\" class=\"size-3\" />\n <span v-else-if=\"stateOf(row.node) === 'indeterminate'\" class=\"block h-0.5 w-2 rounded bg-white\" />\n </span>\n <span class=\"truncate\">{{ row.node.label ?? row.node.value }}</span>\n </TreeItem>\n </TreeRoot>\n\n <div v-if=\"modelValue.length\" class=\"mt-2 flex justify-end border-t border-border pt-2\">\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded px-2 py-1 text-xs text-muted hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"emit('update:modelValue', [])\"\n >\n <X class=\"size-3\" />Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed, ref } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger, TreeItem, TreeRoot } from 'reka-ui'\nimport { Check, ChevronDown, Search, X } from 'lucide-vue-next'\nimport Tag from '../tag/Tag.vue'\nimport {\n checkedStateOf,\n filterTree,\n findNode,\n flattenVisible,\n leafKeys,\n type TreeNode,\n} from '../../lib/tree'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[]\n nodes: TreeNode<T>[]\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n disabled?: boolean\n /** Only leaf nodes are selectable (the classification case: parents are groups). */\n leafOnly?: boolean\n size?: 'sm' | 'default'\n }>(),\n {\n modelValue: () => [],\n placeholder: 'Select',\n filterable: true,\n filterPlaceholder: 'Search',\n leafOnly: true,\n size: 'default',\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst open = ref(false)\nconst query = ref('')\nconst expanded = ref<string[]>([])\n\nconst visibleNodes = computed(() => filterTree(props.nodes, query.value))\nconst rows = computed(() => flattenVisible(visibleNodes.value, expanded.value))\nconst leaves = computed(() => leafKeys(props.nodes))\nconst selectedItems = computed(() =>\n props.modelValue\n .map((key) => findNode(props.nodes, key))\n .filter((node): node is TreeNode<T> => Boolean(node)),\n)\n\n/** Derived from the selected leaf keys, so partially selected parents read correctly. */\nfunction stateOf(node: TreeNode<T>) {\n return checkedStateOf(node, props.modelValue)\n}\n\nfunction onUpdateItems(value: unknown) {\n const items = Array.isArray(value) ? (value as TreeNode<T>[]) : []\n const keys = items.map((item) => item.value)\n emit('update:modelValue', props.leafOnly ? keys.filter((key) => leaves.value.includes(key)) : keys)\n}\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child :disabled=\"disabled\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-start text-sm text-foreground shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'min-h-8 py-1 text-xs' : 'min-h-9 py-1.5',\n ]\"\n >\n <span v-if=\"selectedItems.length === 0\" class=\"truncate text-muted\">{{ placeholder }}</span>\n <span v-else class=\"flex flex-wrap items-center gap-1\">\n <Tag v-for=\"node in selectedItems\" :key=\"node.value\" tone=\"secondary\">{{ node.label ?? node.value }}</Tag>\n </span>\n <ChevronDown class=\"size-4 shrink-0 opacity-50\" />\n </button>\n </PopoverTrigger>\n\n <PopoverContent :side-offset=\"4\" class=\"z-50 w-72 rounded-md border border-border bg-surface p-2 shadow-popover\">\n <div v-if=\"filterable\" class=\"relative mb-2\">\n <Search class=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-muted\" />\n <input\n v-model=\"query\"\n :placeholder=\"filterPlaceholder\"\n class=\"w-full rounded-md border border-border bg-surface py-1.5 pe-2 ps-7 text-sm placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n />\n </div>\n\n <TreeRoot\n :model-value=\"selectedItems\"\n :items=\"visibleNodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n v-model:expanded=\"expanded\"\n multiple\n bubble-select\n @update:model-value=\"onUpdateItems\"\n >\n <TreeItem\n v-for=\"row in rows\"\n :key=\"row.key\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"flex items-center gap-2 rounded py-1.5 text-sm text-foreground data-[selected]:bg-surface-muted/50\"\n :style=\"{ paddingInlineStart: `calc(0.5rem + ${(row.level - 1) * 1}rem)` }\"\n >\n <span\n class=\"flex size-4 shrink-0 items-center justify-center rounded border border-border\"\n :class=\"stateOf(row.node) !== 'unchecked' && 'border-primary-500 bg-primary-500 text-white'\"\n aria-hidden=\"true\"\n >\n <Check v-if=\"stateOf(row.node) === 'checked'\" class=\"size-3\" />\n <span v-else-if=\"stateOf(row.node) === 'indeterminate'\" class=\"block h-0.5 w-2 rounded bg-white\" />\n </span>\n <span class=\"truncate\">{{ row.node.label ?? row.node.value }}</span>\n </TreeItem>\n </TreeRoot>\n\n <div v-if=\"modelValue.length\" class=\"mt-2 flex justify-end border-t border-border pt-2\">\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded px-2 py-1 text-xs text-muted hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"emit('update:modelValue', [])\"\n >\n <X class=\"size-3\" />Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["$attrs","$slots","$attrs"],"sources":["../src/lib/cn.ts","../src/lib/date.ts","../src/lib/icons.ts","../src/components/icon/Icon.vue","../src/components/icon/Icon.vue","../src/components/button/Button.vue","../src/components/button/Button.vue","../src/components/input/Input.vue","../src/components/input/Input.vue","../src/components/textarea/Textarea.vue","../src/components/textarea/Textarea.vue","../src/components/password/Password.vue","../src/components/password/Password.vue","../src/components/checkbox/Checkbox.vue","../src/components/checkbox/Checkbox.vue","../src/components/tag/Tag.vue","../src/components/tag/Tag.vue","../src/components/tabs/Tabs.vue","../src/components/tabs/Tabs.vue","../src/components/tabs/TabsList.vue","../src/components/tabs/TabsList.vue","../src/components/tabs/TabsTrigger.vue","../src/components/tabs/TabsTrigger.vue","../src/components/tabs/TabsContent.vue","../src/components/tabs/TabsContent.vue","../src/components/select/Select.vue","../src/components/select/Select.vue","../src/components/select-button/SelectButton.vue","../src/components/select-button/SelectButton.vue","../src/components/date-picker/DatePicker.vue","../src/components/date-picker/DatePicker.vue","../src/components/dialog/Dialog.vue","../src/components/dialog/Dialog.vue","../src/components/dropdown-menu/DropdownMenu.vue","../src/components/dropdown-menu/DropdownMenu.vue","../src/components/dropdown-menu/DropdownMenuTrigger.vue","../src/components/dropdown-menu/DropdownMenuTrigger.vue","../src/components/dropdown-menu/DropdownMenuContent.vue","../src/components/dropdown-menu/DropdownMenuContent.vue","../src/components/dropdown-menu/DropdownMenuItem.vue","../src/components/dropdown-menu/DropdownMenuItem.vue","../src/components/transfer-list/TransferList.vue","../src/components/transfer-list/TransferList.vue","../src/components/table/Table.vue","../src/components/table/Table.vue","../src/components/table/TableHeader.vue","../src/components/table/TableBody.vue","../src/components/table/TableRow.vue","../src/components/table/TableRow.vue","../src/components/table/TableHead.vue","../src/components/table/TableHead.vue","../src/components/table/TableCell.vue","../src/components/table/TableCell.vue","../src/components/table/TableEmpty.vue","../src/components/table/TableEmpty.vue","../src/lib/pagination.ts","../src/components/table/TablePagination.vue","../src/components/table/TablePagination.vue","../src/lib/table.ts","../src/lib/tableInteractions.ts","../src/components/data-table/DataTable.vue","../src/components/data-table/DataTable.vue","../src/lib/tree.ts","../src/components/tree-table/TreeTable.vue","../src/components/tree-table/TreeTable.vue","../src/components/tree-select/TreeSelect.vue","../src/components/tree-select/TreeSelect.vue"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { CalendarDate, CalendarDateTime, getLocalTimeZone, type DateValue } from '@internationalized/date'\n\nexport function dateToValue(d: Date): CalendarDate {\n return new CalendarDate(d.getFullYear(), d.getMonth() + 1, d.getDate())\n}\n\nexport function valueToDate(v: DateValue): Date {\n if (v instanceof CalendarDateTime) return v.toDate(getLocalTimeZone())\n return new Date(v.year, v.month - 1, v.day)\n}\n\nexport function toMinutes(time: string): number {\n const [h, m] = time.split(':').map(Number)\n return h * 60 + (m || 0)\n}\n\nexport function toTime(minutes: number): string {\n const h = Math.floor(minutes / 60)\n const m = minutes % 60\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`\n}\n\nexport function clampTime(d: Date, time: string): Date {\n const out = new Date(d)\n out.setHours(Math.floor(toMinutes(time) / 60), toMinutes(time) % 60, 0, 0)\n return out\n}\n\nexport function sortRange(a: Date, b: Date): [Date, Date]\nexport function sortRange(a: Date | null, b: Date | null): [Date | null, Date | null]\nexport function sortRange(a: Date | null, b: Date | null): [Date | null, Date | null] {\n if (!a || !b) return [a, b]\n return a.getTime() <= b.getTime() ? [a, b] : [b, a]\n}\n\nexport function toISODate(d: Date): string {\n const m = d.getMonth() + 1\n const day = d.getDate()\n return `${d.getFullYear()}-${String(m).padStart(2, '0')}-${String(day).padStart(2, '0')}`\n}\n","export function toPascalCase(name: string): string {\n return name\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\nconst FALLBACK_ICON = 'circle'\n\n/**\n * Normalises a lucide icon reference to a kebab-case name: accepts `heart`,\n * `chart-line` or `ChevronDown`. An empty name falls back to a circle rather\n * than rendering nothing, so a gap is visible instead of silent.\n */\nexport function resolveIconName(name: string): string {\n const trimmed = name.trim()\n if (!trimmed) return FALLBACK_ICON\n return trimmed\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport * as Lucide from 'lucide-vue-next'\nimport { resolveIconName, toPascalCase } from '../../lib/icons'\n\nconst props = withDefaults(defineProps<{ name: string; size?: number }>(), { size: 16 })\n\nconst resolved = computed(() => {\n const lucide = Lucide as unknown as Record<string, unknown>\n const pascal = toPascalCase(resolveIconName(props.name))\n return (lucide[pascal] as typeof Lucide.Circle | undefined) ?? Lucide.Circle\n})\n</script>\n\n<template>\n <component :is=\"resolved\" :size=\"size\" aria-hidden=\"true\" data-icon :name=\"name\" />\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport * as Lucide from 'lucide-vue-next'\nimport { resolveIconName, toPascalCase } from '../../lib/icons'\n\nconst props = withDefaults(defineProps<{ name: string; size?: number }>(), { size: 16 })\n\nconst resolved = computed(() => {\n const lucide = Lucide as unknown as Record<string, unknown>\n const pascal = toPascalCase(resolveIconName(props.name))\n return (lucide[pascal] as typeof Lucide.Circle | undefined) ?? Lucide.Circle\n})\n</script>\n\n<template>\n <component :is=\"resolved\" :size=\"size\" aria-hidden=\"true\" data-icon :name=\"name\" />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst buttonVariants = tv({\n base: 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 data-[loading=true]:cursor-not-allowed',\n variants: {\n variant: {\n default: 'bg-primary-500 text-white hover:bg-primary-600',\n secondary: 'bg-secondary-500 text-white hover:bg-secondary-600',\n destructive: 'bg-error-500 text-white hover:bg-error-600',\n outline: 'border border-border bg-surface text-foreground hover:bg-surface-muted',\n ghost: 'text-foreground hover:bg-surface-muted',\n },\n size: {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n icon: 'size-9',\n 'icon-sm': 'size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n})\n\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof buttonVariants>['variant']\n size?: VariantProps<typeof buttonVariants>['size']\n type?: 'button' | 'submit' | 'reset'\n disabled?: boolean\n loading?: boolean\n /** Text label; equivalent to slot content. PrimeVue parity for the app migration. */\n label?: string\n }>(),\n { variant: 'default', size: 'default', type: 'button', disabled: false, loading: false },\n)\n\nconst attrs = useAttrs()\nconst isDisabled = computed(() => props.disabled || props.loading || Boolean(attrs.disabled))\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"isDisabled\"\n :data-loading=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <span v-if=\"loading\" class=\"size-4 animate-spin rounded-full border-2 border-current border-t-transparent\" aria-hidden=\"true\" />\n <slot v-else>{{ label }}</slot>\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst buttonVariants = tv({\n base: 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 data-[loading=true]:cursor-not-allowed',\n variants: {\n variant: {\n default: 'bg-primary-500 text-white hover:bg-primary-600',\n secondary: 'bg-secondary-500 text-white hover:bg-secondary-600',\n destructive: 'bg-error-500 text-white hover:bg-error-600',\n outline: 'border border-border bg-surface text-foreground hover:bg-surface-muted',\n ghost: 'text-foreground hover:bg-surface-muted',\n },\n size: {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n icon: 'size-9',\n 'icon-sm': 'size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n})\n\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof buttonVariants>['variant']\n size?: VariantProps<typeof buttonVariants>['size']\n type?: 'button' | 'submit' | 'reset'\n disabled?: boolean\n loading?: boolean\n /** Text label; equivalent to slot content. PrimeVue parity for the app migration. */\n label?: string\n }>(),\n { variant: 'default', size: 'default', type: 'button', disabled: false, loading: false },\n)\n\nconst attrs = useAttrs()\nconst isDisabled = computed(() => props.disabled || props.loading || Boolean(attrs.disabled))\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"isDisabled\"\n :data-loading=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <span v-if=\"loading\" class=\"size-4 animate-spin rounded-full border-2 border-current border-t-transparent\" aria-hidden=\"true\" />\n <slot v-else>{{ label }}</slot>\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n leadingIcon?: string\n trailingIcon?: string\n size?: 'sm' | 'default' | 'lg'\n }>(),\n { size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\n\ndefineExpose({ focus: () => inputRef.value?.focus() })\n</script>\n\n<template>\n <div class=\"relative w-full\">\n <Icon v-if=\"leadingIcon\" :name=\"leadingIcon\" class=\"pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n <input\n ref=\"inputRef\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n leadingIcon ? 'ps-9' : 'ps-3',\n trailingIcon ? 'pe-9' : 'pe-3',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <Icon v-if=\"trailingIcon\" :name=\"trailingIcon\" class=\"pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n leadingIcon?: string\n trailingIcon?: string\n size?: 'sm' | 'default' | 'lg'\n }>(),\n { size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\n\ndefineExpose({ focus: () => inputRef.value?.focus() })\n</script>\n\n<template>\n <div class=\"relative w-full\">\n <Icon v-if=\"leadingIcon\" :name=\"leadingIcon\" class=\"pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n <input\n ref=\"inputRef\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n leadingIcon ? 'ps-9' : 'ps-3',\n trailingIcon ? 'pe-9' : 'pe-3',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <Icon v-if=\"trailingIcon\" :name=\"trailingIcon\" class=\"pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useAttrs } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n }>(),\n { rows: 3 },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\n</script>\n\n<template>\n <textarea\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :class=\"[\n 'w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { useAttrs } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n }>(),\n { rows: 3 },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\n</script>\n\n<template>\n <textarea\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :class=\"[\n 'w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { Eye, EyeOff } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n feedback?: boolean\n /** Applied to the inner input so an external <label for> still matches. */\n id?: string\n }>(),\n { feedback: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst visible = ref(false)\nconst inputType = computed(() => (visible.value ? 'text' : 'password'))\n\nconst strength = computed(() => {\n const v = props.modelValue ?? ''\n if (v.length === 0) return 0\n let score = 0\n if (v.length >= 8) score++\n if (v.length >= 12) score++\n if (/[A-Z]/.test(v) && /[a-z]/.test(v)) score++\n if (/\\d/.test(v)) score++\n if (/[^A-Za-z0-9]/.test(v)) score++\n return Math.max(1, Math.min(4, Math.ceil((score / 5) * 4)))\n})\n</script>\n\n<template>\n <div class=\"w-full\">\n <div class=\"relative w-full\">\n <input\n :id=\"id\"\n :type=\"inputType\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex h-9 w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n 'pe-10',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <button\n type=\"button\"\n :disabled=\"disabled\"\n aria-label=\"Toggle password visibility\"\n class=\"absolute end-2 top-1/2 -translate-y-1/2 rounded p-1 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"visible = !visible\"\n >\n <EyeOff v-if=\"visible\" class=\"size-4\" />\n <Eye v-else class=\"size-4\" />\n </button>\n </div>\n <div v-if=\"feedback && modelValue\" class=\"mt-1.5 flex items-center gap-1.5\" aria-hidden=\"true\">\n <span\n v-for=\"i in 4\"\n :key=\"i\"\n class=\"h-1 flex-1 rounded-full transition-colors\"\n :class=\"i <= strength ? 'bg-success-500' : 'bg-surface-muted'\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { Eye, EyeOff } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n feedback?: boolean\n /** Applied to the inner input so an external <label for> still matches. */\n id?: string\n }>(),\n { feedback: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst visible = ref(false)\nconst inputType = computed(() => (visible.value ? 'text' : 'password'))\n\nconst strength = computed(() => {\n const v = props.modelValue ?? ''\n if (v.length === 0) return 0\n let score = 0\n if (v.length >= 8) score++\n if (v.length >= 12) score++\n if (/[A-Z]/.test(v) && /[a-z]/.test(v)) score++\n if (/\\d/.test(v)) score++\n if (/[^A-Za-z0-9]/.test(v)) score++\n return Math.max(1, Math.min(4, Math.ceil((score / 5) * 4)))\n})\n</script>\n\n<template>\n <div class=\"w-full\">\n <div class=\"relative w-full\">\n <input\n :id=\"id\"\n :type=\"inputType\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex h-9 w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n 'pe-10',\n ]\"\n v-bind=\"attrs\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n />\n <button\n type=\"button\"\n :disabled=\"disabled\"\n aria-label=\"Toggle password visibility\"\n class=\"absolute end-2 top-1/2 -translate-y-1/2 rounded p-1 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"visible = !visible\"\n >\n <EyeOff v-if=\"visible\" class=\"size-4\" />\n <Eye v-else class=\"size-4\" />\n </button>\n </div>\n <div v-if=\"feedback && modelValue\" class=\"mt-1.5 flex items-center gap-1.5\" aria-hidden=\"true\">\n <span\n v-for=\"i in 4\"\n :key=\"i\"\n class=\"h-1 flex-1 rounded-full transition-colors\"\n :class=\"i <= strength ? 'bg-success-500' : 'bg-surface-muted'\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { CheckboxIndicator, CheckboxRoot } from 'reka-ui'\nimport { Check } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean\n disabled?: boolean\n id?: string\n }>(),\n { modelValue: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()\n</script>\n\n<template>\n <CheckboxRoot\n :id=\"id\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"peer size-4 shrink-0 rounded border border-border bg-surface shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 data-[state=checked]:border-primary-500 data-[state=checked]:bg-primary-500 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n @update:model-value=\"emit('update:modelValue', $event as boolean)\"\n >\n <CheckboxIndicator class=\"flex items-center justify-center text-white\">\n <Check class=\"size-3.5\" />\n </CheckboxIndicator>\n </CheckboxRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { CheckboxIndicator, CheckboxRoot } from 'reka-ui'\nimport { Check } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: boolean\n disabled?: boolean\n id?: string\n }>(),\n { modelValue: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()\n</script>\n\n<template>\n <CheckboxRoot\n :id=\"id\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"peer size-4 shrink-0 rounded border border-border bg-surface shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 data-[state=checked]:border-primary-500 data-[state=checked]:bg-primary-500 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n @update:model-value=\"emit('update:modelValue', $event as boolean)\"\n >\n <CheckboxIndicator class=\"flex items-center justify-center text-white\">\n <Check class=\"size-3.5\" />\n </CheckboxIndicator>\n </CheckboxRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\nimport { X } from 'lucide-vue-next'\nimport Icon from '../icon/Icon.vue'\n\nconst tagVariants = tv({\n base: 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n variants: {\n tone: {\n info: 'bg-primary-100 text-primary-800',\n success: 'bg-success-100 text-success-800',\n warning: 'bg-warning-100 text-warning-800',\n danger: 'bg-error-100 text-error-800',\n secondary: 'bg-surface-muted text-foreground',\n },\n },\n defaultVariants: { tone: 'secondary' },\n})\n\nwithDefaults(\n defineProps<{\n tone?: VariantProps<typeof tagVariants>['tone']\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = NonNullable<VariantProps<typeof tagVariants>['tone']>\n</script>\n\n<template>\n <span :class=\"tagVariants({ tone })\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-3\" />\n <slot />\n <button\n v-if=\"removable\"\n type=\"button\"\n :aria-label=\"removeLabel\"\n class=\"-me-0.5 ms-0.5 rounded-full p-0.5 transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"emit('remove')\"\n >\n <X class=\"size-3\" />\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\nimport { X } from 'lucide-vue-next'\nimport Icon from '../icon/Icon.vue'\n\nconst tagVariants = tv({\n base: 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n variants: {\n tone: {\n info: 'bg-primary-100 text-primary-800',\n success: 'bg-success-100 text-success-800',\n warning: 'bg-warning-100 text-warning-800',\n danger: 'bg-error-100 text-error-800',\n secondary: 'bg-surface-muted text-foreground',\n },\n },\n defaultVariants: { tone: 'secondary' },\n})\n\nwithDefaults(\n defineProps<{\n tone?: VariantProps<typeof tagVariants>['tone']\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = NonNullable<VariantProps<typeof tagVariants>['tone']>\n</script>\n\n<template>\n <span :class=\"tagVariants({ tone })\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-3\" />\n <slot />\n <button\n v-if=\"removable\"\n type=\"button\"\n :aria-label=\"removeLabel\"\n class=\"-me-0.5 ms-0.5 rounded-full p-0.5 transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"emit('remove')\"\n >\n <X class=\"size-3\" />\n </button>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsRoot } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ modelValue?: string }>(), {})\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n</script>\n\n<template>\n <TabsRoot :model-value=\"modelValue\" @update:model-value=\"emit('update:modelValue', $event as string)\">\n <slot />\n </TabsRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsRoot } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ modelValue?: string }>(), {})\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n</script>\n\n<template>\n <TabsRoot :model-value=\"modelValue\" @update:model-value=\"emit('update:modelValue', $event as string)\">\n <slot />\n </TabsRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsList as RekaTabsList } from 'reka-ui'\n</script>\n\n<template>\n <RekaTabsList class=\"inline-flex h-9 w-full items-center justify-start gap-1 rounded-lg bg-surface-muted p-1 text-muted\">\n <slot />\n </RekaTabsList>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsList as RekaTabsList } from 'reka-ui'\n</script>\n\n<template>\n <RekaTabsList class=\"inline-flex h-9 w-full items-center justify-start gap-1 rounded-lg bg-surface-muted p-1 text-muted\">\n <slot />\n </RekaTabsList>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsTrigger as RekaTabsTrigger } from 'reka-ui'\n\ndefineProps<{ value: string; disabled?: boolean }>()\n</script>\n\n<template>\n <RekaTabsTrigger\n :value=\"value\"\n :disabled=\"disabled\"\n class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[disabled]:opacity-50\"\n >\n <slot />\n </RekaTabsTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsTrigger as RekaTabsTrigger } from 'reka-ui'\n\ndefineProps<{ value: string; disabled?: boolean }>()\n</script>\n\n<template>\n <RekaTabsTrigger\n :value=\"value\"\n :disabled=\"disabled\"\n class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[disabled]:opacity-50\"\n >\n <slot />\n </RekaTabsTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsContent as RekaTabsContent } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ value: string; padding?: boolean }>(), { padding: true })\n</script>\n\n<template>\n <RekaTabsContent :value=\"value\" :class=\"['focus-visible:outline-none', padding ? 'pt-4' : '']\">\n <slot />\n </RekaTabsContent>\n</template>\n","<script setup lang=\"ts\">\nimport { TabsContent as RekaTabsContent } from 'reka-ui'\n\nconst props = withDefaults(defineProps<{ value: string; padding?: boolean }>(), { padding: true })\n</script>\n\n<template>\n <RekaTabsContent :value=\"value\" :class=\"['focus-visible:outline-none', padding ? 'pt-4' : '']\">\n <slot />\n </RekaTabsContent>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n SelectContent,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectRoot,\n SelectTrigger,\n SelectValue,\n type AcceptableValue,\n} from 'reka-ui'\nimport { Check, ChevronDown, X } from 'lucide-vue-next'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue | AcceptableValue[]\n options?: unknown[]\n optionLabel?: string\n optionValue?: string\n placeholder?: string\n clearable?: boolean\n disabled?: boolean\n multiple?: boolean\n size?: 'sm' | 'default'\n invalid?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst open = ref(false)\n\n/** Options may be objects (optionLabel/optionValue) or primitives, as PrimeVue allowed. */\nfunction valueOf(opt: unknown): AcceptableValue {\n if (opt && typeof opt === 'object' && props.optionValue) {\n return ((opt as Record<string, unknown>)[props.optionValue] ?? opt) as AcceptableValue\n }\n return opt as AcceptableValue\n}\nfunction labelOf(opt: unknown): string {\n if (opt && typeof opt === 'object' && props.optionLabel) {\n return String((opt as Record<string, unknown>)[props.optionLabel] ?? '')\n }\n return opt == null ? '' : String(opt)\n}\n\nconst display = computed(() => {\n if (props.multiple) {\n const sel = (Array.isArray(props.modelValue) ? props.modelValue : []) as unknown[]\n return sel\n .map((v) => labelOf(props.options?.find((o) => valueOf(o) === v)))\n .filter(Boolean)\n .join(', ')\n }\n return props.modelValue == null\n ? ''\n : labelOf(props.options?.find((o) => valueOf(o) === props.modelValue))\n})\n\nconst hasValue = computed(() =>\n props.multiple && Array.isArray(props.modelValue)\n ? (props.modelValue as unknown[]).length > 0\n : props.modelValue != null,\n)\n\nfunction onClear() {\n emit('update:modelValue', props.multiple ? [] : null)\n}\n</script>\n\n<template>\n <SelectRoot\n v-model:open=\"open\"\n :model-value=\"modelValue\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <SelectTrigger\n :class=\"cn(\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n $attrs.class as string || '',\n )\"\n v-bind=\"$attrs\"\n >\n <SelectValue :placeholder=\"placeholder\">\n <span class=\"truncate\">{{ display || placeholder }}</span>\n </SelectValue>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">\n <button\n v-if=\"clearable && hasValue\"\n type=\"button\"\n aria-label=\"Clear selection\"\n class=\"rounded p-0.5 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"onClear\"\n >\n <X class=\"size-3.5\" />\n </button>\n <ChevronDown class=\"size-4 opacity-50\" />\n </span>\n </SelectTrigger>\n <!-- reka-ui keeps an empty placeholder <div> in the DOM while the select is\n closed. In any `gap-*` flex container that extra zero-size item adds a\n gap, which vanishes when the popper opens — shifting sibling labels and\n controls. Rendering the content only while open drops the placeholder. -->\n <SelectContent\n v-if=\"open\"\n position=\"popper\"\n :side-offset=\"4\"\n class=\"z-50 min-w-[--reka-select-trigger-width] rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <SelectItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n class=\"relative flex cursor-pointer select-none items-center rounded px-2 py-1.5 pe-8 text-sm text-foreground outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[disabled]:opacity-50\"\n >\n <SelectItemText>{{ labelOf(opt) }}</SelectItemText>\n <SelectItemIndicator class=\"absolute end-2 flex items-center justify-center text-primary-600\">\n <Check class=\"size-4\" />\n </SelectItemIndicator>\n </SelectItem>\n </SelectContent>\n </SelectRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n SelectContent,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectRoot,\n SelectTrigger,\n SelectValue,\n type AcceptableValue,\n} from 'reka-ui'\nimport { Check, ChevronDown, X } from 'lucide-vue-next'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue | AcceptableValue[]\n options?: unknown[]\n optionLabel?: string\n optionValue?: string\n placeholder?: string\n clearable?: boolean\n disabled?: boolean\n multiple?: boolean\n size?: 'sm' | 'default'\n invalid?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst open = ref(false)\n\n/** Options may be objects (optionLabel/optionValue) or primitives, as PrimeVue allowed. */\nfunction valueOf(opt: unknown): AcceptableValue {\n if (opt && typeof opt === 'object' && props.optionValue) {\n return ((opt as Record<string, unknown>)[props.optionValue] ?? opt) as AcceptableValue\n }\n return opt as AcceptableValue\n}\nfunction labelOf(opt: unknown): string {\n if (opt && typeof opt === 'object' && props.optionLabel) {\n return String((opt as Record<string, unknown>)[props.optionLabel] ?? '')\n }\n return opt == null ? '' : String(opt)\n}\n\nconst display = computed(() => {\n if (props.multiple) {\n const sel = (Array.isArray(props.modelValue) ? props.modelValue : []) as unknown[]\n return sel\n .map((v) => labelOf(props.options?.find((o) => valueOf(o) === v)))\n .filter(Boolean)\n .join(', ')\n }\n return props.modelValue == null\n ? ''\n : labelOf(props.options?.find((o) => valueOf(o) === props.modelValue))\n})\n\nconst hasValue = computed(() =>\n props.multiple && Array.isArray(props.modelValue)\n ? (props.modelValue as unknown[]).length > 0\n : props.modelValue != null,\n)\n\nfunction onClear() {\n emit('update:modelValue', props.multiple ? [] : null)\n}\n</script>\n\n<template>\n <SelectRoot\n v-model:open=\"open\"\n :model-value=\"modelValue\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <SelectTrigger\n :class=\"cn(\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500 focus-visible:ring-error-500' : '',\n $attrs.class as string || '',\n )\"\n v-bind=\"$attrs\"\n >\n <SelectValue :placeholder=\"placeholder\">\n <span class=\"truncate\">{{ display || placeholder }}</span>\n </SelectValue>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">\n <button\n v-if=\"clearable && hasValue\"\n type=\"button\"\n aria-label=\"Clear selection\"\n class=\"rounded p-0.5 text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click.stop=\"onClear\"\n >\n <X class=\"size-3.5\" />\n </button>\n <ChevronDown class=\"size-4 opacity-50\" />\n </span>\n </SelectTrigger>\n <!-- reka-ui keeps an empty placeholder <div> in the DOM while the select is\n closed. In any `gap-*` flex container that extra zero-size item adds a\n gap, which vanishes when the popper opens — shifting sibling labels and\n controls. Rendering the content only while open drops the placeholder. -->\n <SelectContent\n v-if=\"open\"\n position=\"popper\"\n :side-offset=\"4\"\n class=\"z-50 min-w-[--reka-select-trigger-width] rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <SelectItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n class=\"relative flex cursor-pointer select-none items-center rounded px-2 py-1.5 pe-8 text-sm text-foreground outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[disabled]:opacity-50\"\n >\n <SelectItemText>{{ labelOf(opt) }}</SelectItemText>\n <SelectItemIndicator class=\"absolute end-2 flex items-center justify-center text-primary-600\">\n <Check class=\"size-4\" />\n </SelectItemIndicator>\n </SelectItem>\n </SelectContent>\n </SelectRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { RadioGroupIndicator, RadioGroupItem, RadioGroupRoot, type AcceptableValue } from 'reka-ui'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue\n options?: Record<string, unknown>[]\n optionLabel?: string\n optionValue?: string\n disabled?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst rootEl = ref<InstanceType<typeof RadioGroupRoot> | null>(null)\nconst indicator = ref({ left: 0, top: 0, width: 0, height: 0, ready: false })\nlet frame = 0\n\nfunction valueOf(opt: Record<string, unknown> | undefined): AcceptableValue {\n return (opt?.[props.optionValue as string] ?? opt) as AcceptableValue\n}\nfunction labelOf(opt: Record<string, unknown> | undefined): string {\n return String(opt?.[props.optionLabel as string] ?? opt ?? '')\n}\n\nfunction measure() {\n const root = rootEl.value?.$el as HTMLElement | undefined\n const checked = root?.querySelector<HTMLElement>('[role=\"radio\"][data-state=\"checked\"]')\n if (!checked) {\n indicator.value.ready = false\n return\n }\n indicator.value = {\n left: checked.offsetLeft,\n top: checked.offsetTop,\n width: checked.offsetWidth,\n height: checked.offsetHeight,\n ready: true,\n }\n}\n\nfunction scheduleMeasure() {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n}\n\nlet observer: ResizeObserver | undefined\n\nonMounted(() => {\n scheduleMeasure()\n if (typeof ResizeObserver !== 'undefined' && rootEl.value?.$el) {\n observer = new ResizeObserver(scheduleMeasure)\n observer.observe(rootEl.value.$el as HTMLElement)\n }\n window.addEventListener('resize', scheduleMeasure)\n})\n\nonBeforeUnmount(() => {\n cancelAnimationFrame(frame)\n observer?.disconnect()\n window.removeEventListener('resize', scheduleMeasure)\n})\n\nwatch(() => props.modelValue, scheduleMeasure)\nwatch(() => props.options, scheduleMeasure, { deep: true })\n</script>\n\n<template>\n <RadioGroupRoot\n ref=\"rootEl\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"relative inline-flex flex-wrap items-center gap-1 rounded-md border border-border bg-surface p-1\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <span\n v-show=\"indicator.ready\"\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute rounded bg-primary-500 transition-all duration-200 ease-out motion-reduce:transition-none\"\n :style=\"{\n left: `${indicator.left}px`,\n top: `${indicator.top}px`,\n width: `${indicator.width}px`,\n height: `${indicator.height}px`,\n }\"\n />\n <RadioGroupItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n :disabled=\"disabled\"\n class=\"relative inline-flex items-center justify-center rounded px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=checked]:text-white data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n >\n <RadioGroupIndicator class=\"hidden\" />\n {{ labelOf(opt) }}\n </RadioGroupItem>\n </RadioGroupRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { RadioGroupIndicator, RadioGroupItem, RadioGroupRoot, type AcceptableValue } from 'reka-ui'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: AcceptableValue\n options?: Record<string, unknown>[]\n optionLabel?: string\n optionValue?: string\n disabled?: boolean\n }>(),\n { optionLabel: 'label', optionValue: 'value' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst rootEl = ref<InstanceType<typeof RadioGroupRoot> | null>(null)\nconst indicator = ref({ left: 0, top: 0, width: 0, height: 0, ready: false })\nlet frame = 0\n\nfunction valueOf(opt: Record<string, unknown> | undefined): AcceptableValue {\n return (opt?.[props.optionValue as string] ?? opt) as AcceptableValue\n}\nfunction labelOf(opt: Record<string, unknown> | undefined): string {\n return String(opt?.[props.optionLabel as string] ?? opt ?? '')\n}\n\nfunction measure() {\n const root = rootEl.value?.$el as HTMLElement | undefined\n const checked = root?.querySelector<HTMLElement>('[role=\"radio\"][data-state=\"checked\"]')\n if (!checked) {\n indicator.value.ready = false\n return\n }\n indicator.value = {\n left: checked.offsetLeft,\n top: checked.offsetTop,\n width: checked.offsetWidth,\n height: checked.offsetHeight,\n ready: true,\n }\n}\n\nfunction scheduleMeasure() {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n}\n\nlet observer: ResizeObserver | undefined\n\nonMounted(() => {\n scheduleMeasure()\n if (typeof ResizeObserver !== 'undefined' && rootEl.value?.$el) {\n observer = new ResizeObserver(scheduleMeasure)\n observer.observe(rootEl.value.$el as HTMLElement)\n }\n window.addEventListener('resize', scheduleMeasure)\n})\n\nonBeforeUnmount(() => {\n cancelAnimationFrame(frame)\n observer?.disconnect()\n window.removeEventListener('resize', scheduleMeasure)\n})\n\nwatch(() => props.modelValue, scheduleMeasure)\nwatch(() => props.options, scheduleMeasure, { deep: true })\n</script>\n\n<template>\n <RadioGroupRoot\n ref=\"rootEl\"\n :model-value=\"modelValue\"\n :disabled=\"disabled\"\n class=\"relative inline-flex flex-wrap items-center gap-1 rounded-md border border-border bg-surface p-1\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <span\n v-show=\"indicator.ready\"\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute rounded bg-primary-500 transition-all duration-200 ease-out motion-reduce:transition-none\"\n :style=\"{\n left: `${indicator.left}px`,\n top: `${indicator.top}px`,\n width: `${indicator.width}px`,\n height: `${indicator.height}px`,\n }\"\n />\n <RadioGroupItem\n v-for=\"opt in options\"\n :key=\"String(valueOf(opt))\"\n :value=\"valueOf(opt)\"\n :disabled=\"disabled\"\n class=\"relative inline-flex items-center justify-center rounded px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 data-[state=checked]:text-white data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n >\n <RadioGroupIndicator class=\"hidden\" />\n {{ labelOf(opt) }}\n </RadioGroupItem>\n </RadioGroupRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport { clampTime, sortRange, toISODate, toTime } from '../../lib/date'\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n size?: 'sm' | 'default'\n /** Applied to the trigger button so an external <label for> still matches. */\n inputId?: string\n }>(),\n { mode: 'date', placeholder: 'Select date', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst open = ref(false)\nconst viewDate = ref(new Date())\nconst start = ref<Date | null>(null)\nconst end = ref<Date | null>(null)\nconst time = ref('09:00')\n\nconst WEEKDAYS = [0, 1, 2, 3, 4, 5, 6]\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (Array.isArray(v)) {\n start.value = v[0] ?? null\n end.value = v[1] ?? null\n } else if (v instanceof Date) {\n start.value = v\n end.value = null\n } else {\n start.value = null\n end.value = null\n }\n },\n { immediate: true },\n)\n\nconst grid = computed(() => {\n const first = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), 1)\n const lead = (first.getDay() + 6) % 7 // Monday-first\n const cells: (Date | null)[] = Array.from({ length: lead }, () => null)\n const days = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + 1, 0).getDate()\n for (let d = 1; d <= days; d++) cells.push(new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), d))\n return cells\n})\n\nfunction inRange(d: Date): boolean {\n if (!start.value || !end.value) return false\n const [s, e] = sortRange(start.value, end.value)\n return d.getTime() >= s.getTime() && d.getTime() <= e.getTime()\n}\n\nfunction monthLabel(): string {\n return viewDate.value.toLocaleString('en', { month: 'long', year: 'numeric' })\n}\n\nfunction shiftMonth(n: number) {\n viewDate.value = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + n, 1)\n}\n\nfunction hasValue(): boolean {\n return props.mode === 'range' ? Boolean(start.value && end.value) : Boolean(start.value)\n}\n\nfunction pick(d: Date) {\n if (props.mode === 'range') {\n if (!start.value || end.value) {\n start.value = d\n end.value = null\n } else {\n const [s, e] = sortRange(start.value, d)\n start.value = s\n end.value = e\n }\n return\n }\n start.value = d\n if (props.mode === 'datetime') return // wait for Apply\n commit()\n open.value = false\n}\n\nfunction commit() {\n if (!start.value) return\n if (props.mode === 'range') {\n if (!end.value) return\n emit('update:modelValue', [start.value, end.value])\n } else if (props.mode === 'datetime') {\n emit('update:modelValue', clampTime(start.value, time.value))\n } else {\n emit('update:modelValue', start.value)\n }\n}\n\nfunction clear() {\n start.value = null\n end.value = null\n emit('update:modelValue', null)\n open.value = false\n}\n\nconst display = computed(() => {\n if (props.mode === 'range') {\n if (!start.value || !end.value) return ''\n const [s, e] = sortRange(start.value, end.value)\n return `${toISODate(s)} – ${toISODate(e)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n return `${toISODate(d)}${props.mode === 'datetime' ? ' ' + toTime(d.getHours() * 60 + d.getMinutes()) : ''}`\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n :id=\"inputId\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50 data-[state=open]:border-primary-500',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500' : '',\n ]\"\n >\n <span :class=\"['truncate', display ? 'text-foreground' : 'text-muted']\">{{ display || placeholder }}</span>\n <CalendarIcon class=\"size-4 shrink-0 text-muted\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n :side-offset=\"4\"\n class=\"z-50 rounded-md border border-border bg-surface p-3 shadow-popover\"\n >\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(-1)\"\n >\n <ChevronLeft class=\"size-4\" />\n </button>\n <span class=\"text-sm font-medium\">{{ monthLabel() }}</span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(1)\"\n >\n <ChevronRight class=\"size-4\" />\n </button>\n </div>\n\n <div class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"d in WEEKDAYS\" :key=\"d\" class=\"py-1 font-medium text-muted\">\n {{ new Date(2026, 0, 5 + d).toLocaleDateString('en', { weekday: 'short' }) }}\n </span>\n <template v-for=\"(cell, i) in grid\" :key=\"i\">\n <span v-if=\"!cell\" />\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'flex h-8 items-center justify-center rounded-md text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',\n inRange(cell) ? 'bg-primary-100 text-primary-800' : 'hover:bg-surface-muted',\n start && start.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n end && end.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n ]\"\n @click=\"pick(cell)\"\n >\n {{ cell.getDate() }}\n </button>\n </template>\n </div>\n\n <div v-if=\"mode === 'datetime'\" class=\"mt-3 flex items-center justify-between gap-2 border-t border-border pt-3\">\n <label class=\"flex items-center gap-2 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <input v-model=\"time\" type=\"time\" class=\"rounded border border-border bg-surface px-2 py-1 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\" />\n </label>\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n :disabled=\"!start\"\n class=\"rounded bg-primary-500 px-3 py-1 text-sm text-white transition-colors hover:bg-primary-600 disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"commit(); open = false\"\n >\n Apply\n </button>\n </div>\n </div>\n\n <div v-else-if=\"hasValue()\" class=\"mt-3 flex justify-end border-t border-border pt-3\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport { clampTime, sortRange, toISODate, toTime } from '../../lib/date'\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n placeholder?: string\n disabled?: boolean\n invalid?: boolean\n size?: 'sm' | 'default'\n /** Applied to the trigger button so an external <label for> still matches. */\n inputId?: string\n }>(),\n { mode: 'date', placeholder: 'Select date', size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst open = ref(false)\nconst viewDate = ref(new Date())\nconst start = ref<Date | null>(null)\nconst end = ref<Date | null>(null)\nconst time = ref('09:00')\n\nconst WEEKDAYS = [0, 1, 2, 3, 4, 5, 6]\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (Array.isArray(v)) {\n start.value = v[0] ?? null\n end.value = v[1] ?? null\n } else if (v instanceof Date) {\n start.value = v\n end.value = null\n } else {\n start.value = null\n end.value = null\n }\n },\n { immediate: true },\n)\n\nconst grid = computed(() => {\n const first = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), 1)\n const lead = (first.getDay() + 6) % 7 // Monday-first\n const cells: (Date | null)[] = Array.from({ length: lead }, () => null)\n const days = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + 1, 0).getDate()\n for (let d = 1; d <= days; d++) cells.push(new Date(viewDate.value.getFullYear(), viewDate.value.getMonth(), d))\n return cells\n})\n\nfunction inRange(d: Date): boolean {\n if (!start.value || !end.value) return false\n const [s, e] = sortRange(start.value, end.value)\n return d.getTime() >= s.getTime() && d.getTime() <= e.getTime()\n}\n\nfunction monthLabel(): string {\n return viewDate.value.toLocaleString('en', { month: 'long', year: 'numeric' })\n}\n\nfunction shiftMonth(n: number) {\n viewDate.value = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + n, 1)\n}\n\nfunction hasValue(): boolean {\n return props.mode === 'range' ? Boolean(start.value && end.value) : Boolean(start.value)\n}\n\nfunction pick(d: Date) {\n if (props.mode === 'range') {\n if (!start.value || end.value) {\n start.value = d\n end.value = null\n } else {\n const [s, e] = sortRange(start.value, d)\n start.value = s\n end.value = e\n }\n return\n }\n start.value = d\n if (props.mode === 'datetime') return // wait for Apply\n commit()\n open.value = false\n}\n\nfunction commit() {\n if (!start.value) return\n if (props.mode === 'range') {\n if (!end.value) return\n emit('update:modelValue', [start.value, end.value])\n } else if (props.mode === 'datetime') {\n emit('update:modelValue', clampTime(start.value, time.value))\n } else {\n emit('update:modelValue', start.value)\n }\n}\n\nfunction clear() {\n start.value = null\n end.value = null\n emit('update:modelValue', null)\n open.value = false\n}\n\nconst display = computed(() => {\n if (props.mode === 'range') {\n if (!start.value || !end.value) return ''\n const [s, e] = sortRange(start.value, end.value)\n return `${toISODate(s)} – ${toISODate(e)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n return `${toISODate(d)}${props.mode === 'datetime' ? ' ' + toTime(d.getHours() * 60 + d.getMinutes()) : ''}`\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n :id=\"inputId\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50 data-[state=open]:border-primary-500',\n size === 'sm' ? 'h-8 text-xs' : 'h-9',\n invalid ? 'border-error-500' : '',\n ]\"\n >\n <span :class=\"['truncate', display ? 'text-foreground' : 'text-muted']\">{{ display || placeholder }}</span>\n <CalendarIcon class=\"size-4 shrink-0 text-muted\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n :side-offset=\"4\"\n class=\"z-50 rounded-md border border-border bg-surface p-3 shadow-popover\"\n >\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(-1)\"\n >\n <ChevronLeft class=\"size-4\" />\n </button>\n <span class=\"text-sm font-medium\">{{ monthLabel() }}</span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n class=\"rounded p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"shiftMonth(1)\"\n >\n <ChevronRight class=\"size-4\" />\n </button>\n </div>\n\n <div class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"d in WEEKDAYS\" :key=\"d\" class=\"py-1 font-medium text-muted\">\n {{ new Date(2026, 0, 5 + d).toLocaleDateString('en', { weekday: 'short' }) }}\n </span>\n <template v-for=\"(cell, i) in grid\" :key=\"i\">\n <span v-if=\"!cell\" />\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'flex h-8 items-center justify-center rounded-md text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',\n inRange(cell) ? 'bg-primary-100 text-primary-800' : 'hover:bg-surface-muted',\n start && start.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n end && end.getTime() === cell.getTime() ? 'bg-primary-500 text-white hover:bg-primary-500' : '',\n ]\"\n @click=\"pick(cell)\"\n >\n {{ cell.getDate() }}\n </button>\n </template>\n </div>\n\n <div v-if=\"mode === 'datetime'\" class=\"mt-3 flex items-center justify-between gap-2 border-t border-border pt-3\">\n <label class=\"flex items-center gap-2 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <input v-model=\"time\" type=\"time\" class=\"rounded border border-border bg-surface px-2 py-1 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\" />\n </label>\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n <button\n type=\"button\"\n :disabled=\"!start\"\n class=\"rounded bg-primary-500 px-3 py-1 text-sm text-white transition-colors hover:bg-primary-600 disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"commit(); open = false\"\n >\n Apply\n </button>\n </div>\n </div>\n\n <div v-else-if=\"hasValue()\" class=\"mt-3 flex justify-end border-t border-border pt-3\">\n <button\n type=\"button\"\n class=\"rounded px-3 py-1 text-sm text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"clear\"\n >\n Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n DialogTrigger,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n visible?: boolean\n title?: string\n description?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n }>(),\n { size: 'md' },\n)\n\nconst emit = defineEmits<{ 'update:visible': [value: boolean]; close: [] }>()\n\nconst open = computed({\n get: () => props.visible ?? false,\n set: (v: boolean) => emit('update:visible', v),\n})\n\nconst widths: Record<string, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-2xl',\n xl: 'max-w-4xl',\n}\n\nfunction onOpenChange(v: boolean) {\n emit('update:visible', v)\n if (!v) emit('close')\n}\n</script>\n\n<template>\n <DialogRoot :open=\"open\" @update:open=\"onOpenChange\">\n <DialogTrigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" />\n </DialogTrigger>\n <DialogPortal>\n <DialogOverlay class=\"fixed inset-0 z-50 bg-black/50\" />\n <DialogContent\n :class=\"[\n 'fixed left-1/2 top-1/2 z-50 w-full max-h-[85vh] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border border-border bg-surface shadow-dialog focus-visible:outline-none',\n widths[size],\n ]\"\n >\n <div class=\"flex items-start justify-between gap-4 border-b border-border p-5 pb-4\">\n <div class=\"min-w-0\">\n <DialogTitle v-if=\"title || $slots.header\" class=\"text-lg font-semibold text-foreground\">\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription v-if=\"description || $slots.description\" class=\"mt-1 text-sm text-muted\">\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n class=\"rounded-md p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n aria-label=\"Close\"\n >\n <X class=\"size-4\" />\n </DialogClose>\n </div>\n <div class=\"overflow-y-auto bg-surface p-5\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"flex justify-end gap-2 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </div>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n DialogTrigger,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nconst props = withDefaults(\n defineProps<{\n visible?: boolean\n title?: string\n description?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n }>(),\n { size: 'md' },\n)\n\nconst emit = defineEmits<{ 'update:visible': [value: boolean]; close: [] }>()\n\nconst open = computed({\n get: () => props.visible ?? false,\n set: (v: boolean) => emit('update:visible', v),\n})\n\nconst widths: Record<string, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-2xl',\n xl: 'max-w-4xl',\n}\n\nfunction onOpenChange(v: boolean) {\n emit('update:visible', v)\n if (!v) emit('close')\n}\n</script>\n\n<template>\n <DialogRoot :open=\"open\" @update:open=\"onOpenChange\">\n <DialogTrigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" />\n </DialogTrigger>\n <DialogPortal>\n <DialogOverlay class=\"fixed inset-0 z-50 bg-black/50\" />\n <DialogContent\n :class=\"[\n 'fixed left-1/2 top-1/2 z-50 w-full max-h-[85vh] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border border-border bg-surface shadow-dialog focus-visible:outline-none',\n widths[size],\n ]\"\n >\n <div class=\"flex items-start justify-between gap-4 border-b border-border p-5 pb-4\">\n <div class=\"min-w-0\">\n <DialogTitle v-if=\"title || $slots.header\" class=\"text-lg font-semibold text-foreground\">\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription v-if=\"description || $slots.description\" class=\"mt-1 text-sm text-muted\">\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n class=\"rounded-md p-1 text-muted transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n aria-label=\"Close\"\n >\n <X class=\"size-4\" />\n </DialogClose>\n </div>\n <div class=\"overflow-y-auto bg-surface p-5\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"flex justify-end gap-2 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </div>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuRoot } from 'reka-ui'\n\nconst emit = defineEmits<{ 'update:open': [value: boolean] }>()\n</script>\n\n<template>\n <DropdownMenuRoot v-bind=\"$attrs\" @update:open=\"emit('update:open', $event as boolean)\">\n <slot />\n </DropdownMenuRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuRoot } from 'reka-ui'\n\nconst emit = defineEmits<{ 'update:open': [value: boolean] }>()\n</script>\n\n<template>\n <DropdownMenuRoot v-bind=\"$attrs\" @update:open=\"emit('update:open', $event as boolean)\">\n <slot />\n </DropdownMenuRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuTrigger as RekaTrigger } from 'reka-ui'\n</script>\n\n<template>\n <RekaTrigger as-child focus-on-select>\n <slot />\n </RekaTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuTrigger as RekaTrigger } from 'reka-ui'\n</script>\n\n<template>\n <RekaTrigger as-child focus-on-select>\n <slot />\n </RekaTrigger>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuContent as RekaContent, DropdownMenuPortal as RekaPortal } from 'reka-ui'\n\nwithDefaults(\n defineProps<{\n align?: 'start' | 'center' | 'end'\n side?: 'top' | 'right' | 'bottom' | 'left'\n sideOffset?: number\n }>(),\n { align: 'start', side: 'bottom', sideOffset: 4 },\n)\n</script>\n\n<template>\n <RekaPortal>\n <RekaContent\n :align=\"align\"\n :side=\"side\"\n :side-offset=\"sideOffset\"\n class=\"z-50 min-w-40 rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <slot />\n </RekaContent>\n </RekaPortal>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuContent as RekaContent, DropdownMenuPortal as RekaPortal } from 'reka-ui'\n\nwithDefaults(\n defineProps<{\n align?: 'start' | 'center' | 'end'\n side?: 'top' | 'right' | 'bottom' | 'left'\n sideOffset?: number\n }>(),\n { align: 'start', side: 'bottom', sideOffset: 4 },\n)\n</script>\n\n<template>\n <RekaPortal>\n <RekaContent\n :align=\"align\"\n :side=\"side\"\n :side-offset=\"sideOffset\"\n class=\"z-50 min-w-40 rounded-md border border-border bg-surface p-1 shadow-popover\"\n >\n <slot />\n </RekaContent>\n </RekaPortal>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuItem as RekaItem } from 'reka-ui'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst itemVariants = tv({\n base: 'relative flex w-full cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n variants: {\n variant: {\n default: 'text-foreground',\n destructive: 'text-error-600',\n },\n },\n defaultVariants: { variant: 'default' },\n})\n\ndefineProps<{ variant?: VariantProps<typeof itemVariants>['variant'] }>()\nconst emit = defineEmits<{ select: [] }>()\n</script>\n\n<template>\n <RekaItem :class=\"itemVariants({ variant })\" @select=\"emit('select')\">\n <slot />\n </RekaItem>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuItem as RekaItem } from 'reka-ui'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nconst itemVariants = tv({\n base: 'relative flex w-full cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm outline-none transition-colors focus:bg-surface-muted data-[highlighted]:bg-surface-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n variants: {\n variant: {\n default: 'text-foreground',\n destructive: 'text-error-600',\n },\n },\n defaultVariants: { variant: 'default' },\n})\n\ndefineProps<{ variant?: VariantProps<typeof itemVariants>['variant'] }>()\nconst emit = defineEmits<{ select: [] }>()\n</script>\n\n<template>\n <RekaItem :class=\"itemVariants({ variant })\" @select=\"emit('select')\">\n <slot />\n </RekaItem>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport Checkbox from '../checkbox/Checkbox.vue'\n\nconst props = withDefaults(\n defineProps<{\n options: { value: string; label: string }[]\n modelValue?: string[]\n sourceLabel?: string\n targetLabel?: string\n disabled?: boolean\n }>(),\n { sourceLabel: 'Available', targetLabel: 'Selected', disabled: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst selected = ref(new Set<string>(props.modelValue ?? []))\nconst sourceSel = ref(new Set<string>())\nconst targetSel = ref(new Set<string>())\n\nconst left = computed(() => props.options.filter((o) => !selected.value.has(o.value)))\nconst right = computed(() => props.options.filter((o) => selected.value.has(o.value)))\n\nfunction sync() {\n emit('update:modelValue', right.value.map((o) => o.value))\n}\n\nfunction toggle(set: Set<string>, value: string) {\n const next = new Set(set)\n if (next.has(value)) next.delete(value)\n else next.add(value)\n set.clear()\n for (const v of next) set.add(v)\n}\n\nfunction moveToTarget() {\n for (const v of sourceSel.value) selected.value.add(v)\n sourceSel.value.clear()\n sync()\n}\nfunction moveToSource() {\n for (const v of targetSel.value) selected.value.delete(v)\n targetSel.value.clear()\n sync()\n}\nfunction moveAllTarget() {\n for (const o of props.options) selected.value.add(o.value)\n sourceSel.value.clear()\n sync()\n}\nfunction moveAllSource() {\n selected.value.clear()\n targetSel.value.clear()\n sync()\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2 sm:flex-row sm:items-stretch\">\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"source-header\">{{ sourceLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in left\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(sourceSel, o.value)\"\n >\n <Checkbox :model-value=\"sourceSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(sourceSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"left.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n\n <div class=\"flex flex-row items-center justify-center gap-1 sm:flex-col\">\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || sourceSel.size === 0\" aria-label=\"Move selected to target\" @click=\"moveToTarget\">\n <ChevronRight class=\"size-4\" />\n </Button>\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || targetSel.size === 0\" aria-label=\"Move selected to source\" @click=\"moveToSource\">\n <ChevronLeft class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to target\" @click=\"moveAllTarget\">\n <ChevronsRight class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to source\" @click=\"moveAllSource\">\n <ChevronsLeft class=\"size-4\" />\n </Button>\n </div>\n\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"target-header\">{{ targetLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in right\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(targetSel, o.value)\"\n >\n <Checkbox :model-value=\"targetSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(targetSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"right.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport Checkbox from '../checkbox/Checkbox.vue'\n\nconst props = withDefaults(\n defineProps<{\n options: { value: string; label: string }[]\n modelValue?: string[]\n sourceLabel?: string\n targetLabel?: string\n disabled?: boolean\n }>(),\n { sourceLabel: 'Available', targetLabel: 'Selected', disabled: false },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst selected = ref(new Set<string>(props.modelValue ?? []))\nconst sourceSel = ref(new Set<string>())\nconst targetSel = ref(new Set<string>())\n\nconst left = computed(() => props.options.filter((o) => !selected.value.has(o.value)))\nconst right = computed(() => props.options.filter((o) => selected.value.has(o.value)))\n\nfunction sync() {\n emit('update:modelValue', right.value.map((o) => o.value))\n}\n\nfunction toggle(set: Set<string>, value: string) {\n const next = new Set(set)\n if (next.has(value)) next.delete(value)\n else next.add(value)\n set.clear()\n for (const v of next) set.add(v)\n}\n\nfunction moveToTarget() {\n for (const v of sourceSel.value) selected.value.add(v)\n sourceSel.value.clear()\n sync()\n}\nfunction moveToSource() {\n for (const v of targetSel.value) selected.value.delete(v)\n targetSel.value.clear()\n sync()\n}\nfunction moveAllTarget() {\n for (const o of props.options) selected.value.add(o.value)\n sourceSel.value.clear()\n sync()\n}\nfunction moveAllSource() {\n selected.value.clear()\n targetSel.value.clear()\n sync()\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2 sm:flex-row sm:items-stretch\">\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"source-header\">{{ sourceLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in left\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(sourceSel, o.value)\"\n >\n <Checkbox :model-value=\"sourceSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(sourceSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"left.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n\n <div class=\"flex flex-row items-center justify-center gap-1 sm:flex-col\">\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || sourceSel.size === 0\" aria-label=\"Move selected to target\" @click=\"moveToTarget\">\n <ChevronRight class=\"size-4\" />\n </Button>\n <Button variant=\"outline\" size=\"icon-sm\" :disabled=\"disabled || targetSel.size === 0\" aria-label=\"Move selected to source\" @click=\"moveToSource\">\n <ChevronLeft class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to target\" @click=\"moveAllTarget\">\n <ChevronsRight class=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"disabled\" aria-label=\"Move all to source\" @click=\"moveAllSource\">\n <ChevronsLeft class=\"size-4\" />\n </Button>\n </div>\n\n <div :class=\"['flex min-h-40 flex-1 flex-col rounded-md border border-border bg-surface', disabled && 'opacity-50']\">\n <div class=\"border-b border-border px-3 py-2 text-xs font-medium text-muted\">\n <slot name=\"target-header\">{{ targetLabel }}</slot>\n </div>\n <ul class=\"max-h-64 flex-1 overflow-y-auto p-1\">\n <li v-for=\"o in right\" :key=\"o.value\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n class=\"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed\"\n @click=\"toggle(targetSel, o.value)\"\n >\n <Checkbox :model-value=\"targetSel.has(o.value)\" :disabled=\"disabled\" @click.stop @update:model-value=\"toggle(targetSel, o.value)\" />\n <slot name=\"item\" :option=\"o\">\n <span class=\"truncate\">{{ o.label }}</span>\n </slot>\n </button>\n </li>\n <li v-if=\"right.length === 0\" class=\"px-2 py-1.5 text-sm text-muted\">Empty</li>\n </ul>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ striped?: boolean; size?: 'sm' | 'default'; contained?: boolean }>(),\n { size: 'default', contained: true },\n)\n\nconst classes = computed(() =>\n cn(\n 'w-full border-collapse text-start text-sm text-foreground',\n props.size === 'sm' ? 'text-xs' : 'text-sm',\n props.striped && '[&_tbody>tr:nth-child(even)]:bg-surface-muted/40',\n props.contained && 'overflow-hidden rounded-md border border-border bg-surface',\n ),\n)\n</script>\n\n<template>\n <table :class=\"classes\">\n <slot />\n </table>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ striped?: boolean; size?: 'sm' | 'default'; contained?: boolean }>(),\n { size: 'default', contained: true },\n)\n\nconst classes = computed(() =>\n cn(\n 'w-full border-collapse text-start text-sm text-foreground',\n props.size === 'sm' ? 'text-xs' : 'text-sm',\n props.striped && '[&_tbody>tr:nth-child(even)]:bg-surface-muted/40',\n props.contained && 'overflow-hidden rounded-md border border-border bg-surface',\n ),\n)\n</script>\n\n<template>\n <table :class=\"classes\">\n <slot />\n </table>\n</template>\n","<template>\n <thead class=\"border-b border-border bg-surface-muted/60 text-xs font-medium text-muted\">\n <slot />\n </thead>\n</template>\n","<template>\n <tbody>\n <slot />\n </tbody>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(defineProps<{ clickable?: boolean }>(), { clickable: false })\n</script>\n\n<template>\n <tr\n :class=\"[\n 'border-b border-border/60 last:border-b-0',\n clickable && 'cursor-pointer transition-colors hover:bg-surface-muted/50',\n ]\"\n >\n <slot />\n </tr>\n</template>\n","<script setup lang=\"ts\">\nconst props = withDefaults(defineProps<{ clickable?: boolean }>(), { clickable: false })\n</script>\n\n<template>\n <tr\n :class=\"[\n 'border-b border-border/60 last:border-b-0',\n clickable && 'cursor-pointer transition-colors hover:bg-surface-muted/50',\n ]\"\n >\n <slot />\n </tr>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n sortDirection?: 'ascending' | 'descending' | 'none'\n width?: string\n align?: 'start' | 'center' | 'end'\n }>(),\n { align: 'start' },\n)\n\nconst ariaSort = computed(() =>\n props.sortDirection && props.sortDirection !== 'none' ? props.sortDirection : undefined,\n)\n</script>\n\n<template>\n <th\n scope=\"col\"\n :aria-sort=\"ariaSort\"\n :style=\"width ? { width } : undefined\"\n :class=\"cn(\n 'px-3 py-2 font-medium',\n align === 'center' && 'text-center',\n align === 'end' && 'text-end',\n )\"\n >\n <slot />\n </th>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{\n sortDirection?: 'ascending' | 'descending' | 'none'\n width?: string\n align?: 'start' | 'center' | 'end'\n }>(),\n { align: 'start' },\n)\n\nconst ariaSort = computed(() =>\n props.sortDirection && props.sortDirection !== 'none' ? props.sortDirection : undefined,\n)\n</script>\n\n<template>\n <th\n scope=\"col\"\n :aria-sort=\"ariaSort\"\n :style=\"width ? { width } : undefined\"\n :class=\"cn(\n 'px-3 py-2 font-medium',\n align === 'center' && 'text-center',\n align === 'end' && 'text-end',\n )\"\n >\n <slot />\n </th>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ align?: 'start' | 'center' | 'end'; truncate?: boolean }>(),\n { align: 'start' },\n)\n\nconst classes = computed(() =>\n cn(\n 'px-3 py-2 align-middle',\n props.align === 'center' && 'text-center',\n props.align === 'end' && 'text-end',\n props.truncate && 'max-w-0 truncate',\n ),\n)\n</script>\n\n<template>\n <td :class=\"classes\">\n <slot />\n </td>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '../../lib/cn'\n\nconst props = withDefaults(\n defineProps<{ align?: 'start' | 'center' | 'end'; truncate?: boolean }>(),\n { align: 'start' },\n)\n\nconst classes = computed(() =>\n cn(\n 'px-3 py-2 align-middle',\n props.align === 'center' && 'text-center',\n props.align === 'end' && 'text-end',\n props.truncate && 'max-w-0 truncate',\n ),\n)\n</script>\n\n<template>\n <td :class=\"classes\">\n <slot />\n </td>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{ columns: number; label?: string }>()\n</script>\n\n<template>\n <tr>\n <td :colspan=\"columns\" class=\"px-3 py-8 text-center text-sm text-muted\">\n <slot>{{ label }}</slot>\n </td>\n </tr>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{ columns: number; label?: string }>()\n</script>\n\n<template>\n <tr>\n <td :colspan=\"columns\" class=\"px-3 py-8 text-center text-sm text-muted\">\n <slot>{{ label }}</slot>\n </td>\n </tr>\n</template>\n","export interface PageRange {\n /** 1-based index of the first visible row, 0 when there is no row. */\n from: number\n /** 1-based index of the last visible row, 0 when there is no row. */\n to: number\n total: number\n}\n\nexport function pageRange(pageIndex: number, pageSize: number, total: number): PageRange {\n if (total <= 0 || pageSize <= 0) return { from: 0, to: 0, total: Math.max(0, total) }\n const from = pageIndex * pageSize + 1\n const to = Math.min(total, from + pageSize - 1)\n return from > total ? { from: 0, to: 0, total } : { from, to, total }\n}\n\nexport function totalPages(total: number, pageSize: number): number {\n if (pageSize <= 0) return 1\n return Math.max(1, Math.ceil(total / pageSize))\n}\n\n/** 1-based page numbers, clamped to the window and to the bounds. */\nexport function pageWindow(pageIndex: number, pageCount: number, size = 5): number[] {\n if (pageCount <= 0) return []\n const half = Math.floor(size / 2)\n const start = Math.max(0, Math.min(pageIndex - half, pageCount - size))\n const from = Math.max(0, start)\n return Array.from({ length: Math.min(size, pageCount - from) }, (_, i) => from + i + 1)\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport { pageRange, pageWindow, totalPages } from '../../lib/pagination'\n\nconst props = withDefaults(\n defineProps<{\n pageIndex: number\n pageSize: number\n total: number\n pageSizeOptions?: number[]\n rowsPerPageLabel?: string\n ofLabel?: string\n previousLabel?: string\n nextLabel?: string\n }>(),\n {\n pageSizeOptions: () => [5, 10, 20],\n rowsPerPageLabel: 'Rows per page',\n ofLabel: 'of',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n },\n)\n\nconst emit = defineEmits<{\n 'update:pageIndex': [value: number]\n 'update:pageSize': [value: number]\n}>()\n\nconst pageCount = computed(() => totalPages(props.total, props.pageSize))\nconst range = computed(() => pageRange(props.pageIndex, props.pageSize, props.total))\nconst pages = computed(() => pageWindow(props.pageIndex, pageCount.value))\n\nfunction goTo(index: number) {\n emit('update:pageIndex', Math.max(0, Math.min(index, pageCount.value - 1)))\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap items-center justify-between gap-3 px-3 py-2 text-sm text-muted\">\n <div class=\"flex items-center gap-2\">\n <span>{{ rowsPerPageLabel }}</span>\n <select\n :value=\"pageSize\"\n class=\"rounded-md border border-border bg-surface px-2 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @change=\"emit('update:pageSize', Number(($event.target as HTMLSelectElement).value))\"\n >\n <option v-for=\"option in pageSizeOptions\" :key=\"option\" :value=\"option\">{{ option }}</option>\n </select>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span>{{ range.from }}–{{ range.to }} {{ ofLabel }} {{ range.total }}</span>\n <div class=\"flex items-center gap-1\">\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex <= 0\" :aria-label=\"previousLabel\" @click=\"goTo(pageIndex - 1)\">\n <ChevronLeft class=\"size-4 rtl:rotate-180\" />\n </Button>\n <Button\n v-for=\"page in pages\"\n :key=\"page\"\n :variant=\"page - 1 === pageIndex ? 'default' : 'ghost'\"\n size=\"icon-sm\"\n :aria-current=\"page - 1 === pageIndex ? 'page' : undefined\"\n @click=\"goTo(page - 1)\"\n >\n {{ page }}\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex >= pageCount - 1\" :aria-label=\"nextLabel\" @click=\"goTo(pageIndex + 1)\">\n <ChevronRight class=\"size-4 rtl:rotate-180\" />\n </Button>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport Button from '../button/Button.vue'\nimport { pageRange, pageWindow, totalPages } from '../../lib/pagination'\n\nconst props = withDefaults(\n defineProps<{\n pageIndex: number\n pageSize: number\n total: number\n pageSizeOptions?: number[]\n rowsPerPageLabel?: string\n ofLabel?: string\n previousLabel?: string\n nextLabel?: string\n }>(),\n {\n pageSizeOptions: () => [5, 10, 20],\n rowsPerPageLabel: 'Rows per page',\n ofLabel: 'of',\n previousLabel: 'Previous page',\n nextLabel: 'Next page',\n },\n)\n\nconst emit = defineEmits<{\n 'update:pageIndex': [value: number]\n 'update:pageSize': [value: number]\n}>()\n\nconst pageCount = computed(() => totalPages(props.total, props.pageSize))\nconst range = computed(() => pageRange(props.pageIndex, props.pageSize, props.total))\nconst pages = computed(() => pageWindow(props.pageIndex, pageCount.value))\n\nfunction goTo(index: number) {\n emit('update:pageIndex', Math.max(0, Math.min(index, pageCount.value - 1)))\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap items-center justify-between gap-3 px-3 py-2 text-sm text-muted\">\n <div class=\"flex items-center gap-2\">\n <span>{{ rowsPerPageLabel }}</span>\n <select\n :value=\"pageSize\"\n class=\"rounded-md border border-border bg-surface px-2 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @change=\"emit('update:pageSize', Number(($event.target as HTMLSelectElement).value))\"\n >\n <option v-for=\"option in pageSizeOptions\" :key=\"option\" :value=\"option\">{{ option }}</option>\n </select>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span>{{ range.from }}–{{ range.to }} {{ ofLabel }} {{ range.total }}</span>\n <div class=\"flex items-center gap-1\">\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex <= 0\" :aria-label=\"previousLabel\" @click=\"goTo(pageIndex - 1)\">\n <ChevronLeft class=\"size-4 rtl:rotate-180\" />\n </Button>\n <Button\n v-for=\"page in pages\"\n :key=\"page\"\n :variant=\"page - 1 === pageIndex ? 'default' : 'ghost'\"\n size=\"icon-sm\"\n :aria-current=\"page - 1 === pageIndex ? 'page' : undefined\"\n @click=\"goTo(page - 1)\"\n >\n {{ page }}\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" :disabled=\"pageIndex >= pageCount - 1\" :aria-label=\"nextLabel\" @click=\"goTo(pageIndex + 1)\">\n <ChevronRight class=\"size-4 rtl:rotate-180\" />\n </Button>\n </div>\n </div>\n </div>\n</template>\n","import {\n createExpandedRowModel,\n createPaginatedRowModel,\n createSortedRowModel,\n rowExpandingFeature,\n rowPaginationFeature,\n rowSortingFeature,\n sortFns,\n tableFeatures,\n} from '@tanstack/vue-table'\n\n/**\n * Single registration point for the suite's engine.\n * Add a feature here only when a DataTable consumer needs it — v9 tree-shakes\n * whatever is not registered.\n */\nexport const dataTableFeatures = tableFeatures({\n rowSortingFeature,\n rowPaginationFeature,\n rowExpandingFeature,\n sortedRowModel: createSortedRowModel(),\n paginatedRowModel: createPaginatedRowModel(),\n expandedRowModel: createExpandedRowModel(),\n sortFns,\n})\n\nexport type DataTableFeatures = typeof dataTableFeatures\n","/** Structural type so the guard is unit-testable in node env (no DOM). */\nexport interface ClosestHost {\n closest: (selector: string) => unknown\n}\n\nconst INTERACTIVE_SELECTOR = [\n 'a[href]',\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'label',\n '[role=\"checkbox\"]',\n '[role=\"switch\"]',\n '[role=\"combobox\"]',\n '[role=\"menu\"]',\n '[data-row-toggle-ignore]',\n].join(',')\n\n/**\n * Replaces the app's `closest('.p-select, .p-button, ...')` guard: any click\n * landing inside a real interactive element (or an element opted out with\n * `data-row-toggle-ignore`) never toggles the row.\n *\n * The parameter is `unknown` on purpose — DOM `EventTarget` has no `closest`,\n * and callers pass `event.target` straight through.\n */\nexport function shouldIgnoreRowToggle(target: unknown): boolean {\n const host = target as ClosestHost | null | undefined\n if (!host || typeof host.closest !== 'function') return false\n return host.closest(INTERACTIVE_SELECTOR) !== null\n}\n\n/** Single-row expansion map, keyed by row id, as used by `v-model:expanded`. */\nexport function toggleExpandedRow(\n expanded: Record<string, boolean>,\n rowId: string,\n): Record<string, boolean> {\n return expanded[rowId] ? {} : { [rowId]: true }\n}\n","<script setup lang=\"ts\" generic=\"T extends RowData\">\nimport { computed, ref, useSlots } from 'vue'\nimport { FlexRender, useTable, type ColumnDef, type RowData, type SortingState } from '@tanstack/vue-table'\nimport { ChevronDown, ChevronUp, ChevronsUpDown } from 'lucide-vue-next'\nimport { dataTableFeatures } from '../../lib/table'\nimport { shouldIgnoreRowToggle, toggleExpandedRow } from '../../lib/tableInteractions'\nimport Table from '../table/Table.vue'\nimport TableBody from '../table/TableBody.vue'\nimport TableCell from '../table/TableCell.vue'\nimport TableEmpty from '../table/TableEmpty.vue'\nimport TableHead from '../table/TableHead.vue'\nimport TableHeader from '../table/TableHeader.vue'\nimport TableRow from '../table/TableRow.vue'\n\nconst props = withDefaults(\n defineProps<{\n data: T[]\n columns: ColumnDef<typeof dataTableFeatures, T>[]\n getRowId?: (row: T) => string\n striped?: boolean\n size?: 'sm' | 'default'\n emptyLabel?: string\n sortable?: boolean\n expandable?: boolean\n expanded?: Record<string, boolean>\n stopRowToggleOnInteractiveCells?: boolean\n maxHeight?: string\n }>(),\n {\n size: 'default',\n striped: false,\n sortable: true,\n emptyLabel: 'No results',\n expandable: false,\n expanded: () => ({}),\n stopRowToggleOnInteractiveCells: true,\n },\n)\n\nconst emit = defineEmits<{\n 'update:sorting': [value: { id: string; desc: boolean }[]]\n 'update:expanded': [value: Record<string, boolean>]\n 'row-click': [row: unknown]\n}>()\nconst slots = useSlots()\n\nconst sorting = ref<SortingState>([])\nconst getRowId = props.getRowId ? (row: T) => props.getRowId!(row) : undefined\n\nconst table = useTable({\n features: dataTableFeatures,\n get columns() {\n return props.columns\n },\n get data() {\n return props.data\n },\n getRowId,\n getRowCanExpand: () => props.expandable,\n state: {\n get sorting() {\n return sorting.value\n },\n get expanded() {\n return props.expanded\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n emit(\n 'update:sorting',\n sorting.value.map((s) => ({ id: s.id, desc: s.desc })),\n )\n },\n onExpandedChange: (updater) => {\n const next = typeof updater === 'function' ? updater(props.expanded) : updater\n // ExpandedState may be `true` (expand all); the suite only models per-row ids.\n emit('update:expanded', next === true ? {} : next)\n },\n})\n\nconst rows = computed(() => table.getRowModel().rows)\nconst columnCount = computed(() => table.getAllLeafColumns().length)\n\nfunction sortDirection(columnId: string): 'ascending' | 'descending' | 'none' {\n const column = table.getColumn(columnId)\n if (!column?.getIsSorted()) return 'none'\n return column.getIsSorted() === 'desc' ? 'descending' : 'ascending'\n}\n\nconst hasCellSlot = (columnId: string) => Boolean(slots[`cell-${columnId}`])\n\n/** `size` only exists on ColumnDef when columnSizingFeature is registered, so read it structurally. */\nconst widthOf = (columnDef: unknown) => {\n const size = (columnDef as { size?: number }).size\n return size ? `${size}px` : undefined\n}\n\nfunction onRowClick(event: MouseEvent, rowId: string) {\n emit('row-click', rows.value.find((row) => row.id === rowId)?.original)\n if (!props.expandable) return\n if (props.stopRowToggleOnInteractiveCells && shouldIgnoreRowToggle(event.target)) return\n emit('update:expanded', toggleExpandedRow(props.expanded, rowId))\n}\n</script>\n\n<template>\n <div :class=\"maxHeight ? 'overflow-auto' : undefined\" :style=\"maxHeight ? { maxHeight } : undefined\">\n <Table :striped=\"striped\" :size=\"size\">\n <TableHeader>\n <TableRow>\n <TableHead\n v-for=\"header in table.getHeaderGroups()[0]?.headers ?? []\"\n :key=\"header.id\"\n :width=\"widthOf(header.column.columnDef)\"\n :sort-direction=\"header.column.getCanSort() ? sortDirection(header.column.id) : undefined\"\n >\n <button\n v-if=\"sortable && header.column.getCanSort()\"\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"header.column.toggleSorting()\"\n >\n <FlexRender :header=\"header\" />\n <ChevronDown v-if=\"sortDirection(header.column.id) === 'descending'\" class=\"size-3.5\" />\n <ChevronUp v-else-if=\"sortDirection(header.column.id) === 'ascending'\" class=\"size-3.5\" />\n <ChevronsUpDown v-else class=\"size-3.5 opacity-40\" />\n </button>\n <FlexRender v-else :header=\"header\" />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <TableEmpty v-if=\"rows.length === 0\" :columns=\"columnCount\">\n <slot name=\"empty\">{{ emptyLabel }}</slot>\n </TableEmpty>\n <template v-for=\"row in rows\" :key=\"row.id\">\n <TableRow\n :clickable=\"expandable\"\n :data-row-id=\"row.id\"\n :data-state=\"row.getIsExpanded() ? 'expanded' : undefined\"\n @click=\"onRowClick($event, row.id)\"\n >\n <TableCell v-for=\"cell in row.getAllCells()\" :key=\"cell.id\">\n <slot\n v-if=\"hasCellSlot(cell.column.id)\"\n :name=\"`cell-${cell.column.id}`\"\n :row=\"row\"\n :cell=\"cell\"\n :value=\"cell.getValue()\"\n />\n <FlexRender v-else :cell=\"cell\" />\n </TableCell>\n </TableRow>\n <TableRow v-if=\"row.getIsExpanded()\" class=\"bg-surface-muted/30\">\n <TableCell :colspan=\"columnCount\">\n <slot name=\"expansion\" :row=\"row\" />\n </TableCell>\n </TableRow>\n </template>\n </TableBody>\n </Table>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T extends RowData\">\nimport { computed, ref, useSlots } from 'vue'\nimport { FlexRender, useTable, type ColumnDef, type RowData, type SortingState } from '@tanstack/vue-table'\nimport { ChevronDown, ChevronUp, ChevronsUpDown } from 'lucide-vue-next'\nimport { dataTableFeatures } from '../../lib/table'\nimport { shouldIgnoreRowToggle, toggleExpandedRow } from '../../lib/tableInteractions'\nimport Table from '../table/Table.vue'\nimport TableBody from '../table/TableBody.vue'\nimport TableCell from '../table/TableCell.vue'\nimport TableEmpty from '../table/TableEmpty.vue'\nimport TableHead from '../table/TableHead.vue'\nimport TableHeader from '../table/TableHeader.vue'\nimport TableRow from '../table/TableRow.vue'\n\nconst props = withDefaults(\n defineProps<{\n data: T[]\n columns: ColumnDef<typeof dataTableFeatures, T>[]\n getRowId?: (row: T) => string\n striped?: boolean\n size?: 'sm' | 'default'\n emptyLabel?: string\n sortable?: boolean\n expandable?: boolean\n expanded?: Record<string, boolean>\n stopRowToggleOnInteractiveCells?: boolean\n maxHeight?: string\n }>(),\n {\n size: 'default',\n striped: false,\n sortable: true,\n emptyLabel: 'No results',\n expandable: false,\n expanded: () => ({}),\n stopRowToggleOnInteractiveCells: true,\n },\n)\n\nconst emit = defineEmits<{\n 'update:sorting': [value: { id: string; desc: boolean }[]]\n 'update:expanded': [value: Record<string, boolean>]\n 'row-click': [row: unknown]\n}>()\nconst slots = useSlots()\n\nconst sorting = ref<SortingState>([])\nconst getRowId = props.getRowId ? (row: T) => props.getRowId!(row) : undefined\n\nconst table = useTable({\n features: dataTableFeatures,\n get columns() {\n return props.columns\n },\n get data() {\n return props.data\n },\n getRowId,\n getRowCanExpand: () => props.expandable,\n state: {\n get sorting() {\n return sorting.value\n },\n get expanded() {\n return props.expanded\n },\n },\n onSortingChange: (updater) => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n emit(\n 'update:sorting',\n sorting.value.map((s) => ({ id: s.id, desc: s.desc })),\n )\n },\n onExpandedChange: (updater) => {\n const next = typeof updater === 'function' ? updater(props.expanded) : updater\n // ExpandedState may be `true` (expand all); the suite only models per-row ids.\n emit('update:expanded', next === true ? {} : next)\n },\n})\n\nconst rows = computed(() => table.getRowModel().rows)\nconst columnCount = computed(() => table.getAllLeafColumns().length)\n\nfunction sortDirection(columnId: string): 'ascending' | 'descending' | 'none' {\n const column = table.getColumn(columnId)\n if (!column?.getIsSorted()) return 'none'\n return column.getIsSorted() === 'desc' ? 'descending' : 'ascending'\n}\n\nconst hasCellSlot = (columnId: string) => Boolean(slots[`cell-${columnId}`])\n\n/** `size` only exists on ColumnDef when columnSizingFeature is registered, so read it structurally. */\nconst widthOf = (columnDef: unknown) => {\n const size = (columnDef as { size?: number }).size\n return size ? `${size}px` : undefined\n}\n\nfunction onRowClick(event: MouseEvent, rowId: string) {\n emit('row-click', rows.value.find((row) => row.id === rowId)?.original)\n if (!props.expandable) return\n if (props.stopRowToggleOnInteractiveCells && shouldIgnoreRowToggle(event.target)) return\n emit('update:expanded', toggleExpandedRow(props.expanded, rowId))\n}\n</script>\n\n<template>\n <div :class=\"maxHeight ? 'overflow-auto' : undefined\" :style=\"maxHeight ? { maxHeight } : undefined\">\n <Table :striped=\"striped\" :size=\"size\">\n <TableHeader>\n <TableRow>\n <TableHead\n v-for=\"header in table.getHeaderGroups()[0]?.headers ?? []\"\n :key=\"header.id\"\n :width=\"widthOf(header.column.columnDef)\"\n :sort-direction=\"header.column.getCanSort() ? sortDirection(header.column.id) : undefined\"\n >\n <button\n v-if=\"sortable && header.column.getCanSort()\"\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"header.column.toggleSorting()\"\n >\n <FlexRender :header=\"header\" />\n <ChevronDown v-if=\"sortDirection(header.column.id) === 'descending'\" class=\"size-3.5\" />\n <ChevronUp v-else-if=\"sortDirection(header.column.id) === 'ascending'\" class=\"size-3.5\" />\n <ChevronsUpDown v-else class=\"size-3.5 opacity-40\" />\n </button>\n <FlexRender v-else :header=\"header\" />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <TableEmpty v-if=\"rows.length === 0\" :columns=\"columnCount\">\n <slot name=\"empty\">{{ emptyLabel }}</slot>\n </TableEmpty>\n <template v-for=\"row in rows\" :key=\"row.id\">\n <TableRow\n :clickable=\"expandable\"\n :data-row-id=\"row.id\"\n :data-state=\"row.getIsExpanded() ? 'expanded' : undefined\"\n @click=\"onRowClick($event, row.id)\"\n >\n <TableCell v-for=\"cell in row.getAllCells()\" :key=\"cell.id\">\n <slot\n v-if=\"hasCellSlot(cell.column.id)\"\n :name=\"`cell-${cell.column.id}`\"\n :row=\"row\"\n :cell=\"cell\"\n :value=\"cell.getValue()\"\n />\n <FlexRender v-else :cell=\"cell\" />\n </TableCell>\n </TableRow>\n <TableRow v-if=\"row.getIsExpanded()\" class=\"bg-surface-muted/30\">\n <TableCell :colspan=\"columnCount\">\n <slot name=\"expansion\" :row=\"row\" />\n </TableCell>\n </TableRow>\n </template>\n </TableBody>\n </Table>\n </div>\n</template>\n","export interface TreeNode<T = unknown> {\n /** Stable key; also the value emitted by TreeSelect and TreeTable. */\n value: string\n label?: string\n disabled?: boolean\n children?: TreeNode<T>[]\n data?: T\n}\n\nexport interface FlatTreeRow<T = unknown> {\n node: TreeNode<T>\n key: string\n level: number\n parentKey: string | null\n hasChildren: boolean\n}\n\nexport function flattenVisible<T>(\n nodes: TreeNode<T>[],\n expanded: string[],\n level = 1,\n parentKey: string | null = null,\n): FlatTreeRow<T>[] {\n return nodes.flatMap((node) => {\n const row: FlatTreeRow<T> = {\n node,\n key: node.value,\n level,\n parentKey,\n hasChildren: Boolean(node.children?.length),\n }\n if (!row.hasChildren || !expanded.includes(node.value)) return [row]\n return [row, ...flattenVisible(node.children!, expanded, level + 1, node.value)]\n })\n}\n\nexport function findNode<T>(nodes: TreeNode<T>[], key: string): TreeNode<T> | undefined {\n for (const node of nodes) {\n if (node.value === key) return node\n const hit = node.children ? findNode(node.children, key) : undefined\n if (hit) return hit\n }\n return undefined\n}\n\nexport function leafKeys<T>(nodes: TreeNode<T>[]): string[] {\n return nodes.flatMap((node) =>\n node.children?.length ? leafKeys(node.children) : [node.value],\n )\n}\n\nexport type CheckedState = 'checked' | 'indeterminate' | 'unchecked'\n\n/**\n * Replaces the app's `Record<key, { checked, partialChecked }>` store shape:\n * the package contract is the flat list of selected leaf keys, and this derives\n * per-node state from it.\n */\nexport function checkedStateOf<T>(node: TreeNode<T>, selectedLeafKeys: string[]): CheckedState {\n const leaves = node.children?.length ? leafKeys([node]) : [node.value]\n const selected = leaves.filter((key) => selectedLeafKeys.includes(key)).length\n if (selected === 0) return 'unchecked'\n return selected === leaves.length ? 'checked' : 'indeterminate'\n}\n\n/** Keeps a node when it matches or any descendant does; drops empty branches. */\nexport function filterTree<T>(\n nodes: TreeNode<T>[],\n query: string,\n labelOf: (node: TreeNode<T>) => string = (node) => node.label ?? '',\n): TreeNode<T>[] {\n const needle = query.trim().toLowerCase()\n if (!needle) return nodes\n return nodes.reduce<TreeNode<T>[]>((acc, node) => {\n const children = node.children ? filterTree(node.children, query, labelOf) : undefined\n const matches = labelOf(node).toLowerCase().includes(needle)\n if (!matches && (!children || children.length === 0)) return acc\n acc.push({ ...node, children })\n return acc\n }, [])\n}\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed } from 'vue'\nimport { TreeItem, TreeRoot } from 'reka-ui'\nimport { ChevronRight } from 'lucide-vue-next'\nimport { flattenVisible, type TreeNode } from '../../lib/tree'\n\nexport interface TreeTableColumn {\n key: string\n header: string\n width?: string\n align?: 'start' | 'center' | 'end'\n}\n\nconst props = withDefaults(\n defineProps<{\n nodes: TreeNode<T>[]\n columns: TreeTableColumn[]\n expanded?: string[]\n rowLabel?: (node: TreeNode<T>) => string\n rowColumnHeader?: string\n }>(),\n {\n expanded: () => [],\n rowLabel: (node: TreeNode<T>) => node.label ?? node.value,\n rowColumnHeader: 'Name',\n },\n)\n\nconst emit = defineEmits<{ 'update:expanded': [value: string[]] }>()\n\nconst gridTemplate = computed(\n () => `minmax(12rem, 1fr) ${props.columns.map((column) => column.width ?? 'minmax(6rem, 1fr)').join(' ')}`,\n)\nconst flat = computed(() => flattenVisible(props.nodes, props.expanded))\n</script>\n\n<template>\n <div class=\"overflow-hidden rounded-md border border-border bg-surface\">\n <div\n class=\"grid border-b border-border bg-surface-muted/60 text-xs font-medium text-muted\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"px-3 py-2\">\n <slot name=\"header\">{{ rowColumnHeader }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n {{ column.header }}\n </div>\n </div>\n\n <TreeRoot\n :items=\"nodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n :expanded=\"expanded\"\n @update:expanded=\"emit('update:expanded', $event as string[])\"\n >\n <TreeItem\n v-for=\"row in flat\"\n :key=\"row.key\"\n v-slot=\"{ isExpanded, handleToggle }\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"grid items-center border-b border-border/60 text-sm last:border-b-0 data-[selected]:bg-surface-muted/30\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"flex items-center gap-1 px-3 py-2\" :style=\"{ paddingInlineStart: `calc(0.75rem + ${(row.level - 1) * 1.25}rem)` }\">\n <button\n v-if=\"row.hasChildren\"\n type=\"button\"\n :aria-label=\"rowLabel(row.node)\"\n class=\"rounded p-0.5 text-muted transition-transform hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n :class=\"isExpanded && 'rotate-90'\"\n @click.stop=\"handleToggle\"\n >\n <ChevronRight class=\"size-3.5 rtl:rotate-180\" />\n </button>\n <span v-else class=\"inline-block size-4\" />\n <slot name=\"row-label\" :node=\"row.node\" :level=\"row.level\">{{ rowLabel(row.node) }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :node=\"row.node\"\n :row=\"row\"\n :is-expanded=\"isExpanded\"\n :has-children=\"row.hasChildren\"\n :handle-toggle=\"handleToggle\"\n />\n </div>\n </TreeItem>\n </TreeRoot>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed } from 'vue'\nimport { TreeItem, TreeRoot } from 'reka-ui'\nimport { ChevronRight } from 'lucide-vue-next'\nimport { flattenVisible, type TreeNode } from '../../lib/tree'\n\nexport interface TreeTableColumn {\n key: string\n header: string\n width?: string\n align?: 'start' | 'center' | 'end'\n}\n\nconst props = withDefaults(\n defineProps<{\n nodes: TreeNode<T>[]\n columns: TreeTableColumn[]\n expanded?: string[]\n rowLabel?: (node: TreeNode<T>) => string\n rowColumnHeader?: string\n }>(),\n {\n expanded: () => [],\n rowLabel: (node: TreeNode<T>) => node.label ?? node.value,\n rowColumnHeader: 'Name',\n },\n)\n\nconst emit = defineEmits<{ 'update:expanded': [value: string[]] }>()\n\nconst gridTemplate = computed(\n () => `minmax(12rem, 1fr) ${props.columns.map((column) => column.width ?? 'minmax(6rem, 1fr)').join(' ')}`,\n)\nconst flat = computed(() => flattenVisible(props.nodes, props.expanded))\n</script>\n\n<template>\n <div class=\"overflow-hidden rounded-md border border-border bg-surface\">\n <div\n class=\"grid border-b border-border bg-surface-muted/60 text-xs font-medium text-muted\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"px-3 py-2\">\n <slot name=\"header\">{{ rowColumnHeader }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n {{ column.header }}\n </div>\n </div>\n\n <TreeRoot\n :items=\"nodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n :expanded=\"expanded\"\n @update:expanded=\"emit('update:expanded', $event as string[])\"\n >\n <TreeItem\n v-for=\"row in flat\"\n :key=\"row.key\"\n v-slot=\"{ isExpanded, handleToggle }\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"grid items-center border-b border-border/60 text-sm last:border-b-0 data-[selected]:bg-surface-muted/30\"\n :style=\"{ gridTemplateColumns: gridTemplate }\"\n >\n <div class=\"flex items-center gap-1 px-3 py-2\" :style=\"{ paddingInlineStart: `calc(0.75rem + ${(row.level - 1) * 1.25}rem)` }\">\n <button\n v-if=\"row.hasChildren\"\n type=\"button\"\n :aria-label=\"rowLabel(row.node)\"\n class=\"rounded p-0.5 text-muted transition-transform hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n :class=\"isExpanded && 'rotate-90'\"\n @click.stop=\"handleToggle\"\n >\n <ChevronRight class=\"size-3.5 rtl:rotate-180\" />\n </button>\n <span v-else class=\"inline-block size-4\" />\n <slot name=\"row-label\" :node=\"row.node\" :level=\"row.level\">{{ rowLabel(row.node) }}</slot>\n </div>\n <div\n v-for=\"column in columns\"\n :key=\"column.key\"\n class=\"px-3 py-2\"\n :class=\"[column.align === 'center' && 'text-center', column.align === 'end' && 'text-end']\"\n >\n <slot\n :name=\"`cell-${column.key}`\"\n :node=\"row.node\"\n :row=\"row\"\n :is-expanded=\"isExpanded\"\n :has-children=\"row.hasChildren\"\n :handle-toggle=\"handleToggle\"\n />\n </div>\n </TreeItem>\n </TreeRoot>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed, ref } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger, TreeItem, TreeRoot } from 'reka-ui'\nimport { Check, ChevronDown, Search, X } from 'lucide-vue-next'\nimport Tag from '../tag/Tag.vue'\nimport {\n checkedStateOf,\n filterTree,\n findNode,\n flattenVisible,\n leafKeys,\n type TreeNode,\n} from '../../lib/tree'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[]\n nodes: TreeNode<T>[]\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n disabled?: boolean\n /** Only leaf nodes are selectable (the classification case: parents are groups). */\n leafOnly?: boolean\n size?: 'sm' | 'default'\n }>(),\n {\n modelValue: () => [],\n placeholder: 'Select',\n filterable: true,\n filterPlaceholder: 'Search',\n leafOnly: true,\n size: 'default',\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst open = ref(false)\nconst query = ref('')\nconst expanded = ref<string[]>([])\n\nconst visibleNodes = computed(() => filterTree(props.nodes, query.value))\nconst rows = computed(() => flattenVisible(visibleNodes.value, expanded.value))\nconst leaves = computed(() => leafKeys(props.nodes))\nconst selectedItems = computed(() =>\n props.modelValue\n .map((key) => findNode(props.nodes, key))\n .filter((node): node is TreeNode<T> => Boolean(node)),\n)\n\n/** Derived from the selected leaf keys, so partially selected parents read correctly. */\nfunction stateOf(node: TreeNode<T>) {\n return checkedStateOf(node, props.modelValue)\n}\n\nfunction onUpdateItems(value: unknown) {\n const items = Array.isArray(value) ? (value as TreeNode<T>[]) : []\n const keys = items.map((item) => item.value)\n emit('update:modelValue', props.leafOnly ? keys.filter((key) => leaves.value.includes(key)) : keys)\n}\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child :disabled=\"disabled\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-start text-sm text-foreground shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'min-h-8 py-1 text-xs' : 'min-h-9 py-1.5',\n ]\"\n >\n <span v-if=\"selectedItems.length === 0\" class=\"truncate text-muted\">{{ placeholder }}</span>\n <span v-else class=\"flex flex-wrap items-center gap-1\">\n <Tag v-for=\"node in selectedItems\" :key=\"node.value\" tone=\"secondary\">{{ node.label ?? node.value }}</Tag>\n </span>\n <ChevronDown class=\"size-4 shrink-0 opacity-50\" />\n </button>\n </PopoverTrigger>\n\n <PopoverContent :side-offset=\"4\" class=\"z-50 w-72 rounded-md border border-border bg-surface p-2 shadow-popover\">\n <div v-if=\"filterable\" class=\"relative mb-2\">\n <Search class=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-muted\" />\n <input\n v-model=\"query\"\n :placeholder=\"filterPlaceholder\"\n class=\"w-full rounded-md border border-border bg-surface py-1.5 pe-2 ps-7 text-sm placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n />\n </div>\n\n <TreeRoot\n :model-value=\"selectedItems\"\n :items=\"visibleNodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n v-model:expanded=\"expanded\"\n multiple\n bubble-select\n @update:model-value=\"onUpdateItems\"\n >\n <TreeItem\n v-for=\"row in rows\"\n :key=\"row.key\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"flex items-center gap-2 rounded py-1.5 text-sm text-foreground data-[selected]:bg-surface-muted/50\"\n :style=\"{ paddingInlineStart: `calc(0.5rem + ${(row.level - 1) * 1}rem)` }\"\n >\n <span\n class=\"flex size-4 shrink-0 items-center justify-center rounded border border-border\"\n :class=\"stateOf(row.node) !== 'unchecked' && 'border-primary-500 bg-primary-500 text-white'\"\n aria-hidden=\"true\"\n >\n <Check v-if=\"stateOf(row.node) === 'checked'\" class=\"size-3\" />\n <span v-else-if=\"stateOf(row.node) === 'indeterminate'\" class=\"block h-0.5 w-2 rounded bg-white\" />\n </span>\n <span class=\"truncate\">{{ row.node.label ?? row.node.value }}</span>\n </TreeItem>\n </TreeRoot>\n\n <div v-if=\"modelValue.length\" class=\"mt-2 flex justify-end border-t border-border pt-2\">\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded px-2 py-1 text-xs text-muted hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"emit('update:modelValue', [])\"\n >\n <X class=\"size-3\" />Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\" generic=\"T = unknown\">\nimport { computed, ref } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger, TreeItem, TreeRoot } from 'reka-ui'\nimport { Check, ChevronDown, Search, X } from 'lucide-vue-next'\nimport Tag from '../tag/Tag.vue'\nimport {\n checkedStateOf,\n filterTree,\n findNode,\n flattenVisible,\n leafKeys,\n type TreeNode,\n} from '../../lib/tree'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string[]\n nodes: TreeNode<T>[]\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n disabled?: boolean\n /** Only leaf nodes are selectable (the classification case: parents are groups). */\n leafOnly?: boolean\n size?: 'sm' | 'default'\n }>(),\n {\n modelValue: () => [],\n placeholder: 'Select',\n filterable: true,\n filterPlaceholder: 'Search',\n leafOnly: true,\n size: 'default',\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()\n\nconst open = ref(false)\nconst query = ref('')\nconst expanded = ref<string[]>([])\n\nconst visibleNodes = computed(() => filterTree(props.nodes, query.value))\nconst rows = computed(() => flattenVisible(visibleNodes.value, expanded.value))\nconst leaves = computed(() => leafKeys(props.nodes))\nconst selectedItems = computed(() =>\n props.modelValue\n .map((key) => findNode(props.nodes, key))\n .filter((node): node is TreeNode<T> => Boolean(node)),\n)\n\n/** Derived from the selected leaf keys, so partially selected parents read correctly. */\nfunction stateOf(node: TreeNode<T>) {\n return checkedStateOf(node, props.modelValue)\n}\n\nfunction onUpdateItems(value: unknown) {\n const items = Array.isArray(value) ? (value as TreeNode<T>[]) : []\n const keys = items.map((item) => item.value)\n emit('update:modelValue', props.leafOnly ? keys.filter((key) => leaves.value.includes(key)) : keys)\n}\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverTrigger as-child :disabled=\"disabled\">\n <button\n type=\"button\"\n :disabled=\"disabled\"\n :class=\"[\n 'flex w-full items-center justify-between gap-2 rounded-md border border-border bg-surface px-3 text-start text-sm text-foreground shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50',\n size === 'sm' ? 'min-h-8 py-1 text-xs' : 'min-h-9 py-1.5',\n ]\"\n >\n <span v-if=\"selectedItems.length === 0\" class=\"truncate text-muted\">{{ placeholder }}</span>\n <span v-else class=\"flex flex-wrap items-center gap-1\">\n <Tag v-for=\"node in selectedItems\" :key=\"node.value\" tone=\"secondary\">{{ node.label ?? node.value }}</Tag>\n </span>\n <ChevronDown class=\"size-4 shrink-0 opacity-50\" />\n </button>\n </PopoverTrigger>\n\n <PopoverContent :side-offset=\"4\" class=\"z-50 w-72 rounded-md border border-border bg-surface p-2 shadow-popover\">\n <div v-if=\"filterable\" class=\"relative mb-2\">\n <Search class=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-muted\" />\n <input\n v-model=\"query\"\n :placeholder=\"filterPlaceholder\"\n class=\"w-full rounded-md border border-border bg-surface py-1.5 pe-2 ps-7 text-sm placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n />\n </div>\n\n <TreeRoot\n :model-value=\"selectedItems\"\n :items=\"visibleNodes\"\n :get-key=\"(node: TreeNode<T>) => node.value\"\n :get-children=\"(node: TreeNode<T>) => node.children\"\n v-model:expanded=\"expanded\"\n multiple\n bubble-select\n @update:model-value=\"onUpdateItems\"\n >\n <TreeItem\n v-for=\"row in rows\"\n :key=\"row.key\"\n :value=\"row.node\"\n :level=\"row.level\"\n as=\"div\"\n class=\"flex items-center gap-2 rounded py-1.5 text-sm text-foreground data-[selected]:bg-surface-muted/50\"\n :style=\"{ paddingInlineStart: `calc(0.5rem + ${(row.level - 1) * 1}rem)` }\"\n >\n <span\n class=\"flex size-4 shrink-0 items-center justify-center rounded border border-border\"\n :class=\"stateOf(row.node) !== 'unchecked' && 'border-primary-500 bg-primary-500 text-white'\"\n aria-hidden=\"true\"\n >\n <Check v-if=\"stateOf(row.node) === 'checked'\" class=\"size-3\" />\n <span v-else-if=\"stateOf(row.node) === 'indeterminate'\" class=\"block h-0.5 w-2 rounded bg-white\" />\n </span>\n <span class=\"truncate\">{{ row.node.label ?? row.node.value }}</span>\n </TreeItem>\n </TreeRoot>\n\n <div v-if=\"modelValue.length\" class=\"mt-2 flex justify-end border-t border-border pt-2\">\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-1 rounded px-2 py-1 text-xs text-muted hover:bg-surface-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"emit('update:modelValue', [])\"\n >\n <X class=\"size-3\" />Clear\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}