@myghf/ui 0.4.0 → 0.5.1
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/README.md +32 -0
- package/dist/components/data-table/DataTable.vue.d.ts +3 -0
- package/dist/components/data-table/DataTable.vue.d.ts.map +1 -1
- package/dist/components/date-picker/DatePicker.vue.d.ts.map +1 -1
- package/dist/components/select/Select.vue.d.ts.map +1 -1
- package/dist/index.js +583 -556
- package/dist/index.js.map +1 -1
- package/dist/nuxt.d.ts +49 -2
- package/dist/nuxt.d.ts.map +1 -1
- package/dist/nuxt.js +82 -16
- package/dist/nuxt.js.map +1 -1
- package/package.json +5 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["$slots","$slots","$slots","$slots","$attrs","$attrs","$attrs","$slots","$slots","$attrs"],"sources":["../src/lib/cn.ts","../src/lib/date.ts","../src/lib/locale.ts","../src/lib/number.ts","../src/lib/icons.ts","../src/lib/tones.ts","../src/lib/theme.ts","../src/components/theme-toggle/ThemeToggle.vue","../src/components/theme-toggle/ThemeToggle.vue","../src/components/icon/Icon.vue","../src/components/icon/Icon.vue","../src/components/button/Button.vue","../src/components/button/Button.vue","../src/lib/formField.ts","../src/components/input/Input.vue","../src/components/input/Input.vue","../src/components/input-number/InputNumber.vue","../src/components/input-number/InputNumber.vue","../src/components/textarea/Textarea.vue","../src/components/textarea/Textarea.vue","../src/components/password/Password.vue","../src/components/password/Password.vue","../src/components/label/Label.vue","../src/components/label/Label.vue","../src/components/form-field/FormDescription.vue","../src/components/form-field/FormDescription.vue","../src/components/form-field/FormMessage.vue","../src/components/form-field/FormMessage.vue","../src/components/form-field/FormField.vue","../src/components/form-field/FormField.vue","../src/components/checkbox/Checkbox.vue","../src/components/checkbox/Checkbox.vue","../src/components/tag/Tag.vue","../src/components/tag/Tag.vue","../src/components/alert/Alert.vue","../src/components/alert/Alert.vue","../src/components/spinner/Spinner.vue","../src/components/spinner/Spinner.vue","../src/components/skeleton/Skeleton.vue","../src/components/skeleton/Skeleton.vue","../src/components/avatar/Avatar.vue","../src/components/avatar/Avatar.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/drawer/Drawer.vue","../src/components/drawer/Drawer.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/dropdown-menu/DropdownMenuSeparator.vue","../src/components/dropdown-menu/DropdownMenuSeparator.vue","../src/components/dropdown-menu/DropdownMenuLabel.vue","../src/components/dropdown-menu/DropdownMenuLabel.vue","../src/components/dropdown-menu/DropdownMenuGroup.vue","../src/components/dropdown-menu/DropdownMenuGroup.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","../src/components/toast/useToast.ts","../src/components/toast/Toast.vue","../src/components/toast/Toast.vue","../src/components/toast/Toaster.vue","../src/components/toast/Toaster.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\nexport function buildHourOptions(hourFormat: '12' | '24'): number[] {\n if (hourFormat === '12') return Array.from({ length: 12 }, (_, i) => i + 1)\n return Array.from({ length: 24 }, (_, i) => i)\n}\n\nexport function buildMinuteOptions(minuteStep: number): number[] {\n const step = Number.isFinite(minuteStep) && minuteStep > 0 ? minuteStep : 1\n const out: number[] = []\n for (let m = 0; m < 60; m += step) out.push(m)\n return out\n}\n\nexport function to12Hour(hour24: number): { hour: number; meridiem: 'am' | 'pm' } {\n const normalized = ((Math.trunc(hour24) % 24) + 24) % 24\n const meridiem: 'am' | 'pm' = normalized < 12 ? 'am' : 'pm'\n const hour = normalized % 12 === 0 ? 12 : normalized % 12\n return { hour, meridiem }\n}\n\nexport function from12Hour(hour: number, meridiem: 'am' | 'pm'): number {\n const base = Math.trunc(hour) % 12\n return meridiem === 'pm' ? base + 12 : base\n}\n","export function getFirstDayOfWeek(locale: string): number {\n try {\n const loc = new Intl.Locale(locale) as Intl.Locale & {\n weekInfo?: { firstDay: number }\n getWeekInfo?: () => { firstDay: number }\n }\n const weekInfo = loc.weekInfo ?? loc.getWeekInfo?.()\n if (weekInfo && typeof weekInfo.firstDay === 'number') return weekInfo.firstDay % 7\n } catch {\n // fall through to the default\n }\n return 1\n}\n\nexport function getWeekdayLabels(locale: string, weekStartsOn: number): string[] {\n const start = ((Math.trunc(weekStartsOn) % 7) + 7) % 7\n const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short' })\n // 2026-01-04 is a Sunday.\n return Array.from({ length: 7 }, (_, i) =>\n formatter.format(new Date(2026, 0, 4 + ((start + i) % 7))),\n )\n}\n\nexport function getMonthLabel(date: Date, locale: string): string {\n return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(date)\n}\n\nexport function formatLocalizedDate(date: Date, locale: string): string {\n return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(date)\n}\n\nexport function formatLocalizedTime(date: Date, locale: string, hourFormat: '12' | '24'): string {\n const options: Intl.DateTimeFormatOptions =\n hourFormat === '24'\n ? { hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }\n : { hour: 'numeric', minute: '2-digit', hour12: true }\n return new Intl.DateTimeFormat(locale, options).format(date)\n}\n","/**\n * Normalise a numeric field value: empty and non-finite inputs collapse to\n * `null`, while `0` and every other finite number pass through unchanged.\n */\nexport function toNumberOrNull(value: number | null | undefined): number | null {\n if (value === null || value === undefined || !Number.isFinite(value)) return null\n return value\n}\n\n/**\n * Compose the `Intl.NumberFormatOptions` for a number field. Later sources win,\n * so explicit `formatOptions` override the `currency` shorthand and `integer`\n * forces zero fraction digits regardless of what came before.\n */\nexport function mergeFormatOptions(input: {\n currency?: string\n formatOptions?: Intl.NumberFormatOptions\n integer?: boolean\n}): Intl.NumberFormatOptions {\n return {\n ...(input.currency ? { style: 'currency' as const, currency: input.currency } : {}),\n ...input.formatOptions,\n ...(input.integer ? { maximumFractionDigits: 0 } : {}),\n }\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","export type Tone = 'info' | 'success' | 'warning' | 'danger' | 'secondary'\n\nexport interface ToneClasses {\n soft: string\n outline: string\n icon: string\n role: 'alert' | 'status'\n}\n\nexport const toneClasses: Record<Tone, ToneClasses> = {\n info: {\n soft: 'bg-primary-100 text-primary-800 dark:bg-primary-900/40 dark:text-primary-200',\n outline: 'border border-primary-300 text-primary-800 dark:border-primary-700 dark:text-primary-200',\n icon: 'text-primary-500 dark:text-primary-300',\n role: 'status',\n },\n success: {\n soft: 'bg-success-100 text-success-800 dark:bg-success-900/40 dark:text-success-200',\n outline: 'border border-success-300 text-success-800 dark:border-success-700 dark:text-success-200',\n icon: 'text-success-500 dark:text-success-300',\n role: 'status',\n },\n warning: {\n soft: 'bg-warning-100 text-warning-800 dark:bg-warning-900/40 dark:text-warning-200',\n outline: 'border border-warning-300 text-warning-800 dark:border-warning-700 dark:text-warning-200',\n icon: 'text-warning-500 dark:text-warning-300',\n role: 'alert',\n },\n danger: {\n soft: 'bg-error-100 text-error-800 dark:bg-error-900/40 dark:text-error-200',\n outline: 'border border-error-300 text-error-800 dark:border-error-700 dark:text-error-200',\n icon: 'text-error-500 dark:text-error-300',\n role: 'alert',\n },\n secondary: {\n soft: 'bg-surface-muted text-foreground',\n outline: 'border border-border text-foreground',\n icon: 'text-muted',\n role: 'status',\n },\n}\n","import { computed, ref } from 'vue'\nimport type { ComputedRef, Ref } from 'vue'\n\nexport type ThemeMode = 'light' | 'dark' | 'system'\nexport type ThemeAttribute = 'both' | 'class' | 'data-theme'\n\nexport interface UseThemeOptions {\n /** localStorage key used to persist an explicit mode. Defaults to `'myghf-theme'`. */\n storageKey?: string\n /** Which attribute(s) to write on `<html>`. Defaults to `'both'`. */\n attribute?: ThemeAttribute\n /** Mode used when nothing is stored. Defaults to `'system'`. */\n defaultMode?: ThemeMode\n}\n\nexport interface UseThemeReturn {\n /** The user's chosen mode (`'system'` follows the OS). */\n mode: Ref<ThemeMode>\n /** The effective mode after resolving `'system'` against the OS preference. */\n resolved: ComputedRef<'light' | 'dark'>\n /** Convenience flag: `resolved === 'dark'`. */\n isDark: ComputedRef<boolean>\n setMode(mode: ThemeMode): void\n toggle(): void\n enable(): void\n disable(): void\n reset(): void\n}\n\nconst DEFAULT_STORAGE_KEY = 'myghf-theme'\nconst DEFAULT_ATTRIBUTE: ThemeAttribute = 'both'\nconst DEFAULT_MODE: ThemeMode = 'system'\n\n/** SSR guard: every DOM access is behind this. */\nfunction hasDom(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined'\n}\n\nfunction systemPreference(): 'light' | 'dark' {\n if (!hasDom() || typeof window.matchMedia !== 'function') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction readStoredMode(storageKey: string): ThemeMode | null {\n try {\n const stored = window.localStorage.getItem(storageKey)\n return stored === 'light' || stored === 'dark' || stored === 'system' ? stored : null\n } catch {\n // Storage can throw when disabled (private mode, blocked cookies); stay in memory.\n return null\n }\n}\n\nfunction normalize(options: UseThemeOptions): Required<UseThemeOptions> {\n return {\n storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,\n attribute: options.attribute ?? DEFAULT_ATTRIBUTE,\n defaultMode: options.defaultMode ?? DEFAULT_MODE,\n }\n}\n\nfunction optionsEqual(a: UseThemeOptions, b: UseThemeOptions): boolean {\n const left = normalize(a)\n const right = normalize(b)\n return (\n left.storageKey === right.storageKey &&\n left.attribute === right.attribute &&\n left.defaultMode === right.defaultMode\n )\n}\n\n/**\n * Builds an independent theme controller. Writes `.dark` and/or\n * `data-theme=\"dark\"` on `<html>` so the CSS dark token block activates.\n * Safe to call during SSR: without a DOM it resolves to light and is a no-op.\n */\nexport function createTheme(options: UseThemeOptions = {}): UseThemeReturn {\n const { storageKey, attribute, defaultMode } = normalize(options)\n\n const initialMode = hasDom() ? (readStoredMode(storageKey) ?? defaultMode) : defaultMode\n const mode = ref<ThemeMode>(initialMode)\n\n const resolved = computed<'light' | 'dark'>(() =>\n mode.value === 'system' ? systemPreference() : mode.value,\n )\n const isDark = computed(() => resolved.value === 'dark')\n\n function apply(): void {\n if (!hasDom()) return\n const dark = isDark.value\n const root = document.documentElement\n\n if (attribute === 'both' || attribute === 'class') {\n root.classList.toggle('dark', dark)\n } else {\n root.classList.remove('dark')\n }\n\n if (attribute === 'both' || attribute === 'data-theme') {\n if (dark) root.setAttribute('data-theme', 'dark')\n else root.removeAttribute('data-theme')\n } else {\n root.removeAttribute('data-theme')\n }\n }\n\n function persist(value: ThemeMode): void {\n if (!hasDom()) return\n try {\n if (value === 'system') window.localStorage.removeItem(storageKey)\n else window.localStorage.setItem(storageKey, value)\n } catch {\n // Ignore storage failures; the applied theme still works for this session.\n }\n }\n\n function setMode(value: ThemeMode): void {\n mode.value = value\n persist(value)\n apply()\n }\n\n function toggle(): void {\n setMode(isDark.value ? 'light' : 'dark')\n }\n\n function enable(): void {\n setMode('dark')\n }\n\n function disable(): void {\n setMode('light')\n }\n\n function reset(): void {\n // Always return to 'system', regardless of defaultMode: defaultMode only\n // seeds the initial mode when nothing is stored.\n mode.value = 'system'\n if (hasDom()) {\n try {\n window.localStorage.removeItem(storageKey)\n } catch {\n // Ignore storage failures.\n }\n }\n apply()\n }\n\n // Apply the initial stored/default preference on construction.\n apply()\n\n return { mode, resolved, isDark, setMode, toggle, enable, disable, reset }\n}\n\nlet sharedTheme: UseThemeReturn | null = null\nlet sharedOptions: UseThemeOptions | null = null\n\n/**\n * Returns a single shared theme controller, lazily created on first call.\n * Later calls reuse it; in dev a mismatched options object logs a warning.\n */\nexport function useTheme(options?: UseThemeOptions): UseThemeReturn {\n if (!sharedTheme) {\n sharedTheme = createTheme(options)\n sharedOptions = options ?? {}\n return sharedTheme\n }\n\n if (\n import.meta.env.DEV &&\n options !== undefined &&\n !optionsEqual(sharedOptions ?? {}, options)\n ) {\n console.warn(\n '[myghf/ui] useTheme() was called again with different options; reusing the first instance. ' +\n 'Call createTheme() for an independent controller.',\n )\n }\n\n return sharedTheme\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Moon, Sun } from 'lucide-vue-next'\nimport { useTheme } from '../../lib/theme'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n }>(),\n { size: 'default', label: 'Toggle theme' },\n)\n\nconst { isDark, toggle } = useTheme()\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n}\n\n// Mirrors Button's `ghost` variant sizing/hover/focus treatment.\nconst classes = computed(() => [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors',\n 'text-foreground hover:bg-surface-muted',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-background',\n 'disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4',\n SIZE_CLASSES[props.size],\n])\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"classes\"\n :aria-label=\"label\"\n :aria-pressed=\"isDark\"\n @click=\"toggle()\"\n >\n <Sun v-if=\"isDark\" />\n <Moon v-else />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Moon, Sun } from 'lucide-vue-next'\nimport { useTheme } from '../../lib/theme'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n }>(),\n { size: 'default', label: 'Toggle theme' },\n)\n\nconst { isDark, toggle } = useTheme()\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n}\n\n// Mirrors Button's `ghost` variant sizing/hover/focus treatment.\nconst classes = computed(() => [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors',\n 'text-foreground hover:bg-surface-muted',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-background',\n 'disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4',\n SIZE_CLASSES[props.size],\n])\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"classes\"\n :aria-label=\"label\"\n :aria-pressed=\"isDark\"\n @click=\"toggle()\"\n >\n <Sun v-if=\"isDark\" />\n <Moon v-else />\n </button>\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 } 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'\nimport Icon from '../icon/Icon.vue'\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 dark:focus-visible:ring-offset-background 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 /** Leading icon name (lucide). Ignored while `loading` shows the spinner. */\n icon?: string\n /** Trailing icon name (lucide); implies end placement. */\n iconTrailing?: string\n /** Side the `icon` renders on. Defaults to `start`. */\n iconPos?: 'start' | 'end'\n }>(),\n {\n variant: 'default',\n size: 'default',\n type: 'button',\n disabled: false,\n loading: false,\n iconPos: 'start',\n },\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 :aria-busy=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <Icon v-if=\"loading\" name=\"loader-circle\" class=\"animate-spin\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'start' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n <slot>{{ label }}</slot>\n <Icon v-if=\"iconTrailing\" :name=\"iconTrailing\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'end' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { tv, type VariantProps } from 'tailwind-variants'\nimport Icon from '../icon/Icon.vue'\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 dark:focus-visible:ring-offset-background 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 /** Leading icon name (lucide). Ignored while `loading` shows the spinner. */\n icon?: string\n /** Trailing icon name (lucide); implies end placement. */\n iconTrailing?: string\n /** Side the `icon` renders on. Defaults to `start`. */\n iconPos?: 'start' | 'end'\n }>(),\n {\n variant: 'default',\n size: 'default',\n type: 'button',\n disabled: false,\n loading: false,\n iconPos: 'start',\n },\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 :aria-busy=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <Icon v-if=\"loading\" name=\"loader-circle\" class=\"animate-spin\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'start' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n <slot>{{ label }}</slot>\n <Icon v-if=\"iconTrailing\" :name=\"iconTrailing\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'end' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n </button>\n</template>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\n\n/**\n * Shared context provided by `FormField` and consumed by `Label` (and, in\n * later tasks, `Input`, `Textarea`, and `Select`) to auto-wire `for`/`id`,\n * `aria-describedby`, `aria-invalid`, and `required` onto a control.\n *\n * Every member is a computed ref so the context stays reactive when the\n * `FormField` props change after mount.\n */\nexport interface FormFieldContext {\n /** The control id: the `FormField` `id` prop, or a generated fallback. */\n id: ComputedRef<string>\n /** Space-joined description/error ids, or `undefined` when neither exists. */\n describedBy: ComputedRef<string | undefined>\n /** `true` when the field should be marked invalid (defaults to `Boolean(error)`). */\n invalid: ComputedRef<boolean>\n /** `true` when the field is required. */\n required: ComputedRef<boolean>\n}\n\nexport const formFieldKey: InjectionKey<FormFieldContext> = Symbol('myghf-form-field')\n\n/**\n * Reads the nearest `FormField` context. Returns `null` when there is no\n * provider, so consumers can fall back to their explicit props and behave\n * exactly as they did before the context existed.\n */\nexport function useFormField(): FormFieldContext | null {\n return inject(formFieldKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { useFormField } from '../../lib/formField'\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 type?: string\n id?: string\n name?: string\n autocomplete?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { size: 'default', type: 'text', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\nconst field = useFormField()\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :id=\"id\"\n :type=\"type\"\n :name=\"name\"\n :autocomplete=\"autocomplete\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 { computed, ref, useAttrs } from 'vue'\nimport { useFormField } from '../../lib/formField'\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 type?: string\n id?: string\n name?: string\n autocomplete?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { size: 'default', type: 'text', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\nconst field = useFormField()\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :id=\"id\"\n :type=\"type\"\n :name=\"name\"\n :autocomplete=\"autocomplete\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 {\n NumberFieldDecrement,\n NumberFieldIncrement,\n NumberFieldInput,\n NumberFieldRoot,\n} from 'reka-ui'\nimport { computed, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\nimport { mergeFormatOptions, toNumberOrNull } from '../../lib/number'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null\n min?: number\n max?: number\n step?: number\n stepSnapping?: boolean\n integer?: boolean\n locale?: string\n formatOptions?: Intl.NumberFormatOptions\n currency?: string\n prefix?: string\n suffix?: string\n showButtons?: boolean\n placeholder?: string\n disabled?: boolean\n readonly?: boolean\n invalid?: boolean\n size?: 'sm' | 'default' | 'lg'\n id?: string\n name?: string\n }>(),\n { step: 1, size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: number | null] }>()\nconst attrs = useAttrs()\n\n/** Never hand reka a non-positive or non-finite step; it would loop or divide by zero. */\nconst safeStep = computed(() => (Number.isFinite(props.step) && props.step > 0 ? props.step : 1))\n\nconst resolvedFormatOptions = computed(() =>\n mergeFormatOptions({\n currency: props.currency,\n formatOptions: props.formatOptions,\n integer: props.integer,\n }),\n)\n\n/** Locale-formatted value for `aria-valuetext`; `undefined` when empty. */\nconst valuetext = computed<string | undefined>(() => {\n if (props.modelValue == null) return undefined\n try {\n return new Intl.NumberFormat(props.locale, resolvedFormatOptions.value).format(props.modelValue)\n } catch {\n return undefined\n }\n})\n</script>\n\n<template>\n <div\n class=\"relative flex w-full items-center rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors focus-within:ring-2 focus-within:ring-primary-500\"\n :class=\"[\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n invalid ? 'border-error-500 focus-within:ring-error-500' : '',\n disabled ? 'cursor-not-allowed opacity-50' : '',\n ]\"\n >\n <NumberFieldRoot\n :model-value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n :step=\"safeStep\"\n :step-snapping=\"stepSnapping\"\n :format-options=\"resolvedFormatOptions\"\n :locale=\"locale\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :id=\"id\"\n :name=\"name\"\n class=\"flex min-w-0 flex-1 items-center gap-1\"\n @update:model-value=\"emit('update:modelValue', toNumberOrNull($event))\"\n >\n <span v-if=\"prefix\" class=\"shrink-0 select-none text-muted\">{{ prefix }}</span>\n\n <NumberFieldInput\n v-bind=\"attrs\"\n :placeholder=\"placeholder\"\n :aria-invalid=\"invalid || undefined\"\n :aria-valuetext=\"valuetext\"\n class=\"min-w-0 flex-1 border-0 bg-transparent p-0 text-inherit outline-none placeholder:text-muted focus-visible:outline-none disabled:cursor-not-allowed\"\n />\n\n <span v-if=\"suffix\" class=\"shrink-0 select-none text-muted\">{{ suffix }}</span>\n\n <div v-if=\"showButtons\" class=\"ms-1 flex shrink-0 flex-col\">\n <NumberFieldIncrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-up\" :size=\"12\" />\n </NumberFieldIncrement>\n <NumberFieldDecrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-down\" :size=\"12\" />\n </NumberFieldDecrement>\n </div>\n </NumberFieldRoot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n NumberFieldDecrement,\n NumberFieldIncrement,\n NumberFieldInput,\n NumberFieldRoot,\n} from 'reka-ui'\nimport { computed, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\nimport { mergeFormatOptions, toNumberOrNull } from '../../lib/number'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null\n min?: number\n max?: number\n step?: number\n stepSnapping?: boolean\n integer?: boolean\n locale?: string\n formatOptions?: Intl.NumberFormatOptions\n currency?: string\n prefix?: string\n suffix?: string\n showButtons?: boolean\n placeholder?: string\n disabled?: boolean\n readonly?: boolean\n invalid?: boolean\n size?: 'sm' | 'default' | 'lg'\n id?: string\n name?: string\n }>(),\n { step: 1, size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: number | null] }>()\nconst attrs = useAttrs()\n\n/** Never hand reka a non-positive or non-finite step; it would loop or divide by zero. */\nconst safeStep = computed(() => (Number.isFinite(props.step) && props.step > 0 ? props.step : 1))\n\nconst resolvedFormatOptions = computed(() =>\n mergeFormatOptions({\n currency: props.currency,\n formatOptions: props.formatOptions,\n integer: props.integer,\n }),\n)\n\n/** Locale-formatted value for `aria-valuetext`; `undefined` when empty. */\nconst valuetext = computed<string | undefined>(() => {\n if (props.modelValue == null) return undefined\n try {\n return new Intl.NumberFormat(props.locale, resolvedFormatOptions.value).format(props.modelValue)\n } catch {\n return undefined\n }\n})\n</script>\n\n<template>\n <div\n class=\"relative flex w-full items-center rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors focus-within:ring-2 focus-within:ring-primary-500\"\n :class=\"[\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n invalid ? 'border-error-500 focus-within:ring-error-500' : '',\n disabled ? 'cursor-not-allowed opacity-50' : '',\n ]\"\n >\n <NumberFieldRoot\n :model-value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n :step=\"safeStep\"\n :step-snapping=\"stepSnapping\"\n :format-options=\"resolvedFormatOptions\"\n :locale=\"locale\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :id=\"id\"\n :name=\"name\"\n class=\"flex min-w-0 flex-1 items-center gap-1\"\n @update:model-value=\"emit('update:modelValue', toNumberOrNull($event))\"\n >\n <span v-if=\"prefix\" class=\"shrink-0 select-none text-muted\">{{ prefix }}</span>\n\n <NumberFieldInput\n v-bind=\"attrs\"\n :placeholder=\"placeholder\"\n :aria-invalid=\"invalid || undefined\"\n :aria-valuetext=\"valuetext\"\n class=\"min-w-0 flex-1 border-0 bg-transparent p-0 text-inherit outline-none placeholder:text-muted focus-visible:outline-none disabled:cursor-not-allowed\"\n />\n\n <span v-if=\"suffix\" class=\"shrink-0 select-none text-muted\">{{ suffix }}</span>\n\n <div v-if=\"showButtons\" class=\"ms-1 flex shrink-0 flex-col\">\n <NumberFieldIncrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-up\" :size=\"12\" />\n </NumberFieldIncrement>\n <NumberFieldDecrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-down\" :size=\"12\" />\n </NumberFieldDecrement>\n </div>\n </NumberFieldRoot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, useAttrs, watch } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n autoResize?: boolean\n maxRows?: number\n id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { rows: 3, invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst el = ref<HTMLTextAreaElement>()\nconst field = useFormField()\nconst capped = ref(false)\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\n\n/**\n * Grows the textarea to fit its content. Guarded so jsdom (where `scrollHeight`\n * is always 0) neither throws nor writes a `NaNpx` height.\n */\nfunction resize() {\n if (!props.autoResize || !el.value) return\n const node = el.value\n node.style.height = 'auto'\n const next = node.scrollHeight\n let height = next\n capped.value = false\n\n if (props.maxRows && next) {\n const lineHeight = parseFloat(getComputedStyle(node).lineHeight) || 0\n const max = props.maxRows * lineHeight\n if (max > 0 && next > max) {\n height = max\n capped.value = true\n }\n }\n\n node.style.height = next ? `${height}px` : ''\n}\n\nfunction onInput(event: Event) {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value)\n resize()\n}\n\nonMounted(resize)\nwatch(() => props.modelValue, resize, { flush: 'post' })\n</script>\n\n<template>\n <textarea\n ref=\"el\"\n :id=\"id\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 autoResize ? 'resize-none' : '',\n capped ? 'overflow-y-auto' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"onInput\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, useAttrs, watch } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n autoResize?: boolean\n maxRows?: number\n id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { rows: 3, invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst el = ref<HTMLTextAreaElement>()\nconst field = useFormField()\nconst capped = ref(false)\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\n\n/**\n * Grows the textarea to fit its content. Guarded so jsdom (where `scrollHeight`\n * is always 0) neither throws nor writes a `NaNpx` height.\n */\nfunction resize() {\n if (!props.autoResize || !el.value) return\n const node = el.value\n node.style.height = 'auto'\n const next = node.scrollHeight\n let height = next\n capped.value = false\n\n if (props.maxRows && next) {\n const lineHeight = parseFloat(getComputedStyle(node).lineHeight) || 0\n const max = props.maxRows * lineHeight\n if (max > 0 && next > max) {\n height = max\n capped.value = true\n }\n }\n\n node.style.height = next ? `${height}px` : ''\n}\n\nfunction onInput(event: Event) {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value)\n resize()\n}\n\nonMounted(resize)\nwatch(() => props.modelValue, resize, { flush: 'post' })\n</script>\n\n<template>\n <textarea\n ref=\"el\"\n :id=\"id\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 autoResize ? 'resize-none' : '',\n capped ? 'overflow-y-auto' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"onInput\"\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 { computed } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = defineProps<{\n /** The id of the control this label belongs to. Falls back to the field context. */\n for?: string\n /** Renders an accessible-hidden required marker. */\n required?: boolean\n}>()\n\nconst field = useFormField()\nconst forId = computed(() => props.for ?? field?.id.value)\n</script>\n\n<template>\n <label :for=\"forId\" class=\"text-sm font-medium text-foreground text-start\">\n <slot />\n <span v-if=\"required\" class=\"text-error-600\" aria-hidden=\"true\">*</span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = defineProps<{\n /** The id of the control this label belongs to. Falls back to the field context. */\n for?: string\n /** Renders an accessible-hidden required marker. */\n required?: boolean\n}>()\n\nconst field = useFormField()\nconst forId = computed(() => props.for ?? field?.id.value)\n</script>\n\n<template>\n <label :for=\"forId\" class=\"text-sm font-medium text-foreground text-start\">\n <slot />\n <span v-if=\"required\" class=\"text-error-600\" aria-hidden=\"true\">*</span>\n </label>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the description describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" class=\"text-sm text-muted\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the description describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" class=\"text-sm text-muted\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the message describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" role=\"alert\" class=\"text-sm text-error-600\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the message describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" role=\"alert\" class=\"text-sm text-error-600\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUpdate, provide, ref, useId, useSlots } from 'vue'\nimport { formFieldKey } from '../../lib/formField'\nimport Label from '../label/Label.vue'\nimport FormDescription from './FormDescription.vue'\nimport FormMessage from './FormMessage.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** Label text; can also be supplied through the `label` slot. */\n label?: string\n /** Description text; rendered below the control when present. */\n description?: string\n /** Error text; marks the field invalid and renders an alert below the control. */\n error?: string\n /** Marks the field required (adds the label marker and context flag). */\n required?: boolean\n /** Overrides the invalid state. Defaults to `Boolean(error)`. */\n invalid?: boolean\n /** Explicit control id. Defaults to a stable generated id. */\n id?: string\n }>(),\n // An explicit `undefined` keeps Vue's Boolean casting from turning an absent\n // `invalid` into `false`, so `invalid` can fall through to `Boolean(error)`.\n { invalid: undefined },\n)\n\nconst slots = useSlots()\n\n// Slot functions are not reactive: Vue mutates the `slots` object in place\n// during the parent's update, which happens just before this component's\n// `onBeforeUpdate` hook. Bumping a version counter here invalidates `describedBy`\n// when a slot is added or removed after mount, so consumers re-read the\n// description/error ids instead of sticking to their initial value.\nconst slotsVersion = ref(0)\nonBeforeUpdate(() => {\n slotsVersion.value++\n})\n\n// `useId()` must run once, directly in setup — never inside a computed, which\n// could be evaluated in a different instance context.\nconst generatedId = useId()\nconst fieldId = computed(() => props.id ?? generatedId)\nconst invalid = computed(() => props.invalid ?? Boolean(props.error))\nconst required = computed(() => props.required ?? false)\n\n// Description/error content can come from a prop or a slot. `slotsVersion` is\n// read so slot-presence changes invalidate this computed; the template checks\n// `$slots` at render time for actually rendering the element.\nconst describedBy = computed(() => {\n void slotsVersion.value\n const ids: string[] = []\n if (props.description || slots.description) ids.push(`${fieldId.value}-description`)\n if (props.error || slots.error) ids.push(`${fieldId.value}-error`)\n return ids.length > 0 ? ids.join(' ') : undefined\n})\n\nprovide(formFieldKey, { id: fieldId, describedBy, invalid, required })\n</script>\n\n<template>\n <div class=\"grid gap-2\">\n <Label v-if=\"label || $slots.label\" :for=\"fieldId\" :required=\"required\">\n <slot name=\"label\">{{ label }}</slot>\n </Label>\n\n <slot />\n\n <FormDescription v-if=\"description || $slots.description\" :id=\"`${fieldId}-description`\">\n <slot name=\"description\">{{ description }}</slot>\n </FormDescription>\n\n <FormMessage v-if=\"error || $slots.error\" :id=\"`${fieldId}-error`\">\n <slot name=\"error\">{{ error }}</slot>\n </FormMessage>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUpdate, provide, ref, useId, useSlots } from 'vue'\nimport { formFieldKey } from '../../lib/formField'\nimport Label from '../label/Label.vue'\nimport FormDescription from './FormDescription.vue'\nimport FormMessage from './FormMessage.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** Label text; can also be supplied through the `label` slot. */\n label?: string\n /** Description text; rendered below the control when present. */\n description?: string\n /** Error text; marks the field invalid and renders an alert below the control. */\n error?: string\n /** Marks the field required (adds the label marker and context flag). */\n required?: boolean\n /** Overrides the invalid state. Defaults to `Boolean(error)`. */\n invalid?: boolean\n /** Explicit control id. Defaults to a stable generated id. */\n id?: string\n }>(),\n // An explicit `undefined` keeps Vue's Boolean casting from turning an absent\n // `invalid` into `false`, so `invalid` can fall through to `Boolean(error)`.\n { invalid: undefined },\n)\n\nconst slots = useSlots()\n\n// Slot functions are not reactive: Vue mutates the `slots` object in place\n// during the parent's update, which happens just before this component's\n// `onBeforeUpdate` hook. Bumping a version counter here invalidates `describedBy`\n// when a slot is added or removed after mount, so consumers re-read the\n// description/error ids instead of sticking to their initial value.\nconst slotsVersion = ref(0)\nonBeforeUpdate(() => {\n slotsVersion.value++\n})\n\n// `useId()` must run once, directly in setup — never inside a computed, which\n// could be evaluated in a different instance context.\nconst generatedId = useId()\nconst fieldId = computed(() => props.id ?? generatedId)\nconst invalid = computed(() => props.invalid ?? Boolean(props.error))\nconst required = computed(() => props.required ?? false)\n\n// Description/error content can come from a prop or a slot. `slotsVersion` is\n// read so slot-presence changes invalidate this computed; the template checks\n// `$slots` at render time for actually rendering the element.\nconst describedBy = computed(() => {\n void slotsVersion.value\n const ids: string[] = []\n if (props.description || slots.description) ids.push(`${fieldId.value}-description`)\n if (props.error || slots.error) ids.push(`${fieldId.value}-error`)\n return ids.length > 0 ? ids.join(' ') : undefined\n})\n\nprovide(formFieldKey, { id: fieldId, describedBy, invalid, required })\n</script>\n\n<template>\n <div class=\"grid gap-2\">\n <Label v-if=\"label || $slots.label\" :for=\"fieldId\" :required=\"required\">\n <slot name=\"label\">{{ label }}</slot>\n </Label>\n\n <slot />\n\n <FormDescription v-if=\"description || $slots.description\" :id=\"`${fieldId}-description`\">\n <slot name=\"description\">{{ description }}</slot>\n </FormDescription>\n\n <FormMessage v-if=\"error || $slots.error\" :id=\"`${fieldId}-error`\">\n <slot name=\"error\">{{ error }}</slot>\n </FormMessage>\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 dark:focus-visible:ring-offset-background 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 dark:focus-visible:ring-offset-background 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 { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nwithDefaults(\n defineProps<{\n tone?: Tone\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { tone: 'secondary', removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = Tone\n</script>\n\n<template>\n <span\n :class=\"[\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n toneClasses[tone].soft,\n ]\"\n >\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 dark:hover:bg-white/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 { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nwithDefaults(\n defineProps<{\n tone?: Tone\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { tone: 'secondary', removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = Tone\n</script>\n\n<template>\n <span\n :class=\"[\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n toneClasses[tone].soft,\n ]\"\n >\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 dark:hover:bg-white/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 { onBeforeUnmount, onMounted, ref } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nexport type AlertVariant = 'soft' | 'outline'\n\nconst props = withDefaults(\n defineProps<{\n tone?: Tone\n title?: string\n description?: string\n icon?: string\n showIcon?: boolean\n closable?: boolean\n duration?: number\n closeLabel?: string\n variant?: AlertVariant\n }>(),\n {\n tone: 'info',\n showIcon: false,\n closable: false,\n closeLabel: 'Close',\n variant: 'soft',\n },\n)\n\nconst emit = defineEmits<{ close: [] }>()\n\n/** Fallback lucide name per tone, used when `showIcon` is set but `icon` is not. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n\nconst dismissed = ref(false)\nconst hovered = ref(false)\nconst focused = ref(false)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n/** Absolute ms timestamp when the active timer would fire. */\nlet deadline = 0\n/** Ms left when the timer was paused; drives resume. */\nlet remaining = 0\n\nfunction clearTimer() {\n if (timer !== undefined) {\n clearTimeout(timer)\n timer = undefined\n }\n}\n\nfunction start(ms: number) {\n clearTimer()\n if (ms <= 0) return\n remaining = ms\n deadline = Date.now() + ms\n timer = setTimeout(dismiss, ms)\n}\n\nfunction pause() {\n if (timer === undefined) return\n clearTimer()\n remaining = Math.max(0, deadline - Date.now())\n}\n\n/**\n * Re-arms the timer only once both pause sources are released. If the remaining\n * time floored to zero while paused, dismiss immediately instead of stranding.\n */\nfunction maybeResume() {\n if (dismissed.value || hovered.value || focused.value || timer !== undefined) return\n if (!props.duration || props.duration <= 0) return\n if (remaining <= 0) {\n dismiss()\n return\n }\n start(remaining)\n}\n\nfunction onEnter() {\n hovered.value = true\n pause()\n}\n\nfunction onLeave() {\n hovered.value = false\n maybeResume()\n}\n\nfunction onFocusIn() {\n focused.value = true\n pause()\n}\n\nfunction onFocusOut() {\n focused.value = false\n maybeResume()\n}\n\nfunction dismiss() {\n if (dismissed.value) return\n dismissed.value = true\n clearTimer()\n emit('close')\n}\n\nonMounted(() => {\n if (props.duration && props.duration > 0) start(props.duration)\n})\n\nonBeforeUnmount(clearTimer)\n</script>\n\n<template>\n <div\n v-if=\"!dismissed\"\n :role=\"toneClasses[tone].role\"\n :class=\"[\n 'flex w-full items-start gap-3 rounded-lg p-4 text-sm',\n toneClasses[tone][variant],\n ]\"\n @mouseenter=\"onEnter\"\n @mouseleave=\"onLeave\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot name=\"icon\">\n <Icon\n v-if=\"showIcon\"\n :name=\"icon || defaultIcons[tone]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[tone].icon]\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1\">\n <p v-if=\"title || $slots.title\" class=\"font-medium\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n <div\n v-if=\"description || $slots.description\"\n :class=\"['leading-relaxed', title || $slots.title ? 'mt-1' : '']\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </div>\n <slot />\n </div>\n\n <slot name=\"actions\" />\n\n <button\n v-if=\"closable\"\n type=\"button\"\n :aria-label=\"closeLabel\"\n class=\"-me-1 -mt-1 ms-auto shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"dismiss\"\n >\n <slot name=\"close\"><X class=\"size-4\" /></slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nexport type AlertVariant = 'soft' | 'outline'\n\nconst props = withDefaults(\n defineProps<{\n tone?: Tone\n title?: string\n description?: string\n icon?: string\n showIcon?: boolean\n closable?: boolean\n duration?: number\n closeLabel?: string\n variant?: AlertVariant\n }>(),\n {\n tone: 'info',\n showIcon: false,\n closable: false,\n closeLabel: 'Close',\n variant: 'soft',\n },\n)\n\nconst emit = defineEmits<{ close: [] }>()\n\n/** Fallback lucide name per tone, used when `showIcon` is set but `icon` is not. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n\nconst dismissed = ref(false)\nconst hovered = ref(false)\nconst focused = ref(false)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n/** Absolute ms timestamp when the active timer would fire. */\nlet deadline = 0\n/** Ms left when the timer was paused; drives resume. */\nlet remaining = 0\n\nfunction clearTimer() {\n if (timer !== undefined) {\n clearTimeout(timer)\n timer = undefined\n }\n}\n\nfunction start(ms: number) {\n clearTimer()\n if (ms <= 0) return\n remaining = ms\n deadline = Date.now() + ms\n timer = setTimeout(dismiss, ms)\n}\n\nfunction pause() {\n if (timer === undefined) return\n clearTimer()\n remaining = Math.max(0, deadline - Date.now())\n}\n\n/**\n * Re-arms the timer only once both pause sources are released. If the remaining\n * time floored to zero while paused, dismiss immediately instead of stranding.\n */\nfunction maybeResume() {\n if (dismissed.value || hovered.value || focused.value || timer !== undefined) return\n if (!props.duration || props.duration <= 0) return\n if (remaining <= 0) {\n dismiss()\n return\n }\n start(remaining)\n}\n\nfunction onEnter() {\n hovered.value = true\n pause()\n}\n\nfunction onLeave() {\n hovered.value = false\n maybeResume()\n}\n\nfunction onFocusIn() {\n focused.value = true\n pause()\n}\n\nfunction onFocusOut() {\n focused.value = false\n maybeResume()\n}\n\nfunction dismiss() {\n if (dismissed.value) return\n dismissed.value = true\n clearTimer()\n emit('close')\n}\n\nonMounted(() => {\n if (props.duration && props.duration > 0) start(props.duration)\n})\n\nonBeforeUnmount(clearTimer)\n</script>\n\n<template>\n <div\n v-if=\"!dismissed\"\n :role=\"toneClasses[tone].role\"\n :class=\"[\n 'flex w-full items-start gap-3 rounded-lg p-4 text-sm',\n toneClasses[tone][variant],\n ]\"\n @mouseenter=\"onEnter\"\n @mouseleave=\"onLeave\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot name=\"icon\">\n <Icon\n v-if=\"showIcon\"\n :name=\"icon || defaultIcons[tone]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[tone].icon]\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1\">\n <p v-if=\"title || $slots.title\" class=\"font-medium\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n <div\n v-if=\"description || $slots.description\"\n :class=\"['leading-relaxed', title || $slots.title ? 'mt-1' : '']\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </div>\n <slot />\n </div>\n\n <slot name=\"actions\" />\n\n <button\n v-if=\"closable\"\n type=\"button\"\n :aria-label=\"closeLabel\"\n class=\"-me-1 -mt-1 ms-auto shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"dismiss\"\n >\n <slot name=\"close\"><X class=\"size-4\" /></slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport { cn } from '../../lib/cn'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n tone?: Tone\n }>(),\n { size: 'default', label: 'Loading…', tone: 'info' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'size-4',\n default: 'size-5',\n lg: 'size-6',\n}\n\nconst classes = computed(() => cn('inline-flex items-center', toneClasses[props.tone].icon))\n</script>\n\n<template>\n <span role=\"status\" aria-live=\"polite\" :class=\"classes\">\n <Icon\n name=\"loader-circle\"\n :class=\"cn('animate-spin', SIZE_CLASSES[size])\"\n aria-hidden=\"true\"\n />\n <span class=\"sr-only\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport { cn } from '../../lib/cn'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n tone?: Tone\n }>(),\n { size: 'default', label: 'Loading…', tone: 'info' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'size-4',\n default: 'size-5',\n lg: 'size-6',\n}\n\nconst classes = computed(() => cn('inline-flex items-center', toneClasses[props.tone].icon))\n</script>\n\n<template>\n <span role=\"status\" aria-live=\"polite\" :class=\"classes\">\n <Icon\n name=\"loader-circle\"\n :class=\"cn('animate-spin', SIZE_CLASSES[size])\"\n aria-hidden=\"true\"\n />\n <span class=\"sr-only\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\n\ndefineOptions({ inheritAttrs: false })\n\nconst skeleton = tv({\n base: 'animate-pulse bg-surface-muted',\n variants: {\n rounded: {\n none: '',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n },\n },\n defaultVariants: { rounded: 'md' },\n})\n\nwithDefaults(\n defineProps<{\n rounded?: VariantProps<typeof skeleton>['rounded']\n width?: string\n height?: string\n }>(),\n { rounded: 'md' },\n)\n</script>\n\n<template>\n <div :class=\"skeleton({ rounded })\" :style=\"{ width, height }\" v-bind=\"$attrs\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\n\ndefineOptions({ inheritAttrs: false })\n\nconst skeleton = tv({\n base: 'animate-pulse bg-surface-muted',\n variants: {\n rounded: {\n none: '',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n },\n },\n defaultVariants: { rounded: 'md' },\n})\n\nwithDefaults(\n defineProps<{\n rounded?: VariantProps<typeof skeleton>['rounded']\n width?: string\n height?: string\n }>(),\n { rounded: 'md' },\n)\n</script>\n\n<template>\n <div :class=\"skeleton({ rounded })\" :style=\"{ width, height }\" v-bind=\"$attrs\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { cn } from '../../lib/cn'\nimport { toneClasses } from '../../lib/tones'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n src?: string\n alt?: string\n name?: string\n initials?: string\n size?: 'sm' | 'default' | 'lg' | 'xl'\n }>(),\n { size: 'default' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg' | 'xl', string> = {\n sm: 'size-6 text-xs',\n default: 'size-8 text-sm',\n lg: 'size-10 text-base',\n xl: 'size-14 text-lg',\n}\n\nfunction deriveInitials(name?: string): string {\n if (!name) return ''\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => word.charAt(0))\n .join('')\n .toUpperCase()\n}\n\nconst initials = computed(() => props.initials ?? deriveInitials(props.name))\nconst sizeClass = computed(() => SIZE_CLASSES[props.size])\n\n// `role=\"img\"` requires a non-empty accessible name, so only expose the\n// fallback as an image when one is available.\nconst accessibleName = computed(() => {\n const label = props.alt ?? props.name ?? initials.value\n return label === '' ? undefined : label\n})\n\nconst errored = ref(false)\nwatch(\n () => props.src,\n () => {\n errored.value = false\n },\n)\n</script>\n\n<template>\n <img\n v-if=\"src && !errored\"\n v-bind=\"$attrs\"\n :src=\"src\"\n :alt=\"alt ?? name ?? ''\"\n :class=\"cn(sizeClass, 'shrink-0 rounded-full object-cover')\"\n @error=\"errored = true\"\n />\n <span\n v-else\n v-bind=\"$attrs\"\n :role=\"accessibleName ? 'img' : undefined\"\n :aria-label=\"accessibleName\"\n :class=\"\n cn(\n sizeClass,\n toneClasses.info.soft,\n 'inline-flex shrink-0 items-center justify-center rounded-full font-medium',\n )\n \"\n >{{ initials }}</span\n >\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { cn } from '../../lib/cn'\nimport { toneClasses } from '../../lib/tones'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n src?: string\n alt?: string\n name?: string\n initials?: string\n size?: 'sm' | 'default' | 'lg' | 'xl'\n }>(),\n { size: 'default' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg' | 'xl', string> = {\n sm: 'size-6 text-xs',\n default: 'size-8 text-sm',\n lg: 'size-10 text-base',\n xl: 'size-14 text-lg',\n}\n\nfunction deriveInitials(name?: string): string {\n if (!name) return ''\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => word.charAt(0))\n .join('')\n .toUpperCase()\n}\n\nconst initials = computed(() => props.initials ?? deriveInitials(props.name))\nconst sizeClass = computed(() => SIZE_CLASSES[props.size])\n\n// `role=\"img\"` requires a non-empty accessible name, so only expose the\n// fallback as an image when one is available.\nconst accessibleName = computed(() => {\n const label = props.alt ?? props.name ?? initials.value\n return label === '' ? undefined : label\n})\n\nconst errored = ref(false)\nwatch(\n () => props.src,\n () => {\n errored.value = false\n },\n)\n</script>\n\n<template>\n <img\n v-if=\"src && !errored\"\n v-bind=\"$attrs\"\n :src=\"src\"\n :alt=\"alt ?? name ?? ''\"\n :class=\"cn(sizeClass, 'shrink-0 rounded-full object-cover')\"\n @error=\"errored = true\"\n />\n <span\n v-else\n v-bind=\"$attrs\"\n :role=\"accessibleName ? 'img' : undefined\"\n :aria-label=\"accessibleName\"\n :class=\"\n cn(\n sizeClass,\n toneClasses.info.soft,\n 'inline-flex shrink-0 items-center justify-center rounded-full font-medium',\n )\n \"\n >{{ initials }}</span\n >\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'\nimport { useFormField } from '../../lib/formField'\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 id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst field = useFormField()\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :required=\"required || undefined\"\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 :id=\"id\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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'\nimport { useFormField } from '../../lib/formField'\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 id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst field = useFormField()\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :required=\"required || undefined\"\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 :id=\"id\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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, useSlots, watch, type VNode } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport {\n buildHourOptions,\n buildMinuteOptions,\n clampTime,\n from12Hour,\n sortRange,\n to12Hour,\n toTime,\n} from '../../lib/date'\nimport {\n formatLocalizedDate,\n formatLocalizedTime,\n getFirstDayOfWeek,\n getMonthLabel,\n getWeekdayLabels,\n} from '../../lib/locale'\n\nexport interface DatePickerLabels {\n placeholder: string\n previousMonth: string\n nextMonth: string\n clear: string\n apply: string\n today: string\n time: string\n hour: string\n minute: string\n am: string\n pm: string\n}\n\nconst LABELS: Record<string, DatePickerLabels> = {\n en: {\n placeholder: 'Select date',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n clear: 'Clear',\n apply: 'Apply',\n today: 'Today',\n time: 'Time',\n hour: 'Hour',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n fr: {\n placeholder: 'Choisir une date',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n clear: 'Effacer',\n apply: 'Appliquer',\n today: \"Aujourd'hui\",\n time: 'Heure',\n hour: 'Heure',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n es: {\n placeholder: 'Seleccionar fecha',\n previousMonth: 'Mes anterior',\n nextMonth: 'Mes siguiente',\n clear: 'Borrar',\n apply: 'Aplicar',\n today: 'Hoy',\n time: 'Hora',\n hour: 'Hora',\n minute: 'Minuto',\n am: 'AM',\n pm: 'PM',\n },\n de: {\n placeholder: 'Datum wählen',\n previousMonth: 'Vorheriger Monat',\n nextMonth: 'Nächster Monat',\n clear: 'Löschen',\n apply: 'Übernehmen',\n today: 'Heute',\n time: 'Uhrzeit',\n hour: 'Stunde',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n ar: {\n placeholder: 'اختر التاريخ',\n previousMonth: 'الشهر السابق',\n nextMonth: 'الشهر التالي',\n clear: 'مسح',\n apply: 'تطبيق',\n today: 'اليوم',\n time: 'الوقت',\n hour: 'الساعة',\n minute: 'الدقيقة',\n am: 'ص',\n pm: 'م',\n },\n}\n\nfunction defaultLabels(locale: string): DatePickerLabels {\n const lang = locale.toLowerCase().split(/[-_]/)[0]\n return LABELS[lang] ?? LABELS.en\n}\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n /** @deprecated Prefer `labels.placeholder`; kept for the existing trigger API. */\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 hourFormat?: '12' | '24'\n minuteStep?: number\n locale?: string\n labels?: Partial<DatePickerLabels>\n weekStartsOn?: number\n defaultOpen?: boolean\n }>(),\n {\n mode: 'date',\n size: 'default',\n hourFormat: '24',\n minuteStep: 1,\n // Runtime locale, best-effort, falling back to English. Inlined because\n // `withDefaults` is hoisted and cannot reference local declarations.\n locale: () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().locale || 'en'\n } catch {\n return 'en'\n }\n },\n defaultOpen: false,\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst slots = useSlots()\n\nconst open = ref(props.defaultOpen ?? 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 effectiveLocale = computed(() => props.locale || 'en')\n\nconst resolvedLabels = computed<DatePickerLabels>(() => ({\n ...defaultLabels(effectiveLocale.value),\n // The legacy `placeholder` prop fills in only when the new labels API has no\n // value; `labels.placeholder` is spread last so it wins over both.\n ...(props.placeholder !== undefined ? { placeholder: props.placeholder } : {}),\n ...props.labels,\n}))\n\nfunction flatten(node: unknown): string {\n if (node == null || typeof node === 'boolean') return ''\n if (typeof node === 'string' || typeof node === 'number') return String(node)\n if (Array.isArray(node)) return node.map(flatten).join('')\n const vnode = node as VNode\n if (typeof vnode.children === 'string') return vnode.children\n if (Array.isArray(vnode.children)) return vnode.children.map(flatten).join('')\n return ''\n}\n\n/** `label-<key>` slot text when supplied, otherwise the resolved label. */\nfunction labelFor(key: keyof DatePickerLabels): string {\n const slot = slots[`label-${key}`]\n if (slot) {\n const text = slot().map(flatten).join('').trim()\n if (text) return text\n }\n return resolvedLabels.value[key]\n}\n\nconst weekStartsOn = computed(() => props.weekStartsOn ?? getFirstDayOfWeek(effectiveLocale.value))\nconst weekdayLabels = computed(() => getWeekdayLabels(effectiveLocale.value, weekStartsOn.value))\nconst monthLabel = computed(() => getMonthLabel(viewDate.value, effectiveLocale.value))\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() - weekStartsOn.value + 7) % 7\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 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 parsedTime = computed(() => {\n const [h, m] = time.value.split(':').map(Number)\n return {\n hour24: Number.isFinite(h) ? ((Math.trunc(h) % 24) + 24) % 24 : 0,\n minute: Number.isFinite(m) ? ((Math.trunc(m) % 60) + 60) % 60 : 0,\n }\n})\n\nconst hourOptions = computed(() => buildHourOptions(props.hourFormat))\nconst minuteOptions = computed(() =>\n buildMinuteOptions(Math.min(30, Math.max(1, props.minuteStep ?? 1))),\n)\n\nconst selectedHour = computed<number>({\n get: () =>\n props.hourFormat === '12' ? to12Hour(parsedTime.value.hour24).hour : parsedTime.value.hour24,\n set: (value) => {\n const { hour24, minute } = parsedTime.value\n const next =\n props.hourFormat === '12' ? from12Hour(value, to12Hour(hour24).meridiem) : value\n time.value = toTime(next * 60 + minute)\n },\n})\n\nconst selectedMinute = computed<number>({\n get: () => parsedTime.value.minute,\n set: (value) => {\n time.value = toTime(parsedTime.value.hour24 * 60 + value)\n },\n})\n\nconst selectedMeridiem = computed<'am' | 'pm'>({\n get: () => to12Hour(parsedTime.value.hour24).meridiem,\n set: (value) => {\n const { hour } = to12Hour(parsedTime.value.hour24)\n time.value = toTime(from12Hour(hour, value) * 60 + parsedTime.value.minute)\n },\n})\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0')\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 `${formatLocalizedDate(s, effectiveLocale.value)} – ${formatLocalizedDate(e, effectiveLocale.value)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n if (props.mode === 'datetime') {\n return `${formatLocalizedDate(d, effectiveLocale.value)} ${formatLocalizedTime(d, effectiveLocale.value, props.hourFormat)}`\n }\n return formatLocalizedDate(d, effectiveLocale.value)\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 || labelFor('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=\"labelFor('previousMonth')\"\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 rtl:rotate-180\" />\n </button>\n <span data-test=\"month-label\" class=\"text-sm font-medium\">{{ monthLabel }}</span>\n <button\n type=\"button\"\n :aria-label=\"labelFor('nextMonth')\"\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 rtl:rotate-180\" />\n </button>\n </div>\n\n <div data-test=\"weekdays\" class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"(d, i) in weekdayLabels\" :key=\"i\" class=\"py-1 font-medium text-muted\">\n {{ d }}\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 dark:bg-primary-900/40 dark:text-primary-200' : '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 <div role=\"group\" :aria-label=\"labelFor('time')\" class=\"flex items-center gap-1.5 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <select\n v-model.number=\"selectedHour\"\n data-test=\"hours\"\n :aria-label=\"labelFor('hour')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"h in hourOptions\" :key=\"h\" :value=\"h\">\n {{ hourFormat === '12' ? h : pad(h) }}\n </option>\n </select>\n <span aria-hidden=\"true\">:</span>\n <select\n v-model.number=\"selectedMinute\"\n data-test=\"minutes\"\n :aria-label=\"labelFor('minute')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"m in minuteOptions\" :key=\"m\" :value=\"m\">{{ pad(m) }}</option>\n </select>\n <select\n v-if=\"hourFormat === '12'\"\n v-model=\"selectedMeridiem\"\n data-test=\"meridiem\"\n :aria-label=\"labelFor('time')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option value=\"am\">{{ labelFor('am') }}</option>\n <option value=\"pm\">{{ labelFor('pm') }}</option>\n </select>\n </div>\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 {{ labelFor('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 {{ labelFor('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 {{ labelFor('clear') }}\n </button>\n </div>\n </PopoverContent>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useSlots, watch, type VNode } from 'vue'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport {\n buildHourOptions,\n buildMinuteOptions,\n clampTime,\n from12Hour,\n sortRange,\n to12Hour,\n toTime,\n} from '../../lib/date'\nimport {\n formatLocalizedDate,\n formatLocalizedTime,\n getFirstDayOfWeek,\n getMonthLabel,\n getWeekdayLabels,\n} from '../../lib/locale'\n\nexport interface DatePickerLabels {\n placeholder: string\n previousMonth: string\n nextMonth: string\n clear: string\n apply: string\n today: string\n time: string\n hour: string\n minute: string\n am: string\n pm: string\n}\n\nconst LABELS: Record<string, DatePickerLabels> = {\n en: {\n placeholder: 'Select date',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n clear: 'Clear',\n apply: 'Apply',\n today: 'Today',\n time: 'Time',\n hour: 'Hour',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n fr: {\n placeholder: 'Choisir une date',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n clear: 'Effacer',\n apply: 'Appliquer',\n today: \"Aujourd'hui\",\n time: 'Heure',\n hour: 'Heure',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n es: {\n placeholder: 'Seleccionar fecha',\n previousMonth: 'Mes anterior',\n nextMonth: 'Mes siguiente',\n clear: 'Borrar',\n apply: 'Aplicar',\n today: 'Hoy',\n time: 'Hora',\n hour: 'Hora',\n minute: 'Minuto',\n am: 'AM',\n pm: 'PM',\n },\n de: {\n placeholder: 'Datum wählen',\n previousMonth: 'Vorheriger Monat',\n nextMonth: 'Nächster Monat',\n clear: 'Löschen',\n apply: 'Übernehmen',\n today: 'Heute',\n time: 'Uhrzeit',\n hour: 'Stunde',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n ar: {\n placeholder: 'اختر التاريخ',\n previousMonth: 'الشهر السابق',\n nextMonth: 'الشهر التالي',\n clear: 'مسح',\n apply: 'تطبيق',\n today: 'اليوم',\n time: 'الوقت',\n hour: 'الساعة',\n minute: 'الدقيقة',\n am: 'ص',\n pm: 'م',\n },\n}\n\nfunction defaultLabels(locale: string): DatePickerLabels {\n const lang = locale.toLowerCase().split(/[-_]/)[0]\n return LABELS[lang] ?? LABELS.en\n}\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n /** @deprecated Prefer `labels.placeholder`; kept for the existing trigger API. */\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 hourFormat?: '12' | '24'\n minuteStep?: number\n locale?: string\n labels?: Partial<DatePickerLabels>\n weekStartsOn?: number\n defaultOpen?: boolean\n }>(),\n {\n mode: 'date',\n size: 'default',\n hourFormat: '24',\n minuteStep: 1,\n // Runtime locale, best-effort, falling back to English. Inlined because\n // `withDefaults` is hoisted and cannot reference local declarations.\n locale: () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().locale || 'en'\n } catch {\n return 'en'\n }\n },\n defaultOpen: false,\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst slots = useSlots()\n\nconst open = ref(props.defaultOpen ?? 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 effectiveLocale = computed(() => props.locale || 'en')\n\nconst resolvedLabels = computed<DatePickerLabels>(() => ({\n ...defaultLabels(effectiveLocale.value),\n // The legacy `placeholder` prop fills in only when the new labels API has no\n // value; `labels.placeholder` is spread last so it wins over both.\n ...(props.placeholder !== undefined ? { placeholder: props.placeholder } : {}),\n ...props.labels,\n}))\n\nfunction flatten(node: unknown): string {\n if (node == null || typeof node === 'boolean') return ''\n if (typeof node === 'string' || typeof node === 'number') return String(node)\n if (Array.isArray(node)) return node.map(flatten).join('')\n const vnode = node as VNode\n if (typeof vnode.children === 'string') return vnode.children\n if (Array.isArray(vnode.children)) return vnode.children.map(flatten).join('')\n return ''\n}\n\n/** `label-<key>` slot text when supplied, otherwise the resolved label. */\nfunction labelFor(key: keyof DatePickerLabels): string {\n const slot = slots[`label-${key}`]\n if (slot) {\n const text = slot().map(flatten).join('').trim()\n if (text) return text\n }\n return resolvedLabels.value[key]\n}\n\nconst weekStartsOn = computed(() => props.weekStartsOn ?? getFirstDayOfWeek(effectiveLocale.value))\nconst weekdayLabels = computed(() => getWeekdayLabels(effectiveLocale.value, weekStartsOn.value))\nconst monthLabel = computed(() => getMonthLabel(viewDate.value, effectiveLocale.value))\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() - weekStartsOn.value + 7) % 7\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 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 parsedTime = computed(() => {\n const [h, m] = time.value.split(':').map(Number)\n return {\n hour24: Number.isFinite(h) ? ((Math.trunc(h) % 24) + 24) % 24 : 0,\n minute: Number.isFinite(m) ? ((Math.trunc(m) % 60) + 60) % 60 : 0,\n }\n})\n\nconst hourOptions = computed(() => buildHourOptions(props.hourFormat))\nconst minuteOptions = computed(() =>\n buildMinuteOptions(Math.min(30, Math.max(1, props.minuteStep ?? 1))),\n)\n\nconst selectedHour = computed<number>({\n get: () =>\n props.hourFormat === '12' ? to12Hour(parsedTime.value.hour24).hour : parsedTime.value.hour24,\n set: (value) => {\n const { hour24, minute } = parsedTime.value\n const next =\n props.hourFormat === '12' ? from12Hour(value, to12Hour(hour24).meridiem) : value\n time.value = toTime(next * 60 + minute)\n },\n})\n\nconst selectedMinute = computed<number>({\n get: () => parsedTime.value.minute,\n set: (value) => {\n time.value = toTime(parsedTime.value.hour24 * 60 + value)\n },\n})\n\nconst selectedMeridiem = computed<'am' | 'pm'>({\n get: () => to12Hour(parsedTime.value.hour24).meridiem,\n set: (value) => {\n const { hour } = to12Hour(parsedTime.value.hour24)\n time.value = toTime(from12Hour(hour, value) * 60 + parsedTime.value.minute)\n },\n})\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0')\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 `${formatLocalizedDate(s, effectiveLocale.value)} – ${formatLocalizedDate(e, effectiveLocale.value)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n if (props.mode === 'datetime') {\n return `${formatLocalizedDate(d, effectiveLocale.value)} ${formatLocalizedTime(d, effectiveLocale.value, props.hourFormat)}`\n }\n return formatLocalizedDate(d, effectiveLocale.value)\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 || labelFor('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=\"labelFor('previousMonth')\"\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 rtl:rotate-180\" />\n </button>\n <span data-test=\"month-label\" class=\"text-sm font-medium\">{{ monthLabel }}</span>\n <button\n type=\"button\"\n :aria-label=\"labelFor('nextMonth')\"\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 rtl:rotate-180\" />\n </button>\n </div>\n\n <div data-test=\"weekdays\" class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"(d, i) in weekdayLabels\" :key=\"i\" class=\"py-1 font-medium text-muted\">\n {{ d }}\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 dark:bg-primary-900/40 dark:text-primary-200' : '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 <div role=\"group\" :aria-label=\"labelFor('time')\" class=\"flex items-center gap-1.5 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <select\n v-model.number=\"selectedHour\"\n data-test=\"hours\"\n :aria-label=\"labelFor('hour')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"h in hourOptions\" :key=\"h\" :value=\"h\">\n {{ hourFormat === '12' ? h : pad(h) }}\n </option>\n </select>\n <span aria-hidden=\"true\">:</span>\n <select\n v-model.number=\"selectedMinute\"\n data-test=\"minutes\"\n :aria-label=\"labelFor('minute')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"m in minuteOptions\" :key=\"m\" :value=\"m\">{{ pad(m) }}</option>\n </select>\n <select\n v-if=\"hourFormat === '12'\"\n v-model=\"selectedMeridiem\"\n data-test=\"meridiem\"\n :aria-label=\"labelFor('time')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option value=\"am\">{{ labelFor('am') }}</option>\n <option value=\"pm\">{{ labelFor('pm') }}</option>\n </select>\n </div>\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 {{ labelFor('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 {{ labelFor('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 {{ labelFor('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 dark:bg-black/70\" />\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 dark:bg-black/70\" />\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 VisuallyHidden,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nexport type DrawerPosition = 'left' | 'right' | 'top' | 'bottom' | 'start' | 'end'\nexport type DrawerSize = 'sm' | 'md' | 'lg' | 'full'\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean\n position?: DrawerPosition\n size?: DrawerSize\n backdrop?: boolean\n closeOnEscape?: boolean\n closeOnOutside?: boolean\n title?: string\n description?: string\n showClose?: boolean\n preventScroll?: boolean\n }>(),\n {\n open: false,\n position: 'right',\n size: 'md',\n backdrop: true,\n closeOnEscape: true,\n closeOnOutside: true,\n showClose: true,\n preventScroll: true,\n },\n)\n\nconst emit = defineEmits<{ 'update:open': [value: boolean]; open: []; close: [] }>()\n\nconst open = computed({\n get: () => props.open,\n set: (value: boolean) => emit('update:open', value),\n})\n\nfunction onOpenChange(value: boolean) {\n emit('update:open', value)\n if (value) emit('open')\n else emit('close')\n}\n\n/**\n * Reka dismisses on Escape itself; cancelling the default is what blocks the\n * dismissal, so we only preventDefault when the consumer opted out.\n */\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n/** Same contract for outside pointer/focus/inert dismissal. */\nfunction onPointerDownOutside(event: Event) {\n if (!props.closeOnOutside) event.preventDefault()\n}\n\n/** Physical `left`/`right`; `start`/`end` mirror them and flip in RTL. */\nconst positionClasses: Record<DrawerPosition, string> = {\n right: 'inset-y-0 right-0 h-full w-full data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n left: 'inset-y-0 left-0 h-full w-full data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n end: 'inset-y-0 end-0 h-full w-full data-[state=closed]:translate-x-full rtl:data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n start: 'inset-y-0 start-0 h-full w-full data-[state=closed]:-translate-x-full rtl:data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n top: 'inset-x-0 top-0 w-full h-full data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0',\n bottom: 'inset-x-0 bottom-0 w-full h-full data-[state=closed]:translate-y-full data-[state=open]:translate-y-0',\n}\n\nconst horizontalSizes: Record<DrawerSize, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n full: 'max-w-full',\n}\n\nconst verticalSizes: Record<DrawerSize, string> = {\n sm: 'max-h-64',\n md: 'max-h-96',\n lg: 'max-h-[32rem]',\n full: 'max-h-full',\n}\n\nconst isVertical = computed(() => props.position === 'top' || props.position === 'bottom')\nconst sizeClass = computed(() => (isVertical.value ? verticalSizes[props.size] : horizontalSizes[props.size]))\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 <!--\n `force-mount` mirrors `open` so the portal's first render is synchronous when\n the drawer starts open (reka's Teleport defers its children until mounted).\n Once mounted the portal stays put, so presence/animation still work on close.\n -->\n <DialogPortal :force-mount=\"open\">\n <DialogOverlay\n v-if=\"backdrop || preventScroll\"\n :class=\"['fixed inset-0 z-50', backdrop ? 'bg-black/50 dark:bg-black/70' : 'bg-transparent']\"\n />\n <DialogContent\n :class=\"[\n 'fixed z-50 flex flex-col overflow-hidden border-border bg-surface shadow-dialog transition-transform duration-200 focus-visible:outline-none',\n positionClasses[position],\n sizeClass,\n ]\"\n @escape-key-down=\"onEscapeKeyDown\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <VisuallyHidden v-if=\"!title && !$slots.header\">\n <DialogTitle>Drawer</DialogTitle>\n </VisuallyHidden>\n\n <header\n v-if=\"title || $slots.header || description || $slots.description || showClose\"\n class=\"flex shrink-0 items-start justify-between gap-4 border-b border-border p-5 pb-4\"\n >\n <div class=\"min-w-0\">\n <DialogTitle\n v-if=\"title || $slots.header\"\n class=\"text-lg font-semibold text-foreground\"\n >\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription\n v-if=\"description || $slots.description\"\n class=\"mt-1 text-sm text-muted\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n v-if=\"showClose\"\n class=\"ms-auto shrink-0 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 <slot name=\"close\"><X class=\"size-4\" /></slot>\n </DialogClose>\n </header>\n\n <div class=\"flex-1 overflow-y-auto p-5\">\n <slot />\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"shrink-0 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </footer>\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 VisuallyHidden,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nexport type DrawerPosition = 'left' | 'right' | 'top' | 'bottom' | 'start' | 'end'\nexport type DrawerSize = 'sm' | 'md' | 'lg' | 'full'\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean\n position?: DrawerPosition\n size?: DrawerSize\n backdrop?: boolean\n closeOnEscape?: boolean\n closeOnOutside?: boolean\n title?: string\n description?: string\n showClose?: boolean\n preventScroll?: boolean\n }>(),\n {\n open: false,\n position: 'right',\n size: 'md',\n backdrop: true,\n closeOnEscape: true,\n closeOnOutside: true,\n showClose: true,\n preventScroll: true,\n },\n)\n\nconst emit = defineEmits<{ 'update:open': [value: boolean]; open: []; close: [] }>()\n\nconst open = computed({\n get: () => props.open,\n set: (value: boolean) => emit('update:open', value),\n})\n\nfunction onOpenChange(value: boolean) {\n emit('update:open', value)\n if (value) emit('open')\n else emit('close')\n}\n\n/**\n * Reka dismisses on Escape itself; cancelling the default is what blocks the\n * dismissal, so we only preventDefault when the consumer opted out.\n */\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n/** Same contract for outside pointer/focus/inert dismissal. */\nfunction onPointerDownOutside(event: Event) {\n if (!props.closeOnOutside) event.preventDefault()\n}\n\n/** Physical `left`/`right`; `start`/`end` mirror them and flip in RTL. */\nconst positionClasses: Record<DrawerPosition, string> = {\n right: 'inset-y-0 right-0 h-full w-full data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n left: 'inset-y-0 left-0 h-full w-full data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n end: 'inset-y-0 end-0 h-full w-full data-[state=closed]:translate-x-full rtl:data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n start: 'inset-y-0 start-0 h-full w-full data-[state=closed]:-translate-x-full rtl:data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n top: 'inset-x-0 top-0 w-full h-full data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0',\n bottom: 'inset-x-0 bottom-0 w-full h-full data-[state=closed]:translate-y-full data-[state=open]:translate-y-0',\n}\n\nconst horizontalSizes: Record<DrawerSize, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n full: 'max-w-full',\n}\n\nconst verticalSizes: Record<DrawerSize, string> = {\n sm: 'max-h-64',\n md: 'max-h-96',\n lg: 'max-h-[32rem]',\n full: 'max-h-full',\n}\n\nconst isVertical = computed(() => props.position === 'top' || props.position === 'bottom')\nconst sizeClass = computed(() => (isVertical.value ? verticalSizes[props.size] : horizontalSizes[props.size]))\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 <!--\n `force-mount` mirrors `open` so the portal's first render is synchronous when\n the drawer starts open (reka's Teleport defers its children until mounted).\n Once mounted the portal stays put, so presence/animation still work on close.\n -->\n <DialogPortal :force-mount=\"open\">\n <DialogOverlay\n v-if=\"backdrop || preventScroll\"\n :class=\"['fixed inset-0 z-50', backdrop ? 'bg-black/50 dark:bg-black/70' : 'bg-transparent']\"\n />\n <DialogContent\n :class=\"[\n 'fixed z-50 flex flex-col overflow-hidden border-border bg-surface shadow-dialog transition-transform duration-200 focus-visible:outline-none',\n positionClasses[position],\n sizeClass,\n ]\"\n @escape-key-down=\"onEscapeKeyDown\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <VisuallyHidden v-if=\"!title && !$slots.header\">\n <DialogTitle>Drawer</DialogTitle>\n </VisuallyHidden>\n\n <header\n v-if=\"title || $slots.header || description || $slots.description || showClose\"\n class=\"flex shrink-0 items-start justify-between gap-4 border-b border-border p-5 pb-4\"\n >\n <div class=\"min-w-0\">\n <DialogTitle\n v-if=\"title || $slots.header\"\n class=\"text-lg font-semibold text-foreground\"\n >\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription\n v-if=\"description || $slots.description\"\n class=\"mt-1 text-sm text-muted\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n v-if=\"showClose\"\n class=\"ms-auto shrink-0 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 <slot name=\"close\"><X class=\"size-4\" /></slot>\n </DialogClose>\n </header>\n\n <div class=\"flex-1 overflow-y-auto p-5\">\n <slot />\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"shrink-0 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </footer>\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'\nimport Icon from '../icon/Icon.vue'\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\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof itemVariants>['variant']\n icon?: string\n disabled?: boolean\n }>(),\n { disabled: false },\n)\n\nconst emit = defineEmits<{ select: [] }>()\n\nfunction onSelect() {\n if (!props.disabled) emit('select')\n}\n</script>\n\n<template>\n <RekaItem :disabled=\"disabled\" :class=\"itemVariants({ variant })\" @select=\"onSelect\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-4 shrink-0\" />\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'\nimport Icon from '../icon/Icon.vue'\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\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof itemVariants>['variant']\n icon?: string\n disabled?: boolean\n }>(),\n { disabled: false },\n)\n\nconst emit = defineEmits<{ select: [] }>()\n\nfunction onSelect() {\n if (!props.disabled) emit('select')\n}\n</script>\n\n<template>\n <RekaItem :disabled=\"disabled\" :class=\"itemVariants({ variant })\" @select=\"onSelect\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-4 shrink-0\" />\n <slot />\n </RekaItem>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuSeparator as RekaSeparator } from 'reka-ui'\n</script>\n\n<template>\n <RekaSeparator class=\"my-1 h-px bg-border\" />\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuSeparator as RekaSeparator } from 'reka-ui'\n</script>\n\n<template>\n <RekaSeparator class=\"my-1 h-px bg-border\" />\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuLabel as RekaLabel } from 'reka-ui'\n</script>\n\n<template>\n <RekaLabel class=\"px-2 py-1.5 text-xs font-medium text-muted\">\n <slot />\n </RekaLabel>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuLabel as RekaLabel } from 'reka-ui'\n</script>\n\n<template>\n <RekaLabel class=\"px-2 py-1.5 text-xs font-medium text-muted\">\n <slot />\n </RekaLabel>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuGroup as RekaGroup } from 'reka-ui'\n</script>\n\n<template>\n <RekaGroup>\n <slot />\n </RekaGroup>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuGroup as RekaGroup } from 'reka-ui'\n</script>\n\n<template>\n <RekaGroup>\n <slot />\n </RekaGroup>\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","import { computed, inject, ref, type ComputedRef, type InjectionKey, type Ref } from 'vue'\n\nexport type ToastSeverity = 'info' | 'success' | 'warning' | 'danger' | 'secondary'\n\nexport type ToastPosition =\n | 'top-start' | 'top-center' | 'top-end'\n | 'bottom-start' | 'bottom-center' | 'bottom-end'\n\nexport interface ToastAction {\n label: string\n onClick: () => void\n}\n\nexport interface ToastOptions {\n title?: string\n description?: string\n severity?: ToastSeverity\n duration?: number\n position?: ToastPosition\n closable?: boolean\n icon?: string\n action?: ToastAction\n}\n\nexport interface ToastItem extends ToastOptions {\n id: string\n}\n\nexport interface ToastStoreOptions {\n max?: number\n duration?: number\n position?: ToastPosition\n}\n\nexport interface ToastStore {\n /** All toasts, including those queued past `max`. */\n items: Ref<ToastItem[]>\n /** The `max` most recent toasts, oldest first. */\n visible: ComputedRef<ToastItem[]>\n add: (options: ToastOptions) => string\n remove: (id: string) => void\n clear: () => void\n info: (title: string, description?: string) => string\n success: (title: string, description?: string) => string\n warning: (title: string, description?: string) => string\n danger: (title: string, description?: string) => string\n secondary: (title: string, description?: string) => string\n}\n\n/** Injection key for the toast store provided by `<Toaster />`. */\nexport const toastKey: InjectionKey<ToastStore> = Symbol('myghf-toast')\n\nlet seq = 0\n\nexport function createToastStore(options: ToastStoreOptions = {}): ToastStore {\n const max = Math.max(1, options.max ?? 4)\n const duration = options.duration ?? 5000\n const position = options.position ?? 'top-end'\n\n const items = ref<ToastItem[]>([])\n const visible = computed(() => items.value.slice(0, max))\n\n function add(options: ToastOptions): string {\n const id = `toast-${++seq}`\n items.value.push({ severity: 'info', position, duration, ...options, id })\n return id\n }\n\n function remove(id: string) {\n const index = items.value.findIndex((item) => item.id === id)\n if (index !== -1) items.value.splice(index, 1)\n }\n\n function clear() {\n items.value = []\n }\n\n function convenience(severity: ToastSeverity) {\n return (title: string, description?: string) => add({ title, description, severity })\n }\n\n return {\n items,\n visible,\n add,\n remove,\n clear,\n info: convenience('info'),\n success: convenience('success'),\n warning: convenience('warning'),\n danger: convenience('danger'),\n secondary: convenience('secondary'),\n }\n}\n\nexport function useToast(): ToastStore {\n const store = inject(toastKey)\n if (!store) {\n throw new Error('useToast() requires a <Toaster /> mounted above this component.')\n }\n return store\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ToastAction as RekaToastAction,\n ToastClose,\n ToastDescription,\n ToastRoot,\n ToastTitle,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\nimport type { ToastItem, ToastSeverity } from './useToast'\n\nconst props = defineProps<{\n item: ToastItem\n duration: number\n}>()\n\nconst emit = defineEmits<{ close: [] }>()\n\nconst severity = computed<ToastSeverity>(() => props.item.severity ?? 'info')\n\n/** Foreground toasts are announced assertively; background ones politely. */\nconst type = computed(() =>\n severity.value === 'danger' || severity.value === 'warning' ? 'foreground' : 'background',\n)\n\nconst resolvedDuration = computed(() => props.item.duration ?? props.duration)\n\n/** Fallback lucide name per severity, used when no explicit `icon` is set. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n</script>\n\n<template>\n <ToastRoot\n :default-open=\"true\"\n :duration=\"resolvedDuration\"\n :type=\"type\"\n data-toast-root\n :data-duration=\"resolvedDuration\"\n :class=\"[\n 'pointer-events-auto flex w-full items-start gap-3 rounded-lg p-4 text-sm shadow-popover',\n toneClasses[severity].soft,\n ]\"\n @update:open=\"(open) => !open && emit('close')\"\n >\n <Icon\n :name=\"item.icon || defaultIcons[severity]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[severity].icon]\"\n />\n\n <div class=\"min-w-0 flex-1\">\n <ToastTitle v-if=\"item.title\" class=\"font-medium\">\n {{ item.title }}\n </ToastTitle>\n <ToastDescription\n v-if=\"item.description\"\n :class=\"['leading-relaxed', item.title ? 'mt-1' : '']\"\n >\n {{ item.description }}\n </ToastDescription>\n </div>\n\n <RekaToastAction\n v-if=\"item.action\"\n :alt-text=\"item.action.label\"\n class=\"-my-1 shrink-0 rounded-md px-2 py-1 font-medium transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"item.action.onClick()\"\n >\n {{ item.action.label }}\n </RekaToastAction>\n\n <ToastClose\n v-if=\"item.closable !== false\"\n aria-label=\"Close\"\n class=\"-me-1 -mt-1 shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <X class=\"size-4\" />\n </ToastClose>\n </ToastRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ToastAction as RekaToastAction,\n ToastClose,\n ToastDescription,\n ToastRoot,\n ToastTitle,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\nimport type { ToastItem, ToastSeverity } from './useToast'\n\nconst props = defineProps<{\n item: ToastItem\n duration: number\n}>()\n\nconst emit = defineEmits<{ close: [] }>()\n\nconst severity = computed<ToastSeverity>(() => props.item.severity ?? 'info')\n\n/** Foreground toasts are announced assertively; background ones politely. */\nconst type = computed(() =>\n severity.value === 'danger' || severity.value === 'warning' ? 'foreground' : 'background',\n)\n\nconst resolvedDuration = computed(() => props.item.duration ?? props.duration)\n\n/** Fallback lucide name per severity, used when no explicit `icon` is set. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n</script>\n\n<template>\n <ToastRoot\n :default-open=\"true\"\n :duration=\"resolvedDuration\"\n :type=\"type\"\n data-toast-root\n :data-duration=\"resolvedDuration\"\n :class=\"[\n 'pointer-events-auto flex w-full items-start gap-3 rounded-lg p-4 text-sm shadow-popover',\n toneClasses[severity].soft,\n ]\"\n @update:open=\"(open) => !open && emit('close')\"\n >\n <Icon\n :name=\"item.icon || defaultIcons[severity]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[severity].icon]\"\n />\n\n <div class=\"min-w-0 flex-1\">\n <ToastTitle v-if=\"item.title\" class=\"font-medium\">\n {{ item.title }}\n </ToastTitle>\n <ToastDescription\n v-if=\"item.description\"\n :class=\"['leading-relaxed', item.title ? 'mt-1' : '']\"\n >\n {{ item.description }}\n </ToastDescription>\n </div>\n\n <RekaToastAction\n v-if=\"item.action\"\n :alt-text=\"item.action.label\"\n class=\"-my-1 shrink-0 rounded-md px-2 py-1 font-medium transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"item.action.onClick()\"\n >\n {{ item.action.label }}\n </RekaToastAction>\n\n <ToastClose\n v-if=\"item.closable !== false\"\n aria-label=\"Close\"\n class=\"-me-1 -mt-1 shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <X class=\"size-4\" />\n </ToastClose>\n </ToastRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { provide } from 'vue'\nimport { ToastProvider, ToastViewport } from 'reka-ui'\nimport { createToastStore, toastKey, type ToastPosition, type ToastStore } from './useToast'\nimport Toast from './Toast.vue'\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition\n max?: number\n duration?: number\n gap?: string\n label?: string\n store?: ToastStore\n }>(),\n {\n position: 'top-end',\n max: 4,\n duration: 5000,\n gap: '0.5rem',\n label: 'Notifications',\n },\n)\n\nconst toastStore = props.store ?? createToastStore({\n max: props.max,\n duration: props.duration,\n position: props.position,\n})\n\nprovide(toastKey, toastStore)\n\nconst POSITIONS: ToastPosition[] = [\n 'top-start', 'top-center', 'top-end',\n 'bottom-start', 'bottom-center', 'bottom-end',\n]\n\nconst viewportPosition: Record<ToastPosition, string> = {\n 'top-start': 'top-0 start-0',\n 'top-center': 'top-0 inset-x-0 mx-auto',\n 'top-end': 'top-0 end-0',\n 'bottom-start': 'bottom-0 start-0',\n 'bottom-center': 'bottom-0 inset-x-0 mx-auto',\n 'bottom-end': 'bottom-0 end-0',\n}\n\nfunction itemsFor(position: ToastPosition) {\n return toastStore.visible.value.filter((item) => (item.position ?? props.position) === position)\n}\n</script>\n\n<template>\n <ToastProvider :label=\"label\" :duration=\"duration\">\n <slot />\n <template v-for=\"pos in POSITIONS\" :key=\"pos\">\n <ToastViewport\n v-if=\"itemsFor(pos).length > 0\"\n :label=\"label\"\n :class=\"[\n 'pointer-events-none fixed z-50 flex max-h-screen w-full max-w-sm flex-col',\n viewportPosition[pos],\n ]\"\n :style=\"{ gap }\"\n >\n <Toast\n v-for=\"item in itemsFor(pos)\"\n :key=\"item.id\"\n :item=\"item\"\n :duration=\"duration\"\n @close=\"toastStore.remove(item.id)\"\n />\n </ToastViewport>\n </template>\n </ToastProvider>\n</template>\n","<script setup lang=\"ts\">\nimport { provide } from 'vue'\nimport { ToastProvider, ToastViewport } from 'reka-ui'\nimport { createToastStore, toastKey, type ToastPosition, type ToastStore } from './useToast'\nimport Toast from './Toast.vue'\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition\n max?: number\n duration?: number\n gap?: string\n label?: string\n store?: ToastStore\n }>(),\n {\n position: 'top-end',\n max: 4,\n duration: 5000,\n gap: '0.5rem',\n label: 'Notifications',\n },\n)\n\nconst toastStore = props.store ?? createToastStore({\n max: props.max,\n duration: props.duration,\n position: props.position,\n})\n\nprovide(toastKey, toastStore)\n\nconst POSITIONS: ToastPosition[] = [\n 'top-start', 'top-center', 'top-end',\n 'bottom-start', 'bottom-center', 'bottom-end',\n]\n\nconst viewportPosition: Record<ToastPosition, string> = {\n 'top-start': 'top-0 start-0',\n 'top-center': 'top-0 inset-x-0 mx-auto',\n 'top-end': 'top-0 end-0',\n 'bottom-start': 'bottom-0 start-0',\n 'bottom-center': 'bottom-0 inset-x-0 mx-auto',\n 'bottom-end': 'bottom-0 end-0',\n}\n\nfunction itemsFor(position: ToastPosition) {\n return toastStore.visible.value.filter((item) => (item.position ?? props.position) === position)\n}\n</script>\n\n<template>\n <ToastProvider :label=\"label\" :duration=\"duration\">\n <slot />\n <template v-for=\"pos in POSITIONS\" :key=\"pos\">\n <ToastViewport\n v-if=\"itemsFor(pos).length > 0\"\n :label=\"label\"\n :class=\"[\n 'pointer-events-none fixed z-50 flex max-h-screen w-full max-w-sm flex-col',\n viewportPosition[pos],\n ]\"\n :style=\"{ gap }\"\n >\n <Toast\n v-for=\"item in itemsFor(pos)\"\n :key=\"item.id\"\n :item=\"item\"\n :duration=\"duration\"\n @close=\"toastStore.remove(item.id)\"\n />\n </ToastViewport>\n </template>\n </ToastProvider>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["$slots","$slots","$slots","$slots","$attrs","$attrs","$attrs","$slots","$slots","$attrs"],"sources":["../src/lib/cn.ts","../src/lib/date.ts","../src/lib/locale.ts","../src/lib/number.ts","../src/lib/icons.ts","../src/lib/tones.ts","../src/lib/theme.ts","../src/components/theme-toggle/ThemeToggle.vue","../src/components/theme-toggle/ThemeToggle.vue","../src/components/icon/Icon.vue","../src/components/icon/Icon.vue","../src/components/button/Button.vue","../src/components/button/Button.vue","../src/lib/formField.ts","../src/components/input/Input.vue","../src/components/input/Input.vue","../src/components/input-number/InputNumber.vue","../src/components/input-number/InputNumber.vue","../src/components/textarea/Textarea.vue","../src/components/textarea/Textarea.vue","../src/components/password/Password.vue","../src/components/password/Password.vue","../src/components/label/Label.vue","../src/components/label/Label.vue","../src/components/form-field/FormDescription.vue","../src/components/form-field/FormDescription.vue","../src/components/form-field/FormMessage.vue","../src/components/form-field/FormMessage.vue","../src/components/form-field/FormField.vue","../src/components/form-field/FormField.vue","../src/components/checkbox/Checkbox.vue","../src/components/checkbox/Checkbox.vue","../src/components/tag/Tag.vue","../src/components/tag/Tag.vue","../src/components/alert/Alert.vue","../src/components/alert/Alert.vue","../src/components/spinner/Spinner.vue","../src/components/spinner/Spinner.vue","../src/components/skeleton/Skeleton.vue","../src/components/skeleton/Skeleton.vue","../src/components/avatar/Avatar.vue","../src/components/avatar/Avatar.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/drawer/Drawer.vue","../src/components/drawer/Drawer.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/dropdown-menu/DropdownMenuSeparator.vue","../src/components/dropdown-menu/DropdownMenuSeparator.vue","../src/components/dropdown-menu/DropdownMenuLabel.vue","../src/components/dropdown-menu/DropdownMenuLabel.vue","../src/components/dropdown-menu/DropdownMenuGroup.vue","../src/components/dropdown-menu/DropdownMenuGroup.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","../src/components/toast/useToast.ts","../src/components/toast/Toast.vue","../src/components/toast/Toast.vue","../src/components/toast/Toaster.vue","../src/components/toast/Toaster.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\nexport function buildHourOptions(hourFormat: '12' | '24'): number[] {\n if (hourFormat === '12') return Array.from({ length: 12 }, (_, i) => i + 1)\n return Array.from({ length: 24 }, (_, i) => i)\n}\n\nexport function buildMinuteOptions(minuteStep: number): number[] {\n const step = Number.isFinite(minuteStep) && minuteStep > 0 ? minuteStep : 1\n const out: number[] = []\n for (let m = 0; m < 60; m += step) out.push(m)\n return out\n}\n\nexport function to12Hour(hour24: number): { hour: number; meridiem: 'am' | 'pm' } {\n const normalized = ((Math.trunc(hour24) % 24) + 24) % 24\n const meridiem: 'am' | 'pm' = normalized < 12 ? 'am' : 'pm'\n const hour = normalized % 12 === 0 ? 12 : normalized % 12\n return { hour, meridiem }\n}\n\nexport function from12Hour(hour: number, meridiem: 'am' | 'pm'): number {\n const base = Math.trunc(hour) % 12\n return meridiem === 'pm' ? base + 12 : base\n}\n","export function getFirstDayOfWeek(locale: string): number {\n try {\n const loc = new Intl.Locale(locale) as Intl.Locale & {\n weekInfo?: { firstDay: number }\n getWeekInfo?: () => { firstDay: number }\n }\n const weekInfo = loc.weekInfo ?? loc.getWeekInfo?.()\n if (weekInfo && typeof weekInfo.firstDay === 'number') return weekInfo.firstDay % 7\n } catch {\n // fall through to the default\n }\n return 1\n}\n\nexport function getWeekdayLabels(locale: string, weekStartsOn: number): string[] {\n const start = ((Math.trunc(weekStartsOn) % 7) + 7) % 7\n const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short' })\n // 2026-01-04 is a Sunday.\n return Array.from({ length: 7 }, (_, i) =>\n formatter.format(new Date(2026, 0, 4 + ((start + i) % 7))),\n )\n}\n\nexport function getMonthLabel(date: Date, locale: string): string {\n return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(date)\n}\n\nexport function formatLocalizedDate(date: Date, locale: string): string {\n return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(date)\n}\n\nexport function formatLocalizedTime(date: Date, locale: string, hourFormat: '12' | '24'): string {\n const options: Intl.DateTimeFormatOptions =\n hourFormat === '24'\n ? { hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }\n : { hour: 'numeric', minute: '2-digit', hour12: true }\n return new Intl.DateTimeFormat(locale, options).format(date)\n}\n","/**\n * Normalise a numeric field value: empty and non-finite inputs collapse to\n * `null`, while `0` and every other finite number pass through unchanged.\n */\nexport function toNumberOrNull(value: number | null | undefined): number | null {\n if (value === null || value === undefined || !Number.isFinite(value)) return null\n return value\n}\n\n/**\n * Compose the `Intl.NumberFormatOptions` for a number field. Later sources win,\n * so explicit `formatOptions` override the `currency` shorthand and `integer`\n * forces zero fraction digits regardless of what came before.\n */\nexport function mergeFormatOptions(input: {\n currency?: string\n formatOptions?: Intl.NumberFormatOptions\n integer?: boolean\n}): Intl.NumberFormatOptions {\n return {\n ...(input.currency ? { style: 'currency' as const, currency: input.currency } : {}),\n ...input.formatOptions,\n ...(input.integer ? { maximumFractionDigits: 0 } : {}),\n }\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","export type Tone = 'info' | 'success' | 'warning' | 'danger' | 'secondary'\n\nexport interface ToneClasses {\n soft: string\n outline: string\n icon: string\n role: 'alert' | 'status'\n}\n\nexport const toneClasses: Record<Tone, ToneClasses> = {\n info: {\n soft: 'bg-primary-100 text-primary-800 dark:bg-primary-900/40 dark:text-primary-200',\n outline: 'border border-primary-300 text-primary-800 dark:border-primary-700 dark:text-primary-200',\n icon: 'text-primary-500 dark:text-primary-300',\n role: 'status',\n },\n success: {\n soft: 'bg-success-100 text-success-800 dark:bg-success-900/40 dark:text-success-200',\n outline: 'border border-success-300 text-success-800 dark:border-success-700 dark:text-success-200',\n icon: 'text-success-500 dark:text-success-300',\n role: 'status',\n },\n warning: {\n soft: 'bg-warning-100 text-warning-800 dark:bg-warning-900/40 dark:text-warning-200',\n outline: 'border border-warning-300 text-warning-800 dark:border-warning-700 dark:text-warning-200',\n icon: 'text-warning-500 dark:text-warning-300',\n role: 'alert',\n },\n danger: {\n soft: 'bg-error-100 text-error-800 dark:bg-error-900/40 dark:text-error-200',\n outline: 'border border-error-300 text-error-800 dark:border-error-700 dark:text-error-200',\n icon: 'text-error-500 dark:text-error-300',\n role: 'alert',\n },\n secondary: {\n soft: 'bg-surface-muted text-foreground',\n outline: 'border border-border text-foreground',\n icon: 'text-muted',\n role: 'status',\n },\n}\n","import { computed, ref } from 'vue'\nimport type { ComputedRef, Ref } from 'vue'\n\nexport type ThemeMode = 'light' | 'dark' | 'system'\nexport type ThemeAttribute = 'both' | 'class' | 'data-theme'\n\nexport interface UseThemeOptions {\n /** localStorage key used to persist an explicit mode. Defaults to `'myghf-theme'`. */\n storageKey?: string\n /** Which attribute(s) to write on `<html>`. Defaults to `'both'`. */\n attribute?: ThemeAttribute\n /** Mode used when nothing is stored. Defaults to `'system'`. */\n defaultMode?: ThemeMode\n}\n\nexport interface UseThemeReturn {\n /** The user's chosen mode (`'system'` follows the OS). */\n mode: Ref<ThemeMode>\n /** The effective mode after resolving `'system'` against the OS preference. */\n resolved: ComputedRef<'light' | 'dark'>\n /** Convenience flag: `resolved === 'dark'`. */\n isDark: ComputedRef<boolean>\n setMode(mode: ThemeMode): void\n toggle(): void\n enable(): void\n disable(): void\n reset(): void\n}\n\nconst DEFAULT_STORAGE_KEY = 'myghf-theme'\nconst DEFAULT_ATTRIBUTE: ThemeAttribute = 'both'\nconst DEFAULT_MODE: ThemeMode = 'system'\n\n/** SSR guard: every DOM access is behind this. */\nfunction hasDom(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined'\n}\n\nfunction systemPreference(): 'light' | 'dark' {\n if (!hasDom() || typeof window.matchMedia !== 'function') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction readStoredMode(storageKey: string): ThemeMode | null {\n try {\n const stored = window.localStorage.getItem(storageKey)\n return stored === 'light' || stored === 'dark' || stored === 'system' ? stored : null\n } catch {\n // Storage can throw when disabled (private mode, blocked cookies); stay in memory.\n return null\n }\n}\n\nfunction normalize(options: UseThemeOptions): Required<UseThemeOptions> {\n return {\n storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,\n attribute: options.attribute ?? DEFAULT_ATTRIBUTE,\n defaultMode: options.defaultMode ?? DEFAULT_MODE,\n }\n}\n\nfunction optionsEqual(a: UseThemeOptions, b: UseThemeOptions): boolean {\n const left = normalize(a)\n const right = normalize(b)\n return (\n left.storageKey === right.storageKey &&\n left.attribute === right.attribute &&\n left.defaultMode === right.defaultMode\n )\n}\n\n/**\n * Builds an independent theme controller. Writes `.dark` and/or\n * `data-theme=\"dark\"` on `<html>` so the CSS dark token block activates.\n * Safe to call during SSR: without a DOM it resolves to light and is a no-op.\n */\nexport function createTheme(options: UseThemeOptions = {}): UseThemeReturn {\n const { storageKey, attribute, defaultMode } = normalize(options)\n\n const initialMode = hasDom() ? (readStoredMode(storageKey) ?? defaultMode) : defaultMode\n const mode = ref<ThemeMode>(initialMode)\n\n const resolved = computed<'light' | 'dark'>(() =>\n mode.value === 'system' ? systemPreference() : mode.value,\n )\n const isDark = computed(() => resolved.value === 'dark')\n\n function apply(): void {\n if (!hasDom()) return\n const dark = isDark.value\n const root = document.documentElement\n\n if (attribute === 'both' || attribute === 'class') {\n root.classList.toggle('dark', dark)\n } else {\n root.classList.remove('dark')\n }\n\n if (attribute === 'both' || attribute === 'data-theme') {\n if (dark) root.setAttribute('data-theme', 'dark')\n else root.removeAttribute('data-theme')\n } else {\n root.removeAttribute('data-theme')\n }\n }\n\n function persist(value: ThemeMode): void {\n if (!hasDom()) return\n try {\n if (value === 'system') window.localStorage.removeItem(storageKey)\n else window.localStorage.setItem(storageKey, value)\n } catch {\n // Ignore storage failures; the applied theme still works for this session.\n }\n }\n\n function setMode(value: ThemeMode): void {\n mode.value = value\n persist(value)\n apply()\n }\n\n function toggle(): void {\n setMode(isDark.value ? 'light' : 'dark')\n }\n\n function enable(): void {\n setMode('dark')\n }\n\n function disable(): void {\n setMode('light')\n }\n\n function reset(): void {\n // Always return to 'system', regardless of defaultMode: defaultMode only\n // seeds the initial mode when nothing is stored.\n mode.value = 'system'\n if (hasDom()) {\n try {\n window.localStorage.removeItem(storageKey)\n } catch {\n // Ignore storage failures.\n }\n }\n apply()\n }\n\n // Apply the initial stored/default preference on construction.\n apply()\n\n return { mode, resolved, isDark, setMode, toggle, enable, disable, reset }\n}\n\nlet sharedTheme: UseThemeReturn | null = null\nlet sharedOptions: UseThemeOptions | null = null\n\n/**\n * Returns a single shared theme controller, lazily created on first call.\n * Later calls reuse it; in dev a mismatched options object logs a warning.\n */\nexport function useTheme(options?: UseThemeOptions): UseThemeReturn {\n if (!sharedTheme) {\n sharedTheme = createTheme(options)\n sharedOptions = options ?? {}\n return sharedTheme\n }\n\n if (\n import.meta.env.DEV &&\n options !== undefined &&\n !optionsEqual(sharedOptions ?? {}, options)\n ) {\n console.warn(\n '[myghf/ui] useTheme() was called again with different options; reusing the first instance. ' +\n 'Call createTheme() for an independent controller.',\n )\n }\n\n return sharedTheme\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Moon, Sun } from 'lucide-vue-next'\nimport { useTheme } from '../../lib/theme'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n }>(),\n { size: 'default', label: 'Toggle theme' },\n)\n\nconst { isDark, toggle } = useTheme()\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n}\n\n// Mirrors Button's `ghost` variant sizing/hover/focus treatment.\nconst classes = computed(() => [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors',\n 'text-foreground hover:bg-surface-muted',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-background',\n 'disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4',\n SIZE_CLASSES[props.size],\n])\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"classes\"\n :aria-label=\"label\"\n :aria-pressed=\"isDark\"\n @click=\"toggle()\"\n >\n <Sun v-if=\"isDark\" />\n <Moon v-else />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Moon, Sun } from 'lucide-vue-next'\nimport { useTheme } from '../../lib/theme'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n }>(),\n { size: 'default', label: 'Toggle theme' },\n)\n\nconst { isDark, toggle } = useTheme()\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'h-8 px-3 text-xs',\n default: 'h-9 px-4',\n lg: 'h-10 px-6',\n}\n\n// Mirrors Button's `ghost` variant sizing/hover/focus treatment.\nconst classes = computed(() => [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors',\n 'text-foreground hover:bg-surface-muted',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-background',\n 'disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4',\n SIZE_CLASSES[props.size],\n])\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"classes\"\n :aria-label=\"label\"\n :aria-pressed=\"isDark\"\n @click=\"toggle()\"\n >\n <Sun v-if=\"isDark\" />\n <Moon v-else />\n </button>\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 } 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'\nimport Icon from '../icon/Icon.vue'\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 dark:focus-visible:ring-offset-background 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 /** Leading icon name (lucide). Ignored while `loading` shows the spinner. */\n icon?: string\n /** Trailing icon name (lucide); implies end placement. */\n iconTrailing?: string\n /** Side the `icon` renders on. Defaults to `start`. */\n iconPos?: 'start' | 'end'\n }>(),\n {\n variant: 'default',\n size: 'default',\n type: 'button',\n disabled: false,\n loading: false,\n iconPos: 'start',\n },\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 :aria-busy=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <Icon v-if=\"loading\" name=\"loader-circle\" class=\"animate-spin\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'start' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n <slot>{{ label }}</slot>\n <Icon v-if=\"iconTrailing\" :name=\"iconTrailing\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'end' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { tv, type VariantProps } from 'tailwind-variants'\nimport Icon from '../icon/Icon.vue'\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 dark:focus-visible:ring-offset-background 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 /** Leading icon name (lucide). Ignored while `loading` shows the spinner. */\n icon?: string\n /** Trailing icon name (lucide); implies end placement. */\n iconTrailing?: string\n /** Side the `icon` renders on. Defaults to `start`. */\n iconPos?: 'start' | 'end'\n }>(),\n {\n variant: 'default',\n size: 'default',\n type: 'button',\n disabled: false,\n loading: false,\n iconPos: 'start',\n },\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 :aria-busy=\"loading || undefined\"\n :class=\"buttonVariants({ variant, size })\"\n v-bind=\"attrs\"\n >\n <Icon v-if=\"loading\" name=\"loader-circle\" class=\"animate-spin\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'start' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n <slot>{{ label }}</slot>\n <Icon v-if=\"iconTrailing\" :name=\"iconTrailing\" aria-hidden=\"true\" />\n <Icon v-else-if=\"iconPos === 'end' && icon\" :name=\"icon\" aria-hidden=\"true\" />\n </button>\n</template>\n","import { inject, type ComputedRef, type InjectionKey } from 'vue'\n\n/**\n * Shared context provided by `FormField` and consumed by `Label` (and, in\n * later tasks, `Input`, `Textarea`, and `Select`) to auto-wire `for`/`id`,\n * `aria-describedby`, `aria-invalid`, and `required` onto a control.\n *\n * Every member is a computed ref so the context stays reactive when the\n * `FormField` props change after mount.\n */\nexport interface FormFieldContext {\n /** The control id: the `FormField` `id` prop, or a generated fallback. */\n id: ComputedRef<string>\n /** Space-joined description/error ids, or `undefined` when neither exists. */\n describedBy: ComputedRef<string | undefined>\n /** `true` when the field should be marked invalid (defaults to `Boolean(error)`). */\n invalid: ComputedRef<boolean>\n /** `true` when the field is required. */\n required: ComputedRef<boolean>\n}\n\nexport const formFieldKey: InjectionKey<FormFieldContext> = Symbol('myghf-form-field')\n\n/**\n * Reads the nearest `FormField` context. Returns `null` when there is no\n * provider, so consumers can fall back to their explicit props and behave\n * exactly as they did before the context existed.\n */\nexport function useFormField(): FormFieldContext | null {\n return inject(formFieldKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { useFormField } from '../../lib/formField'\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 type?: string\n id?: string\n name?: string\n autocomplete?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { size: 'default', type: 'text', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\nconst field = useFormField()\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :id=\"id\"\n :type=\"type\"\n :name=\"name\"\n :autocomplete=\"autocomplete\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 { computed, ref, useAttrs } from 'vue'\nimport { useFormField } from '../../lib/formField'\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 type?: string\n id?: string\n name?: string\n autocomplete?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { size: 'default', type: 'text', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst inputRef = ref<HTMLInputElement>()\nconst field = useFormField()\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :id=\"id\"\n :type=\"type\"\n :name=\"name\"\n :autocomplete=\"autocomplete\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 {\n NumberFieldDecrement,\n NumberFieldIncrement,\n NumberFieldInput,\n NumberFieldRoot,\n} from 'reka-ui'\nimport { computed, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\nimport { mergeFormatOptions, toNumberOrNull } from '../../lib/number'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null\n min?: number\n max?: number\n step?: number\n stepSnapping?: boolean\n integer?: boolean\n locale?: string\n formatOptions?: Intl.NumberFormatOptions\n currency?: string\n prefix?: string\n suffix?: string\n showButtons?: boolean\n placeholder?: string\n disabled?: boolean\n readonly?: boolean\n invalid?: boolean\n size?: 'sm' | 'default' | 'lg'\n id?: string\n name?: string\n }>(),\n { step: 1, size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: number | null] }>()\nconst attrs = useAttrs()\n\n/** Never hand reka a non-positive or non-finite step; it would loop or divide by zero. */\nconst safeStep = computed(() => (Number.isFinite(props.step) && props.step > 0 ? props.step : 1))\n\nconst resolvedFormatOptions = computed(() =>\n mergeFormatOptions({\n currency: props.currency,\n formatOptions: props.formatOptions,\n integer: props.integer,\n }),\n)\n\n/** Locale-formatted value for `aria-valuetext`; `undefined` when empty. */\nconst valuetext = computed<string | undefined>(() => {\n if (props.modelValue == null) return undefined\n try {\n return new Intl.NumberFormat(props.locale, resolvedFormatOptions.value).format(props.modelValue)\n } catch {\n return undefined\n }\n})\n</script>\n\n<template>\n <div\n class=\"relative flex w-full items-center rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors focus-within:ring-2 focus-within:ring-primary-500\"\n :class=\"[\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n invalid ? 'border-error-500 focus-within:ring-error-500' : '',\n disabled ? 'cursor-not-allowed opacity-50' : '',\n ]\"\n >\n <NumberFieldRoot\n :model-value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n :step=\"safeStep\"\n :step-snapping=\"stepSnapping\"\n :format-options=\"resolvedFormatOptions\"\n :locale=\"locale\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :id=\"id\"\n :name=\"name\"\n class=\"flex min-w-0 flex-1 items-center gap-1\"\n @update:model-value=\"emit('update:modelValue', toNumberOrNull($event))\"\n >\n <span v-if=\"prefix\" class=\"shrink-0 select-none text-muted\">{{ prefix }}</span>\n\n <NumberFieldInput\n v-bind=\"attrs\"\n :placeholder=\"placeholder\"\n :aria-invalid=\"invalid || undefined\"\n :aria-valuetext=\"valuetext\"\n class=\"min-w-0 flex-1 border-0 bg-transparent p-0 text-inherit outline-none placeholder:text-muted focus-visible:outline-none disabled:cursor-not-allowed\"\n />\n\n <span v-if=\"suffix\" class=\"shrink-0 select-none text-muted\">{{ suffix }}</span>\n\n <div v-if=\"showButtons\" class=\"ms-1 flex shrink-0 flex-col\">\n <NumberFieldIncrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-up\" :size=\"12\" />\n </NumberFieldIncrement>\n <NumberFieldDecrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-down\" :size=\"12\" />\n </NumberFieldDecrement>\n </div>\n </NumberFieldRoot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n NumberFieldDecrement,\n NumberFieldIncrement,\n NumberFieldInput,\n NumberFieldRoot,\n} from 'reka-ui'\nimport { computed, useAttrs } from 'vue'\nimport Icon from '../icon/Icon.vue'\nimport { mergeFormatOptions, toNumberOrNull } from '../../lib/number'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: number | null\n min?: number\n max?: number\n step?: number\n stepSnapping?: boolean\n integer?: boolean\n locale?: string\n formatOptions?: Intl.NumberFormatOptions\n currency?: string\n prefix?: string\n suffix?: string\n showButtons?: boolean\n placeholder?: string\n disabled?: boolean\n readonly?: boolean\n invalid?: boolean\n size?: 'sm' | 'default' | 'lg'\n id?: string\n name?: string\n }>(),\n { step: 1, size: 'default' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: number | null] }>()\nconst attrs = useAttrs()\n\n/** Never hand reka a non-positive or non-finite step; it would loop or divide by zero. */\nconst safeStep = computed(() => (Number.isFinite(props.step) && props.step > 0 ? props.step : 1))\n\nconst resolvedFormatOptions = computed(() =>\n mergeFormatOptions({\n currency: props.currency,\n formatOptions: props.formatOptions,\n integer: props.integer,\n }),\n)\n\n/** Locale-formatted value for `aria-valuetext`; `undefined` when empty. */\nconst valuetext = computed<string | undefined>(() => {\n if (props.modelValue == null) return undefined\n try {\n return new Intl.NumberFormat(props.locale, resolvedFormatOptions.value).format(props.modelValue)\n } catch {\n return undefined\n }\n})\n</script>\n\n<template>\n <div\n class=\"relative flex w-full items-center rounded-md border border-border bg-surface px-3 text-sm text-foreground shadow-sm transition-colors focus-within:ring-2 focus-within:ring-primary-500\"\n :class=\"[\n size === 'sm' ? 'h-8 text-xs' : size === 'lg' ? 'h-10' : 'h-9',\n invalid ? 'border-error-500 focus-within:ring-error-500' : '',\n disabled ? 'cursor-not-allowed opacity-50' : '',\n ]\"\n >\n <NumberFieldRoot\n :model-value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n :step=\"safeStep\"\n :step-snapping=\"stepSnapping\"\n :format-options=\"resolvedFormatOptions\"\n :locale=\"locale\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :id=\"id\"\n :name=\"name\"\n class=\"flex min-w-0 flex-1 items-center gap-1\"\n @update:model-value=\"emit('update:modelValue', toNumberOrNull($event))\"\n >\n <span v-if=\"prefix\" class=\"shrink-0 select-none text-muted\">{{ prefix }}</span>\n\n <NumberFieldInput\n v-bind=\"attrs\"\n :placeholder=\"placeholder\"\n :aria-invalid=\"invalid || undefined\"\n :aria-valuetext=\"valuetext\"\n class=\"min-w-0 flex-1 border-0 bg-transparent p-0 text-inherit outline-none placeholder:text-muted focus-visible:outline-none disabled:cursor-not-allowed\"\n />\n\n <span v-if=\"suffix\" class=\"shrink-0 select-none text-muted\">{{ suffix }}</span>\n\n <div v-if=\"showButtons\" class=\"ms-1 flex shrink-0 flex-col\">\n <NumberFieldIncrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-up\" :size=\"12\" />\n </NumberFieldIncrement>\n <NumberFieldDecrement\n class=\"flex size-4 items-center justify-center rounded text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Icon name=\"chevron-down\" :size=\"12\" />\n </NumberFieldDecrement>\n </div>\n </NumberFieldRoot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, useAttrs, watch } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n autoResize?: boolean\n maxRows?: number\n id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { rows: 3, invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst el = ref<HTMLTextAreaElement>()\nconst field = useFormField()\nconst capped = ref(false)\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\n\n/**\n * Grows the textarea to fit its content. Guarded so jsdom (where `scrollHeight`\n * is always 0) neither throws nor writes a `NaNpx` height.\n */\nfunction resize() {\n if (!props.autoResize || !el.value) return\n const node = el.value\n node.style.height = 'auto'\n const next = node.scrollHeight\n let height = next\n capped.value = false\n\n if (props.maxRows && next) {\n const lineHeight = parseFloat(getComputedStyle(node).lineHeight) || 0\n const max = props.maxRows * lineHeight\n if (max > 0 && next > max) {\n height = max\n capped.value = true\n }\n }\n\n node.style.height = next ? `${height}px` : ''\n}\n\nfunction onInput(event: Event) {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value)\n resize()\n}\n\nonMounted(resize)\nwatch(() => props.modelValue, resize, { flush: 'post' })\n</script>\n\n<template>\n <textarea\n ref=\"el\"\n :id=\"id\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 autoResize ? 'resize-none' : '',\n capped ? 'overflow-y-auto' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"onInput\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, useAttrs, watch } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number | null\n placeholder?: string\n disabled?: boolean\n rows?: number\n invalid?: boolean\n autoResize?: boolean\n maxRows?: number\n id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { rows: 3, invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\nconst attrs = useAttrs()\nconst el = ref<HTMLTextAreaElement>()\nconst field = useFormField()\nconst capped = ref(false)\n\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\n\n/**\n * Grows the textarea to fit its content. Guarded so jsdom (where `scrollHeight`\n * is always 0) neither throws nor writes a `NaNpx` height.\n */\nfunction resize() {\n if (!props.autoResize || !el.value) return\n const node = el.value\n node.style.height = 'auto'\n const next = node.scrollHeight\n let height = next\n capped.value = false\n\n if (props.maxRows && next) {\n const lineHeight = parseFloat(getComputedStyle(node).lineHeight) || 0\n const max = props.maxRows * lineHeight\n if (max > 0 && next > max) {\n height = max\n capped.value = true\n }\n }\n\n node.style.height = next ? `${height}px` : ''\n}\n\nfunction onInput(event: Event) {\n emit('update:modelValue', (event.target as HTMLTextAreaElement).value)\n resize()\n}\n\nonMounted(resize)\nwatch(() => props.modelValue, resize, { flush: 'post' })\n</script>\n\n<template>\n <textarea\n ref=\"el\"\n :id=\"id\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :rows=\"rows\"\n :required=\"required\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 autoResize ? 'resize-none' : '',\n capped ? 'overflow-y-auto' : '',\n ]\"\n v-bind=\"attrs\"\n @input=\"onInput\"\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 { computed } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = defineProps<{\n /** The id of the control this label belongs to. Falls back to the field context. */\n for?: string\n /** Renders an accessible-hidden required marker. */\n required?: boolean\n}>()\n\nconst field = useFormField()\nconst forId = computed(() => props.for ?? field?.id.value)\n</script>\n\n<template>\n <label :for=\"forId\" class=\"text-sm font-medium text-foreground text-start\">\n <slot />\n <span v-if=\"required\" class=\"text-error-600\" aria-hidden=\"true\">*</span>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useFormField } from '../../lib/formField'\n\nconst props = defineProps<{\n /** The id of the control this label belongs to. Falls back to the field context. */\n for?: string\n /** Renders an accessible-hidden required marker. */\n required?: boolean\n}>()\n\nconst field = useFormField()\nconst forId = computed(() => props.for ?? field?.id.value)\n</script>\n\n<template>\n <label :for=\"forId\" class=\"text-sm font-medium text-foreground text-start\">\n <slot />\n <span v-if=\"required\" class=\"text-error-600\" aria-hidden=\"true\">*</span>\n </label>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the description describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" class=\"text-sm text-muted\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the description describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" class=\"text-sm text-muted\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the message describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" role=\"alert\" class=\"text-sm text-error-600\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n /** The id of the element the message describes. */\n id?: string\n}>()\n</script>\n\n<template>\n <p v-if=\"$slots.default\" :id=\"id\" role=\"alert\" class=\"text-sm text-error-600\">\n <slot />\n </p>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUpdate, provide, ref, useId, useSlots } from 'vue'\nimport { formFieldKey } from '../../lib/formField'\nimport Label from '../label/Label.vue'\nimport FormDescription from './FormDescription.vue'\nimport FormMessage from './FormMessage.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** Label text; can also be supplied through the `label` slot. */\n label?: string\n /** Description text; rendered below the control when present. */\n description?: string\n /** Error text; marks the field invalid and renders an alert below the control. */\n error?: string\n /** Marks the field required (adds the label marker and context flag). */\n required?: boolean\n /** Overrides the invalid state. Defaults to `Boolean(error)`. */\n invalid?: boolean\n /** Explicit control id. Defaults to a stable generated id. */\n id?: string\n }>(),\n // An explicit `undefined` keeps Vue's Boolean casting from turning an absent\n // `invalid` into `false`, so `invalid` can fall through to `Boolean(error)`.\n { invalid: undefined },\n)\n\nconst slots = useSlots()\n\n// Slot functions are not reactive: Vue mutates the `slots` object in place\n// during the parent's update, which happens just before this component's\n// `onBeforeUpdate` hook. Bumping a version counter here invalidates `describedBy`\n// when a slot is added or removed after mount, so consumers re-read the\n// description/error ids instead of sticking to their initial value.\nconst slotsVersion = ref(0)\nonBeforeUpdate(() => {\n slotsVersion.value++\n})\n\n// `useId()` must run once, directly in setup — never inside a computed, which\n// could be evaluated in a different instance context.\nconst generatedId = useId()\nconst fieldId = computed(() => props.id ?? generatedId)\nconst invalid = computed(() => props.invalid ?? Boolean(props.error))\nconst required = computed(() => props.required ?? false)\n\n// Description/error content can come from a prop or a slot. `slotsVersion` is\n// read so slot-presence changes invalidate this computed; the template checks\n// `$slots` at render time for actually rendering the element.\nconst describedBy = computed(() => {\n void slotsVersion.value\n const ids: string[] = []\n if (props.description || slots.description) ids.push(`${fieldId.value}-description`)\n if (props.error || slots.error) ids.push(`${fieldId.value}-error`)\n return ids.length > 0 ? ids.join(' ') : undefined\n})\n\nprovide(formFieldKey, { id: fieldId, describedBy, invalid, required })\n</script>\n\n<template>\n <div class=\"grid gap-2\">\n <Label v-if=\"label || $slots.label\" :for=\"fieldId\" :required=\"required\">\n <slot name=\"label\">{{ label }}</slot>\n </Label>\n\n <slot />\n\n <FormDescription v-if=\"description || $slots.description\" :id=\"`${fieldId}-description`\">\n <slot name=\"description\">{{ description }}</slot>\n </FormDescription>\n\n <FormMessage v-if=\"error || $slots.error\" :id=\"`${fieldId}-error`\">\n <slot name=\"error\">{{ error }}</slot>\n </FormMessage>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUpdate, provide, ref, useId, useSlots } from 'vue'\nimport { formFieldKey } from '../../lib/formField'\nimport Label from '../label/Label.vue'\nimport FormDescription from './FormDescription.vue'\nimport FormMessage from './FormMessage.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** Label text; can also be supplied through the `label` slot. */\n label?: string\n /** Description text; rendered below the control when present. */\n description?: string\n /** Error text; marks the field invalid and renders an alert below the control. */\n error?: string\n /** Marks the field required (adds the label marker and context flag). */\n required?: boolean\n /** Overrides the invalid state. Defaults to `Boolean(error)`. */\n invalid?: boolean\n /** Explicit control id. Defaults to a stable generated id. */\n id?: string\n }>(),\n // An explicit `undefined` keeps Vue's Boolean casting from turning an absent\n // `invalid` into `false`, so `invalid` can fall through to `Boolean(error)`.\n { invalid: undefined },\n)\n\nconst slots = useSlots()\n\n// Slot functions are not reactive: Vue mutates the `slots` object in place\n// during the parent's update, which happens just before this component's\n// `onBeforeUpdate` hook. Bumping a version counter here invalidates `describedBy`\n// when a slot is added or removed after mount, so consumers re-read the\n// description/error ids instead of sticking to their initial value.\nconst slotsVersion = ref(0)\nonBeforeUpdate(() => {\n slotsVersion.value++\n})\n\n// `useId()` must run once, directly in setup — never inside a computed, which\n// could be evaluated in a different instance context.\nconst generatedId = useId()\nconst fieldId = computed(() => props.id ?? generatedId)\nconst invalid = computed(() => props.invalid ?? Boolean(props.error))\nconst required = computed(() => props.required ?? false)\n\n// Description/error content can come from a prop or a slot. `slotsVersion` is\n// read so slot-presence changes invalidate this computed; the template checks\n// `$slots` at render time for actually rendering the element.\nconst describedBy = computed(() => {\n void slotsVersion.value\n const ids: string[] = []\n if (props.description || slots.description) ids.push(`${fieldId.value}-description`)\n if (props.error || slots.error) ids.push(`${fieldId.value}-error`)\n return ids.length > 0 ? ids.join(' ') : undefined\n})\n\nprovide(formFieldKey, { id: fieldId, describedBy, invalid, required })\n</script>\n\n<template>\n <div class=\"grid gap-2\">\n <Label v-if=\"label || $slots.label\" :for=\"fieldId\" :required=\"required\">\n <slot name=\"label\">{{ label }}</slot>\n </Label>\n\n <slot />\n\n <FormDescription v-if=\"description || $slots.description\" :id=\"`${fieldId}-description`\">\n <slot name=\"description\">{{ description }}</slot>\n </FormDescription>\n\n <FormMessage v-if=\"error || $slots.error\" :id=\"`${fieldId}-error`\">\n <slot name=\"error\">{{ error }}</slot>\n </FormMessage>\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 dark:focus-visible:ring-offset-background 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 dark:focus-visible:ring-offset-background 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 { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nwithDefaults(\n defineProps<{\n tone?: Tone\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { tone: 'secondary', removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = Tone\n</script>\n\n<template>\n <span\n :class=\"[\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n toneClasses[tone].soft,\n ]\"\n >\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 dark:hover:bg-white/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 { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nwithDefaults(\n defineProps<{\n tone?: Tone\n icon?: string\n removable?: boolean\n removeLabel?: string\n }>(),\n { tone: 'secondary', removeLabel: 'Remove' },\n)\n\nconst emit = defineEmits<{ remove: [] }>()\n\nexport type TagTone = Tone\n</script>\n\n<template>\n <span\n :class=\"[\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium',\n toneClasses[tone].soft,\n ]\"\n >\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 dark:hover:bg-white/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 { onBeforeUnmount, onMounted, ref } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nexport type AlertVariant = 'soft' | 'outline'\n\nconst props = withDefaults(\n defineProps<{\n tone?: Tone\n title?: string\n description?: string\n icon?: string\n showIcon?: boolean\n closable?: boolean\n duration?: number\n closeLabel?: string\n variant?: AlertVariant\n }>(),\n {\n tone: 'info',\n showIcon: false,\n closable: false,\n closeLabel: 'Close',\n variant: 'soft',\n },\n)\n\nconst emit = defineEmits<{ close: [] }>()\n\n/** Fallback lucide name per tone, used when `showIcon` is set but `icon` is not. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n\nconst dismissed = ref(false)\nconst hovered = ref(false)\nconst focused = ref(false)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n/** Absolute ms timestamp when the active timer would fire. */\nlet deadline = 0\n/** Ms left when the timer was paused; drives resume. */\nlet remaining = 0\n\nfunction clearTimer() {\n if (timer !== undefined) {\n clearTimeout(timer)\n timer = undefined\n }\n}\n\nfunction start(ms: number) {\n clearTimer()\n if (ms <= 0) return\n remaining = ms\n deadline = Date.now() + ms\n timer = setTimeout(dismiss, ms)\n}\n\nfunction pause() {\n if (timer === undefined) return\n clearTimer()\n remaining = Math.max(0, deadline - Date.now())\n}\n\n/**\n * Re-arms the timer only once both pause sources are released. If the remaining\n * time floored to zero while paused, dismiss immediately instead of stranding.\n */\nfunction maybeResume() {\n if (dismissed.value || hovered.value || focused.value || timer !== undefined) return\n if (!props.duration || props.duration <= 0) return\n if (remaining <= 0) {\n dismiss()\n return\n }\n start(remaining)\n}\n\nfunction onEnter() {\n hovered.value = true\n pause()\n}\n\nfunction onLeave() {\n hovered.value = false\n maybeResume()\n}\n\nfunction onFocusIn() {\n focused.value = true\n pause()\n}\n\nfunction onFocusOut() {\n focused.value = false\n maybeResume()\n}\n\nfunction dismiss() {\n if (dismissed.value) return\n dismissed.value = true\n clearTimer()\n emit('close')\n}\n\nonMounted(() => {\n if (props.duration && props.duration > 0) start(props.duration)\n})\n\nonBeforeUnmount(clearTimer)\n</script>\n\n<template>\n <div\n v-if=\"!dismissed\"\n :role=\"toneClasses[tone].role\"\n :class=\"[\n 'flex w-full items-start gap-3 rounded-lg p-4 text-sm',\n toneClasses[tone][variant],\n ]\"\n @mouseenter=\"onEnter\"\n @mouseleave=\"onLeave\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot name=\"icon\">\n <Icon\n v-if=\"showIcon\"\n :name=\"icon || defaultIcons[tone]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[tone].icon]\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1\">\n <p v-if=\"title || $slots.title\" class=\"font-medium\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n <div\n v-if=\"description || $slots.description\"\n :class=\"['leading-relaxed', title || $slots.title ? 'mt-1' : '']\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </div>\n <slot />\n </div>\n\n <slot name=\"actions\" />\n\n <button\n v-if=\"closable\"\n type=\"button\"\n :aria-label=\"closeLabel\"\n class=\"-me-1 -mt-1 ms-auto shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"dismiss\"\n >\n <slot name=\"close\"><X class=\"size-4\" /></slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\n\nexport type AlertVariant = 'soft' | 'outline'\n\nconst props = withDefaults(\n defineProps<{\n tone?: Tone\n title?: string\n description?: string\n icon?: string\n showIcon?: boolean\n closable?: boolean\n duration?: number\n closeLabel?: string\n variant?: AlertVariant\n }>(),\n {\n tone: 'info',\n showIcon: false,\n closable: false,\n closeLabel: 'Close',\n variant: 'soft',\n },\n)\n\nconst emit = defineEmits<{ close: [] }>()\n\n/** Fallback lucide name per tone, used when `showIcon` is set but `icon` is not. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n\nconst dismissed = ref(false)\nconst hovered = ref(false)\nconst focused = ref(false)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\n/** Absolute ms timestamp when the active timer would fire. */\nlet deadline = 0\n/** Ms left when the timer was paused; drives resume. */\nlet remaining = 0\n\nfunction clearTimer() {\n if (timer !== undefined) {\n clearTimeout(timer)\n timer = undefined\n }\n}\n\nfunction start(ms: number) {\n clearTimer()\n if (ms <= 0) return\n remaining = ms\n deadline = Date.now() + ms\n timer = setTimeout(dismiss, ms)\n}\n\nfunction pause() {\n if (timer === undefined) return\n clearTimer()\n remaining = Math.max(0, deadline - Date.now())\n}\n\n/**\n * Re-arms the timer only once both pause sources are released. If the remaining\n * time floored to zero while paused, dismiss immediately instead of stranding.\n */\nfunction maybeResume() {\n if (dismissed.value || hovered.value || focused.value || timer !== undefined) return\n if (!props.duration || props.duration <= 0) return\n if (remaining <= 0) {\n dismiss()\n return\n }\n start(remaining)\n}\n\nfunction onEnter() {\n hovered.value = true\n pause()\n}\n\nfunction onLeave() {\n hovered.value = false\n maybeResume()\n}\n\nfunction onFocusIn() {\n focused.value = true\n pause()\n}\n\nfunction onFocusOut() {\n focused.value = false\n maybeResume()\n}\n\nfunction dismiss() {\n if (dismissed.value) return\n dismissed.value = true\n clearTimer()\n emit('close')\n}\n\nonMounted(() => {\n if (props.duration && props.duration > 0) start(props.duration)\n})\n\nonBeforeUnmount(clearTimer)\n</script>\n\n<template>\n <div\n v-if=\"!dismissed\"\n :role=\"toneClasses[tone].role\"\n :class=\"[\n 'flex w-full items-start gap-3 rounded-lg p-4 text-sm',\n toneClasses[tone][variant],\n ]\"\n @mouseenter=\"onEnter\"\n @mouseleave=\"onLeave\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot name=\"icon\">\n <Icon\n v-if=\"showIcon\"\n :name=\"icon || defaultIcons[tone]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[tone].icon]\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1\">\n <p v-if=\"title || $slots.title\" class=\"font-medium\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n <div\n v-if=\"description || $slots.description\"\n :class=\"['leading-relaxed', title || $slots.title ? 'mt-1' : '']\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </div>\n <slot />\n </div>\n\n <slot name=\"actions\" />\n\n <button\n v-if=\"closable\"\n type=\"button\"\n :aria-label=\"closeLabel\"\n class=\"-me-1 -mt-1 ms-auto shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"dismiss\"\n >\n <slot name=\"close\"><X class=\"size-4\" /></slot>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport { cn } from '../../lib/cn'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n tone?: Tone\n }>(),\n { size: 'default', label: 'Loading…', tone: 'info' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'size-4',\n default: 'size-5',\n lg: 'size-6',\n}\n\nconst classes = computed(() => cn('inline-flex items-center', toneClasses[props.tone].icon))\n</script>\n\n<template>\n <span role=\"status\" aria-live=\"polite\" :class=\"classes\">\n <Icon\n name=\"loader-circle\"\n :class=\"cn('animate-spin', SIZE_CLASSES[size])\"\n aria-hidden=\"true\"\n />\n <span class=\"sr-only\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport { cn } from '../../lib/cn'\nimport Icon from '../icon/Icon.vue'\n\nconst props = withDefaults(\n defineProps<{\n size?: 'sm' | 'default' | 'lg'\n label?: string\n tone?: Tone\n }>(),\n { size: 'default', label: 'Loading…', tone: 'info' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg', string> = {\n sm: 'size-4',\n default: 'size-5',\n lg: 'size-6',\n}\n\nconst classes = computed(() => cn('inline-flex items-center', toneClasses[props.tone].icon))\n</script>\n\n<template>\n <span role=\"status\" aria-live=\"polite\" :class=\"classes\">\n <Icon\n name=\"loader-circle\"\n :class=\"cn('animate-spin', SIZE_CLASSES[size])\"\n aria-hidden=\"true\"\n />\n <span class=\"sr-only\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\n\ndefineOptions({ inheritAttrs: false })\n\nconst skeleton = tv({\n base: 'animate-pulse bg-surface-muted',\n variants: {\n rounded: {\n none: '',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n },\n },\n defaultVariants: { rounded: 'md' },\n})\n\nwithDefaults(\n defineProps<{\n rounded?: VariantProps<typeof skeleton>['rounded']\n width?: string\n height?: string\n }>(),\n { rounded: 'md' },\n)\n</script>\n\n<template>\n <div :class=\"skeleton({ rounded })\" :style=\"{ width, height }\" v-bind=\"$attrs\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { tv, type VariantProps } from 'tailwind-variants'\n\ndefineOptions({ inheritAttrs: false })\n\nconst skeleton = tv({\n base: 'animate-pulse bg-surface-muted',\n variants: {\n rounded: {\n none: '',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n },\n },\n defaultVariants: { rounded: 'md' },\n})\n\nwithDefaults(\n defineProps<{\n rounded?: VariantProps<typeof skeleton>['rounded']\n width?: string\n height?: string\n }>(),\n { rounded: 'md' },\n)\n</script>\n\n<template>\n <div :class=\"skeleton({ rounded })\" :style=\"{ width, height }\" v-bind=\"$attrs\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { cn } from '../../lib/cn'\nimport { toneClasses } from '../../lib/tones'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n src?: string\n alt?: string\n name?: string\n initials?: string\n size?: 'sm' | 'default' | 'lg' | 'xl'\n }>(),\n { size: 'default' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg' | 'xl', string> = {\n sm: 'size-6 text-xs',\n default: 'size-8 text-sm',\n lg: 'size-10 text-base',\n xl: 'size-14 text-lg',\n}\n\nfunction deriveInitials(name?: string): string {\n if (!name) return ''\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => word.charAt(0))\n .join('')\n .toUpperCase()\n}\n\nconst initials = computed(() => props.initials ?? deriveInitials(props.name))\nconst sizeClass = computed(() => SIZE_CLASSES[props.size])\n\n// `role=\"img\"` requires a non-empty accessible name, so only expose the\n// fallback as an image when one is available.\nconst accessibleName = computed(() => {\n const label = props.alt ?? props.name ?? initials.value\n return label === '' ? undefined : label\n})\n\nconst errored = ref(false)\nwatch(\n () => props.src,\n () => {\n errored.value = false\n },\n)\n</script>\n\n<template>\n <img\n v-if=\"src && !errored\"\n v-bind=\"$attrs\"\n :src=\"src\"\n :alt=\"alt ?? name ?? ''\"\n :class=\"cn(sizeClass, 'shrink-0 rounded-full object-cover')\"\n @error=\"errored = true\"\n />\n <span\n v-else\n v-bind=\"$attrs\"\n :role=\"accessibleName ? 'img' : undefined\"\n :aria-label=\"accessibleName\"\n :class=\"\n cn(\n sizeClass,\n toneClasses.info.soft,\n 'inline-flex shrink-0 items-center justify-center rounded-full font-medium',\n )\n \"\n >{{ initials }}</span\n >\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { cn } from '../../lib/cn'\nimport { toneClasses } from '../../lib/tones'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n src?: string\n alt?: string\n name?: string\n initials?: string\n size?: 'sm' | 'default' | 'lg' | 'xl'\n }>(),\n { size: 'default' },\n)\n\nconst SIZE_CLASSES: Record<'sm' | 'default' | 'lg' | 'xl', string> = {\n sm: 'size-6 text-xs',\n default: 'size-8 text-sm',\n lg: 'size-10 text-base',\n xl: 'size-14 text-lg',\n}\n\nfunction deriveInitials(name?: string): string {\n if (!name) return ''\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => word.charAt(0))\n .join('')\n .toUpperCase()\n}\n\nconst initials = computed(() => props.initials ?? deriveInitials(props.name))\nconst sizeClass = computed(() => SIZE_CLASSES[props.size])\n\n// `role=\"img\"` requires a non-empty accessible name, so only expose the\n// fallback as an image when one is available.\nconst accessibleName = computed(() => {\n const label = props.alt ?? props.name ?? initials.value\n return label === '' ? undefined : label\n})\n\nconst errored = ref(false)\nwatch(\n () => props.src,\n () => {\n errored.value = false\n },\n)\n</script>\n\n<template>\n <img\n v-if=\"src && !errored\"\n v-bind=\"$attrs\"\n :src=\"src\"\n :alt=\"alt ?? name ?? ''\"\n :class=\"cn(sizeClass, 'shrink-0 rounded-full object-cover')\"\n @error=\"errored = true\"\n />\n <span\n v-else\n v-bind=\"$attrs\"\n :role=\"accessibleName ? 'img' : undefined\"\n :aria-label=\"accessibleName\"\n :class=\"\n cn(\n sizeClass,\n toneClasses.info.soft,\n 'inline-flex shrink-0 items-center justify-center rounded-full font-medium',\n )\n \"\n >{{ initials }}</span\n >\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 SelectPortal,\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'\nimport { useFormField } from '../../lib/formField'\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 id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst field = useFormField()\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :required=\"required || undefined\"\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 :id=\"id\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 <SelectPortal>\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 </SelectPortal>\n </SelectRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n SelectContent,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectPortal,\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'\nimport { useFormField } from '../../lib/formField'\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 id?: string\n required?: boolean\n }>(),\n // `invalid`/`required` default to `undefined` (not `false`) so Vue's Boolean\n // casting does not swallow them and they can fall through to the form field.\n { optionLabel: 'label', optionValue: 'value', placeholder: '', size: 'default', invalid: undefined, required: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nconst field = useFormField()\nconst id = computed(() => props.id ?? field?.id.value)\nconst invalid = computed(() => props.invalid ?? field?.invalid.value ?? false)\nconst required = computed(() => props.required ?? field?.required.value ?? false)\nconst describedBy = computed(() => field?.describedBy.value)\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 :required=\"required || undefined\"\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 :id=\"id\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\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 <SelectPortal>\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 </SelectPortal>\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, useSlots, watch, type VNode } from 'vue'\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport {\n buildHourOptions,\n buildMinuteOptions,\n clampTime,\n from12Hour,\n sortRange,\n to12Hour,\n toTime,\n} from '../../lib/date'\nimport {\n formatLocalizedDate,\n formatLocalizedTime,\n getFirstDayOfWeek,\n getMonthLabel,\n getWeekdayLabels,\n} from '../../lib/locale'\n\nexport interface DatePickerLabels {\n placeholder: string\n previousMonth: string\n nextMonth: string\n clear: string\n apply: string\n today: string\n time: string\n hour: string\n minute: string\n am: string\n pm: string\n}\n\nconst LABELS: Record<string, DatePickerLabels> = {\n en: {\n placeholder: 'Select date',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n clear: 'Clear',\n apply: 'Apply',\n today: 'Today',\n time: 'Time',\n hour: 'Hour',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n fr: {\n placeholder: 'Choisir une date',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n clear: 'Effacer',\n apply: 'Appliquer',\n today: \"Aujourd'hui\",\n time: 'Heure',\n hour: 'Heure',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n es: {\n placeholder: 'Seleccionar fecha',\n previousMonth: 'Mes anterior',\n nextMonth: 'Mes siguiente',\n clear: 'Borrar',\n apply: 'Aplicar',\n today: 'Hoy',\n time: 'Hora',\n hour: 'Hora',\n minute: 'Minuto',\n am: 'AM',\n pm: 'PM',\n },\n de: {\n placeholder: 'Datum wählen',\n previousMonth: 'Vorheriger Monat',\n nextMonth: 'Nächster Monat',\n clear: 'Löschen',\n apply: 'Übernehmen',\n today: 'Heute',\n time: 'Uhrzeit',\n hour: 'Stunde',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n ar: {\n placeholder: 'اختر التاريخ',\n previousMonth: 'الشهر السابق',\n nextMonth: 'الشهر التالي',\n clear: 'مسح',\n apply: 'تطبيق',\n today: 'اليوم',\n time: 'الوقت',\n hour: 'الساعة',\n minute: 'الدقيقة',\n am: 'ص',\n pm: 'م',\n },\n}\n\nfunction defaultLabels(locale: string): DatePickerLabels {\n const lang = locale.toLowerCase().split(/[-_]/)[0]\n return LABELS[lang] ?? LABELS.en\n}\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n /** @deprecated Prefer `labels.placeholder`; kept for the existing trigger API. */\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 hourFormat?: '12' | '24'\n minuteStep?: number\n locale?: string\n labels?: Partial<DatePickerLabels>\n weekStartsOn?: number\n defaultOpen?: boolean\n }>(),\n {\n mode: 'date',\n size: 'default',\n hourFormat: '24',\n minuteStep: 1,\n // Runtime locale, best-effort, falling back to English. Inlined because\n // `withDefaults` is hoisted and cannot reference local declarations.\n locale: () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().locale || 'en'\n } catch {\n return 'en'\n }\n },\n defaultOpen: false,\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst slots = useSlots()\n\nconst open = ref(props.defaultOpen ?? 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 effectiveLocale = computed(() => props.locale || 'en')\n\nconst resolvedLabels = computed<DatePickerLabels>(() => ({\n ...defaultLabels(effectiveLocale.value),\n // The legacy `placeholder` prop fills in only when the new labels API has no\n // value; `labels.placeholder` is spread last so it wins over both.\n ...(props.placeholder !== undefined ? { placeholder: props.placeholder } : {}),\n ...props.labels,\n}))\n\nfunction flatten(node: unknown): string {\n if (node == null || typeof node === 'boolean') return ''\n if (typeof node === 'string' || typeof node === 'number') return String(node)\n if (Array.isArray(node)) return node.map(flatten).join('')\n const vnode = node as VNode\n if (typeof vnode.children === 'string') return vnode.children\n if (Array.isArray(vnode.children)) return vnode.children.map(flatten).join('')\n return ''\n}\n\n/** `label-<key>` slot text when supplied, otherwise the resolved label. */\nfunction labelFor(key: keyof DatePickerLabels): string {\n const slot = slots[`label-${key}`]\n if (slot) {\n const text = slot().map(flatten).join('').trim()\n if (text) return text\n }\n return resolvedLabels.value[key]\n}\n\nconst weekStartsOn = computed(() => props.weekStartsOn ?? getFirstDayOfWeek(effectiveLocale.value))\nconst weekdayLabels = computed(() => getWeekdayLabels(effectiveLocale.value, weekStartsOn.value))\nconst monthLabel = computed(() => getMonthLabel(viewDate.value, effectiveLocale.value))\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() - weekStartsOn.value + 7) % 7\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 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 parsedTime = computed(() => {\n const [h, m] = time.value.split(':').map(Number)\n return {\n hour24: Number.isFinite(h) ? ((Math.trunc(h) % 24) + 24) % 24 : 0,\n minute: Number.isFinite(m) ? ((Math.trunc(m) % 60) + 60) % 60 : 0,\n }\n})\n\nconst hourOptions = computed(() => buildHourOptions(props.hourFormat))\nconst minuteOptions = computed(() =>\n buildMinuteOptions(Math.min(30, Math.max(1, props.minuteStep ?? 1))),\n)\n\nconst selectedHour = computed<number>({\n get: () =>\n props.hourFormat === '12' ? to12Hour(parsedTime.value.hour24).hour : parsedTime.value.hour24,\n set: (value) => {\n const { hour24, minute } = parsedTime.value\n const next =\n props.hourFormat === '12' ? from12Hour(value, to12Hour(hour24).meridiem) : value\n time.value = toTime(next * 60 + minute)\n },\n})\n\nconst selectedMinute = computed<number>({\n get: () => parsedTime.value.minute,\n set: (value) => {\n time.value = toTime(parsedTime.value.hour24 * 60 + value)\n },\n})\n\nconst selectedMeridiem = computed<'am' | 'pm'>({\n get: () => to12Hour(parsedTime.value.hour24).meridiem,\n set: (value) => {\n const { hour } = to12Hour(parsedTime.value.hour24)\n time.value = toTime(from12Hour(hour, value) * 60 + parsedTime.value.minute)\n },\n})\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0')\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 `${formatLocalizedDate(s, effectiveLocale.value)} – ${formatLocalizedDate(e, effectiveLocale.value)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n if (props.mode === 'datetime') {\n return `${formatLocalizedDate(d, effectiveLocale.value)} ${formatLocalizedTime(d, effectiveLocale.value, props.hourFormat)}`\n }\n return formatLocalizedDate(d, effectiveLocale.value)\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 || labelFor('placeholder') }}</span>\n <CalendarIcon class=\"size-4 shrink-0 text-muted\" />\n </button>\n </PopoverTrigger>\n <PopoverPortal>\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=\"labelFor('previousMonth')\"\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 rtl:rotate-180\" />\n </button>\n <span data-test=\"month-label\" class=\"text-sm font-medium\">{{ monthLabel }}</span>\n <button\n type=\"button\"\n :aria-label=\"labelFor('nextMonth')\"\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 rtl:rotate-180\" />\n </button>\n </div>\n\n <div data-test=\"weekdays\" class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"(d, i) in weekdayLabels\" :key=\"i\" class=\"py-1 font-medium text-muted\">\n {{ d }}\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 dark:bg-primary-900/40 dark:text-primary-200' : '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 <div role=\"group\" :aria-label=\"labelFor('time')\" class=\"flex items-center gap-1.5 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <select\n v-model.number=\"selectedHour\"\n data-test=\"hours\"\n :aria-label=\"labelFor('hour')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"h in hourOptions\" :key=\"h\" :value=\"h\">\n {{ hourFormat === '12' ? h : pad(h) }}\n </option>\n </select>\n <span aria-hidden=\"true\">:</span>\n <select\n v-model.number=\"selectedMinute\"\n data-test=\"minutes\"\n :aria-label=\"labelFor('minute')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"m in minuteOptions\" :key=\"m\" :value=\"m\">{{ pad(m) }}</option>\n </select>\n <select\n v-if=\"hourFormat === '12'\"\n v-model=\"selectedMeridiem\"\n data-test=\"meridiem\"\n :aria-label=\"labelFor('time')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option value=\"am\">{{ labelFor('am') }}</option>\n <option value=\"pm\">{{ labelFor('pm') }}</option>\n </select>\n </div>\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 {{ labelFor('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 {{ labelFor('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 {{ labelFor('clear') }}\n </button>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useSlots, watch, type VNode } from 'vue'\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'\nimport { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Clock } from 'lucide-vue-next'\nimport {\n buildHourOptions,\n buildMinuteOptions,\n clampTime,\n from12Hour,\n sortRange,\n to12Hour,\n toTime,\n} from '../../lib/date'\nimport {\n formatLocalizedDate,\n formatLocalizedTime,\n getFirstDayOfWeek,\n getMonthLabel,\n getWeekdayLabels,\n} from '../../lib/locale'\n\nexport interface DatePickerLabels {\n placeholder: string\n previousMonth: string\n nextMonth: string\n clear: string\n apply: string\n today: string\n time: string\n hour: string\n minute: string\n am: string\n pm: string\n}\n\nconst LABELS: Record<string, DatePickerLabels> = {\n en: {\n placeholder: 'Select date',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n clear: 'Clear',\n apply: 'Apply',\n today: 'Today',\n time: 'Time',\n hour: 'Hour',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n fr: {\n placeholder: 'Choisir une date',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n clear: 'Effacer',\n apply: 'Appliquer',\n today: \"Aujourd'hui\",\n time: 'Heure',\n hour: 'Heure',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n es: {\n placeholder: 'Seleccionar fecha',\n previousMonth: 'Mes anterior',\n nextMonth: 'Mes siguiente',\n clear: 'Borrar',\n apply: 'Aplicar',\n today: 'Hoy',\n time: 'Hora',\n hour: 'Hora',\n minute: 'Minuto',\n am: 'AM',\n pm: 'PM',\n },\n de: {\n placeholder: 'Datum wählen',\n previousMonth: 'Vorheriger Monat',\n nextMonth: 'Nächster Monat',\n clear: 'Löschen',\n apply: 'Übernehmen',\n today: 'Heute',\n time: 'Uhrzeit',\n hour: 'Stunde',\n minute: 'Minute',\n am: 'AM',\n pm: 'PM',\n },\n ar: {\n placeholder: 'اختر التاريخ',\n previousMonth: 'الشهر السابق',\n nextMonth: 'الشهر التالي',\n clear: 'مسح',\n apply: 'تطبيق',\n today: 'اليوم',\n time: 'الوقت',\n hour: 'الساعة',\n minute: 'الدقيقة',\n am: 'ص',\n pm: 'م',\n },\n}\n\nfunction defaultLabels(locale: string): DatePickerLabels {\n const lang = locale.toLowerCase().split(/[-_]/)[0]\n return LABELS[lang] ?? LABELS.en\n}\n\nconst props = withDefaults(\n defineProps<{\n mode?: 'date' | 'range' | 'datetime'\n modelValue?: Date | [Date, Date] | null\n /** @deprecated Prefer `labels.placeholder`; kept for the existing trigger API. */\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 hourFormat?: '12' | '24'\n minuteStep?: number\n locale?: string\n labels?: Partial<DatePickerLabels>\n weekStartsOn?: number\n defaultOpen?: boolean\n }>(),\n {\n mode: 'date',\n size: 'default',\n hourFormat: '24',\n minuteStep: 1,\n // Runtime locale, best-effort, falling back to English. Inlined because\n // `withDefaults` is hoisted and cannot reference local declarations.\n locale: () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().locale || 'en'\n } catch {\n return 'en'\n }\n },\n defaultOpen: false,\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: Date | [Date, Date] | null] }>()\n\nconst slots = useSlots()\n\nconst open = ref(props.defaultOpen ?? 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 effectiveLocale = computed(() => props.locale || 'en')\n\nconst resolvedLabels = computed<DatePickerLabels>(() => ({\n ...defaultLabels(effectiveLocale.value),\n // The legacy `placeholder` prop fills in only when the new labels API has no\n // value; `labels.placeholder` is spread last so it wins over both.\n ...(props.placeholder !== undefined ? { placeholder: props.placeholder } : {}),\n ...props.labels,\n}))\n\nfunction flatten(node: unknown): string {\n if (node == null || typeof node === 'boolean') return ''\n if (typeof node === 'string' || typeof node === 'number') return String(node)\n if (Array.isArray(node)) return node.map(flatten).join('')\n const vnode = node as VNode\n if (typeof vnode.children === 'string') return vnode.children\n if (Array.isArray(vnode.children)) return vnode.children.map(flatten).join('')\n return ''\n}\n\n/** `label-<key>` slot text when supplied, otherwise the resolved label. */\nfunction labelFor(key: keyof DatePickerLabels): string {\n const slot = slots[`label-${key}`]\n if (slot) {\n const text = slot().map(flatten).join('').trim()\n if (text) return text\n }\n return resolvedLabels.value[key]\n}\n\nconst weekStartsOn = computed(() => props.weekStartsOn ?? getFirstDayOfWeek(effectiveLocale.value))\nconst weekdayLabels = computed(() => getWeekdayLabels(effectiveLocale.value, weekStartsOn.value))\nconst monthLabel = computed(() => getMonthLabel(viewDate.value, effectiveLocale.value))\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() - weekStartsOn.value + 7) % 7\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 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 parsedTime = computed(() => {\n const [h, m] = time.value.split(':').map(Number)\n return {\n hour24: Number.isFinite(h) ? ((Math.trunc(h) % 24) + 24) % 24 : 0,\n minute: Number.isFinite(m) ? ((Math.trunc(m) % 60) + 60) % 60 : 0,\n }\n})\n\nconst hourOptions = computed(() => buildHourOptions(props.hourFormat))\nconst minuteOptions = computed(() =>\n buildMinuteOptions(Math.min(30, Math.max(1, props.minuteStep ?? 1))),\n)\n\nconst selectedHour = computed<number>({\n get: () =>\n props.hourFormat === '12' ? to12Hour(parsedTime.value.hour24).hour : parsedTime.value.hour24,\n set: (value) => {\n const { hour24, minute } = parsedTime.value\n const next =\n props.hourFormat === '12' ? from12Hour(value, to12Hour(hour24).meridiem) : value\n time.value = toTime(next * 60 + minute)\n },\n})\n\nconst selectedMinute = computed<number>({\n get: () => parsedTime.value.minute,\n set: (value) => {\n time.value = toTime(parsedTime.value.hour24 * 60 + value)\n },\n})\n\nconst selectedMeridiem = computed<'am' | 'pm'>({\n get: () => to12Hour(parsedTime.value.hour24).meridiem,\n set: (value) => {\n const { hour } = to12Hour(parsedTime.value.hour24)\n time.value = toTime(from12Hour(hour, value) * 60 + parsedTime.value.minute)\n },\n})\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0')\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 `${formatLocalizedDate(s, effectiveLocale.value)} – ${formatLocalizedDate(e, effectiveLocale.value)}`\n }\n if (!start.value) return ''\n const d = props.mode === 'datetime' ? clampTime(start.value, time.value) : start.value\n if (props.mode === 'datetime') {\n return `${formatLocalizedDate(d, effectiveLocale.value)} ${formatLocalizedTime(d, effectiveLocale.value, props.hourFormat)}`\n }\n return formatLocalizedDate(d, effectiveLocale.value)\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 || labelFor('placeholder') }}</span>\n <CalendarIcon class=\"size-4 shrink-0 text-muted\" />\n </button>\n </PopoverTrigger>\n <PopoverPortal>\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=\"labelFor('previousMonth')\"\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 rtl:rotate-180\" />\n </button>\n <span data-test=\"month-label\" class=\"text-sm font-medium\">{{ monthLabel }}</span>\n <button\n type=\"button\"\n :aria-label=\"labelFor('nextMonth')\"\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 rtl:rotate-180\" />\n </button>\n </div>\n\n <div data-test=\"weekdays\" class=\"mt-2 grid grid-cols-7 gap-0.5 text-center text-xs\">\n <span v-for=\"(d, i) in weekdayLabels\" :key=\"i\" class=\"py-1 font-medium text-muted\">\n {{ d }}\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 dark:bg-primary-900/40 dark:text-primary-200' : '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 <div role=\"group\" :aria-label=\"labelFor('time')\" class=\"flex items-center gap-1.5 text-xs text-muted\">\n <Clock class=\"size-3.5\" />\n <select\n v-model.number=\"selectedHour\"\n data-test=\"hours\"\n :aria-label=\"labelFor('hour')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"h in hourOptions\" :key=\"h\" :value=\"h\">\n {{ hourFormat === '12' ? h : pad(h) }}\n </option>\n </select>\n <span aria-hidden=\"true\">:</span>\n <select\n v-model.number=\"selectedMinute\"\n data-test=\"minutes\"\n :aria-label=\"labelFor('minute')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option v-for=\"m in minuteOptions\" :key=\"m\" :value=\"m\">{{ pad(m) }}</option>\n </select>\n <select\n v-if=\"hourFormat === '12'\"\n v-model=\"selectedMeridiem\"\n data-test=\"meridiem\"\n :aria-label=\"labelFor('time')\"\n class=\"rounded border border-border bg-surface px-1.5 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <option value=\"am\">{{ labelFor('am') }}</option>\n <option value=\"pm\">{{ labelFor('pm') }}</option>\n </select>\n </div>\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 {{ labelFor('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 {{ labelFor('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 {{ labelFor('clear') }}\n </button>\n </div>\n </PopoverContent>\n </PopoverPortal>\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 dark:bg-black/70\" />\n <DialogContent\n :class=\"[\n 'fixed left-1/2 top-1/2 z-50 flex flex-col 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 shrink-0 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=\"flex-1 overflow-y-auto bg-surface p-5\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"flex shrink-0 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 dark:bg-black/70\" />\n <DialogContent\n :class=\"[\n 'fixed left-1/2 top-1/2 z-50 flex flex-col 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 shrink-0 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=\"flex-1 overflow-y-auto bg-surface p-5\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"flex shrink-0 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 VisuallyHidden,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nexport type DrawerPosition = 'left' | 'right' | 'top' | 'bottom' | 'start' | 'end'\nexport type DrawerSize = 'sm' | 'md' | 'lg' | 'full'\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean\n position?: DrawerPosition\n size?: DrawerSize\n backdrop?: boolean\n closeOnEscape?: boolean\n closeOnOutside?: boolean\n title?: string\n description?: string\n showClose?: boolean\n preventScroll?: boolean\n }>(),\n {\n open: false,\n position: 'right',\n size: 'md',\n backdrop: true,\n closeOnEscape: true,\n closeOnOutside: true,\n showClose: true,\n preventScroll: true,\n },\n)\n\nconst emit = defineEmits<{ 'update:open': [value: boolean]; open: []; close: [] }>()\n\nconst open = computed({\n get: () => props.open,\n set: (value: boolean) => emit('update:open', value),\n})\n\nfunction onOpenChange(value: boolean) {\n emit('update:open', value)\n if (value) emit('open')\n else emit('close')\n}\n\n/**\n * Reka dismisses on Escape itself; cancelling the default is what blocks the\n * dismissal, so we only preventDefault when the consumer opted out.\n */\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n/** Same contract for outside pointer/focus/inert dismissal. */\nfunction onPointerDownOutside(event: Event) {\n if (!props.closeOnOutside) event.preventDefault()\n}\n\n/** Physical `left`/`right`; `start`/`end` mirror them and flip in RTL. */\nconst positionClasses: Record<DrawerPosition, string> = {\n right: 'inset-y-0 right-0 h-full w-full data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n left: 'inset-y-0 left-0 h-full w-full data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n end: 'inset-y-0 end-0 h-full w-full data-[state=closed]:translate-x-full rtl:data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n start: 'inset-y-0 start-0 h-full w-full data-[state=closed]:-translate-x-full rtl:data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n top: 'inset-x-0 top-0 w-full h-full data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0',\n bottom: 'inset-x-0 bottom-0 w-full h-full data-[state=closed]:translate-y-full data-[state=open]:translate-y-0',\n}\n\nconst horizontalSizes: Record<DrawerSize, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n full: 'max-w-full',\n}\n\nconst verticalSizes: Record<DrawerSize, string> = {\n sm: 'max-h-64',\n md: 'max-h-96',\n lg: 'max-h-[32rem]',\n full: 'max-h-full',\n}\n\nconst isVertical = computed(() => props.position === 'top' || props.position === 'bottom')\nconst sizeClass = computed(() => (isVertical.value ? verticalSizes[props.size] : horizontalSizes[props.size]))\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 <!--\n `force-mount` mirrors `open` so the portal's first render is synchronous when\n the drawer starts open (reka's Teleport defers its children until mounted).\n Once mounted the portal stays put, so presence/animation still work on close.\n -->\n <DialogPortal :force-mount=\"open\">\n <DialogOverlay\n v-if=\"backdrop || preventScroll\"\n :class=\"['fixed inset-0 z-50', backdrop ? 'bg-black/50 dark:bg-black/70' : 'bg-transparent']\"\n />\n <DialogContent\n :class=\"[\n 'fixed z-50 flex flex-col overflow-hidden border-border bg-surface shadow-dialog transition-transform duration-200 focus-visible:outline-none',\n positionClasses[position],\n sizeClass,\n ]\"\n @escape-key-down=\"onEscapeKeyDown\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <VisuallyHidden v-if=\"!title && !$slots.header\">\n <DialogTitle>Drawer</DialogTitle>\n </VisuallyHidden>\n\n <header\n v-if=\"title || $slots.header || description || $slots.description || showClose\"\n class=\"flex shrink-0 items-start justify-between gap-4 border-b border-border p-5 pb-4\"\n >\n <div class=\"min-w-0\">\n <DialogTitle\n v-if=\"title || $slots.header\"\n class=\"text-lg font-semibold text-foreground\"\n >\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription\n v-if=\"description || $slots.description\"\n class=\"mt-1 text-sm text-muted\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n v-if=\"showClose\"\n class=\"ms-auto shrink-0 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 <slot name=\"close\"><X class=\"size-4\" /></slot>\n </DialogClose>\n </header>\n\n <div class=\"flex-1 overflow-y-auto p-5\">\n <slot />\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"shrink-0 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </footer>\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 VisuallyHidden,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\n\nexport type DrawerPosition = 'left' | 'right' | 'top' | 'bottom' | 'start' | 'end'\nexport type DrawerSize = 'sm' | 'md' | 'lg' | 'full'\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean\n position?: DrawerPosition\n size?: DrawerSize\n backdrop?: boolean\n closeOnEscape?: boolean\n closeOnOutside?: boolean\n title?: string\n description?: string\n showClose?: boolean\n preventScroll?: boolean\n }>(),\n {\n open: false,\n position: 'right',\n size: 'md',\n backdrop: true,\n closeOnEscape: true,\n closeOnOutside: true,\n showClose: true,\n preventScroll: true,\n },\n)\n\nconst emit = defineEmits<{ 'update:open': [value: boolean]; open: []; close: [] }>()\n\nconst open = computed({\n get: () => props.open,\n set: (value: boolean) => emit('update:open', value),\n})\n\nfunction onOpenChange(value: boolean) {\n emit('update:open', value)\n if (value) emit('open')\n else emit('close')\n}\n\n/**\n * Reka dismisses on Escape itself; cancelling the default is what blocks the\n * dismissal, so we only preventDefault when the consumer opted out.\n */\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n/** Same contract for outside pointer/focus/inert dismissal. */\nfunction onPointerDownOutside(event: Event) {\n if (!props.closeOnOutside) event.preventDefault()\n}\n\n/** Physical `left`/`right`; `start`/`end` mirror them and flip in RTL. */\nconst positionClasses: Record<DrawerPosition, string> = {\n right: 'inset-y-0 right-0 h-full w-full data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n left: 'inset-y-0 left-0 h-full w-full data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n end: 'inset-y-0 end-0 h-full w-full data-[state=closed]:translate-x-full rtl:data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',\n start: 'inset-y-0 start-0 h-full w-full data-[state=closed]:-translate-x-full rtl:data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n top: 'inset-x-0 top-0 w-full h-full data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0',\n bottom: 'inset-x-0 bottom-0 w-full h-full data-[state=closed]:translate-y-full data-[state=open]:translate-y-0',\n}\n\nconst horizontalSizes: Record<DrawerSize, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n full: 'max-w-full',\n}\n\nconst verticalSizes: Record<DrawerSize, string> = {\n sm: 'max-h-64',\n md: 'max-h-96',\n lg: 'max-h-[32rem]',\n full: 'max-h-full',\n}\n\nconst isVertical = computed(() => props.position === 'top' || props.position === 'bottom')\nconst sizeClass = computed(() => (isVertical.value ? verticalSizes[props.size] : horizontalSizes[props.size]))\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 <!--\n `force-mount` mirrors `open` so the portal's first render is synchronous when\n the drawer starts open (reka's Teleport defers its children until mounted).\n Once mounted the portal stays put, so presence/animation still work on close.\n -->\n <DialogPortal :force-mount=\"open\">\n <DialogOverlay\n v-if=\"backdrop || preventScroll\"\n :class=\"['fixed inset-0 z-50', backdrop ? 'bg-black/50 dark:bg-black/70' : 'bg-transparent']\"\n />\n <DialogContent\n :class=\"[\n 'fixed z-50 flex flex-col overflow-hidden border-border bg-surface shadow-dialog transition-transform duration-200 focus-visible:outline-none',\n positionClasses[position],\n sizeClass,\n ]\"\n @escape-key-down=\"onEscapeKeyDown\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <VisuallyHidden v-if=\"!title && !$slots.header\">\n <DialogTitle>Drawer</DialogTitle>\n </VisuallyHidden>\n\n <header\n v-if=\"title || $slots.header || description || $slots.description || showClose\"\n class=\"flex shrink-0 items-start justify-between gap-4 border-b border-border p-5 pb-4\"\n >\n <div class=\"min-w-0\">\n <DialogTitle\n v-if=\"title || $slots.header\"\n class=\"text-lg font-semibold text-foreground\"\n >\n <slot name=\"header\">{{ title }}</slot>\n </DialogTitle>\n <DialogDescription\n v-if=\"description || $slots.description\"\n class=\"mt-1 text-sm text-muted\"\n >\n <slot name=\"description\">{{ description }}</slot>\n </DialogDescription>\n </div>\n <DialogClose\n v-if=\"showClose\"\n class=\"ms-auto shrink-0 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 <slot name=\"close\"><X class=\"size-4\" /></slot>\n </DialogClose>\n </header>\n\n <div class=\"flex-1 overflow-y-auto p-5\">\n <slot />\n </div>\n\n <footer v-if=\"$slots.footer\" class=\"shrink-0 border-t border-border bg-surface-muted p-4\">\n <slot name=\"footer\" />\n </footer>\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'\nimport Icon from '../icon/Icon.vue'\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\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof itemVariants>['variant']\n icon?: string\n disabled?: boolean\n }>(),\n { disabled: false },\n)\n\nconst emit = defineEmits<{ select: [] }>()\n\nfunction onSelect() {\n if (!props.disabled) emit('select')\n}\n</script>\n\n<template>\n <RekaItem :disabled=\"disabled\" :class=\"itemVariants({ variant })\" @select=\"onSelect\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-4 shrink-0\" />\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'\nimport Icon from '../icon/Icon.vue'\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\nconst props = withDefaults(\n defineProps<{\n variant?: VariantProps<typeof itemVariants>['variant']\n icon?: string\n disabled?: boolean\n }>(),\n { disabled: false },\n)\n\nconst emit = defineEmits<{ select: [] }>()\n\nfunction onSelect() {\n if (!props.disabled) emit('select')\n}\n</script>\n\n<template>\n <RekaItem :disabled=\"disabled\" :class=\"itemVariants({ variant })\" @select=\"onSelect\">\n <Icon v-if=\"icon\" :name=\"icon\" class=\"size-4 shrink-0\" />\n <slot />\n </RekaItem>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuSeparator as RekaSeparator } from 'reka-ui'\n</script>\n\n<template>\n <RekaSeparator class=\"my-1 h-px bg-border\" />\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuSeparator as RekaSeparator } from 'reka-ui'\n</script>\n\n<template>\n <RekaSeparator class=\"my-1 h-px bg-border\" />\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuLabel as RekaLabel } from 'reka-ui'\n</script>\n\n<template>\n <RekaLabel class=\"px-2 py-1.5 text-xs font-medium text-muted\">\n <slot />\n </RekaLabel>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuLabel as RekaLabel } from 'reka-ui'\n</script>\n\n<template>\n <RekaLabel class=\"px-2 py-1.5 text-xs font-medium text-muted\">\n <slot />\n </RekaLabel>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuGroup as RekaGroup } from 'reka-ui'\n</script>\n\n<template>\n <RekaGroup>\n <slot />\n </RekaGroup>\n</template>\n","<script setup lang=\"ts\">\nimport { DropdownMenuGroup as RekaGroup } from 'reka-ui'\n</script>\n\n<template>\n <RekaGroup>\n <slot />\n </RekaGroup>\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 Skeleton from '../skeleton/Skeleton.vue'\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 loading?: boolean\n loadingRows?: number\n loadingLabel?: 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 loading: false,\n loadingRows: 5,\n loadingLabel: 'Loading…',\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/** Clamp to at least one placeholder row so 0/negative/fractional values still render. */\nconst placeholderRowCount = computed(() => Math.max(1, Math.floor(props.loadingRows)))\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\n :class=\"maxHeight ? 'overflow-auto' : undefined\"\n :style=\"maxHeight ? { maxHeight } : undefined\"\n :aria-busy=\"loading || undefined\"\n >\n <span v-if=\"loading\" class=\"sr-only\" role=\"status\" aria-live=\"polite\">{{ loadingLabel }}</span>\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=\"!loading && rows.length === 0\" :columns=\"columnCount\">\n <slot name=\"empty\">{{ emptyLabel }}</slot>\n </TableEmpty>\n <template v-if=\"loading\">\n <TableRow v-for=\"n in placeholderRowCount\" :key=\"'loading-' + n\">\n <TableCell v-for=\"c in columnCount\" :key=\"c\">\n <Skeleton height=\"1rem\" rounded=\"sm\" />\n </TableCell>\n </TableRow>\n </template>\n <template v-else>\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 </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 Skeleton from '../skeleton/Skeleton.vue'\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 loading?: boolean\n loadingRows?: number\n loadingLabel?: 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 loading: false,\n loadingRows: 5,\n loadingLabel: 'Loading…',\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/** Clamp to at least one placeholder row so 0/negative/fractional values still render. */\nconst placeholderRowCount = computed(() => Math.max(1, Math.floor(props.loadingRows)))\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\n :class=\"maxHeight ? 'overflow-auto' : undefined\"\n :style=\"maxHeight ? { maxHeight } : undefined\"\n :aria-busy=\"loading || undefined\"\n >\n <span v-if=\"loading\" class=\"sr-only\" role=\"status\" aria-live=\"polite\">{{ loadingLabel }}</span>\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=\"!loading && rows.length === 0\" :columns=\"columnCount\">\n <slot name=\"empty\">{{ emptyLabel }}</slot>\n </TableEmpty>\n <template v-if=\"loading\">\n <TableRow v-for=\"n in placeholderRowCount\" :key=\"'loading-' + n\">\n <TableCell v-for=\"c in columnCount\" :key=\"c\">\n <Skeleton height=\"1rem\" rounded=\"sm\" />\n </TableCell>\n </TableRow>\n </template>\n <template v-else>\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 </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","import { computed, inject, ref, type ComputedRef, type InjectionKey, type Ref } from 'vue'\n\nexport type ToastSeverity = 'info' | 'success' | 'warning' | 'danger' | 'secondary'\n\nexport type ToastPosition =\n | 'top-start' | 'top-center' | 'top-end'\n | 'bottom-start' | 'bottom-center' | 'bottom-end'\n\nexport interface ToastAction {\n label: string\n onClick: () => void\n}\n\nexport interface ToastOptions {\n title?: string\n description?: string\n severity?: ToastSeverity\n duration?: number\n position?: ToastPosition\n closable?: boolean\n icon?: string\n action?: ToastAction\n}\n\nexport interface ToastItem extends ToastOptions {\n id: string\n}\n\nexport interface ToastStoreOptions {\n max?: number\n duration?: number\n position?: ToastPosition\n}\n\nexport interface ToastStore {\n /** All toasts, including those queued past `max`. */\n items: Ref<ToastItem[]>\n /** The `max` most recent toasts, oldest first. */\n visible: ComputedRef<ToastItem[]>\n add: (options: ToastOptions) => string\n remove: (id: string) => void\n clear: () => void\n info: (title: string, description?: string) => string\n success: (title: string, description?: string) => string\n warning: (title: string, description?: string) => string\n danger: (title: string, description?: string) => string\n secondary: (title: string, description?: string) => string\n}\n\n/** Injection key for the toast store provided by `<Toaster />`. */\nexport const toastKey: InjectionKey<ToastStore> = Symbol('myghf-toast')\n\nlet seq = 0\n\nexport function createToastStore(options: ToastStoreOptions = {}): ToastStore {\n const max = Math.max(1, options.max ?? 4)\n const duration = options.duration ?? 5000\n const position = options.position ?? 'top-end'\n\n const items = ref<ToastItem[]>([])\n const visible = computed(() => items.value.slice(0, max))\n\n function add(options: ToastOptions): string {\n const id = `toast-${++seq}`\n items.value.push({ severity: 'info', position, duration, ...options, id })\n return id\n }\n\n function remove(id: string) {\n const index = items.value.findIndex((item) => item.id === id)\n if (index !== -1) items.value.splice(index, 1)\n }\n\n function clear() {\n items.value = []\n }\n\n function convenience(severity: ToastSeverity) {\n return (title: string, description?: string) => add({ title, description, severity })\n }\n\n return {\n items,\n visible,\n add,\n remove,\n clear,\n info: convenience('info'),\n success: convenience('success'),\n warning: convenience('warning'),\n danger: convenience('danger'),\n secondary: convenience('secondary'),\n }\n}\n\nexport function useToast(): ToastStore {\n const store = inject(toastKey)\n if (!store) {\n throw new Error('useToast() requires a <Toaster /> mounted above this component.')\n }\n return store\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ToastAction as RekaToastAction,\n ToastClose,\n ToastDescription,\n ToastRoot,\n ToastTitle,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\nimport type { ToastItem, ToastSeverity } from './useToast'\n\nconst props = defineProps<{\n item: ToastItem\n duration: number\n}>()\n\nconst emit = defineEmits<{ close: [] }>()\n\nconst severity = computed<ToastSeverity>(() => props.item.severity ?? 'info')\n\n/** Foreground toasts are announced assertively; background ones politely. */\nconst type = computed(() =>\n severity.value === 'danger' || severity.value === 'warning' ? 'foreground' : 'background',\n)\n\nconst resolvedDuration = computed(() => props.item.duration ?? props.duration)\n\n/** Fallback lucide name per severity, used when no explicit `icon` is set. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n</script>\n\n<template>\n <ToastRoot\n :default-open=\"true\"\n :duration=\"resolvedDuration\"\n :type=\"type\"\n data-toast-root\n :data-duration=\"resolvedDuration\"\n :class=\"[\n 'pointer-events-auto flex w-full items-start gap-3 rounded-lg p-4 text-sm shadow-popover',\n toneClasses[severity].soft,\n ]\"\n @update:open=\"(open) => !open && emit('close')\"\n >\n <Icon\n :name=\"item.icon || defaultIcons[severity]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[severity].icon]\"\n />\n\n <div class=\"min-w-0 flex-1\">\n <ToastTitle v-if=\"item.title\" class=\"font-medium\">\n {{ item.title }}\n </ToastTitle>\n <ToastDescription\n v-if=\"item.description\"\n :class=\"['leading-relaxed', item.title ? 'mt-1' : '']\"\n >\n {{ item.description }}\n </ToastDescription>\n </div>\n\n <RekaToastAction\n v-if=\"item.action\"\n :alt-text=\"item.action.label\"\n class=\"-my-1 shrink-0 rounded-md px-2 py-1 font-medium transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"item.action.onClick()\"\n >\n {{ item.action.label }}\n </RekaToastAction>\n\n <ToastClose\n v-if=\"item.closable !== false\"\n aria-label=\"Close\"\n class=\"-me-1 -mt-1 shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <X class=\"size-4\" />\n </ToastClose>\n </ToastRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ToastAction as RekaToastAction,\n ToastClose,\n ToastDescription,\n ToastRoot,\n ToastTitle,\n} from 'reka-ui'\nimport { X } from 'lucide-vue-next'\nimport { toneClasses, type Tone } from '../../lib/tones'\nimport Icon from '../icon/Icon.vue'\nimport type { ToastItem, ToastSeverity } from './useToast'\n\nconst props = defineProps<{\n item: ToastItem\n duration: number\n}>()\n\nconst emit = defineEmits<{ close: [] }>()\n\nconst severity = computed<ToastSeverity>(() => props.item.severity ?? 'info')\n\n/** Foreground toasts are announced assertively; background ones politely. */\nconst type = computed(() =>\n severity.value === 'danger' || severity.value === 'warning' ? 'foreground' : 'background',\n)\n\nconst resolvedDuration = computed(() => props.item.duration ?? props.duration)\n\n/** Fallback lucide name per severity, used when no explicit `icon` is set. */\nconst defaultIcons: Record<Tone, string> = {\n info: 'info',\n success: 'circle-check',\n warning: 'triangle-alert',\n danger: 'circle-alert',\n secondary: 'info',\n}\n</script>\n\n<template>\n <ToastRoot\n :default-open=\"true\"\n :duration=\"resolvedDuration\"\n :type=\"type\"\n data-toast-root\n :data-duration=\"resolvedDuration\"\n :class=\"[\n 'pointer-events-auto flex w-full items-start gap-3 rounded-lg p-4 text-sm shadow-popover',\n toneClasses[severity].soft,\n ]\"\n @update:open=\"(open) => !open && emit('close')\"\n >\n <Icon\n :name=\"item.icon || defaultIcons[severity]\"\n :class=\"['mt-0.5 size-4 shrink-0', toneClasses[severity].icon]\"\n />\n\n <div class=\"min-w-0 flex-1\">\n <ToastTitle v-if=\"item.title\" class=\"font-medium\">\n {{ item.title }}\n </ToastTitle>\n <ToastDescription\n v-if=\"item.description\"\n :class=\"['leading-relaxed', item.title ? 'mt-1' : '']\"\n >\n {{ item.description }}\n </ToastDescription>\n </div>\n\n <RekaToastAction\n v-if=\"item.action\"\n :alt-text=\"item.action.label\"\n class=\"-my-1 shrink-0 rounded-md px-2 py-1 font-medium transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n @click=\"item.action.onClick()\"\n >\n {{ item.action.label }}\n </RekaToastAction>\n\n <ToastClose\n v-if=\"item.closable !== false\"\n aria-label=\"Close\"\n class=\"-me-1 -mt-1 shrink-0 rounded-md p-1 transition-colors hover:bg-black/10 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500\"\n >\n <X class=\"size-4\" />\n </ToastClose>\n </ToastRoot>\n</template>\n","<script setup lang=\"ts\">\nimport { provide } from 'vue'\nimport { ToastProvider, ToastViewport } from 'reka-ui'\nimport { createToastStore, toastKey, type ToastPosition, type ToastStore } from './useToast'\nimport Toast from './Toast.vue'\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition\n max?: number\n duration?: number\n gap?: string\n label?: string\n store?: ToastStore\n }>(),\n {\n position: 'top-end',\n max: 4,\n duration: 5000,\n gap: '0.5rem',\n label: 'Notifications',\n },\n)\n\nconst toastStore = props.store ?? createToastStore({\n max: props.max,\n duration: props.duration,\n position: props.position,\n})\n\nprovide(toastKey, toastStore)\n\nconst POSITIONS: ToastPosition[] = [\n 'top-start', 'top-center', 'top-end',\n 'bottom-start', 'bottom-center', 'bottom-end',\n]\n\nconst viewportPosition: Record<ToastPosition, string> = {\n 'top-start': 'top-0 start-0',\n 'top-center': 'top-0 inset-x-0 mx-auto',\n 'top-end': 'top-0 end-0',\n 'bottom-start': 'bottom-0 start-0',\n 'bottom-center': 'bottom-0 inset-x-0 mx-auto',\n 'bottom-end': 'bottom-0 end-0',\n}\n\nfunction itemsFor(position: ToastPosition) {\n return toastStore.visible.value.filter((item) => (item.position ?? props.position) === position)\n}\n</script>\n\n<template>\n <ToastProvider :label=\"label\" :duration=\"duration\">\n <slot />\n <template v-for=\"pos in POSITIONS\" :key=\"pos\">\n <ToastViewport\n v-if=\"itemsFor(pos).length > 0\"\n :label=\"label\"\n :class=\"[\n 'pointer-events-none fixed z-50 flex max-h-screen w-full max-w-sm flex-col',\n viewportPosition[pos],\n ]\"\n :style=\"{ gap }\"\n >\n <Toast\n v-for=\"item in itemsFor(pos)\"\n :key=\"item.id\"\n :item=\"item\"\n :duration=\"duration\"\n @close=\"toastStore.remove(item.id)\"\n />\n </ToastViewport>\n </template>\n </ToastProvider>\n</template>\n","<script setup lang=\"ts\">\nimport { provide } from 'vue'\nimport { ToastProvider, ToastViewport } from 'reka-ui'\nimport { createToastStore, toastKey, type ToastPosition, type ToastStore } from './useToast'\nimport Toast from './Toast.vue'\n\nconst props = withDefaults(\n defineProps<{\n position?: ToastPosition\n max?: number\n duration?: number\n gap?: string\n label?: string\n store?: ToastStore\n }>(),\n {\n position: 'top-end',\n max: 4,\n duration: 5000,\n gap: '0.5rem',\n label: 'Notifications',\n },\n)\n\nconst toastStore = props.store ?? createToastStore({\n max: props.max,\n duration: props.duration,\n position: props.position,\n})\n\nprovide(toastKey, toastStore)\n\nconst POSITIONS: ToastPosition[] = [\n 'top-start', 'top-center', 'top-end',\n 'bottom-start', 'bottom-center', 'bottom-end',\n]\n\nconst viewportPosition: Record<ToastPosition, string> = {\n 'top-start': 'top-0 start-0',\n 'top-center': 'top-0 inset-x-0 mx-auto',\n 'top-end': 'top-0 end-0',\n 'bottom-start': 'bottom-0 start-0',\n 'bottom-center': 'bottom-0 inset-x-0 mx-auto',\n 'bottom-end': 'bottom-0 end-0',\n}\n\nfunction itemsFor(position: ToastPosition) {\n return toastStore.visible.value.filter((item) => (item.position ?? props.position) === position)\n}\n</script>\n\n<template>\n <ToastProvider :label=\"label\" :duration=\"duration\">\n <slot />\n <template v-for=\"pos in POSITIONS\" :key=\"pos\">\n <ToastViewport\n v-if=\"itemsFor(pos).length > 0\"\n :label=\"label\"\n :class=\"[\n 'pointer-events-none fixed z-50 flex max-h-screen w-full max-w-sm flex-col',\n viewportPosition[pos],\n ]\"\n :style=\"{ gap }\"\n >\n <Toast\n v-for=\"item in itemsFor(pos)\"\n :key=\"item.id\"\n :item=\"item\"\n :duration=\"duration\"\n @close=\"toastStore.remove(item.id)\"\n />\n </ToastViewport>\n </template>\n </ToastProvider>\n</template>\n"],"mappings":"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"}
|