@inshorts/glint-ui 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-UBJK4OEO.js +110 -0
- package/dist/chunk-UBJK4OEO.js.map +1 -0
- package/dist/chunk-YXKAUYDJ.js +158 -0
- package/dist/chunk-YXKAUYDJ.js.map +1 -0
- package/dist/dialog.cjs +160 -0
- package/dist/dialog.cjs.map +1 -0
- package/dist/dialog.d.cts +26 -0
- package/dist/dialog.d.ts +26 -0
- package/dist/dialog.js +27 -0
- package/dist/dialog.js.map +1 -0
- package/dist/dropdown-menu.cjs +213 -0
- package/dist/dropdown-menu.cjs.map +1 -0
- package/dist/dropdown-menu.d.cts +33 -0
- package/dist/dropdown-menu.d.ts +33 -0
- package/dist/dropdown-menu.js +37 -0
- package/dist/dropdown-menu.js.map +1 -0
- package/dist/index.cjs +447 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +73 -19
- package/package.json +32 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/alert.tsx","../src/utils.ts","../src/autocomplete.tsx","../src/modal.tsx","../src/dialogLayer.ts","../src/badge.tsx","../src/breadcrumb.tsx","../src/button.tsx","../src/spinner.tsx","../src/card.tsx","../src/checkbox.tsx","../src/clipboard.ts","../src/collapsible.tsx","../src/confirm-dialog.tsx","../src/copy-button.tsx","../src/data-table.tsx","../src/date-range-picker/index.tsx","../src/date-range-picker/dateRange.ts","../src/state-panel.tsx","../src/feature-access-gate.tsx","../src/field.tsx","../src/image-uploader.tsx","../src/input.tsx","../src/label.tsx","../src/page-header.tsx","../src/panel-brand-mark.tsx","../src/panel-sign-in.tsx","../src/pagination.tsx","../src/segmented-control.tsx","../src/select.tsx","../src/separator.tsx","../src/side-drawer.tsx","../src/spreadsheet-grid.tsx","../src/switch.tsx","../src/table.tsx","../src/tabs.tsx","../src/textarea.tsx"],"sourcesContent":["export * from \"./alert\";\nexport * from \"./autocomplete\";\nexport * from \"./badge\";\nexport * from \"./breadcrumb\";\nexport * from \"./button\";\nexport * from \"./card\";\nexport * from \"./checkbox\";\nexport * from \"./clipboard\";\nexport * from \"./collapsible\";\nexport * from \"./confirm-dialog\";\nexport * from \"./copy-button\";\nexport * from \"./data-table\";\nexport * from \"./date-range-picker\";\nexport * from \"./date-range-picker/dateRange\";\nexport * from \"./dialogLayer\";\nexport * from \"./feature-access-gate\";\nexport * from \"./field\";\nexport * from \"./image-uploader\";\nexport * from \"./input\";\nexport * from \"./label\";\nexport * from \"./modal\";\nexport * from \"./page-header\";\nexport * from \"./panel-brand-mark\";\nexport * from \"./panel-sign-in\";\nexport * from \"./pagination\";\nexport * from \"./segmented-control\";\nexport * from \"./select\";\nexport * from \"./separator\";\nexport * from \"./side-drawer\";\nexport * from \"./spinner\";\nexport * from \"./spreadsheet-grid\";\nexport * from \"./state-panel\";\nexport * from \"./switch\";\nexport * from \"./table\";\nexport * from \"./tabs\";\nexport * from \"./textarea\";\nexport * from \"./utils\";\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The inline message banner — a failed load, a warning above a form, a note.\n *\n * This was the most duplicated markup in the panel: thirty blocks across\n * twenty-eight files, spelled seven different ways. `px-3 py-2` in most places\n * and `px-4 py-3` in others, `text-rose-700` here and `text-destructive`\n * there — all meaning \"something went wrong\".\n *\n * `role` is derived from the variant rather than left to callers. An error a\n * user needs to act on should interrupt a screen reader; a note should not.\n * Almost none of the hand-rolled copies set either.\n */\nconst alertVariants = cva(\"rounded-lg border px-3 py-2 text-sm\", {\n variants: {\n variant: {\n danger: \"border-destructive/30 bg-destructive/5 text-destructive\",\n warning: \"border-warning/30 bg-warning/5 text-warning\",\n success: \"border-success/30 bg-success/5 text-success\",\n info: \"border-info/30 bg-info/5 text-info\",\n /**\n * The quiet state of a banner that also has loud ones — \"no default\n * campaign set\" next to \"this is the default\". Without it those callers\n * keep a ternary of raw class strings and the shared component only\n * covers half of what they draw.\n */\n neutral: \"border-border bg-muted/40 text-muted-foreground\",\n },\n },\n defaultVariants: {\n // Failure is what a banner almost always reports here, and defaulting to\n // it means the noisy case cannot be forgotten.\n variant: \"danger\",\n },\n});\n\nexport interface AlertProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof alertVariants> {\n /**\n * A control belonging to the message, such as Retry. Given one, the banner\n * lays out as a row and keeps the action at its end.\n */\n action?: React.ReactNode;\n}\n\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n ({ className, variant, action, children, ...props }, ref) => (\n <div\n ref={ref}\n role={variant === \"danger\" || variant == null ? \"alert\" : \"status\"}\n className={cn(\n alertVariants({ variant }),\n action && \"flex flex-wrap items-center justify-between gap-3\",\n className,\n )}\n {...props}\n >\n {/* Wrapped so the action sits opposite the text rather than being\n pushed around by whatever the caller passed as children. */}\n {action ? <span>{children}</span> : children}\n {action}\n </div>\n ),\n);\n\nAlert.displayName = \"Alert\";\n\nexport { alertVariants };\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Check, ChevronDown, Search, X } from \"lucide-react\";\n\nimport { useHasMounted } from \"./modal\";\nimport { cn } from \"./utils\";\n\n/** Room the list wants below the control before it gives up and flips. */\nconst PREFERRED_LIST_HEIGHT = 224;\n/** Below this there is no point opening downward at all. */\nconst MIN_LIST_HEIGHT = 120;\nconst VIEWPORT_MARGIN = 8;\nconst ANCHOR_GAP = 4;\n\ntype DropdownPosition = {\n left: number;\n width: number;\n maxHeight: number;\n /** One of the two is set: `top` opens downward, `bottom` opens upward. */\n top?: number;\n bottom?: number;\n};\n\nexport type AutocompleteOption = {\n value: string;\n label: string;\n disabled?: boolean;\n};\n\ntype BaseAutocompleteProps = {\n options: AutocompleteOption[];\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n emptyMessage?: string;\n id?: string;\n /**\n * Accessible name for the combobox.\n *\n * `Field` renders its label as a `<span>`, so without this the control is\n * announced as an unnamed combobox and cannot be queried by name — the\n * filter toolbars work around it by counting comboboxes on the page.\n */\n ariaLabel?: string;\n /**\n * `compact` is the spreadsheet cell: no search icon, no min height, and a\n * list wide enough to read a name. The closed control still shows the\n * chosen label, and typing filters the list.\n */\n size?: \"default\" | \"compact\";\n /**\n * Type a value and press Enter (or paste a list) to add it, like antd\n * `Select mode=\"tags\"`. With `multiple` a pasted list is split into several\n * values; on a single-value control it accepts one typed value the options\n * do not offer — an id for a record the list has not loaded, say.\n */\n creatable?: boolean;\n /**\n * Shows the clear button once a value is chosen. Off for dropdowns that\n * always keep one of their options, where clearing would blank a required\n * field.\n */\n clearable?: boolean;\n};\n\ntype SingleAutocompleteProps = BaseAutocompleteProps & {\n multiple?: false;\n value: string;\n onChange: (value: string) => void;\n};\n\ntype MultipleAutocompleteProps = BaseAutocompleteProps & {\n multiple: true;\n value: string[];\n onChange: (value: string[]) => void;\n};\n\nexport type AutocompleteProps =\n SingleAutocompleteProps | MultipleAutocompleteProps;\n\nfunction normalizeQuery(query: string) {\n return query.trim().toLowerCase();\n}\n\nfunction filterOptions(options: AutocompleteOption[], query: string) {\n const normalized = normalizeQuery(query);\n if (!normalized) return options;\n\n return options.filter(\n (option) =>\n option.label.toLowerCase().includes(normalized) ||\n option.value.toLowerCase().includes(normalized),\n );\n}\n\nfunction getOptionLabel(options: AutocompleteOption[], value: string) {\n return options.find((option) => option.value === value)?.label ?? value;\n}\n\nfunction parseTagTokens(raw: string): string[] {\n const seen = new Set<string>();\n const tokens: string[] = [];\n for (const part of raw.split(/[\\s,]+/)) {\n const token = part.trim();\n if (!token || seen.has(token)) continue;\n seen.add(token);\n tokens.push(token);\n }\n return tokens;\n}\n\nexport function Autocomplete(props: AutocompleteProps) {\n const {\n options,\n placeholder = \"Search…\",\n disabled = false,\n className,\n emptyMessage = \"No results found\",\n id,\n ariaLabel,\n size = \"default\",\n creatable = false,\n clearable = true,\n } = props;\n\n const multiple = props.multiple ?? false;\n const singleValue = multiple\n ? undefined\n : (props as SingleAutocompleteProps).value;\n const multipleValue = multiple\n ? (props as MultipleAutocompleteProps).value\n : undefined;\n\n // Memoized so dependent callbacks below keep stable identities across renders.\n const selectedValues = React.useMemo<string[]>(() => {\n if (multiple) return multipleValue ?? [];\n return singleValue ? [singleValue] : [];\n }, [multiple, multipleValue, singleValue]);\n\n const onSingleChange = !multiple\n ? (props as SingleAutocompleteProps).onChange\n : undefined;\n const onMultipleChange = multiple\n ? (props as MultipleAutocompleteProps).onChange\n : undefined;\n\n const containerRef = React.useRef<HTMLDivElement>(null);\n const dropdownRef = React.useRef<HTMLDivElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const listRef = React.useRef<HTMLUListElement>(null);\n const ignoreBlurRef = React.useRef(false);\n\n const mounted = useHasMounted();\n const [open, setOpen] = React.useState(false);\n const [position, setPosition] = React.useState<DropdownPosition | null>(null);\n const [query, setQuery] = React.useState(\"\");\n const [highlightedIndex, setHighlightedIndex] = React.useState(0);\n\n const filteredOptions = React.useMemo(\n () => filterOptions(options, query),\n [options, query],\n );\n\n // Clamp during render instead of via a setState-in-effect: if the option list\n // shrinks below the stored index, fall back to the last valid row.\n const safeHighlightedIndex =\n highlightedIndex >= filteredOptions.length\n ? Math.max(filteredOptions.length - 1, 0)\n : highlightedIndex;\n\n const close = React.useCallback(() => {\n setOpen(false);\n setQuery(\"\");\n setHighlightedIndex(0);\n }, []);\n\n const openDropdown = React.useCallback(() => {\n if (disabled) return;\n setOpen(true);\n setHighlightedIndex(0);\n }, [disabled]);\n\n const commitSingleValue = React.useCallback(\n (value: string) => {\n if (!multiple) {\n onSingleChange?.(value);\n close();\n }\n },\n [close, multiple, onSingleChange],\n );\n\n const toggleMultipleValue = React.useCallback(\n (value: string) => {\n if (!multiple || !onMultipleChange) return;\n\n onMultipleChange(\n selectedValues.includes(value)\n ? selectedValues.filter((item) => item !== value)\n : [...selectedValues, value],\n );\n setQuery(\"\");\n setHighlightedIndex(0);\n },\n [multiple, onMultipleChange, selectedValues],\n );\n\n const commitCustomValues = React.useCallback(\n (raw: string) => {\n if (!creatable) return;\n\n if (!multiple) {\n const value = raw.trim();\n if (!value) return;\n commitSingleValue(value);\n return;\n }\n\n if (!onMultipleChange) return;\n const tokens = parseTagTokens(raw);\n if (!tokens.length) return;\n const next = [...selectedValues];\n for (const token of tokens) {\n if (!next.includes(token)) next.push(token);\n }\n onMultipleChange(next);\n setQuery(\"\");\n setHighlightedIndex(0);\n },\n [commitSingleValue, creatable, multiple, onMultipleChange, selectedValues],\n );\n\n const removeValue = React.useCallback(\n (value: string) => {\n if (!multiple || !onMultipleChange) return;\n onMultipleChange(selectedValues.filter((item) => item !== value));\n window.requestAnimationFrame(() => inputRef.current?.focus());\n },\n [multiple, onMultipleChange, selectedValues],\n );\n\n const selectOption = React.useCallback(\n (option: AutocompleteOption) => {\n if (option.disabled) return;\n\n ignoreBlurRef.current = true;\n window.setTimeout(() => {\n ignoreBlurRef.current = false;\n }, 0);\n\n if (multiple) {\n toggleMultipleValue(option.value);\n window.requestAnimationFrame(() => inputRef.current?.focus());\n return;\n }\n\n commitSingleValue(option.value);\n },\n [commitSingleValue, multiple, toggleMultipleValue],\n );\n\n const selectHighlighted = React.useCallback(() => {\n const option = filteredOptions[safeHighlightedIndex];\n if (!option) return;\n selectOption(option);\n }, [filteredOptions, safeHighlightedIndex, selectOption]);\n\n React.useEffect(() => {\n if (!open) return;\n\n function handlePointerDown(event: PointerEvent) {\n const target = event.target as Node;\n // The list is portalled to the body, so containment has to be checked\n // against both halves or picking an option would close the control\n // before the choice registered.\n if (\n containerRef.current?.contains(target) ||\n dropdownRef.current?.contains(target)\n ) {\n return;\n }\n close();\n }\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [close, open]);\n\n /*\n The list is measured against the viewport and rendered in a portal.\n\n Anchored inside the control it was clipped by whatever `overflow` ancestor\n happened to be above it — inside a dialog body that is the scroll region,\n so the last field on a form showed one row of a six-hundred-row list. It\n opens downward when there is room, upward when there is not, and shrinks to\n what is left when neither side can take the whole list.\n */\n React.useLayoutEffect(() => {\n // Not cleared on close: the render is gated on `open`, and the layout\n // effect recomputes before the next paint, so a stale value is never seen.\n if (!open) return;\n\n const update = () => {\n const anchor = containerRef.current;\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n const below =\n window.innerHeight - rect.bottom - ANCHOR_GAP - VIEWPORT_MARGIN;\n const above = rect.top - ANCHOR_GAP - VIEWPORT_MARGIN;\n const flip =\n below < Math.min(PREFERRED_LIST_HEIGHT, MIN_LIST_HEIGHT) &&\n above > below;\n const room = flip ? above : below;\n const width = Math.max(rect.width, size === \"compact\" ? 220 : 0);\n const left = Math.max(\n VIEWPORT_MARGIN,\n Math.min(rect.left, window.innerWidth - width - VIEWPORT_MARGIN),\n );\n setPosition({\n left,\n width,\n maxHeight: Math.max(\n MIN_LIST_HEIGHT,\n Math.min(PREFERRED_LIST_HEIGHT, room),\n ),\n ...(flip\n ? { bottom: window.innerHeight - rect.top + ANCHOR_GAP }\n : { top: rect.bottom + ANCHOR_GAP }),\n });\n };\n\n update();\n // Capture, so a scroll in any ancestor — the dialog body included — moves\n // the list with its control instead of leaving it behind.\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open, size]);\n\n React.useEffect(() => {\n if (!open || !listRef.current) return;\n\n const highlighted = listRef.current.children[safeHighlightedIndex] as\n HTMLElement | undefined;\n\n highlighted?.scrollIntoView({ block: \"nearest\" });\n }, [safeHighlightedIndex, open]);\n\n function handleInputKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {\n if (disabled) return;\n\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!open) {\n openDropdown();\n return;\n }\n setHighlightedIndex(\n Math.min(safeHighlightedIndex + 1, filteredOptions.length - 1),\n );\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!open) {\n openDropdown();\n return;\n }\n setHighlightedIndex(Math.max(safeHighlightedIndex - 1, 0));\n break;\n case \"Enter\":\n event.preventDefault();\n if (creatable && query.trim()) {\n // A single-value control filters its list as you type, so a match\n // is what Enter means there; only an unmatched query is taken as a\n // new value. Tags have no such list to defer to.\n if (multiple || filteredOptions.length === 0) {\n commitCustomValues(query);\n return;\n }\n }\n if (!open) {\n openDropdown();\n return;\n }\n selectHighlighted();\n break;\n case \",\":\n if (creatable && multiple && query.trim()) {\n event.preventDefault();\n commitCustomValues(query);\n }\n break;\n case \"Escape\":\n event.preventDefault();\n close();\n break;\n case \"Backspace\":\n if (multiple && query.length === 0 && selectedValues.length > 0) {\n event.preventDefault();\n removeValue(selectedValues[selectedValues.length - 1]);\n }\n break;\n case \"Tab\":\n close();\n break;\n default:\n break;\n }\n }\n\n const displayValue =\n !multiple && !open && !query && selectedValues[0]\n ? getOptionLabel(options, selectedValues[0])\n : query;\n\n const inputPlaceholder =\n multiple && selectedValues.length > 0 ? \"\" : placeholder;\n\n const createLabel = query.trim();\n const canCreate =\n creatable && Boolean(createLabel) && !selectedValues.includes(createLabel);\n\n const listboxId = id ? `${id}-listbox` : undefined;\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"relative\",\n size === \"compact\" ? \"w-auto min-w-24\" : \"w-full\",\n className,\n )}\n >\n <div\n className={cn(\n \"border-border bg-background flex w-full cursor-pointer items-center rounded-md border transition-colors\",\n \"focus-within:border-ring focus-within:ring-ring/30 focus-within:ring-2\",\n size === \"compact\"\n ? \"min-h-0 gap-0.5 border-transparent bg-transparent px-1 py-0.5 text-xs shadow-none\"\n : \"min-h-9 gap-1.5 px-2 py-1.5 text-sm shadow-sm\",\n disabled && \"cursor-not-allowed opacity-50\",\n open && \"border-ring ring-ring/30 ring-2\",\n )}\n onPointerDown={(event) => {\n if (disabled) return;\n if ((event.target as HTMLElement).closest(\"[data-option]\")) return;\n if ((event.target as HTMLElement).closest(\"[data-chip-remove]\"))\n return;\n\n if (!(event.target as HTMLElement).closest(\"input\")) {\n event.preventDefault();\n inputRef.current?.focus();\n }\n\n openDropdown();\n }}\n >\n {size === \"compact\" ? null : (\n <Search className=\"text-muted-foreground size-4 shrink-0\" />\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-1\">\n {multiple &&\n selectedValues.map((value) => (\n <span\n key={value}\n className=\"bg-primary/10 text-primary inline-flex max-w-full items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium\"\n >\n <span className=\"truncate\">\n {getOptionLabel(options, value)}\n </span>\n <button\n type=\"button\"\n data-chip-remove\n className=\"text-primary/70 hover:bg-primary/15 hover:text-primary rounded-sm transition\"\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n removeValue(value);\n }}\n aria-label={`Remove ${getOptionLabel(options, value)}`}\n >\n <X className=\"size-3\" />\n </button>\n </span>\n ))}\n\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n role=\"combobox\"\n aria-label={ariaLabel}\n aria-expanded={open}\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n disabled={disabled}\n value={displayValue}\n placeholder={inputPlaceholder}\n className={cn(\n \"placeholder:text-muted-foreground flex-1 bg-transparent outline-none\",\n size === \"compact\" ? \"min-w-0\" : \"min-w-[6rem]\",\n )}\n onFocus={openDropdown}\n onBlur={() => {\n if (ignoreBlurRef.current) return;\n close();\n }}\n onChange={(event) => {\n setQuery(event.target.value);\n setHighlightedIndex(0);\n if (!open) setOpen(true);\n }}\n onKeyDown={handleInputKeyDown}\n onPaste={(event) => {\n if (!creatable || !multiple) return;\n const text = event.clipboardData.getData(\"text\");\n if (!/[\\s,]/.test(text)) return;\n event.preventDefault();\n commitCustomValues(text);\n }}\n />\n </div>\n\n {clearable && !multiple && selectedValues[0] && !disabled && (\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground rounded-sm p-0.5 transition\"\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onSingleChange?.(\"\");\n setQuery(\"\");\n inputRef.current?.focus();\n }}\n aria-label=\"Clear selection\"\n >\n <X className=\"size-3.5\" />\n </button>\n )}\n\n <ChevronDown\n className={cn(\n \"text-muted-foreground shrink-0 transition-transform\",\n size === \"compact\" ? \"size-3\" : \"size-4\",\n open && \"rotate-180\",\n )}\n />\n </div>\n\n {open && mounted && position\n ? createPortal(\n <div\n ref={dropdownRef}\n data-autocomplete-dropdown\n style={{\n position: \"fixed\",\n left: position.left,\n width: position.width,\n top: position.top,\n bottom: position.bottom,\n // Above the modal shell (z-100) it is usually opened inside.\n zIndex: 200,\n }}\n className=\"border-border bg-background overflow-hidden rounded-md border shadow-lg\"\n >\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n className=\"overflow-y-auto p-1\"\n style={{ maxHeight: position.maxHeight }}\n >\n {filteredOptions.length === 0 && !canCreate ? (\n <li className=\"text-muted-foreground px-3 py-6 text-center text-sm\">\n {emptyMessage}\n </li>\n ) : (\n <>\n {filteredOptions.map((option, index) => {\n const isSelected = selectedValues.includes(option.value);\n const isHighlighted = index === safeHighlightedIndex;\n\n return (\n <li\n key={option.value}\n data-option\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled || undefined}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm transition-colors\",\n size === \"compact\"\n ? \"px-2 py-1 text-xs\"\n : \"px-2.5 py-2 text-sm\",\n isHighlighted && \"bg-muted\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n onMouseEnter={() => setHighlightedIndex(index)}\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n selectOption(option);\n }}\n >\n {multiple ? (\n <span\n className={cn(\n \"border-border flex size-4 shrink-0 items-center justify-center rounded border\",\n isSelected &&\n \"border-primary bg-primary text-primary-foreground\",\n )}\n >\n {isSelected ? <Check className=\"size-3\" /> : null}\n </span>\n ) : (\n <Check\n className={cn(\n \"text-primary size-4 shrink-0\",\n isSelected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n )}\n <span className=\"truncate\">{option.label}</span>\n </li>\n );\n })}\n {canCreate ? (\n <li\n data-option\n role=\"option\"\n aria-selected={false}\n className=\"hover:bg-muted flex cursor-pointer items-center gap-2 rounded-sm px-2.5 py-2 text-sm transition-colors\"\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n ignoreBlurRef.current = true;\n window.setTimeout(() => {\n ignoreBlurRef.current = false;\n }, 0);\n commitCustomValues(query);\n window.requestAnimationFrame(() =>\n inputRef.current?.focus(),\n );\n }}\n >\n Add “{createLabel}”\n </li>\n ) : null}\n </>\n )}\n </ul>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { useDialogLayer } from \"./dialogLayer\";\nimport { cn } from \"./utils\";\n\nconst emptySubscribe = () => () => {};\n\n/**\n * Returns false during SSR and the first client render, then true once mounted.\n * `useSyncExternalStore` is the React-recommended way to read client-only state\n * without a setState-in-effect (which triggers cascading renders).\n */\nexport function useHasMounted(): boolean {\n return React.useSyncExternalStore(\n emptySubscribe,\n () => true,\n () => false,\n );\n}\n\ninterface ModalProps {\n isOpen: boolean;\n /** id of the element labelling the dialog; wired to aria-labelledby. */\n labelledBy: string;\n /**\n * Optional id(s) of elements describing the dialog (APG alertdialog body).\n * Space-separated when multiple.\n */\n describedBy?: string;\n /** Accessible label for the backdrop dismiss button. */\n closeLabel: string;\n onClose: () => void;\n children: React.ReactNode;\n /**\n * When false, Escape and backdrop clicks do not close the modal (e.g. while a\n * save is in flight). Defaults to true.\n */\n dismissible?: boolean;\n /** Use \"alertdialog\" for destructive confirmations. Defaults to \"dialog\". */\n role?: \"dialog\" | \"alertdialog\";\n /** Tailwind max-width class for the panel. Defaults to \"max-w-md\". */\n panelClassName?: string;\n}\n\n/**\n * Shared modal shell: renders a portal-backed, scroll-locked, Escape-dismissible\n * overlay with a centered panel. Callers provide the panel body (heading, form,\n * footer). Consolidates the boilerplate previously copied across every dialog.\n */\nexport function Modal({\n isOpen,\n labelledBy,\n describedBy,\n closeLabel,\n onClose,\n children,\n dismissible = true,\n role = \"dialog\",\n panelClassName,\n}: ModalProps) {\n const mounted = useHasMounted();\n const panelRef = React.useRef<HTMLDivElement>(null);\n\n useDialogLayer({\n // Gated on `mounted` too: before that the panel is not rendered, so there\n // would be nothing to move focus into.\n active: isOpen && mounted,\n containerRef: panelRef,\n onEscape: dismissible ? onClose : undefined,\n });\n\n if (!mounted || !isOpen) return null;\n\n return createPortal(\n /*\n `overflow-y-auto` on the overlay, `my-auto` on the panel — not\n `items-center`. A flex item centred with `align-items` overflows equally\n in both directions once it is taller than its container, and the half\n above the top edge cannot be scrolled to: with the page behind it locked,\n an over-tall dialog was simply unreachable at both ends. Auto margins\n centre a short panel the same way and collapse to zero on a tall one,\n which scrolls.\n */\n <div className=\"fixed inset-0 z-[100] flex justify-center overflow-y-auto p-4\">\n {/* `fixed`, not `absolute`: inside a scrolling overlay an absolute\n backdrop scrolls away with the content and leaves the rest of a tall\n dialog sitting on an undimmed page. */}\n <button\n type=\"button\"\n aria-label={closeLabel}\n tabIndex={-1}\n className=\"fixed inset-0 bg-overlay/50\"\n onClick={() => {\n if (dismissible) onClose();\n }}\n />\n <div\n ref={panelRef}\n role={role}\n aria-modal=\"true\"\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n tabIndex={-1}\n className={cn(\n \"border-border bg-background relative z-10 my-auto w-full rounded-lg border shadow-2xl outline-none\",\n panelClassName ?? \"max-w-md p-6\",\n )}\n >\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\n/**\n * The keyboard and focus behaviour every dialog needs, in one place.\n *\n * `Modal` and `SideDrawer` each had a copy of the scroll lock and an Escape\n * handler, and neither did anything about focus: opening a dialog left focus\n * on the button behind it, Tab walked the page underneath — through the\n * full-screen backdrop button, among other things — and closing left focus\n * wherever it had wandered. That is the whole keyboard story for thirty\n * dialogs, so it is fixed once here rather than thirty times.\n */\n\n/**\n * Open dialogs, innermost last.\n *\n * Nesting is real here — \"Create audience group\" opens on top of \"Send\n * notification\" — and without an ordering both would answer the same Escape\n * and fight over the same Tab. Only the top layer acts.\n */\nconst layers: symbol[] = [];\n\nconst FOCUSABLE = [\n \"a[href]\",\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(\",\");\n\n/**\n * Deliberately not `offsetParent` or `getClientRects`: the first is null for\n * anything `position: fixed`, which a dialog panel usually is, and the second\n * is empty for *everything* under a test renderer that does no layout — which\n * would collapse the trap to \"no focusable elements\" in every test.\n */\nfunction isVisible(element: HTMLElement): boolean {\n if (element.closest(\"[hidden]\")) return false;\n if (element.getAttribute(\"aria-hidden\") === \"true\") return false;\n return typeof element.checkVisibility === \"function\"\n ? element.checkVisibility()\n : true;\n}\n\nfunction focusableWithin(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n isVisible,\n );\n}\n\nexport function useDialogLayer({\n active,\n containerRef,\n onEscape,\n}: {\n active: boolean;\n /** The panel. Focus is moved into it and kept inside it. */\n containerRef: React.RefObject<HTMLElement | null>;\n /** Called on Escape, only while this is the top layer. Omit to ignore it. */\n onEscape?: () => void;\n}): void {\n // Read through a ref so a caller passing a fresh closure every render does\n // not tear the listener down and rebuild it on every keystroke.\n const escapeRef = React.useRef(onEscape);\n React.useEffect(() => {\n escapeRef.current = onEscape;\n });\n\n React.useEffect(() => {\n if (!active) return;\n\n const layer = Symbol(\"dialog-layer\");\n layers.push(layer);\n const isTopLayer = () => layers[layers.length - 1] === layer;\n\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n\n const container = containerRef.current;\n // Something inside may have claimed focus already — an `autoFocus` input —\n // and that choice is better than any this could make.\n if (container && !container.contains(document.activeElement)) {\n const [first] = focusableWithin(container);\n // The panel itself, not its first control: the first control is a Delete\n // button often enough that focusing it would put a destructive action\n // one Enter away from an accidental keypress.\n (container.hasAttribute(\"tabindex\") ? container : first)?.focus();\n }\n\n function handleKeyDown(event: KeyboardEvent) {\n if (!isTopLayer()) return;\n\n if (event.key === \"Escape\") {\n escapeRef.current?.();\n return;\n }\n\n if (event.key !== \"Tab\") return;\n const panel = containerRef.current;\n if (!panel) return;\n\n const items = focusableWithin(panel);\n if (items.length === 0) {\n event.preventDefault();\n panel.focus();\n return;\n }\n\n const first = items[0]!;\n const last = items[items.length - 1]!;\n const active = document.activeElement;\n const outside = !panel.contains(active);\n\n if (event.shiftKey && (active === first || outside)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (active === last || outside)) {\n event.preventDefault();\n first.focus();\n }\n }\n\n document.addEventListener(\"keydown\", handleKeyDown);\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n document.body.style.overflow = previousOverflow;\n const index = layers.indexOf(layer);\n if (index !== -1) layers.splice(index, 1);\n // Back where it came from, so closing a dialog opened by keyboard does\n // not drop the caret at the top of the document.\n if (previouslyFocused?.isConnected) previouslyFocused.focus();\n };\n }, [active, containerRef]);\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The status pill every list panel was spelling out by hand.\n *\n * Variants are semantic rather than named after a colour, because the same\n * status means the same thing on every panel and should not have to be\n * re-decided per table — Deleted was `bg-rose-100 text-rose-800` in one place\n * and `text-rose-900` two files away.\n *\n * These stay light-on-dark-text in both themes on purpose. A pill is a small\n * block of colour whose whole job is to be picked out of a row of text, and\n * inverting it per theme made the same status read as two different states.\n */\nconst badgeVariants = cva(\n \"inline-flex items-center gap-1 rounded font-medium whitespace-nowrap\",\n {\n variants: {\n variant: {\n neutral: \"bg-muted text-muted-foreground\",\n success: \"bg-success/15 text-success\",\n warning: \"bg-warning/15 text-warning\",\n danger: \"bg-destructive/15 text-destructive\",\n info: \"bg-info/15 text-info\",\n },\n size: {\n /** Inline chips — a category, a tenant, a permission. */\n sm: \"px-1.5 py-0.5 text-xs\",\n /** A row's status. */\n md: \"px-2 py-0.5 text-xs\",\n },\n },\n defaultVariants: {\n variant: \"neutral\",\n size: \"md\",\n },\n },\n);\n\nexport interface BadgeProps\n extends\n React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant, size, ...props }, ref) => (\n <span\n ref={ref}\n className={cn(badgeVariants({ variant, size }), className)}\n {...props}\n />\n ),\n);\n\nBadge.displayName = \"Badge\";\n\nexport { badgeVariants };\n","import { ChevronRight } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type BreadcrumbItem = {\n label: string;\n href?: string;\n onClick?: () => void;\n};\n\ninterface BreadcrumbProps {\n items: BreadcrumbItem[];\n className?: string;\n}\n\nexport function Breadcrumb({ items, className }: BreadcrumbProps) {\n return (\n <nav aria-label=\"Breadcrumb\" className={cn(\"text-sm\", className)}>\n <ol className=\"flex flex-wrap items-center gap-1.5\">\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n const isInteractive = !isLast && (item.href || item.onClick);\n\n return (\n <li\n key={`${item.label}-${index}`}\n className=\"flex items-center gap-1.5\"\n >\n {index > 0 && (\n <ChevronRight\n className=\"text-muted-foreground/70 size-3.5 shrink-0\"\n aria-hidden\n />\n )}\n {isInteractive ? (\n item.href ? (\n <a\n href={item.href}\n className=\"text-muted-foreground hover:text-foreground transition\"\n >\n {item.label}\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={item.onClick}\n className=\"text-muted-foreground hover:text-foreground transition\"\n >\n {item.label}\n </button>\n )\n ) : (\n <span\n className={cn(\n isLast\n ? \"text-foreground font-medium\"\n : \"text-muted-foreground\",\n )}\n aria-current={isLast ? \"page\" : undefined}\n >\n {item.label}\n </span>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"@radix-ui/react-slot\";\n\nimport { Spinner } from \"./spinner\";\nimport { cn } from \"./utils\";\n\nconst buttonVariants = cva(\n \"inline-flex h-9 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md px-3 text-sm font-medium transition duration-200 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n secondary: \"bg-muted text-foreground hover:bg-muted/80\",\n ghost: \"hover:bg-muted\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline: \"border border-border bg-background hover:bg-muted\",\n },\n size: {\n sm: \"h-8 px-2.5\",\n md: \"h-9 px-3\",\n lg: \"h-10 px-4\",\n icon: \"h-9 w-9 px-0\",\n // Square, matching `sm`'s height — for an icon-only control sitting in\n // a table row or beside `sm` buttons, where `icon` is a row taller.\n \"icon-sm\": \"h-8 w-8 px-0\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n },\n);\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n /**\n * Work is in flight: shows a spinner, disables the button, and sets\n * `aria-busy`.\n *\n * This exists because the panel had 272 disabled buttons and only 22 that\n * said anything about why — the rest went dead on click with no spinner and\n * no label change, which reads as a broken button rather than a busy one.\n * Making the feedback part of `disabled` rather than something each caller\n * remembers separately is the only way that ratio stays fixed.\n *\n * The label is kept rather than swapped. \"Saving…\" loses which button you\n * pressed, and the spinner already says it is working. An icon-only button\n * is the exception — there is no room beside the glyph, so the spinner takes\n * its place; the `aria-label` is what names the button either way.\n *\n * \"Icon-only\" means an icon `size`. A square button that grew a spinner\n * beside its glyph would not just look wrong, it would resize mid-request\n * and shove whatever sits next to it sideways.\n */\n loading?: boolean;\n}\n\n/** Sizes with no room for a spinner beside the glyph. */\nconst ICON_SIZES = new Set<string>([\"icon\", \"icon-sm\"]);\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n asChild = false,\n loading,\n disabled,\n children,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n\n // `asChild` renders someone else's element, which may not take a spinner or\n // a disabled attribute — so the busy treatment is only applied to a real\n // button, and passing both is a mistake worth not papering over.\n if (asChild) {\n return (\n <Comp\n ref={ref}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n >\n {children}\n </Comp>\n );\n }\n\n return (\n <button\n ref={ref}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n >\n {loading ? <Spinner size=\"sm\" /> : null}\n {loading && size != null && ICON_SIZES.has(size) ? null : children}\n </button>\n );\n },\n);\n\nButton.displayName = \"Button\";\n","import * as React from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one spinner.\n *\n * There were five spellings of `animate-spin` across twelve files — `h-4 w-4`,\n * `h-5 w-5`, `size-4`, bare, and a hand-drawn ring in `ProtectedRoute` — so the\n * same \"working\" signal came out a different size depending on which panel you\n * were on.\n *\n * It is `aria-hidden` on purpose. A spinner is decoration; what a screen reader\n * needs is the surrounding control's `aria-busy` or the panel's status text,\n * and announcing \"loading\" twice is worse than once. `Button` and `StatePanel`\n * both supply that.\n */\nconst SIZES = {\n sm: \"size-3.5\",\n md: \"size-4\",\n lg: \"size-5\",\n xl: \"size-10 border-2\",\n} as const;\n\nexport interface SpinnerProps extends React.SVGProps<SVGSVGElement> {\n size?: keyof typeof SIZES;\n}\n\nexport function Spinner({ size = \"md\", className, ...props }: SpinnerProps) {\n return (\n <Loader2\n aria-hidden\n className={cn(\"animate-spin\", SIZES[size], className)}\n {...props}\n />\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * Surface container for grouped content. Prefer a bare section when there is\n * no need for border / padding chrome — cards are for interactive or\n * self-contained blocks, not every stack of text.\n */\nexport const Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"bg-card text-card-foreground rounded-xl border shadow\",\n className,\n )}\n {...props}\n />\n));\nCard.displayName = \"Card\";\n\nexport const CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n {...props}\n />\n));\nCardHeader.displayName = \"CardHeader\";\n\nexport const CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"leading-none font-semibold tracking-tight\", className)}\n {...props}\n />\n));\nCardTitle.displayName = \"CardTitle\";\n\nexport const CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n));\nCardDescription.displayName = \"CardDescription\";\n\nexport const CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />\n));\nCardContent.displayName = \"CardContent\";\n\nexport const CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex items-center p-6 pt-0\", className)}\n {...props}\n />\n));\nCardFooter.displayName = \"CardFooter\";\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The native checkbox, sized and coloured once.\n *\n * Twenty-six of these were scattered across thirteen files and twenty of them\n * carried **no class at all** — browser defaults, so they were a different size\n * to the six that set `size-4` and drew their tick in the operating system's\n * accent rather than the panel's.\n *\n * This deliberately stays a native `<input type=\"checkbox\">` rather than an\n * `appearance-none` box with an SVG tick. Native gets indeterminate state,\n * form participation, platform focus behaviour and assistive-technology support\n * for free, and a custom one would have to re-earn all of it to look slightly\n * different.\n *\n * `border` and `rounded` mostly do not render on a native checkbox — they are\n * kept because the six styled copies had them and removing them would be a\n * silent change to those. `accent-primary` and `size-4` are what actually show.\n */\nexport const checkboxClass =\n \"accent-primary border-border focus-visible:ring-ring size-4 shrink-0 cursor-pointer rounded border focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type CheckboxProps = Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n \"type\"\n>;\n\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, ...props }, ref) => (\n <input\n ref={ref}\n type=\"checkbox\"\n className={cn(checkboxClass, className)}\n {...props}\n />\n ),\n);\n\nCheckbox.displayName = \"Checkbox\";\n","/**\n * Range maths and clipboard text for the card table's spreadsheet selection.\n *\n * Ported from video-shorts-panel `app/src/common/components/ExcelTable.jsx`.\n * Kept free of React and the DOM (except `writeToClipboard`) so the escaping\n * and range rules are unit-testable.\n */\n\nexport type CellRef = { r: number; c: number };\n\nexport type CellRange = { r1: number; r2: number; c1: number; c2: number };\n\n/** Tab for the clipboard (Excel/Sheets split on it), comma for a .csv file. */\nexport const TSV_DELIMITER = \"\\t\";\nexport const CSV_DELIMITER = \",\";\n\n/**\n * Anchor and focus can be dragged in any direction, so the range is whichever\n * corners they happen to be — normalize to top-left / bottom-right.\n */\nexport function normalizeRange(\n anchor: CellRef | null | undefined,\n focus: CellRef | null | undefined,\n): CellRange | null {\n if (!anchor || !focus) return null;\n return {\n r1: Math.min(anchor.r, focus.r),\n r2: Math.max(anchor.r, focus.r),\n c1: Math.min(anchor.c, focus.c),\n c2: Math.max(anchor.c, focus.c),\n };\n}\n\n/**\n * A cell needs quoting once it carries the delimiters themselves — the same\n * rule Excel uses when it parses the clipboard. Without it, a title containing\n * a tab or a newline silently becomes extra columns or rows on paste.\n */\nexport function escapeCell(raw: unknown, delimiter: string): string {\n const value = raw == null ? \"\" : String(raw);\n if (\n value.includes(delimiter) ||\n value.includes(\"\\n\") ||\n value.includes(\"\\r\") ||\n value.includes('\"')\n ) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\nexport type TextColumn<Row> = {\n title: string;\n value: (row: Row) => string;\n};\n\n/** Renders a range as delimited text, optionally with a header line. */\nexport function buildRangeText<Row>(\n range: CellRange | null,\n columns: TextColumn<Row>[],\n rows: Row[],\n delimiter: string,\n includeHeaders: boolean,\n): string {\n if (!range) return \"\";\n const lines: string[] = [];\n\n if (includeHeaders) {\n const header: string[] = [];\n for (let c = range.c1; c <= range.c2; c++) {\n header.push(escapeCell(columns[c]?.title, delimiter));\n }\n lines.push(header.join(delimiter));\n }\n\n for (let r = range.r1; r <= range.r2; r++) {\n const line: string[] = [];\n const row = rows[r];\n for (let c = range.c1; c <= range.c2; c++) {\n const column = columns[c];\n line.push(\n escapeCell(\n column && row !== undefined ? column.value(row) : \"\",\n delimiter,\n ),\n );\n }\n lines.push(line.join(delimiter));\n }\n\n return lines.join(\"\\n\");\n}\n\n/** The whole grid, or null when there is nothing to select. */\nexport function fullRange<Row>(\n columns: TextColumn<Row>[],\n rows: Row[],\n): CellRange | null {\n if (!rows.length || !columns.length) return null;\n return { r1: 0, r2: rows.length - 1, c1: 0, c2: columns.length - 1 };\n}\n\n/** \"3 × 2 selected\" — what the toolbar reports back to the user. */\nexport function describeRange(range: CellRange | null): string {\n if (!range) return \"No selection\";\n const rowCount = range.r2 - range.r1 + 1;\n const colCount = range.c2 - range.c1 + 1;\n if (rowCount === 1 && colCount === 1) return \"1 cell selected\";\n return `${rowCount} × ${colCount} selected`;\n}\n\nexport function countCells(range: CellRange): {\n rows: number;\n columns: number;\n} {\n return {\n rows: range.r2 - range.r1 + 1,\n columns: range.c2 - range.c1 + 1,\n };\n}\n\n/**\n * `navigator.clipboard` is unavailable on http origins and older browsers, so\n * fall back to a hidden textarea + execCommand rather than failing the copy.\n */\nexport async function writeToClipboard(text: string): Promise<void> {\n if (navigator.clipboard?.writeText) {\n return navigator.clipboard.writeText(text);\n }\n\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.style.position = \"fixed\";\n textarea.style.top = \"-1000px\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n if (!document.execCommand(\"copy\")) {\n throw new Error(\"Could not write to the clipboard\");\n }\n } finally {\n document.body.removeChild(textarea);\n }\n}\n","\"use client\";\n\nimport { ChevronDown } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * A titled section that folds away.\n *\n * For sidebar panels that are long but not always in use — the body stays\n * mounted so its state (a loaded list, a half-filled filter) survives being\n * collapsed, rather than being thrown away and refetched on the way back.\n */\nexport function CollapsibleSection({\n title,\n icon,\n defaultOpen = true,\n right,\n className,\n children,\n}: {\n title: string;\n /** Optional leading glyph, shown between the chevron and the title. */\n icon?: React.ReactNode;\n defaultOpen?: boolean;\n /** Optional trailing content in the header, e.g. a count. */\n right?: React.ReactNode;\n className?: string;\n children: React.ReactNode;\n}) {\n const [open, setOpen] = React.useState(defaultOpen);\n const bodyId = React.useId();\n\n return (\n <div className={cn(\"border-border rounded-lg border\", className)}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={bodyId}\n onClick={() => setOpen((current) => !current)}\n className=\"hover:bg-muted/50 flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-semibold transition\"\n >\n <ChevronDown\n size={14}\n aria-hidden\n className={cn(\n \"shrink-0 transition-transform\",\n open ? \"\" : \"-rotate-90\",\n )}\n />\n {icon}\n <span className=\"flex-1\">{title}</span>\n {right}\n </button>\n {/* Hidden rather than unmounted, so collapsing does not discard the\n panel's state or refetch what it had already loaded. */}\n <div id={bodyId} hidden={!open} className=\"space-y-3 px-3 pt-1 pb-3\">\n {children}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { Modal } from \"./modal\";\n\ninterface ConfirmDialogProps {\n isOpen: boolean;\n title: string;\n description?: React.ReactNode;\n confirmLabel?: string;\n cancelLabel?: string;\n isConfirming?: boolean;\n error?: string | null;\n onConfirm: () => void;\n onClose: () => void;\n}\n\nexport function ConfirmDialog({\n isOpen,\n title,\n description,\n confirmLabel = \"Delete\",\n cancelLabel = \"Cancel\",\n isConfirming,\n error,\n onConfirm,\n onClose,\n}: ConfirmDialogProps) {\n const titleId = React.useId();\n const descriptionId = React.useId();\n const errorId = React.useId();\n\n const describedBy = [\n description ? descriptionId : null,\n error ? errorId : null,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <Modal\n isOpen={isOpen}\n role=\"alertdialog\"\n labelledBy={titleId}\n describedBy={describedBy || undefined}\n closeLabel=\"Close dialog\"\n onClose={onClose}\n >\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {title}\n </h3>\n {description ? (\n <div id={descriptionId} className=\"text-muted-foreground mt-2 text-sm\">\n {description}\n </div>\n ) : null}\n\n {error ? (\n <div\n id={errorId}\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/5 text-destructive mt-4 rounded-lg border px-3 py-2 text-sm\"\n >\n {error}\n </div>\n ) : null}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <Button variant=\"outline\" onClick={onClose} disabled={isConfirming}>\n {cancelLabel}\n </Button>\n <Button\n variant=\"destructive\"\n onClick={onConfirm}\n loading={isConfirming}\n >\n {confirmLabel}\n </Button>\n </div>\n </Modal>\n );\n}\n","\"use client\";\n\nimport { Check, Copy } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { writeToClipboard } from \"./clipboard\";\nimport { cn } from \"./utils\";\n\n/**\n * Copies one short string — an id, a title, a URL — and says so for a moment.\n *\n * The panel had this three times over, each with its own timeout and its own\n * silent-failure story. `writeToClipboard` is used rather than\n * `navigator.clipboard` directly because the latter is undefined on http\n * origins, which is exactly where this panel runs in local dev.\n */\nexport function CopyButton({\n value,\n label,\n className,\n}: {\n value: string;\n /** What is being copied, for the accessible name: \"card id\", \"title\". */\n label: string;\n className?: string;\n}) {\n const [copied, setCopied] = React.useState(false);\n\n React.useEffect(() => {\n if (!copied) return;\n const timer = window.setTimeout(() => setCopied(false), 1500);\n return () => window.clearTimeout(timer);\n }, [copied]);\n\n return (\n <button\n type=\"button\"\n aria-label={copied ? `${label} copied` : `Copy ${label}`}\n title={copied ? \"Copied\" : `Copy ${label}`}\n className={cn(\n \"text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring shrink-0 cursor-pointer rounded p-1 transition focus-visible:ring-2 focus-visible:outline-none\",\n className,\n )}\n onClick={() => {\n // A denied clipboard permission should not throw into the row.\n void writeToClipboard(value)\n .then(() => setCopied(true))\n .catch(() => undefined);\n }}\n >\n {copied ? (\n <Check className=\"size-3.5 text-success\" aria-hidden />\n ) : (\n <Copy className=\"size-3.5\" aria-hidden />\n )}\n </button>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The list table every feature panel was hand-rolling.\n *\n * Seventeen files repeated the same wrapper string\n * (`border-border bg-background/80 overflow-x-auto rounded-lg border`) and the\n * header had already drifted into two incompatible looks, so Campaigns and\n * Targets did not resemble each other. Both are kept as `variant` rather than\n * unified here: collapsing them is a visual change to ten panels and belongs in\n * its own reviewable diff, not smuggled in with a refactor.\n *\n * The column contract deliberately echoes `GridColumn` in\n * `spreadsheet-grid.tsx` — `key`, `title`, a renderer, an optional class — so\n * the repo has one shape to learn. It drops that type's `value: (row) => string`\n * because there is no clipboard or CSV here; nothing would keep it honest, and\n * a required field nobody reads gets filled in with lies.\n *\n * **Not for every table.** `GroupTable` renders parent and child rows with\n * different column counts, and `BusinessTable`'s rows are dnd-kit sortables that\n * own their own refs and transforms. `PublishModal`, `BulkCreateModal` and the\n * clone queue in `MetaAdSetsPanel` are grids of inputs rather than lists of\n * values — every cell is an editable control, and they size their header and\n * body rows differently on purpose. All five are legitimately tables of a\n * different kind; bending this component around them would cost more than it\n * saves.\n */\nexport type TableColumn<Row> = {\n key: string;\n /** Node, not string: a header can carry a select-all box or a sort control. */\n title: React.ReactNode;\n cell: (row: Row, index: number) => React.ReactNode;\n align?: \"left\" | \"right\" | \"center\";\n /**\n * Set on a sortable column so a screen reader announces the current sort.\n * Only the sorted column says `ascending`/`descending`; the rest say `none`,\n * which is what marks them as sortable at all.\n */\n ariaSort?: \"ascending\" | \"descending\" | \"none\";\n /** Extra classes for this column's `<td>`. */\n className?: string;\n /** Extra classes for this column's `<th>`. */\n headerClassName?: string;\n};\n\nexport interface DataTableProps<Row> {\n columns: TableColumn<Row>[];\n rows: Row[];\n /** Stable React key per row. */\n rowKey: (row: Row, index: number) => string;\n /**\n * `uppercase` — the tinted small-caps header (campaigns, showcase, filters).\n * `plain` — the quieter left-aligned header (ads, targets, creatives).\n */\n variant?: \"uppercase\" | \"plain\";\n /**\n * `comfortable` — the roomy default, for tables of a handful of columns.\n * `compact` — what every table of eight columns or more had already chosen by\n * hand, because the roomy padding pushes them into a horizontal scroll.\n */\n density?: \"comfortable\" | \"compact\";\n /** Pins the header for a table inside its own scroll container. */\n stickyHeader?: boolean;\n rowClassName?: (row: Row, index: number) => string | undefined;\n /** Rendered in place of `<tbody>` rows when there are none. */\n emptyMessage?: React.ReactNode;\n /**\n * Rows for a `<tfoot>` — a totals line, typically. The caller supplies the\n * `<tr>` itself because a summary row rarely lines up with the columns above\n * it; designer-counts spans its first two.\n */\n footer?: React.ReactNode;\n /** Names the table for screen readers when no visible caption fits. */\n ariaLabel?: string;\n /** Classes for the scroll wrapper. */\n className?: string;\n /** Classes for the `<table>`. */\n tableClassName?: string;\n}\n\nconst HEADER_VARIANTS = {\n uppercase:\n \"border-border bg-muted/40 text-muted-foreground border-b text-xs tracking-wide uppercase\",\n plain: \"text-muted-foreground border-border border-b text-left\",\n} as const;\n\nconst DENSITY = {\n comfortable: \"px-4 py-3\",\n compact: \"px-3 py-2\",\n} as const;\n\nconst ALIGN = {\n left: \"text-left\",\n right: \"text-right\",\n center: \"text-center\",\n} as const;\n\nexport function DataTable<Row>({\n columns,\n rows,\n rowKey,\n variant = \"uppercase\",\n density = \"comfortable\",\n stickyHeader = false,\n rowClassName,\n emptyMessage,\n footer,\n ariaLabel,\n className,\n tableClassName,\n}: DataTableProps<Row>) {\n return (\n <div\n className={cn(\n \"border-border bg-background/80 overflow-x-auto rounded-lg border\",\n className,\n )}\n >\n <table\n aria-label={ariaLabel}\n className={cn(\"min-w-full text-left text-sm\", tableClassName)}\n >\n <thead\n className={cn(\n HEADER_VARIANTS[variant],\n stickyHeader && \"bg-muted sticky top-0 z-10\",\n )}\n >\n <tr>\n {columns.map((column) => (\n <th\n key={column.key}\n scope=\"col\"\n aria-sort={column.ariaSort}\n className={cn(\n DENSITY[density],\n \"font-medium\",\n ALIGN[column.align ?? \"left\"],\n column.headerClassName,\n )}\n >\n {column.title}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 && emptyMessage != null ? (\n <tr>\n {/* One cell across the whole width — a short row would otherwise\n leave the message sitting under the first column. */}\n <td\n colSpan={columns.length}\n className=\"text-muted-foreground px-4 py-6 text-center text-sm\"\n >\n {emptyMessage}\n </td>\n </tr>\n ) : (\n rows.map((row, index) => (\n <tr\n key={rowKey(row, index)}\n className={cn(\n \"border-border/70 border-b last:border-0\",\n rowClassName?.(row, index),\n )}\n >\n {columns.map((column) => (\n <td\n key={column.key}\n className={cn(\n DENSITY[density],\n ALIGN[column.align ?? \"left\"],\n column.className,\n )}\n >\n {column.cell(row, index)}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n {footer != null ? <tfoot>{footer}</tfoot> : null}\n </table>\n </div>\n );\n}\n","\"use client\";\n\nimport { CalendarDays, ChevronLeft, ChevronRight, X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"../utils\";\nimport {\n addDays,\n addMonths,\n formatDisplay,\n fromIsoDate,\n isSameDay,\n monthGrid,\n monthLabel,\n startOfMonth,\n toIsoDate,\n} from \"./dateRange\";\n\nexport type DateRangeValue = { from: string; to: string };\n\n/**\n * A two-month range calendar.\n *\n * Two separate date fields cost two columns and read as two unrelated\n * questions when they are one: which window. They also let the pair be set\n * backwards, which returns nothing and looks like a broken filter.\n *\n * Two months rather than one because almost every range anyone picks here\n * crosses a month boundary — \"last week of July into the first of August\" is a\n * single gesture with two months visible and a paging exercise with one.\n *\n * Presets are the useful half. The common ranges are the same handful every\n * time, and picking \"Last 7 days\" out of a list beats counting backwards on a\n * grid.\n */\nconst PRESETS: { label: string; range: () => DateRangeValue }[] = [\n {\n label: \"Today\",\n range: () => {\n const today = toIsoDate(new Date());\n return { from: today, to: today };\n },\n },\n {\n label: \"Yesterday\",\n range: () => {\n const day = toIsoDate(addDays(new Date(), -1));\n return { from: day, to: day };\n },\n },\n {\n label: \"Last 7 days\",\n range: () => ({\n from: toIsoDate(addDays(new Date(), -6)),\n to: toIsoDate(new Date()),\n }),\n },\n {\n label: \"Last 30 days\",\n range: () => ({\n from: toIsoDate(addDays(new Date(), -29)),\n to: toIsoDate(new Date()),\n }),\n },\n {\n label: \"This month\",\n range: () => ({\n from: toIsoDate(startOfMonth(new Date())),\n to: toIsoDate(new Date()),\n }),\n },\n];\n\nconst WEEKDAYS = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"];\n\nexport interface DateRangePickerProps {\n value: DateRangeValue;\n onChange: (next: DateRangeValue) => void;\n disabled?: boolean;\n placeholder?: string;\n className?: string;\n /** Names the trigger for screen readers when there is no visible label. */\n ariaLabel?: string;\n}\n\nexport function DateRangePicker({\n value,\n onChange,\n disabled,\n placeholder = \"Any date\",\n className,\n ariaLabel = \"Date range\",\n}: DateRangePickerProps) {\n const [open, setOpen] = React.useState(false);\n const [hovered, setHovered] = React.useState<Date | null>(null);\n /** Set while choosing the second end, so the range can preview under the cursor. */\n const [pendingFrom, setPendingFrom] = React.useState<Date | null>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n const from = fromIsoDate(value.from);\n const to = fromIsoDate(value.to);\n\n const [viewMonth, setViewMonth] = React.useState<Date>(() =>\n startOfMonth(from ?? new Date()),\n );\n\n React.useEffect(() => {\n if (!open) return undefined;\n const onPointerDown = (event: MouseEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) setOpen(false);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"mousedown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open]);\n\n /**\n * Reopening lands on the current selection rather than wherever the view was\n * left. Done here rather than in an effect: it is a response to an event, and\n * setting state from an effect is what `react-hooks/set-state-in-effect`\n * rejects — correctly, since it costs an extra render every open.\n */\n function openPicker() {\n setViewMonth(startOfMonth(fromIsoDate(value.from) ?? new Date()));\n setPendingFrom(null);\n setHovered(null);\n setOpen(true);\n }\n\n const anchor = pendingFrom ?? (to ? null : from);\n const previewEnd = pendingFrom ? hovered : null;\n\n function rangeBounds(): [Date | null, Date | null] {\n if (pendingFrom) {\n if (!previewEnd) return [pendingFrom, pendingFrom];\n return previewEnd.getTime() < pendingFrom.getTime()\n ? [previewEnd, pendingFrom]\n : [pendingFrom, previewEnd];\n }\n return [from, to];\n }\n\n const [rangeStart, rangeEnd] = rangeBounds();\n\n function selectDay(day: Date) {\n if (!anchor) {\n // Starting a new range. Keeping only `from` means the next click closes\n // it, whichever side of the anchor it lands on.\n setPendingFrom(day);\n onChange({ from: toIsoDate(day), to: \"\" });\n return;\n }\n const [start, end] =\n day.getTime() < anchor.getTime() ? [day, anchor] : [anchor, day];\n onChange({ from: toIsoDate(start), to: toIsoDate(end) });\n setPendingFrom(null);\n setHovered(null);\n setOpen(false);\n }\n\n /** Arrow keys move by day/week across both months, as a calendar should. */\n function onGridKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const offsets: Record<string, number> = {\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -7,\n ArrowDown: 7,\n };\n const offset = offsets[event.key];\n if (offset === undefined) return;\n const focused = document.activeElement as HTMLElement | null;\n const iso = focused?.dataset?.day;\n const current = fromIsoDate(iso);\n if (!current) return;\n event.preventDefault();\n const next = addDays(current, offset);\n const nextIso = toIsoDate(next);\n // Page the view when the move lands outside what is rendered.\n if (!rootRef.current?.querySelector(`[data-day=\"${nextIso}\"]`)) {\n setViewMonth(startOfMonth(offset < 0 ? next : addMonths(next, -1)));\n }\n window.requestAnimationFrame(() => {\n rootRef.current\n ?.querySelector<HTMLElement>(`[data-day=\"${nextIso}\"]`)\n ?.focus();\n });\n }\n\n const label =\n value.from || value.to\n ? `${formatDisplay(value.from) || \"Any\"} → ${formatDisplay(value.to) || \"Any\"}`\n : placeholder;\n\n const today = new Date();\n\n function renderMonth(month: Date) {\n return (\n <div key={monthLabel(month)} className=\"w-[15.75rem] shrink-0\">\n <div className=\"text-foreground mb-2 text-center text-sm font-medium whitespace-nowrap\">\n {monthLabel(month)}\n </div>\n <div className=\"text-muted-foreground grid grid-cols-7 text-center text-[11px]\">\n {WEEKDAYS.map((day) => (\n <div key={day} className=\"grid size-9 place-items-center\">\n {day}\n </div>\n ))}\n </div>\n <div className=\"grid grid-cols-7\">\n {monthGrid(month).map((day) => {\n const iso = toIsoDate(day);\n const outside = day.getMonth() !== month.getMonth();\n const isStart = isSameDay(day, rangeStart);\n const isEnd = isSameDay(day, rangeEnd);\n const inRange =\n rangeStart != null &&\n rangeEnd != null &&\n day.getTime() > rangeStart.getTime() &&\n day.getTime() < rangeEnd.getTime();\n const isToday = isSameDay(day, today);\n\n return (\n <button\n key={iso}\n type=\"button\"\n data-day={iso}\n // Outside days stay clickable — clicking one is how you reach\n // the neighbouring month without paging.\n onClick={() => selectDay(day)}\n onMouseEnter={() => setHovered(day)}\n aria-label={day.toDateString()}\n aria-pressed={isStart || isEnd}\n className={cn(\n \"focus-visible:ring-ring relative grid size-9 place-items-center rounded-md text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none\",\n outside ? \"text-muted-foreground/50\" : \"text-foreground\",\n inRange && \"bg-primary/10 rounded-none\",\n (isStart || isEnd) &&\n \"bg-primary text-primary-foreground font-medium\",\n // Square off the inner edge so a range reads as one bar\n // rather than two pills with a gap.\n isStart && rangeEnd && !isEnd && \"rounded-r-none\",\n isEnd && rangeStart && !isStart && \"rounded-l-none\",\n !isStart && !isEnd && \"hover:bg-muted\",\n isToday &&\n !isStart &&\n !isEnd &&\n \"ring-border font-semibold ring-1\",\n )}\n >\n {day.getDate()}\n </button>\n );\n })}\n </div>\n </div>\n );\n }\n\n return (\n <div ref={rootRef} className={cn(\"relative\", className)}>\n <div\n className={cn(\n \"border-border bg-background flex items-center rounded-md border\",\n \"focus-within:ring-ring/50 focus-within:border-ring focus-within:ring-2\",\n disabled && \"opacity-50\",\n )}\n >\n <button\n type=\"button\"\n disabled={disabled}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-label={ariaLabel}\n onClick={() => (open ? setOpen(false) : openPicker())}\n className=\"flex min-w-0 flex-1 items-center gap-2 px-2 py-1.5 text-left text-sm\"\n >\n <CalendarDays\n className=\"text-muted-foreground size-4 shrink-0\"\n aria-hidden\n />\n <span\n className={cn(\n \"truncate\",\n !value.from && !value.to && \"text-muted-foreground\",\n )}\n >\n {label}\n </span>\n </button>\n {(value.from || value.to) && !disabled ? (\n <button\n type=\"button\"\n aria-label=\"Clear date range\"\n onClick={() => {\n onChange({ from: \"\", to: \"\" });\n setPendingFrom(null);\n }}\n className=\"text-muted-foreground hover:text-foreground shrink-0 px-2\"\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n </div>\n\n {open ? (\n <div\n role=\"dialog\"\n aria-label={ariaLabel}\n // `w-max` so the calendar sets its own width instead of inheriting\n // the filter column, which squeezed the months until the numbers ran\n // together. Anchored right because this sits in the last column and\n // would otherwise open off the edge of the viewport.\n className=\"border-border bg-background absolute top-full right-0 z-50 mt-1 flex w-max rounded-lg border p-3 shadow-lg\"\n >\n <div className=\"border-border mr-3 flex w-32 shrink-0 flex-col gap-0.5 border-r pr-3\">\n {PRESETS.map((preset) => (\n <button\n key={preset.label}\n type=\"button\"\n className=\"hover:bg-muted text-foreground rounded-md px-2 py-1.5 text-left text-xs\"\n onClick={() => {\n onChange(preset.range());\n setPendingFrom(null);\n setOpen(false);\n }}\n >\n {preset.label}\n </button>\n ))}\n </div>\n\n <div onKeyDown={onGridKeyDown}>\n <div className=\"mb-2 flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n className=\"hover:bg-muted text-muted-foreground hover:text-foreground rounded-md p-1.5\"\n onClick={() => setViewMonth(addMonths(viewMonth, -1))}\n >\n <ChevronLeft className=\"size-4\" aria-hidden />\n </button>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n className=\"hover:bg-muted text-muted-foreground hover:text-foreground rounded-md p-1.5\"\n onClick={() => setViewMonth(addMonths(viewMonth, 1))}\n >\n <ChevronRight className=\"size-4\" aria-hidden />\n </button>\n </div>\n <div className=\"flex gap-5\" onMouseLeave={() => setHovered(null)}>\n {renderMonth(viewMonth)}\n {renderMonth(addMonths(viewMonth, 1))}\n </div>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * Date helpers for the range picker, all in local time.\n *\n * Deliberately not `toISOString()`: that converts to UTC first, so on any\n * negative-offset day it returns yesterday's date and the picker highlights the\n * wrong cell. Every value here is built and read as the local calendar day the\n * user is actually looking at.\n */\n\n/** `YYYY-MM-DD`, the value shape the filters store. */\nexport type IsoDate = string;\n\nconst pad = (n: number) => String(n).padStart(2, \"0\");\n\nexport function toIsoDate(date: Date): IsoDate {\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n}\n\n/** Parses `YYYY-MM-DD` into a local midnight Date; null for anything else. */\nexport function fromIsoDate(value: string | null | undefined): Date | null {\n if (!value) return null;\n const trimmed = value.trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(trimmed);\n if (!match) return null;\n const date = new Date(\n Number(match[1]),\n Number(match[2]) - 1,\n Number(match[3]),\n );\n // Rejects 2026-02-31, which would otherwise roll silently into March.\n return toIsoDate(date) === trimmed ? date : null;\n}\n\nexport function startOfMonth(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\nexport function addMonths(date: Date, count: number): Date {\n return new Date(date.getFullYear(), date.getMonth() + count, 1);\n}\n\nexport function addDays(date: Date, count: number): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() + count);\n}\n\nexport function isSameDay(a: Date | null, b: Date | null): boolean {\n if (!a || !b) return false;\n return toIsoDate(a) === toIsoDate(b);\n}\n\n/**\n * The six-week grid for a month, Sunday-first, padded with the neighbouring\n * months so every row has seven cells.\n *\n * Always six rows, never five: a grid that changes height as you page through\n * months makes everything below it jump.\n */\nexport function monthGrid(month: Date): Date[] {\n const first = startOfMonth(month);\n const start = addDays(first, -first.getDay());\n return Array.from({ length: 42 }, (_, index) => addDays(start, index));\n}\n\nexport function monthLabel(month: Date, locale = \"en-IN\"): string {\n return month.toLocaleDateString(locale, { month: \"long\", year: \"numeric\" });\n}\n\n/** Human form for the trigger — \"22 Aug 2026\". */\nexport function formatDisplay(value: string, locale = \"en-IN\"): string {\n const date = fromIsoDate(value);\n if (!date) return \"\";\n return date.toLocaleDateString(locale, {\n day: \"numeric\",\n month: \"short\",\n year: \"numeric\",\n });\n}\n\nexport function startOfDayMs(value: string): number {\n const date = fromIsoDate(value);\n return date ? date.getTime() : 0;\n}\n\n/**\n * The end of a day as milliseconds.\n *\n * A range picked as whole days has to include everything created on the last\n * day, so \"to\" means 23:59:59.999 rather than that morning's midnight — which\n * would drop a whole day of cards without saying so.\n */\nexport function endOfDayMs(value: string): number {\n const date = fromIsoDate(value);\n if (!date) return 0;\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n 23,\n 59,\n 59,\n 999,\n ).getTime();\n}\n\n/**\n * 11:59 PM on that local day, as 23:59:59.\n *\n * The next midnight is already the following date, and the feed includes that\n * whole day — so the 28th through the 28th came back with the 29th. Stopping\n * at 11:59 PM keeps the end on the day that was picked.\n */\nexport function endAt2359Ms(value: string): number {\n const date = fromIsoDate(value);\n if (!date) return 0;\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n 23,\n 59,\n 59,\n 0,\n ).getTime();\n}\n\n/**\n * Created-date window for the feed.\n *\n * A blank end means the start day, so one selected date is that whole day.\n * `end_time` is 11:59 PM on the end date.\n */\nexport function createdRangeMs(\n from: string,\n to: string,\n): { start_time: number; end_time: number } {\n const startDate = from.trim() || to.trim();\n const endDate = to.trim() || from.trim();\n return {\n start_time: startOfDayMs(startDate),\n end_time: endAt2359Ms(endDate),\n };\n}\n","import * as React from \"react\";\n\nimport { Spinner } from \"./spinner\";\nimport { cn } from \"./utils\";\n\n/**\n * The bordered block a list shows instead of rows: loading, or nothing found.\n *\n * Fourteen copies of the same\n * `border-border bg-background/80 … rounded-lg border px-4 py-6 text-center`\n * across the panels, each with its own wording — \"Loading users…\", \"Loading\n * taxonomy…\", \"Loading showcases…\". The wording is worth keeping (it says what\n * is loading), the markup is not.\n *\n * `loading` adds two things the hand-rolled versions did not have: a spinner,\n * so a slow panel does not look like an empty one, and `role=\"status\"` with\n * `aria-live=\"polite\"`, so a screen reader is told the list arrived instead of\n * silently finding rows on the next tab press.\n */\nexport interface StatePanelProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Shows a spinner and announces politely. */\n loading?: boolean;\n}\n\nexport function StatePanel({\n loading,\n className,\n children,\n ...props\n}: StatePanelProps) {\n return (\n <div\n role={loading ? \"status\" : undefined}\n aria-live={loading ? \"polite\" : undefined}\n className={cn(\n \"border-border bg-background/80 text-muted-foreground rounded-lg border px-4 py-6 text-center text-sm\",\n loading && \"flex items-center justify-center gap-2\",\n className,\n )}\n {...props}\n >\n {loading ? <Spinner size=\"md\" /> : null}\n {children}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { Alert } from \"./alert\";\nimport { StatePanel } from \"./state-panel\";\n\ntype FeatureAccessGateProps = {\n isLoading?: boolean;\n allowed: boolean;\n deniedMessage: React.ReactNode;\n children: React.ReactNode;\n};\n\n/**\n * Shared loading / denied shell for feature Managers (showcase, headers, …).\n */\nexport function FeatureAccessGate({\n isLoading,\n allowed,\n deniedMessage,\n children,\n}: FeatureAccessGateProps) {\n if (isLoading) {\n return (\n <StatePanel loading className=\"p-6\">\n Checking permissions…\n </StatePanel>\n );\n }\n\n if (!allowed) {\n // `Alert`, not a hand-rolled banner: this is the denial surface for\n // seventeen panels, and it was the one copy the Alert migration missed —\n // so being refused a panel announced nothing to a screen reader.\n return <Alert>{deniedMessage}</Alert>;\n }\n\n return <>{children}</>;\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\ninterface FieldProps {\n label: React.ReactNode;\n required?: boolean;\n /**\n * Associates the label with a control via `htmlFor` / `id`. Prefer this for\n * native inputs rendered as siblings (not wrapped). For composite controls\n * (Autocomplete), omit and use `as=\"label\"` wrapping or an `aria-label`.\n */\n htmlFor?: string;\n /**\n * Render as a `<label>` (wraps a native control so clicking the text focuses\n * it) or a `<div>` (for composite controls like Autocomplete that manage\n * their own focus / render in a portal). Defaults to `div`.\n */\n as?: \"label\" | \"div\";\n className?: string;\n children: React.ReactNode;\n}\n\nexport function Field({\n label,\n required,\n htmlFor,\n as = \"div\",\n className,\n children,\n}: FieldProps) {\n const Wrapper = as;\n const labelNode = (\n <>\n {label}\n {required ? (\n <span className=\"text-destructive ml-0.5\" aria-hidden=\"true\">\n *\n </span>\n ) : null}\n </>\n );\n\n return (\n <Wrapper className={cn(\"space-y-1 text-sm\", className)}>\n {htmlFor && as === \"div\" ? (\n <label htmlFor={htmlFor} className=\"text-muted-foreground\">\n {labelNode}\n </label>\n ) : (\n <span className=\"text-muted-foreground\">{labelNode}</span>\n )}\n {children}\n </Wrapper>\n );\n}\n","\"use client\";\n\nimport { ImagePlus, Loader2, X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { cn } from \"./utils\";\n\nexport type ImageUploaderProps = {\n value?: string;\n onChange: (url: string) => void;\n disabled?: boolean;\n label?: string;\n className?: string;\n /** Allow pasting a remote URL in addition to file upload. Default true. */\n allowUrlPaste?: boolean;\n accept?: string;\n /**\n * Upload a picked file and return its hosted URL.\n * Injected by the panel — Upload stays enabled either way; without a\n * handler, picking a file surfaces a configuration error.\n */\n uploadFile?: (file: File) => Promise<string>;\n /**\n * Optional transform for pasted values (e.g. host a relative path).\n * When omitted, any pasted non-empty string is applied as-is. Absolute\n * `http(s)` URLs never call this.\n */\n uploadFromUrl?: (imageUrl: string) => Promise<string>;\n};\n\n/**\n * Reusable image uploader.\n *\n * Upload and URL paste are both enabled by default. Hosting is injected:\n * each panel passes `uploadFile` / `uploadFromUrl` so the kit stays free of\n * panel-specific API routes.\n */\nexport function ImageUploader({\n value = \"\",\n onChange,\n disabled,\n label,\n className,\n allowUrlPaste = true,\n accept = \"image/*,.gif\",\n uploadFile,\n uploadFromUrl,\n}: ImageUploaderProps) {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [uploading, setUploading] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n const busy = Boolean(disabled || uploading);\n\n const handleFile = async (file: File) => {\n if (!uploadFile) {\n setError(\"File upload is not configured for this panel.\");\n return;\n }\n setUploading(true);\n setError(null);\n try {\n onChange(await uploadFile(file));\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n if (inputRef.current) inputRef.current.value = \"\";\n }\n };\n\n const handleUrl = async (imageUrl: string) => {\n const trimmed = imageUrl.trim();\n if (!trimmed) {\n onChange(\"\");\n return;\n }\n if (trimmed === value) return;\n\n // Absolute URLs — and any paste when no transform is configured — apply\n // as-is. Paste is never gated behind a disabled input.\n if (!uploadFromUrl || /^https?:\\/\\//i.test(trimmed)) {\n setError(null);\n onChange(trimmed);\n return;\n }\n\n setUploading(true);\n setError(null);\n try {\n onChange(await uploadFromUrl(trimmed));\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n {label ? (\n <div className=\"text-muted-foreground text-xs font-medium\">{label}</div>\n ) : null}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n className=\"hidden\"\n disabled={busy}\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) void handleFile(file);\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n onClick={() => inputRef.current?.click()}\n >\n {uploading ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <ImagePlus className=\"h-4 w-4\" />\n )}\n {uploading ? \"Uploading…\" : \"Upload\"}\n </Button>\n {value ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n onClick={() => onChange(\"\")}\n aria-label=\"Clear image\"\n >\n <X className=\"h-4 w-4\" />\n Clear\n </Button>\n ) : null}\n </div>\n\n {allowUrlPaste ? (\n <Input\n key={value || \"empty\"}\n defaultValue={value}\n disabled={busy}\n placeholder=\"Or paste image URL…\"\n onBlur={(e) => {\n void handleUrl(e.target.value);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void handleUrl((e.target as HTMLInputElement).value);\n }\n }}\n />\n ) : null}\n\n {value ? (\n // eslint-disable-next-line @next/next/no-img-element -- CDN URLs vary\n <img\n src={value}\n alt=\"\"\n className=\"border-border max-h-24 rounded border bg-white object-contain p-1\"\n />\n ) : null}\n\n {error ? (\n <p className=\"text-destructive text-xs\" role=\"alert\">\n {error}\n </p>\n ) : null}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport const inputClass =\n \"h-9 w-full rounded-md border border-border bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, ...props }, ref) => (\n <input ref={ref} className={cn(inputClass, className)} {...props} />\n ),\n);\n\nInput.displayName = \"Input\";\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type LabelProps = React.LabelHTMLAttributes<HTMLLabelElement>;\n\n/** Form label — pair with a native control via `htmlFor`. */\nexport const Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => (\n <label\n ref={ref}\n className={cn(\n \"text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n ),\n);\n\nLabel.displayName = \"Label\";\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The title block every panel opens with.\n *\n * Twenty Managers wrote the same `<h1>` and subtitle by hand, differing only in\n * whether the row said `gap-3` or `gap-x-4 gap-y-2` and whether the inner block\n * carried `min-w-0` — differences nobody chose, which is what made them worth\n * removing.\n *\n * `description` takes a node rather than a string because several panels put a\n * `<code>` in theirs, naming the Firebase field they write. That is the useful\n * kind of subtitle and it should not have to opt out of the shared component to\n * stay.\n *\n * `min-w-0` is not optional here. Without it a long title refuses to shrink and\n * pushes the actions off the row instead of wrapping — which is the bug the\n * three panels that set it had already hit, and the seven that did not had not\n * yet.\n */\nexport interface PageHeaderProps {\n title: React.ReactNode;\n description?: React.ReactNode;\n /**\n * Sits above the title: a breadcrumb, or the back link the filter editors\n * use. Four panels had one, each spacing it by hand.\n */\n eyebrow?: React.ReactNode;\n /** Buttons belonging to the page, laid out at the end of the title row. */\n actions?: React.ReactNode;\n className?: string;\n}\n\nexport function PageHeader({\n title,\n description,\n eyebrow,\n actions,\n className,\n}: PageHeaderProps) {\n const heading = (\n <div className=\"min-w-0\">\n {eyebrow}\n <h1\n className={cn(\n \"text-2xl font-semibold tracking-tight\",\n eyebrow != null && \"mt-1\",\n )}\n >\n {title}\n </h1>\n {description != null ? (\n <p className=\"text-muted-foreground mt-1 text-sm\">{description}</p>\n ) : null}\n </div>\n );\n\n if (!actions) {\n return <div className={className}>{heading}</div>;\n }\n\n return (\n <div\n className={cn(\n \"flex flex-wrap items-center justify-between gap-3\",\n className,\n )}\n >\n {heading}\n {actions}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type PanelBrandMarkProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Icon inside the mark (lucide, etc.). */\n children: React.ReactNode;\n size?: \"sm\" | \"md\";\n};\n\n/**\n * Quiet brand tile for sidebar / sign-in — solid primary, no decorative gradients.\n */\nexport function PanelBrandMark({\n children,\n size = \"md\",\n className,\n ...props\n}: PanelBrandMarkProps) {\n return (\n <div\n className={cn(\n \"bg-primary text-primary-foreground grid shrink-0 place-items-center rounded-lg\",\n size === \"sm\" ? \"h-9 w-9\" : \"h-10 w-10\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n","\"use client\";\n\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { PanelBrandMark } from \"./panel-brand-mark\";\nimport { cn } from \"./utils\";\n\nexport type PanelSignInProps = {\n appName: string;\n /** Short line under the brand (e.g. \"Secure Google sign-in\"). */\n eyebrow?: string;\n /** One supporting sentence under the headline. */\n description?: string;\n /** Optional feature bullets — keep to ≤3; DESIGN.md: one job per surface. */\n features?: string[];\n brandIcon?: React.ReactNode;\n error?: string | null;\n /** Google signed in but panel access refused. */\n refused?: boolean;\n refusedTitle?: string;\n refusedMessage?: string;\n isSessionLoading?: boolean;\n isSigningIn?: boolean;\n onSignIn: () => void;\n signInLabel?: string;\n className?: string;\n};\n\n/**\n * DESIGN.md-compliant panel login: brand-first, ink neutrals, no purple glow.\n */\nexport function PanelSignIn({\n appName,\n eyebrow = \"Secure Google sign-in\",\n description = \"Use your work Google account to continue.\",\n features,\n brandIcon,\n error,\n refused = false,\n refusedTitle = \"Access denied\",\n refusedMessage = \"This Google account is signed in, but it is not provisioned for this panel.\",\n isSessionLoading = false,\n isSigningIn = false,\n onSignIn,\n signInLabel = \"Continue with Google\",\n className,\n}: PanelSignInProps) {\n const busy = isSessionLoading || isSigningIn;\n\n return (\n <main\n className={cn(\n \"bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <section className=\"border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm\">\n <div className=\"flex items-center gap-3\">\n <PanelBrandMark>\n {brandIcon ?? (\n <span className=\"text-sm font-semibold\" aria-hidden>\n {appName.slice(0, 1).toUpperCase()}\n </span>\n )}\n </PanelBrandMark>\n <div className=\"min-w-0\">\n <p className=\"text-title truncate font-semibold\">{appName}</p>\n <p className=\"text-muted-foreground text-meta\">{eyebrow}</p>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <h1 className=\"text-display font-semibold tracking-tight\">\n {refused ? refusedTitle : \"Sign in\"}\n </h1>\n <p className=\"text-muted-foreground text-body\">\n {refused ? refusedMessage : description}\n </p>\n </div>\n\n {features && features.length > 0 && !refused ? (\n <ul className=\"text-muted-foreground text-body space-y-1.5\">\n {features.slice(0, 3).map((feature) => (\n <li key={feature} className=\"flex gap-2\">\n <span className=\"text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current\" />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n ) : null}\n\n {error ? (\n <p\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm\"\n >\n {error}\n </p>\n ) : null}\n\n <Button\n className=\"w-full\"\n disabled={busy}\n onClick={onSignIn}\n aria-busy={busy}\n >\n {busy ? (\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" aria-hidden />\n ) : null}\n {isSigningIn ? \"Redirecting…\" : signInLabel}\n </Button>\n </section>\n </main>\n );\n}\n\nexport function PanelSignInSkeleton({ className }: { className?: string }) {\n return (\n <main\n className={cn(\n \"bg-background grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <div className=\"border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm\">\n <div className=\"bg-muted h-3 w-24 animate-pulse rounded\" />\n <div className=\"bg-muted h-8 w-48 animate-pulse rounded\" />\n <div className=\"bg-muted mt-7 h-10 w-full animate-pulse rounded-md\" />\n </div>\n </main>\n );\n}\n","\"use client\";\n\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\n\nexport type PaginationProps = {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n loading?: boolean;\n showPageInfo?: boolean;\n};\n\n/**\n * Numbered pager for list panels. Hides itself when there is only one page.\n */\nexport function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n loading = false,\n showPageInfo = true,\n}: PaginationProps) {\n const visiblePages = React.useMemo(() => {\n const delta = 2;\n const range: number[] = [];\n const rangeWithDots: Array<number | \"...\"> = [];\n\n for (\n let i = Math.max(2, currentPage - delta);\n i <= Math.min(totalPages - 1, currentPage + delta);\n i++\n ) {\n range.push(i);\n }\n\n if (currentPage - delta > 2) {\n rangeWithDots.push(1, \"...\");\n } else {\n rangeWithDots.push(1);\n }\n\n rangeWithDots.push(...range);\n\n if (currentPage + delta < totalPages - 1) {\n rangeWithDots.push(\"...\", totalPages);\n } else if (totalPages > 1) {\n rangeWithDots.push(totalPages);\n }\n\n return rangeWithDots;\n }, [currentPage, totalPages]);\n\n if (totalPages <= 1) return null;\n\n return (\n <div className=\"flex flex-col items-center justify-between gap-4 sm:flex-row\">\n {showPageInfo ? (\n <div className=\"text-muted-foreground order-2 text-sm sm:order-1\">\n Page {currentPage} of {totalPages}\n </div>\n ) : null}\n\n <div className=\"order-1 flex items-center space-x-1 sm:order-2 sm:space-x-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1 || loading}\n className=\"h-8 min-w-8 px-2\"\n aria-label=\"Previous page\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n\n <div className=\"flex max-w-[200px] items-center space-x-1 overflow-x-auto sm:max-w-none\">\n {visiblePages.map((page, index) =>\n page === \"...\" ? (\n <div\n key={`dots-${index}`}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center\"\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </div>\n ) : (\n <Button\n key={page}\n variant={page === currentPage ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onPageChange(page)}\n disabled={loading}\n className=\"h-8 min-w-8 shrink-0 px-2\"\n aria-current={page === currentPage ? \"page\" : undefined}\n >\n {page}\n </Button>\n ),\n )}\n </div>\n\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages || loading}\n className=\"h-8 min-w-8 px-2\"\n aria-label=\"Next page\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one-of-N picker seven panels were each drawing by hand.\n *\n * Not `Tabs`, which is a bottom-bordered strip sitting above the content it\n * switches. This is the inline version — a bordered track with the selected\n * option filled in — used for a filter or a setting that sits among other\n * controls rather than heading a panel.\n *\n * **Roles are the reason to use this.** The seven copies had three different\n * ideas about what they were: one said `tablist`/`tab`, one said\n * `group`/`aria-pressed`, and the other five said nothing at all — so on five\n * of seven a screen reader heard a row of unlabelled buttons with no\n * indication which one was active. None of the three was right. `tablist`\n * without a `tabpanel` is a promise the markup does not keep, and\n * `aria-pressed` describes independent toggles, not a choice of one. Picking a\n * value out of a fixed set is a radio group, so that is what this is, with the\n * roving tabindex and arrow keys that come with the role.\n *\n * `tone` is kept for call-site compatibility. Both `emphasis` and `primary`\n * resolve to `bg-primary text-primary-foreground` — neutral brand primary is\n * already the ink fill five panels used, and a raw `slate-950` utility would\n * escape brand recoloring. Prefer `primary` in new code.\n */\nexport interface SegmentedOption<Value extends string> {\n value: Value;\n label: React.ReactNode;\n disabled?: boolean;\n /**\n * Hover text. Worth setting on a disabled option — \"Everyone\" going grey\n * says nothing about which permission would bring it back.\n */\n title?: string;\n}\n\nexport interface SegmentedControlProps<Value extends string> {\n options: ReadonlyArray<SegmentedOption<Value>>;\n value: Value;\n onChange: (value: Value) => void;\n /**\n * Required: the group never has a visible label — the options name the\n * choice between them, which tells you nothing about what is being chosen.\n */\n ariaLabel: string;\n /**\n * `contained` — one bordered track around the options (five panels).\n * `loose` — free-standing pills with a gap between them (two panels).\n */\n variant?: \"contained\" | \"loose\";\n /** Prefer `primary`. `emphasis` is an alias kept for existing call sites. */\n tone?: \"emphasis\" | \"primary\";\n /** Options share the width equally, for a control that fills its column. */\n fill?: boolean;\n className?: string;\n}\n\nconst TONE_ON = \"bg-primary text-primary-foreground\";\nconst TONE_OFF = \"text-muted-foreground hover:bg-muted\";\n\nconst TONES = {\n emphasis: { on: TONE_ON, off: TONE_OFF },\n primary: { on: TONE_ON, off: TONE_OFF },\n} as const;\n\nconst TRACKS = {\n contained: \"border-border inline-flex rounded-md border p-0.5\",\n loose: \"flex flex-wrap gap-2\",\n} as const;\n\nexport function SegmentedControl<Value extends string>({\n options,\n value,\n onChange,\n ariaLabel,\n variant = \"contained\",\n tone = \"emphasis\",\n fill = false,\n className,\n}: SegmentedControlProps<Value>) {\n const refs = React.useRef(new Map<Value, HTMLButtonElement | null>());\n\n function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step =\n event.key === \"ArrowRight\" || event.key === \"ArrowDown\"\n ? 1\n : event.key === \"ArrowLeft\" || event.key === \"ArrowUp\"\n ? -1\n : 0;\n if (step === 0) return;\n\n const selectable = options.filter((option) => !option.disabled);\n if (selectable.length < 2) return;\n\n const current = selectable.findIndex((option) => option.value === value);\n // Wraps, which is what a radio group is expected to do.\n const next =\n selectable[(current + step + selectable.length) % selectable.length];\n\n event.preventDefault();\n onChange(next.value);\n // The newly checked option has to take focus, or the next arrow press is\n // still measured from the old one.\n refs.current.get(next.value)?.focus();\n }\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n className={cn(TRACKS[variant], className)}\n >\n {options.map((option) => {\n const checked = option.value === value;\n return (\n <button\n key={option.value}\n ref={(node) => {\n refs.current.set(option.value, node);\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n disabled={option.disabled}\n title={option.title}\n // Only the checked option is reachable by Tab; arrows move within\n // the group. Without this a keyboard user pages through every\n // option to get past the control.\n tabIndex={checked ? 0 : -1}\n onClick={() => onChange(option.value)}\n className={cn(\n \"cursor-pointer rounded px-3 py-1 text-sm font-medium transition\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n fill && \"flex-1\",\n checked ? TONES[tone].on : TONES[tone].off,\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Autocomplete, type AutocompleteOption } from \"./autocomplete\";\n\ntype SelectChange = {\n target: { value: string };\n currentTarget: { value: string };\n};\n\nexport type SelectProps = {\n id?: string;\n className?: string;\n disabled?: boolean;\n /** Accessible name when the control is not wrapped in a label. */\n \"aria-label\"?: string;\n /** `compact` fits a spreadsheet cell. Typing still filters the list. */\n size?: \"default\" | \"compact\";\n value?: string | number | readonly string[];\n placeholder?: string;\n children?: React.ReactNode;\n onChange?: (event: SelectChange) => void;\n};\n\nfunction optionText(node: React.ReactNode): 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(optionText).join(\"\");\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return optionText(node.props.children);\n }\n return \"\";\n}\n\nfunction optionsFromChildren(children: React.ReactNode): AutocompleteOption[] {\n const options: AutocompleteOption[] = [];\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n if (child.type === React.Fragment) {\n options.push(\n ...optionsFromChildren(\n (child.props as { children?: React.ReactNode }).children,\n ),\n );\n return;\n }\n const props = child.props as {\n value?: string | number;\n disabled?: boolean;\n children?: React.ReactNode;\n };\n const value = props.value == null ? \"\" : String(props.value);\n options.push({\n value,\n label: optionText(props.children).trim() || value,\n disabled: Boolean(props.disabled),\n });\n });\n return options;\n}\n\n/**\n * The dropdown. It is the searchable autocomplete, not a native `<select>`,\n * so a long list can be typed into and an empty list still opens.\n */\nexport function Select({\n id,\n className,\n disabled,\n value,\n placeholder,\n children,\n onChange,\n size = \"default\",\n \"aria-label\": ariaLabel,\n}: SelectProps) {\n const options = optionsFromChildren(children);\n const current = Array.isArray(value)\n ? String(value[0] ?? \"\")\n : value == null\n ? \"\"\n : String(value);\n const blank = options.find((option) => option.value === \"\");\n\n return (\n <Autocomplete\n id={id}\n className={className}\n disabled={Boolean(disabled)}\n ariaLabel={ariaLabel}\n size={size}\n options={options}\n value={current}\n clearable={false}\n placeholder={placeholder ?? blank?.label ?? \"Search…\"}\n onChange={(next) =>\n onChange?.({\n target: { value: next },\n currentTarget: { value: next },\n })\n }\n />\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type SeparatorProps = React.HTMLAttributes<HTMLDivElement> & {\n orientation?: \"horizontal\" | \"vertical\";\n decorative?: boolean;\n};\n\n/** Thin rule between sections. */\nexport const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref,\n ) => (\n <div\n ref={ref}\n role={decorative ? \"none\" : \"separator\"}\n aria-orientation={orientation}\n className={cn(\n \"bg-border shrink-0\",\n orientation === \"horizontal\" ? \"h-px w-full\" : \"h-full w-px\",\n className,\n )}\n {...props}\n />\n ),\n);\n\nSeparator.displayName = \"Separator\";\n","\"use client\";\n\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { Button } from \"./button\";\nimport { useDialogLayer } from \"./dialogLayer\";\nimport { useHasMounted } from \"./modal\";\nimport { cn } from \"./utils\";\n\ninterface SideDrawerProps {\n isOpen: boolean;\n title: string;\n onClose: () => void;\n children: React.ReactNode;\n /** Tailwind width class for the panel. Defaults to a reading-width column. */\n panelClassName?: string;\n}\n\n/**\n * A panel that slides in from the right.\n *\n * For content that belongs beside the page rather than on top of it — a queue\n * you glance at and dismiss, not a decision you have to answer. Unlike\n * `Modal`, it does not centre or dim the whole page to a stop: the table\n * underneath stays readable, which is the point of looking at both.\n */\nexport function SideDrawer({\n isOpen,\n title,\n onClose,\n children,\n panelClassName,\n}: SideDrawerProps) {\n const mounted = useHasMounted();\n const headingId = React.useId();\n const panelRef = React.useRef<HTMLElement>(null);\n\n useDialogLayer({\n // Gated on `mounted` too: before that the panel is not rendered, so there\n // would be nothing to move focus into.\n active: isOpen && mounted,\n containerRef: panelRef,\n onEscape: onClose,\n });\n\n if (!mounted || !isOpen) return null;\n\n return createPortal(\n <>\n <div\n aria-hidden\n onClick={onClose}\n className=\"fixed inset-0 z-[90] bg-overlay/30\"\n />\n <aside\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={headingId}\n tabIndex={-1}\n className={cn(\n \"border-border bg-background fixed inset-y-0 right-0 z-[95] flex flex-col border-l shadow-2xl outline-none\",\n panelClassName ?? \"w-full max-w-md\",\n )}\n >\n <div className=\"border-border flex items-center justify-between gap-3 border-b px-4 py-3\">\n <h2 id={headingId} className=\"truncate text-base font-semibold\">\n {title}\n </h2>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Close panel\"\n onClick={onClose}\n >\n <X className=\"h-4 w-4\" aria-hidden />\n </Button>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">{children}</div>\n </aside>\n </>,\n document.body,\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { type CellRange, type CellRef } from \"./clipboard\";\n\n/**\n * A column knows three things: its heading, the text it contributes to a copy\n * or CSV export, and optionally how to draw itself.\n *\n * Keeping `value` and `render` together is what stops an exported sheet from\n * drifting from the visible grid.\n */\nexport type GridColumn<Row> = {\n key: string;\n title: string;\n /** Text used for clipboard and CSV. Never JSX. */\n value: (row: Row) => string;\n /** Defaults to `value`. Use for links, tiles, truncation. */\n render?: (row: Row) => React.ReactNode;\n /** Extra classes for the <td>. */\n className?: string;\n};\n\nexport interface SpreadsheetGridProps<Row> {\n columns: GridColumn<Row>[];\n rows: Row[];\n /** Stable React key per row. Defaults to the row index. */\n rowKey?: (row: Row, index: number) => string;\n loading?: boolean;\n emptyMessage?: string;\n loadingMessage?: string;\n ariaLabel?: string;\n /** Lifted so a toolbar can copy and describe the current selection. */\n range: CellRange | null;\n onRangeChange: (selection: {\n anchor: CellRef | null;\n focus: CellRef | null;\n }) => void;\n onCopy: () => void;\n}\n\nfunction isInRange(range: CellRange | null, r: number, c: number): boolean {\n if (!range) return false;\n return r >= range.r1 && r <= range.r2 && c >= range.c1 && c <= range.c2;\n}\n\n/**\n * Spreadsheet-like grid: click-drag a range, shift+click to extend, arrows to\n * move, click a heading to take the column, click the row number to take the\n * row, Cmd/Ctrl+A for everything, Escape to clear, Cmd/Ctrl+C to copy.\n *\n * Ported from video-shorts-panel's ExcelTable, which several panels share for\n * exactly this reason — a table people paste into a sheet.\n */\nexport function SpreadsheetGrid<Row>({\n columns,\n rows,\n rowKey,\n loading,\n emptyMessage = \"Nothing to show.\",\n loadingMessage = \"Loading…\",\n ariaLabel = \"Data grid\",\n range,\n onRangeChange,\n onCopy,\n}: SpreadsheetGridProps<Row>) {\n const gridRef = React.useRef<HTMLDivElement>(null);\n const anchorRef = React.useRef<CellRef | null>(null);\n const focusRef = React.useRef<CellRef | null>(null);\n const [dragging, setDragging] = React.useState(false);\n\n const setSelection = React.useCallback(\n (anchor: CellRef | null, focus: CellRef | null) => {\n anchorRef.current = anchor;\n focusRef.current = focus;\n onRangeChange({ anchor, focus });\n },\n [onRangeChange],\n );\n\n const selectCell = React.useCallback(\n (r: number, c: number, extend?: boolean) => {\n if (extend && anchorRef.current)\n setSelection(anchorRef.current, { r, c });\n else setSelection({ r, c }, { r, c });\n },\n [setSelection],\n );\n\n const selectColumn = React.useCallback(\n (c: number, extend?: boolean) => {\n const lastRow = Math.max(rows.length - 1, 0);\n const anchorCol = extend && anchorRef.current ? anchorRef.current.c : c;\n setSelection({ r: 0, c: anchorCol }, { r: lastRow, c });\n },\n [rows.length, setSelection],\n );\n\n const selectRow = React.useCallback(\n (r: number, extend?: boolean) => {\n const lastCol = columns.length - 1;\n const anchorRow = extend && anchorRef.current ? anchorRef.current.r : r;\n setSelection({ r: anchorRow, c: 0 }, { r, c: lastCol });\n },\n [columns.length, setSelection],\n );\n\n const selectAll = React.useCallback(() => {\n if (!rows.length || !columns.length) return;\n setSelection({ r: 0, c: 0 }, { r: rows.length - 1, c: columns.length - 1 });\n }, [rows.length, columns.length, setSelection]);\n\n const scrollCellIntoView = React.useCallback((r: number, c: number) => {\n const cell = gridRef.current?.querySelector(`[data-cell=\"${r}-${c}\"]`);\n cell?.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n }, []);\n\n const moveFocus = React.useCallback(\n (dr: number, dc: number, extend?: boolean) => {\n if (!rows.length || !columns.length) return;\n const base = focusRef.current || { r: 0, c: 0 };\n const r = Math.min(Math.max(base.r + dr, 0), rows.length - 1);\n const c = Math.min(Math.max(base.c + dc, 0), columns.length - 1);\n selectCell(r, c, extend);\n scrollCellIntoView(r, c);\n },\n [rows.length, columns.length, selectCell, scrollCellIntoView],\n );\n\n // Dragging must end even if the pointer is released outside the grid.\n React.useEffect(() => {\n if (!dragging) return;\n const stop = () => setDragging(false);\n window.addEventListener(\"mouseup\", stop);\n return () => window.removeEventListener(\"mouseup\", stop);\n }, [dragging]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const meta = event.metaKey || event.ctrlKey;\n if (meta && event.key.toLowerCase() === \"c\") {\n event.preventDefault();\n onCopy();\n return;\n }\n if (meta && event.key.toLowerCase() === \"a\") {\n event.preventDefault();\n selectAll();\n return;\n }\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n moveFocus(-1, 0, event.shiftKey);\n break;\n case \"ArrowDown\":\n event.preventDefault();\n moveFocus(1, 0, event.shiftKey);\n break;\n case \"ArrowLeft\":\n event.preventDefault();\n moveFocus(0, -1, event.shiftKey);\n break;\n case \"ArrowRight\":\n case \"Tab\":\n event.preventDefault();\n moveFocus(0, 1, event.shiftKey && event.key !== \"Tab\");\n break;\n case \"Escape\":\n setSelection(null, null);\n break;\n default:\n break;\n }\n };\n\n return (\n <div\n ref={gridRef}\n tabIndex={0}\n role=\"grid\"\n aria-label={ariaLabel}\n onKeyDown={handleKeyDown}\n className=\"border-border bg-background/80 overflow-x-auto rounded-lg border outline-none\"\n >\n <table className=\"w-full text-sm whitespace-nowrap select-none\">\n <thead className=\"text-muted-foreground border-border border-b text-left\">\n <tr>\n <th\n scope=\"col\"\n className=\"w-10 cursor-pointer px-2 py-2 text-center font-medium\"\n title=\"Select everything\"\n onMouseDown={() => selectAll()}\n >\n #\n </th>\n {columns.map((column, c) => (\n <th\n key={column.key}\n scope=\"col\"\n className=\"cursor-pointer px-3 py-2 font-medium\"\n title={`Select the ${column.title} column`}\n onMouseDown={(event) => selectColumn(c, event.shiftKey)}\n >\n {column.title}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length + 1}\n className=\"text-muted-foreground px-3 py-6 text-center\"\n >\n {loading ? loadingMessage : emptyMessage}\n </td>\n </tr>\n ) : (\n rows.map((row, r) => (\n <tr\n key={rowKey ? rowKey(row, r) : String(r)}\n className=\"border-border border-b\"\n >\n <td\n className=\"text-muted-foreground w-10 cursor-pointer px-2 py-2 text-center text-xs\"\n title=\"Select this row\"\n onMouseDown={(event) => selectRow(r, event.shiftKey)}\n >\n {r + 1}\n </td>\n {columns.map((column, c) => (\n <td\n key={column.key}\n data-cell={`${r}-${c}`}\n onMouseDown={(event) => {\n selectCell(r, c, event.shiftKey);\n setDragging(true);\n gridRef.current?.focus();\n }}\n onMouseEnter={() => {\n if (dragging) setSelection(anchorRef.current, { r, c });\n }}\n className={`px-3 py-2 ${column.className || \"\"} ${\n isInRange(range, r, c) ? \"bg-primary/15\" : \"\"\n }`}\n title={\n column.className?.includes(\"truncate\")\n ? column.value(row)\n : undefined\n }\n >\n {column.render ? column.render(row) : column.value(row)}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type SwitchProps = Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"onChange\"\n> & {\n checked: boolean;\n onCheckedChange: (checked: boolean) => void;\n};\n\n/** Compact accessible toggle — use instead of full-width checkbox inputs. */\nexport const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(\n ({ checked, onCheckedChange, className, disabled, id, ...props }, ref) => (\n <button\n ref={ref}\n id={id}\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled}\n onClick={() => onCheckedChange(!checked)}\n className={cn(\n // 24×44px track meets DESIGN.md 24px minimum target size.\n \"relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border transition-colors\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n checked ? \"border-primary bg-primary\" : \"border-border bg-muted\",\n className,\n )}\n {...props}\n >\n <span\n aria-hidden\n className={cn(\n \"bg-background pointer-events-none block size-5 rounded-full shadow-sm transition-transform\",\n checked ? \"translate-x-5\" : \"translate-x-0.5\",\n )}\n />\n </button>\n ),\n);\n\nSwitch.displayName = \"Switch\";\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * Low-level table primitives. Prefer `DataTable` for list panels; use these\n * when the row markup is custom (nested actions, expandable rows, etc.).\n */\nexport const Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n));\nTable.displayName = \"Table\";\n\nexport const TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n));\nTableHeader.displayName = \"TableHeader\";\n\nexport const TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n));\nTableBody.displayName = \"TableBody\";\n\nexport const TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n \"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0\",\n className,\n )}\n {...props}\n />\n));\nTableFooter.displayName = \"TableFooter\";\n\nexport const TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n \"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors\",\n className,\n )}\n {...props}\n />\n));\nTableRow.displayName = \"TableRow\";\n\nexport const TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"text-muted-foreground h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0\",\n className,\n )}\n {...props}\n />\n));\nTableHead.displayName = \"TableHead\";\n\nexport const TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n));\nTableCell.displayName = \"TableCell\";\n\nexport const TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn(\"text-muted-foreground mt-4 text-sm\", className)}\n {...props}\n />\n));\nTableCaption.displayName = \"TableCaption\";\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The tab strip five Managers were each drawing by hand, with the same\n * `rounded-t-md px-3 py-1.5 text-sm font-medium` and their own idea of what an\n * active tab looks like.\n *\n * It is a controlled component with no state of its own: every caller already\n * held the active key, usually because a URL or a query depends on it.\n *\n * Roles are the reason to use this rather than styling buttons again. A hand\n * -rolled strip is a row of buttons to a screen reader, which says nothing\n * about how many tabs there are or which is selected; `tablist` / `tab` /\n * `aria-selected` do. Arrow-key navigation comes with that expectation, so it\n * is implemented here too.\n *\n * Optional `panel` on a tab (or a sibling `TabPanel`) wires APG `aria-controls`\n * / `role=\"tabpanel\"`. Callers that already render content from `value` can\n * keep doing so and pass `panelId` for association, or switch to `panel`.\n */\nexport interface TabItem<Key extends string = string> {\n key: Key;\n label: React.ReactNode;\n /** Rendered after the label — a count, usually. */\n badge?: React.ReactNode;\n disabled?: boolean;\n /**\n * Optional panel body. When any tab provides `panel`, panels render under\n * the strip with `role=\"tabpanel\"`.\n */\n panel?: React.ReactNode;\n /**\n * External panel element id for `aria-controls` when panels live outside\n * this component.\n */\n panelId?: string;\n}\n\nexport interface TabsProps<Key extends string = string> {\n tabs: ReadonlyArray<TabItem<Key>>;\n value: Key;\n onChange: (key: Key) => void;\n /** Names the strip for screen readers. */\n ariaLabel?: string;\n className?: string;\n}\n\nexport interface TabPanelProps {\n /** Must match the controlling tab's generated or explicit id. */\n id: string;\n /** Id of the tab that labels this panel. */\n labelledBy: string;\n active: boolean;\n children: React.ReactNode;\n className?: string;\n}\n\n/** Companion panel for callers that keep content outside `Tabs`. */\nexport function TabPanel({\n id,\n labelledBy,\n active,\n children,\n className,\n}: TabPanelProps) {\n return (\n <div\n role=\"tabpanel\"\n id={id}\n aria-labelledby={labelledBy}\n hidden={!active}\n className={className}\n >\n {active ? children : null}\n </div>\n );\n}\n\nexport function Tabs<Key extends string = string>({\n tabs,\n value,\n onChange,\n ariaLabel,\n className,\n}: TabsProps<Key>) {\n const refs = React.useRef(new Map<Key, HTMLButtonElement | null>());\n const reactId = React.useId();\n const hasInlinePanels = tabs.some((tab) => tab.panel != null);\n\n function tabDomId(key: Key) {\n return `${reactId}-tab-${key}`;\n }\n\n function panelDomId(tab: TabItem<Key>) {\n return tab.panelId ?? `${reactId}-panel-${tab.key}`;\n }\n\n function focusTab(key: Key) {\n onChange(key);\n // The newly selected tab has to take focus, or the next arrow press is\n // still measured from the old one.\n refs.current.get(key)?.focus();\n }\n\n function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step =\n event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (step === 0) return;\n\n const selectable = tabs.filter((tab) => !tab.disabled);\n if (selectable.length < 2) return;\n\n const current = selectable.findIndex((tab) => tab.key === value);\n // Wraps, which is what a tablist is expected to do.\n const next =\n selectable[(current + step + selectable.length) % selectable.length];\n\n event.preventDefault();\n focusTab(next.key);\n }\n\n const tablist = (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n className={cn(\n \"border-border flex flex-wrap gap-1 border-b\",\n !hasInlinePanels ? className : undefined,\n )}\n >\n {tabs.map((tab) => {\n const active = tab.key === value;\n const id = tabDomId(tab.key);\n const controls =\n tab.panel != null || tab.panelId ? panelDomId(tab) : undefined;\n return (\n <button\n key={tab.key}\n id={id}\n ref={(node) => {\n refs.current.set(tab.key, node);\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n aria-controls={controls}\n disabled={tab.disabled}\n // Only the active tab is reachable by Tab; arrows move within the\n // strip. Without this a keyboard user pages through every tab to\n // get past the strip.\n tabIndex={active ? 0 : -1}\n onClick={() => onChange(tab.key)}\n className={cn(\n \"cursor-pointer rounded-t-md px-3 py-1.5 text-sm font-medium transition\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n // The filled-pill active state the five hand-rolled strips\n // already used. Adopting it keeps this a deduplication rather\n // than a restyle of every panel that has tabs.\n active\n ? \"bg-primary text-primary-foreground\"\n : \"text-muted-foreground hover:bg-muted\",\n )}\n >\n {tab.label}\n {tab.badge != null ? (\n <span className=\"text-muted-foreground ml-1.5 text-xs\">\n {tab.badge}\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n );\n\n if (!hasInlinePanels) return tablist;\n\n return (\n <div className={cn(\"space-y-3\", className)}>\n {tablist}\n {tabs.map((tab) =>\n tab.panel != null ? (\n <TabPanel\n key={tab.key}\n id={panelDomId(tab)}\n labelledBy={tabDomId(tab.key)}\n active={tab.key === value}\n >\n {tab.panel}\n </TabPanel>\n ) : null,\n )}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The multi-line counterpart to `Input`.\n *\n * There was no shared textarea, so sixteen of them were styled individually\n * and no two agreed — different borders, different focus rings, some with no\n * focus ring at all, which is a keyboard user losing their place.\n *\n * Deliberately not `inputClass`: that fixes `h-9`, which is a one-line\n * control. Everything else is shared so a textarea and an input sitting in the\n * same form look related.\n */\nexport const textareaClass =\n \"border-border bg-background focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, rows = 3, ...props }, ref) => (\n <textarea\n ref={ref}\n rows={rows}\n className={cn(textareaClass, className)}\n {...props}\n />\n ),\n);\n\nTextarea.displayName = \"Textarea\";\n"],"mappings":"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","names":["React","import_react_dom","React","React","active","import_jsx_runtime","import_jsx_runtime","React","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_jsx_runtime","React","import_class_variance_authority","import_lucide_react","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","React","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_lucide_react","React","React","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","import_lucide_react","React","import_react_dom","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/alert.tsx","../src/utils.ts","../src/autocomplete.tsx","../src/modal.tsx","../src/dialogLayer.ts","../src/badge.tsx","../src/breadcrumb.tsx","../src/button.tsx","../src/spinner.tsx","../src/card.tsx","../src/checkbox.tsx","../src/clipboard.ts","../src/collapsible.tsx","../src/confirm-dialog.tsx","../src/copy-button.tsx","../src/data-table.tsx","../src/date-range-picker/index.tsx","../src/date-range-picker/dateRange.ts","../src/dialog.tsx","../src/dropdown-menu.tsx","../src/state-panel.tsx","../src/feature-access-gate.tsx","../src/field.tsx","../src/image-uploader.tsx","../src/input.tsx","../src/label.tsx","../src/page-header.tsx","../src/panel-brand-mark.tsx","../src/panel-sign-in.tsx","../src/pagination.tsx","../src/segmented-control.tsx","../src/select.tsx","../src/separator.tsx","../src/side-drawer.tsx","../src/spreadsheet-grid.tsx","../src/switch.tsx","../src/table.tsx","../src/tabs.tsx","../src/textarea.tsx"],"sourcesContent":["export * from \"./alert\";\nexport * from \"./autocomplete\";\nexport * from \"./badge\";\nexport * from \"./breadcrumb\";\nexport * from \"./button\";\nexport * from \"./card\";\nexport * from \"./checkbox\";\nexport * from \"./clipboard\";\nexport * from \"./collapsible\";\nexport * from \"./confirm-dialog\";\nexport * from \"./copy-button\";\nexport * from \"./data-table\";\nexport * from \"./date-range-picker\";\nexport * from \"./date-range-picker/dateRange\";\nexport * from \"./dialog\";\nexport * from \"./dialogLayer\";\nexport * from \"./dropdown-menu\";\nexport * from \"./feature-access-gate\";\nexport * from \"./field\";\nexport * from \"./image-uploader\";\nexport * from \"./input\";\nexport * from \"./label\";\nexport * from \"./modal\";\nexport * from \"./page-header\";\nexport * from \"./panel-brand-mark\";\nexport * from \"./panel-sign-in\";\nexport * from \"./pagination\";\nexport * from \"./segmented-control\";\nexport * from \"./select\";\nexport * from \"./separator\";\nexport * from \"./side-drawer\";\nexport * from \"./spinner\";\nexport * from \"./spreadsheet-grid\";\nexport * from \"./state-panel\";\nexport * from \"./switch\";\nexport * from \"./table\";\nexport * from \"./tabs\";\nexport * from \"./textarea\";\nexport * from \"./utils\";\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The inline message banner — a failed load, a warning above a form, a note.\n *\n * This was the most duplicated markup in the panel: thirty blocks across\n * twenty-eight files, spelled seven different ways. `px-3 py-2` in most places\n * and `px-4 py-3` in others, `text-rose-700` here and `text-destructive`\n * there — all meaning \"something went wrong\".\n *\n * `role` is derived from the variant rather than left to callers. An error a\n * user needs to act on should interrupt a screen reader; a note should not.\n * Almost none of the hand-rolled copies set either.\n */\nconst alertVariants = cva(\"rounded-lg border px-3 py-2 text-sm\", {\n variants: {\n variant: {\n danger: \"border-destructive/30 bg-destructive/5 text-destructive\",\n warning: \"border-warning/30 bg-warning/5 text-warning\",\n success: \"border-success/30 bg-success/5 text-success\",\n info: \"border-info/30 bg-info/5 text-info\",\n /**\n * The quiet state of a banner that also has loud ones — \"no default\n * campaign set\" next to \"this is the default\". Without it those callers\n * keep a ternary of raw class strings and the shared component only\n * covers half of what they draw.\n */\n neutral: \"border-border bg-muted/40 text-muted-foreground\",\n },\n },\n defaultVariants: {\n // Failure is what a banner almost always reports here, and defaulting to\n // it means the noisy case cannot be forgotten.\n variant: \"danger\",\n },\n});\n\nexport interface AlertProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof alertVariants> {\n /**\n * A control belonging to the message, such as Retry. Given one, the banner\n * lays out as a row and keeps the action at its end.\n */\n action?: React.ReactNode;\n}\n\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n ({ className, variant, action, children, ...props }, ref) => (\n <div\n ref={ref}\n role={variant === \"danger\" || variant == null ? \"alert\" : \"status\"}\n className={cn(\n alertVariants({ variant }),\n action && \"flex flex-wrap items-center justify-between gap-3\",\n className,\n )}\n {...props}\n >\n {/* Wrapped so the action sits opposite the text rather than being\n pushed around by whatever the caller passed as children. */}\n {action ? <span>{children}</span> : children}\n {action}\n </div>\n ),\n);\n\nAlert.displayName = \"Alert\";\n\nexport { alertVariants };\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Check, ChevronDown, Search, X } from \"lucide-react\";\n\nimport { useHasMounted } from \"./modal\";\nimport { cn } from \"./utils\";\n\n/** Room the list wants below the control before it gives up and flips. */\nconst PREFERRED_LIST_HEIGHT = 224;\n/** Below this there is no point opening downward at all. */\nconst MIN_LIST_HEIGHT = 120;\nconst VIEWPORT_MARGIN = 8;\nconst ANCHOR_GAP = 4;\n\ntype DropdownPosition = {\n left: number;\n width: number;\n maxHeight: number;\n /** One of the two is set: `top` opens downward, `bottom` opens upward. */\n top?: number;\n bottom?: number;\n};\n\nexport type AutocompleteOption = {\n value: string;\n label: string;\n disabled?: boolean;\n};\n\ntype BaseAutocompleteProps = {\n options: AutocompleteOption[];\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n emptyMessage?: string;\n id?: string;\n /**\n * Accessible name for the combobox.\n *\n * `Field` renders its label as a `<span>`, so without this the control is\n * announced as an unnamed combobox and cannot be queried by name — the\n * filter toolbars work around it by counting comboboxes on the page.\n */\n ariaLabel?: string;\n /**\n * `compact` is the spreadsheet cell: no search icon, no min height, and a\n * list wide enough to read a name. The closed control still shows the\n * chosen label, and typing filters the list.\n */\n size?: \"default\" | \"compact\";\n /**\n * Type a value and press Enter (or paste a list) to add it, like antd\n * `Select mode=\"tags\"`. With `multiple` a pasted list is split into several\n * values; on a single-value control it accepts one typed value the options\n * do not offer — an id for a record the list has not loaded, say.\n */\n creatable?: boolean;\n /**\n * Shows the clear button once a value is chosen. Off for dropdowns that\n * always keep one of their options, where clearing would blank a required\n * field.\n */\n clearable?: boolean;\n};\n\ntype SingleAutocompleteProps = BaseAutocompleteProps & {\n multiple?: false;\n value: string;\n onChange: (value: string) => void;\n};\n\ntype MultipleAutocompleteProps = BaseAutocompleteProps & {\n multiple: true;\n value: string[];\n onChange: (value: string[]) => void;\n};\n\nexport type AutocompleteProps =\n SingleAutocompleteProps | MultipleAutocompleteProps;\n\nfunction normalizeQuery(query: string) {\n return query.trim().toLowerCase();\n}\n\nfunction filterOptions(options: AutocompleteOption[], query: string) {\n const normalized = normalizeQuery(query);\n if (!normalized) return options;\n\n return options.filter(\n (option) =>\n option.label.toLowerCase().includes(normalized) ||\n option.value.toLowerCase().includes(normalized),\n );\n}\n\nfunction getOptionLabel(options: AutocompleteOption[], value: string) {\n return options.find((option) => option.value === value)?.label ?? value;\n}\n\nfunction parseTagTokens(raw: string): string[] {\n const seen = new Set<string>();\n const tokens: string[] = [];\n for (const part of raw.split(/[\\s,]+/)) {\n const token = part.trim();\n if (!token || seen.has(token)) continue;\n seen.add(token);\n tokens.push(token);\n }\n return tokens;\n}\n\nexport function Autocomplete(props: AutocompleteProps) {\n const {\n options,\n placeholder = \"Search…\",\n disabled = false,\n className,\n emptyMessage = \"No results found\",\n id,\n ariaLabel,\n size = \"default\",\n creatable = false,\n clearable = true,\n } = props;\n\n const multiple = props.multiple ?? false;\n const singleValue = multiple\n ? undefined\n : (props as SingleAutocompleteProps).value;\n const multipleValue = multiple\n ? (props as MultipleAutocompleteProps).value\n : undefined;\n\n // Memoized so dependent callbacks below keep stable identities across renders.\n const selectedValues = React.useMemo<string[]>(() => {\n if (multiple) return multipleValue ?? [];\n return singleValue ? [singleValue] : [];\n }, [multiple, multipleValue, singleValue]);\n\n const onSingleChange = !multiple\n ? (props as SingleAutocompleteProps).onChange\n : undefined;\n const onMultipleChange = multiple\n ? (props as MultipleAutocompleteProps).onChange\n : undefined;\n\n const containerRef = React.useRef<HTMLDivElement>(null);\n const dropdownRef = React.useRef<HTMLDivElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const listRef = React.useRef<HTMLUListElement>(null);\n const ignoreBlurRef = React.useRef(false);\n\n const mounted = useHasMounted();\n const [open, setOpen] = React.useState(false);\n const [position, setPosition] = React.useState<DropdownPosition | null>(null);\n const [query, setQuery] = React.useState(\"\");\n const [highlightedIndex, setHighlightedIndex] = React.useState(0);\n\n const filteredOptions = React.useMemo(\n () => filterOptions(options, query),\n [options, query],\n );\n\n // Clamp during render instead of via a setState-in-effect: if the option list\n // shrinks below the stored index, fall back to the last valid row.\n const safeHighlightedIndex =\n highlightedIndex >= filteredOptions.length\n ? Math.max(filteredOptions.length - 1, 0)\n : highlightedIndex;\n\n const close = React.useCallback(() => {\n setOpen(false);\n setQuery(\"\");\n setHighlightedIndex(0);\n }, []);\n\n const openDropdown = React.useCallback(() => {\n if (disabled) return;\n setOpen(true);\n setHighlightedIndex(0);\n }, [disabled]);\n\n const commitSingleValue = React.useCallback(\n (value: string) => {\n if (!multiple) {\n onSingleChange?.(value);\n close();\n }\n },\n [close, multiple, onSingleChange],\n );\n\n const toggleMultipleValue = React.useCallback(\n (value: string) => {\n if (!multiple || !onMultipleChange) return;\n\n onMultipleChange(\n selectedValues.includes(value)\n ? selectedValues.filter((item) => item !== value)\n : [...selectedValues, value],\n );\n setQuery(\"\");\n setHighlightedIndex(0);\n },\n [multiple, onMultipleChange, selectedValues],\n );\n\n const commitCustomValues = React.useCallback(\n (raw: string) => {\n if (!creatable) return;\n\n if (!multiple) {\n const value = raw.trim();\n if (!value) return;\n commitSingleValue(value);\n return;\n }\n\n if (!onMultipleChange) return;\n const tokens = parseTagTokens(raw);\n if (!tokens.length) return;\n const next = [...selectedValues];\n for (const token of tokens) {\n if (!next.includes(token)) next.push(token);\n }\n onMultipleChange(next);\n setQuery(\"\");\n setHighlightedIndex(0);\n },\n [commitSingleValue, creatable, multiple, onMultipleChange, selectedValues],\n );\n\n const removeValue = React.useCallback(\n (value: string) => {\n if (!multiple || !onMultipleChange) return;\n onMultipleChange(selectedValues.filter((item) => item !== value));\n window.requestAnimationFrame(() => inputRef.current?.focus());\n },\n [multiple, onMultipleChange, selectedValues],\n );\n\n const selectOption = React.useCallback(\n (option: AutocompleteOption) => {\n if (option.disabled) return;\n\n ignoreBlurRef.current = true;\n window.setTimeout(() => {\n ignoreBlurRef.current = false;\n }, 0);\n\n if (multiple) {\n toggleMultipleValue(option.value);\n window.requestAnimationFrame(() => inputRef.current?.focus());\n return;\n }\n\n commitSingleValue(option.value);\n },\n [commitSingleValue, multiple, toggleMultipleValue],\n );\n\n const selectHighlighted = React.useCallback(() => {\n const option = filteredOptions[safeHighlightedIndex];\n if (!option) return;\n selectOption(option);\n }, [filteredOptions, safeHighlightedIndex, selectOption]);\n\n React.useEffect(() => {\n if (!open) return;\n\n function handlePointerDown(event: PointerEvent) {\n const target = event.target as Node;\n // The list is portalled to the body, so containment has to be checked\n // against both halves or picking an option would close the control\n // before the choice registered.\n if (\n containerRef.current?.contains(target) ||\n dropdownRef.current?.contains(target)\n ) {\n return;\n }\n close();\n }\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [close, open]);\n\n /*\n The list is measured against the viewport and rendered in a portal.\n\n Anchored inside the control it was clipped by whatever `overflow` ancestor\n happened to be above it — inside a dialog body that is the scroll region,\n so the last field on a form showed one row of a six-hundred-row list. It\n opens downward when there is room, upward when there is not, and shrinks to\n what is left when neither side can take the whole list.\n */\n React.useLayoutEffect(() => {\n // Not cleared on close: the render is gated on `open`, and the layout\n // effect recomputes before the next paint, so a stale value is never seen.\n if (!open) return;\n\n const update = () => {\n const anchor = containerRef.current;\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n const below =\n window.innerHeight - rect.bottom - ANCHOR_GAP - VIEWPORT_MARGIN;\n const above = rect.top - ANCHOR_GAP - VIEWPORT_MARGIN;\n const flip =\n below < Math.min(PREFERRED_LIST_HEIGHT, MIN_LIST_HEIGHT) &&\n above > below;\n const room = flip ? above : below;\n const width = Math.max(rect.width, size === \"compact\" ? 220 : 0);\n const left = Math.max(\n VIEWPORT_MARGIN,\n Math.min(rect.left, window.innerWidth - width - VIEWPORT_MARGIN),\n );\n setPosition({\n left,\n width,\n maxHeight: Math.max(\n MIN_LIST_HEIGHT,\n Math.min(PREFERRED_LIST_HEIGHT, room),\n ),\n ...(flip\n ? { bottom: window.innerHeight - rect.top + ANCHOR_GAP }\n : { top: rect.bottom + ANCHOR_GAP }),\n });\n };\n\n update();\n // Capture, so a scroll in any ancestor — the dialog body included — moves\n // the list with its control instead of leaving it behind.\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open, size]);\n\n React.useEffect(() => {\n if (!open || !listRef.current) return;\n\n const highlighted = listRef.current.children[safeHighlightedIndex] as\n HTMLElement | undefined;\n\n highlighted?.scrollIntoView({ block: \"nearest\" });\n }, [safeHighlightedIndex, open]);\n\n function handleInputKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {\n if (disabled) return;\n\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!open) {\n openDropdown();\n return;\n }\n setHighlightedIndex(\n Math.min(safeHighlightedIndex + 1, filteredOptions.length - 1),\n );\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!open) {\n openDropdown();\n return;\n }\n setHighlightedIndex(Math.max(safeHighlightedIndex - 1, 0));\n break;\n case \"Enter\":\n event.preventDefault();\n if (creatable && query.trim()) {\n // A single-value control filters its list as you type, so a match\n // is what Enter means there; only an unmatched query is taken as a\n // new value. Tags have no such list to defer to.\n if (multiple || filteredOptions.length === 0) {\n commitCustomValues(query);\n return;\n }\n }\n if (!open) {\n openDropdown();\n return;\n }\n selectHighlighted();\n break;\n case \",\":\n if (creatable && multiple && query.trim()) {\n event.preventDefault();\n commitCustomValues(query);\n }\n break;\n case \"Escape\":\n event.preventDefault();\n close();\n break;\n case \"Backspace\":\n if (multiple && query.length === 0 && selectedValues.length > 0) {\n event.preventDefault();\n removeValue(selectedValues[selectedValues.length - 1]);\n }\n break;\n case \"Tab\":\n close();\n break;\n default:\n break;\n }\n }\n\n const displayValue =\n !multiple && !open && !query && selectedValues[0]\n ? getOptionLabel(options, selectedValues[0])\n : query;\n\n const inputPlaceholder =\n multiple && selectedValues.length > 0 ? \"\" : placeholder;\n\n const createLabel = query.trim();\n const canCreate =\n creatable && Boolean(createLabel) && !selectedValues.includes(createLabel);\n\n const listboxId = id ? `${id}-listbox` : undefined;\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"relative\",\n size === \"compact\" ? \"w-auto min-w-24\" : \"w-full\",\n className,\n )}\n >\n <div\n className={cn(\n \"border-border bg-background flex w-full cursor-pointer items-center rounded-md border transition-colors\",\n \"focus-within:border-ring focus-within:ring-ring/30 focus-within:ring-2\",\n size === \"compact\"\n ? \"min-h-0 gap-0.5 border-transparent bg-transparent px-1 py-0.5 text-xs shadow-none\"\n : \"min-h-9 gap-1.5 px-2 py-1.5 text-sm shadow-sm\",\n disabled && \"cursor-not-allowed opacity-50\",\n open && \"border-ring ring-ring/30 ring-2\",\n )}\n onPointerDown={(event) => {\n if (disabled) return;\n if ((event.target as HTMLElement).closest(\"[data-option]\")) return;\n if ((event.target as HTMLElement).closest(\"[data-chip-remove]\"))\n return;\n\n if (!(event.target as HTMLElement).closest(\"input\")) {\n event.preventDefault();\n inputRef.current?.focus();\n }\n\n openDropdown();\n }}\n >\n {size === \"compact\" ? null : (\n <Search className=\"text-muted-foreground size-4 shrink-0\" />\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-1\">\n {multiple &&\n selectedValues.map((value) => (\n <span\n key={value}\n className=\"bg-primary/10 text-primary inline-flex max-w-full items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium\"\n >\n <span className=\"truncate\">\n {getOptionLabel(options, value)}\n </span>\n <button\n type=\"button\"\n data-chip-remove\n className=\"text-primary/70 hover:bg-primary/15 hover:text-primary rounded-sm transition\"\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n removeValue(value);\n }}\n aria-label={`Remove ${getOptionLabel(options, value)}`}\n >\n <X className=\"size-3\" />\n </button>\n </span>\n ))}\n\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n role=\"combobox\"\n aria-label={ariaLabel}\n aria-expanded={open}\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n disabled={disabled}\n value={displayValue}\n placeholder={inputPlaceholder}\n className={cn(\n \"placeholder:text-muted-foreground flex-1 bg-transparent outline-none\",\n size === \"compact\" ? \"min-w-0\" : \"min-w-[6rem]\",\n )}\n onFocus={openDropdown}\n onBlur={() => {\n if (ignoreBlurRef.current) return;\n close();\n }}\n onChange={(event) => {\n setQuery(event.target.value);\n setHighlightedIndex(0);\n if (!open) setOpen(true);\n }}\n onKeyDown={handleInputKeyDown}\n onPaste={(event) => {\n if (!creatable || !multiple) return;\n const text = event.clipboardData.getData(\"text\");\n if (!/[\\s,]/.test(text)) return;\n event.preventDefault();\n commitCustomValues(text);\n }}\n />\n </div>\n\n {clearable && !multiple && selectedValues[0] && !disabled && (\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground rounded-sm p-0.5 transition\"\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onSingleChange?.(\"\");\n setQuery(\"\");\n inputRef.current?.focus();\n }}\n aria-label=\"Clear selection\"\n >\n <X className=\"size-3.5\" />\n </button>\n )}\n\n <ChevronDown\n className={cn(\n \"text-muted-foreground shrink-0 transition-transform\",\n size === \"compact\" ? \"size-3\" : \"size-4\",\n open && \"rotate-180\",\n )}\n />\n </div>\n\n {open && mounted && position\n ? createPortal(\n <div\n ref={dropdownRef}\n data-autocomplete-dropdown\n style={{\n position: \"fixed\",\n left: position.left,\n width: position.width,\n top: position.top,\n bottom: position.bottom,\n // Above the modal shell (z-100) it is usually opened inside.\n zIndex: 200,\n }}\n className=\"border-border bg-background overflow-hidden rounded-md border shadow-lg\"\n >\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n className=\"overflow-y-auto p-1\"\n style={{ maxHeight: position.maxHeight }}\n >\n {filteredOptions.length === 0 && !canCreate ? (\n <li className=\"text-muted-foreground px-3 py-6 text-center text-sm\">\n {emptyMessage}\n </li>\n ) : (\n <>\n {filteredOptions.map((option, index) => {\n const isSelected = selectedValues.includes(option.value);\n const isHighlighted = index === safeHighlightedIndex;\n\n return (\n <li\n key={option.value}\n data-option\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled || undefined}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm transition-colors\",\n size === \"compact\"\n ? \"px-2 py-1 text-xs\"\n : \"px-2.5 py-2 text-sm\",\n isHighlighted && \"bg-muted\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n onMouseEnter={() => setHighlightedIndex(index)}\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n selectOption(option);\n }}\n >\n {multiple ? (\n <span\n className={cn(\n \"border-border flex size-4 shrink-0 items-center justify-center rounded border\",\n isSelected &&\n \"border-primary bg-primary text-primary-foreground\",\n )}\n >\n {isSelected ? <Check className=\"size-3\" /> : null}\n </span>\n ) : (\n <Check\n className={cn(\n \"text-primary size-4 shrink-0\",\n isSelected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n )}\n <span className=\"truncate\">{option.label}</span>\n </li>\n );\n })}\n {canCreate ? (\n <li\n data-option\n role=\"option\"\n aria-selected={false}\n className=\"hover:bg-muted flex cursor-pointer items-center gap-2 rounded-sm px-2.5 py-2 text-sm transition-colors\"\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n ignoreBlurRef.current = true;\n window.setTimeout(() => {\n ignoreBlurRef.current = false;\n }, 0);\n commitCustomValues(query);\n window.requestAnimationFrame(() =>\n inputRef.current?.focus(),\n );\n }}\n >\n Add “{createLabel}”\n </li>\n ) : null}\n </>\n )}\n </ul>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { useDialogLayer } from \"./dialogLayer\";\nimport { cn } from \"./utils\";\n\nconst emptySubscribe = () => () => {};\n\n/**\n * Returns false during SSR and the first client render, then true once mounted.\n * `useSyncExternalStore` is the React-recommended way to read client-only state\n * without a setState-in-effect (which triggers cascading renders).\n */\nexport function useHasMounted(): boolean {\n return React.useSyncExternalStore(\n emptySubscribe,\n () => true,\n () => false,\n );\n}\n\ninterface ModalProps {\n isOpen: boolean;\n /** id of the element labelling the dialog; wired to aria-labelledby. */\n labelledBy: string;\n /**\n * Optional id(s) of elements describing the dialog (APG alertdialog body).\n * Space-separated when multiple.\n */\n describedBy?: string;\n /** Accessible label for the backdrop dismiss button. */\n closeLabel: string;\n onClose: () => void;\n children: React.ReactNode;\n /**\n * When false, Escape and backdrop clicks do not close the modal (e.g. while a\n * save is in flight). Defaults to true.\n */\n dismissible?: boolean;\n /** Use \"alertdialog\" for destructive confirmations. Defaults to \"dialog\". */\n role?: \"dialog\" | \"alertdialog\";\n /** Tailwind max-width class for the panel. Defaults to \"max-w-md\". */\n panelClassName?: string;\n}\n\n/**\n * Shared modal shell: renders a portal-backed, scroll-locked, Escape-dismissible\n * overlay with a centered panel. Callers provide the panel body (heading, form,\n * footer). Consolidates the boilerplate previously copied across every dialog.\n */\nexport function Modal({\n isOpen,\n labelledBy,\n describedBy,\n closeLabel,\n onClose,\n children,\n dismissible = true,\n role = \"dialog\",\n panelClassName,\n}: ModalProps) {\n const mounted = useHasMounted();\n const panelRef = React.useRef<HTMLDivElement>(null);\n\n useDialogLayer({\n // Gated on `mounted` too: before that the panel is not rendered, so there\n // would be nothing to move focus into.\n active: isOpen && mounted,\n containerRef: panelRef,\n onEscape: dismissible ? onClose : undefined,\n });\n\n if (!mounted || !isOpen) return null;\n\n return createPortal(\n /*\n `overflow-y-auto` on the overlay, `my-auto` on the panel — not\n `items-center`. A flex item centred with `align-items` overflows equally\n in both directions once it is taller than its container, and the half\n above the top edge cannot be scrolled to: with the page behind it locked,\n an over-tall dialog was simply unreachable at both ends. Auto margins\n centre a short panel the same way and collapse to zero on a tall one,\n which scrolls.\n */\n <div className=\"fixed inset-0 z-[100] flex justify-center overflow-y-auto p-4\">\n {/* `fixed`, not `absolute`: inside a scrolling overlay an absolute\n backdrop scrolls away with the content and leaves the rest of a tall\n dialog sitting on an undimmed page. */}\n <button\n type=\"button\"\n aria-label={closeLabel}\n tabIndex={-1}\n className=\"fixed inset-0 bg-overlay/50\"\n onClick={() => {\n if (dismissible) onClose();\n }}\n />\n <div\n ref={panelRef}\n role={role}\n aria-modal=\"true\"\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n tabIndex={-1}\n className={cn(\n \"border-border bg-background relative z-10 my-auto w-full rounded-lg border shadow-2xl outline-none\",\n panelClassName ?? \"max-w-md p-6\",\n )}\n >\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\n/**\n * The keyboard and focus behaviour every dialog needs, in one place.\n *\n * `Modal` and `SideDrawer` each had a copy of the scroll lock and an Escape\n * handler, and neither did anything about focus: opening a dialog left focus\n * on the button behind it, Tab walked the page underneath — through the\n * full-screen backdrop button, among other things — and closing left focus\n * wherever it had wandered. That is the whole keyboard story for thirty\n * dialogs, so it is fixed once here rather than thirty times.\n */\n\n/**\n * Open dialogs, innermost last.\n *\n * Nesting is real here — \"Create audience group\" opens on top of \"Send\n * notification\" — and without an ordering both would answer the same Escape\n * and fight over the same Tab. Only the top layer acts.\n */\nconst layers: symbol[] = [];\n\nconst FOCUSABLE = [\n \"a[href]\",\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(\",\");\n\n/**\n * Deliberately not `offsetParent` or `getClientRects`: the first is null for\n * anything `position: fixed`, which a dialog panel usually is, and the second\n * is empty for *everything* under a test renderer that does no layout — which\n * would collapse the trap to \"no focusable elements\" in every test.\n */\nfunction isVisible(element: HTMLElement): boolean {\n if (element.closest(\"[hidden]\")) return false;\n if (element.getAttribute(\"aria-hidden\") === \"true\") return false;\n return typeof element.checkVisibility === \"function\"\n ? element.checkVisibility()\n : true;\n}\n\nfunction focusableWithin(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n isVisible,\n );\n}\n\nexport function useDialogLayer({\n active,\n containerRef,\n onEscape,\n}: {\n active: boolean;\n /** The panel. Focus is moved into it and kept inside it. */\n containerRef: React.RefObject<HTMLElement | null>;\n /** Called on Escape, only while this is the top layer. Omit to ignore it. */\n onEscape?: () => void;\n}): void {\n // Read through a ref so a caller passing a fresh closure every render does\n // not tear the listener down and rebuild it on every keystroke.\n const escapeRef = React.useRef(onEscape);\n React.useEffect(() => {\n escapeRef.current = onEscape;\n });\n\n React.useEffect(() => {\n if (!active) return;\n\n const layer = Symbol(\"dialog-layer\");\n layers.push(layer);\n const isTopLayer = () => layers[layers.length - 1] === layer;\n\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n\n const container = containerRef.current;\n // Something inside may have claimed focus already — an `autoFocus` input —\n // and that choice is better than any this could make.\n if (container && !container.contains(document.activeElement)) {\n const [first] = focusableWithin(container);\n // The panel itself, not its first control: the first control is a Delete\n // button often enough that focusing it would put a destructive action\n // one Enter away from an accidental keypress.\n (container.hasAttribute(\"tabindex\") ? container : first)?.focus();\n }\n\n function handleKeyDown(event: KeyboardEvent) {\n if (!isTopLayer()) return;\n\n if (event.key === \"Escape\") {\n escapeRef.current?.();\n return;\n }\n\n if (event.key !== \"Tab\") return;\n const panel = containerRef.current;\n if (!panel) return;\n\n const items = focusableWithin(panel);\n if (items.length === 0) {\n event.preventDefault();\n panel.focus();\n return;\n }\n\n const first = items[0]!;\n const last = items[items.length - 1]!;\n const active = document.activeElement;\n const outside = !panel.contains(active);\n\n if (event.shiftKey && (active === first || outside)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (active === last || outside)) {\n event.preventDefault();\n first.focus();\n }\n }\n\n document.addEventListener(\"keydown\", handleKeyDown);\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n document.body.style.overflow = previousOverflow;\n const index = layers.indexOf(layer);\n if (index !== -1) layers.splice(index, 1);\n // Back where it came from, so closing a dialog opened by keyboard does\n // not drop the caret at the top of the document.\n if (previouslyFocused?.isConnected) previouslyFocused.focus();\n };\n }, [active, containerRef]);\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The status pill every list panel was spelling out by hand.\n *\n * Variants are semantic rather than named after a colour, because the same\n * status means the same thing on every panel and should not have to be\n * re-decided per table — Deleted was `bg-rose-100 text-rose-800` in one place\n * and `text-rose-900` two files away.\n *\n * These stay light-on-dark-text in both themes on purpose. A pill is a small\n * block of colour whose whole job is to be picked out of a row of text, and\n * inverting it per theme made the same status read as two different states.\n */\nconst badgeVariants = cva(\n \"inline-flex items-center gap-1 rounded font-medium whitespace-nowrap\",\n {\n variants: {\n variant: {\n neutral: \"bg-muted text-muted-foreground\",\n success: \"bg-success/15 text-success\",\n warning: \"bg-warning/15 text-warning\",\n danger: \"bg-destructive/15 text-destructive\",\n info: \"bg-info/15 text-info\",\n },\n size: {\n /** Inline chips — a category, a tenant, a permission. */\n sm: \"px-1.5 py-0.5 text-xs\",\n /** A row's status. */\n md: \"px-2 py-0.5 text-xs\",\n },\n },\n defaultVariants: {\n variant: \"neutral\",\n size: \"md\",\n },\n },\n);\n\nexport interface BadgeProps\n extends\n React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant, size, ...props }, ref) => (\n <span\n ref={ref}\n className={cn(badgeVariants({ variant, size }), className)}\n {...props}\n />\n ),\n);\n\nBadge.displayName = \"Badge\";\n\nexport { badgeVariants };\n","import { ChevronRight } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type BreadcrumbItem = {\n label: string;\n href?: string;\n onClick?: () => void;\n};\n\ninterface BreadcrumbProps {\n items: BreadcrumbItem[];\n className?: string;\n}\n\nexport function Breadcrumb({ items, className }: BreadcrumbProps) {\n return (\n <nav aria-label=\"Breadcrumb\" className={cn(\"text-sm\", className)}>\n <ol className=\"flex flex-wrap items-center gap-1.5\">\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n const isInteractive = !isLast && (item.href || item.onClick);\n\n return (\n <li\n key={`${item.label}-${index}`}\n className=\"flex items-center gap-1.5\"\n >\n {index > 0 && (\n <ChevronRight\n className=\"text-muted-foreground/70 size-3.5 shrink-0\"\n aria-hidden\n />\n )}\n {isInteractive ? (\n item.href ? (\n <a\n href={item.href}\n className=\"text-muted-foreground hover:text-foreground transition\"\n >\n {item.label}\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={item.onClick}\n className=\"text-muted-foreground hover:text-foreground transition\"\n >\n {item.label}\n </button>\n )\n ) : (\n <span\n className={cn(\n isLast\n ? \"text-foreground font-medium\"\n : \"text-muted-foreground\",\n )}\n aria-current={isLast ? \"page\" : undefined}\n >\n {item.label}\n </span>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"@radix-ui/react-slot\";\n\nimport { Spinner } from \"./spinner\";\nimport { cn } from \"./utils\";\n\nconst buttonVariants = cva(\n \"inline-flex h-9 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md px-3 text-sm font-medium transition duration-200 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n secondary: \"bg-muted text-foreground hover:bg-muted/80\",\n ghost: \"hover:bg-muted\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline: \"border border-border bg-background hover:bg-muted\",\n },\n size: {\n sm: \"h-8 px-2.5\",\n md: \"h-9 px-3\",\n lg: \"h-10 px-4\",\n icon: \"h-9 w-9 px-0\",\n // Square, matching `sm`'s height — for an icon-only control sitting in\n // a table row or beside `sm` buttons, where `icon` is a row taller.\n \"icon-sm\": \"h-8 w-8 px-0\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n },\n);\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n /**\n * Work is in flight: shows a spinner, disables the button, and sets\n * `aria-busy`.\n *\n * This exists because the panel had 272 disabled buttons and only 22 that\n * said anything about why — the rest went dead on click with no spinner and\n * no label change, which reads as a broken button rather than a busy one.\n * Making the feedback part of `disabled` rather than something each caller\n * remembers separately is the only way that ratio stays fixed.\n *\n * The label is kept rather than swapped. \"Saving…\" loses which button you\n * pressed, and the spinner already says it is working. An icon-only button\n * is the exception — there is no room beside the glyph, so the spinner takes\n * its place; the `aria-label` is what names the button either way.\n *\n * \"Icon-only\" means an icon `size`. A square button that grew a spinner\n * beside its glyph would not just look wrong, it would resize mid-request\n * and shove whatever sits next to it sideways.\n */\n loading?: boolean;\n}\n\n/** Sizes with no room for a spinner beside the glyph. */\nconst ICON_SIZES = new Set<string>([\"icon\", \"icon-sm\"]);\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n asChild = false,\n loading,\n disabled,\n children,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n\n // `asChild` renders someone else's element, which may not take a spinner or\n // a disabled attribute — so the busy treatment is only applied to a real\n // button, and passing both is a mistake worth not papering over.\n if (asChild) {\n return (\n <Comp\n ref={ref}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n >\n {children}\n </Comp>\n );\n }\n\n return (\n <button\n ref={ref}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n >\n {loading ? <Spinner size=\"sm\" /> : null}\n {loading && size != null && ICON_SIZES.has(size) ? null : children}\n </button>\n );\n },\n);\n\nButton.displayName = \"Button\";\n","import * as React from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one spinner.\n *\n * There were five spellings of `animate-spin` across twelve files — `h-4 w-4`,\n * `h-5 w-5`, `size-4`, bare, and a hand-drawn ring in `ProtectedRoute` — so the\n * same \"working\" signal came out a different size depending on which panel you\n * were on.\n *\n * It is `aria-hidden` on purpose. A spinner is decoration; what a screen reader\n * needs is the surrounding control's `aria-busy` or the panel's status text,\n * and announcing \"loading\" twice is worse than once. `Button` and `StatePanel`\n * both supply that.\n */\nconst SIZES = {\n sm: \"size-3.5\",\n md: \"size-4\",\n lg: \"size-5\",\n xl: \"size-10 border-2\",\n} as const;\n\nexport interface SpinnerProps extends React.SVGProps<SVGSVGElement> {\n size?: keyof typeof SIZES;\n}\n\nexport function Spinner({ size = \"md\", className, ...props }: SpinnerProps) {\n return (\n <Loader2\n aria-hidden\n className={cn(\"animate-spin\", SIZES[size], className)}\n {...props}\n />\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * Surface container for grouped content. Prefer a bare section when there is\n * no need for border / padding chrome — cards are for interactive or\n * self-contained blocks, not every stack of text.\n */\nexport const Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"bg-card text-card-foreground rounded-xl border shadow\",\n className,\n )}\n {...props}\n />\n));\nCard.displayName = \"Card\";\n\nexport const CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n {...props}\n />\n));\nCardHeader.displayName = \"CardHeader\";\n\nexport const CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"leading-none font-semibold tracking-tight\", className)}\n {...props}\n />\n));\nCardTitle.displayName = \"CardTitle\";\n\nexport const CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n));\nCardDescription.displayName = \"CardDescription\";\n\nexport const CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />\n));\nCardContent.displayName = \"CardContent\";\n\nexport const CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex items-center p-6 pt-0\", className)}\n {...props}\n />\n));\nCardFooter.displayName = \"CardFooter\";\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The native checkbox, sized and coloured once.\n *\n * Twenty-six of these were scattered across thirteen files and twenty of them\n * carried **no class at all** — browser defaults, so they were a different size\n * to the six that set `size-4` and drew their tick in the operating system's\n * accent rather than the panel's.\n *\n * This deliberately stays a native `<input type=\"checkbox\">` rather than an\n * `appearance-none` box with an SVG tick. Native gets indeterminate state,\n * form participation, platform focus behaviour and assistive-technology support\n * for free, and a custom one would have to re-earn all of it to look slightly\n * different.\n *\n * `border` and `rounded` mostly do not render on a native checkbox — they are\n * kept because the six styled copies had them and removing them would be a\n * silent change to those. `accent-primary` and `size-4` are what actually show.\n */\nexport const checkboxClass =\n \"accent-primary border-border focus-visible:ring-ring size-4 shrink-0 cursor-pointer rounded border focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type CheckboxProps = Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n \"type\"\n>;\n\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, ...props }, ref) => (\n <input\n ref={ref}\n type=\"checkbox\"\n className={cn(checkboxClass, className)}\n {...props}\n />\n ),\n);\n\nCheckbox.displayName = \"Checkbox\";\n","/**\n * Range maths and clipboard text for the card table's spreadsheet selection.\n *\n * Ported from video-shorts-panel `app/src/common/components/ExcelTable.jsx`.\n * Kept free of React and the DOM (except `writeToClipboard`) so the escaping\n * and range rules are unit-testable.\n */\n\nexport type CellRef = { r: number; c: number };\n\nexport type CellRange = { r1: number; r2: number; c1: number; c2: number };\n\n/** Tab for the clipboard (Excel/Sheets split on it), comma for a .csv file. */\nexport const TSV_DELIMITER = \"\\t\";\nexport const CSV_DELIMITER = \",\";\n\n/**\n * Anchor and focus can be dragged in any direction, so the range is whichever\n * corners they happen to be — normalize to top-left / bottom-right.\n */\nexport function normalizeRange(\n anchor: CellRef | null | undefined,\n focus: CellRef | null | undefined,\n): CellRange | null {\n if (!anchor || !focus) return null;\n return {\n r1: Math.min(anchor.r, focus.r),\n r2: Math.max(anchor.r, focus.r),\n c1: Math.min(anchor.c, focus.c),\n c2: Math.max(anchor.c, focus.c),\n };\n}\n\n/**\n * A cell needs quoting once it carries the delimiters themselves — the same\n * rule Excel uses when it parses the clipboard. Without it, a title containing\n * a tab or a newline silently becomes extra columns or rows on paste.\n */\nexport function escapeCell(raw: unknown, delimiter: string): string {\n const value = raw == null ? \"\" : String(raw);\n if (\n value.includes(delimiter) ||\n value.includes(\"\\n\") ||\n value.includes(\"\\r\") ||\n value.includes('\"')\n ) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\nexport type TextColumn<Row> = {\n title: string;\n value: (row: Row) => string;\n};\n\n/** Renders a range as delimited text, optionally with a header line. */\nexport function buildRangeText<Row>(\n range: CellRange | null,\n columns: TextColumn<Row>[],\n rows: Row[],\n delimiter: string,\n includeHeaders: boolean,\n): string {\n if (!range) return \"\";\n const lines: string[] = [];\n\n if (includeHeaders) {\n const header: string[] = [];\n for (let c = range.c1; c <= range.c2; c++) {\n header.push(escapeCell(columns[c]?.title, delimiter));\n }\n lines.push(header.join(delimiter));\n }\n\n for (let r = range.r1; r <= range.r2; r++) {\n const line: string[] = [];\n const row = rows[r];\n for (let c = range.c1; c <= range.c2; c++) {\n const column = columns[c];\n line.push(\n escapeCell(\n column && row !== undefined ? column.value(row) : \"\",\n delimiter,\n ),\n );\n }\n lines.push(line.join(delimiter));\n }\n\n return lines.join(\"\\n\");\n}\n\n/** The whole grid, or null when there is nothing to select. */\nexport function fullRange<Row>(\n columns: TextColumn<Row>[],\n rows: Row[],\n): CellRange | null {\n if (!rows.length || !columns.length) return null;\n return { r1: 0, r2: rows.length - 1, c1: 0, c2: columns.length - 1 };\n}\n\n/** \"3 × 2 selected\" — what the toolbar reports back to the user. */\nexport function describeRange(range: CellRange | null): string {\n if (!range) return \"No selection\";\n const rowCount = range.r2 - range.r1 + 1;\n const colCount = range.c2 - range.c1 + 1;\n if (rowCount === 1 && colCount === 1) return \"1 cell selected\";\n return `${rowCount} × ${colCount} selected`;\n}\n\nexport function countCells(range: CellRange): {\n rows: number;\n columns: number;\n} {\n return {\n rows: range.r2 - range.r1 + 1,\n columns: range.c2 - range.c1 + 1,\n };\n}\n\n/**\n * `navigator.clipboard` is unavailable on http origins and older browsers, so\n * fall back to a hidden textarea + execCommand rather than failing the copy.\n */\nexport async function writeToClipboard(text: string): Promise<void> {\n if (navigator.clipboard?.writeText) {\n return navigator.clipboard.writeText(text);\n }\n\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.style.position = \"fixed\";\n textarea.style.top = \"-1000px\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n if (!document.execCommand(\"copy\")) {\n throw new Error(\"Could not write to the clipboard\");\n }\n } finally {\n document.body.removeChild(textarea);\n }\n}\n","\"use client\";\n\nimport { ChevronDown } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * A titled section that folds away.\n *\n * For sidebar panels that are long but not always in use — the body stays\n * mounted so its state (a loaded list, a half-filled filter) survives being\n * collapsed, rather than being thrown away and refetched on the way back.\n */\nexport function CollapsibleSection({\n title,\n icon,\n defaultOpen = true,\n right,\n className,\n children,\n}: {\n title: string;\n /** Optional leading glyph, shown between the chevron and the title. */\n icon?: React.ReactNode;\n defaultOpen?: boolean;\n /** Optional trailing content in the header, e.g. a count. */\n right?: React.ReactNode;\n className?: string;\n children: React.ReactNode;\n}) {\n const [open, setOpen] = React.useState(defaultOpen);\n const bodyId = React.useId();\n\n return (\n <div className={cn(\"border-border rounded-lg border\", className)}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={bodyId}\n onClick={() => setOpen((current) => !current)}\n className=\"hover:bg-muted/50 flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-semibold transition\"\n >\n <ChevronDown\n size={14}\n aria-hidden\n className={cn(\n \"shrink-0 transition-transform\",\n open ? \"\" : \"-rotate-90\",\n )}\n />\n {icon}\n <span className=\"flex-1\">{title}</span>\n {right}\n </button>\n {/* Hidden rather than unmounted, so collapsing does not discard the\n panel's state or refetch what it had already loaded. */}\n <div id={bodyId} hidden={!open} className=\"space-y-3 px-3 pt-1 pb-3\">\n {children}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { Modal } from \"./modal\";\n\ninterface ConfirmDialogProps {\n isOpen: boolean;\n title: string;\n description?: React.ReactNode;\n confirmLabel?: string;\n cancelLabel?: string;\n isConfirming?: boolean;\n error?: string | null;\n onConfirm: () => void;\n onClose: () => void;\n}\n\nexport function ConfirmDialog({\n isOpen,\n title,\n description,\n confirmLabel = \"Delete\",\n cancelLabel = \"Cancel\",\n isConfirming,\n error,\n onConfirm,\n onClose,\n}: ConfirmDialogProps) {\n const titleId = React.useId();\n const descriptionId = React.useId();\n const errorId = React.useId();\n\n const describedBy = [\n description ? descriptionId : null,\n error ? errorId : null,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <Modal\n isOpen={isOpen}\n role=\"alertdialog\"\n labelledBy={titleId}\n describedBy={describedBy || undefined}\n closeLabel=\"Close dialog\"\n onClose={onClose}\n >\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {title}\n </h3>\n {description ? (\n <div id={descriptionId} className=\"text-muted-foreground mt-2 text-sm\">\n {description}\n </div>\n ) : null}\n\n {error ? (\n <div\n id={errorId}\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/5 text-destructive mt-4 rounded-lg border px-3 py-2 text-sm\"\n >\n {error}\n </div>\n ) : null}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <Button variant=\"outline\" onClick={onClose} disabled={isConfirming}>\n {cancelLabel}\n </Button>\n <Button\n variant=\"destructive\"\n onClick={onConfirm}\n loading={isConfirming}\n >\n {confirmLabel}\n </Button>\n </div>\n </Modal>\n );\n}\n","\"use client\";\n\nimport { Check, Copy } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { writeToClipboard } from \"./clipboard\";\nimport { cn } from \"./utils\";\n\n/**\n * Copies one short string — an id, a title, a URL — and says so for a moment.\n *\n * The panel had this three times over, each with its own timeout and its own\n * silent-failure story. `writeToClipboard` is used rather than\n * `navigator.clipboard` directly because the latter is undefined on http\n * origins, which is exactly where this panel runs in local dev.\n */\nexport function CopyButton({\n value,\n label,\n className,\n}: {\n value: string;\n /** What is being copied, for the accessible name: \"card id\", \"title\". */\n label: string;\n className?: string;\n}) {\n const [copied, setCopied] = React.useState(false);\n\n React.useEffect(() => {\n if (!copied) return;\n const timer = window.setTimeout(() => setCopied(false), 1500);\n return () => window.clearTimeout(timer);\n }, [copied]);\n\n return (\n <button\n type=\"button\"\n aria-label={copied ? `${label} copied` : `Copy ${label}`}\n title={copied ? \"Copied\" : `Copy ${label}`}\n className={cn(\n \"text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring shrink-0 cursor-pointer rounded p-1 transition focus-visible:ring-2 focus-visible:outline-none\",\n className,\n )}\n onClick={() => {\n // A denied clipboard permission should not throw into the row.\n void writeToClipboard(value)\n .then(() => setCopied(true))\n .catch(() => undefined);\n }}\n >\n {copied ? (\n <Check className=\"size-3.5 text-success\" aria-hidden />\n ) : (\n <Copy className=\"size-3.5\" aria-hidden />\n )}\n </button>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The list table every feature panel was hand-rolling.\n *\n * Seventeen files repeated the same wrapper string\n * (`border-border bg-background/80 overflow-x-auto rounded-lg border`) and the\n * header had already drifted into two incompatible looks, so Campaigns and\n * Targets did not resemble each other. Both are kept as `variant` rather than\n * unified here: collapsing them is a visual change to ten panels and belongs in\n * its own reviewable diff, not smuggled in with a refactor.\n *\n * The column contract deliberately echoes `GridColumn` in\n * `spreadsheet-grid.tsx` — `key`, `title`, a renderer, an optional class — so\n * the repo has one shape to learn. It drops that type's `value: (row) => string`\n * because there is no clipboard or CSV here; nothing would keep it honest, and\n * a required field nobody reads gets filled in with lies.\n *\n * **Not for every table.** `GroupTable` renders parent and child rows with\n * different column counts, and `BusinessTable`'s rows are dnd-kit sortables that\n * own their own refs and transforms. `PublishModal`, `BulkCreateModal` and the\n * clone queue in `MetaAdSetsPanel` are grids of inputs rather than lists of\n * values — every cell is an editable control, and they size their header and\n * body rows differently on purpose. All five are legitimately tables of a\n * different kind; bending this component around them would cost more than it\n * saves.\n */\nexport type TableColumn<Row> = {\n key: string;\n /** Node, not string: a header can carry a select-all box or a sort control. */\n title: React.ReactNode;\n cell: (row: Row, index: number) => React.ReactNode;\n align?: \"left\" | \"right\" | \"center\";\n /**\n * Set on a sortable column so a screen reader announces the current sort.\n * Only the sorted column says `ascending`/`descending`; the rest say `none`,\n * which is what marks them as sortable at all.\n */\n ariaSort?: \"ascending\" | \"descending\" | \"none\";\n /** Extra classes for this column's `<td>`. */\n className?: string;\n /** Extra classes for this column's `<th>`. */\n headerClassName?: string;\n};\n\nexport interface DataTableProps<Row> {\n columns: TableColumn<Row>[];\n rows: Row[];\n /** Stable React key per row. */\n rowKey: (row: Row, index: number) => string;\n /**\n * `uppercase` — the tinted small-caps header (campaigns, showcase, filters).\n * `plain` — the quieter left-aligned header (ads, targets, creatives).\n */\n variant?: \"uppercase\" | \"plain\";\n /**\n * `comfortable` — the roomy default, for tables of a handful of columns.\n * `compact` — what every table of eight columns or more had already chosen by\n * hand, because the roomy padding pushes them into a horizontal scroll.\n */\n density?: \"comfortable\" | \"compact\";\n /** Pins the header for a table inside its own scroll container. */\n stickyHeader?: boolean;\n rowClassName?: (row: Row, index: number) => string | undefined;\n /** Rendered in place of `<tbody>` rows when there are none. */\n emptyMessage?: React.ReactNode;\n /**\n * Rows for a `<tfoot>` — a totals line, typically. The caller supplies the\n * `<tr>` itself because a summary row rarely lines up with the columns above\n * it; designer-counts spans its first two.\n */\n footer?: React.ReactNode;\n /** Names the table for screen readers when no visible caption fits. */\n ariaLabel?: string;\n /** Classes for the scroll wrapper. */\n className?: string;\n /** Classes for the `<table>`. */\n tableClassName?: string;\n}\n\nconst HEADER_VARIANTS = {\n uppercase:\n \"border-border bg-muted/40 text-muted-foreground border-b text-xs tracking-wide uppercase\",\n plain: \"text-muted-foreground border-border border-b text-left\",\n} as const;\n\nconst DENSITY = {\n comfortable: \"px-4 py-3\",\n compact: \"px-3 py-2\",\n} as const;\n\nconst ALIGN = {\n left: \"text-left\",\n right: \"text-right\",\n center: \"text-center\",\n} as const;\n\nexport function DataTable<Row>({\n columns,\n rows,\n rowKey,\n variant = \"uppercase\",\n density = \"comfortable\",\n stickyHeader = false,\n rowClassName,\n emptyMessage,\n footer,\n ariaLabel,\n className,\n tableClassName,\n}: DataTableProps<Row>) {\n return (\n <div\n className={cn(\n \"border-border bg-background/80 overflow-x-auto rounded-lg border\",\n className,\n )}\n >\n <table\n aria-label={ariaLabel}\n className={cn(\"min-w-full text-left text-sm\", tableClassName)}\n >\n <thead\n className={cn(\n HEADER_VARIANTS[variant],\n stickyHeader && \"bg-muted sticky top-0 z-10\",\n )}\n >\n <tr>\n {columns.map((column) => (\n <th\n key={column.key}\n scope=\"col\"\n aria-sort={column.ariaSort}\n className={cn(\n DENSITY[density],\n \"font-medium\",\n ALIGN[column.align ?? \"left\"],\n column.headerClassName,\n )}\n >\n {column.title}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 && emptyMessage != null ? (\n <tr>\n {/* One cell across the whole width — a short row would otherwise\n leave the message sitting under the first column. */}\n <td\n colSpan={columns.length}\n className=\"text-muted-foreground px-4 py-6 text-center text-sm\"\n >\n {emptyMessage}\n </td>\n </tr>\n ) : (\n rows.map((row, index) => (\n <tr\n key={rowKey(row, index)}\n className={cn(\n \"border-border/70 border-b last:border-0\",\n rowClassName?.(row, index),\n )}\n >\n {columns.map((column) => (\n <td\n key={column.key}\n className={cn(\n DENSITY[density],\n ALIGN[column.align ?? \"left\"],\n column.className,\n )}\n >\n {column.cell(row, index)}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n {footer != null ? <tfoot>{footer}</tfoot> : null}\n </table>\n </div>\n );\n}\n","\"use client\";\n\nimport { CalendarDays, ChevronLeft, ChevronRight, X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"../utils\";\nimport {\n addDays,\n addMonths,\n formatDisplay,\n fromIsoDate,\n isSameDay,\n monthGrid,\n monthLabel,\n startOfMonth,\n toIsoDate,\n} from \"./dateRange\";\n\nexport type DateRangeValue = { from: string; to: string };\n\n/**\n * A two-month range calendar.\n *\n * Two separate date fields cost two columns and read as two unrelated\n * questions when they are one: which window. They also let the pair be set\n * backwards, which returns nothing and looks like a broken filter.\n *\n * Two months rather than one because almost every range anyone picks here\n * crosses a month boundary — \"last week of July into the first of August\" is a\n * single gesture with two months visible and a paging exercise with one.\n *\n * Presets are the useful half. The common ranges are the same handful every\n * time, and picking \"Last 7 days\" out of a list beats counting backwards on a\n * grid.\n */\nconst PRESETS: { label: string; range: () => DateRangeValue }[] = [\n {\n label: \"Today\",\n range: () => {\n const today = toIsoDate(new Date());\n return { from: today, to: today };\n },\n },\n {\n label: \"Yesterday\",\n range: () => {\n const day = toIsoDate(addDays(new Date(), -1));\n return { from: day, to: day };\n },\n },\n {\n label: \"Last 7 days\",\n range: () => ({\n from: toIsoDate(addDays(new Date(), -6)),\n to: toIsoDate(new Date()),\n }),\n },\n {\n label: \"Last 30 days\",\n range: () => ({\n from: toIsoDate(addDays(new Date(), -29)),\n to: toIsoDate(new Date()),\n }),\n },\n {\n label: \"This month\",\n range: () => ({\n from: toIsoDate(startOfMonth(new Date())),\n to: toIsoDate(new Date()),\n }),\n },\n];\n\nconst WEEKDAYS = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"];\n\nexport interface DateRangePickerProps {\n value: DateRangeValue;\n onChange: (next: DateRangeValue) => void;\n disabled?: boolean;\n placeholder?: string;\n className?: string;\n /** Names the trigger for screen readers when there is no visible label. */\n ariaLabel?: string;\n}\n\nexport function DateRangePicker({\n value,\n onChange,\n disabled,\n placeholder = \"Any date\",\n className,\n ariaLabel = \"Date range\",\n}: DateRangePickerProps) {\n const [open, setOpen] = React.useState(false);\n const [hovered, setHovered] = React.useState<Date | null>(null);\n /** Set while choosing the second end, so the range can preview under the cursor. */\n const [pendingFrom, setPendingFrom] = React.useState<Date | null>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n const from = fromIsoDate(value.from);\n const to = fromIsoDate(value.to);\n\n const [viewMonth, setViewMonth] = React.useState<Date>(() =>\n startOfMonth(from ?? new Date()),\n );\n\n React.useEffect(() => {\n if (!open) return undefined;\n const onPointerDown = (event: MouseEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) setOpen(false);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"mousedown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open]);\n\n /**\n * Reopening lands on the current selection rather than wherever the view was\n * left. Done here rather than in an effect: it is a response to an event, and\n * setting state from an effect is what `react-hooks/set-state-in-effect`\n * rejects — correctly, since it costs an extra render every open.\n */\n function openPicker() {\n setViewMonth(startOfMonth(fromIsoDate(value.from) ?? new Date()));\n setPendingFrom(null);\n setHovered(null);\n setOpen(true);\n }\n\n const anchor = pendingFrom ?? (to ? null : from);\n const previewEnd = pendingFrom ? hovered : null;\n\n function rangeBounds(): [Date | null, Date | null] {\n if (pendingFrom) {\n if (!previewEnd) return [pendingFrom, pendingFrom];\n return previewEnd.getTime() < pendingFrom.getTime()\n ? [previewEnd, pendingFrom]\n : [pendingFrom, previewEnd];\n }\n return [from, to];\n }\n\n const [rangeStart, rangeEnd] = rangeBounds();\n\n function selectDay(day: Date) {\n if (!anchor) {\n // Starting a new range. Keeping only `from` means the next click closes\n // it, whichever side of the anchor it lands on.\n setPendingFrom(day);\n onChange({ from: toIsoDate(day), to: \"\" });\n return;\n }\n const [start, end] =\n day.getTime() < anchor.getTime() ? [day, anchor] : [anchor, day];\n onChange({ from: toIsoDate(start), to: toIsoDate(end) });\n setPendingFrom(null);\n setHovered(null);\n setOpen(false);\n }\n\n /** Arrow keys move by day/week across both months, as a calendar should. */\n function onGridKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const offsets: Record<string, number> = {\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -7,\n ArrowDown: 7,\n };\n const offset = offsets[event.key];\n if (offset === undefined) return;\n const focused = document.activeElement as HTMLElement | null;\n const iso = focused?.dataset?.day;\n const current = fromIsoDate(iso);\n if (!current) return;\n event.preventDefault();\n const next = addDays(current, offset);\n const nextIso = toIsoDate(next);\n // Page the view when the move lands outside what is rendered.\n if (!rootRef.current?.querySelector(`[data-day=\"${nextIso}\"]`)) {\n setViewMonth(startOfMonth(offset < 0 ? next : addMonths(next, -1)));\n }\n window.requestAnimationFrame(() => {\n rootRef.current\n ?.querySelector<HTMLElement>(`[data-day=\"${nextIso}\"]`)\n ?.focus();\n });\n }\n\n const label =\n value.from || value.to\n ? `${formatDisplay(value.from) || \"Any\"} → ${formatDisplay(value.to) || \"Any\"}`\n : placeholder;\n\n const today = new Date();\n\n function renderMonth(month: Date) {\n return (\n <div key={monthLabel(month)} className=\"w-[15.75rem] shrink-0\">\n <div className=\"text-foreground mb-2 text-center text-sm font-medium whitespace-nowrap\">\n {monthLabel(month)}\n </div>\n <div className=\"text-muted-foreground grid grid-cols-7 text-center text-[11px]\">\n {WEEKDAYS.map((day) => (\n <div key={day} className=\"grid size-9 place-items-center\">\n {day}\n </div>\n ))}\n </div>\n <div className=\"grid grid-cols-7\">\n {monthGrid(month).map((day) => {\n const iso = toIsoDate(day);\n const outside = day.getMonth() !== month.getMonth();\n const isStart = isSameDay(day, rangeStart);\n const isEnd = isSameDay(day, rangeEnd);\n const inRange =\n rangeStart != null &&\n rangeEnd != null &&\n day.getTime() > rangeStart.getTime() &&\n day.getTime() < rangeEnd.getTime();\n const isToday = isSameDay(day, today);\n\n return (\n <button\n key={iso}\n type=\"button\"\n data-day={iso}\n // Outside days stay clickable — clicking one is how you reach\n // the neighbouring month without paging.\n onClick={() => selectDay(day)}\n onMouseEnter={() => setHovered(day)}\n aria-label={day.toDateString()}\n aria-pressed={isStart || isEnd}\n className={cn(\n \"focus-visible:ring-ring relative grid size-9 place-items-center rounded-md text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none\",\n outside ? \"text-muted-foreground/50\" : \"text-foreground\",\n inRange && \"bg-primary/10 rounded-none\",\n (isStart || isEnd) &&\n \"bg-primary text-primary-foreground font-medium\",\n // Square off the inner edge so a range reads as one bar\n // rather than two pills with a gap.\n isStart && rangeEnd && !isEnd && \"rounded-r-none\",\n isEnd && rangeStart && !isStart && \"rounded-l-none\",\n !isStart && !isEnd && \"hover:bg-muted\",\n isToday &&\n !isStart &&\n !isEnd &&\n \"ring-border font-semibold ring-1\",\n )}\n >\n {day.getDate()}\n </button>\n );\n })}\n </div>\n </div>\n );\n }\n\n return (\n <div ref={rootRef} className={cn(\"relative\", className)}>\n <div\n className={cn(\n \"border-border bg-background flex items-center rounded-md border\",\n \"focus-within:ring-ring/50 focus-within:border-ring focus-within:ring-2\",\n disabled && \"opacity-50\",\n )}\n >\n <button\n type=\"button\"\n disabled={disabled}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-label={ariaLabel}\n onClick={() => (open ? setOpen(false) : openPicker())}\n className=\"flex min-w-0 flex-1 items-center gap-2 px-2 py-1.5 text-left text-sm\"\n >\n <CalendarDays\n className=\"text-muted-foreground size-4 shrink-0\"\n aria-hidden\n />\n <span\n className={cn(\n \"truncate\",\n !value.from && !value.to && \"text-muted-foreground\",\n )}\n >\n {label}\n </span>\n </button>\n {(value.from || value.to) && !disabled ? (\n <button\n type=\"button\"\n aria-label=\"Clear date range\"\n onClick={() => {\n onChange({ from: \"\", to: \"\" });\n setPendingFrom(null);\n }}\n className=\"text-muted-foreground hover:text-foreground shrink-0 px-2\"\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n </div>\n\n {open ? (\n <div\n role=\"dialog\"\n aria-label={ariaLabel}\n // `w-max` so the calendar sets its own width instead of inheriting\n // the filter column, which squeezed the months until the numbers ran\n // together. Anchored right because this sits in the last column and\n // would otherwise open off the edge of the viewport.\n className=\"border-border bg-background absolute top-full right-0 z-50 mt-1 flex w-max rounded-lg border p-3 shadow-lg\"\n >\n <div className=\"border-border mr-3 flex w-32 shrink-0 flex-col gap-0.5 border-r pr-3\">\n {PRESETS.map((preset) => (\n <button\n key={preset.label}\n type=\"button\"\n className=\"hover:bg-muted text-foreground rounded-md px-2 py-1.5 text-left text-xs\"\n onClick={() => {\n onChange(preset.range());\n setPendingFrom(null);\n setOpen(false);\n }}\n >\n {preset.label}\n </button>\n ))}\n </div>\n\n <div onKeyDown={onGridKeyDown}>\n <div className=\"mb-2 flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n className=\"hover:bg-muted text-muted-foreground hover:text-foreground rounded-md p-1.5\"\n onClick={() => setViewMonth(addMonths(viewMonth, -1))}\n >\n <ChevronLeft className=\"size-4\" aria-hidden />\n </button>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n className=\"hover:bg-muted text-muted-foreground hover:text-foreground rounded-md p-1.5\"\n onClick={() => setViewMonth(addMonths(viewMonth, 1))}\n >\n <ChevronRight className=\"size-4\" aria-hidden />\n </button>\n </div>\n <div className=\"flex gap-5\" onMouseLeave={() => setHovered(null)}>\n {renderMonth(viewMonth)}\n {renderMonth(addMonths(viewMonth, 1))}\n </div>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * Date helpers for the range picker, all in local time.\n *\n * Deliberately not `toISOString()`: that converts to UTC first, so on any\n * negative-offset day it returns yesterday's date and the picker highlights the\n * wrong cell. Every value here is built and read as the local calendar day the\n * user is actually looking at.\n */\n\n/** `YYYY-MM-DD`, the value shape the filters store. */\nexport type IsoDate = string;\n\nconst pad = (n: number) => String(n).padStart(2, \"0\");\n\nexport function toIsoDate(date: Date): IsoDate {\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n}\n\n/** Parses `YYYY-MM-DD` into a local midnight Date; null for anything else. */\nexport function fromIsoDate(value: string | null | undefined): Date | null {\n if (!value) return null;\n const trimmed = value.trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(trimmed);\n if (!match) return null;\n const date = new Date(\n Number(match[1]),\n Number(match[2]) - 1,\n Number(match[3]),\n );\n // Rejects 2026-02-31, which would otherwise roll silently into March.\n return toIsoDate(date) === trimmed ? date : null;\n}\n\nexport function startOfMonth(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\nexport function addMonths(date: Date, count: number): Date {\n return new Date(date.getFullYear(), date.getMonth() + count, 1);\n}\n\nexport function addDays(date: Date, count: number): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() + count);\n}\n\nexport function isSameDay(a: Date | null, b: Date | null): boolean {\n if (!a || !b) return false;\n return toIsoDate(a) === toIsoDate(b);\n}\n\n/**\n * The six-week grid for a month, Sunday-first, padded with the neighbouring\n * months so every row has seven cells.\n *\n * Always six rows, never five: a grid that changes height as you page through\n * months makes everything below it jump.\n */\nexport function monthGrid(month: Date): Date[] {\n const first = startOfMonth(month);\n const start = addDays(first, -first.getDay());\n return Array.from({ length: 42 }, (_, index) => addDays(start, index));\n}\n\nexport function monthLabel(month: Date, locale = \"en-IN\"): string {\n return month.toLocaleDateString(locale, { month: \"long\", year: \"numeric\" });\n}\n\n/** Human form for the trigger — \"22 Aug 2026\". */\nexport function formatDisplay(value: string, locale = \"en-IN\"): string {\n const date = fromIsoDate(value);\n if (!date) return \"\";\n return date.toLocaleDateString(locale, {\n day: \"numeric\",\n month: \"short\",\n year: \"numeric\",\n });\n}\n\nexport function startOfDayMs(value: string): number {\n const date = fromIsoDate(value);\n return date ? date.getTime() : 0;\n}\n\n/**\n * The end of a day as milliseconds.\n *\n * A range picked as whole days has to include everything created on the last\n * day, so \"to\" means 23:59:59.999 rather than that morning's midnight — which\n * would drop a whole day of cards without saying so.\n */\nexport function endOfDayMs(value: string): number {\n const date = fromIsoDate(value);\n if (!date) return 0;\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n 23,\n 59,\n 59,\n 999,\n ).getTime();\n}\n\n/**\n * 11:59 PM on that local day, as 23:59:59.\n *\n * The next midnight is already the following date, and the feed includes that\n * whole day — so the 28th through the 28th came back with the 29th. Stopping\n * at 11:59 PM keeps the end on the day that was picked.\n */\nexport function endAt2359Ms(value: string): number {\n const date = fromIsoDate(value);\n if (!date) return 0;\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n 23,\n 59,\n 59,\n 0,\n ).getTime();\n}\n\n/**\n * Created-date window for the feed.\n *\n * A blank end means the start day, so one selected date is that whole day.\n * `end_time` is 11:59 PM on the end date.\n */\nexport function createdRangeMs(\n from: string,\n to: string,\n): { start_time: number; end_time: number } {\n const startDate = from.trim() || to.trim();\n const endDate = to.trim() || from.trim();\n return {\n start_time: startOfDayMs(startDate),\n end_time: endAt2359Ms(endDate),\n };\n}\n","\"use client\";\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * Radix compound Dialog for content modals that need Trigger / Portal /\n * Header / Footer composition. Prefer {@link Modal} for a single controlled\n * panel with a scrim — this is the API CRM (and shadcn call sites) already use.\n */\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"bg-overlay/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"border-border bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg\",\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-1.5 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\n \"text-lg leading-none font-semibold tracking-tight\",\n className,\n )}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { Check, ChevronRight, Circle } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * Radix DropdownMenu compound API. Glint has no simpler replacement — menus\n * that open from a trigger (navbar, filters, theme toggle) need this surface.\n */\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"focus:bg-accent data-[state=open]:bg-accent flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto\" />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-hidden rounded-md border p-1 shadow-lg\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"bg-muted -mx-1 my-1 h-px\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n {...props}\n />\n );\n};\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n","import * as React from \"react\";\n\nimport { Spinner } from \"./spinner\";\nimport { cn } from \"./utils\";\n\n/**\n * The bordered block a list shows instead of rows: loading, or nothing found.\n *\n * Fourteen copies of the same\n * `border-border bg-background/80 … rounded-lg border px-4 py-6 text-center`\n * across the panels, each with its own wording — \"Loading users…\", \"Loading\n * taxonomy…\", \"Loading showcases…\". The wording is worth keeping (it says what\n * is loading), the markup is not.\n *\n * `loading` adds two things the hand-rolled versions did not have: a spinner,\n * so a slow panel does not look like an empty one, and `role=\"status\"` with\n * `aria-live=\"polite\"`, so a screen reader is told the list arrived instead of\n * silently finding rows on the next tab press.\n */\nexport interface StatePanelProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Shows a spinner and announces politely. */\n loading?: boolean;\n}\n\nexport function StatePanel({\n loading,\n className,\n children,\n ...props\n}: StatePanelProps) {\n return (\n <div\n role={loading ? \"status\" : undefined}\n aria-live={loading ? \"polite\" : undefined}\n className={cn(\n \"border-border bg-background/80 text-muted-foreground rounded-lg border px-4 py-6 text-center text-sm\",\n loading && \"flex items-center justify-center gap-2\",\n className,\n )}\n {...props}\n >\n {loading ? <Spinner size=\"md\" /> : null}\n {children}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { Alert } from \"./alert\";\nimport { StatePanel } from \"./state-panel\";\n\ntype FeatureAccessGateProps = {\n isLoading?: boolean;\n allowed: boolean;\n deniedMessage: React.ReactNode;\n children: React.ReactNode;\n};\n\n/**\n * Shared loading / denied shell for feature Managers (showcase, headers, …).\n */\nexport function FeatureAccessGate({\n isLoading,\n allowed,\n deniedMessage,\n children,\n}: FeatureAccessGateProps) {\n if (isLoading) {\n return (\n <StatePanel loading className=\"p-6\">\n Checking permissions…\n </StatePanel>\n );\n }\n\n if (!allowed) {\n // `Alert`, not a hand-rolled banner: this is the denial surface for\n // seventeen panels, and it was the one copy the Alert migration missed —\n // so being refused a panel announced nothing to a screen reader.\n return <Alert>{deniedMessage}</Alert>;\n }\n\n return <>{children}</>;\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\ninterface FieldProps {\n label: React.ReactNode;\n required?: boolean;\n /**\n * Associates the label with a control via `htmlFor` / `id`. Prefer this for\n * native inputs rendered as siblings (not wrapped). For composite controls\n * (Autocomplete), omit and use `as=\"label\"` wrapping or an `aria-label`.\n */\n htmlFor?: string;\n /**\n * Render as a `<label>` (wraps a native control so clicking the text focuses\n * it) or a `<div>` (for composite controls like Autocomplete that manage\n * their own focus / render in a portal). Defaults to `div`.\n */\n as?: \"label\" | \"div\";\n className?: string;\n children: React.ReactNode;\n}\n\nexport function Field({\n label,\n required,\n htmlFor,\n as = \"div\",\n className,\n children,\n}: FieldProps) {\n const Wrapper = as;\n const labelNode = (\n <>\n {label}\n {required ? (\n <span className=\"text-destructive ml-0.5\" aria-hidden=\"true\">\n *\n </span>\n ) : null}\n </>\n );\n\n return (\n <Wrapper className={cn(\"space-y-1 text-sm\", className)}>\n {htmlFor && as === \"div\" ? (\n <label htmlFor={htmlFor} className=\"text-muted-foreground\">\n {labelNode}\n </label>\n ) : (\n <span className=\"text-muted-foreground\">{labelNode}</span>\n )}\n {children}\n </Wrapper>\n );\n}\n","\"use client\";\n\nimport { ImagePlus, Loader2, X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { cn } from \"./utils\";\n\nexport type ImageUploaderProps = {\n value?: string;\n onChange: (url: string) => void;\n disabled?: boolean;\n label?: string;\n className?: string;\n /** Allow pasting a remote URL in addition to file upload. Default true. */\n allowUrlPaste?: boolean;\n accept?: string;\n /**\n * Upload a picked file and return its hosted URL.\n * Injected by the panel — Upload stays enabled either way; without a\n * handler, picking a file surfaces a configuration error.\n */\n uploadFile?: (file: File) => Promise<string>;\n /**\n * Optional transform for pasted values (e.g. host a relative path).\n * When omitted, any pasted non-empty string is applied as-is. Absolute\n * `http(s)` URLs never call this.\n */\n uploadFromUrl?: (imageUrl: string) => Promise<string>;\n};\n\n/**\n * Reusable image uploader.\n *\n * Upload and URL paste are both enabled by default. Hosting is injected:\n * each panel passes `uploadFile` / `uploadFromUrl` so the kit stays free of\n * panel-specific API routes.\n */\nexport function ImageUploader({\n value = \"\",\n onChange,\n disabled,\n label,\n className,\n allowUrlPaste = true,\n accept = \"image/*,.gif\",\n uploadFile,\n uploadFromUrl,\n}: ImageUploaderProps) {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [uploading, setUploading] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n const busy = Boolean(disabled || uploading);\n\n const handleFile = async (file: File) => {\n if (!uploadFile) {\n setError(\"File upload is not configured for this panel.\");\n return;\n }\n setUploading(true);\n setError(null);\n try {\n onChange(await uploadFile(file));\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n if (inputRef.current) inputRef.current.value = \"\";\n }\n };\n\n const handleUrl = async (imageUrl: string) => {\n const trimmed = imageUrl.trim();\n if (!trimmed) {\n onChange(\"\");\n return;\n }\n if (trimmed === value) return;\n\n // Absolute URLs — and any paste when no transform is configured — apply\n // as-is. Paste is never gated behind a disabled input.\n if (!uploadFromUrl || /^https?:\\/\\//i.test(trimmed)) {\n setError(null);\n onChange(trimmed);\n return;\n }\n\n setUploading(true);\n setError(null);\n try {\n onChange(await uploadFromUrl(trimmed));\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Upload failed\");\n } finally {\n setUploading(false);\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n {label ? (\n <div className=\"text-muted-foreground text-xs font-medium\">{label}</div>\n ) : null}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n className=\"hidden\"\n disabled={busy}\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) void handleFile(file);\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n onClick={() => inputRef.current?.click()}\n >\n {uploading ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <ImagePlus className=\"h-4 w-4\" />\n )}\n {uploading ? \"Uploading…\" : \"Upload\"}\n </Button>\n {value ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n onClick={() => onChange(\"\")}\n aria-label=\"Clear image\"\n >\n <X className=\"h-4 w-4\" />\n Clear\n </Button>\n ) : null}\n </div>\n\n {allowUrlPaste ? (\n <Input\n key={value || \"empty\"}\n defaultValue={value}\n disabled={busy}\n placeholder=\"Or paste image URL…\"\n onBlur={(e) => {\n void handleUrl(e.target.value);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void handleUrl((e.target as HTMLInputElement).value);\n }\n }}\n />\n ) : null}\n\n {value ? (\n // eslint-disable-next-line @next/next/no-img-element -- CDN URLs vary\n <img\n src={value}\n alt=\"\"\n className=\"border-border max-h-24 rounded border bg-white object-contain p-1\"\n />\n ) : null}\n\n {error ? (\n <p className=\"text-destructive text-xs\" role=\"alert\">\n {error}\n </p>\n ) : null}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport const inputClass =\n \"h-9 w-full rounded-md border border-border bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, ...props }, ref) => (\n <input ref={ref} className={cn(inputClass, className)} {...props} />\n ),\n);\n\nInput.displayName = \"Input\";\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type LabelProps = React.LabelHTMLAttributes<HTMLLabelElement>;\n\n/** Form label — pair with a native control via `htmlFor`. */\nexport const Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => (\n <label\n ref={ref}\n className={cn(\n \"text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n ),\n);\n\nLabel.displayName = \"Label\";\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The title block every panel opens with.\n *\n * Twenty Managers wrote the same `<h1>` and subtitle by hand, differing only in\n * whether the row said `gap-3` or `gap-x-4 gap-y-2` and whether the inner block\n * carried `min-w-0` — differences nobody chose, which is what made them worth\n * removing.\n *\n * `description` takes a node rather than a string because several panels put a\n * `<code>` in theirs, naming the Firebase field they write. That is the useful\n * kind of subtitle and it should not have to opt out of the shared component to\n * stay.\n *\n * `min-w-0` is not optional here. Without it a long title refuses to shrink and\n * pushes the actions off the row instead of wrapping — which is the bug the\n * three panels that set it had already hit, and the seven that did not had not\n * yet.\n */\nexport interface PageHeaderProps {\n title: React.ReactNode;\n description?: React.ReactNode;\n /**\n * Sits above the title: a breadcrumb, or the back link the filter editors\n * use. Four panels had one, each spacing it by hand.\n */\n eyebrow?: React.ReactNode;\n /** Buttons belonging to the page, laid out at the end of the title row. */\n actions?: React.ReactNode;\n className?: string;\n}\n\nexport function PageHeader({\n title,\n description,\n eyebrow,\n actions,\n className,\n}: PageHeaderProps) {\n const heading = (\n <div className=\"min-w-0\">\n {eyebrow}\n <h1\n className={cn(\n \"text-2xl font-semibold tracking-tight\",\n eyebrow != null && \"mt-1\",\n )}\n >\n {title}\n </h1>\n {description != null ? (\n <p className=\"text-muted-foreground mt-1 text-sm\">{description}</p>\n ) : null}\n </div>\n );\n\n if (!actions) {\n return <div className={className}>{heading}</div>;\n }\n\n return (\n <div\n className={cn(\n \"flex flex-wrap items-center justify-between gap-3\",\n className,\n )}\n >\n {heading}\n {actions}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type PanelBrandMarkProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Icon inside the mark (lucide, etc.). */\n children: React.ReactNode;\n size?: \"sm\" | \"md\";\n};\n\n/**\n * Quiet brand tile for sidebar / sign-in — solid primary, no decorative gradients.\n */\nexport function PanelBrandMark({\n children,\n size = \"md\",\n className,\n ...props\n}: PanelBrandMarkProps) {\n return (\n <div\n className={cn(\n \"bg-primary text-primary-foreground grid shrink-0 place-items-center rounded-lg\",\n size === \"sm\" ? \"h-9 w-9\" : \"h-10 w-10\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n","\"use client\";\n\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { PanelBrandMark } from \"./panel-brand-mark\";\nimport { cn } from \"./utils\";\n\nexport type PanelSignInProps = {\n appName: string;\n /** Short line under the brand (e.g. \"Secure Google sign-in\"). */\n eyebrow?: string;\n /** One supporting sentence under the headline. */\n description?: string;\n /** Optional feature bullets — keep to ≤3; DESIGN.md: one job per surface. */\n features?: string[];\n brandIcon?: React.ReactNode;\n error?: string | null;\n /** Google signed in but panel access refused. */\n refused?: boolean;\n refusedTitle?: string;\n refusedMessage?: string;\n isSessionLoading?: boolean;\n isSigningIn?: boolean;\n onSignIn: () => void;\n signInLabel?: string;\n className?: string;\n};\n\n/**\n * DESIGN.md-compliant panel login: brand-first, ink neutrals, no purple glow.\n */\nexport function PanelSignIn({\n appName,\n eyebrow = \"Secure Google sign-in\",\n description = \"Use your work Google account to continue.\",\n features,\n brandIcon,\n error,\n refused = false,\n refusedTitle = \"Access denied\",\n refusedMessage = \"This Google account is signed in, but it is not provisioned for this panel.\",\n isSessionLoading = false,\n isSigningIn = false,\n onSignIn,\n signInLabel = \"Continue with Google\",\n className,\n}: PanelSignInProps) {\n const busy = isSessionLoading || isSigningIn;\n\n return (\n <main\n className={cn(\n \"bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <section className=\"border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm\">\n <div className=\"flex items-center gap-3\">\n <PanelBrandMark>\n {brandIcon ?? (\n <span className=\"text-sm font-semibold\" aria-hidden>\n {appName.slice(0, 1).toUpperCase()}\n </span>\n )}\n </PanelBrandMark>\n <div className=\"min-w-0\">\n <p className=\"text-title truncate font-semibold\">{appName}</p>\n <p className=\"text-muted-foreground text-meta\">{eyebrow}</p>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <h1 className=\"text-display font-semibold tracking-tight\">\n {refused ? refusedTitle : \"Sign in\"}\n </h1>\n <p className=\"text-muted-foreground text-body\">\n {refused ? refusedMessage : description}\n </p>\n </div>\n\n {features && features.length > 0 && !refused ? (\n <ul className=\"text-muted-foreground text-body space-y-1.5\">\n {features.slice(0, 3).map((feature) => (\n <li key={feature} className=\"flex gap-2\">\n <span className=\"text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current\" />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n ) : null}\n\n {error ? (\n <p\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm\"\n >\n {error}\n </p>\n ) : null}\n\n <Button\n className=\"w-full\"\n disabled={busy}\n onClick={onSignIn}\n aria-busy={busy}\n >\n {busy ? (\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" aria-hidden />\n ) : null}\n {isSigningIn ? \"Redirecting…\" : signInLabel}\n </Button>\n </section>\n </main>\n );\n}\n\nexport function PanelSignInSkeleton({ className }: { className?: string }) {\n return (\n <main\n className={cn(\n \"bg-background grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <div className=\"border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm\">\n <div className=\"bg-muted h-3 w-24 animate-pulse rounded\" />\n <div className=\"bg-muted h-8 w-48 animate-pulse rounded\" />\n <div className=\"bg-muted mt-7 h-10 w-full animate-pulse rounded-md\" />\n </div>\n </main>\n );\n}\n","\"use client\";\n\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\n\nexport type PaginationProps = {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n loading?: boolean;\n showPageInfo?: boolean;\n};\n\n/**\n * Numbered pager for list panels. Hides itself when there is only one page.\n */\nexport function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n loading = false,\n showPageInfo = true,\n}: PaginationProps) {\n const visiblePages = React.useMemo(() => {\n const delta = 2;\n const range: number[] = [];\n const rangeWithDots: Array<number | \"...\"> = [];\n\n for (\n let i = Math.max(2, currentPage - delta);\n i <= Math.min(totalPages - 1, currentPage + delta);\n i++\n ) {\n range.push(i);\n }\n\n if (currentPage - delta > 2) {\n rangeWithDots.push(1, \"...\");\n } else {\n rangeWithDots.push(1);\n }\n\n rangeWithDots.push(...range);\n\n if (currentPage + delta < totalPages - 1) {\n rangeWithDots.push(\"...\", totalPages);\n } else if (totalPages > 1) {\n rangeWithDots.push(totalPages);\n }\n\n return rangeWithDots;\n }, [currentPage, totalPages]);\n\n if (totalPages <= 1) return null;\n\n return (\n <div className=\"flex flex-col items-center justify-between gap-4 sm:flex-row\">\n {showPageInfo ? (\n <div className=\"text-muted-foreground order-2 text-sm sm:order-1\">\n Page {currentPage} of {totalPages}\n </div>\n ) : null}\n\n <div className=\"order-1 flex items-center space-x-1 sm:order-2 sm:space-x-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1 || loading}\n className=\"h-8 min-w-8 px-2\"\n aria-label=\"Previous page\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n\n <div className=\"flex max-w-[200px] items-center space-x-1 overflow-x-auto sm:max-w-none\">\n {visiblePages.map((page, index) =>\n page === \"...\" ? (\n <div\n key={`dots-${index}`}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center\"\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </div>\n ) : (\n <Button\n key={page}\n variant={page === currentPage ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onPageChange(page)}\n disabled={loading}\n className=\"h-8 min-w-8 shrink-0 px-2\"\n aria-current={page === currentPage ? \"page\" : undefined}\n >\n {page}\n </Button>\n ),\n )}\n </div>\n\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages || loading}\n className=\"h-8 min-w-8 px-2\"\n aria-label=\"Next page\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The one-of-N picker seven panels were each drawing by hand.\n *\n * Not `Tabs`, which is a bottom-bordered strip sitting above the content it\n * switches. This is the inline version — a bordered track with the selected\n * option filled in — used for a filter or a setting that sits among other\n * controls rather than heading a panel.\n *\n * **Roles are the reason to use this.** The seven copies had three different\n * ideas about what they were: one said `tablist`/`tab`, one said\n * `group`/`aria-pressed`, and the other five said nothing at all — so on five\n * of seven a screen reader heard a row of unlabelled buttons with no\n * indication which one was active. None of the three was right. `tablist`\n * without a `tabpanel` is a promise the markup does not keep, and\n * `aria-pressed` describes independent toggles, not a choice of one. Picking a\n * value out of a fixed set is a radio group, so that is what this is, with the\n * roving tabindex and arrow keys that come with the role.\n *\n * `tone` is kept for call-site compatibility. Both `emphasis` and `primary`\n * resolve to `bg-primary text-primary-foreground` — neutral brand primary is\n * already the ink fill five panels used, and a raw `slate-950` utility would\n * escape brand recoloring. Prefer `primary` in new code.\n */\nexport interface SegmentedOption<Value extends string> {\n value: Value;\n label: React.ReactNode;\n disabled?: boolean;\n /**\n * Hover text. Worth setting on a disabled option — \"Everyone\" going grey\n * says nothing about which permission would bring it back.\n */\n title?: string;\n}\n\nexport interface SegmentedControlProps<Value extends string> {\n options: ReadonlyArray<SegmentedOption<Value>>;\n value: Value;\n onChange: (value: Value) => void;\n /**\n * Required: the group never has a visible label — the options name the\n * choice between them, which tells you nothing about what is being chosen.\n */\n ariaLabel: string;\n /**\n * `contained` — one bordered track around the options (five panels).\n * `loose` — free-standing pills with a gap between them (two panels).\n */\n variant?: \"contained\" | \"loose\";\n /** Prefer `primary`. `emphasis` is an alias kept for existing call sites. */\n tone?: \"emphasis\" | \"primary\";\n /** Options share the width equally, for a control that fills its column. */\n fill?: boolean;\n className?: string;\n}\n\nconst TONE_ON = \"bg-primary text-primary-foreground\";\nconst TONE_OFF = \"text-muted-foreground hover:bg-muted\";\n\nconst TONES = {\n emphasis: { on: TONE_ON, off: TONE_OFF },\n primary: { on: TONE_ON, off: TONE_OFF },\n} as const;\n\nconst TRACKS = {\n contained: \"border-border inline-flex rounded-md border p-0.5\",\n loose: \"flex flex-wrap gap-2\",\n} as const;\n\nexport function SegmentedControl<Value extends string>({\n options,\n value,\n onChange,\n ariaLabel,\n variant = \"contained\",\n tone = \"emphasis\",\n fill = false,\n className,\n}: SegmentedControlProps<Value>) {\n const refs = React.useRef(new Map<Value, HTMLButtonElement | null>());\n\n function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step =\n event.key === \"ArrowRight\" || event.key === \"ArrowDown\"\n ? 1\n : event.key === \"ArrowLeft\" || event.key === \"ArrowUp\"\n ? -1\n : 0;\n if (step === 0) return;\n\n const selectable = options.filter((option) => !option.disabled);\n if (selectable.length < 2) return;\n\n const current = selectable.findIndex((option) => option.value === value);\n // Wraps, which is what a radio group is expected to do.\n const next =\n selectable[(current + step + selectable.length) % selectable.length];\n\n event.preventDefault();\n onChange(next.value);\n // The newly checked option has to take focus, or the next arrow press is\n // still measured from the old one.\n refs.current.get(next.value)?.focus();\n }\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n className={cn(TRACKS[variant], className)}\n >\n {options.map((option) => {\n const checked = option.value === value;\n return (\n <button\n key={option.value}\n ref={(node) => {\n refs.current.set(option.value, node);\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n disabled={option.disabled}\n title={option.title}\n // Only the checked option is reachable by Tab; arrows move within\n // the group. Without this a keyboard user pages through every\n // option to get past the control.\n tabIndex={checked ? 0 : -1}\n onClick={() => onChange(option.value)}\n className={cn(\n \"cursor-pointer rounded px-3 py-1 text-sm font-medium transition\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n fill && \"flex-1\",\n checked ? TONES[tone].on : TONES[tone].off,\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Autocomplete, type AutocompleteOption } from \"./autocomplete\";\n\ntype SelectChange = {\n target: { value: string };\n currentTarget: { value: string };\n};\n\nexport type SelectProps = {\n id?: string;\n className?: string;\n disabled?: boolean;\n /** Accessible name when the control is not wrapped in a label. */\n \"aria-label\"?: string;\n /** `compact` fits a spreadsheet cell. Typing still filters the list. */\n size?: \"default\" | \"compact\";\n value?: string | number | readonly string[];\n placeholder?: string;\n children?: React.ReactNode;\n onChange?: (event: SelectChange) => void;\n};\n\nfunction optionText(node: React.ReactNode): 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(optionText).join(\"\");\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return optionText(node.props.children);\n }\n return \"\";\n}\n\nfunction optionsFromChildren(children: React.ReactNode): AutocompleteOption[] {\n const options: AutocompleteOption[] = [];\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n if (child.type === React.Fragment) {\n options.push(\n ...optionsFromChildren(\n (child.props as { children?: React.ReactNode }).children,\n ),\n );\n return;\n }\n const props = child.props as {\n value?: string | number;\n disabled?: boolean;\n children?: React.ReactNode;\n };\n const value = props.value == null ? \"\" : String(props.value);\n options.push({\n value,\n label: optionText(props.children).trim() || value,\n disabled: Boolean(props.disabled),\n });\n });\n return options;\n}\n\n/**\n * The dropdown. It is the searchable autocomplete, not a native `<select>`,\n * so a long list can be typed into and an empty list still opens.\n */\nexport function Select({\n id,\n className,\n disabled,\n value,\n placeholder,\n children,\n onChange,\n size = \"default\",\n \"aria-label\": ariaLabel,\n}: SelectProps) {\n const options = optionsFromChildren(children);\n const current = Array.isArray(value)\n ? String(value[0] ?? \"\")\n : value == null\n ? \"\"\n : String(value);\n const blank = options.find((option) => option.value === \"\");\n\n return (\n <Autocomplete\n id={id}\n className={className}\n disabled={Boolean(disabled)}\n ariaLabel={ariaLabel}\n size={size}\n options={options}\n value={current}\n clearable={false}\n placeholder={placeholder ?? blank?.label ?? \"Search…\"}\n onChange={(next) =>\n onChange?.({\n target: { value: next },\n currentTarget: { value: next },\n })\n }\n />\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type SeparatorProps = React.HTMLAttributes<HTMLDivElement> & {\n orientation?: \"horizontal\" | \"vertical\";\n decorative?: boolean;\n};\n\n/** Thin rule between sections. */\nexport const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref,\n ) => (\n <div\n ref={ref}\n role={decorative ? \"none\" : \"separator\"}\n aria-orientation={orientation}\n className={cn(\n \"bg-border shrink-0\",\n orientation === \"horizontal\" ? \"h-px w-full\" : \"h-full w-px\",\n className,\n )}\n {...props}\n />\n ),\n);\n\nSeparator.displayName = \"Separator\";\n","\"use client\";\n\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { Button } from \"./button\";\nimport { useDialogLayer } from \"./dialogLayer\";\nimport { useHasMounted } from \"./modal\";\nimport { cn } from \"./utils\";\n\ninterface SideDrawerProps {\n isOpen: boolean;\n title: string;\n onClose: () => void;\n children: React.ReactNode;\n /** Tailwind width class for the panel. Defaults to a reading-width column. */\n panelClassName?: string;\n}\n\n/**\n * A panel that slides in from the right.\n *\n * For content that belongs beside the page rather than on top of it — a queue\n * you glance at and dismiss, not a decision you have to answer. Unlike\n * `Modal`, it does not centre or dim the whole page to a stop: the table\n * underneath stays readable, which is the point of looking at both.\n */\nexport function SideDrawer({\n isOpen,\n title,\n onClose,\n children,\n panelClassName,\n}: SideDrawerProps) {\n const mounted = useHasMounted();\n const headingId = React.useId();\n const panelRef = React.useRef<HTMLElement>(null);\n\n useDialogLayer({\n // Gated on `mounted` too: before that the panel is not rendered, so there\n // would be nothing to move focus into.\n active: isOpen && mounted,\n containerRef: panelRef,\n onEscape: onClose,\n });\n\n if (!mounted || !isOpen) return null;\n\n return createPortal(\n <>\n <div\n aria-hidden\n onClick={onClose}\n className=\"fixed inset-0 z-[90] bg-overlay/30\"\n />\n <aside\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={headingId}\n tabIndex={-1}\n className={cn(\n \"border-border bg-background fixed inset-y-0 right-0 z-[95] flex flex-col border-l shadow-2xl outline-none\",\n panelClassName ?? \"w-full max-w-md\",\n )}\n >\n <div className=\"border-border flex items-center justify-between gap-3 border-b px-4 py-3\">\n <h2 id={headingId} className=\"truncate text-base font-semibold\">\n {title}\n </h2>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Close panel\"\n onClick={onClose}\n >\n <X className=\"h-4 w-4\" aria-hidden />\n </Button>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">{children}</div>\n </aside>\n </>,\n document.body,\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { type CellRange, type CellRef } from \"./clipboard\";\n\n/**\n * A column knows three things: its heading, the text it contributes to a copy\n * or CSV export, and optionally how to draw itself.\n *\n * Keeping `value` and `render` together is what stops an exported sheet from\n * drifting from the visible grid.\n */\nexport type GridColumn<Row> = {\n key: string;\n title: string;\n /** Text used for clipboard and CSV. Never JSX. */\n value: (row: Row) => string;\n /** Defaults to `value`. Use for links, tiles, truncation. */\n render?: (row: Row) => React.ReactNode;\n /** Extra classes for the <td>. */\n className?: string;\n};\n\nexport interface SpreadsheetGridProps<Row> {\n columns: GridColumn<Row>[];\n rows: Row[];\n /** Stable React key per row. Defaults to the row index. */\n rowKey?: (row: Row, index: number) => string;\n loading?: boolean;\n emptyMessage?: string;\n loadingMessage?: string;\n ariaLabel?: string;\n /** Lifted so a toolbar can copy and describe the current selection. */\n range: CellRange | null;\n onRangeChange: (selection: {\n anchor: CellRef | null;\n focus: CellRef | null;\n }) => void;\n onCopy: () => void;\n}\n\nfunction isInRange(range: CellRange | null, r: number, c: number): boolean {\n if (!range) return false;\n return r >= range.r1 && r <= range.r2 && c >= range.c1 && c <= range.c2;\n}\n\n/**\n * Spreadsheet-like grid: click-drag a range, shift+click to extend, arrows to\n * move, click a heading to take the column, click the row number to take the\n * row, Cmd/Ctrl+A for everything, Escape to clear, Cmd/Ctrl+C to copy.\n *\n * Ported from video-shorts-panel's ExcelTable, which several panels share for\n * exactly this reason — a table people paste into a sheet.\n */\nexport function SpreadsheetGrid<Row>({\n columns,\n rows,\n rowKey,\n loading,\n emptyMessage = \"Nothing to show.\",\n loadingMessage = \"Loading…\",\n ariaLabel = \"Data grid\",\n range,\n onRangeChange,\n onCopy,\n}: SpreadsheetGridProps<Row>) {\n const gridRef = React.useRef<HTMLDivElement>(null);\n const anchorRef = React.useRef<CellRef | null>(null);\n const focusRef = React.useRef<CellRef | null>(null);\n const [dragging, setDragging] = React.useState(false);\n\n const setSelection = React.useCallback(\n (anchor: CellRef | null, focus: CellRef | null) => {\n anchorRef.current = anchor;\n focusRef.current = focus;\n onRangeChange({ anchor, focus });\n },\n [onRangeChange],\n );\n\n const selectCell = React.useCallback(\n (r: number, c: number, extend?: boolean) => {\n if (extend && anchorRef.current)\n setSelection(anchorRef.current, { r, c });\n else setSelection({ r, c }, { r, c });\n },\n [setSelection],\n );\n\n const selectColumn = React.useCallback(\n (c: number, extend?: boolean) => {\n const lastRow = Math.max(rows.length - 1, 0);\n const anchorCol = extend && anchorRef.current ? anchorRef.current.c : c;\n setSelection({ r: 0, c: anchorCol }, { r: lastRow, c });\n },\n [rows.length, setSelection],\n );\n\n const selectRow = React.useCallback(\n (r: number, extend?: boolean) => {\n const lastCol = columns.length - 1;\n const anchorRow = extend && anchorRef.current ? anchorRef.current.r : r;\n setSelection({ r: anchorRow, c: 0 }, { r, c: lastCol });\n },\n [columns.length, setSelection],\n );\n\n const selectAll = React.useCallback(() => {\n if (!rows.length || !columns.length) return;\n setSelection({ r: 0, c: 0 }, { r: rows.length - 1, c: columns.length - 1 });\n }, [rows.length, columns.length, setSelection]);\n\n const scrollCellIntoView = React.useCallback((r: number, c: number) => {\n const cell = gridRef.current?.querySelector(`[data-cell=\"${r}-${c}\"]`);\n cell?.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n }, []);\n\n const moveFocus = React.useCallback(\n (dr: number, dc: number, extend?: boolean) => {\n if (!rows.length || !columns.length) return;\n const base = focusRef.current || { r: 0, c: 0 };\n const r = Math.min(Math.max(base.r + dr, 0), rows.length - 1);\n const c = Math.min(Math.max(base.c + dc, 0), columns.length - 1);\n selectCell(r, c, extend);\n scrollCellIntoView(r, c);\n },\n [rows.length, columns.length, selectCell, scrollCellIntoView],\n );\n\n // Dragging must end even if the pointer is released outside the grid.\n React.useEffect(() => {\n if (!dragging) return;\n const stop = () => setDragging(false);\n window.addEventListener(\"mouseup\", stop);\n return () => window.removeEventListener(\"mouseup\", stop);\n }, [dragging]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const meta = event.metaKey || event.ctrlKey;\n if (meta && event.key.toLowerCase() === \"c\") {\n event.preventDefault();\n onCopy();\n return;\n }\n if (meta && event.key.toLowerCase() === \"a\") {\n event.preventDefault();\n selectAll();\n return;\n }\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n moveFocus(-1, 0, event.shiftKey);\n break;\n case \"ArrowDown\":\n event.preventDefault();\n moveFocus(1, 0, event.shiftKey);\n break;\n case \"ArrowLeft\":\n event.preventDefault();\n moveFocus(0, -1, event.shiftKey);\n break;\n case \"ArrowRight\":\n case \"Tab\":\n event.preventDefault();\n moveFocus(0, 1, event.shiftKey && event.key !== \"Tab\");\n break;\n case \"Escape\":\n setSelection(null, null);\n break;\n default:\n break;\n }\n };\n\n return (\n <div\n ref={gridRef}\n tabIndex={0}\n role=\"grid\"\n aria-label={ariaLabel}\n onKeyDown={handleKeyDown}\n className=\"border-border bg-background/80 overflow-x-auto rounded-lg border outline-none\"\n >\n <table className=\"w-full text-sm whitespace-nowrap select-none\">\n <thead className=\"text-muted-foreground border-border border-b text-left\">\n <tr>\n <th\n scope=\"col\"\n className=\"w-10 cursor-pointer px-2 py-2 text-center font-medium\"\n title=\"Select everything\"\n onMouseDown={() => selectAll()}\n >\n #\n </th>\n {columns.map((column, c) => (\n <th\n key={column.key}\n scope=\"col\"\n className=\"cursor-pointer px-3 py-2 font-medium\"\n title={`Select the ${column.title} column`}\n onMouseDown={(event) => selectColumn(c, event.shiftKey)}\n >\n {column.title}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length + 1}\n className=\"text-muted-foreground px-3 py-6 text-center\"\n >\n {loading ? loadingMessage : emptyMessage}\n </td>\n </tr>\n ) : (\n rows.map((row, r) => (\n <tr\n key={rowKey ? rowKey(row, r) : String(r)}\n className=\"border-border border-b\"\n >\n <td\n className=\"text-muted-foreground w-10 cursor-pointer px-2 py-2 text-center text-xs\"\n title=\"Select this row\"\n onMouseDown={(event) => selectRow(r, event.shiftKey)}\n >\n {r + 1}\n </td>\n {columns.map((column, c) => (\n <td\n key={column.key}\n data-cell={`${r}-${c}`}\n onMouseDown={(event) => {\n selectCell(r, c, event.shiftKey);\n setDragging(true);\n gridRef.current?.focus();\n }}\n onMouseEnter={() => {\n if (dragging) setSelection(anchorRef.current, { r, c });\n }}\n className={`px-3 py-2 ${column.className || \"\"} ${\n isInRange(range, r, c) ? \"bg-primary/15\" : \"\"\n }`}\n title={\n column.className?.includes(\"truncate\")\n ? column.value(row)\n : undefined\n }\n >\n {column.render ? column.render(row) : column.value(row)}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type SwitchProps = Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"onChange\"\n> & {\n checked: boolean;\n onCheckedChange: (checked: boolean) => void;\n};\n\n/** Compact accessible toggle — use instead of full-width checkbox inputs. */\nexport const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(\n ({ checked, onCheckedChange, className, disabled, id, ...props }, ref) => (\n <button\n ref={ref}\n id={id}\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled}\n onClick={() => onCheckedChange(!checked)}\n className={cn(\n // 24×44px track meets DESIGN.md 24px minimum target size.\n \"relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border transition-colors\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n checked ? \"border-primary bg-primary\" : \"border-border bg-muted\",\n className,\n )}\n {...props}\n >\n <span\n aria-hidden\n className={cn(\n \"bg-background pointer-events-none block size-5 rounded-full shadow-sm transition-transform\",\n checked ? \"translate-x-5\" : \"translate-x-0.5\",\n )}\n />\n </button>\n ),\n);\n\nSwitch.displayName = \"Switch\";\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * Low-level table primitives. Prefer `DataTable` for list panels; use these\n * when the row markup is custom (nested actions, expandable rows, etc.).\n */\nexport const Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n));\nTable.displayName = \"Table\";\n\nexport const TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n));\nTableHeader.displayName = \"TableHeader\";\n\nexport const TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n));\nTableBody.displayName = \"TableBody\";\n\nexport const TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n \"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0\",\n className,\n )}\n {...props}\n />\n));\nTableFooter.displayName = \"TableFooter\";\n\nexport const TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n \"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors\",\n className,\n )}\n {...props}\n />\n));\nTableRow.displayName = \"TableRow\";\n\nexport const TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"text-muted-foreground h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0\",\n className,\n )}\n {...props}\n />\n));\nTableHead.displayName = \"TableHead\";\n\nexport const TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n));\nTableCell.displayName = \"TableCell\";\n\nexport const TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn(\"text-muted-foreground mt-4 text-sm\", className)}\n {...props}\n />\n));\nTableCaption.displayName = \"TableCaption\";\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The tab strip five Managers were each drawing by hand, with the same\n * `rounded-t-md px-3 py-1.5 text-sm font-medium` and their own idea of what an\n * active tab looks like.\n *\n * It is a controlled component with no state of its own: every caller already\n * held the active key, usually because a URL or a query depends on it.\n *\n * Roles are the reason to use this rather than styling buttons again. A hand\n * -rolled strip is a row of buttons to a screen reader, which says nothing\n * about how many tabs there are or which is selected; `tablist` / `tab` /\n * `aria-selected` do. Arrow-key navigation comes with that expectation, so it\n * is implemented here too.\n *\n * Optional `panel` on a tab (or a sibling `TabPanel`) wires APG `aria-controls`\n * / `role=\"tabpanel\"`. Callers that already render content from `value` can\n * keep doing so and pass `panelId` for association, or switch to `panel`.\n */\nexport interface TabItem<Key extends string = string> {\n key: Key;\n label: React.ReactNode;\n /** Rendered after the label — a count, usually. */\n badge?: React.ReactNode;\n disabled?: boolean;\n /**\n * Optional panel body. When any tab provides `panel`, panels render under\n * the strip with `role=\"tabpanel\"`.\n */\n panel?: React.ReactNode;\n /**\n * External panel element id for `aria-controls` when panels live outside\n * this component.\n */\n panelId?: string;\n}\n\nexport interface TabsProps<Key extends string = string> {\n tabs: ReadonlyArray<TabItem<Key>>;\n value: Key;\n onChange: (key: Key) => void;\n /** Names the strip for screen readers. */\n ariaLabel?: string;\n className?: string;\n}\n\nexport interface TabPanelProps {\n /** Must match the controlling tab's generated or explicit id. */\n id: string;\n /** Id of the tab that labels this panel. */\n labelledBy: string;\n active: boolean;\n children: React.ReactNode;\n className?: string;\n}\n\n/** Companion panel for callers that keep content outside `Tabs`. */\nexport function TabPanel({\n id,\n labelledBy,\n active,\n children,\n className,\n}: TabPanelProps) {\n return (\n <div\n role=\"tabpanel\"\n id={id}\n aria-labelledby={labelledBy}\n hidden={!active}\n className={className}\n >\n {active ? children : null}\n </div>\n );\n}\n\nexport function Tabs<Key extends string = string>({\n tabs,\n value,\n onChange,\n ariaLabel,\n className,\n}: TabsProps<Key>) {\n const refs = React.useRef(new Map<Key, HTMLButtonElement | null>());\n const reactId = React.useId();\n const hasInlinePanels = tabs.some((tab) => tab.panel != null);\n\n function tabDomId(key: Key) {\n return `${reactId}-tab-${key}`;\n }\n\n function panelDomId(tab: TabItem<Key>) {\n return tab.panelId ?? `${reactId}-panel-${tab.key}`;\n }\n\n function focusTab(key: Key) {\n onChange(key);\n // The newly selected tab has to take focus, or the next arrow press is\n // still measured from the old one.\n refs.current.get(key)?.focus();\n }\n\n function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step =\n event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (step === 0) return;\n\n const selectable = tabs.filter((tab) => !tab.disabled);\n if (selectable.length < 2) return;\n\n const current = selectable.findIndex((tab) => tab.key === value);\n // Wraps, which is what a tablist is expected to do.\n const next =\n selectable[(current + step + selectable.length) % selectable.length];\n\n event.preventDefault();\n focusTab(next.key);\n }\n\n const tablist = (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n className={cn(\n \"border-border flex flex-wrap gap-1 border-b\",\n !hasInlinePanels ? className : undefined,\n )}\n >\n {tabs.map((tab) => {\n const active = tab.key === value;\n const id = tabDomId(tab.key);\n const controls =\n tab.panel != null || tab.panelId ? panelDomId(tab) : undefined;\n return (\n <button\n key={tab.key}\n id={id}\n ref={(node) => {\n refs.current.set(tab.key, node);\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n aria-controls={controls}\n disabled={tab.disabled}\n // Only the active tab is reachable by Tab; arrows move within the\n // strip. Without this a keyboard user pages through every tab to\n // get past the strip.\n tabIndex={active ? 0 : -1}\n onClick={() => onChange(tab.key)}\n className={cn(\n \"cursor-pointer rounded-t-md px-3 py-1.5 text-sm font-medium transition\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n // The filled-pill active state the five hand-rolled strips\n // already used. Adopting it keeps this a deduplication rather\n // than a restyle of every panel that has tabs.\n active\n ? \"bg-primary text-primary-foreground\"\n : \"text-muted-foreground hover:bg-muted\",\n )}\n >\n {tab.label}\n {tab.badge != null ? (\n <span className=\"text-muted-foreground ml-1.5 text-xs\">\n {tab.badge}\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n );\n\n if (!hasInlinePanels) return tablist;\n\n return (\n <div className={cn(\"space-y-3\", className)}>\n {tablist}\n {tabs.map((tab) =>\n tab.panel != null ? (\n <TabPanel\n key={tab.key}\n id={panelDomId(tab)}\n labelledBy={tabDomId(tab.key)}\n active={tab.key === value}\n >\n {tab.panel}\n </TabPanel>\n ) : null,\n )}\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The multi-line counterpart to `Input`.\n *\n * There was no shared textarea, so sixteen of them were styled individually\n * and no two agreed — different borders, different focus rings, some with no\n * focus ring at all, which is a keyboard user losing their place.\n *\n * Deliberately not `inputClass`: that fixes `h-9`, which is a one-line\n * control. Everything else is shared so a textarea and an input sitting in the\n * same form look related.\n */\nexport const textareaClass =\n \"border-border bg-background focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, rows = 3, ...props }, ref) => (\n <textarea\n ref={ref}\n rows={rows}\n className={cn(textareaClass, className)}\n {...props}\n />\n ),\n);\n\nTextarea.displayName = \"Textarea\";\n"],"mappings":"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","names":["Label","Separator","React","import_react_dom","React","React","active","import_jsx_runtime","import_jsx_runtime","React","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_jsx_runtime","React","import_class_variance_authority","import_lucide_react","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","React","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_lucide_react","React","React","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","Label","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","Separator","import_lucide_react","React","import_react_dom","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime"]}
|