@reopt-ai/opt-ui 1.7.0 → 1.8.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.
@@ -1 +1 @@
1
- {"version":3,"file":"field-sidebar-Cs-J-5VE.js","names":["PrimCommandRoot","DialogRoot","DialogPanel","DialogHeading","DialogDescription","CommandInput","PrimCommandInput","CommandList","PrimCommandList","CommandEmpty","PrimCommandEmpty","CommandGroup","PrimCommandGroup","CommandSeparator","PrimCommandSeparator","CommandItem","PrimCommandItem","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","defaultLabels","defaultLabels","ComboboxRoot","ComboboxInput","ComboboxPopover","ComboboxItem","defaultLabels","SelectRoot","SelectLabel","SelectTrigger","SelectPopover","SelectItem","defaultLabels","MenuRoot","MenuTrigger","MenuButtonArrow","MenuPopover","MenuSeparator","MenuItemCheckbox","MenuItemRadio","MenuItem","MenubarRoot","MenubarContainer","defaultLabels","defaultLabels","TooltipProvider","TooltipAnchor","ToolbarButton","Tooltip","ToolbarRoot","ToolbarContainer","ToolbarSeparator","defaultLabels","TabsRoot","TabList","Tab","TabPanel","defaultLabels","DisclosureRoot","DisclosureTrigger","DisclosureContent","defaultLabels","FormRoot","FormLabel","FormError","FormRadioGroup","FormRadio","FormCheckbox","FormSwitch","FormInput","FormSubmit","statusBadge","statusLabel","ComboboxRoot","ComboboxInput","ComboboxPopover","ComboboxItem","defaultLabels","DisclosureProvider","Disclosure","DisclosureContent","defaultLabels","SelectRoot","SelectLabel","SelectTrigger","SelectPopover","SelectItem","defaultLabels","Fragment","defaultLabels","defaultLabels","defaultLabels","PopoverRoot","PopoverTrigger","PopoverContent","SelectRoot","SelectTrigger","SelectPopover","SelectItem","defaultLabels","defaultLabels","defaultLabels"],"sources":["../src/core/command.tsx","../src/shells/command-palette.tsx","../src/shells/command-palette-trigger.tsx","../src/shells/dashboard-grid.tsx","../src/shells/search-combobox.tsx","../src/shells/status-select.tsx","../src/shells/app-menubar.tsx","../src/shells/sidebar-nav.tsx","../src/shells/editor-toolbar.tsx","../src/shells/content-tabs.tsx","../src/shells/faq-accordion.tsx","../src/shells/settings-form.tsx","../src/shells/deployment-timeline.tsx","../src/shells/project-switcher.tsx","../src/shells/env-panel.tsx","../src/shells/branch-select.tsx","../src/shells/domain-table.tsx","../src/shells/data-table.tsx","../src/shells/notification-toast.tsx","../src/shells/failure-list.tsx","../src/shells/key-value-editor.tsx","../src/shells/workflow-canvas.tsx","../src/lib/use-auto-refresh.ts","../src/shells/time-range-control.tsx","../src/shells/time-series-panel.tsx","../src/shells/log-table.tsx","../src/lib/query/query-ast.ts","../src/lib/query/query-parse.ts","../src/lib/query/query-format.ts","../src/shells/query-bar.tsx","../src/shells/field-sidebar.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { SearchIcon } from \"lucide-react\";\nimport {\n CommandRoot as PrimCommandRoot,\n CommandInput as PrimCommandInput,\n CommandList as PrimCommandList,\n CommandEmpty as PrimCommandEmpty,\n CommandGroup as PrimCommandGroup,\n CommandSeparator as PrimCommandSeparator,\n CommandItem as PrimCommandItem,\n} from \"@reopt-ai/opt-ui-primitives\";\nimport type {\n CommandRootProps as PrimCommandRootProps,\n CommandInputProps as PrimCommandInputProps,\n CommandListProps as PrimCommandListProps,\n CommandEmptyProps as PrimCommandEmptyProps,\n CommandGroupProps as PrimCommandGroupProps,\n CommandSeparatorProps as PrimCommandSeparatorProps,\n CommandItemProps as PrimCommandItemProps,\n} from \"@reopt-ai/opt-ui-primitives\";\nimport { cn } from \"../lib/cn\";\nimport {\n DialogRoot,\n DialogPanel,\n DialogHeading,\n DialogDescription,\n} from \"./dialog\";\n\n/* ─── Command (root) ─── */\n\n/** Renders the `Command` component. */\nexport function Command({ className, ...props }: PrimCommandRootProps) {\n return (\n <PrimCommandRoot\n className={cn(\n \"bg-surface text-text-primary flex w-full flex-col overflow-hidden rounded-xl\",\n className,\n )}\n {...props}\n data-opt-id=\"4FYBW\"\n data-opt-slug=\"command.Command\"\n />\n );\n}\n\n/* ─── CommandDialog ─── */\n\n/** Props for the `CommandDialog` component. */\nexport interface CommandDialogProps {\n /** Open state. */\n open: boolean;\n /** Open state setter. */\n onOpenChange: (open: boolean) => void;\n /** Accessible title (visually hidden by default). */\n title?: string;\n /** Accessible description (visually hidden by default). */\n description?: string;\n /** Optional className for the dialog panel. */\n className?: string;\n /** Optional className for the inner Command root. */\n commandClassName?: string;\n /** Filter behaviour passed through to the inner Command root. */\n shouldFilter?: PrimCommandRootProps[\"shouldFilter\"];\n filter?: PrimCommandRootProps[\"filter\"];\n children: ReactNode;\n}\n\n/** Renders a Command in a dialog overlay, à la Cmd+K palette. */\nexport function CommandDialog({\n open,\n onOpenChange,\n title = \"Command Palette\",\n description = \"검색 후 Enter 또는 클릭으로 명령을 실행하세요.\",\n className,\n commandClassName,\n shouldFilter,\n filter,\n children,\n}: CommandDialogProps) {\n return (\n <DialogRoot\n open={open}\n onOpenChange={onOpenChange}\n data-opt-id=\"DVRSX\"\n data-opt-slug=\"command.CommandDialog\"\n >\n <DialogPanel\n className={cn(\n \"top-[20%] left-1/2 -translate-x-1/2\",\n \"w-full max-w-lg overflow-hidden p-0 shadow-2xl\",\n className,\n )}\n >\n <DialogHeading className=\"sr-only\">{title}</DialogHeading>\n <DialogDescription className=\"sr-only\">{description}</DialogDescription>\n <Command\n shouldFilter={shouldFilter}\n filter={filter}\n className={commandClassName}\n >\n {children}\n </Command>\n </DialogPanel>\n </DialogRoot>\n );\n}\n\n/* ─── CommandInput ─── */\n\n/** Props for the `CommandInput` component. */\nexport interface CommandInputProps extends PrimCommandInputProps {\n /** Trailing content rendered on the right side (e.g. ESC kbd). */\n trailing?: ReactNode;\n /** Optional className for the input wrapper. */\n wrapperClassName?: string;\n}\n\n/** Renders the `CommandInput` component with a leading search icon. */\nexport function CommandInput({\n className,\n trailing,\n wrapperClassName,\n placeholder,\n \"aria-label\": ariaLabel,\n ...props\n}: CommandInputProps) {\n return (\n <div\n data-slot=\"command-input-wrapper\"\n className={cn(\n \"border-border-subtle gap-element flex h-12 items-center border-b px-3\",\n wrapperClassName,\n )}\n data-opt-id=\"HB1K3\"\n data-opt-slug=\"command.CommandInput\"\n >\n <SearchIcon aria-hidden className=\"text-text-tertiary size-4 shrink-0\" />\n <PrimCommandInput\n className={cn(\n // cmdk 컨벤션 — input 자체는 ring 없이 자연스러운 검색 경험.\n // 포커스 표시는 wrapper(border-b)가 시각적 컨텍스트로 제공.\n \"text-text-primary placeholder:text-text-tertiary flex h-full w-full bg-transparent text-sm outline-none focus-visible:ring-0 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n placeholder={placeholder}\n aria-label={\n ariaLabel ??\n (typeof placeholder === \"string\" ? placeholder : \"Command search\")\n }\n {...props}\n />\n {trailing}\n </div>\n );\n}\n\n/* ─── CommandList ─── */\n\n/** Renders the `CommandList` component. */\nexport function CommandList({\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: PrimCommandListProps) {\n return (\n <PrimCommandList\n className={cn(\n \"max-h-80 scroll-py-1 overflow-x-hidden overflow-y-auto p-1\",\n className,\n )}\n aria-label={ariaLabel ?? \"Commands\"}\n {...props}\n data-opt-id=\"NPXC5\"\n data-opt-slug=\"command.CommandList\"\n />\n );\n}\n\n/* ─── CommandEmpty ─── */\n\n/** Renders the `CommandEmpty` component. */\nexport function CommandEmpty({ className, ...props }: PrimCommandEmptyProps) {\n return (\n <PrimCommandEmpty\n className={cn(\"text-text-tertiary py-6 text-center text-sm\", className)}\n {...props}\n data-opt-id=\"A8BZM\"\n data-opt-slug=\"command.CommandEmpty\"\n />\n );\n}\n\n/* ─── CommandGroup ─── */\n\n/** Renders the `CommandGroup` component with an optional heading. */\nexport function CommandGroup({\n className,\n heading,\n ...props\n}: PrimCommandGroupProps) {\n return (\n <PrimCommandGroup\n heading={\n heading != null ? (\n <div className=\"text-text-tertiary px-2 py-1.5 text-xs font-medium\">\n {heading}\n </div>\n ) : undefined\n }\n className={cn(\"py-1\", className)}\n {...props}\n data-opt-id=\"JPK1Y\"\n data-opt-slug=\"command.CommandGroup\"\n />\n );\n}\n\n/* ─── CommandSeparator ─── */\n\n/** Renders the `CommandSeparator` component. */\nexport function CommandSeparator({\n className,\n ...props\n}: PrimCommandSeparatorProps) {\n return (\n <PrimCommandSeparator\n className={cn(\"bg-border-subtle -mx-1 my-1 h-px\", className)}\n {...props}\n data-opt-id=\"10P0E\"\n data-opt-slug=\"command.CommandSeparator\"\n />\n );\n}\n\n/* ─── CommandItem ─── */\n\n/** Renders the `CommandItem` component. */\nexport function CommandItem({ className, ...props }: PrimCommandItemProps) {\n return (\n <PrimCommandItem\n className={cn(\n \"text-text-primary flex cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-sm select-none\",\n \"data-[active-item]:bg-accent data-[active-item]:text-accent-fg\",\n \"data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n data-opt-id=\"K674W\"\n data-opt-slug=\"command.CommandItem\"\n />\n );\n}\n\n/* ─── CommandShortcut ─── */\n\n/** Renders the `CommandShortcut` component (right-aligned hint). */\nexport function CommandShortcut({\n className,\n ...props\n}: ComponentPropsWithoutRef<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n \"text-text-tertiary ml-auto text-xs tracking-widest\",\n \"data-[active-item]:text-accent-fg/80\",\n className,\n )}\n {...props}\n data-opt-id=\"75CQK\"\n data-opt-slug=\"command.CommandShortcut\"\n />\n );\n}\n","\"use client\";\n\nimport { useMemo, type KeyboardEvent, type ReactNode } from \"react\";\nimport type { CommandDef } from \"../lib/types\";\nimport { Kbd } from \"../core/kbd\";\nimport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n} from \"../core/command\";\nimport { cn } from \"../lib/cn\";\n\n/** Localized labels for the command palette component. */\nexport interface CommandPaletteLabels {\n title?: string;\n description?: string;\n input?: string;\n placeholder?: string;\n list?: string;\n empty?: ReactNode;\n escape?: string;\n}\n\nconst DEFAULT_LABELS: Required<CommandPaletteLabels> = {\n title: \"Command Palette\",\n description: \"검색 후 Enter 또는 클릭으로 명령을 실행하세요.\",\n input: \"명령어 검색\",\n placeholder: \"명령어를 검색하세요...\",\n list: \"명령어 목록\",\n empty: \"결과가 없습니다.\",\n escape: \"ESC\",\n};\n\n/** Props for the command palette component. */\nexport interface CommandPaletteProps {\n commands: Omit<CommandDef, \"action\">[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSelect?: (command: Omit<CommandDef, \"action\">) => void;\n /** Render inline (no dialog overlay). */\n inline?: boolean;\n labels?: CommandPaletteLabels;\n footer?: ReactNode;\n empty?: ReactNode;\n inputTrailing?: ReactNode;\n className?: string;\n}\n\n/** Renders the command palette component. */\nexport function CommandPalette({\n commands,\n open,\n onOpenChange,\n onSelect,\n inline = false,\n labels,\n footer,\n empty,\n inputTrailing,\n className,\n}: CommandPaletteProps) {\n const resolvedLabels = { ...DEFAULT_LABELS, ...labels };\n const hasCommands = commands.length > 0;\n const grouped = useMemo(() => {\n const map = new Map<string, Omit<CommandDef, \"action\">[]>();\n for (const cmd of commands) {\n const list = map.get(cmd.group) ?? [];\n list.push(cmd);\n map.set(cmd.group, list);\n }\n return map;\n }, [commands]);\n\n const handleSelect = (cmdId: string) => {\n const cmd = commands.find((c) => c.id === cmdId);\n if (!cmd) return;\n onSelect?.(cmd);\n onOpenChange(false);\n };\n\n const handleInputKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Escape\" && !inline) {\n // Dialog handles its own Esc; this branch covers the inline-with-Esc case.\n e.preventDefault();\n onOpenChange(false);\n }\n };\n\n const body = (\n <>\n <CommandInput\n aria-label={resolvedLabels.input}\n placeholder={resolvedLabels.placeholder}\n onKeyDown={handleInputKeyDown}\n trailing={\n inputTrailing ??\n (!inline ? <Kbd>{resolvedLabels.escape}</Kbd> : undefined)\n }\n />\n <CommandList aria-label={resolvedLabels.list}>\n <CommandEmpty>{empty ?? resolvedLabels.empty}</CommandEmpty>\n {hasCommands\n ? Array.from(grouped.entries()).map(([group, items]) => (\n <CommandGroup key={group} heading={group}>\n {items.map((cmd) => (\n <CommandItem\n key={cmd.id}\n value={cmd.id}\n keywords={[\n cmd.label,\n cmd.group,\n ...(cmd.shortcut ? [cmd.shortcut] : []),\n ]}\n onSelect={handleSelect}\n >\n <span>{cmd.label}</span>\n {cmd.shortcut && (\n <CommandShortcut>{cmd.shortcut}</CommandShortcut>\n )}\n </CommandItem>\n ))}\n </CommandGroup>\n ))\n : null}\n </CommandList>\n {footer}\n </>\n );\n\n if (inline) {\n if (!open) return null;\n return (\n <Command\n className={cn(\n \"border-border bg-surface w-full max-w-lg border shadow-lg\",\n className,\n )}\n data-opt-id=\"ATTF5\"\n data-opt-slug=\"command-palette.CommandPalette\"\n >\n {body}\n </Command>\n );\n }\n\n return (\n <CommandDialog\n open={open}\n onOpenChange={onOpenChange}\n title={resolvedLabels.title}\n description={resolvedLabels.description}\n className={className}\n data-opt-id=\"ATTF5\"\n data-opt-slug=\"command-palette.CommandPalette\"\n >\n {body}\n </CommandDialog>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { CommandDef } from \"../lib/types\";\nimport { CommandPalette, type CommandPaletteLabels } from \"./command-palette\";\n\n/** Props for the command palette trigger component. */\nexport interface CommandPaletteTriggerProps {\n commands: Omit<CommandDef, \"action\">[];\n onSelect?: (command: Omit<CommandDef, \"action\">) => void;\n labels?: CommandPaletteTriggerLabels;\n}\n\n/** Localized labels for the command palette trigger component. */\nexport type CommandPaletteTriggerLabels = CommandPaletteLabels;\n\n/** Renders the command palette trigger component. */\nexport function CommandPaletteTrigger({\n commands,\n onSelect,\n labels,\n}: CommandPaletteTriggerProps) {\n const [open, setOpen] = useState(false);\n\n const handleKeyDown = useCallback((e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"k\") {\n e.preventDefault();\n setOpen(true);\n }\n }, []);\n\n useEffect(() => {\n if (commands.length === 0) return;\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [commands.length, handleKeyDown]);\n\n if (commands.length === 0) return null;\n\n return (\n <CommandPalette\n commands={commands}\n open={open}\n onOpenChange={setOpen}\n onSelect={onSelect}\n labels={labels}\n data-opt-id=\"4FCDB\"\n data-opt-slug=\"command-palette-trigger.CommandPaletteTrigger\"\n />\n );\n}\n","import type { CSSProperties } from \"react\";\n\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n CompositeRow,\n} from \"../core/composite-zone\";\nimport { StatCard } from \"../core/stat-card\";\nimport type { StatCard as StatCardType } from \"../lib/types\";\n\n/** Localized labels for the dashboard grid component. */\nexport interface DashboardGridLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<DashboardGridLabels> = {\n ariaLabel: \"대시보드 통계\",\n};\n\nconst MIN_DASHBOARD_COLUMNS = 1;\nconst MAX_DASHBOARD_COLUMNS = 12;\n\nfunction normalizeDashboardColumns(columns: number): number {\n if (!Number.isFinite(columns)) return MIN_DASHBOARD_COLUMNS;\n return Math.min(\n MAX_DASHBOARD_COLUMNS,\n Math.max(MIN_DASHBOARD_COLUMNS, Math.floor(columns)),\n );\n}\n\n/** Props for the dashboard grid component. */\nexport interface DashboardGridProps {\n stats: StatCardType[];\n columns?: number;\n labels?: DashboardGridLabels;\n}\n\n/** Renders the dashboard grid component. */\nexport function DashboardGrid({\n stats,\n columns = 3,\n labels: customLabels,\n}: DashboardGridProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const columnCount = normalizeDashboardColumns(columns);\n const rowStyle = {\n \"--opt-dashboard-grid-columns\": `repeat(${columnCount}, minmax(0, 1fr))`,\n } as CSSProperties;\n\n const rows: StatCardType[][] = [];\n for (let i = 0; i < stats.length; i += columnCount) {\n rows.push(stats.slice(i, i + columnCount));\n }\n\n return (\n <CompositeProvider\n focusLoop\n focusWrap\n data-opt-id=\"BM7NA\"\n data-opt-slug=\"dashboard-grid.DashboardGrid\"\n >\n <Composite\n role=\"grid\"\n aria-label={labels.ariaLabel}\n className=\"gap-group flex flex-col\"\n >\n {rows.map((row, ri) => (\n <CompositeRow\n key={ri}\n className=\"gap-group grid grid-cols-1 sm:[grid-template-columns:var(--opt-dashboard-grid-columns)]\"\n style={rowStyle}\n >\n {row.map((stat) => (\n <CompositeItem\n key={stat.id}\n className=\"data-[active-item]:ring-ring data-[active-item]:ring-offset-ring-offset data-[focus-visible]:ring-ring data-[focus-visible]:ring-offset-ring-offset rounded-xl outline-none data-[active-item]:ring-2 data-[active-item]:ring-offset-2 data-[focus-visible]:ring-2 data-[focus-visible]:ring-offset-2\"\n render={<div role=\"gridcell\" />}\n >\n <StatCard {...stat} />\n </CompositeItem>\n ))}\n </CompositeRow>\n ))}\n </Composite>\n </CompositeProvider>\n );\n}\n","\"use client\";\n\nimport { matchSorter } from \"match-sorter\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { FormEvent } from \"react\";\nimport {\n ComboboxRoot,\n ComboboxInput,\n ComboboxPopover,\n ComboboxItem,\n ComboboxEmpty,\n} from \"../core/combobox\";\nimport { Spinner } from \"../core/spinner\";\nimport { OPT_TEXT_LABEL } from \"../lib/styles\";\n\n/** Localized labels for the search combobox component. */\nexport interface SearchComboboxLabels {\n noResults?: string;\n loading?: string;\n}\n\nconst defaultLabels: Required<SearchComboboxLabels> = {\n noResults: \"결과가 없습니다.\",\n loading: \"Loading…\",\n};\n\n/** Props for the search combobox component. */\nexport interface SearchComboboxProps {\n items: string[];\n placeholder?: string;\n label?: string;\n onSelect?: (item: string) => void;\n labels?: SearchComboboxLabels;\n /** Enable async search mode */\n async?: boolean;\n /** Async search callback (used when async=true) */\n onSearch?: (query: string) => Promise<string[]>;\n /** Debounce ms for async search */\n debounceMs?: number;\n}\n\n/** Renders the search combobox component. */\nexport function SearchCombobox({\n items,\n placeholder = \"검색...\",\n label = \"검색\",\n onSelect,\n labels: customLabels,\n async: isAsync = false,\n onSearch,\n debounceMs = 300,\n}: SearchComboboxProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const inputId = useId();\n const [query, setQuery] = useState(\"\");\n const [asyncResults, setAsyncResults] = useState<string[]>([]);\n const [loading, setLoading] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n const searchGenerationRef = useRef(0);\n\n const syncMatches = useMemo(() => {\n if (isAsync) return [];\n if (!query) return items;\n return matchSorter(items, query);\n }, [query, items, isAsync]);\n\n const handleInput = (event: FormEvent<HTMLInputElement>) => {\n searchGenerationRef.current += 1;\n setQuery(event.currentTarget.value);\n };\n\n const handleValueChange = (item: string) => {\n searchGenerationRef.current += 1;\n setQuery(item);\n onSelect?.(item);\n };\n\n useEffect(() => {\n const generation = ++searchGenerationRef.current;\n\n if (timerRef.current) clearTimeout(timerRef.current);\n\n if (!isAsync || !onSearch) {\n setLoading(false);\n return;\n }\n\n if (!query) {\n setAsyncResults([]);\n setLoading(false);\n return;\n }\n\n setLoading(true);\n timerRef.current = setTimeout(async () => {\n try {\n const results = await onSearch(query);\n if (searchGenerationRef.current !== generation) {\n return;\n }\n setAsyncResults(results);\n } finally {\n if (searchGenerationRef.current === generation) {\n setLoading(false);\n }\n }\n }, debounceMs);\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, [query, isAsync, onSearch, debounceMs]);\n\n const matches = isAsync ? asyncResults : syncMatches;\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"KH4TQ\"\n data-opt-slug=\"search-combobox.SearchCombobox\"\n >\n <ComboboxRoot onValueChange={handleValueChange}>\n <label htmlFor={inputId} className={OPT_TEXT_LABEL}>\n {label}\n </label>\n <ComboboxInput\n id={inputId}\n placeholder={placeholder}\n className=\"max-w-xs\"\n aria-busy={loading || undefined}\n onInput={handleInput}\n />\n <ComboboxPopover className=\"max-w-xs\">\n {isAsync && loading ? (\n <div\n className=\"text-text-secondary gap-element flex items-center px-3 py-2 text-sm\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size=\"sm\" aria-hidden=\"true\" />\n {labels.loading}\n </div>\n ) : matches.length === 0 ? (\n <ComboboxEmpty>{labels.noResults}</ComboboxEmpty>\n ) : (\n matches.map((item) => (\n <ComboboxItem key={item} value={item}>\n {item}\n </ComboboxItem>\n ))\n )}\n </ComboboxPopover>\n </ComboboxRoot>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { SelectOption } from \"../lib/types\";\nimport {\n SelectRoot,\n SelectLabel,\n SelectTrigger,\n SelectPopover,\n SelectItem,\n} from \"../core/select\";\nimport {\n OPT_TEXT_LABEL,\n OPT_INPUT,\n OPT_FOCUS,\n OPT_SURFACE_POPOVER,\n OPT_ANIMATE_ENTER_EXIT,\n} from \"../lib/styles\";\n\n/** Props for the status select component. */\nexport interface StatusSelectProps {\n options: SelectOption[];\n value?: string;\n onChange?: (value: string) => void;\n label?: string;\n labels?: StatusSelectLabels;\n}\n\n/** Localized labels for the status select component. */\nexport interface StatusSelectLabels {\n selectLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<StatusSelectLabels> = {\n selectLabel: \"상태\",\n emptyMessage: \"사용 가능한 상태 옵션이 없습니다.\",\n};\n\n/** Renders the status select component. */\nexport function StatusSelect({\n options,\n value: controlledValue,\n onChange,\n label,\n labels: customLabels,\n}: StatusSelectProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const resolvedLabel = label ?? labels.selectLabel;\n const [internalValue, setInternalValue] = useState(options[0]?.value ?? \"\");\n const value = controlledValue ?? internalValue;\n const selected = options.find((s) => s.value === value);\n\n if (options.length === 0) {\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"R46E6\"\n data-opt-slug=\"status-select.StatusSelect\"\n >\n <span className={OPT_TEXT_LABEL}>{resolvedLabel}</span>\n <span className=\"text-text-tertiary text-sm\">\n {labels.emptyMessage}\n </span>\n </div>\n );\n }\n\n const handleChange = (v: string | string[]) => {\n const next = Array.isArray(v) ? (v[0] ?? \"\") : v;\n if (onChange) onChange(next);\n else setInternalValue(next);\n };\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"R46E6\"\n data-opt-slug=\"status-select.StatusSelect\"\n >\n <SelectRoot value={value} onValueChange={handleChange}>\n <SelectLabel className={OPT_TEXT_LABEL}>{resolvedLabel}</SelectLabel>\n <SelectTrigger\n className={`${OPT_INPUT} max-w-xs items-center justify-between ${OPT_FOCUS}`}\n >\n <span className=\"gap-element flex items-center\">\n {selected?.color && (\n <span className={`h-2 w-2 rounded-full ${selected.color}`} />\n )}\n {selected?.label}\n </span>\n <svg\n className=\"text-text-tertiary h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </SelectTrigger>\n <SelectPopover\n className={`${OPT_SURFACE_POPOVER} ${OPT_ANIMATE_ENTER_EXIT} max-w-xs`}\n >\n {options.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.color && (\n <span className={`h-2 w-2 rounded-full ${option.color}`} />\n )}\n {option.label}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n </div>\n );\n}\n","\"use client\";\n\nimport type { MenuDef } from \"../lib/types\";\nimport { Kbd } from \"../core/kbd\";\nimport {\n MenubarRoot,\n MenubarContainer,\n MenuRoot,\n MenuTrigger,\n MenuButtonArrow,\n MenuPopover,\n MenuItem,\n MenuItemCheckbox,\n MenuItemRadio,\n MenuSeparator,\n} from \"../core/menu\";\n\n/** Props for the app menubar component. */\nexport interface AppMenubarProps {\n menus: MenuDef[];\n labels?: AppMenubarLabels;\n}\n\n/** Localized labels for the app menubar component. */\nexport interface AppMenubarLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<AppMenubarLabels> = {\n ariaLabel: \"Application menu\",\n};\n\nfunction MenuSection({ menu }: { menu: MenuDef }) {\n return (\n <MenuRoot>\n <MenuTrigger>\n {menu.label}\n <MenuButtonArrow />\n </MenuTrigger>\n <MenuPopover>\n {menu.items.map((item, i) => {\n if (item.type === \"separator\") {\n return <MenuSeparator key={`sep-${i}`} />;\n }\n if (item.type === \"checkbox\") {\n return (\n <MenuItemCheckbox\n key={item.id}\n name={item.name ?? item.id}\n value={item.value ?? item.id}\n checked={item.checked}\n onChange={item.onChange}\n >\n <span className=\"gap-element flex items-center\">\n <span className=\"w-4 text-center\">\n {item.checked ? \"✓\" : \"\"}\n </span>\n {item.label}\n </span>\n </MenuItemCheckbox>\n );\n }\n if (item.type === \"radio\") {\n return (\n <MenuItemRadio\n key={item.id}\n name={item.name ?? \"\"}\n value={item.value ?? \"\"}\n checked={item.checked}\n onChange={item.onChange}\n >\n <span className=\"gap-element flex items-center\">\n <span className=\"w-4 text-center\">\n {item.checked ? \"●\" : \"\"}\n </span>\n {item.label}\n </span>\n </MenuItemRadio>\n );\n }\n return (\n <MenuItem key={item.id} onClick={item.onClick}>\n <span>{item.label}</span>\n {item.shortcut && <Kbd>{item.shortcut}</Kbd>}\n </MenuItem>\n );\n })}\n </MenuPopover>\n </MenuRoot>\n );\n}\n\n/** Renders the app menubar component. */\nexport function AppMenubar({ menus, labels: customLabels }: AppMenubarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n if (menus.length === 0) return null;\n\n return (\n <MenubarRoot data-opt-id=\"BGKHW\" data-opt-slug=\"app-menubar.AppMenubar\">\n <MenubarContainer aria-label={labels.ariaLabel}>\n {menus.map((menu) => (\n <MenuSection key={menu.id} menu={menu} />\n ))}\n </MenubarContainer>\n </MenubarRoot>\n );\n}\n\nAppMenubar.displayName = \"AppMenubar\";\n","\"use client\";\n\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport { useEffect, useState } from \"react\";\nimport type { NavItemDef } from \"../lib/types\";\nimport { cn } from \"../lib/cn\";\n\nconst NAV_ID_PREFIX = \"sidebar-nav-\";\n\nfunction domId(id: string) {\n return `${NAV_ID_PREFIX}${id}`;\n}\n\n// 섹션별 스타일 정의 (한글/영문 모두 지원)\nconst sectionStyles: Record<string, string> = {\n // 한글 키\n 시작하기: \"text-accent\",\n \"핵심 개념\": \"text-info-fg\",\n 구축·운영: \"text-success-fg\",\n 도구: \"text-warning-fg\",\n DataGrid: \"text-accent\",\n \"컴포넌트 · Core\": \"text-accent\",\n \"컴포넌트 · Visuals\": \"text-success-fg\",\n \"컴포넌트 · Shells\": \"text-warning-fg\",\n \"컴포넌트 · Surfaces\": \"text-info-fg\",\n \"기본 컴포넌트\": \"text-accent\",\n \"블록 컴포넌트\": \"text-info-fg\",\n \"조합 컴포넌트\": \"text-warning-fg\",\n 템플릿: \"text-text-tertiary\",\n 릴리즈: \"text-text-tertiary\",\n // 영문 키 (하위 호환)\n Primitives: \"text-accent\",\n Blocks: \"text-info-fg\",\n Compositions: \"text-warning-fg\",\n Templates: \"text-text-tertiary\",\n};\n\nconst defaultSectionStyle = \"text-text-secondary\";\n\n/** Localized labels for the sidebar nav component. */\nexport interface SidebarNavLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<SidebarNavLabels> = {\n ariaLabel: \"문서 네비게이션\",\n};\n\n/** Props for the sidebar nav component. */\nexport interface SidebarNavProps {\n items: NavItemDef[];\n labels?: SidebarNavLabels;\n}\n\n/** Renders the sidebar nav component. */\nexport function SidebarNav({ items, labels: customLabels }: SidebarNavProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const pathname = usePathname();\n const activeItem = items.find((item) => item.href === pathname);\n const [activeId, setActiveId] = useState<string | null | undefined>(\n activeItem ? domId(activeItem.id) : undefined,\n );\n\n useEffect(() => {\n const match = items.find((item) => item.href === pathname);\n if (match) {\n setActiveId(domId(match.id));\n }\n }, [pathname, items]);\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <CompositeProvider\n focusLoop\n orientation=\"vertical\"\n activeId={activeId}\n onActiveIdChange={setActiveId}\n data-opt-id=\"1FZNH\"\n data-opt-slug=\"sidebar-nav.SidebarNav\"\n >\n <Composite\n role=\"navigation\"\n aria-label={labels.ariaLabel}\n className=\"flex flex-col\"\n >\n {items.map((item, index) => {\n const isSelected = pathname === item.href;\n const isFirstItem = index === 0;\n const sectionTextStyle = item.sectionLabel\n ? (sectionStyles[item.sectionLabel] ?? defaultSectionStyle)\n : defaultSectionStyle;\n\n return (\n <div key={item.id}>\n {/* Section Header */}\n {item.separator && (\n <div className={cn(\"mb-2 pt-2\", !isFirstItem && \"mt-7\")}>\n <span\n className={cn(\n \"px-2 text-[11px] font-semibold tracking-wider uppercase\",\n sectionTextStyle,\n )}\n >\n {item.sectionLabel ?? \"\"}\n </span>\n </div>\n )}\n\n {/* Nav Item */}\n <CompositeItem\n id={domId(item.id)}\n render={\n <Link\n href={item.href}\n className={cn(\n // Base styles\n \"group relative block rounded-md px-2 py-1.5 text-[13px] leading-snug outline-none\",\n \"transition-all duration-150\",\n\n // Default state\n !isSelected && [\n \"text-text-secondary\",\n // Hover\n \"hover:bg-bg-subtle hover:text-text-primary\",\n ],\n\n // Selected (current page)\n isSelected && [\n \"bg-bg-subtle text-text-primary font-medium\",\n ],\n\n // Keyboard navigation focus (roving tabindex active)\n \"data-[active-item]:bg-accent-subtle data-[active-item]:text-accent\",\n\n // Focus visible (actual keyboard focus indicator)\n \"data-[focus-visible]:ring-ring data-[focus-visible]:ring-2\",\n \"data-[focus-visible]:ring-offset-ring-offset data-[focus-visible]:ring-offset-2\",\n\n // Combined: selected + keyboard active\n isSelected && [\n \"data-[active-item]:bg-accent-subtle data-[active-item]:text-accent\",\n ],\n )}\n />\n }\n >\n {/* Left indicator bar */}\n <span\n className={cn(\n \"absolute top-1/2 left-0 h-4 w-0.5 -translate-y-1/2 rounded-full transition-all duration-150\",\n // Selected: solid accent bar\n isSelected && \"bg-accent\",\n // Keyboard active (not selected): lighter bar\n !isSelected &&\n \"group-data-[active-item]:bg-accent bg-transparent\",\n // Focus visible: ensure bar is visible\n \"group-data-[focus-visible]:bg-accent\",\n )}\n />\n <span className=\"pl-2\">{item.label}</span>\n </CompositeItem>\n </div>\n );\n })}\n </Composite>\n </CompositeProvider>\n );\n}\n","\"use client\";\n\nimport type { ToolbarButtonDef } from \"../lib/types\";\nimport {\n ToolbarRoot,\n ToolbarContainer,\n ToolbarButton,\n ToolbarSeparator,\n TooltipProvider,\n TooltipAnchor,\n Tooltip,\n} from \"../core/toolbar\";\n\n/** Localized labels for the editor toolbar component. */\nexport interface EditorToolbarLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<EditorToolbarLabels> = {\n ariaLabel: \"텍스트 편집기 툴바\",\n};\n\n/** Props for the editor toolbar component. */\nexport interface EditorToolbarProps {\n buttons: ToolbarButtonDef[];\n onAction?: (id: string) => void;\n activeButtons?: string[];\n labels?: EditorToolbarLabels;\n}\n\nfunction ToolbarButtonWithTooltip({\n button,\n active,\n onAction,\n}: {\n button: ToolbarButtonDef;\n active: boolean;\n onAction?: (id: string) => void;\n}) {\n return (\n <TooltipProvider>\n <TooltipAnchor>\n <ToolbarButton\n className={`text-text-primary data-[active-item]:bg-bg-subtle data-[focus-visible]:ring-ring rounded-md p-2 transition-colors outline-none data-[focus-visible]:ring-2 ${\n active ? \"bg-bg-muted\" : \"hover:bg-bg-subtle\"\n }`}\n onClick={() => onAction?.(button.id)}\n >\n {button.icon}\n </ToolbarButton>\n </TooltipAnchor>\n <Tooltip>{button.label}</Tooltip>\n </TooltipProvider>\n );\n}\n\n/** Renders the editor toolbar component. */\nexport function EditorToolbar({\n buttons,\n onAction,\n activeButtons = [],\n labels: customLabels,\n}: EditorToolbarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n const groups: (ToolbarButtonDef | \"separator\")[][] = [];\n let current: (ToolbarButtonDef | \"separator\")[] = [];\n for (const btn of buttons) {\n if (btn.separator) {\n groups.push(current);\n current = [];\n }\n current.push(btn);\n }\n if (current.length) groups.push(current);\n\n return (\n <ToolbarRoot\n data-opt-id=\"Z73K6\"\n data-opt-slug=\"editor-toolbar.EditorToolbar\"\n >\n <ToolbarContainer aria-label={labels.ariaLabel}>\n {groups.map((group, gi) => (\n <span key={gi} className=\"contents\">\n {gi > 0 && <ToolbarSeparator />}\n {group.map((item) => {\n if (item === \"separator\") return null;\n const btn = item as ToolbarButtonDef;\n return (\n <ToolbarButtonWithTooltip\n key={btn.id}\n button={btn}\n active={activeButtons.includes(btn.id)}\n onAction={onAction}\n />\n );\n })}\n </span>\n ))}\n </ToolbarContainer>\n </ToolbarRoot>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { TabDef } from \"../lib/types\";\nimport { TabsRoot, TabList, Tab, TabPanel } from \"../core/tabs\";\n\n/** Localized labels for the content tabs component. */\nexport interface ContentTabsLabels {\n ariaLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<ContentTabsLabels> = {\n ariaLabel: \"콘텐츠 탭\",\n emptyMessage: \"표시할 탭이 없습니다.\",\n};\n\n/** Props for the content tabs component. */\nexport interface ContentTabsProps {\n tabs: TabDef[];\n defaultTabId?: string;\n labels?: ContentTabsLabels;\n}\n\n/** Renders the content tabs component. */\nexport function ContentTabs({\n tabs,\n defaultTabId,\n labels: customLabels,\n}: ContentTabsProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [selectedTabId, setSelectedTabId] = useState(\n defaultTabId ?? tabs[0]?.id,\n );\n\n if (tabs.length === 0) {\n return (\n <div\n className=\"text-text-secondary text-sm\"\n data-opt-id=\"9W97K\"\n data-opt-slug=\"content-tabs.ContentTabs\"\n >\n {labels.emptyMessage}\n </div>\n );\n }\n\n const handleSelectedTabId = (nextId: string | null | undefined) => {\n setSelectedTabId(nextId ?? tabs[0]?.id);\n };\n const activeTab = tabs.find((tab) => tab.id === selectedTabId) ?? tabs[0];\n\n return (\n <TabsRoot\n selectedId={selectedTabId}\n onSelectedIdChange={handleSelectedTabId}\n data-opt-id=\"9W97K\"\n data-opt-slug=\"content-tabs.ContentTabs\"\n >\n <TabList aria-label={labels.ariaLabel}>\n {tabs.map((tab) => (\n <Tab key={tab.id} id={tab.id}>\n {tab.label}\n </Tab>\n ))}\n </TabList>\n {activeTab && (\n <TabPanel tabId={activeTab.id}>{activeTab.content}</TabPanel>\n )}\n </TabsRoot>\n );\n}\n","import {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport type { FaqItem } from \"../lib/types\";\nimport {\n DisclosureRoot,\n DisclosureTrigger,\n DisclosureContent,\n} from \"../core/disclosure\";\n\n/** Localized labels for the faq accordion component. */\nexport interface FaqAccordionLabels {\n ariaLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<FaqAccordionLabels> = {\n ariaLabel: \"자주 묻는 질문\",\n emptyMessage: \"등록된 FAQ가 없습니다.\",\n};\n\n/** Props for the faq accordion component. */\nexport interface FaqAccordionProps {\n items: FaqItem[];\n labels?: FaqAccordionLabels;\n}\n\n/** Renders the faq accordion component. */\nexport function FaqAccordion({\n items,\n labels: customLabels,\n}: FaqAccordionProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n if (items.length === 0) {\n return (\n <div\n className=\"text-text-secondary text-sm\"\n data-opt-id=\"QRBHV\"\n data-opt-slug=\"faq-accordion.FaqAccordion\"\n >\n {labels.emptyMessage}\n </div>\n );\n }\n\n return (\n <CompositeProvider\n focusLoop\n orientation=\"vertical\"\n data-opt-id=\"QRBHV\"\n data-opt-slug=\"faq-accordion.FaqAccordion\"\n >\n <Composite\n role=\"region\"\n aria-label={labels.ariaLabel}\n className=\"divide-border-subtle border-border divide-y rounded-lg border\"\n >\n {items.map((faq) => (\n <DisclosureRoot key={faq.id}>\n <div>\n <CompositeItem render={<DisclosureTrigger />}>\n {faq.question}\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0 transition-transform [[data-open]>&]:rotate-180\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </CompositeItem>\n <DisclosureContent>\n <p className=\"text-text-secondary px-4 pt-2 pb-4 text-sm\">\n {faq.answer}\n </p>\n </DisclosureContent>\n </div>\n </DisclosureRoot>\n ))}\n </Composite>\n </CompositeProvider>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { FormFieldDef } from \"../lib/types\";\nimport {\n FormRoot,\n FormInput,\n FormTextarea,\n FormSelect,\n FormSelectPopover,\n FormSelectItem,\n FormSwitch,\n FormLabel,\n FormError,\n FormSubmit,\n FormCheckbox,\n FormRadioGroup,\n FormRadio,\n useFormStore,\n} from \"../core/form\";\nimport { EmptyState } from \"../core/empty-state\";\nimport { TagInput } from \"../core/tag-input\";\n\n/** Localized labels for the settings form component. */\nexport interface SettingsFormLabels {\n formAriaLabel?: string;\n submitButton?: string;\n successMessage?: string;\n}\n\nconst defaultLabels: Required<SettingsFormLabels> = {\n formAriaLabel: \"설정 폼\",\n submitButton: \"저장\",\n successMessage: \"설정이 저장되었습니다.\",\n};\n\n/** Props for the settings form component. */\nexport interface SettingsFormProps {\n fields: FormFieldDef[];\n onSubmit?: (values: Record<string, unknown>) => void;\n labels?: SettingsFormLabels;\n}\n\n/** Renders the settings form component. */\nexport function SettingsForm({\n fields,\n onSubmit,\n labels: customLabels,\n}: SettingsFormProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [submitted, setSubmitted] = useState(false);\n\n const defaultValues: Record<string, unknown> = {};\n for (const field of fields) {\n defaultValues[field.name] =\n field.defaultValue ??\n (field.type === \"switch\" || field.type === \"checkbox\"\n ? false\n : field.type === \"tags\"\n ? []\n : \"\");\n }\n\n const form = useFormStore({\n defaultValues,\n validate: (values) => {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (field.required) {\n const value = values[field.name];\n if (!value || (typeof value === \"string\" && !value.trim())) {\n errors[field.name] =\n field.requiredMessage ?? `${field.label}을(를) 입력해주세요.`;\n }\n }\n if (field.validate) {\n const value = values[field.name];\n const error = field.validate(value);\n if (error) {\n errors[field.name] = error;\n }\n }\n }\n return errors;\n },\n onSubmit: (values) => {\n setSubmitted(true);\n onSubmit?.(values);\n },\n });\n\n if (fields.length === 0) {\n return (\n <EmptyState\n title=\"설정 항목이 없습니다.\"\n description=\"표시할 설정 필드를 추가하면 이 폼이 렌더링됩니다.\"\n data-opt-id=\"9TEEJ\"\n data-opt-slug=\"settings-form.SettingsForm\"\n />\n );\n }\n\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"9TEEJ\"\n data-opt-slug=\"settings-form.SettingsForm\"\n >\n <FormRoot store={form} aria-label={labels.formAriaLabel}>\n {fields.map((field) => {\n if (field.visible !== undefined) {\n const currentValues = form.getValues();\n const isVisible =\n typeof field.visible === \"function\"\n ? field.visible(currentValues)\n : field.visible;\n if (!isVisible) return null;\n }\n\n if (field.type === \"tags\") {\n const rawValue = form.getValue(field.name) as string[] | undefined;\n const tags = Array.isArray(rawValue) ? rawValue : [];\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <TagInput\n value={tags}\n onChange={(next) => form.setValue(field.name, next)}\n placeholder={field.placeholder}\n />\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"radio\") {\n return (\n <fieldset key={field.name} className=\"gap-element flex flex-col\">\n <legend className=\"text-text-primary text-sm font-medium\">\n {field.label}\n </legend>\n <FormRadioGroup>\n <div className=\"gap-group flex\">\n {field.options?.map((option) => (\n <label\n key={option.value}\n className=\"text-text-primary gap-element flex items-center text-sm\"\n >\n <FormRadio name={field.name} value={option.value} />\n {option.label}\n </label>\n ))}\n </div>\n </FormRadioGroup>\n <FormError name={field.name} />\n </fieldset>\n );\n }\n\n if (field.type === \"checkbox\") {\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <label className=\"text-text-primary gap-element flex items-center text-sm\">\n <FormCheckbox name={field.name} />\n <span>{field.label}</span>\n </label>\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"textarea\") {\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <FormTextarea\n name={field.name}\n placeholder={field.placeholder}\n rows={field.rows ?? 4}\n resize={field.resize ?? \"vertical\"}\n className={\n field.font === \"mono\" ? \"font-mono text-sm\" : undefined\n }\n />\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"select\") {\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <FormSelect name={field.name} placeholder={field.placeholder}>\n <FormSelectPopover>\n {field.options?.map((option) => (\n <FormSelectItem key={option.value} value={option.value}>\n {option.label}\n </FormSelectItem>\n ))}\n </FormSelectPopover>\n </FormSelect>\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"switch\") {\n return (\n <label key={field.name} className=\"gap-group flex items-center\">\n <FormSwitch name={field.name} />\n <div className=\"flex flex-col\">\n <span className=\"text-text-primary text-sm font-medium\">\n {field.label}\n </span>\n {field.description && (\n <span className=\"text-text-secondary text-sm\">\n {field.description}\n </span>\n )}\n </div>\n </label>\n );\n }\n\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <FormInput\n name={field.name}\n type={field.type ?? \"text\"}\n placeholder={field.placeholder}\n />\n <FormError name={field.name} />\n </div>\n );\n })}\n\n <FormSubmit>{labels.submitButton}</FormSubmit>\n </FormRoot>\n\n {submitted && (\n <div className=\"border-success bg-success-subtle text-success-fg rounded-lg border p-3 text-sm\">\n {labels.successMessage}\n </div>\n )}\n </div>\n );\n}\n","import {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport type { DeploymentStep } from \"../lib/types\";\nimport {\n OPT_FOCUS,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_TEXT_TERTIARY,\n OPT_BADGE_GREEN,\n OPT_BADGE_RED,\n OPT_BADGE_NEUTRAL,\n} from \"../lib/styles\";\n\n/** Localized labels for the deployment timeline component. */\nexport type DeploymentTimelineLabels = Record<never, never>;\n\n/** Props for the deployment timeline component. */\nexport interface DeploymentTimelineProps {\n steps: DeploymentStep[];\n title?: string;\n}\n\nconst statusIcon: Record<DeploymentStep[\"status\"], string> = {\n success: \"●\",\n pending: \"◌\",\n running: \"⟳\",\n error: \"✗\",\n skipped: \"○\",\n};\n\nconst statusColor: Record<DeploymentStep[\"status\"], string> = {\n success: \"text-success-fg\",\n pending: OPT_TEXT_TERTIARY,\n running: \"text-accent\",\n error: \"text-danger-fg\",\n skipped: \"text-text-tertiary\",\n};\n\nconst statusBadge: Record<DeploymentStep[\"status\"], string> = {\n success: OPT_BADGE_GREEN,\n pending: OPT_BADGE_NEUTRAL,\n running:\n \"inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium bg-info-subtle text-info-fg\",\n error: OPT_BADGE_RED,\n skipped: OPT_BADGE_NEUTRAL,\n};\n\nconst statusLabel: Record<DeploymentStep[\"status\"], string> = {\n success: \"성공\",\n pending: \"대기\",\n running: \"실행 중\",\n error: \"에러\",\n skipped: \"건너뜀\",\n};\n\n/** Renders the deployment timeline component. */\nexport function DeploymentTimeline({\n steps,\n title = \"배포 타임라인\",\n}: DeploymentTimelineProps) {\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"XXVQ2\"\n data-opt-slug=\"deployment-timeline.DeploymentTimeline\"\n >\n {title && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>{title}</h3>\n )}\n <CompositeProvider focusLoop orientation=\"vertical\">\n <Composite role=\"list\" aria-label={title} className=\"relative\">\n {steps.map((step, i) => {\n const isLast = i === steps.length - 1;\n return (\n <CompositeItem\n key={step.id}\n className={`group gap-group relative flex w-full scroll-m-2 rounded-lg px-3 py-2 ${OPT_FOCUS} data-[active-item]:bg-accent-subtle`}\n role=\"listitem\"\n >\n {/* 연결선 + 아이콘 */}\n <div className=\"flex flex-col items-center\">\n <span\n className={`text-lg leading-none ${statusColor[step.status]}`}\n aria-label={statusLabel[step.status]}\n >\n {statusIcon[step.status]}\n </span>\n {!isLast && (\n <div className=\"bg-border-subtle mt-1 w-px flex-1\" />\n )}\n </div>\n\n {/* 내용 */}\n <div className=\"flex-1 pb-3\">\n <div className=\"gap-element flex items-center\">\n <span className={`text-sm font-medium ${OPT_TEXT_PRIMARY}`}>\n {step.name}\n </span>\n <span className={statusBadge[step.status]}>\n {statusLabel[step.status]}\n </span>\n {step.duration && (\n <span className={`text-xs ${OPT_TEXT_TERTIARY}`}>\n {step.duration}\n </span>\n )}\n </div>\n {step.detail && (\n <p className={`mt-0.5 text-xs ${OPT_TEXT_SECONDARY}`}>\n {step.detail}\n </p>\n )}\n </div>\n </CompositeItem>\n );\n })}\n </Composite>\n </CompositeProvider>\n </div>\n );\n}\n","\"use client\";\n\nimport { matchSorter } from \"match-sorter\";\nimport { useMemo, useState } from \"react\";\nimport type { ProjectDef } from \"../lib/types\";\nimport {\n ComboboxRoot,\n ComboboxInput,\n ComboboxPopover,\n ComboboxItem,\n} from \"../core/combobox\";\nimport {\n OPT_INPUT,\n OPT_ITEM_BASE,\n OPT_ACTIVE_ITEM,\n OPT_TEXT_LABEL,\n OPT_TEXT_SECONDARY,\n OPT_BADGE_NEUTRAL,\n OPT_DOT_GREEN,\n OPT_DOT_YELLOW,\n OPT_DOT_RED,\n} from \"../lib/styles\";\n\n/** Localized labels for the project switcher component. */\nexport type ProjectSwitcherLabels = Record<never, never>;\n\n/** Props for the project switcher component. */\nexport interface ProjectSwitcherProps {\n projects: ProjectDef[];\n value?: string;\n onChange?: (id: string) => void;\n placeholder?: string;\n}\n\nconst statusDot: Record<ProjectDef[\"status\"], string> = {\n active: OPT_DOT_GREEN,\n paused: OPT_DOT_YELLOW,\n error: OPT_DOT_RED,\n};\n\n/** Renders the project switcher component. */\nexport function ProjectSwitcher({\n projects,\n value,\n onChange,\n placeholder = \"프로젝트 검색...\",\n}: ProjectSwitcherProps) {\n const [search, setSearch] = useState(\"\");\n\n const matches = useMemo(() => {\n if (!search) return projects;\n return matchSorter(projects, search, { keys: [\"name\", \"framework\"] });\n }, [search, projects]);\n\n const selected = projects.find((p) => p.id === value);\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"5R3AG\"\n data-opt-slug=\"project-switcher.ProjectSwitcher\"\n >\n <ComboboxRoot onValueChange={setSearch}>\n <label className={OPT_TEXT_LABEL}>프로젝트</label>\n <ComboboxInput\n placeholder={selected ? selected.name : placeholder}\n className={OPT_INPUT}\n />\n <ComboboxPopover className=\"max-h-72 overflow-y-auto\">\n {matches.length === 0 && (\n <p className={`py-6 text-center text-sm ${OPT_TEXT_SECONDARY}`}>\n 결과가 없습니다.\n </p>\n )}\n {matches.map((project) => (\n <ComboboxItem\n key={project.id}\n value={project.name}\n onClick={() => onChange?.(project.id)}\n className={`gap-element flex scroll-m-2 items-center ${OPT_ITEM_BASE} ${OPT_ACTIVE_ITEM}`}\n >\n <span className={`shrink-0 ${statusDot[project.status]}`} />\n <span className=\"flex-1 truncate font-medium\">\n {project.name}\n </span>\n <span className={OPT_BADGE_NEUTRAL}>{project.framework}</span>\n {project.domain && (\n <span\n className={`truncate text-xs ${OPT_TEXT_SECONDARY} data-[active-item]:text-accent-fg/70`}\n >\n {project.domain}\n </span>\n )}\n </ComboboxItem>\n ))}\n </ComboboxPopover>\n </ComboboxRoot>\n </div>\n );\n}\n\nProjectSwitcher.displayName = \"ProjectSwitcher\";\n","\"use client\";\n\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport {\n DisclosureRoot as DisclosureProvider,\n DisclosureTrigger as Disclosure,\n DisclosureContent,\n} from \"../core/disclosure\";\nimport type { EnvGroupDef } from \"../lib/types\";\nimport {\n OPT_BORDER,\n OPT_DIVIDER,\n OPT_DISCLOSURE_TRIGGER,\n OPT_DISCLOSURE_CONTENT,\n OPT_FOCUS,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_TEXT_TERTIARY,\n OPT_BADGE_NEUTRAL,\n OPT_DOT_RED,\n OPT_DOT_YELLOW,\n OPT_DOT_GREEN,\n} from \"../lib/styles\";\n\n/** Localized labels for the env panel component. */\nexport interface EnvPanelLabels {\n varCount?: (count: number) => string;\n envVarsLabel?: (env: string) => string;\n secretBadge?: string;\n}\n\nconst defaultLabels: Required<EnvPanelLabels> = {\n varCount: (count: number) => `${count}개 변수`,\n envVarsLabel: (env: string) => `${env} 환경 변수`,\n secretBadge: \"secret\",\n};\n\n/** Props for the env panel component. */\nexport interface EnvPanelProps {\n groups: EnvGroupDef[];\n labels?: EnvPanelLabels;\n}\n\nconst envDot: Record<string, string> = {\n Production: OPT_DOT_RED,\n Preview: OPT_DOT_YELLOW,\n Development: OPT_DOT_GREEN,\n};\n\n/** Renders the env panel component. */\nexport function EnvPanel({ groups, labels: customLabels }: EnvPanelProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n return (\n <div\n className={`rounded-lg ${OPT_BORDER} divide-y ${OPT_DIVIDER} bg-surface`}\n data-opt-id=\"ZBDWK\"\n data-opt-slug=\"env-panel.EnvPanel\"\n >\n {groups.map((group) => (\n <DisclosureProvider\n key={group.env}\n defaultOpen={group.env === \"Production\"}\n >\n <div>\n <Disclosure className={OPT_DISCLOSURE_TRIGGER}>\n <span className=\"gap-element flex items-center\">\n <span\n className={\n envDot[group.env] ?? \"bg-bg-muted h-2 w-2 rounded-full\"\n }\n />\n <span className=\"font-medium\">{group.env}</span>\n <span className={`text-xs ${OPT_TEXT_TERTIARY}`}>\n {labels.varCount(group.vars.length)}\n </span>\n </span>\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0 transition-transform [[data-open]>&]:rotate-180\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </Disclosure>\n <DisclosureContent className={OPT_DISCLOSURE_CONTENT}>\n <CompositeProvider focusLoop orientation=\"vertical\">\n <Composite\n role=\"list\"\n aria-label={labels.envVarsLabel(group.env)}\n className=\"px-4 pb-3\"\n >\n {group.vars.map((v) => (\n <CompositeItem\n key={v.key}\n role=\"listitem\"\n className={`gap-group flex scroll-m-2 items-center rounded px-2 py-1.5 text-sm ${OPT_FOCUS} data-[active-item]:bg-accent-subtle`}\n >\n <span\n className={`w-44 shrink-0 truncate font-mono text-xs font-medium ${OPT_TEXT_PRIMARY}`}\n >\n {v.key}\n </span>\n <span\n className={`flex-1 truncate font-mono text-xs ${OPT_TEXT_SECONDARY}`}\n >\n {v.isSecret ? \"••••••••\" : v.value}\n </span>\n {v.isSecret && (\n <span className={OPT_BADGE_NEUTRAL}>\n {labels.secretBadge}\n </span>\n )}\n </CompositeItem>\n ))}\n </Composite>\n </CompositeProvider>\n </DisclosureContent>\n </div>\n </DisclosureProvider>\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { BranchDef } from \"../lib/types\";\nimport {\n SelectRoot,\n SelectLabel,\n SelectTrigger,\n SelectPopover,\n SelectItem,\n} from \"../core/select\";\nimport {\n OPT_INPUT,\n OPT_ITEM_BASE,\n OPT_ACTIVE_ITEM,\n OPT_TEXT_LABEL,\n OPT_TEXT_TERTIARY,\n OPT_BADGE_BLUE,\n} from \"../lib/styles\";\n\n/** Localized labels for the branch select component. */\nexport interface BranchSelectLabels {\n selectLabel?: string;\n emptySelectionLabel?: string;\n emptyMessage?: string;\n defaultBadge?: string;\n}\n\nconst defaultLabels: Required<BranchSelectLabels> = {\n selectLabel: \"브랜치\",\n emptySelectionLabel: \"선택...\",\n emptyMessage: \"사용 가능한 브랜치가 없습니다.\",\n defaultBadge: \"default\",\n};\n\n/** Props for the branch select component. */\nexport interface BranchSelectProps {\n branches: BranchDef[];\n value?: string;\n onChange?: (name: string) => void;\n label?: string;\n labels?: BranchSelectLabels;\n}\n\n/** Renders the branch select component. */\nexport function BranchSelect({\n branches,\n value: controlledValue,\n onChange,\n label,\n labels: customLabels,\n}: BranchSelectProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const resolvedLabel = label ?? labels.selectLabel;\n const defaultBranch = branches.find((b) => b.isDefault);\n const [internalValue, setInternalValue] = useState(\n defaultBranch?.name ?? branches[0]?.name ?? \"\",\n );\n const value = controlledValue ?? internalValue;\n const selected = branches.find((b) => b.name === value);\n\n if (branches.length === 0) {\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"7EDEP\"\n data-opt-slug=\"branch-select.BranchSelect\"\n >\n <span className={OPT_TEXT_LABEL}>{resolvedLabel}</span>\n <span className={OPT_TEXT_TERTIARY}>{labels.emptyMessage}</span>\n </div>\n );\n }\n\n const handleChange = (v: string | string[]) => {\n const next = Array.isArray(v) ? (v[0] ?? \"\") : v;\n if (onChange) onChange(next);\n else setInternalValue(next);\n };\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"7EDEP\"\n data-opt-slug=\"branch-select.BranchSelect\"\n >\n <SelectRoot value={value} onValueChange={handleChange}>\n <SelectLabel className={OPT_TEXT_LABEL}>{resolvedLabel}</SelectLabel>\n <SelectTrigger\n className={`${OPT_INPUT} max-w-xs items-center justify-between gap-1`}\n >\n <span className=\"gap-element flex items-center truncate\">\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244\"\n />\n </svg>\n <span className=\"truncate\">\n {selected?.name ?? labels.emptySelectionLabel}\n </span>\n {selected?.isDefault && (\n <span className={OPT_BADGE_BLUE}>{labels.defaultBadge}</span>\n )}\n </span>\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </SelectTrigger>\n <SelectPopover className=\"max-w-xs\">\n {branches.map((branch) => (\n <SelectItem\n key={branch.name}\n value={branch.name}\n className={`gap-element flex scroll-m-2 items-center ${OPT_ITEM_BASE} ${OPT_ACTIVE_ITEM}`}\n >\n <span className=\"flex-1 truncate\">{branch.name}</span>\n {branch.isDefault && (\n <span className=\"bg-accent-subtle text-accent data-[active-item]:bg-accent-fg/20 data-[active-item]:text-accent-fg rounded-full px-2 py-0.5 text-[11px] font-medium\">\n {labels.defaultBadge}\n </span>\n )}\n {branch.lastCommit && (\n <span\n className={`font-mono text-xs ${OPT_TEXT_TERTIARY} data-[active-item]:text-accent-fg/60`}\n >\n {branch.lastCommit}\n </span>\n )}\n {branch.author && (\n <span\n className={`text-xs ${OPT_TEXT_TERTIARY} data-[active-item]:text-accent-fg/60`}\n >\n {branch.author}\n </span>\n )}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n </div>\n );\n}\n\nBranchSelect.displayName = \"BranchSelect\";\n","import {\n Composite,\n CompositeItem,\n CompositeProvider,\n CompositeRow,\n} from \"../core/composite-zone\";\nimport type { DomainDef } from \"../lib/types\";\nimport {\n OPT_BORDER,\n OPT_DIVIDER,\n OPT_TH,\n OPT_TD,\n OPT_TD_MUTED,\n OPT_TABLE_ROW_ACTIVE,\n OPT_BADGE_GREEN,\n OPT_BADGE_YELLOW,\n OPT_BADGE_RED,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n} from \"../lib/styles\";\n\n/** Localized labels for the domain table component. */\nexport interface DomainTableLabels {\n domain?: string;\n status?: string;\n ssl?: string;\n redirect?: string;\n added?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<DomainTableLabels> = {\n domain: \"Domain\",\n status: \"Status\",\n ssl: \"SSL\",\n redirect: \"Redirect\",\n added: \"Added\",\n emptyMessage: \"No domains configured\",\n};\n\n/** Props for the domain table component. */\nexport interface DomainTableProps {\n domains: DomainDef[];\n title?: string;\n labels?: DomainTableLabels;\n}\n\nconst statusBadge: Record<DomainDef[\"status\"], string> = {\n active: OPT_BADGE_GREEN,\n pending: OPT_BADGE_YELLOW,\n error: OPT_BADGE_RED,\n};\n\nconst sslBadge: Record<DomainDef[\"ssl\"], string> = {\n valid: OPT_BADGE_GREEN,\n pending: OPT_BADGE_YELLOW,\n expired: OPT_BADGE_RED,\n};\n\nconst statusLabel: Record<DomainDef[\"status\"], string> = {\n active: \"Active\",\n pending: \"Pending\",\n error: \"Error\",\n};\n\nconst sslLabel: Record<DomainDef[\"ssl\"], string> = {\n valid: \"Valid\",\n pending: \"Pending\",\n expired: \"Expired\",\n};\n\n/** Renders the domain table component. */\nexport function DomainTable({\n domains,\n title = \"도메인\",\n labels: customLabels,\n}: DomainTableProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n if (domains.length === 0) {\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"A7SRM\"\n data-opt-slug=\"domain-table.DomainTable\"\n >\n {title && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>\n {title}\n </h3>\n )}\n <div\n className={`rounded-lg px-4 py-6 text-sm ${OPT_BORDER} ${OPT_TEXT_SECONDARY} bg-surface`}\n >\n {labels.emptyMessage}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"A7SRM\"\n data-opt-slug=\"domain-table.DomainTable\"\n >\n {title && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>{title}</h3>\n )}\n <div className={`overflow-x-auto rounded-lg ${OPT_BORDER} bg-surface`}>\n <CompositeProvider focusLoop focusWrap>\n <Composite\n role=\"grid\"\n aria-label={title}\n className=\"w-full\"\n render={<table />}\n >\n <thead className=\"border-border-subtle bg-surface-inset border-b\">\n <tr>\n <th className={OPT_TH}>{labels.domain}</th>\n <th className={OPT_TH}>{labels.status}</th>\n <th className={OPT_TH}>{labels.ssl}</th>\n <th className={OPT_TH}>{labels.redirect}</th>\n <th className={OPT_TH}>{labels.added}</th>\n </tr>\n </thead>\n <tbody className={`divide-y ${OPT_DIVIDER}`}>\n {domains.map((d) => (\n <CompositeRow key={d.domain} render={<tr />}>\n <CompositeItem\n render={\n <td\n className={`${OPT_TD} font-mono font-medium`}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n >\n {d.domain}\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <span className={statusBadge[d.status]}>\n {statusLabel[d.status]}\n </span>\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <span className={sslBadge[d.ssl]}>{sslLabel[d.ssl]}</span>\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n {d.redirect ?? \"—\"}\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD_MUTED} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n {d.addedAt ?? \"—\"}\n </CompositeItem>\n </CompositeRow>\n ))}\n </tbody>\n </Composite>\n </CompositeProvider>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n useState,\n useMemo,\n useCallback,\n Fragment,\n type ReactNode,\n} from \"react\";\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n CompositeRow,\n} from \"../core/composite-zone\";\nimport {\n OPT_BORDER,\n OPT_DIVIDER,\n OPT_TH,\n OPT_TD,\n OPT_TABLE_ROW_ACTIVE,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_FOCUS_VISIBLE,\n} from \"../lib/styles\";\nimport { cn } from \"../lib/cn\";\nimport { Checkbox } from \"../core/checkbox\";\nimport { Pagination } from \"../core/pagination\";\n\n/**\n * Column definition for DataTable.\n * `accessor` can be a property key for simple lookups or a render function\n * for computed/complex cells.\n */\nexport interface ColumnDef<T> {\n id: string;\n header: string;\n accessor: keyof T | ((row: T) => ReactNode);\n width?: string;\n align?: \"left\" | \"center\" | \"right\";\n sortable?: boolean;\n /** Show an inline progress bar in the cell. Return a 0-1 ratio. */\n bar?: (row: T) => number;\n /** Bar color class (default: \"bg-accent\") */\n barColor?: string;\n}\n\n/** Localized labels for the data table component. */\nexport type DataTableLabels = Record<never, never>;\n\n/** Props for the data table component. */\nexport interface DataTableProps<T> {\n data: T[];\n columns: ColumnDef<T>[];\n keyExtractor: (row: T) => string;\n title?: string;\n onRowClick?: (row: T) => void;\n emptyMessage?: string;\n /** Highlight a single row by its key */\n activeRowId?: string;\n /** Enable column sorting */\n sortable?: boolean;\n /** Enable row selection with checkboxes */\n selectable?: boolean;\n selectedKeys?: string[];\n onSelectionChange?: (keys: string[]) => void;\n /** Enable expandable rows */\n expandable?: boolean;\n renderExpanded?: (row: T) => ReactNode;\n /** Enable pagination */\n pageSize?: number;\n /** Sticky table header */\n stickyHeader?: boolean;\n /** Enable column resizing via drag handle */\n resizableColumns?: boolean;\n /** External (server-side) sort callback */\n onSort?: (columnId: string, direction: \"asc\" | \"desc\" | null) => void;\n className?: string;\n}\n\ntype SortDir = \"asc\" | \"desc\" | null;\n\nconst MIN_COLUMN_WIDTH = 40;\nconst DEFAULT_COLUMN_RESIZE_MAX = 1200;\n\nconst alignmentClass: Record<\n NonNullable<ColumnDef<unknown>[\"align\"]>,\n string\n> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n};\n\nfunction getCellValue<T>(\n row: T,\n accessor: ColumnDef<T>[\"accessor\"],\n): ReactNode {\n if (typeof accessor === \"function\") {\n try {\n return accessor(row);\n } catch {\n return \"—\";\n }\n }\n const value = row[accessor];\n if (\n value === null ||\n value === undefined ||\n (typeof value === \"number\" && !Number.isFinite(value))\n ) {\n return \"—\";\n }\n return String(value);\n}\n\nfunction getRawValue<T>(row: T, accessor: ColumnDef<T>[\"accessor\"]): unknown {\n if (typeof accessor === \"function\") {\n return accessor(row);\n }\n return row[accessor];\n}\n\nfunction isMissingSortValue(value: unknown): boolean {\n return (\n value == null || (typeof value === \"number\" && !Number.isFinite(value))\n );\n}\n\nfunction compareSortValues(aVal: unknown, bVal: unknown, dir: SortDir): number {\n const aMissing = isMissingSortValue(aVal);\n const bMissing = isMissingSortValue(bVal);\n\n if (aMissing && bMissing) return 0;\n if (aMissing) return 1;\n if (bMissing) return -1;\n\n const cmp =\n typeof aVal === \"number\" && typeof bVal === \"number\"\n ? aVal - bVal\n : String(aVal).localeCompare(String(bVal));\n\n return dir === \"desc\" ? -cmp : cmp;\n}\n\nfunction clampPercent(ratio: number): number {\n if (!Number.isFinite(ratio)) return 0;\n return Math.min(100, Math.max(0, Math.round(ratio * 100)));\n}\n\nfunction getResizeHandleValue(\n currentWidth: number | undefined,\n configuredWidth: string | undefined,\n): number {\n if (typeof currentWidth === \"number\" && Number.isFinite(currentWidth)) {\n return Math.max(MIN_COLUMN_WIDTH, Math.round(currentWidth));\n }\n\n const pxWidth = configuredWidth?.trim().match(/^(\\d+(?:\\.\\d+)?)px$/);\n if (pxWidth) {\n return Math.max(MIN_COLUMN_WIDTH, Math.round(Number(pxWidth[1])));\n }\n\n return MIN_COLUMN_WIDTH;\n}\n\nfunction DataTableProgressBar({\n value,\n barColor,\n label,\n}: {\n value: number;\n barColor?: string;\n label: string;\n}) {\n const percent = clampPercent(value);\n\n return (\n <div\n className=\"bg-bg-subtle mt-1 h-1.5 w-full overflow-hidden rounded-full\"\n role=\"progressbar\"\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuetext={`${percent}%`}\n aria-label={label}\n >\n <div\n className={cn(\"h-full rounded-full transition-all\", barColor)}\n style={{ width: `${percent}%` }}\n />\n </div>\n );\n}\n\n/** Renders the data table component. */\nexport function DataTable<T>({\n data,\n columns,\n keyExtractor,\n title = \"Data Table\",\n onRowClick,\n emptyMessage = \"No data available\",\n activeRowId,\n sortable = false,\n selectable = false,\n selectedKeys,\n onSelectionChange,\n expandable = false,\n renderExpanded,\n pageSize,\n stickyHeader = false,\n resizableColumns = false,\n onSort: onSortExternal,\n className,\n}: DataTableProps<T>) {\n const [sortCol, setSortCol] = useState<string | null>(null);\n const [sortDir, setSortDir] = useState<SortDir>(null);\n const [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set());\n const [page, setPage] = useState(0);\n const [colWidths, setColWidths] = useState<Record<string, number>>({});\n\n // Client-side sorting: numeric values compared directly, others via localeCompare.\n // Nullish and non-finite numeric values are sorted to the end regardless of direction.\n // Skipped when onSort (external/server-side sort) is provided — caller handles ordering.\n const sortedData = useMemo(() => {\n if (!sortable || !sortCol || !sortDir) return data;\n const col = columns.find((c) => c.id === sortCol);\n if (!col) return data;\n return [...data].sort((a, b) => {\n const aVal = getRawValue(a, col.accessor);\n const bVal = getRawValue(b, col.accessor);\n return compareSortValues(aVal, bVal, sortDir);\n });\n }, [data, sortable, sortCol, sortDir, columns]);\n\n // Pagination\n const totalPages = pageSize ? Math.ceil(sortedData.length / pageSize) : 1;\n const pagedData = pageSize\n ? sortedData.slice(page * pageSize, (page + 1) * pageSize)\n : sortedData;\n\n // Sort cycles: null → asc → desc → null (tri-state toggle).\n // Resets pagination to page 0 on each sort change.\n const handleSort = useCallback(\n (colId: string) => {\n if (!sortable) return;\n let nextDir: SortDir;\n if (sortCol === colId) {\n nextDir =\n sortDir === \"asc\" ? \"desc\" : sortDir === \"desc\" ? null : \"asc\";\n setSortDir(nextDir);\n if (nextDir === null) setSortCol(null);\n } else {\n setSortCol(colId);\n setSortDir(\"asc\");\n nextDir = \"asc\";\n }\n setPage(0);\n if (onSortExternal) {\n onSortExternal(colId, nextDir);\n }\n },\n [sortable, sortCol, sortDir, onSortExternal],\n );\n\n const toggleExpand = useCallback((key: string) => {\n setExpandedKeys((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n }, []);\n\n // Selection — membership lookups go through a Set so select-all and the\n // per-row `isSelected` check stay O(1) instead of O(selected) on every row.\n // Keyed on the `selectedKeys` prop (not the `selected` fallback array, which\n // gets a fresh reference each render when the prop is undefined).\n const selected = selectedKeys ?? [];\n const selectedSet = useMemo(\n () => new Set(selectedKeys ?? []),\n [selectedKeys],\n );\n const allKeys = data.map(keyExtractor);\n const allSelected =\n allKeys.length > 0 && allKeys.every((k) => selectedSet.has(k));\n const toggleSelectAll = useCallback(() => {\n if (!onSelectionChange) return;\n onSelectionChange(allSelected ? [] : allKeys);\n }, [allSelected, allKeys, onSelectionChange]);\n\n const toggleSelectRow = useCallback(\n (key: string) => {\n if (!onSelectionChange) return;\n onSelectionChange(\n selectedSet.has(key)\n ? selected.filter((k) => k !== key)\n : [...selected, key],\n );\n },\n [selected, selectedSet, onSelectionChange],\n );\n\n const sortIndicator = (colId: string) => {\n if (sortCol !== colId) return null;\n return sortDir === \"asc\" ? \" ▲\" : sortDir === \"desc\" ? \" ▼\" : null;\n };\n\n const colCount = columns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0);\n\n return (\n <div\n className={cn(\"gap-group flex flex-col\", className)}\n data-opt-id=\"J1KN4\"\n data-opt-slug=\"data-table.DataTable\"\n >\n {title && (\n <h3 className={cn(\"text-sm font-semibold\", OPT_TEXT_PRIMARY)}>\n {title}\n </h3>\n )}\n <div\n className={cn(\"overflow-x-auto rounded-lg\", OPT_BORDER, \"bg-surface\")}\n >\n {data.length === 0 ? (\n <div\n className={cn(\"px-4 py-8 text-center text-sm\", OPT_TEXT_SECONDARY)}\n >\n {emptyMessage}\n </div>\n ) : (\n <CompositeProvider focusLoop focusWrap>\n <Composite\n role=\"grid\"\n aria-label={title}\n className=\"w-full\"\n render={<table />}\n >\n <thead\n className={cn(\n \"border-border-subtle bg-surface-inset border-b\",\n stickyHeader && \"sticky top-0 z-10\",\n )}\n >\n <tr>\n {selectable && (\n <th className={cn(OPT_TH, \"w-10\")}>\n <Checkbox\n checked={allSelected}\n onChange={toggleSelectAll}\n aria-label=\"Select all\"\n />\n </th>\n )}\n {expandable && <th className={cn(OPT_TH, \"w-10\")} />}\n {columns.map((col) => {\n const isSortable = sortable && col.sortable !== false;\n const resizeValue = getResizeHandleValue(\n colWidths[col.id],\n col.width,\n );\n const resizeMax = Math.max(\n DEFAULT_COLUMN_RESIZE_MAX,\n resizeValue,\n );\n return (\n <th\n key={col.id}\n className={cn(\n OPT_TH,\n \"relative\",\n alignmentClass[col.align ?? \"left\"],\n isSortable &&\n \"hover:text-text-primary cursor-pointer select-none\",\n isSortable && OPT_FOCUS_VISIBLE,\n )}\n style={{\n width: colWidths[col.id] || col.width || undefined,\n }}\n onClick={\n isSortable ? () => handleSort(col.id) : undefined\n }\n onKeyDown={(event) => {\n if (\n !isSortable ||\n (event.key !== \"Enter\" && event.key !== \" \")\n ) {\n return;\n }\n event.preventDefault();\n handleSort(col.id);\n }}\n tabIndex={isSortable ? 0 : undefined}\n aria-sort={\n sortCol === col.id && sortDir\n ? sortDir === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : undefined\n }\n >\n <span className=\"flex items-center\">\n {col.header}\n {sortIndicator(col.id)}\n </span>\n {resizableColumns && (\n <span\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${col.header}`}\n aria-valuemin={MIN_COLUMN_WIDTH}\n aria-valuemax={resizeMax}\n aria-valuenow={resizeValue}\n aria-valuetext={`${resizeValue} pixels`}\n tabIndex={0}\n className=\"bg-border absolute top-0 right-0 bottom-0 w-1 cursor-col-resize opacity-0 hover:opacity-100\"\n onKeyDown={(e) => {\n if (\n e.key !== \"ArrowLeft\" &&\n e.key !== \"ArrowRight\" &&\n e.key !== \"Home\" &&\n e.key !== \"End\"\n ) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n if (e.key === \"Home\" || e.key === \"End\") {\n setColWidths((prev) => ({\n ...prev,\n [col.id]:\n e.key === \"Home\"\n ? MIN_COLUMN_WIDTH\n : resizeMax,\n }));\n return;\n }\n const delta = e.shiftKey ? 40 : 10;\n const direction = e.key === \"ArrowRight\" ? 1 : -1;\n setColWidths((prev) => {\n const current = getResizeHandleValue(\n prev[col.id],\n col.width,\n );\n return {\n ...prev,\n [col.id]: Math.max(\n MIN_COLUMN_WIDTH,\n current + direction * delta,\n ),\n };\n });\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const startX = e.clientX;\n const th = (e.target as HTMLElement)\n .parentElement!;\n const startW = th.offsetWidth;\n const onMove = (ev: MouseEvent) => {\n const newW = Math.max(\n MIN_COLUMN_WIDTH,\n startW + ev.clientX - startX,\n );\n setColWidths((prev) => ({\n ...prev,\n [col.id]: newW,\n }));\n };\n const onUp = () => {\n document.removeEventListener(\n \"mousemove\",\n onMove,\n );\n document.removeEventListener(\"mouseup\", onUp);\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n }}\n />\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody className={cn(\"divide-y\", OPT_DIVIDER)}>\n {pagedData.map((row) => {\n const key = keyExtractor(row);\n const isExpanded = expandedKeys.has(key);\n const isSelected = selectedSet.has(key);\n const isActive = activeRowId === key;\n\n return (\n <Fragment key={key}>\n <CompositeRow\n render={\n <tr\n className={cn(\n onRowClick ? \"cursor-pointer\" : undefined,\n (isSelected || isActive) && \"bg-accent-subtle\",\n )}\n onClick={\n onRowClick ? () => onRowClick(row) : undefined\n }\n />\n }\n >\n {selectable && (\n <CompositeItem\n render={\n <td\n className={cn(OPT_TD, \"w-10\")}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <Checkbox\n checked={isSelected}\n onChange={() => toggleSelectRow(key)}\n aria-label={`Select row ${key}`}\n />\n </CompositeItem>\n )}\n {expandable && (\n <CompositeItem\n render={\n <td\n className={cn(OPT_TD, \"w-10\")}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n toggleExpand(key);\n }}\n className={cn(\n \"rounded p-0.5 text-sm transition-transform\",\n OPT_TEXT_SECONDARY,\n OPT_FOCUS_VISIBLE,\n isExpanded && \"rotate-90\",\n )}\n aria-expanded={isExpanded}\n aria-label={`${isExpanded ? \"Collapse\" : \"Expand\"} row ${key}`}\n >\n &#x25B6;\n </button>\n </CompositeItem>\n )}\n {columns.map((col, colIndex) => (\n <CompositeItem\n key={col.id}\n render={\n <td\n className={cn(\n OPT_TD,\n alignmentClass[col.align ?? \"left\"],\n colIndex === 0 ? \"font-medium\" : \"\",\n )}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n onKeyDown={(event) => {\n if (\n !onRowClick ||\n event.target !== event.currentTarget ||\n (event.key !== \"Enter\" && event.key !== \" \")\n ) {\n return;\n }\n event.preventDefault();\n onRowClick(row);\n }}\n >\n {getCellValue(row, col.accessor)}\n {col.bar && (\n <DataTableProgressBar\n value={col.bar(row)}\n barColor={col.barColor ?? \"bg-accent\"}\n label={col.header}\n />\n )}\n </CompositeItem>\n ))}\n </CompositeRow>\n {expandable && isExpanded && renderExpanded && (\n <tr>\n <td\n colSpan={colCount}\n className=\"border-border-subtle bg-surface-inset border-t px-4 py-3\"\n >\n {renderExpanded(row)}\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </Composite>\n </CompositeProvider>\n )}\n </div>\n\n {/* Pagination */}\n {pageSize && totalPages > 1 && (\n <Pagination\n totalItems={sortedData.length}\n pageSize={pageSize}\n currentPage={page + 1}\n onPageChange={(p) => setPage(p - 1)}\n />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Alert } from \"../core/alert\";\n\n/** Defines the toast action shape. */\nexport interface ToastAction {\n label: string;\n onClick: () => void;\n}\n\n/** Toast severity. */\nexport type ToastVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\n/** Defines the toast message shape. */\nexport interface ToastMessage {\n id: string;\n variant: ToastVariant;\n title?: string;\n message: string;\n duration?: number;\n actions?: ToastAction[];\n}\n\n/** Options accepted by the imperative `toast()` API. */\nexport interface ToastOptions {\n variant?: ToastVariant;\n title?: string;\n message: string;\n duration?: number;\n actions?: ToastAction[];\n}\n\n/** Defines the toast context value shape. */\nexport interface ToastContextValue {\n toasts: ToastMessage[];\n addToast: (toast: Omit<ToastMessage, \"id\">) => string;\n removeToast: (id: string) => void;\n}\n\n/* ─── Imperative store ───\n *\n * A module-level store lets any code (event handlers, non-React modules) fire a\n * toast via `toast.success(\"Saved\")` without threading the `useToast` hook\n * through props. A mounted `ToastProvider` subscribes and renders the queue.\n */\n\nlet toastCounter = 0;\nlet toasts: ToastMessage[] = [];\nconst listeners = new Set<() => void>();\n\nfunction emitChange() {\n for (const l of listeners) l();\n}\n\nconst toastStore = {\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return toasts;\n },\n add(input: ToastOptions): string {\n const id = `toast-${++toastCounter}`;\n toasts = [...toasts, { id, variant: input.variant ?? \"info\", ...input }];\n emitChange();\n return id;\n },\n dismiss(id: string) {\n const next = toasts.filter((t) => t.id !== id);\n if (next.length !== toasts.length) {\n toasts = next;\n emitChange();\n }\n },\n clear() {\n if (toasts.length) {\n toasts = [];\n emitChange();\n }\n },\n};\n\nfunction makeVariant(variant: ToastVariant) {\n return (\n message: string,\n options?: Omit<ToastOptions, \"message\" | \"variant\">,\n ) => toastStore.add({ ...options, message, variant });\n}\n\n/**\n * Imperative toast API. Call from anywhere (no hook required):\n * `toast.success(\"Saved\")`, `toast.error(\"Failed\", { title: \"Oops\" })`,\n * `toast.dismiss(id)`, `toast.clear()`. Requires a mounted `ToastProvider`.\n */\nexport const toast = Object.assign(\n (options: ToastOptions) => toastStore.add(options),\n {\n info: makeVariant(\"info\"),\n success: makeVariant(\"success\"),\n warning: makeVariant(\"warning\"),\n error: makeVariant(\"error\"),\n dismiss: (id: string) => toastStore.dismiss(id),\n clear: () => toastStore.clear(),\n },\n);\n\nconst ToastContext = createContext<ToastContextValue | null>(null);\n\n/** Localized labels for the notification toast component. */\nexport type NotificationToastLabels = Record<never, never>;\n\n/** Props for the toast provider component. */\nexport interface ToastProviderProps {\n children: ReactNode;\n position?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n defaultDuration?: number;\n stackLimit?: number;\n}\n\nconst positionStyles: Record<\n NonNullable<ToastProviderProps[\"position\"]>,\n string\n> = {\n \"top-right\": \"top-4 right-4\",\n \"top-left\": \"top-4 left-4\",\n \"bottom-right\": \"bottom-4 right-4\",\n \"bottom-left\": \"bottom-4 left-4\",\n};\n\n/** Renders the toast provider component. */\nexport function ToastProvider({\n children,\n position = \"top-right\",\n defaultDuration = 5000,\n stackLimit = 5,\n}: ToastProviderProps) {\n const allToasts = useSyncExternalStore(\n toastStore.subscribe,\n toastStore.getSnapshot,\n toastStore.getSnapshot,\n );\n // Newest toasts win when the queue exceeds the stack limit.\n const visibleToasts =\n allToasts.length > stackLimit ? allToasts.slice(-stackLimit) : allToasts;\n\n const addToast = useCallback(\n (t: Omit<ToastMessage, \"id\">) => toastStore.add(t),\n [],\n );\n const removeToast = useCallback((id: string) => toastStore.dismiss(id), []);\n\n return (\n <ToastContext.Provider\n value={{ toasts: visibleToasts, addToast, removeToast }}\n >\n {children}\n <div\n className={cn(\n \"gap-element fixed z-50 flex flex-col\",\n positionStyles[position],\n )}\n role=\"region\"\n aria-label=\"Notifications\"\n data-opt-id=\"M0KTS\"\n data-opt-slug=\"notification-toast.ToastProvider\"\n >\n {visibleToasts.map((t) => (\n <NotificationToast\n key={t.id}\n toast={t}\n defaultDuration={defaultDuration}\n onDismiss={() => toastStore.dismiss(t.id)}\n />\n ))}\n </div>\n </ToastContext.Provider>\n );\n}\n\n/** Provides toast. */\nexport function useToast() {\n const context = useContext(ToastContext);\n if (!context) {\n throw new Error(\"useToast must be used within a ToastProvider\");\n }\n return context;\n}\n\ninterface NotificationToastProps {\n toast: ToastMessage;\n onDismiss: () => void;\n /** Falls back here when the toast itself sets no duration. */\n defaultDuration?: number;\n}\n\n/** Renders the notification toast component. */\nexport function NotificationToast({\n toast,\n onDismiss,\n defaultDuration = 5000,\n}: NotificationToastProps) {\n const duration = toast.duration ?? defaultDuration;\n const isUrgent = toast.variant === \"error\" || toast.variant === \"warning\";\n const onDismissRef = useRef(onDismiss);\n const dismissedRef = useRef(false);\n const timerStartedAtRef = useRef<number | null>(null);\n const remainingDurationRef = useRef(duration);\n const [paused, setPaused] = useState(false);\n\n useEffect(() => {\n onDismissRef.current = onDismiss;\n }, [onDismiss]);\n\n const dismissOnce = useCallback(() => {\n if (dismissedRef.current) return;\n dismissedRef.current = true;\n onDismissRef.current();\n }, []);\n\n useEffect(() => {\n dismissedRef.current = false;\n remainingDurationRef.current = duration;\n }, [toast.id, duration]);\n\n useEffect(() => {\n if (!duration || duration <= 0 || paused || dismissedRef.current) {\n return;\n }\n\n timerStartedAtRef.current = Date.now();\n const timer = setTimeout(() => {\n dismissOnce();\n }, remainingDurationRef.current);\n\n return () => {\n clearTimeout(timer);\n if (timerStartedAtRef.current !== null) {\n const elapsed = Date.now() - timerStartedAtRef.current;\n remainingDurationRef.current = Math.max(\n 0,\n remainingDurationRef.current - elapsed,\n );\n timerStartedAtRef.current = null;\n }\n };\n }, [dismissOnce, duration, paused]);\n\n return (\n <div\n className=\"animate-in slide-in-from-right-full fade-in w-80 duration-200\"\n role={isUrgent ? \"alert\" : \"status\"}\n aria-live={isUrgent ? \"assertive\" : \"polite\"}\n aria-atomic=\"true\"\n onMouseEnter={() => setPaused(true)}\n onMouseLeave={() => setPaused(false)}\n onFocus={() => setPaused(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) {\n setPaused(false);\n }\n }}\n data-opt-id=\"26YVM\"\n data-opt-slug=\"notification-toast.NotificationToast\"\n >\n <Alert\n variant={toast.variant}\n title={toast.title}\n dismissible\n onDismiss={dismissOnce}\n >\n {toast.message}\n {toast.actions && toast.actions.length > 0 && (\n <div className=\"gap-element mt-2 flex\">\n {toast.actions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n onClick={action.onClick}\n className=\"text-xs font-medium underline hover:no-underline\"\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </Alert>\n </div>\n );\n}\n","\"use client\";\n\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport type { FailureItem } from \"../lib/types\";\nimport {\n OPT_FOCUS,\n OPT_FOCUS_VISIBLE,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_TEXT_TERTIARY,\n OPT_BORDER,\n} from \"../lib/styles\";\nimport { cn } from \"../lib/cn\";\nimport { Badge } from \"../core/badge\";\n\n// ── Labels ──\n\ninterface TimeAgoLabels {\n justNow: string;\n minutesAgo: string;\n hoursAgo: string;\n daysAgo: string;\n}\n\n/** Localized labels for the failure list component. */\nexport interface FailureListLabels {\n title?: string;\n emptyMessage?: string;\n moreItems?: string;\n severityLabels?: Partial<Record<\"critical\" | \"error\" | \"warning\", string>>;\n timeAgo?: Partial<TimeAgoLabels>;\n}\n\ninterface DefaultLabels {\n title: string;\n emptyMessage: string;\n moreItems: string;\n severityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n timeAgo: TimeAgoLabels;\n}\n\nconst defaultLabels: DefaultLabels = {\n title: \"최근 실패\",\n emptyMessage: \"실패 항목이 없습니다\",\n moreItems: \"{count}개 더 보기\",\n severityLabels: {\n critical: \"심각\",\n error: \"오류\",\n warning: \"경고\",\n },\n timeAgo: {\n justNow: \"방금 전\",\n minutesAgo: \"{minutes}분 전\",\n hoursAgo: \"{hours}시간 전\",\n daysAgo: \"{days}일 전\",\n },\n};\n\n// ── Severity ──\n\nconst severityVariant: Record<FailureItem[\"severity\"], \"error\" | \"warning\"> = {\n critical: \"error\",\n error: \"error\",\n warning: \"warning\",\n};\n\nconst severityBorder: Record<FailureItem[\"severity\"], string> = {\n critical: \"border-l-2 border-l-danger\",\n error: \"border-l-2 border-l-danger\",\n warning: \"border-l-2 border-l-warning\",\n};\n\n// ── Props ──\n\n/** Props for the failure list component. */\nexport interface FailureListProps {\n failures: FailureItem[];\n title?: string;\n maxItems?: number;\n /** Group failures by `group` field */\n grouped?: boolean;\n onFailureClick?: (failure: FailureItem) => void;\n onShowMore?: () => void;\n labels?: FailureListLabels;\n locale?: string;\n loading?: boolean;\n renderActions?: (failure: FailureItem) => ReactNode;\n className?: string;\n}\n\n// ── Helpers ──\n\nfunction formatRelativeTime(\n timestamp: string,\n timeLabels: TimeAgoLabels,\n locale: string,\n): string {\n const now = new Date();\n const date = new Date(timestamp);\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return timeLabels.justNow;\n if (diffMins < 60)\n return timeLabels.minutesAgo.replace(\"{minutes}\", String(diffMins));\n if (diffHours < 24)\n return timeLabels.hoursAgo.replace(\"{hours}\", String(diffHours));\n if (diffDays < 7)\n return timeLabels.daysAgo.replace(\"{days}\", String(diffDays));\n return date.toLocaleDateString(locale);\n}\n\nfunction groupBy<T>(items: T[], key: (item: T) => string): Map<string, T[]> {\n const map = new Map<string, T[]>();\n for (const item of items) {\n const k = key(item);\n const existing = map.get(k);\n if (existing) {\n existing.push(item);\n } else {\n map.set(k, [item]);\n }\n }\n return map;\n}\n\n// ── Component ──\n\nfunction FailureItemRow({\n failure,\n isLast,\n onFailureClick,\n renderActions,\n mergedSeverityLabels,\n mergedTimeAgo,\n locale,\n}: {\n failure: FailureItem;\n isLast: boolean;\n onFailureClick?: (failure: FailureItem) => void;\n renderActions?: (failure: FailureItem) => ReactNode;\n mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n mergedTimeAgo: TimeAgoLabels;\n locale: string;\n}) {\n const itemId = `failure-${failure.id}`;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!onFailureClick) return;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onFailureClick(failure);\n };\n\n return (\n <CompositeItem\n render={<article />}\n key={failure.id}\n role=\"article\"\n aria-labelledby={itemId}\n className={cn(\n \"group gap-group relative flex w-full items-start p-3\",\n OPT_FOCUS_VISIBLE,\n \"data-[active-item]:bg-accent-subtle\",\n onFailureClick && \"cursor-pointer\",\n !isLast && \"border-border-subtle border-b\",\n severityBorder[failure.severity],\n )}\n onClick={() => onFailureClick?.(failure)}\n onKeyDown={handleKeyDown}\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"gap-element flex items-center\">\n <Badge variant={severityVariant[failure.severity]} size=\"sm\">\n {mergedSeverityLabels[failure.severity]}\n </Badge>\n <span\n id={itemId}\n className={`text-sm font-medium ${OPT_TEXT_PRIMARY} truncate`}\n >\n {failure.title}\n </span>\n </div>\n\n {failure.message && (\n <p className={`mt-1 text-xs ${OPT_TEXT_SECONDARY} line-clamp-2`}>\n {failure.message}\n </p>\n )}\n\n <time\n dateTime={failure.timestamp}\n className={`mt-1 block text-xs ${OPT_TEXT_TERTIARY}`}\n >\n {formatRelativeTime(failure.timestamp, mergedTimeAgo, locale)}\n </time>\n </div>\n\n {renderActions && (\n <div className=\"flex shrink-0 items-center gap-1\">\n {renderActions(failure)}\n </div>\n )}\n </CompositeItem>\n );\n}\n\n/** Renders the failure list component. */\nexport function FailureList({\n failures,\n title,\n maxItems,\n grouped = false,\n onFailureClick,\n onShowMore,\n labels: customLabels,\n locale = \"ko-KR\",\n loading = false,\n renderActions,\n className,\n}: FailureListProps) {\n const mergedTimeAgo: TimeAgoLabels = {\n justNow: customLabels?.timeAgo?.justNow ?? defaultLabels.timeAgo.justNow,\n minutesAgo:\n customLabels?.timeAgo?.minutesAgo ?? defaultLabels.timeAgo.minutesAgo,\n hoursAgo: customLabels?.timeAgo?.hoursAgo ?? defaultLabels.timeAgo.hoursAgo,\n daysAgo: customLabels?.timeAgo?.daysAgo ?? defaultLabels.timeAgo.daysAgo,\n };\n const mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string> =\n {\n critical:\n customLabels?.severityLabels?.critical ??\n defaultLabels.severityLabels.critical,\n error:\n customLabels?.severityLabels?.error ??\n defaultLabels.severityLabels.error,\n warning:\n customLabels?.severityLabels?.warning ??\n defaultLabels.severityLabels.warning,\n };\n const labels = {\n title: customLabels?.title ?? defaultLabels.title,\n emptyMessage: customLabels?.emptyMessage ?? defaultLabels.emptyMessage,\n moreItems: customLabels?.moreItems ?? defaultLabels.moreItems,\n };\n\n const displayTitle = title ?? labels.title;\n\n const allItems = maxItems ? failures.slice(0, maxItems) : failures;\n const remainingCount = maxItems ? Math.max(0, failures.length - maxItems) : 0;\n\n const rowProps = {\n onFailureClick,\n renderActions,\n mergedSeverityLabels,\n mergedTimeAgo,\n locale,\n };\n\n return (\n <div\n className={className}\n data-opt-id=\"ZAM3R\"\n data-opt-slug=\"failure-list.FailureList\"\n >\n <div className=\"gap-group flex flex-col\">\n {displayTitle && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>\n {displayTitle}\n </h3>\n )}\n\n {failures.length === 0 ? (\n <div\n role=\"status\"\n className={`py-8 text-center text-sm ${OPT_TEXT_SECONDARY}`}\n >\n {labels.emptyMessage}\n </div>\n ) : (\n <CompositeProvider focusLoop orientation=\"vertical\">\n <Composite\n role=\"feed\"\n aria-label={displayTitle}\n aria-busy={loading}\n className={`rounded-lg ${OPT_BORDER} bg-surface`}\n >\n {grouped\n ? renderGrouped(\n allItems,\n remainingCount,\n rowProps,\n labels,\n onShowMore,\n )\n : renderFlat(\n allItems,\n remainingCount,\n rowProps,\n labels,\n onShowMore,\n )}\n </Composite>\n </CompositeProvider>\n )}\n </div>\n </div>\n );\n}\n\nfunction renderFlat(\n items: FailureItem[],\n remainingCount: number,\n rowProps: {\n onFailureClick?: (failure: FailureItem) => void;\n renderActions?: (failure: FailureItem) => ReactNode;\n mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n mergedTimeAgo: TimeAgoLabels;\n locale: string;\n },\n labels: { moreItems: string },\n onShowMore?: () => void,\n) {\n return (\n <>\n {items.map((failure, index) => (\n <FailureItemRow\n key={failure.id}\n failure={failure}\n isLast={index === items.length - 1 && remainingCount === 0}\n {...rowProps}\n />\n ))}\n {remainingCount > 0 && (\n <CompositeItem\n render={<button type=\"button\" />}\n onClick={onShowMore}\n className={`border-border-subtle w-full border-t p-3 text-center text-xs font-medium ${OPT_TEXT_SECONDARY} ${OPT_FOCUS} hover:text-accent data-[active-item]:bg-accent-subtle transition-colors`}\n aria-label={`${remainingCount}개의 실패 더 보기`}\n >\n {labels.moreItems.replace(\"{count}\", String(remainingCount))}\n </CompositeItem>\n )}\n </>\n );\n}\n\nfunction renderGrouped(\n items: FailureItem[],\n remainingCount: number,\n rowProps: {\n onFailureClick?: (failure: FailureItem) => void;\n renderActions?: (failure: FailureItem) => ReactNode;\n mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n mergedTimeAgo: TimeAgoLabels;\n locale: string;\n },\n labels: { moreItems: string },\n onShowMore?: () => void,\n) {\n const groups = groupBy(items, (f) => f.group ?? \"\");\n const groupEntries = Array.from(groups.entries());\n\n return (\n <>\n {groupEntries.map(([groupName, groupItems], groupIndex) => {\n const isLastGroup =\n groupIndex === groupEntries.length - 1 && remainingCount === 0;\n\n return (\n <div key={groupName || \"__ungrouped__\"}>\n {groupName && (\n <div\n className={cn(\n `px-3 py-2 text-xs font-semibold ${OPT_TEXT_TERTIARY} tracking-wider uppercase`,\n groupIndex > 0 && \"border-border-subtle border-t\",\n )}\n >\n {groupName}\n </div>\n )}\n {groupItems.map((failure, index) => (\n <FailureItemRow\n key={failure.id}\n failure={failure}\n isLast={isLastGroup && index === groupItems.length - 1}\n {...rowProps}\n />\n ))}\n </div>\n );\n })}\n {remainingCount > 0 && (\n <CompositeItem\n render={<button type=\"button\" />}\n onClick={onShowMore}\n className={`border-border-subtle w-full border-t p-3 text-center text-xs font-medium ${OPT_TEXT_SECONDARY} ${OPT_FOCUS} hover:text-accent data-[active-item]:bg-accent-subtle transition-colors`}\n aria-label={`${remainingCount}개의 실패 더 보기`}\n >\n {labels.moreItems.replace(\"{count}\", String(remainingCount))}\n </CompositeItem>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback, useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/** Defines the key value entry shape. */\nexport interface KeyValueEntry {\n id: string;\n key: string;\n value: string;\n isSecret?: boolean;\n}\n\n/** Localized labels for the key value editor component. */\nexport interface KeyValueEditorLabels {\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n addButton?: string;\n removeAriaLabel?: string;\n toggleSecretAriaLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<KeyValueEditorLabels> = {\n keyPlaceholder: \"키\",\n valuePlaceholder: \"값\",\n addButton: \"추가\",\n removeAriaLabel: \"항목 삭제\",\n toggleSecretAriaLabel: \"비밀값 토글\",\n emptyMessage: \"항목이 없습니다. 추가 버튼을 눌러주세요.\",\n};\n\n/** Props for the key value editor component. */\nexport interface KeyValueEditorProps {\n /** Current entries (controlled) */\n value?: KeyValueEntry[];\n /** Initial entries (uncontrolled) */\n defaultValue?: KeyValueEntry[];\n /** Called when entries change */\n onChange?: (entries: KeyValueEntry[]) => void;\n /** Allow toggling secret/password visibility */\n showSecretToggle?: boolean;\n /** Maximum number of entries allowed */\n maxEntries?: number;\n /** Whether entries are read-only */\n readOnly?: boolean;\n /** Custom labels for i18n */\n labels?: KeyValueEditorLabels;\n /** Render custom actions per entry */\n renderActions?: (entry: KeyValueEntry, index: number) => ReactNode;\n /** Validate key on change. Return error message or undefined. */\n validateKey?: (key: string, entries: KeyValueEntry[]) => string | undefined;\n className?: string;\n}\n\nlet idCounter = 0;\nfunction generateId() {\n return `kv-${++idCounter}`;\n}\n\n/** Renders the key value editor component. */\nexport function KeyValueEditor({\n value: controlledValue,\n defaultValue,\n onChange,\n showSecretToggle = false,\n maxEntries,\n readOnly = false,\n labels: customLabels,\n renderActions,\n validateKey,\n className,\n}: KeyValueEditorProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [internalEntries, setInternalEntries] = useState<KeyValueEntry[]>(\n () => defaultValue ?? [],\n );\n const entries = controlledValue ?? internalEntries;\n const keyInputRef = useRef<HTMLInputElement>(null);\n\n const updateEntries = useCallback(\n (next: KeyValueEntry[]) => {\n if (!controlledValue) {\n setInternalEntries(next);\n }\n onChange?.(next);\n },\n [controlledValue, onChange],\n );\n\n const addEntry = useCallback(() => {\n if (maxEntries && entries.length >= maxEntries) return;\n const newEntry: KeyValueEntry = {\n id: generateId(),\n key: \"\",\n value: \"\",\n isSecret: false,\n };\n updateEntries([...entries, newEntry]);\n // Focus the new key input after render\n requestAnimationFrame(() => {\n keyInputRef.current\n ?.closest(\"[data-kv-list]\")\n ?.querySelector<HTMLInputElement>(\n `[data-kv-id=\"${newEntry.id}\"] [data-kv-key]`,\n )\n ?.focus();\n });\n }, [entries, maxEntries, updateEntries]);\n\n const removeEntry = useCallback(\n (id: string) => {\n updateEntries(entries.filter((e) => e.id !== id));\n },\n [entries, updateEntries],\n );\n\n const updateEntry = useCallback(\n (id: string, field: \"key\" | \"value\", val: string) => {\n updateEntries(\n entries.map((e) => (e.id === id ? { ...e, [field]: val } : e)),\n );\n },\n [entries, updateEntries],\n );\n\n const toggleSecret = useCallback(\n (id: string) => {\n updateEntries(\n entries.map((e) => (e.id === id ? { ...e, isSecret: !e.isSecret } : e)),\n );\n },\n [entries, updateEntries],\n );\n\n const canAdd = !readOnly && (!maxEntries || entries.length < maxEntries);\n\n return (\n <div\n className={cn(\"gap-group flex flex-col\", className)}\n data-opt-id=\"NCBWA\"\n data-opt-slug=\"key-value-editor.KeyValueEditor\"\n >\n {entries.length === 0 ? (\n <p className=\"text-text-tertiary py-4 text-center text-sm\">\n {labels.emptyMessage}\n </p>\n ) : (\n <div className=\"gap-element flex flex-col\" data-kv-list>\n {entries.map((entry, index) => {\n const keyError = validateKey?.(entry.key, entries);\n return (\n <div\n key={entry.id}\n data-kv-id={entry.id}\n className={cn(\n \"gap-element flex items-start\",\n \"border-border rounded-lg border p-3\",\n \"bg-surface\",\n )}\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <input\n data-kv-key\n ref={index === entries.length - 1 ? keyInputRef : undefined}\n type=\"text\"\n value={entry.key}\n onChange={(e) =>\n updateEntry(entry.id, \"key\", e.target.value)\n }\n placeholder={labels.keyPlaceholder}\n readOnly={readOnly}\n aria-label={`${labels.keyPlaceholder} ${index + 1}`}\n className={cn(\n \"border-border bg-bg-subtle text-text-primary placeholder:text-text-tertiary w-full rounded-md border px-3 py-1.5 font-mono text-sm\",\n \"focus:border-accent focus-visible:ring-ring focus-visible:ring-offset-ring-offset focus-visible:ring-2 focus-visible:ring-offset-1\",\n readOnly && \"cursor-default opacity-70\",\n keyError && \"border-error\",\n )}\n />\n {keyError && (\n <span className=\"text-error text-xs\">{keyError}</span>\n )}\n </div>\n <span className=\"text-text-tertiary px-1 py-1.5\">=</span>\n <div className=\"min-w-0 flex-1\">\n <input\n type={entry.isSecret ? \"password\" : \"text\"}\n value={entry.value}\n onChange={(e) =>\n updateEntry(entry.id, \"value\", e.target.value)\n }\n placeholder={labels.valuePlaceholder}\n readOnly={readOnly}\n aria-label={`${labels.valuePlaceholder} ${index + 1}`}\n className={cn(\n \"border-border bg-bg-subtle text-text-primary placeholder:text-text-tertiary w-full rounded-md border px-3 py-1.5 font-mono text-sm\",\n \"focus:border-accent focus-visible:ring-ring focus-visible:ring-offset-ring-offset focus-visible:ring-2 focus-visible:ring-offset-1\",\n readOnly && \"cursor-default opacity-70\",\n )}\n />\n </div>\n {showSecretToggle && !readOnly && (\n <button\n type=\"button\"\n onClick={() => toggleSecret(entry.id)}\n aria-label={labels.toggleSecretAriaLabel}\n aria-pressed={entry.isSecret}\n className=\"text-text-tertiary hover:text-text-primary shrink-0 rounded p-1.5 transition-colors\"\n >\n {entry.isSecret ? (\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88\"\n />\n </svg>\n ) : (\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n )}\n </button>\n )}\n {renderActions?.(entry, index)}\n {!readOnly && (\n <button\n type=\"button\"\n onClick={() => removeEntry(entry.id)}\n aria-label={labels.removeAriaLabel}\n className=\"text-text-tertiary hover:text-error shrink-0 rounded p-1.5 transition-colors\"\n >\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n })}\n </div>\n )}\n {canAdd && (\n <button\n type=\"button\"\n onClick={addEntry}\n className={cn(\n \"border-border text-text-secondary rounded-lg border border-dashed px-4 py-2 text-sm transition-colors\",\n \"hover:border-accent hover:text-accent\",\n )}\n >\n {labels.addButton}\n </button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Badge } from \"../core/badge\";\n\n/** Defines the workflow canvas step shape. */\nexport interface WorkflowCanvasStep {\n id: string;\n title: string;\n row: number;\n col: number;\n status?: \"idle\" | \"running\" | \"success\" | \"error\";\n}\n\n/** Defines the workflow canvas connection shape. */\nexport interface WorkflowCanvasConnection {\n from: string;\n to: string;\n label?: string;\n}\n\n/** Localized labels for the workflow canvas component. */\nexport type WorkflowCanvasLabels = Record<never, never>;\n\n/** Props for the workflow canvas component. */\nexport interface WorkflowCanvasProps {\n steps: WorkflowCanvasStep[];\n connections?: WorkflowCanvasConnection[];\n rows?: number;\n cols?: number;\n cellSize?: number;\n gap?: number;\n title?: string;\n emptyMessage?: string;\n selectedStepId?: string;\n onSelectStep?: (step: WorkflowCanvasStep) => void;\n onStepMove?: (stepId: string, row: number, col: number) => void;\n renderStep?: (step: WorkflowCanvasStep, selected: boolean) => React.ReactNode;\n className?: string;\n}\n\nconst statusVariant = {\n idle: \"default\",\n running: \"info\",\n success: \"success\",\n error: \"error\",\n} as const;\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/** Renders the workflow canvas component. */\nexport function WorkflowCanvas({\n steps,\n connections = [],\n rows = 9,\n cols = 9,\n cellSize = 72,\n gap = 12,\n title = \"Workflow Canvas\",\n emptyMessage = \"No workflow steps\",\n selectedStepId,\n onSelectStep,\n onStepMove,\n renderStep,\n className,\n}: WorkflowCanvasProps) {\n const stepMap = React.useMemo(\n () => new Map(steps.map((step) => [step.id, step])),\n [steps],\n );\n\n const width = cols * cellSize + (cols - 1) * gap;\n const height = rows * cellSize + (rows - 1) * gap;\n\n const renderDefaultStep = React.useCallback(\n (step: WorkflowCanvasStep, selected: boolean) => (\n <button\n type=\"button\"\n onClick={() => onSelectStep?.(step)}\n className={cn(\n \"group absolute flex h-full w-full flex-col justify-between rounded-lg border p-2 text-left transition-colors\",\n selected\n ? \"border-accent bg-accent-subtle\"\n : \"border-border bg-surface hover:bg-bg-subtle\",\n )}\n >\n <span className=\"text-text-primary truncate text-xs font-medium\">\n {step.title}\n </span>\n {step.status && (\n <Badge\n variant={statusVariant[step.status]}\n size=\"sm\"\n className=\"w-fit\"\n >\n {step.status}\n </Badge>\n )}\n </button>\n ),\n [onSelectStep],\n );\n\n const handleStepKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>, step: WorkflowCanvasStep) => {\n if (!onStepMove) {\n return;\n }\n\n let nextRow = step.row;\n let nextCol = step.col;\n\n switch (event.key) {\n case \"ArrowUp\":\n nextRow -= 1;\n break;\n case \"ArrowDown\":\n nextRow += 1;\n break;\n case \"ArrowLeft\":\n nextCol -= 1;\n break;\n case \"ArrowRight\":\n nextCol += 1;\n break;\n default:\n return;\n }\n\n event.preventDefault();\n onStepMove(\n step.id,\n clamp(nextRow, 0, rows - 1),\n clamp(nextCol, 0, cols - 1),\n );\n },\n [onStepMove, rows, cols],\n );\n\n return (\n <div\n className={cn(\"gap-group flex flex-col\", className)}\n data-opt-id=\"4TX11\"\n data-opt-slug=\"workflow-canvas.WorkflowCanvas\"\n >\n <h3 className=\"text-text-primary text-sm font-semibold\">{title}</h3>\n\n {steps.length === 0 ? (\n <div className=\"text-text-secondary border-border rounded-lg border border-dashed p-8 text-center text-sm\">\n {emptyMessage}\n </div>\n ) : (\n <div className=\"border-border bg-bg-subtle relative overflow-auto rounded-lg border p-3\">\n <div\n role=\"grid\"\n aria-label={title}\n className=\"relative\"\n style={{ width, height }}\n >\n <div\n className=\"grid\"\n style={{\n gridTemplateColumns: `repeat(${cols}, ${cellSize}px)`,\n gridTemplateRows: `repeat(${rows}, ${cellSize}px)`,\n gap,\n }}\n >\n {Array.from({ length: rows * cols }, (_, i) => (\n <div\n key={i}\n aria-hidden=\"true\"\n className=\"border-border-subtle bg-surface/30 rounded-md border border-dashed\"\n />\n ))}\n </div>\n\n <svg\n className=\"pointer-events-none absolute inset-0\"\n width={width}\n height={height}\n aria-hidden=\"true\"\n >\n {connections.map((connection) => {\n const from = stepMap.get(connection.from);\n const to = stepMap.get(connection.to);\n if (!from || !to) {\n return null;\n }\n\n const x1 = from.col * (cellSize + gap) + cellSize / 2;\n const y1 = from.row * (cellSize + gap) + cellSize / 2;\n const x2 = to.col * (cellSize + gap) + cellSize / 2;\n const y2 = to.row * (cellSize + gap) + cellSize / 2;\n\n return (\n <g key={`${connection.from}-${connection.to}`}>\n <line\n x1={x1}\n y1={y1}\n x2={x2}\n y2={y2}\n stroke=\"currentColor\"\n strokeOpacity=\"0.35\"\n strokeWidth=\"2\"\n />\n {connection.label && (\n <text\n x={(x1 + x2) / 2}\n y={(y1 + y2) / 2 - 4}\n textAnchor=\"middle\"\n className=\"fill-text-secondary text-[10px]\"\n >\n {connection.label}\n </text>\n )}\n </g>\n );\n })}\n </svg>\n\n {steps.map((step) => {\n const selected = selectedStepId === step.id;\n\n return (\n <div\n key={step.id}\n role=\"gridcell\"\n tabIndex={0}\n aria-selected={selected}\n aria-label={`${step.title} (${step.row + 1}, ${step.col + 1})`}\n onKeyDown={(event) => handleStepKeyDown(event, step)}\n className=\"focus-visible:ring-ring absolute focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-white focus-visible:outline-none\"\n style={{\n width: cellSize,\n height: cellSize,\n left: step.col * (cellSize + gap),\n top: step.row * (cellSize + gap),\n }}\n >\n {renderStep\n ? renderStep(step, selected)\n : renderDefaultStep(step, selected)}\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n\nWorkflowCanvas.displayName = \"WorkflowCanvas\";\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n/** Configuration for {@link useAutoRefresh}. */\nexport interface AutoRefreshOptions {\n /** Milliseconds between runs. `0` disables the timer. */\n interval: number;\n paused?: boolean;\n /** Called on each tick. If it returns a promise, the next wait starts after it settles. */\n onRefresh?: () => void | Promise<unknown>;\n}\n\n/**\n * A refresh timer that waits for its own work.\n *\n * A plain `setInterval` fires on a schedule regardless of whether the previous\n * query came back, so a five-second interval over a seven-second query stacks\n * requests until something gives. Chaining the next wait onto the settled\n * promise keeps exactly one refresh in flight, and a rejection stops the loop\n * instead of hammering an endpoint that is already failing.\n */\nexport function useAutoRefresh({\n interval,\n paused = false,\n onRefresh,\n}: AutoRefreshOptions): void {\n const callbackRef = useRef(onRefresh);\n callbackRef.current = onRefresh;\n\n useEffect(() => {\n if (paused || interval <= 0 || !callbackRef.current) return;\n\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const schedule = () => {\n timer = setTimeout(async () => {\n if (cancelled) return;\n try {\n await callbackRef.current?.();\n } catch {\n // The caller owns error reporting; stop the loop rather than\n // retrying against something that is already broken.\n return;\n }\n if (!cancelled) schedule();\n }, interval);\n };\n\n schedule();\n\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [interval, paused]);\n}\n","\"use client\";\n\nimport {\n ChevronLeft,\n ChevronRight,\n Clock,\n RefreshCw,\n ZoomIn,\n ZoomOut,\n} from \"lucide-react\";\nimport { useCallback, useMemo, useState, type KeyboardEvent } from \"react\";\nimport {\n formatCountUnit,\n formatDuration,\n formatInstant,\n isDateOnly,\n isExactMinutes,\n isRelativeExpression,\n isRelativeToNow,\n measureTimeWindow,\n parseRelativeParts,\n parseTimeExpression,\n shiftTimeRange,\n zoomTimeRange,\n type TimeRange,\n} from \"@reopt-ai/opt-charts\";\nimport { Button } from \"../core/button\";\nimport { Input } from \"../core/input\";\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from \"../core/popover\";\nimport {\n SelectItem,\n SelectPopover,\n SelectRoot,\n SelectTrigger,\n} from \"../core/select\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_TEXT_SECONDARY } from \"../lib/styles\";\nimport { useAutoRefresh } from \"../lib/use-auto-refresh\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type { TimeRange };\n\n/** A named window offered in the quick-select list. */\nexport interface TimeRangePreset {\n label: string;\n range: TimeRange;\n}\n\n/** How often the control asks its owner to re-query. */\nexport interface RefreshSetting {\n /** Milliseconds. `0` means off. */\n interval: number;\n paused: boolean;\n}\n\n/** Localized strings for the time range control. */\nexport interface TimeRangeControlLabels {\n trigger?: string;\n invalid?: string;\n last?: (duration: string) => string;\n next?: (duration: string) => string;\n quickSelect?: string;\n apply?: string;\n update?: string;\n refresh?: string;\n commonlyUsed?: string;\n recentlyUsed?: string;\n start?: string;\n end?: string;\n startHint?: string;\n autoRefresh?: string;\n autoRefreshOff?: string;\n every?: (duration: string) => string;\n previous?: string;\n nextWindow?: string;\n zoomIn?: string;\n zoomOut?: string;\n /** e.g. \"This day\" for a window snapped to a calendar unit. */\n thisUnit?: (unit: string) => string;\n units?: Partial<Record<TimeUnitKey, string>>;\n}\n\n/** Units the control can name. `s` only shows up in a parsed expression. */\ntype TimeUnitKey = \"s\" | \"m\" | \"h\" | \"d\" | \"w\" | \"M\" | \"y\";\n\nconst defaultLabels: Required<Omit<TimeRangeControlLabels, \"units\">> & {\n units: Record<TimeUnitKey, string>;\n} = {\n trigger: \"Select time range\",\n invalid: \"Invalid time range\",\n last: (duration) => `Last ${duration}`,\n next: (duration) => `Next ${duration}`,\n quickSelect: \"Quick select\",\n apply: \"Apply\",\n update: \"Update\",\n refresh: \"Refresh\",\n commonlyUsed: \"Commonly used\",\n recentlyUsed: \"Recently used\",\n start: \"Start\",\n end: \"End\",\n startHint: \"Absolute time or date math, e.g. now-7d\",\n autoRefresh: \"Auto refresh\",\n autoRefreshOff: \"Off\",\n every: (duration) => `Every ${duration}`,\n previous: \"Previous window\",\n nextWindow: \"Next window\",\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n thisUnit: (unit) => `This ${unit}`,\n units: {\n s: \"seconds\",\n m: \"minutes\",\n h: \"hours\",\n d: \"days\",\n w: \"weeks\",\n M: \"months\",\n y: \"years\",\n },\n};\n\n/** Props for the time range control. */\nexport interface TimeRangeControlProps {\n value: TimeRange;\n onChange: (range: TimeRange) => void;\n\n /** Named windows shown in the popover. */\n presets?: TimeRangePreset[];\n /** Windows the user picked before, newest first. Owned by the caller. */\n recentRanges?: TimeRangePreset[];\n\n /** IANA zone used for rounding and display. */\n timeZone?: string;\n locale?: string;\n\n /**\n * Hold edits until the user commits them. A queried window is expensive;\n * typing \"now-3\" should not fire three requests.\n */\n showUpdateButton?: boolean;\n /** Step the window back and forth, and widen or narrow it. */\n showWindowButtons?: boolean;\n /** Zoom-out step, as a fraction of the current width. */\n zoomFactor?: number;\n\n refresh?: RefreshSetting;\n onRefreshChange?: (setting: RefreshSetting) => void;\n /** Called by the refresh button and by each auto-refresh tick. */\n onRefresh?: () => void | Promise<unknown>;\n\n isLoading?: boolean;\n disabled?: boolean;\n className?: string;\n labels?: TimeRangeControlLabels;\n \"aria-label\"?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nconst QUICK_UNITS = [\"m\", \"h\", \"d\", \"w\", \"M\", \"y\"] as const;\ntype QuickUnit = (typeof QUICK_UNITS)[number];\n\nconst REFRESH_INTERVALS = [0, 5_000, 10_000, 30_000, 60_000, 300_000];\n\nfunction selectValue(value: string | string[]): string {\n return Array.isArray(value) ? (value[0] ?? \"\") : value;\n}\n\n/**\n * What the trigger says.\n *\n * A window anchored to `now` deserves its intent (\"Last 7 days\"), not two\n * timestamps the reader has to subtract. Everything else gets both ends\n * spelled out. A duration that does not divide into whole minutes is prefixed\n * with `~` rather than rounded silently.\n */\nfunction describeRange(\n range: TimeRange,\n labels: typeof defaultLabels,\n options: { locale?: string; timeZone?: string; now?: number },\n): { text: string; isInvalid: boolean } {\n const window = measureTimeWindow(range, {\n timeZone: options.timeZone,\n now: options.now,\n });\n if (window.isInvalid) return { text: labels.invalid, isInvalid: true };\n\n // A window that snaps to a calendar unit on both ends is that unit:\n // `now/d – now/d` is \"This day\", not two timestamps a day apart.\n const fromParts = parseRelativeParts(range.from);\n const toParts = parseRelativeParts(range.to);\n if (\n fromParts?.roundUnit &&\n fromParts.count === 0 &&\n toParts?.roundUnit === fromParts.roundUnit &&\n toParts.count === 0\n ) {\n return {\n text: labels.thisUnit(\n formatCountUnit(1, fromParts.roundUnit, options.locale).replace(\n /^1\\s*/,\n \"\",\n ),\n ),\n isInvalid: false,\n };\n }\n\n if (isRelativeToNow(range)) {\n const anchoredAtEnd = (toParts?.count ?? 0) === 0;\n const parts = anchoredAtEnd ? fromParts : toParts;\n // Say it back in the unit it was asked in: `now-90d` is \"90 days\", and\n // re-deriving from milliseconds would answer \"3 months\" to a different\n // question.\n //\n // A window snapped to whole units counts inclusively: `now-29d/d … now/d`\n // covers thirty days, not the twenty-nine its offset names. Counting in\n // the expression's own unit is also the only way to get that right —\n // measuring the milliseconds lands on \"1 month\", which is a different\n // claim about the same window.\n const bothSnapped =\n parts?.roundUnit === parts?.unit && toParts?.roundUnit === parts?.unit;\n const counted =\n parts && parts.count > 0\n ? formatCountUnit(\n parts.roundUnit && bothSnapped ? parts.count + 1 : parts.count,\n parts.unit,\n options.locale,\n )\n : null;\n const exact = counted !== null && (!parts?.roundUnit || bothSnapped);\n const duration = exact\n ? counted\n : formatDuration(window.duration, options.locale);\n const prefix = exact || isExactMinutes(window.duration) ? \"\" : \"~\";\n const text = anchoredAtEnd\n ? labels.last(`${prefix}${duration}`)\n : labels.next(`${prefix}${duration}`);\n return { text, isInvalid: false };\n }\n\n // A bound written as a calendar day is a day; printing a clock beside it\n // invents a precision the caller did not ask for.\n const dateOnly = isDateOnly(range.from) && isDateOnly(range.to);\n const from = formatInstant(window.from, { ...options, dateOnly });\n const to = formatInstant(window.to, { ...options, dateOnly });\n return { text: from === to ? from : `${from} – ${to}`, isInvalid: false };\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\n/**\n * TimeRangeControl — the window as an expression, not two frozen instants.\n *\n * Holding `{ from: \"now-7d\", to: \"now\" }` instead of a resolved pair is what\n * makes a saved board, a shared link and an auto-refresh timer all mean the\n * same thing tomorrow that they mean today. Around that sit the moves people\n * actually make on a chart: jump to a named window, step the same width back\n * and forth to compare, widen when the interesting thing is just off screen,\n * and let it re-query on a timer while they watch.\n *\n * @example\n * ```tsx\n * const [range, setRange] = useState<TimeRange>({ from: \"now-7d\", to: \"now\" });\n *\n * <TimeRangeControl\n * value={range}\n * onChange={setRange}\n * timeZone=\"Asia/Seoul\"\n * showWindowButtons\n * onRefresh={() => refetch()}\n * />\n * ```\n */\nexport function TimeRangeControl({\n value,\n onChange,\n presets,\n recentRanges,\n timeZone,\n locale,\n showUpdateButton = true,\n showWindowButtons = true,\n zoomFactor = 0.5,\n refresh,\n onRefreshChange,\n onRefresh,\n isLoading = false,\n disabled = false,\n className,\n labels: customLabels,\n \"aria-label\": ariaLabel,\n}: TimeRangeControlProps) {\n const labels = {\n ...defaultLabels,\n ...customLabels,\n units: { ...defaultLabels.units, ...customLabels?.units },\n };\n\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState<TimeRange | null>(null);\n const [quickCount, setQuickCount] = useState(\"15\");\n const [quickUnit, setQuickUnit] = useState<QuickUnit>(\"m\");\n\n const editing = draft ?? value;\n const hasChanges =\n draft !== null && (draft.from !== value.from || draft.to !== value.to);\n\n const description = useMemo(\n () => describeRange(value, labels, { locale, timeZone }),\n // `labels` is rebuilt each render by design; its content is what matters.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [value, locale, timeZone, customLabels],\n );\n\n const boundState = useCallback(\n (expression: string) =>\n parseTimeExpression(expression, { timeZone }) === null\n ? labels.invalid\n : undefined,\n [timeZone, labels],\n );\n\n const commit = useCallback(\n (range: TimeRange) => {\n setDraft(null);\n onChange(range);\n },\n [onChange],\n );\n\n const apply = useCallback(() => {\n if (draft) commit(draft);\n else onRefresh?.();\n }, [draft, commit, onRefresh]);\n\n // Enter commits from either bound input. The single Update button outside\n // the popover stays the one place a change is applied — two of them would\n // read as two different actions.\n const commitOnEnter = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key !== \"Enter\") return;\n apply();\n setOpen(false);\n },\n [apply],\n );\n\n const applyQuick = useCallback(() => {\n const count = Number(quickCount);\n if (!Number.isFinite(count) || count <= 0) return;\n commit({ from: `now-${Math.round(count)}${quickUnit}`, to: \"now\" });\n setOpen(false);\n }, [quickCount, quickUnit, commit]);\n\n const step = useCallback(\n (direction: 1 | -1) => {\n const next = shiftTimeRange(value, direction, { timeZone });\n if (next) commit(next);\n },\n [value, timeZone, commit],\n );\n\n const zoom = useCallback(\n (factor: number) => {\n const next = zoomTimeRange(value, factor, { timeZone });\n if (next) commit(next);\n },\n [value, timeZone, commit],\n );\n\n useAutoRefresh({\n interval: refresh?.interval ?? 0,\n paused: refresh?.paused ?? true,\n onRefresh,\n });\n\n const refreshLabel =\n !refresh || refresh.paused || refresh.interval === 0\n ? labels.autoRefreshOff\n : labels.every(formatDuration(refresh.interval, locale));\n\n return (\n <div\n className={cn(\n \"bg-surface inline-flex items-center rounded-lg border\",\n OPT_BORDER,\n className,\n )}\n role=\"group\"\n aria-label={ariaLabel ?? labels.trigger}\n data-opt-id=\"3WJ8H\"\n data-opt-slug=\"time-range-control.TimeRangeControl\"\n >\n <PopoverRoot open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n className={cn(\n \"text-text-primary h-10 gap-2\",\n description.isInvalid && \"text-danger-fg\",\n )}\n disabled={disabled}\n >\n <Clock className=\"text-text-tertiary h-4 w-4\" aria-hidden=\"true\" />\n <span className=\"truncate text-sm\">{description.text}</span>\n </PopoverTrigger>\n\n <PopoverContent className=\"gap-group flex w-80 flex-col\">\n {/* Quick select: \"Last N units\", the move people make most. */}\n <div className=\"gap-element flex flex-col\">\n <p className=\"text-text-primary text-xs font-medium\">\n {labels.quickSelect}\n </p>\n <div className=\"flex items-end gap-2\">\n <Input\n aria-label={labels.quickSelect}\n type=\"number\"\n min={1}\n size=\"sm\"\n className=\"w-20\"\n value={quickCount}\n onChange={(event) => setQuickCount(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") applyQuick();\n }}\n />\n <SelectRoot\n value={quickUnit}\n setValue={(next) =>\n setQuickUnit(selectValue(next) as QuickUnit)\n }\n >\n <SelectTrigger minWidth={110} aria-label={labels.quickSelect} />\n <SelectPopover>\n {QUICK_UNITS.map((unit) => (\n <SelectItem key={unit} value={unit}>\n {labels.units[unit]}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n <Button variant=\"secondary\" size=\"sm\" onClick={applyQuick}>\n {labels.apply}\n </Button>\n </div>\n </div>\n\n {/* Both bounds, editable as date math or an absolute timestamp. */}\n <div className=\"gap-element flex flex-col\">\n <Input\n label={labels.start}\n size=\"sm\"\n value={editing.from}\n error={boundState(editing.from)}\n hint={labels.startHint}\n onChange={(event) =>\n setDraft({ ...editing, from: event.target.value })\n }\n onKeyDown={commitOnEnter}\n />\n <Input\n label={labels.end}\n size=\"sm\"\n value={editing.to}\n error={boundState(editing.to)}\n onChange={(event) =>\n setDraft({ ...editing, to: event.target.value })\n }\n onKeyDown={commitOnEnter}\n />\n </div>\n\n {presets && presets.length > 0 && (\n <RangeList\n title={labels.commonlyUsed}\n items={presets}\n onPick={(range) => {\n commit(range);\n setOpen(false);\n }}\n />\n )}\n\n {recentRanges && recentRanges.length > 0 && (\n <RangeList\n title={labels.recentlyUsed}\n items={recentRanges.slice(0, 5)}\n onPick={(range) => {\n commit(range);\n setOpen(false);\n }}\n />\n )}\n\n {onRefreshChange && (\n <div className=\"gap-element flex flex-col\">\n <p className=\"text-text-primary text-xs font-medium\">\n {labels.autoRefresh}\n </p>\n <SelectRoot\n value={String(refresh?.paused ? 0 : (refresh?.interval ?? 0))}\n setValue={(next) => {\n const interval = Number(selectValue(next));\n onRefreshChange({ interval, paused: interval === 0 });\n }}\n >\n <SelectTrigger minWidth={140} aria-label={labels.autoRefresh} />\n <SelectPopover>\n {REFRESH_INTERVALS.map((interval) => (\n <SelectItem key={interval} value={String(interval)}>\n {interval === 0\n ? labels.autoRefreshOff\n : labels.every(formatDuration(interval, locale))}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n </div>\n )}\n </PopoverContent>\n </PopoverRoot>\n\n {showWindowButtons && (\n <div\n className={cn(\"flex items-center border-l\", OPT_BORDER)}\n role=\"group\"\n aria-label={labels.previous}\n >\n <IconButton\n label={labels.previous}\n disabled={disabled || description.isInvalid}\n onClick={() => step(-1)}\n >\n <ChevronLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton\n label={labels.zoomIn}\n disabled={disabled || description.isInvalid}\n onClick={() => zoom(-zoomFactor)}\n >\n <ZoomIn className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton\n label={labels.zoomOut}\n disabled={disabled || description.isInvalid}\n onClick={() => zoom(zoomFactor)}\n >\n <ZoomOut className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton\n label={labels.nextWindow}\n disabled={disabled || description.isInvalid}\n onClick={() => step(1)}\n >\n <ChevronRight className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n )}\n\n {(onRefresh || showUpdateButton) && (\n <div className={cn(\"border-l pl-2 pr-2\", OPT_BORDER)}>\n <Button\n variant={hasChanges ? \"primary\" : \"secondary\"}\n size=\"sm\"\n loading={isLoading}\n disabled={disabled || description.isInvalid}\n onClick={apply}\n leftIcon={\n hasChanges ? undefined : (\n <RefreshCw className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n )\n }\n title={refreshLabel}\n >\n {hasChanges ? labels.update : labels.refresh}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nTimeRangeControl.displayName = \"TimeRangeControl\";\n\n/* ------------------------------------------------------------------ */\n/* Internals */\n/* ------------------------------------------------------------------ */\n\nfunction IconButton({\n label,\n disabled,\n onClick,\n children,\n}: {\n label: string;\n disabled?: boolean;\n onClick: () => void;\n children: React.ReactNode;\n}) {\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={label}\n title={label}\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </Button>\n );\n}\n\nfunction RangeList({\n title,\n items,\n onPick,\n}: {\n title: string;\n items: TimeRangePreset[];\n onPick: (range: TimeRange) => void;\n}) {\n return (\n <div className=\"gap-element flex flex-col\">\n <p className=\"text-text-primary text-xs font-medium\">{title}</p>\n <ul className=\"grid grid-cols-2 gap-1\">\n {items.map((item, index) => (\n <li key={`${item.label}-${index}`}>\n <button\n type=\"button\"\n className={cn(\n \"hover:bg-bg-subtle w-full cursor-pointer rounded px-2 py-1 text-left text-xs\",\n OPT_TEXT_SECONDARY,\n )}\n onClick={() => onPick(item.range)}\n >\n {item.label}\n </button>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\n/**\n * The windows most analytics tools open with. Exported so a caller gets a\n * sensible list without inventing date math of their own.\n */\nexport const DEFAULT_TIME_PRESETS: TimeRangePreset[] = [\n { label: \"Last 15 minutes\", range: { from: \"now-15m\", to: \"now\" } },\n { label: \"Last hour\", range: { from: \"now-1h\", to: \"now\" } },\n { label: \"Last 24 hours\", range: { from: \"now-24h\", to: \"now\" } },\n { label: \"Last 7 days\", range: { from: \"now-7d\", to: \"now\" } },\n { label: \"Last 30 days\", range: { from: \"now-30d\", to: \"now\" } },\n { label: \"Last 90 days\", range: { from: \"now-90d\", to: \"now\" } },\n { label: \"Today\", range: { from: \"now/d\", to: \"now/d\" } },\n { label: \"This week\", range: { from: \"now/w\", to: \"now/w\" } },\n];\n\nexport { isRelativeExpression };\n","\"use client\";\n\nimport { Undo2 } from \"lucide-react\";\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport {\n resolveTimeRange,\n TimeSeriesChart,\n toAbsoluteRange,\n type TimeGranularity,\n type TimeRange,\n type TimeSeriesAnnotation,\n type TimeSeriesChartProps,\n type TimeSeriesDef,\n type TimeSeriesPoint,\n} from \"@reopt-ai/opt-charts\";\nimport { Button } from \"../core/button\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_SURFACE, OPT_TEXT_SECONDARY } from \"../lib/styles\";\nimport {\n TimeRangeControl,\n type RefreshSetting,\n type TimeRangeControlLabels,\n type TimeRangePreset,\n} from \"./time-range-control\";\n\n/** Localized strings for the time series panel. */\nexport interface TimeSeriesPanelLabels {\n back?: string;\n legend?: string;\n control?: TimeRangeControlLabels;\n}\n\nconst defaultLabels: Required<Omit<TimeSeriesPanelLabels, \"control\">> = {\n back: \"Back to previous range\",\n legend: \"Series\",\n};\n\n/** Props for the time series panel. */\nexport interface TimeSeriesPanelProps {\n title?: ReactNode;\n description?: ReactNode;\n /** Extra controls for the header's right side. */\n actions?: ReactNode;\n\n data: TimeSeriesPoint[];\n series: TimeSeriesDef[];\n\n /** The queried window. Also pins the chart's axis. */\n range: TimeRange;\n onRangeChange: (range: TimeRange) => void;\n\n granularity?: TimeGranularity | \"auto\";\n timeZone?: string;\n locale?: string;\n\n /** Render the built-in time range control in the header. */\n showRangeControl?: boolean;\n presets?: TimeRangePreset[];\n recentRanges?: TimeRangePreset[];\n refresh?: RefreshSetting;\n onRefreshChange?: (setting: RefreshSetting) => void;\n onRefresh?: () => void | Promise<unknown>;\n\n /** Legend entries can be clicked to hide a series. */\n toggleableLegend?: boolean;\n annotations?: TimeSeriesAnnotation[];\n isLoading?: boolean;\n height?: number;\n className?: string;\n /** Anything the chart itself accepts, for the cases this shell does not name. */\n chartProps?: Omit<\n TimeSeriesChartProps,\n \"data\" | \"series\" | \"from\" | \"to\" | \"granularity\" | \"timeZone\" | \"locale\"\n >;\n labels?: TimeSeriesPanelLabels;\n \"aria-label\"?: string;\n}\n\n/**\n * TimeSeriesPanel — a chart you can steer.\n *\n * The point of putting the control and the chart in one component is the\n * loop between them: drag across the plot and the window narrows to what you\n * dragged, which re-queries, which redraws the axis you just picked. That\n * only works if someone owns the step back out again — so zoom keeps a\n * history, and the header offers the way back rather than leaving the reader\n * to retype the range they came from.\n *\n * @example\n * ```tsx\n * const [range, setRange] = useState<TimeRange>({ from: \"now-7d\", to: \"now\" });\n *\n * <TimeSeriesPanel\n * title=\"Sessions\"\n * data={points}\n * series={[{ dataKey: \"sessions\", name: \"Sessions\" }]}\n * range={range}\n * onRangeChange={setRange}\n * onRefresh={() => refetch()}\n * toggleableLegend\n * />\n * ```\n */\nexport function TimeSeriesPanel({\n title,\n description,\n actions,\n data,\n series,\n range,\n onRangeChange,\n granularity = \"auto\",\n timeZone,\n locale,\n showRangeControl = true,\n presets,\n recentRanges,\n refresh,\n onRefreshChange,\n onRefresh,\n toggleableLegend = false,\n annotations,\n isLoading = false,\n height = 280,\n className,\n chartProps,\n labels: customLabels,\n \"aria-label\": ariaLabel,\n}: TimeSeriesPanelProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n const [history, setHistory] = useState<TimeRange[]>([]);\n const [hidden, setHidden] = useState<string[]>([]);\n\n // The chart needs instants; the control speaks date math. Resolving here is\n // what lets \"now-7d\" pin an axis at all.\n const resolved = useMemo(\n () => resolveTimeRange(range, { timeZone }),\n [range, timeZone],\n );\n\n const visibleSeries = useMemo(\n () => series.filter((def) => !hidden.includes(def.dataKey)),\n [series, hidden],\n );\n\n const handleRangeSelect = useCallback(\n (selection: { from: number; to: number }) => {\n setHistory((current) => [...current, range].slice(-10));\n onRangeChange(toAbsoluteRange(selection));\n },\n [range, onRangeChange],\n );\n\n const goBack = useCallback(() => {\n setHistory((current) => {\n const previous = current[current.length - 1];\n if (previous) onRangeChange(previous);\n return current.slice(0, -1);\n });\n }, [onRangeChange]);\n\n const setRange = useCallback(\n (next: TimeRange) => {\n // A range chosen from the control is a fresh start, not a zoom step.\n setHistory([]);\n onRangeChange(next);\n },\n [onRangeChange],\n );\n\n const toggleSeries = useCallback((dataKey: string) => {\n setHidden((current) =>\n current.includes(dataKey)\n ? current.filter((key) => key !== dataKey)\n : [...current, dataKey],\n );\n }, []);\n\n return (\n <section\n className={cn(OPT_SURFACE, OPT_BORDER, \"flex flex-col\", className)}\n aria-label={ariaLabel}\n data-opt-id=\"Y0XCY\"\n data-opt-slug=\"time-series-panel.TimeSeriesPanel\"\n >\n <header className=\"gap-group flex flex-wrap items-start justify-between px-5 pt-5 pb-3\">\n <div className=\"gap-element flex min-w-0 flex-col\">\n {title && (\n <h3 className=\"text-text-primary truncate text-base font-semibold\">\n {title}\n </h3>\n )}\n {description && (\n <p className={cn(OPT_TEXT_SECONDARY, \"truncate text-sm\")}>\n {description}\n </p>\n )}\n </div>\n <div className=\"gap-element flex flex-wrap items-center\">\n {history.length > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={goBack}\n leftIcon={<Undo2 className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />}\n >\n {labels.back}\n </Button>\n )}\n {actions}\n {showRangeControl && (\n <TimeRangeControl\n value={range}\n onChange={setRange}\n presets={presets}\n recentRanges={recentRanges}\n timeZone={timeZone}\n locale={locale}\n refresh={refresh}\n onRefreshChange={onRefreshChange}\n onRefresh={onRefresh}\n isLoading={isLoading}\n labels={customLabels?.control}\n />\n )}\n </div>\n </header>\n\n <div className=\"px-2 pb-4\">\n <TimeSeriesChart\n data={data}\n series={visibleSeries}\n from={resolved?.from}\n to={resolved?.to}\n granularity={granularity}\n timeZone={timeZone}\n locale={locale}\n height={height}\n selectable\n onRangeSelect={handleRangeSelect}\n annotations={annotations}\n showLegend={series.length > 1}\n legendOptions={\n toggleableLegend\n ? { onClick: toggleSeries, inactiveKeys: hidden }\n : undefined\n }\n aria-label={\n typeof title === \"string\" ? `${title} time series` : ariaLabel\n }\n {...chartProps}\n />\n </div>\n </section>\n );\n}\n\nTimeSeriesPanel.displayName = \"TimeSeriesPanel\";\n","\"use client\";\n\nimport { ChevronDown, ChevronUp, Minus, Plus } from \"lucide-react\";\nimport {\n forwardRef,\n memo,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type Ref,\n type UIEvent,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_TEXT_TERTIARY } from \"../lib/styles\";\nimport { Spinner } from \"../core/spinner\";\n\n/* ------------------------------------------------------------------ */\n/* Columns */\n/* ------------------------------------------------------------------ */\n\n/**\n * When a column gives up its space.\n *\n * Named steps rather than arbitrary widths because the breakpoints are\n * container queries compiled by Tailwind, which cannot see a value computed at\n * runtime. They are also the honest unit here: what matters is the order\n * columns drop in, not the pixel each one leaves at.\n */\nexport type LogColumnPriority = \"always\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nconst HIDE_BELOW: Record<LogColumnPriority, string> = {\n always: \"\",\n sm: \"hidden @[40rem]/log:flex\",\n md: \"hidden @[46rem]/log:flex\",\n lg: \"hidden @[58rem]/log:flex\",\n xl: \"hidden @[70rem]/log:flex\",\n};\n\n/** One column of the log. */\nexport interface LogColumn<Row> {\n id: string;\n header: ReactNode;\n /**\n * The field this column reads, as the query language names it. Set it and the\n * cell offers \"filter for / filter out\"; leave it off for a derived column\n * that no filter could express.\n */\n field?: string;\n /** CSS width. Omit on exactly one column to let it take the slack. */\n width?: string;\n priority?: LogColumnPriority;\n align?: \"left\" | \"right\";\n mono?: boolean;\n sortable?: boolean;\n /** The cell's text — also what a cell action filters on. */\n value: (row: Row) => string | number | null | undefined;\n /** Richer cell content. Falls back to `value`. */\n render?: (row: Row) => ReactNode;\n /**\n * Draw a colour marker before the value, hashed from the value itself so the\n * same one lands on the same hue in every session.\n */\n marker?: boolean;\n}\n\n/** Which column the rows are ordered by. */\nexport interface LogSort {\n columnId: string;\n direction: \"asc\" | \"desc\";\n}\n\n/** What a cell action asks the caller to do. */\nexport interface LogCellAction {\n field: string;\n value: string;\n intent: \"include\" | \"exclude\";\n}\n\nexport type LogDensity = \"compact\" | \"normal\" | \"comfortable\";\n\nconst ROW_HEIGHT: Record<LogDensity, number> = {\n compact: 26,\n normal: 32,\n comfortable: 40,\n};\n\nconst DENSITY_TEXT: Record<LogDensity, string> = {\n compact: \"text-[11px]\",\n normal: \"text-xs\",\n comfortable: \"text-sm\",\n};\n\n/** Localized strings for the log table. */\nexport interface LogTableLabels {\n listLabel?: string;\n loadingMore?: string;\n endOfResults?: string;\n filterFor?: (value: string) => string;\n filterOut?: (value: string) => string;\n sortAscending?: string;\n sortDescending?: string;\n}\n\nconst defaultLabels: Required<LogTableLabels> = {\n listLabel: \"Log\",\n loadingMore: \"Loading earlier entries…\",\n endOfResults: \"That is every entry in this range.\",\n filterFor: (value) => `Filter for ${value}`,\n filterOut: (value) => `Filter out ${value}`,\n sortAscending: \"Sort ascending\",\n sortDescending: \"Sort descending\",\n};\n\nexport interface LogTableProps<Row> {\n rows: Row[];\n columns: LogColumn<Row>[];\n getRowId: (row: Row) => string;\n\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n\n /** Fetch the next page. Called once when the viewport nears the end. */\n onLoadMore?: () => void;\n hasMore?: boolean;\n loadingMore?: boolean;\n\n /**\n * Rows arrive at the top while the reader is scrolled down — a live tail.\n * Turning this on holds their place when that happens and reports whether\n * they are pinned to the newest row.\n */\n prepending?: boolean;\n onFollowChange?: (following: boolean) => void;\n /** Highlight a row once, for entries that just arrived. */\n isNew?: (row: Row) => boolean;\n\n sort?: LogSort | null;\n onSortChange?: (sort: LogSort) => void;\n\n /** Offer \"filter for / filter out\" on cells whose column names a field. */\n onCellAction?: (action: LogCellAction) => void;\n\n density?: LogDensity;\n showHeader?: boolean;\n emptyState?: ReactNode;\n labels?: LogTableLabels;\n className?: string;\n}\n\nexport interface LogTableHandle {\n /** Jump to the newest row. */\n scrollToTop: () => void;\n /** Bring a row into view, leaving the scroll alone if it already is. */\n revealRow: (id: string) => void;\n}\n\n/** Rows rendered beyond the viewport on each side, so a fast scroll stays filled. */\nconst OVERSCAN = 10;\n\n/**\n * A stable hue per value. Colour does real work in a log — the eye groups by it\n * long before it reads the text — so the same event name has to land on the\n * same hue on every render and in every session, which rules out an index into\n * a palette.\n */\nfunction hueOf(value: string): number {\n let hash = 0;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 31 + value.charCodeAt(index)) | 0;\n }\n return Math.abs(hash) % 360;\n}\n\nconst EM_DASH = \"—\";\n/**\n * A column with nothing in it is a fact about the entry, not a value. Dimming\n * every absence the same way lets the eye skip the gaps while scanning, instead\n * of reading a dash as though it were data.\n */\nconst ABSENT = \"text-text-tertiary/50\";\n\nfunction columnStyle<Row>(column: LogColumn<Row>) {\n return column.width\n ? { width: column.width, flex: \"0 0 auto\" }\n : { flex: \"1 1 0%\", minWidth: 0 };\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\n/**\n * LogTable — a windowed table for entries that keep arriving.\n *\n * Written by hand rather than delegated to a data grid for the two things a log\n * needs that a grid does not: rows are inserted at the *top* while the reader\n * is partway down, which needs a scroll correction applied before paint, and\n * \"am I at the newest row?\" has to be answerable from the scroll container to\n * decide whether to follow the tail or hold position.\n *\n * What it takes from a data grid is the part readers actually reach for:\n * columns are data, so a caller can let people add, drop and reorder them; a\n * cell offers to filter for or against its own value; and density is a setting\n * rather than a constant.\n *\n * @example\n * ```tsx\n * <LogTable\n * rows={rows}\n * getRowId={(row) => row.id}\n * columns={[\n * { id: \"time\", header: \"Time\", width: \"9rem\", mono: true, value: (r) => r.time },\n * { id: \"name\", header: \"Event\", width: \"14rem\", field: \"name\", marker: true, value: (r) => r.name },\n * { id: \"path\", header: \"Path\", field: \"path\", value: (r) => r.path },\n * ]}\n * onCellAction={(action) => setQuery(applyCellAction(query, action))}\n * />\n * ```\n */\nfunction LogTableInner<Row>(\n {\n rows,\n columns,\n getRowId,\n selectedId = null,\n onSelect,\n onLoadMore,\n hasMore = false,\n loadingMore = false,\n prepending = false,\n onFollowChange,\n isNew,\n sort = null,\n onSortChange,\n onCellAction,\n density = \"normal\",\n showHeader = true,\n emptyState,\n labels: customLabels,\n className,\n }: LogTableProps<Row>,\n ref: Ref<LogTableHandle>,\n) {\n const labels = { ...defaultLabels, ...customLabels };\n const rowHeight = ROW_HEIGHT[density];\n\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [viewportHeight, setViewportHeight] = useState(0);\n const followingRef = useRef(true);\n\n // What the list looked like before this render, so a prepend can be measured.\n const previousTopIdRef = useRef<string | null>(null);\n const previousLengthRef = useRef(0);\n\n useImperativeHandle(\n ref,\n () => ({\n scrollToTop: () => {\n const container = scrollRef.current;\n if (!container) return;\n // Instant, not smooth. A smooth scroll is still in flight when flushed\n // rows land, so the position-holding correction below would read the\n // old offset and fight it — and \"jump to newest\" is a destination, not\n // a journey.\n container.scrollTop = 0;\n setScrollTop(0);\n if (!followingRef.current) {\n followingRef.current = true;\n onFollowChange?.(true);\n }\n },\n revealRow: (id: string) => {\n const index = rows.findIndex((row) => getRowId(row) === id);\n const container = scrollRef.current;\n if (index === -1 || !container) return;\n const top = index * rowHeight;\n const bottom = top + rowHeight;\n if (top < container.scrollTop) container.scrollTop = top;\n else if (bottom > container.scrollTop + container.clientHeight) {\n container.scrollTop = bottom - container.clientHeight;\n }\n },\n }),\n [onFollowChange, rows, getRowId, rowHeight],\n );\n\n useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() =>\n setViewportHeight(container.clientHeight),\n );\n observer.observe(container);\n setViewportHeight(container.clientHeight);\n return () => observer.disconnect();\n }, []);\n\n /**\n * Report whether the list is pinned to the newest row.\n *\n * Called from more than the scroll handler on purpose: the list can arrive at\n * the top without a scroll event — a reset, a jump to newest, a shorter\n * result set — and a stale \"not following\" would silently divert every live\n * row into a held-back pile.\n */\n const syncFollowing = useCallback(\n (container: HTMLDivElement) => {\n const following = container.scrollTop <= rowHeight;\n if (following === followingRef.current) return;\n followingRef.current = following;\n onFollowChange?.(following);\n },\n [onFollowChange, rowHeight],\n );\n\n /**\n * Hold the reader's place when rows arrive above them.\n *\n * Runs before paint: by the time the browser draws, the scroll offset has\n * already absorbed the inserted height, so the content under the cursor never\n * moves. Skipped while following, where the whole point is to stay at the top.\n */\n useLayoutEffect(() => {\n const container = scrollRef.current;\n const previousTopId = previousTopIdRef.current;\n previousTopIdRef.current = rows.length ? getRowId(rows[0]!) : null;\n const previousLength = previousLengthRef.current;\n previousLengthRef.current = rows.length;\n\n if (!container) return;\n syncFollowing(container);\n\n if (!prepending || followingRef.current || !previousTopId) return;\n // Only a genuine prepend shifts the reader; appended pages do not.\n if (rows.length <= previousLength) return;\n\n const prepended = rows.findIndex((row) => getRowId(row) === previousTopId);\n if (prepended <= 0) return;\n\n container.scrollTop += prepended * rowHeight;\n setScrollTop(container.scrollTop);\n }, [rows, getRowId, prepending, rowHeight, syncFollowing]);\n\n /**\n * Page forward when the rows do not reach the bottom of the viewport.\n *\n * Without this the list only advances on a scroll event, so a tall screen —\n * or a filter matching few rows per page — stops at the first page with no\n * way to ask for more.\n */\n useEffect(() => {\n const container = scrollRef.current;\n if (!container || !hasMore || loadingMore || !onLoadMore) return;\n if (container.scrollHeight <= container.clientHeight) onLoadMore();\n }, [hasMore, loadingMore, onLoadMore, rows.length, viewportHeight]);\n\n const handleScroll = useCallback(\n (event: UIEvent<HTMLDivElement>) => {\n const container = event.currentTarget;\n setScrollTop(container.scrollTop);\n syncFollowing(container);\n // One viewport of slack, so the next page is in flight before the reader\n // reaches the end of the current one.\n const remaining =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n if (hasMore && !loadingMore && remaining < container.clientHeight) {\n onLoadMore?.();\n }\n },\n [hasMore, loadingMore, onLoadMore, syncFollowing],\n );\n\n const totalHeight = rows.length * rowHeight;\n const firstVisible = Math.max(\n 0,\n Math.floor(scrollTop / rowHeight) - OVERSCAN,\n );\n const visibleCount =\n Math.ceil((viewportHeight || 480) / rowHeight) + OVERSCAN * 2;\n const lastVisible = Math.min(rows.length, firstVisible + visibleCount);\n const visibleRows = useMemo(\n () => rows.slice(firstVisible, lastVisible),\n [rows, firstVisible, lastVisible],\n );\n\n return (\n <div\n className={cn(\"@container/log flex min-h-0 flex-col\", className)}\n data-opt-id=\"NJ4N9\"\n data-opt-slug=\"log-table.LogTable\"\n >\n {showHeader && (\n <LogTableHeader\n columns={columns}\n sort={sort}\n onSortChange={onSortChange}\n density={density}\n labels={labels}\n />\n )}\n\n <div\n ref={scrollRef}\n onScroll={handleScroll}\n className=\"relative min-h-0 flex-1 overflow-x-hidden overflow-y-auto\"\n // A log with one open row is a listbox: the rows are selectable options\n // and the detail view renders the selected one. `<option>` is not a\n // substitute — it is only valid inside a select, and these rows are\n // absolutely positioned by the windowing math.\n // eslint-disable-next-line jsx-a11y/prefer-tag-over-role -- see above\n role=\"listbox\"\n aria-label={labels.listLabel}\n aria-activedescendant={selectedId ? `log-row-${selectedId}` : undefined}\n tabIndex={0}\n >\n {rows.length === 0 ? (\n emptyState\n ) : (\n <div style={{ height: totalHeight }} className=\"relative\">\n {visibleRows.map((row, index) => {\n const id = getRowId(row);\n return (\n <LogTableRow\n key={id}\n id={id}\n row={row}\n columns={columns}\n top={(firstVisible + index) * rowHeight}\n height={rowHeight}\n density={density}\n selected={id === selectedId}\n isNew={isNew?.(row) ?? false}\n onSelect={onSelect}\n onCellAction={onCellAction}\n labels={labels}\n />\n );\n })}\n </div>\n )}\n\n {loadingMore && (\n <div className=\"gap-element text-text-tertiary flex items-center justify-center py-3 text-xs\">\n <Spinner size=\"sm\" aria-hidden />\n {labels.loadingMore}\n </div>\n )}\n\n {!hasMore && rows.length > 0 && (\n <p className={cn(OPT_TEXT_TERTIARY, \"py-3 text-center text-xs\")}>\n {labels.endOfResults}\n </p>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * LogTable — see {@link LogTableInner}.\n *\n * The cast preserves the row generic through `forwardRef`, which otherwise\n * widens it to its constraint and takes the column callbacks' types with it.\n */\nexport const LogTable = forwardRef(LogTableInner) as <Row>(\n props: LogTableProps<Row> & { ref?: Ref<LogTableHandle> },\n) => ReturnType<typeof LogTableInner>;\n\n/* ------------------------------------------------------------------ */\n/* Header */\n/* ------------------------------------------------------------------ */\n\nfunction LogTableHeader<Row>({\n columns,\n sort,\n onSortChange,\n density,\n labels,\n}: {\n columns: LogColumn<Row>[];\n sort: LogSort | null;\n onSortChange?: (sort: LogSort) => void;\n density: LogDensity;\n labels: Required<LogTableLabels>;\n}) {\n return (\n <div\n role=\"row\"\n className={cn(\n \"border-border-subtle text-text-tertiary flex shrink-0 items-center gap-3 border-b px-3\",\n DENSITY_TEXT[density],\n )}\n style={{ height: ROW_HEIGHT[density] }}\n >\n {columns.map((column) => {\n const active = sort?.columnId === column.id;\n const sortable = column.sortable && onSortChange;\n const content = (\n <>\n {/* The marker's width, so the header sits over its own column. */}\n {column.marker && (\n <span aria-hidden className=\"size-1.5 shrink-0\" />\n )}\n <span className=\"truncate\">{column.header}</span>\n {active &&\n (sort!.direction === \"asc\" ? (\n <ChevronUp className=\"size-3 shrink-0\" aria-hidden />\n ) : (\n <ChevronDown className=\"size-3 shrink-0\" aria-hidden />\n ))}\n </>\n );\n\n return (\n <div\n key={column.id}\n role=\"columnheader\"\n aria-sort={\n active\n ? sort!.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : undefined\n }\n className={cn(\n \"flex items-center gap-1.5\",\n column.align === \"right\" && \"justify-end\",\n HIDE_BELOW[column.priority ?? \"always\"],\n )}\n style={columnStyle(column)}\n >\n {sortable ? (\n <button\n type=\"button\"\n className=\"hover:text-text-primary flex cursor-pointer items-center gap-1.5 truncate\"\n title={\n active && sort!.direction === \"desc\"\n ? labels.sortAscending\n : labels.sortDescending\n }\n onClick={() =>\n onSortChange({\n columnId: column.id,\n direction:\n active && sort!.direction === \"desc\" ? \"asc\" : \"desc\",\n })\n }\n >\n {content}\n </button>\n ) : (\n content\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Row */\n/* ------------------------------------------------------------------ */\n\ninterface LogTableRowProps<Row> {\n id: string;\n row: Row;\n columns: LogColumn<Row>[];\n top: number;\n height: number;\n density: LogDensity;\n selected: boolean;\n isNew: boolean;\n onSelect?: (id: string) => void;\n onCellAction?: (action: LogCellAction) => void;\n labels: Required<LogTableLabels>;\n}\n\nfunction LogTableRowImpl<Row>({\n id,\n row,\n columns,\n top,\n height,\n density,\n selected,\n isNew,\n onSelect,\n onCellAction,\n labels,\n}: LogTableRowProps<Row>) {\n return (\n <div\n // See the listbox note above: these rows are options, positioned by the\n // windowing math rather than laid out by the browser.\n // eslint-disable-next-line jsx-a11y/prefer-tag-over-role -- see above\n role=\"option\"\n aria-selected={selected}\n tabIndex={-1}\n id={`log-row-${id}`}\n data-log-row-id={id}\n onClick={() => onSelect?.(id)}\n onKeyDown={(event) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onSelect?.(id);\n }}\n style={{ top, height }}\n className={cn(\n \"border-border-subtle/60 absolute inset-x-0 flex items-center gap-3 border-b px-3\",\n DENSITY_TEXT[density],\n onSelect && \"cursor-pointer\",\n \"transition-colors duration-100\",\n \"hover:bg-surface-hover\",\n selected && \"bg-accent-subtle hover:bg-accent-subtle\",\n isNew && !selected && \"opt-log-row-enter\",\n )}\n >\n {columns.map((column) => {\n const raw = column.value(row);\n const text =\n raw === null || raw === undefined || raw === \"\" ? \"\" : String(raw);\n return (\n <div\n key={column.id}\n className={cn(\n \"group/cell relative flex min-w-0 items-center gap-1.5\",\n column.align === \"right\" && \"justify-end\",\n HIDE_BELOW[column.priority ?? \"always\"],\n )}\n style={columnStyle(column)}\n >\n {column.marker && text && (\n <span\n aria-hidden\n className=\"size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: `hsl(${hueOf(text)} 65% 55%)` }}\n />\n )}\n <span\n className={cn(\n \"truncate\",\n column.mono && \"font-mono\",\n text ? \"text-text-secondary\" : ABSENT,\n )}\n title={text || undefined}\n >\n {column.render ? column.render(row) : text || EM_DASH}\n </span>\n {onCellAction && column.field && text && (\n <CellActions\n field={column.field}\n value={text}\n onAction={onCellAction}\n labels={labels}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Memoized because a live log re-renders several times a second while almost\n * every visible row is unchanged.\n */\nconst LogTableRow = memo(LogTableRowImpl) as typeof LogTableRowImpl;\n\n/**\n * The two questions a reader has about a value they just spotted: show me only\n * these, and get these out of my way.\n *\n * Revealed on hover rather than always drawn — a log is scanned, and a pair of\n * buttons on every cell of every row is a wall of chrome. They stay in the tab\n * order regardless, since hover is not an interaction everyone has.\n */\nfunction CellActions({\n field,\n value,\n onAction,\n labels,\n}: {\n field: string;\n value: string;\n onAction: (action: LogCellAction) => void;\n labels: Required<LogTableLabels>;\n}) {\n const button =\n \"cursor-pointer rounded-sm p-0.5 text-text-tertiary hover:bg-bg-muted hover:text-text-primary\";\n return (\n <span\n className={cn(\n \"bg-surface/90 ml-auto hidden shrink-0 items-center gap-0.5 rounded pl-1\",\n \"group-hover/cell:flex focus-within:flex\",\n )}\n >\n <button\n type=\"button\"\n className={button}\n title={labels.filterFor(value)}\n aria-label={labels.filterFor(value)}\n onClick={(event) => {\n event.stopPropagation();\n onAction({ field, value, intent: \"include\" });\n }}\n >\n <Plus className=\"size-3\" aria-hidden />\n </button>\n <button\n type=\"button\"\n className={button}\n title={labels.filterOut(value)}\n aria-label={labels.filterOut(value)}\n onClick={(event) => {\n event.stopPropagation();\n onAction({ field, value, intent: \"exclude\" });\n }}\n >\n <Minus className=\"size-3\" aria-hidden />\n </button>\n </span>\n );\n}\n","/**\n * A search query, as a value.\n *\n * Free-text search and a row of filter pickers answer different halves of the\n * same question, and neither can express the other: a picker cannot say \"not\n * this\", and a text box cannot say \"this field, exactly\". A parsed query is one\n * thing that does both, and — because it is a value rather than a widget's\n * internal state — it survives a URL, a saved view, and the trip to a server\n * that has to turn it into a database filter.\n *\n * The grammar follows the one analytics tools have converged on (Elastic's\n * `EuiSearchBar`, Kibana, GitHub's issue search), minus the parts that only\n * make sense against a Lucene index:\n *\n * error a term anywhere in the row\n * \"connection reset\" a phrase, kept together\n * -health a term that must not appear\n * path:/checkout a field equal to a value\n * path:(/a or /b) a field equal to any of several values\n * -status:200 a field that must not equal a value\n * status>=500 a comparison\n * path:*checkout* the field contains this somewhere\n * utm_source:* the field is present at all\n *\n * Clauses combine with AND; `or` only groups values inside one field. That is\n * a deliberate ceiling: arbitrary boolean nesting reads worse than it queries,\n * and every backend this targets can express the restricted form directly.\n */\n\n/** How a field clause compares. */\nexport type QueryOperator =\n | \"eq\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"exists\";\n\n/** A bare or quoted word matched against the whole row. */\nexport interface QueryTermClause {\n type: \"term\";\n value: string;\n negated: boolean;\n}\n\n/** A constraint on one named field. Several values read as \"any of\". */\nexport interface QueryFieldClause {\n type: \"field\";\n field: string;\n operator: QueryOperator;\n values: string[];\n negated: boolean;\n}\n\nexport type QueryClause = QueryTermClause | QueryFieldClause;\n\n/** A parsed query: clauses combined with AND. */\nexport interface Query {\n clauses: QueryClause[];\n}\n\nexport const EMPTY_QUERY: Query = { clauses: [] };\n\n/** Whether a query constrains anything at all. */\nexport function isEmptyQuery(query: Query | null | undefined): boolean {\n return !query || query.clauses.length === 0;\n}\n\n/* ------------------------------------------------------------------ */\n/* Editing */\n/* ------------------------------------------------------------------ */\n\nfunction sameClause(a: QueryClause, b: QueryClause): boolean {\n if (a.type !== b.type) return false;\n if (a.type === \"term\" && b.type === \"term\") {\n return a.value === b.value && a.negated === b.negated;\n }\n const fieldA = a as QueryFieldClause;\n const fieldB = b as QueryFieldClause;\n return (\n fieldA.field === fieldB.field &&\n fieldA.operator === fieldB.operator &&\n fieldA.negated === fieldB.negated &&\n fieldA.values.length === fieldB.values.length &&\n fieldA.values.every((value, index) => value === fieldB.values[index])\n );\n}\n\n/** Add a clause unless an identical one is already there. */\nexport function addClause(query: Query, clause: QueryClause): Query {\n if (query.clauses.some((existing) => sameClause(existing, clause))) {\n return query;\n }\n return { clauses: [...query.clauses, clause] };\n}\n\n/**\n * Constrain a field to a value — what a cell's \"filter for this\" action does.\n *\n * Applying the opposite of a constraint already present replaces it rather than\n * adding it: `status:200` then \"filter out 200\" should read as one changed\n * mind, not as a query that can never match.\n */\nexport function withFieldValue(\n query: Query,\n field: string,\n value: string,\n options: { negated?: boolean; operator?: QueryOperator } = {},\n): Query {\n const negated = options.negated ?? false;\n const operator = options.operator ?? \"eq\";\n const clauses = query.clauses.filter(\n (clause) =>\n !(\n clause.type === \"field\" &&\n clause.field === field &&\n clause.operator === operator &&\n clause.values.length === 1 &&\n clause.values[0] === value\n ),\n );\n return {\n clauses: [\n ...clauses,\n { type: \"field\", field, operator, values: [value], negated },\n ],\n };\n}\n\n/** Drop every clause naming `field`. */\nexport function withoutField(query: Query, field: string): Query {\n return {\n clauses: query.clauses.filter(\n (clause) => clause.type !== \"field\" || clause.field !== field,\n ),\n };\n}\n\n/** Drop the clause at `index`, for a removable chip. */\nexport function removeClause(query: Query, index: number): Query {\n return { clauses: query.clauses.filter((_, at) => at !== index) };\n}\n\n/** Every field the query names, in the order they first appear. */\nexport function queryFields(query: Query): string[] {\n const seen: string[] = [];\n for (const clause of query.clauses) {\n if (clause.type === \"field\" && !seen.includes(clause.field)) {\n seen.push(clause.field);\n }\n }\n return seen;\n}\n\n/** The values a field is constrained to, if any — for showing a filter as active. */\nexport function fieldValues(query: Query, field: string): string[] {\n return query.clauses.flatMap((clause) =>\n clause.type === \"field\" && clause.field === field && !clause.negated\n ? clause.values\n : [],\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Cell actions */\n/* ------------------------------------------------------------------ */\n\n/** What a \"filter for / filter out\" control on a value asks for. */\nexport interface QueryCellAction {\n field: string;\n value: string;\n intent: \"include\" | \"exclude\";\n}\n\n/**\n * Fold a cell action into the query.\n *\n * The pair of buttons on a log cell is the fastest path from \"I noticed this\n * value\" to a filtered view, and the reason it works is that the result is a\n * query the reader can then see, edit and share — not a hidden filter stack\n * with its own rules.\n */\nexport function applyCellAction(query: Query, action: QueryCellAction): Query {\n return withFieldValue(query, action.field, action.value, {\n negated: action.intent === \"exclude\",\n });\n}\n","/**\n * Text in, {@link Query} out — and never an exception.\n *\n * A search box is edited one keystroke at a time, so most of the strings this\n * sees are half-written: `path:`, `status>`, `\"unclosed`. A parser that throws\n * on those turns every intermediate state into an error banner, which trains\n * people to type somewhere else and paste. Instead, anything that cannot be\n * read as a clause is kept as a plain term, and the caller is told separately\n * (via {@link parseQueryWithDiagnostics}) if it wants to warn.\n *\n * Written by hand rather than generated. EUI compiles a PEG grammar for the\n * same job, which buys arbitrary nesting we deliberately do not offer, at the\n * cost of a build-time plugin in every consumer.\n */\nimport type {\n Query,\n QueryClause,\n QueryFieldClause,\n QueryOperator,\n} from \"./query-ast\";\n\n/** A part of the input that could not be read as intended. */\nexport interface QueryDiagnostic {\n /** Character offset into the original string. */\n at: number;\n text: string;\n message: string;\n}\n\nexport interface ParsedQuery {\n query: Query;\n diagnostics: QueryDiagnostic[];\n /** The final clause is still being typed — the caller can complete it. */\n trailing: { field: string; operator: QueryOperator; value: string } | null;\n}\n\nconst FIELD_NAME = /^[A-Za-z_][A-Za-z0-9_.-]*$/;\n\ninterface Token {\n text: string;\n at: number;\n /** The token was written inside quotes, so it is a phrase, not syntax. */\n quoted: boolean;\n}\n\n/**\n * Split on whitespace, but keep quoted runs and parenthesised groups whole.\n *\n * An unterminated quote or group swallows the rest of the line rather than\n * erroring: the reader is mid-word, and the alternative is the query flickering\n * between two different meanings as they type the closing character.\n */\nfunction tokenize(input: string): Token[] {\n const tokens: Token[] = [];\n let index = 0;\n\n while (index < input.length) {\n while (index < input.length && /\\s/.test(input[index]!)) index += 1;\n if (index >= input.length) break;\n\n const start = index;\n let text = \"\";\n // Only a token that *opens* with a quote is a phrase. `name:\"a b\"` quotes\n // its value, not the constraint — reading the whole token as a phrase there\n // would turn a field filter into a search for the literal text.\n let quoted = false;\n let atTokenStart = true;\n let depth = 0;\n\n while (index < input.length) {\n const char = input[index]!;\n\n if (char === '\"') {\n if (atTokenStart) quoted = true;\n atTokenStart = false;\n index += 1;\n while (index < input.length && input[index] !== '\"') {\n text += input[index];\n index += 1;\n }\n index += 1; // closing quote, or the end of the input\n continue;\n }\n\n if (char === \"(\") depth += 1;\n if (char === \")\") depth = Math.max(0, depth - 1);\n if (/\\s/.test(char) && depth === 0) break;\n\n atTokenStart = false;\n text += char;\n index += 1;\n }\n\n if (text.length > 0 || quoted) tokens.push({ text, at: start, quoted });\n }\n\n return tokens;\n}\n\n/** `(a or b)` → `[\"a\", \"b\"]`; anything else is a single value. */\nfunction readValues(raw: string): string[] {\n const trimmed = raw.trim();\n if (!trimmed.startsWith(\"(\")) {\n return [stripQuotes(trimmed)];\n }\n const inner = trimmed.replace(/^\\(/, \"\").replace(/\\)$/, \"\");\n return inner\n .split(/\\s+or\\s+/i)\n .map((part) => stripQuotes(part.trim()))\n .filter((part) => part.length > 0);\n}\n\nfunction stripQuotes(value: string): string {\n if (value.length >= 2 && value.startsWith('\"') && value.endsWith('\"')) {\n return value.slice(1, -1);\n }\n return value.replace(/^\"/, \"\");\n}\n\nconst OPERATORS: { symbol: string; operator: QueryOperator }[] = [\n { symbol: \">=\", operator: \"gte\" },\n { symbol: \"<=\", operator: \"lte\" },\n { symbol: \":\", operator: \"eq\" },\n { symbol: \">\", operator: \"gt\" },\n { symbol: \"<\", operator: \"lt\" },\n];\n\n/** Where a field operator starts in the token, or `-1`. */\nfunction findOperator(\n text: string,\n): { index: number; symbol: string; operator: QueryOperator } | null {\n let best: { index: number; symbol: string; operator: QueryOperator } | null =\n null;\n for (const { symbol, operator } of OPERATORS) {\n const index = text.indexOf(symbol);\n if (index <= 0) continue;\n // `>=` must win over the `>` inside it.\n if (\n !best ||\n index < best.index ||\n (index === best.index && symbol.length > best.symbol.length)\n ) {\n best = { index, symbol, operator };\n }\n }\n return best;\n}\n\n/** Parse, keeping whatever could not be understood as a plain term. */\nexport function parseQueryWithDiagnostics(input: string): ParsedQuery {\n const diagnostics: QueryDiagnostic[] = [];\n const clauses: QueryClause[] = [];\n let trailing: ParsedQuery[\"trailing\"] = null;\n\n for (const token of tokenize(input)) {\n let text = token.text;\n let negated = false;\n\n if (!token.quoted && text.startsWith(\"-\") && text.length > 1) {\n negated = true;\n text = text.slice(1);\n }\n\n const operator = token.quoted ? null : findOperator(text);\n if (!operator) {\n if (text.length > 0) clauses.push({ type: \"term\", value: text, negated });\n continue;\n }\n\n const field = text.slice(0, operator.index);\n const rawValue = text.slice(operator.index + operator.symbol.length);\n\n if (!FIELD_NAME.test(field)) {\n // `12:30` is a time, not a field constraint.\n clauses.push({ type: \"term\", value: text, negated });\n continue;\n }\n\n if (rawValue === \"\") {\n // Mid-typing: remember it so the caller can offer completions, but do not\n // constrain anything yet — an empty value would match nothing.\n trailing = { field, operator: operator.operator, value: \"\" };\n continue;\n }\n\n if (rawValue === \"*\" && operator.operator === \"eq\") {\n clauses.push({\n type: \"field\",\n field,\n operator: \"exists\",\n values: [],\n negated,\n });\n continue;\n }\n\n // `path:*checkout*` — the wildcards are the syntax, the middle is the value.\n // Distinct from a bare `*`, which asks whether the field is there at all.\n if (\n operator.operator === \"eq\" &&\n rawValue.length > 2 &&\n rawValue.startsWith(\"*\") &&\n rawValue.endsWith(\"*\")\n ) {\n clauses.push({\n type: \"field\",\n field,\n operator: \"contains\",\n values: [stripQuotes(rawValue.slice(1, -1))],\n negated,\n });\n continue;\n }\n\n const values = readValues(rawValue);\n if (values.length === 0) {\n diagnostics.push({\n at: token.at,\n text: token.text,\n message: \"Empty value group\",\n });\n continue;\n }\n\n if (operator.operator !== \"eq\" && values.length > 1) {\n diagnostics.push({\n at: token.at,\n text: token.text,\n message: \"A comparison takes a single value\",\n });\n }\n\n const clause: QueryFieldClause = {\n type: \"field\",\n field,\n operator: operator.operator,\n values: operator.operator === \"eq\" ? values : values.slice(0, 1),\n negated,\n };\n clauses.push(clause);\n if (!rawValue.startsWith(\"(\")) {\n trailing = { field, operator: operator.operator, value: values[0] ?? \"\" };\n }\n }\n\n return { query: { clauses }, diagnostics, trailing };\n}\n\n/** Parse, discarding diagnostics. */\nexport function parseQuery(input: string): Query {\n return parseQueryWithDiagnostics(input).query;\n}\n","/**\n * {@link Query} back to text, so the box shows what the chips mean.\n *\n * Round-tripping matters more than prettiness: whatever a cell action or a\n * sidebar click adds to the query has to appear in the input as something the\n * reader could have typed themselves, and could edit by hand from there.\n */\nimport type { Query, QueryClause, QueryOperator } from \"./query-ast\";\n\nconst OPERATOR_SYMBOL: Record<QueryOperator, string> = {\n eq: \":\",\n contains: \":\",\n gt: \">\",\n gte: \">=\",\n lt: \"<\",\n lte: \"<=\",\n exists: \":\",\n};\n\n/** Quote a value that would otherwise re-parse as something else. */\nexport function quoteValue(value: string): string {\n return /[\\s\"()]/.test(value) || value === \"\"\n ? `\"${value.replace(/\"/g, \"\")}\"`\n : value;\n}\n\n/** One clause as text. */\nexport function formatClause(clause: QueryClause): string {\n const prefix = clause.negated ? \"-\" : \"\";\n if (clause.type === \"term\") return `${prefix}${quoteValue(clause.value)}`;\n if (clause.operator === \"exists\") return `${prefix}${clause.field}:*`;\n if (clause.operator === \"contains\") {\n return `${prefix}${clause.field}:*${clause.values[0] ?? \"\"}*`;\n }\n\n const symbol = OPERATOR_SYMBOL[clause.operator];\n if (clause.values.length > 1) {\n return `${prefix}${clause.field}${symbol}(${clause.values.map(quoteValue).join(\" or \")})`;\n }\n return `${prefix}${clause.field}${symbol}${quoteValue(clause.values[0] ?? \"\")}`;\n}\n\n/** The whole query as text. */\nexport function formatQuery(query: Query): string {\n return query.clauses.map(formatClause).join(\" \");\n}\n\n/** A short human label for a clause chip. */\nexport function describeClause(clause: QueryClause): string {\n if (clause.type === \"term\") {\n return clause.negated ? `not \"${clause.value}\"` : `\"${clause.value}\"`;\n }\n if (clause.operator === \"exists\") {\n return clause.negated\n ? `${clause.field} missing`\n : `${clause.field} present`;\n }\n if (clause.operator === \"contains\") {\n return `${clause.negated ? \"not \" : \"\"}${clause.field} ⊃ ${clause.values[0] ?? \"\"}`;\n }\n const values = clause.values.join(\", \");\n const symbol = OPERATOR_SYMBOL[clause.operator];\n return `${clause.negated ? \"not \" : \"\"}${clause.field} ${symbol === \":\" ? \"=\" : symbol} ${values}`;\n}\n","\"use client\";\n\nimport { Search, X } from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_FOCUS_VISIBLE } from \"../lib/styles\";\nimport {\n describeClause,\n formatQuery,\n parseQueryWithDiagnostics,\n removeClause,\n type Query,\n type QueryDiagnostic,\n} from \"../lib/query\";\n\n/** A field the query can constrain, offered as a completion. */\nexport interface QueryField {\n name: string;\n /** Shown beside the name — a type, a count, whatever tells them apart. */\n hint?: string;\n /** Known values, offered once the reader has typed `field:`. */\n values?: string[];\n}\n\n/** Localized strings for the query bar. */\nexport interface QueryBarLabels {\n placeholder?: string;\n ariaLabel?: string;\n clear?: string;\n removeClause?: (clause: string) => string;\n fieldsHeading?: string;\n valuesHeading?: string;\n syntaxHint?: ReactNode;\n}\n\nconst defaultLabels: Required<Omit<QueryBarLabels, \"syntaxHint\">> & {\n syntaxHint: ReactNode;\n} = {\n placeholder: \"Search, or filter with field:value\",\n ariaLabel: \"Search query\",\n clear: \"Clear query\",\n removeClause: (clause) => `Remove ${clause}`,\n fieldsHeading: \"Fields\",\n valuesHeading: \"Values\",\n syntaxHint: null,\n};\n\nexport interface QueryBarProps {\n value: Query;\n onChange: (query: Query) => void;\n /** Fields offered as completions, with their known values. */\n fields?: QueryField[];\n /** Show each clause as a removable chip below the input. */\n showClauses?: boolean;\n /** Commit on every keystroke instead of on Enter and blur. */\n live?: boolean;\n disabled?: boolean;\n className?: string;\n labels?: QueryBarLabels;\n}\n\nconst MAX_SUGGESTIONS = 8;\n\n/**\n * QueryBar — one control for \"find this\" and \"only these\".\n *\n * A search box and a row of filter pickers answer halves of the same question\n * and neither can express the other, so people end up using both and holding\n * the combination in their head. Typing the filter is what closes that: the\n * whole question is one string, which means it can be read back, corrected in\n * place, pasted to a colleague, and stored in a URL.\n *\n * The text is the source of truth while the reader is typing; the parsed query\n * is committed on Enter or blur. Anything half-written parses to a plain term\n * rather than an error, so the bar never argues with someone mid-word.\n *\n * @example\n * ```tsx\n * <QueryBar\n * value={query}\n * onChange={setQuery}\n * fields={[{ name: \"path\", values: [\"/checkout\", \"/cart\"] }]}\n * showClauses\n * />\n * ```\n */\nexport function QueryBar({\n value,\n onChange,\n fields = [],\n showClauses = false,\n live = false,\n disabled = false,\n className,\n labels: customLabels,\n}: QueryBarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const inputRef = useRef<HTMLInputElement>(null);\n const [text, setText] = useState(() => formatQuery(value));\n const [focused, setFocused] = useState(false);\n const [highlighted, setHighlighted] = useState(0);\n\n // Follow the query when it changes elsewhere — a cell action, a preset, the\n // back button — but never while the reader is mid-word in this very input.\n const committedRef = useRef(formatQuery(value));\n useEffect(() => {\n const next = formatQuery(value);\n if (next === committedRef.current) return;\n committedRef.current = next;\n if (!focused) setText(next);\n }, [value, focused]);\n\n const parsed = useMemo(() => parseQueryWithDiagnostics(text), [text]);\n\n const commit = useCallback(\n (nextText: string) => {\n const nextQuery = parseQueryWithDiagnostics(nextText).query;\n committedRef.current = formatQuery(nextQuery);\n onChange(nextQuery);\n },\n [onChange],\n );\n\n const suggestions = useSuggestions(text, parsed.trailing, fields);\n\n const applySuggestion = useCallback(\n (suggestion: Suggestion) => {\n const nextText = suggestion.replace(text);\n setText(nextText);\n if (suggestion.kind === \"value\") commit(nextText);\n inputRef.current?.focus();\n setHighlighted(0);\n },\n [text, commit],\n );\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (suggestions.length > 0 && focused) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setHighlighted((current) => (current + 1) % suggestions.length);\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setHighlighted(\n (current) => (current - 1 + suggestions.length) % suggestions.length,\n );\n return;\n }\n if (event.key === \"Tab\" || (event.key === \"Enter\" && highlighted > 0)) {\n event.preventDefault();\n applySuggestion(suggestions[highlighted]!);\n return;\n }\n }\n if (event.key === \"Enter\") {\n event.preventDefault();\n commit(text);\n return;\n }\n if (event.key === \"Escape\") {\n setText(committedRef.current);\n inputRef.current?.blur();\n }\n };\n\n const showSuggestions = focused && suggestions.length > 0;\n\n return (\n <div\n className={cn(\"relative flex min-w-0 flex-col gap-1.5\", className)}\n data-opt-id=\"JSVZ1\"\n data-opt-slug=\"query-bar.QueryBar\"\n >\n <div\n className={cn(\n \"bg-surface flex h-9 items-center gap-2 rounded-md border px-2.5\",\n OPT_BORDER,\n \"focus-within:border-accent transition-colors\",\n disabled && \"opacity-60\",\n )}\n >\n <Search className=\"text-text-tertiary size-4 shrink-0\" aria-hidden />\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={showSuggestions}\n aria-controls=\"query-bar-suggestions\"\n aria-autocomplete=\"list\"\n aria-label={labels.ariaLabel}\n placeholder={labels.placeholder}\n disabled={disabled}\n className={cn(\n \"text-text-primary placeholder:text-text-tertiary min-w-0 flex-1\",\n // The focus ring lives on the wrapper (`focus-within:border-accent`),\n // so the input drawing its own would double it.\n \"bg-transparent font-mono text-sm outline-none focus-visible:outline-none\",\n )}\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n setHighlighted(0);\n if (live) commit(event.target.value);\n }}\n onFocus={() => setFocused(true)}\n onBlur={() => {\n // Let a click on a suggestion land before the list unmounts.\n window.setTimeout(() => setFocused(false), 120);\n if (!live) commit(text);\n }}\n onKeyDown={handleKeyDown}\n />\n {text.length > 0 && (\n <button\n type=\"button\"\n aria-label={labels.clear}\n title={labels.clear}\n className={cn(\n \"text-text-tertiary hover:text-text-primary cursor-pointer rounded-sm p-0.5\",\n OPT_FOCUS_VISIBLE,\n )}\n onClick={() => {\n setText(\"\");\n commit(\"\");\n }}\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n\n {showSuggestions && (\n <ul\n id=\"query-bar-suggestions\"\n role=\"listbox\"\n className={cn(\n \"bg-surface-overlay absolute top-10 z-40 max-h-64 w-full overflow-y-auto rounded-md border p-1 shadow-lg\",\n OPT_BORDER,\n )}\n >\n {suggestions.map((suggestion, index) => (\n <li key={`${suggestion.kind}-${suggestion.label}`}>\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={index === highlighted}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between gap-3 rounded px-2 py-1 text-left text-sm\",\n index === highlighted ? \"bg-bg-subtle\" : \"hover:bg-bg-subtle\",\n )}\n onMouseEnter={() => setHighlighted(index)}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => applySuggestion(suggestion)}\n >\n <span className=\"text-text-primary truncate font-mono\">\n {suggestion.label}\n </span>\n {suggestion.hint && (\n <span className=\"text-text-tertiary shrink-0 text-xs\">\n {suggestion.hint}\n </span>\n )}\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {showClauses && value.clauses.length > 0 && (\n <ul className=\"flex flex-wrap items-center gap-1.5\">\n {value.clauses.map((clause, index) => {\n const label = describeClause(clause);\n return (\n <li\n key={`${label}-${index}`}\n className={cn(\n \"bg-bg-subtle text-text-secondary flex items-center gap-1 rounded px-1.5 py-0.5 text-xs\",\n clause.negated && \"text-danger-fg\",\n )}\n >\n <span className=\"truncate\">{label}</span>\n <button\n type=\"button\"\n aria-label={labels.removeClause(label)}\n className=\"hover:text-text-primary cursor-pointer\"\n onClick={() => {\n const next = removeClause(value, index);\n setText(formatQuery(next));\n committedRef.current = formatQuery(next);\n onChange(next);\n }}\n >\n <X className=\"size-3\" aria-hidden />\n </button>\n </li>\n );\n })}\n </ul>\n )}\n\n {parsed.diagnostics.length > 0 && (\n <QueryDiagnostics diagnostics={parsed.diagnostics} />\n )}\n\n {labels.syntaxHint && !showSuggestions && (\n <p className=\"text-text-tertiary text-xs\">{labels.syntaxHint}</p>\n )}\n </div>\n );\n}\n\nQueryBar.displayName = \"QueryBar\";\n\nfunction QueryDiagnostics({ diagnostics }: { diagnostics: QueryDiagnostic[] }) {\n return (\n <ul className=\"text-warning-fg flex flex-col gap-0.5 text-xs\">\n {diagnostics.map((diagnostic, index) => (\n <li key={`${diagnostic.at}-${index}`}>\n <code className=\"font-mono\">{diagnostic.text}</code> —{\" \"}\n {diagnostic.message}\n </li>\n ))}\n </ul>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Completions */\n/* ------------------------------------------------------------------ */\n\ninterface Suggestion {\n kind: \"field\" | \"value\";\n label: string;\n hint?: string;\n /** Rewrite the whole input, since only the last token is being completed. */\n replace: (text: string) => string;\n}\n\n/**\n * What to offer, based on the token under the cursor.\n *\n * Completing fields is the part that makes the syntax discoverable at all —\n * nobody guesses that `utm_source` is a field they can filter on. Once the\n * field is chosen, its known values are the second half of the same guess.\n */\nfunction useSuggestions(\n text: string,\n trailing: { field: string; operator: string; value: string } | null,\n fields: QueryField[],\n): Suggestion[] {\n return useMemo(() => {\n const lastSpace = text.lastIndexOf(\" \");\n const head = lastSpace === -1 ? \"\" : text.slice(0, lastSpace + 1);\n const token = text.slice(lastSpace + 1);\n\n if (trailing) {\n const field = fields.find(\n (candidate) => candidate.name === trailing.field,\n );\n const values = field?.values ?? [];\n const typed = trailing.value.toLowerCase();\n return values\n .filter((value) => value.toLowerCase().includes(typed))\n .slice(0, MAX_SUGGESTIONS)\n .map((value) => ({\n kind: \"value\" as const,\n label: `${trailing.field}:${value}`,\n replace: () =>\n `${head}${trailing.field}:${/[\\s\"()]/.test(value) ? `\"${value}\"` : value} `,\n }));\n }\n\n const bare = token.replace(/^-/, \"\").toLowerCase();\n if (bare.length === 0) return [];\n return fields\n .filter((field) => field.name.toLowerCase().includes(bare))\n .slice(0, MAX_SUGGESTIONS)\n .map((field) => ({\n kind: \"field\" as const,\n label: `${field.name}:`,\n hint: field.hint,\n replace: () =>\n `${head}${token.startsWith(\"-\") ? \"-\" : \"\"}${field.name}:`,\n }));\n }, [text, trailing, fields]);\n}\n","\"use client\";\n\nimport { Columns3, Minus, Plus, Search } from \"lucide-react\";\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_TEXT_TERTIARY } from \"../lib/styles\";\nimport { Spinner } from \"../core/spinner\";\n\n/** One value a field takes, with how often. */\nexport interface FieldValueCount {\n value: string;\n count: number;\n /** Share of the sampled rows, 0–1. Derived from counts when omitted. */\n share?: number;\n}\n\n/** A field the reader can inspect, filter on, or put in the table. */\nexport interface FieldSummary {\n name: string;\n /** Shown beside the name — \"string\", \"number\", a source, whatever separates them. */\n type?: string;\n /** Grouping header. Fields with the same group are listed together. */\n group?: string;\n /** True when the field is currently a column. */\n inTable?: boolean;\n /** False for fields that exist but cannot be a column (a nested object, say). */\n columnable?: boolean;\n}\n\n/** Localized strings for the field sidebar. */\nexport interface FieldSidebarLabels {\n heading?: string;\n searchPlaceholder?: string;\n searchLabel?: string;\n empty?: string;\n addColumn?: (field: string) => string;\n removeColumn?: (field: string) => string;\n filterFor?: (value: string) => string;\n filterOut?: (value: string) => string;\n topValues?: (count: number) => string;\n noValues?: string;\n loadingValues?: string;\n otherGroup?: string;\n}\n\nconst defaultLabels: Required<FieldSidebarLabels> = {\n heading: \"Fields\",\n searchPlaceholder: \"Find a field\",\n searchLabel: \"Find a field\",\n empty: \"No fields match.\",\n addColumn: (field) => `Show ${field} as a column`,\n removeColumn: (field) => `Remove the ${field} column`,\n filterFor: (value) => `Filter for ${value}`,\n filterOut: (value) => `Filter out ${value}`,\n topValues: (count) => `Top ${count} values`,\n noValues: \"No values in this range.\",\n loadingValues: \"Counting…\",\n otherGroup: \"Other\",\n};\n\nexport interface FieldSidebarProps {\n fields: FieldSummary[];\n /** The field whose values are open. Controlled so the caller can fetch them. */\n expandedField?: string | null;\n onExpandedFieldChange?: (field: string | null) => void;\n /** Values for the expanded field. The caller fetches them on expansion. */\n values?: FieldValueCount[];\n valuesLoading?: boolean;\n /** Rows the counts were taken over, for the reader to judge the sample by. */\n sampledRows?: number;\n\n onToggleColumn?: (field: string, next: boolean) => void;\n onFilter?: (\n field: string,\n value: string,\n intent: \"include\" | \"exclude\",\n ) => void;\n\n header?: ReactNode;\n className?: string;\n labels?: FieldSidebarLabels;\n}\n\n/**\n * FieldSidebar — what is in this data, and what does it contain.\n *\n * Without it, a log answers only the questions you already knew to ask: you can\n * filter on `utm_source` if you remember it exists, and you can read a value if\n * you open a row and scroll to it. Listing the fields turns that around — the\n * data tells the reader what is available — and the value counts answer the\n * question that actually follows (\"mostly which?\") before they have to run a\n * query to find out.\n *\n * Three actions live here because they are the three things people do next:\n * put the field in the table, keep only rows with a value, drop rows with it.\n *\n * @example\n * ```tsx\n * <FieldSidebar\n * fields={fields}\n * expandedField={openField}\n * onExpandedFieldChange={setOpenField}\n * values={valuesQuery.data}\n * valuesLoading={valuesQuery.isLoading}\n * onToggleColumn={(field, next) => setColumns(...)}\n * onFilter={(field, value, intent) => setQuery(applyCellAction(query, { field, value, intent }))}\n * />\n * ```\n */\nexport function FieldSidebar({\n fields,\n expandedField = null,\n onExpandedFieldChange,\n values,\n valuesLoading = false,\n sampledRows,\n onToggleColumn,\n onFilter,\n header,\n className,\n labels: customLabels,\n}: FieldSidebarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [search, setSearch] = useState(\"\");\n\n const groups = useMemo(() => {\n const needle = search.trim().toLowerCase();\n const matching = needle\n ? fields.filter((field) => field.name.toLowerCase().includes(needle))\n : fields;\n\n const byGroup = new Map<string, FieldSummary[]>();\n for (const field of matching) {\n const key = field.group ?? \"\";\n const bucket = byGroup.get(key);\n if (bucket) bucket.push(field);\n else byGroup.set(key, [field]);\n }\n return [...byGroup.entries()];\n }, [fields, search]);\n\n const total = useMemo(\n () => (values ?? []).reduce((sum, entry) => sum + entry.count, 0),\n [values],\n );\n\n return (\n <aside\n className={cn(\"flex min-h-0 flex-col\", className)}\n aria-label={labels.heading}\n data-opt-id=\"17D4Y\"\n data-opt-slug=\"field-sidebar.FieldSidebar\"\n >\n {header}\n\n <div\n className={cn(\n \"flex items-center gap-2 border-b px-3 py-2\",\n \"focus-within:border-accent transition-colors\",\n OPT_BORDER,\n )}\n >\n <Search className=\"text-text-tertiary size-3.5 shrink-0\" aria-hidden />\n <input\n type=\"search\"\n aria-label={labels.searchLabel}\n placeholder={labels.searchPlaceholder}\n className={cn(\n \"text-text-primary placeholder:text-text-tertiary min-w-0 flex-1\",\n // Focus is shown on the row's border; a second ring inside it reads\n // as two controls.\n \"bg-transparent text-sm outline-none focus-visible:outline-none\",\n )}\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n />\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {groups.length === 0 ? (\n <p className={cn(OPT_TEXT_TERTIARY, \"px-3 py-4 text-xs\")}>\n {labels.empty}\n </p>\n ) : (\n groups.map(([group, groupFields]) => (\n <section key={group || \"__ungrouped__\"}>\n {group && (\n <h4\n className={cn(\n OPT_TEXT_TERTIARY,\n \"px-3 pt-3 pb-1 text-[11px] font-medium tracking-wide uppercase\",\n )}\n >\n {group}\n </h4>\n )}\n <ul>\n {groupFields.map((field) => (\n <FieldRow\n key={field.name}\n field={field}\n expanded={expandedField === field.name}\n onToggleExpanded={() =>\n onExpandedFieldChange?.(\n expandedField === field.name ? null : field.name,\n )\n }\n onToggleColumn={onToggleColumn}\n labels={labels}\n >\n {expandedField === field.name && (\n <FieldValues\n values={values}\n loading={valuesLoading}\n total={total}\n sampledRows={sampledRows}\n onFilter={\n onFilter\n ? (value, intent) =>\n onFilter(field.name, value, intent)\n : undefined\n }\n labels={labels}\n />\n )}\n </FieldRow>\n ))}\n </ul>\n </section>\n ))\n )}\n </div>\n </aside>\n );\n}\n\nFieldSidebar.displayName = \"FieldSidebar\";\n\n/* ------------------------------------------------------------------ */\n/* Internals */\n/* ------------------------------------------------------------------ */\n\nfunction FieldRow({\n field,\n expanded,\n onToggleExpanded,\n onToggleColumn,\n labels,\n children,\n}: {\n field: FieldSummary;\n expanded: boolean;\n onToggleExpanded: () => void;\n onToggleColumn?: (field: string, next: boolean) => void;\n labels: Required<FieldSidebarLabels>;\n children?: ReactNode;\n}) {\n const columnable = field.columnable ?? true;\n return (\n <li>\n <div className=\"hover:bg-bg-subtle group/field flex items-center gap-1.5 px-3 py-1\">\n <button\n type=\"button\"\n className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-left\"\n aria-expanded={expanded}\n onClick={onToggleExpanded}\n >\n {field.type && (\n <span\n className={cn(\n OPT_TEXT_TERTIARY,\n \"w-8 shrink-0 truncate font-mono text-[10px] uppercase\",\n )}\n >\n {field.type}\n </span>\n )}\n <span className=\"text-text-primary truncate font-mono text-xs\">\n {field.name}\n </span>\n </button>\n\n {onToggleColumn && columnable && (\n <button\n type=\"button\"\n className={cn(\n \"cursor-pointer rounded-sm p-0.5\",\n field.inTable\n ? \"text-accent\"\n : \"text-text-tertiary hover:text-text-primary opacity-0 group-hover/field:opacity-100 focus-visible:opacity-100\",\n )}\n aria-label={\n field.inTable\n ? labels.removeColumn(field.name)\n : labels.addColumn(field.name)\n }\n title={\n field.inTable\n ? labels.removeColumn(field.name)\n : labels.addColumn(field.name)\n }\n aria-pressed={field.inTable ?? false}\n onClick={() => onToggleColumn(field.name, !field.inTable)}\n >\n <Columns3 className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n {children}\n </li>\n );\n}\n\n/**\n * The distribution, as bars.\n *\n * A count alone (\"342\") means nothing without the denominator, and a reader\n * scanning for \"what is this field mostly\" reads the bar before the number.\n * The sample size is stated rather than implied — these are the top values in\n * the rows that were counted, not in all of history, and a chart that hides\n * that invites the wrong conclusion.\n */\nfunction FieldValues({\n values,\n loading,\n total,\n sampledRows,\n onFilter,\n labels,\n}: {\n values?: FieldValueCount[];\n loading: boolean;\n total: number;\n sampledRows?: number;\n onFilter?: (value: string, intent: \"include\" | \"exclude\") => void;\n labels: Required<FieldSidebarLabels>;\n}) {\n if (loading) {\n return (\n <p\n className={cn(\n OPT_TEXT_TERTIARY,\n \"flex items-center gap-2 px-3 pb-2 text-xs\",\n )}\n >\n <Spinner size=\"sm\" aria-hidden />\n {labels.loadingValues}\n </p>\n );\n }\n\n if (!values || values.length === 0) {\n return (\n <p className={cn(OPT_TEXT_TERTIARY, \"px-3 pb-2 text-xs\")}>\n {labels.noValues}\n </p>\n );\n }\n\n const denominator = sampledRows ?? total;\n\n return (\n <div className=\"flex flex-col gap-1 px-3 pt-1 pb-2\">\n <p className={cn(OPT_TEXT_TERTIARY, \"text-[11px]\")}>\n {labels.topValues(values.length)}\n {sampledRows ? ` · ${sampledRows.toLocaleString()}` : \"\"}\n </p>\n {values.map((entry) => {\n const share =\n entry.share ?? (denominator > 0 ? entry.count / denominator : 0);\n return (\n <div key={entry.value} className=\"group/value flex flex-col gap-0.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span\n className=\"text-text-secondary min-w-0 flex-1 truncate font-mono text-[11px]\"\n title={entry.value}\n >\n {entry.value || \"—\"}\n </span>\n <span\n className={cn(\n OPT_TEXT_TERTIARY,\n \"shrink-0 text-[11px] tabular-nums\",\n )}\n >\n {Math.round(share * 100)}%\n </span>\n {onFilter && (\n <span className=\"hidden shrink-0 items-center gap-0.5 group-hover/value:flex focus-within:flex\">\n <button\n type=\"button\"\n className=\"text-text-tertiary hover:text-text-primary cursor-pointer\"\n aria-label={labels.filterFor(entry.value)}\n title={labels.filterFor(entry.value)}\n onClick={() => onFilter(entry.value, \"include\")}\n >\n <Plus className=\"size-3\" aria-hidden />\n </button>\n <button\n type=\"button\"\n className=\"text-text-tertiary hover:text-text-primary cursor-pointer\"\n aria-label={labels.filterOut(entry.value)}\n title={labels.filterOut(entry.value)}\n onClick={() => onFilter(entry.value, \"exclude\")}\n >\n <Minus className=\"size-3\" aria-hidden />\n </button>\n </span>\n )}\n </div>\n <div className=\"bg-bg-muted h-1 w-full overflow-hidden rounded-full\">\n <div\n className=\"bg-accent h-full rounded-full\"\n style={{ width: `${Math.max(2, Math.round(share * 100))}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"field-sidebar-BYD_UIjG.js","names":["PrimCommandRoot","DialogRoot","DialogPanel","DialogHeading","DialogDescription","CommandInput","PrimCommandInput","CommandList","PrimCommandList","CommandEmpty","PrimCommandEmpty","CommandGroup","PrimCommandGroup","CommandSeparator","PrimCommandSeparator","CommandItem","PrimCommandItem","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","defaultLabels","defaultLabels","ComboboxRoot","ComboboxInput","ComboboxPopover","ComboboxItem","defaultLabels","SelectRoot","SelectLabel","SelectTrigger","SelectPopover","SelectItem","defaultLabels","MenuRoot","MenuTrigger","MenuButtonArrow","MenuPopover","MenuSeparator","MenuItemCheckbox","MenuItemRadio","MenuItem","MenubarRoot","MenubarContainer","defaultLabels","defaultLabels","TooltipProvider","TooltipAnchor","ToolbarButton","Tooltip","ToolbarRoot","ToolbarContainer","ToolbarSeparator","defaultLabels","TabsRoot","TabList","Tab","TabPanel","defaultLabels","DisclosureRoot","DisclosureTrigger","DisclosureContent","defaultLabels","FormRoot","FormLabel","FormError","FormRadioGroup","FormRadio","FormCheckbox","FormSwitch","FormInput","FormSubmit","statusBadge","statusLabel","ComboboxRoot","ComboboxInput","ComboboxPopover","ComboboxItem","defaultLabels","DisclosureProvider","Disclosure","DisclosureContent","defaultLabels","SelectRoot","SelectLabel","SelectTrigger","SelectPopover","SelectItem","defaultLabels","Fragment","defaultLabels","defaultLabels","defaultLabels","PopoverRoot","PopoverTrigger","PopoverContent","SelectRoot","SelectTrigger","SelectPopover","SelectItem","defaultLabels","defaultLabels","defaultLabels"],"sources":["../src/core/command.tsx","../src/shells/command-palette.tsx","../src/shells/command-palette-trigger.tsx","../src/shells/dashboard-grid.tsx","../src/shells/search-combobox.tsx","../src/shells/status-select.tsx","../src/shells/app-menubar.tsx","../src/shells/sidebar-nav.tsx","../src/shells/editor-toolbar.tsx","../src/shells/content-tabs.tsx","../src/shells/faq-accordion.tsx","../src/shells/settings-form.tsx","../src/shells/deployment-timeline.tsx","../src/shells/project-switcher.tsx","../src/shells/env-panel.tsx","../src/shells/branch-select.tsx","../src/shells/domain-table.tsx","../src/shells/data-table.tsx","../src/shells/notification-toast.tsx","../src/shells/failure-list.tsx","../src/shells/key-value-editor.tsx","../src/shells/workflow-canvas.tsx","../src/lib/use-auto-refresh.ts","../src/shells/time-range-control.tsx","../src/shells/time-series-panel.tsx","../src/shells/log-table.tsx","../src/lib/query/query-ast.ts","../src/lib/query/query-parse.ts","../src/lib/query/query-format.ts","../src/shells/query-bar.tsx","../src/shells/field-sidebar.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { SearchIcon } from \"lucide-react\";\nimport {\n CommandRoot as PrimCommandRoot,\n CommandInput as PrimCommandInput,\n CommandList as PrimCommandList,\n CommandEmpty as PrimCommandEmpty,\n CommandGroup as PrimCommandGroup,\n CommandSeparator as PrimCommandSeparator,\n CommandItem as PrimCommandItem,\n} from \"@reopt-ai/opt-ui-primitives\";\nimport type {\n CommandRootProps as PrimCommandRootProps,\n CommandInputProps as PrimCommandInputProps,\n CommandListProps as PrimCommandListProps,\n CommandEmptyProps as PrimCommandEmptyProps,\n CommandGroupProps as PrimCommandGroupProps,\n CommandSeparatorProps as PrimCommandSeparatorProps,\n CommandItemProps as PrimCommandItemProps,\n} from \"@reopt-ai/opt-ui-primitives\";\nimport { cn } from \"../lib/cn\";\nimport {\n DialogRoot,\n DialogPanel,\n DialogHeading,\n DialogDescription,\n} from \"./dialog\";\n\n/* ─── Command (root) ─── */\n\n/** Renders the `Command` component. */\nexport function Command({ className, ...props }: PrimCommandRootProps) {\n return (\n <PrimCommandRoot\n className={cn(\n \"bg-surface text-text-primary flex w-full flex-col overflow-hidden rounded-xl\",\n className,\n )}\n {...props}\n data-opt-id=\"4FYBW\"\n data-opt-slug=\"command.Command\"\n />\n );\n}\n\n/* ─── CommandDialog ─── */\n\n/** Props for the `CommandDialog` component. */\nexport interface CommandDialogProps {\n /** Open state. */\n open: boolean;\n /** Open state setter. */\n onOpenChange: (open: boolean) => void;\n /** Accessible title (visually hidden by default). */\n title?: string;\n /** Accessible description (visually hidden by default). */\n description?: string;\n /** Optional className for the dialog panel. */\n className?: string;\n /** Optional className for the inner Command root. */\n commandClassName?: string;\n /** Filter behaviour passed through to the inner Command root. */\n shouldFilter?: PrimCommandRootProps[\"shouldFilter\"];\n filter?: PrimCommandRootProps[\"filter\"];\n children: ReactNode;\n}\n\n/** Renders a Command in a dialog overlay, à la Cmd+K palette. */\nexport function CommandDialog({\n open,\n onOpenChange,\n title = \"Command Palette\",\n description = \"검색 후 Enter 또는 클릭으로 명령을 실행하세요.\",\n className,\n commandClassName,\n shouldFilter,\n filter,\n children,\n}: CommandDialogProps) {\n return (\n <DialogRoot\n open={open}\n onOpenChange={onOpenChange}\n data-opt-id=\"DVRSX\"\n data-opt-slug=\"command.CommandDialog\"\n >\n <DialogPanel\n className={cn(\n \"top-[20%] left-1/2 -translate-x-1/2\",\n \"w-full max-w-lg overflow-hidden p-0 shadow-2xl\",\n className,\n )}\n >\n <DialogHeading className=\"sr-only\">{title}</DialogHeading>\n <DialogDescription className=\"sr-only\">{description}</DialogDescription>\n <Command\n shouldFilter={shouldFilter}\n filter={filter}\n className={commandClassName}\n >\n {children}\n </Command>\n </DialogPanel>\n </DialogRoot>\n );\n}\n\n/* ─── CommandInput ─── */\n\n/** Props for the `CommandInput` component. */\nexport interface CommandInputProps extends PrimCommandInputProps {\n /** Trailing content rendered on the right side (e.g. ESC kbd). */\n trailing?: ReactNode;\n /** Optional className for the input wrapper. */\n wrapperClassName?: string;\n}\n\n/** Renders the `CommandInput` component with a leading search icon. */\nexport function CommandInput({\n className,\n trailing,\n wrapperClassName,\n placeholder,\n \"aria-label\": ariaLabel,\n ...props\n}: CommandInputProps) {\n return (\n <div\n data-slot=\"command-input-wrapper\"\n className={cn(\n \"border-border-subtle gap-element flex h-12 items-center border-b px-3\",\n wrapperClassName,\n )}\n data-opt-id=\"HB1K3\"\n data-opt-slug=\"command.CommandInput\"\n >\n <SearchIcon aria-hidden className=\"text-text-tertiary size-4 shrink-0\" />\n <PrimCommandInput\n className={cn(\n // cmdk 컨벤션 — input 자체는 ring 없이 자연스러운 검색 경험.\n // 포커스 표시는 wrapper(border-b)가 시각적 컨텍스트로 제공.\n \"text-text-primary placeholder:text-text-tertiary flex h-full w-full bg-transparent text-sm outline-none focus-visible:ring-0 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n placeholder={placeholder}\n aria-label={\n ariaLabel ??\n (typeof placeholder === \"string\" ? placeholder : \"Command search\")\n }\n {...props}\n />\n {trailing}\n </div>\n );\n}\n\n/* ─── CommandList ─── */\n\n/** Renders the `CommandList` component. */\nexport function CommandList({\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: PrimCommandListProps) {\n return (\n <PrimCommandList\n className={cn(\n \"max-h-80 scroll-py-1 overflow-x-hidden overflow-y-auto p-1\",\n className,\n )}\n aria-label={ariaLabel ?? \"Commands\"}\n {...props}\n data-opt-id=\"NPXC5\"\n data-opt-slug=\"command.CommandList\"\n />\n );\n}\n\n/* ─── CommandEmpty ─── */\n\n/** Renders the `CommandEmpty` component. */\nexport function CommandEmpty({ className, ...props }: PrimCommandEmptyProps) {\n return (\n <PrimCommandEmpty\n className={cn(\"text-text-tertiary py-6 text-center text-sm\", className)}\n {...props}\n data-opt-id=\"A8BZM\"\n data-opt-slug=\"command.CommandEmpty\"\n />\n );\n}\n\n/* ─── CommandGroup ─── */\n\n/** Renders the `CommandGroup` component with an optional heading. */\nexport function CommandGroup({\n className,\n heading,\n ...props\n}: PrimCommandGroupProps) {\n return (\n <PrimCommandGroup\n heading={\n heading != null ? (\n <div className=\"text-text-tertiary px-2 py-1.5 text-xs font-medium\">\n {heading}\n </div>\n ) : undefined\n }\n className={cn(\"py-1\", className)}\n {...props}\n data-opt-id=\"JPK1Y\"\n data-opt-slug=\"command.CommandGroup\"\n />\n );\n}\n\n/* ─── CommandSeparator ─── */\n\n/** Renders the `CommandSeparator` component. */\nexport function CommandSeparator({\n className,\n ...props\n}: PrimCommandSeparatorProps) {\n return (\n <PrimCommandSeparator\n className={cn(\"bg-border-subtle -mx-1 my-1 h-px\", className)}\n {...props}\n data-opt-id=\"10P0E\"\n data-opt-slug=\"command.CommandSeparator\"\n />\n );\n}\n\n/* ─── CommandItem ─── */\n\n/** Renders the `CommandItem` component. */\nexport function CommandItem({ className, ...props }: PrimCommandItemProps) {\n return (\n <PrimCommandItem\n className={cn(\n \"text-text-primary flex cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-sm select-none\",\n \"data-[active-item]:bg-accent data-[active-item]:text-accent-fg\",\n \"data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n data-opt-id=\"K674W\"\n data-opt-slug=\"command.CommandItem\"\n />\n );\n}\n\n/* ─── CommandShortcut ─── */\n\n/** Renders the `CommandShortcut` component (right-aligned hint). */\nexport function CommandShortcut({\n className,\n ...props\n}: ComponentPropsWithoutRef<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n \"text-text-tertiary ml-auto text-xs tracking-widest\",\n \"data-[active-item]:text-accent-fg/80\",\n className,\n )}\n {...props}\n data-opt-id=\"75CQK\"\n data-opt-slug=\"command.CommandShortcut\"\n />\n );\n}\n","\"use client\";\n\nimport { useMemo, type KeyboardEvent, type ReactNode } from \"react\";\nimport type { CommandDef } from \"../lib/types\";\nimport { Kbd } from \"../core/kbd\";\nimport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n} from \"../core/command\";\nimport { cn } from \"../lib/cn\";\n\n/** Localized labels for the command palette component. */\nexport interface CommandPaletteLabels {\n title?: string;\n description?: string;\n input?: string;\n placeholder?: string;\n list?: string;\n empty?: ReactNode;\n escape?: string;\n}\n\nconst DEFAULT_LABELS: Required<CommandPaletteLabels> = {\n title: \"Command Palette\",\n description: \"검색 후 Enter 또는 클릭으로 명령을 실행하세요.\",\n input: \"명령어 검색\",\n placeholder: \"명령어를 검색하세요...\",\n list: \"명령어 목록\",\n empty: \"결과가 없습니다.\",\n escape: \"ESC\",\n};\n\n/** Props for the command palette component. */\nexport interface CommandPaletteProps {\n commands: Omit<CommandDef, \"action\">[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSelect?: (command: Omit<CommandDef, \"action\">) => void;\n /** Render inline (no dialog overlay). */\n inline?: boolean;\n labels?: CommandPaletteLabels;\n footer?: ReactNode;\n empty?: ReactNode;\n inputTrailing?: ReactNode;\n className?: string;\n}\n\n/** Renders the command palette component. */\nexport function CommandPalette({\n commands,\n open,\n onOpenChange,\n onSelect,\n inline = false,\n labels,\n footer,\n empty,\n inputTrailing,\n className,\n}: CommandPaletteProps) {\n const resolvedLabels = { ...DEFAULT_LABELS, ...labels };\n const hasCommands = commands.length > 0;\n const grouped = useMemo(() => {\n const map = new Map<string, Omit<CommandDef, \"action\">[]>();\n for (const cmd of commands) {\n const list = map.get(cmd.group) ?? [];\n list.push(cmd);\n map.set(cmd.group, list);\n }\n return map;\n }, [commands]);\n\n const handleSelect = (cmdId: string) => {\n const cmd = commands.find((c) => c.id === cmdId);\n if (!cmd) return;\n onSelect?.(cmd);\n onOpenChange(false);\n };\n\n const handleInputKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Escape\" && !inline) {\n // Dialog handles its own Esc; this branch covers the inline-with-Esc case.\n e.preventDefault();\n onOpenChange(false);\n }\n };\n\n const body = (\n <>\n <CommandInput\n aria-label={resolvedLabels.input}\n placeholder={resolvedLabels.placeholder}\n onKeyDown={handleInputKeyDown}\n trailing={\n inputTrailing ??\n (!inline ? <Kbd>{resolvedLabels.escape}</Kbd> : undefined)\n }\n />\n <CommandList aria-label={resolvedLabels.list}>\n <CommandEmpty>{empty ?? resolvedLabels.empty}</CommandEmpty>\n {hasCommands\n ? Array.from(grouped.entries()).map(([group, items]) => (\n <CommandGroup key={group} heading={group}>\n {items.map((cmd) => (\n <CommandItem\n key={cmd.id}\n value={cmd.id}\n keywords={[\n cmd.label,\n cmd.group,\n ...(cmd.shortcut ? [cmd.shortcut] : []),\n ]}\n onSelect={handleSelect}\n >\n <span>{cmd.label}</span>\n {cmd.shortcut && (\n <CommandShortcut>{cmd.shortcut}</CommandShortcut>\n )}\n </CommandItem>\n ))}\n </CommandGroup>\n ))\n : null}\n </CommandList>\n {footer}\n </>\n );\n\n if (inline) {\n if (!open) return null;\n return (\n <Command\n className={cn(\n \"border-border bg-surface w-full max-w-lg border shadow-lg\",\n className,\n )}\n data-opt-id=\"ATTF5\"\n data-opt-slug=\"command-palette.CommandPalette\"\n >\n {body}\n </Command>\n );\n }\n\n return (\n <CommandDialog\n open={open}\n onOpenChange={onOpenChange}\n title={resolvedLabels.title}\n description={resolvedLabels.description}\n className={className}\n data-opt-id=\"ATTF5\"\n data-opt-slug=\"command-palette.CommandPalette\"\n >\n {body}\n </CommandDialog>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { CommandDef } from \"../lib/types\";\nimport { CommandPalette, type CommandPaletteLabels } from \"./command-palette\";\n\n/** Props for the command palette trigger component. */\nexport interface CommandPaletteTriggerProps {\n commands: Omit<CommandDef, \"action\">[];\n onSelect?: (command: Omit<CommandDef, \"action\">) => void;\n labels?: CommandPaletteTriggerLabels;\n}\n\n/** Localized labels for the command palette trigger component. */\nexport type CommandPaletteTriggerLabels = CommandPaletteLabels;\n\n/** Renders the command palette trigger component. */\nexport function CommandPaletteTrigger({\n commands,\n onSelect,\n labels,\n}: CommandPaletteTriggerProps) {\n const [open, setOpen] = useState(false);\n\n const handleKeyDown = useCallback((e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"k\") {\n e.preventDefault();\n setOpen(true);\n }\n }, []);\n\n useEffect(() => {\n if (commands.length === 0) return;\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [commands.length, handleKeyDown]);\n\n if (commands.length === 0) return null;\n\n return (\n <CommandPalette\n commands={commands}\n open={open}\n onOpenChange={setOpen}\n onSelect={onSelect}\n labels={labels}\n data-opt-id=\"4FCDB\"\n data-opt-slug=\"command-palette-trigger.CommandPaletteTrigger\"\n />\n );\n}\n","import type { CSSProperties } from \"react\";\n\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n CompositeRow,\n} from \"../core/composite-zone\";\nimport { StatCard } from \"../core/stat-card\";\nimport type { StatCard as StatCardType } from \"../lib/types\";\n\n/** Localized labels for the dashboard grid component. */\nexport interface DashboardGridLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<DashboardGridLabels> = {\n ariaLabel: \"대시보드 통계\",\n};\n\nconst MIN_DASHBOARD_COLUMNS = 1;\nconst MAX_DASHBOARD_COLUMNS = 12;\n\nfunction normalizeDashboardColumns(columns: number): number {\n if (!Number.isFinite(columns)) return MIN_DASHBOARD_COLUMNS;\n return Math.min(\n MAX_DASHBOARD_COLUMNS,\n Math.max(MIN_DASHBOARD_COLUMNS, Math.floor(columns)),\n );\n}\n\n/** Props for the dashboard grid component. */\nexport interface DashboardGridProps {\n stats: StatCardType[];\n columns?: number;\n labels?: DashboardGridLabels;\n}\n\n/** Renders the dashboard grid component. */\nexport function DashboardGrid({\n stats,\n columns = 3,\n labels: customLabels,\n}: DashboardGridProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const columnCount = normalizeDashboardColumns(columns);\n const rowStyle = {\n \"--opt-dashboard-grid-columns\": `repeat(${columnCount}, minmax(0, 1fr))`,\n } as CSSProperties;\n\n const rows: StatCardType[][] = [];\n for (let i = 0; i < stats.length; i += columnCount) {\n rows.push(stats.slice(i, i + columnCount));\n }\n\n return (\n <CompositeProvider\n focusLoop\n focusWrap\n data-opt-id=\"BM7NA\"\n data-opt-slug=\"dashboard-grid.DashboardGrid\"\n >\n <Composite\n role=\"grid\"\n aria-label={labels.ariaLabel}\n className=\"gap-group flex flex-col\"\n >\n {rows.map((row, ri) => (\n <CompositeRow\n key={ri}\n className=\"gap-group grid grid-cols-1 sm:[grid-template-columns:var(--opt-dashboard-grid-columns)]\"\n style={rowStyle}\n >\n {row.map((stat) => (\n <CompositeItem\n key={stat.id}\n className=\"data-[active-item]:ring-ring data-[active-item]:ring-offset-ring-offset data-[focus-visible]:ring-ring data-[focus-visible]:ring-offset-ring-offset rounded-xl outline-none data-[active-item]:ring-2 data-[active-item]:ring-offset-2 data-[focus-visible]:ring-2 data-[focus-visible]:ring-offset-2\"\n render={<div role=\"gridcell\" />}\n >\n <StatCard {...stat} />\n </CompositeItem>\n ))}\n </CompositeRow>\n ))}\n </Composite>\n </CompositeProvider>\n );\n}\n","\"use client\";\n\nimport { matchSorter } from \"match-sorter\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { FormEvent } from \"react\";\nimport {\n ComboboxRoot,\n ComboboxInput,\n ComboboxPopover,\n ComboboxItem,\n ComboboxEmpty,\n} from \"../core/combobox\";\nimport { Spinner } from \"../core/spinner\";\nimport { OPT_TEXT_LABEL } from \"../lib/styles\";\n\n/** Localized labels for the search combobox component. */\nexport interface SearchComboboxLabels {\n noResults?: string;\n loading?: string;\n}\n\nconst defaultLabels: Required<SearchComboboxLabels> = {\n noResults: \"결과가 없습니다.\",\n loading: \"Loading…\",\n};\n\n/** Props for the search combobox component. */\nexport interface SearchComboboxProps {\n items: string[];\n placeholder?: string;\n label?: string;\n onSelect?: (item: string) => void;\n labels?: SearchComboboxLabels;\n /** Enable async search mode */\n async?: boolean;\n /** Async search callback (used when async=true) */\n onSearch?: (query: string) => Promise<string[]>;\n /** Debounce ms for async search */\n debounceMs?: number;\n}\n\n/** Renders the search combobox component. */\nexport function SearchCombobox({\n items,\n placeholder = \"검색...\",\n label = \"검색\",\n onSelect,\n labels: customLabels,\n async: isAsync = false,\n onSearch,\n debounceMs = 300,\n}: SearchComboboxProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const inputId = useId();\n const [query, setQuery] = useState(\"\");\n const [asyncResults, setAsyncResults] = useState<string[]>([]);\n const [loading, setLoading] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n const searchGenerationRef = useRef(0);\n\n const syncMatches = useMemo(() => {\n if (isAsync) return [];\n if (!query) return items;\n return matchSorter(items, query);\n }, [query, items, isAsync]);\n\n const handleInput = (event: FormEvent<HTMLInputElement>) => {\n searchGenerationRef.current += 1;\n setQuery(event.currentTarget.value);\n };\n\n const handleValueChange = (item: string) => {\n searchGenerationRef.current += 1;\n setQuery(item);\n onSelect?.(item);\n };\n\n useEffect(() => {\n const generation = ++searchGenerationRef.current;\n\n if (timerRef.current) clearTimeout(timerRef.current);\n\n if (!isAsync || !onSearch) {\n setLoading(false);\n return;\n }\n\n if (!query) {\n setAsyncResults([]);\n setLoading(false);\n return;\n }\n\n setLoading(true);\n timerRef.current = setTimeout(async () => {\n try {\n const results = await onSearch(query);\n if (searchGenerationRef.current !== generation) {\n return;\n }\n setAsyncResults(results);\n } finally {\n if (searchGenerationRef.current === generation) {\n setLoading(false);\n }\n }\n }, debounceMs);\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, [query, isAsync, onSearch, debounceMs]);\n\n const matches = isAsync ? asyncResults : syncMatches;\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"KH4TQ\"\n data-opt-slug=\"search-combobox.SearchCombobox\"\n >\n <ComboboxRoot onValueChange={handleValueChange}>\n <label htmlFor={inputId} className={OPT_TEXT_LABEL}>\n {label}\n </label>\n <ComboboxInput\n id={inputId}\n placeholder={placeholder}\n className=\"max-w-xs\"\n aria-busy={loading || undefined}\n onInput={handleInput}\n />\n <ComboboxPopover className=\"max-w-xs\">\n {isAsync && loading ? (\n <div\n className=\"text-text-secondary gap-element flex items-center px-3 py-2 text-sm\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size=\"sm\" aria-hidden=\"true\" />\n {labels.loading}\n </div>\n ) : matches.length === 0 ? (\n <ComboboxEmpty>{labels.noResults}</ComboboxEmpty>\n ) : (\n matches.map((item) => (\n <ComboboxItem key={item} value={item}>\n {item}\n </ComboboxItem>\n ))\n )}\n </ComboboxPopover>\n </ComboboxRoot>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { SelectOption } from \"../lib/types\";\nimport {\n SelectRoot,\n SelectLabel,\n SelectTrigger,\n SelectPopover,\n SelectItem,\n} from \"../core/select\";\nimport {\n OPT_TEXT_LABEL,\n OPT_INPUT,\n OPT_FOCUS,\n OPT_SURFACE_POPOVER,\n OPT_ANIMATE_ENTER_EXIT,\n} from \"../lib/styles\";\n\n/** Props for the status select component. */\nexport interface StatusSelectProps {\n options: SelectOption[];\n value?: string;\n onChange?: (value: string) => void;\n label?: string;\n labels?: StatusSelectLabels;\n}\n\n/** Localized labels for the status select component. */\nexport interface StatusSelectLabels {\n selectLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<StatusSelectLabels> = {\n selectLabel: \"상태\",\n emptyMessage: \"사용 가능한 상태 옵션이 없습니다.\",\n};\n\n/** Renders the status select component. */\nexport function StatusSelect({\n options,\n value: controlledValue,\n onChange,\n label,\n labels: customLabels,\n}: StatusSelectProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const resolvedLabel = label ?? labels.selectLabel;\n const [internalValue, setInternalValue] = useState(options[0]?.value ?? \"\");\n const value = controlledValue ?? internalValue;\n const selected = options.find((s) => s.value === value);\n\n if (options.length === 0) {\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"R46E6\"\n data-opt-slug=\"status-select.StatusSelect\"\n >\n <span className={OPT_TEXT_LABEL}>{resolvedLabel}</span>\n <span className=\"text-text-tertiary text-sm\">\n {labels.emptyMessage}\n </span>\n </div>\n );\n }\n\n const handleChange = (v: string | string[]) => {\n const next = Array.isArray(v) ? (v[0] ?? \"\") : v;\n if (onChange) onChange(next);\n else setInternalValue(next);\n };\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"R46E6\"\n data-opt-slug=\"status-select.StatusSelect\"\n >\n <SelectRoot value={value} onValueChange={handleChange}>\n <SelectLabel className={OPT_TEXT_LABEL}>{resolvedLabel}</SelectLabel>\n <SelectTrigger\n className={`${OPT_INPUT} max-w-xs items-center justify-between ${OPT_FOCUS}`}\n >\n <span className=\"gap-element flex items-center\">\n {selected?.color && (\n <span className={`h-2 w-2 rounded-full ${selected.color}`} />\n )}\n {selected?.label}\n </span>\n <svg\n className=\"text-text-tertiary h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </SelectTrigger>\n <SelectPopover\n className={`${OPT_SURFACE_POPOVER} ${OPT_ANIMATE_ENTER_EXIT} max-w-xs`}\n >\n {options.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.color && (\n <span className={`h-2 w-2 rounded-full ${option.color}`} />\n )}\n {option.label}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n </div>\n );\n}\n","\"use client\";\n\nimport type { MenuDef } from \"../lib/types\";\nimport { Kbd } from \"../core/kbd\";\nimport {\n MenubarRoot,\n MenubarContainer,\n MenuRoot,\n MenuTrigger,\n MenuButtonArrow,\n MenuPopover,\n MenuItem,\n MenuItemCheckbox,\n MenuItemRadio,\n MenuSeparator,\n} from \"../core/menu\";\n\n/** Props for the app menubar component. */\nexport interface AppMenubarProps {\n menus: MenuDef[];\n labels?: AppMenubarLabels;\n}\n\n/** Localized labels for the app menubar component. */\nexport interface AppMenubarLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<AppMenubarLabels> = {\n ariaLabel: \"Application menu\",\n};\n\nfunction MenuSection({ menu }: { menu: MenuDef }) {\n return (\n <MenuRoot>\n <MenuTrigger>\n {menu.label}\n <MenuButtonArrow />\n </MenuTrigger>\n <MenuPopover>\n {menu.items.map((item, i) => {\n if (item.type === \"separator\") {\n return <MenuSeparator key={`sep-${i}`} />;\n }\n if (item.type === \"checkbox\") {\n return (\n <MenuItemCheckbox\n key={item.id}\n name={item.name ?? item.id}\n value={item.value ?? item.id}\n checked={item.checked}\n onChange={item.onChange}\n >\n <span className=\"gap-element flex items-center\">\n <span className=\"w-4 text-center\">\n {item.checked ? \"✓\" : \"\"}\n </span>\n {item.label}\n </span>\n </MenuItemCheckbox>\n );\n }\n if (item.type === \"radio\") {\n return (\n <MenuItemRadio\n key={item.id}\n name={item.name ?? \"\"}\n value={item.value ?? \"\"}\n checked={item.checked}\n onChange={item.onChange}\n >\n <span className=\"gap-element flex items-center\">\n <span className=\"w-4 text-center\">\n {item.checked ? \"●\" : \"\"}\n </span>\n {item.label}\n </span>\n </MenuItemRadio>\n );\n }\n return (\n <MenuItem key={item.id} onClick={item.onClick}>\n <span>{item.label}</span>\n {item.shortcut && <Kbd>{item.shortcut}</Kbd>}\n </MenuItem>\n );\n })}\n </MenuPopover>\n </MenuRoot>\n );\n}\n\n/** Renders the app menubar component. */\nexport function AppMenubar({ menus, labels: customLabels }: AppMenubarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n if (menus.length === 0) return null;\n\n return (\n <MenubarRoot data-opt-id=\"BGKHW\" data-opt-slug=\"app-menubar.AppMenubar\">\n <MenubarContainer aria-label={labels.ariaLabel}>\n {menus.map((menu) => (\n <MenuSection key={menu.id} menu={menu} />\n ))}\n </MenubarContainer>\n </MenubarRoot>\n );\n}\n\nAppMenubar.displayName = \"AppMenubar\";\n","\"use client\";\n\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport { useEffect, useState } from \"react\";\nimport type { NavItemDef } from \"../lib/types\";\nimport { cn } from \"../lib/cn\";\n\nconst NAV_ID_PREFIX = \"sidebar-nav-\";\n\nfunction domId(id: string) {\n return `${NAV_ID_PREFIX}${id}`;\n}\n\n// 섹션별 스타일 정의 (한글/영문 모두 지원)\nconst sectionStyles: Record<string, string> = {\n // 한글 키\n 시작하기: \"text-accent\",\n \"핵심 개념\": \"text-info-fg\",\n 구축·운영: \"text-success-fg\",\n 도구: \"text-warning-fg\",\n DataGrid: \"text-accent\",\n \"컴포넌트 · Core\": \"text-accent\",\n \"컴포넌트 · Visuals\": \"text-success-fg\",\n \"컴포넌트 · Shells\": \"text-warning-fg\",\n \"컴포넌트 · Surfaces\": \"text-info-fg\",\n \"기본 컴포넌트\": \"text-accent\",\n \"블록 컴포넌트\": \"text-info-fg\",\n \"조합 컴포넌트\": \"text-warning-fg\",\n 템플릿: \"text-text-tertiary\",\n 릴리즈: \"text-text-tertiary\",\n // 영문 키 (하위 호환)\n Primitives: \"text-accent\",\n Blocks: \"text-info-fg\",\n Compositions: \"text-warning-fg\",\n Templates: \"text-text-tertiary\",\n};\n\nconst defaultSectionStyle = \"text-text-secondary\";\n\n/** Localized labels for the sidebar nav component. */\nexport interface SidebarNavLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<SidebarNavLabels> = {\n ariaLabel: \"문서 네비게이션\",\n};\n\n/** Props for the sidebar nav component. */\nexport interface SidebarNavProps {\n items: NavItemDef[];\n labels?: SidebarNavLabels;\n}\n\n/** Renders the sidebar nav component. */\nexport function SidebarNav({ items, labels: customLabels }: SidebarNavProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const pathname = usePathname();\n const activeItem = items.find((item) => item.href === pathname);\n const [activeId, setActiveId] = useState<string | null | undefined>(\n activeItem ? domId(activeItem.id) : undefined,\n );\n\n useEffect(() => {\n const match = items.find((item) => item.href === pathname);\n if (match) {\n setActiveId(domId(match.id));\n }\n }, [pathname, items]);\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <CompositeProvider\n focusLoop\n orientation=\"vertical\"\n activeId={activeId}\n onActiveIdChange={setActiveId}\n data-opt-id=\"1FZNH\"\n data-opt-slug=\"sidebar-nav.SidebarNav\"\n >\n <Composite\n role=\"navigation\"\n aria-label={labels.ariaLabel}\n className=\"flex flex-col\"\n >\n {items.map((item, index) => {\n const isSelected = pathname === item.href;\n const isFirstItem = index === 0;\n const sectionTextStyle = item.sectionLabel\n ? (sectionStyles[item.sectionLabel] ?? defaultSectionStyle)\n : defaultSectionStyle;\n\n return (\n <div key={item.id}>\n {/* Section Header */}\n {item.separator && (\n <div className={cn(\"mb-2 pt-2\", !isFirstItem && \"mt-7\")}>\n <span\n className={cn(\n \"px-2 text-[11px] font-semibold tracking-wider uppercase\",\n sectionTextStyle,\n )}\n >\n {item.sectionLabel ?? \"\"}\n </span>\n </div>\n )}\n\n {/* Nav Item */}\n <CompositeItem\n id={domId(item.id)}\n render={\n <Link\n href={item.href}\n className={cn(\n // Base styles\n \"group relative block rounded-md px-2 py-1.5 text-[13px] leading-snug outline-none\",\n \"transition-all duration-150\",\n\n // Default state\n !isSelected && [\n \"text-text-secondary\",\n // Hover\n \"hover:bg-bg-subtle hover:text-text-primary\",\n ],\n\n // Selected (current page)\n isSelected && [\n \"bg-bg-subtle text-text-primary font-medium\",\n ],\n\n // Keyboard navigation focus (roving tabindex active)\n \"data-[active-item]:bg-accent-subtle data-[active-item]:text-accent\",\n\n // Focus visible (actual keyboard focus indicator)\n \"data-[focus-visible]:ring-ring data-[focus-visible]:ring-2\",\n \"data-[focus-visible]:ring-offset-ring-offset data-[focus-visible]:ring-offset-2\",\n\n // Combined: selected + keyboard active\n isSelected && [\n \"data-[active-item]:bg-accent-subtle data-[active-item]:text-accent\",\n ],\n )}\n />\n }\n >\n {/* Left indicator bar */}\n <span\n className={cn(\n \"absolute top-1/2 left-0 h-4 w-0.5 -translate-y-1/2 rounded-full transition-all duration-150\",\n // Selected: solid accent bar\n isSelected && \"bg-accent\",\n // Keyboard active (not selected): lighter bar\n !isSelected &&\n \"group-data-[active-item]:bg-accent bg-transparent\",\n // Focus visible: ensure bar is visible\n \"group-data-[focus-visible]:bg-accent\",\n )}\n />\n <span className=\"pl-2\">{item.label}</span>\n </CompositeItem>\n </div>\n );\n })}\n </Composite>\n </CompositeProvider>\n );\n}\n","\"use client\";\n\nimport type { ToolbarButtonDef } from \"../lib/types\";\nimport {\n ToolbarRoot,\n ToolbarContainer,\n ToolbarButton,\n ToolbarSeparator,\n TooltipProvider,\n TooltipAnchor,\n Tooltip,\n} from \"../core/toolbar\";\n\n/** Localized labels for the editor toolbar component. */\nexport interface EditorToolbarLabels {\n ariaLabel?: string;\n}\n\nconst defaultLabels: Required<EditorToolbarLabels> = {\n ariaLabel: \"텍스트 편집기 툴바\",\n};\n\n/** Props for the editor toolbar component. */\nexport interface EditorToolbarProps {\n buttons: ToolbarButtonDef[];\n onAction?: (id: string) => void;\n activeButtons?: string[];\n labels?: EditorToolbarLabels;\n}\n\nfunction ToolbarButtonWithTooltip({\n button,\n active,\n onAction,\n}: {\n button: ToolbarButtonDef;\n active: boolean;\n onAction?: (id: string) => void;\n}) {\n return (\n <TooltipProvider>\n <TooltipAnchor>\n <ToolbarButton\n className={`text-text-primary data-[active-item]:bg-bg-subtle data-[focus-visible]:ring-ring rounded-md p-2 transition-colors outline-none data-[focus-visible]:ring-2 ${\n active ? \"bg-bg-muted\" : \"hover:bg-bg-subtle\"\n }`}\n onClick={() => onAction?.(button.id)}\n >\n {button.icon}\n </ToolbarButton>\n </TooltipAnchor>\n <Tooltip>{button.label}</Tooltip>\n </TooltipProvider>\n );\n}\n\n/** Renders the editor toolbar component. */\nexport function EditorToolbar({\n buttons,\n onAction,\n activeButtons = [],\n labels: customLabels,\n}: EditorToolbarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n const groups: (ToolbarButtonDef | \"separator\")[][] = [];\n let current: (ToolbarButtonDef | \"separator\")[] = [];\n for (const btn of buttons) {\n if (btn.separator) {\n groups.push(current);\n current = [];\n }\n current.push(btn);\n }\n if (current.length) groups.push(current);\n\n return (\n <ToolbarRoot\n data-opt-id=\"Z73K6\"\n data-opt-slug=\"editor-toolbar.EditorToolbar\"\n >\n <ToolbarContainer aria-label={labels.ariaLabel}>\n {groups.map((group, gi) => (\n <span key={gi} className=\"contents\">\n {gi > 0 && <ToolbarSeparator />}\n {group.map((item) => {\n if (item === \"separator\") return null;\n const btn = item as ToolbarButtonDef;\n return (\n <ToolbarButtonWithTooltip\n key={btn.id}\n button={btn}\n active={activeButtons.includes(btn.id)}\n onAction={onAction}\n />\n );\n })}\n </span>\n ))}\n </ToolbarContainer>\n </ToolbarRoot>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { TabDef } from \"../lib/types\";\nimport { TabsRoot, TabList, Tab, TabPanel } from \"../core/tabs\";\n\n/** Localized labels for the content tabs component. */\nexport interface ContentTabsLabels {\n ariaLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<ContentTabsLabels> = {\n ariaLabel: \"콘텐츠 탭\",\n emptyMessage: \"표시할 탭이 없습니다.\",\n};\n\n/** Props for the content tabs component. */\nexport interface ContentTabsProps {\n tabs: TabDef[];\n defaultTabId?: string;\n labels?: ContentTabsLabels;\n}\n\n/** Renders the content tabs component. */\nexport function ContentTabs({\n tabs,\n defaultTabId,\n labels: customLabels,\n}: ContentTabsProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [selectedTabId, setSelectedTabId] = useState(\n defaultTabId ?? tabs[0]?.id,\n );\n\n if (tabs.length === 0) {\n return (\n <div\n className=\"text-text-secondary text-sm\"\n data-opt-id=\"9W97K\"\n data-opt-slug=\"content-tabs.ContentTabs\"\n >\n {labels.emptyMessage}\n </div>\n );\n }\n\n const handleSelectedTabId = (nextId: string | null | undefined) => {\n setSelectedTabId(nextId ?? tabs[0]?.id);\n };\n const activeTab = tabs.find((tab) => tab.id === selectedTabId) ?? tabs[0];\n\n return (\n <TabsRoot\n selectedId={selectedTabId}\n onSelectedIdChange={handleSelectedTabId}\n data-opt-id=\"9W97K\"\n data-opt-slug=\"content-tabs.ContentTabs\"\n >\n <TabList aria-label={labels.ariaLabel}>\n {tabs.map((tab) => (\n <Tab key={tab.id} id={tab.id}>\n {tab.label}\n </Tab>\n ))}\n </TabList>\n {activeTab && (\n <TabPanel tabId={activeTab.id}>{activeTab.content}</TabPanel>\n )}\n </TabsRoot>\n );\n}\n","import {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport type { FaqItem } from \"../lib/types\";\nimport {\n DisclosureRoot,\n DisclosureTrigger,\n DisclosureContent,\n} from \"../core/disclosure\";\n\n/** Localized labels for the faq accordion component. */\nexport interface FaqAccordionLabels {\n ariaLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<FaqAccordionLabels> = {\n ariaLabel: \"자주 묻는 질문\",\n emptyMessage: \"등록된 FAQ가 없습니다.\",\n};\n\n/** Props for the faq accordion component. */\nexport interface FaqAccordionProps {\n items: FaqItem[];\n labels?: FaqAccordionLabels;\n}\n\n/** Renders the faq accordion component. */\nexport function FaqAccordion({\n items,\n labels: customLabels,\n}: FaqAccordionProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n if (items.length === 0) {\n return (\n <div\n className=\"text-text-secondary text-sm\"\n data-opt-id=\"QRBHV\"\n data-opt-slug=\"faq-accordion.FaqAccordion\"\n >\n {labels.emptyMessage}\n </div>\n );\n }\n\n return (\n <CompositeProvider\n focusLoop\n orientation=\"vertical\"\n data-opt-id=\"QRBHV\"\n data-opt-slug=\"faq-accordion.FaqAccordion\"\n >\n <Composite\n role=\"region\"\n aria-label={labels.ariaLabel}\n className=\"divide-border-subtle border-border divide-y rounded-lg border\"\n >\n {items.map((faq) => (\n <DisclosureRoot key={faq.id}>\n <div>\n <CompositeItem render={<DisclosureTrigger />}>\n {faq.question}\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0 transition-transform [[data-open]>&]:rotate-180\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </CompositeItem>\n <DisclosureContent>\n <p className=\"text-text-secondary px-4 pt-2 pb-4 text-sm\">\n {faq.answer}\n </p>\n </DisclosureContent>\n </div>\n </DisclosureRoot>\n ))}\n </Composite>\n </CompositeProvider>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { FormFieldDef } from \"../lib/types\";\nimport {\n FormRoot,\n FormInput,\n FormTextarea,\n FormSelect,\n FormSelectPopover,\n FormSelectItem,\n FormSwitch,\n FormLabel,\n FormError,\n FormSubmit,\n FormCheckbox,\n FormRadioGroup,\n FormRadio,\n useFormStore,\n} from \"../core/form\";\nimport { EmptyState } from \"../core/empty-state\";\nimport { TagInput } from \"../core/tag-input\";\n\n/** Localized labels for the settings form component. */\nexport interface SettingsFormLabels {\n formAriaLabel?: string;\n submitButton?: string;\n successMessage?: string;\n}\n\nconst defaultLabels: Required<SettingsFormLabels> = {\n formAriaLabel: \"설정 폼\",\n submitButton: \"저장\",\n successMessage: \"설정이 저장되었습니다.\",\n};\n\n/** Props for the settings form component. */\nexport interface SettingsFormProps {\n fields: FormFieldDef[];\n onSubmit?: (values: Record<string, unknown>) => void;\n labels?: SettingsFormLabels;\n}\n\n/** Renders the settings form component. */\nexport function SettingsForm({\n fields,\n onSubmit,\n labels: customLabels,\n}: SettingsFormProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [submitted, setSubmitted] = useState(false);\n\n const defaultValues: Record<string, unknown> = {};\n for (const field of fields) {\n defaultValues[field.name] =\n field.defaultValue ??\n (field.type === \"switch\" || field.type === \"checkbox\"\n ? false\n : field.type === \"tags\"\n ? []\n : \"\");\n }\n\n const form = useFormStore({\n defaultValues,\n validate: (values) => {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (field.required) {\n const value = values[field.name];\n if (!value || (typeof value === \"string\" && !value.trim())) {\n errors[field.name] =\n field.requiredMessage ?? `${field.label}을(를) 입력해주세요.`;\n }\n }\n if (field.validate) {\n const value = values[field.name];\n const error = field.validate(value);\n if (error) {\n errors[field.name] = error;\n }\n }\n }\n return errors;\n },\n onSubmit: (values) => {\n setSubmitted(true);\n onSubmit?.(values);\n },\n });\n\n if (fields.length === 0) {\n return (\n <EmptyState\n title=\"설정 항목이 없습니다.\"\n description=\"표시할 설정 필드를 추가하면 이 폼이 렌더링됩니다.\"\n data-opt-id=\"9TEEJ\"\n data-opt-slug=\"settings-form.SettingsForm\"\n />\n );\n }\n\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"9TEEJ\"\n data-opt-slug=\"settings-form.SettingsForm\"\n >\n <FormRoot store={form} aria-label={labels.formAriaLabel}>\n {fields.map((field) => {\n if (field.visible !== undefined) {\n const currentValues = form.getValues();\n const isVisible =\n typeof field.visible === \"function\"\n ? field.visible(currentValues)\n : field.visible;\n if (!isVisible) return null;\n }\n\n if (field.type === \"tags\") {\n const rawValue = form.getValue(field.name) as string[] | undefined;\n const tags = Array.isArray(rawValue) ? rawValue : [];\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <TagInput\n value={tags}\n onChange={(next) => form.setValue(field.name, next)}\n placeholder={field.placeholder}\n />\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"radio\") {\n return (\n <fieldset key={field.name} className=\"gap-element flex flex-col\">\n <legend className=\"text-text-primary text-sm font-medium\">\n {field.label}\n </legend>\n <FormRadioGroup>\n <div className=\"gap-group flex\">\n {field.options?.map((option) => (\n <label\n key={option.value}\n className=\"text-text-primary gap-element flex items-center text-sm\"\n >\n <FormRadio name={field.name} value={option.value} />\n {option.label}\n </label>\n ))}\n </div>\n </FormRadioGroup>\n <FormError name={field.name} />\n </fieldset>\n );\n }\n\n if (field.type === \"checkbox\") {\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <label className=\"text-text-primary gap-element flex items-center text-sm\">\n <FormCheckbox name={field.name} />\n <span>{field.label}</span>\n </label>\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"textarea\") {\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <FormTextarea\n name={field.name}\n placeholder={field.placeholder}\n rows={field.rows ?? 4}\n resize={field.resize ?? \"vertical\"}\n className={\n field.font === \"mono\" ? \"font-mono text-sm\" : undefined\n }\n />\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"select\") {\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <FormSelect name={field.name} placeholder={field.placeholder}>\n <FormSelectPopover>\n {field.options?.map((option) => (\n <FormSelectItem key={option.value} value={option.value}>\n {option.label}\n </FormSelectItem>\n ))}\n </FormSelectPopover>\n </FormSelect>\n <FormError name={field.name} />\n </div>\n );\n }\n\n if (field.type === \"switch\") {\n return (\n <label key={field.name} className=\"gap-group flex items-center\">\n <FormSwitch name={field.name} />\n <div className=\"flex flex-col\">\n <span className=\"text-text-primary text-sm font-medium\">\n {field.label}\n </span>\n {field.description && (\n <span className=\"text-text-secondary text-sm\">\n {field.description}\n </span>\n )}\n </div>\n </label>\n );\n }\n\n return (\n <div key={field.name} className=\"gap-element flex flex-col\">\n <FormLabel name={field.name}>{field.label}</FormLabel>\n <FormInput\n name={field.name}\n type={field.type ?? \"text\"}\n placeholder={field.placeholder}\n />\n <FormError name={field.name} />\n </div>\n );\n })}\n\n <FormSubmit>{labels.submitButton}</FormSubmit>\n </FormRoot>\n\n {submitted && (\n <div className=\"border-success bg-success-subtle text-success-fg rounded-lg border p-3 text-sm\">\n {labels.successMessage}\n </div>\n )}\n </div>\n );\n}\n","import {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport type { DeploymentStep } from \"../lib/types\";\nimport {\n OPT_FOCUS,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_TEXT_TERTIARY,\n OPT_BADGE_GREEN,\n OPT_BADGE_RED,\n OPT_BADGE_NEUTRAL,\n} from \"../lib/styles\";\n\n/** Localized labels for the deployment timeline component. */\nexport type DeploymentTimelineLabels = Record<never, never>;\n\n/** Props for the deployment timeline component. */\nexport interface DeploymentTimelineProps {\n steps: DeploymentStep[];\n title?: string;\n}\n\nconst statusIcon: Record<DeploymentStep[\"status\"], string> = {\n success: \"●\",\n pending: \"◌\",\n running: \"⟳\",\n error: \"✗\",\n skipped: \"○\",\n};\n\nconst statusColor: Record<DeploymentStep[\"status\"], string> = {\n success: \"text-success-fg\",\n pending: OPT_TEXT_TERTIARY,\n running: \"text-accent\",\n error: \"text-danger-fg\",\n skipped: \"text-text-tertiary\",\n};\n\nconst statusBadge: Record<DeploymentStep[\"status\"], string> = {\n success: OPT_BADGE_GREEN,\n pending: OPT_BADGE_NEUTRAL,\n running:\n \"inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium bg-info-subtle text-info-fg\",\n error: OPT_BADGE_RED,\n skipped: OPT_BADGE_NEUTRAL,\n};\n\nconst statusLabel: Record<DeploymentStep[\"status\"], string> = {\n success: \"성공\",\n pending: \"대기\",\n running: \"실행 중\",\n error: \"에러\",\n skipped: \"건너뜀\",\n};\n\n/** Renders the deployment timeline component. */\nexport function DeploymentTimeline({\n steps,\n title = \"배포 타임라인\",\n}: DeploymentTimelineProps) {\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"XXVQ2\"\n data-opt-slug=\"deployment-timeline.DeploymentTimeline\"\n >\n {title && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>{title}</h3>\n )}\n <CompositeProvider focusLoop orientation=\"vertical\">\n <Composite role=\"list\" aria-label={title} className=\"relative\">\n {steps.map((step, i) => {\n const isLast = i === steps.length - 1;\n return (\n <CompositeItem\n key={step.id}\n className={`group gap-group relative flex w-full scroll-m-2 rounded-lg px-3 py-2 ${OPT_FOCUS} data-[active-item]:bg-accent-subtle`}\n role=\"listitem\"\n >\n {/* 연결선 + 아이콘 */}\n <div className=\"flex flex-col items-center\">\n <span\n className={`text-lg leading-none ${statusColor[step.status]}`}\n aria-label={statusLabel[step.status]}\n >\n {statusIcon[step.status]}\n </span>\n {!isLast && (\n <div className=\"bg-border-subtle mt-1 w-px flex-1\" />\n )}\n </div>\n\n {/* 내용 */}\n <div className=\"flex-1 pb-3\">\n <div className=\"gap-element flex items-center\">\n <span className={`text-sm font-medium ${OPT_TEXT_PRIMARY}`}>\n {step.name}\n </span>\n <span className={statusBadge[step.status]}>\n {statusLabel[step.status]}\n </span>\n {step.duration && (\n <span className={`text-xs ${OPT_TEXT_TERTIARY}`}>\n {step.duration}\n </span>\n )}\n </div>\n {step.detail && (\n <p className={`mt-0.5 text-xs ${OPT_TEXT_SECONDARY}`}>\n {step.detail}\n </p>\n )}\n </div>\n </CompositeItem>\n );\n })}\n </Composite>\n </CompositeProvider>\n </div>\n );\n}\n","\"use client\";\n\nimport { matchSorter } from \"match-sorter\";\nimport { useMemo, useState } from \"react\";\nimport type { ProjectDef } from \"../lib/types\";\nimport {\n ComboboxRoot,\n ComboboxInput,\n ComboboxPopover,\n ComboboxItem,\n} from \"../core/combobox\";\nimport {\n OPT_INPUT,\n OPT_ITEM_BASE,\n OPT_ACTIVE_ITEM,\n OPT_TEXT_LABEL,\n OPT_TEXT_SECONDARY,\n OPT_BADGE_NEUTRAL,\n OPT_DOT_GREEN,\n OPT_DOT_YELLOW,\n OPT_DOT_RED,\n} from \"../lib/styles\";\n\n/** Localized labels for the project switcher component. */\nexport type ProjectSwitcherLabels = Record<never, never>;\n\n/** Props for the project switcher component. */\nexport interface ProjectSwitcherProps {\n projects: ProjectDef[];\n value?: string;\n onChange?: (id: string) => void;\n placeholder?: string;\n}\n\nconst statusDot: Record<ProjectDef[\"status\"], string> = {\n active: OPT_DOT_GREEN,\n paused: OPT_DOT_YELLOW,\n error: OPT_DOT_RED,\n};\n\n/** Renders the project switcher component. */\nexport function ProjectSwitcher({\n projects,\n value,\n onChange,\n placeholder = \"프로젝트 검색...\",\n}: ProjectSwitcherProps) {\n const [search, setSearch] = useState(\"\");\n\n const matches = useMemo(() => {\n if (!search) return projects;\n return matchSorter(projects, search, { keys: [\"name\", \"framework\"] });\n }, [search, projects]);\n\n const selected = projects.find((p) => p.id === value);\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"5R3AG\"\n data-opt-slug=\"project-switcher.ProjectSwitcher\"\n >\n <ComboboxRoot onValueChange={setSearch}>\n <label className={OPT_TEXT_LABEL}>프로젝트</label>\n <ComboboxInput\n placeholder={selected ? selected.name : placeholder}\n className={OPT_INPUT}\n />\n <ComboboxPopover className=\"max-h-72 overflow-y-auto\">\n {matches.length === 0 && (\n <p className={`py-6 text-center text-sm ${OPT_TEXT_SECONDARY}`}>\n 결과가 없습니다.\n </p>\n )}\n {matches.map((project) => (\n <ComboboxItem\n key={project.id}\n value={project.name}\n onClick={() => onChange?.(project.id)}\n className={`gap-element flex scroll-m-2 items-center ${OPT_ITEM_BASE} ${OPT_ACTIVE_ITEM}`}\n >\n <span className={`shrink-0 ${statusDot[project.status]}`} />\n <span className=\"flex-1 truncate font-medium\">\n {project.name}\n </span>\n <span className={OPT_BADGE_NEUTRAL}>{project.framework}</span>\n {project.domain && (\n <span\n className={`truncate text-xs ${OPT_TEXT_SECONDARY} data-[active-item]:text-accent-fg/70`}\n >\n {project.domain}\n </span>\n )}\n </ComboboxItem>\n ))}\n </ComboboxPopover>\n </ComboboxRoot>\n </div>\n );\n}\n\nProjectSwitcher.displayName = \"ProjectSwitcher\";\n","\"use client\";\n\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport {\n DisclosureRoot as DisclosureProvider,\n DisclosureTrigger as Disclosure,\n DisclosureContent,\n} from \"../core/disclosure\";\nimport type { EnvGroupDef } from \"../lib/types\";\nimport {\n OPT_BORDER,\n OPT_DIVIDER,\n OPT_DISCLOSURE_TRIGGER,\n OPT_DISCLOSURE_CONTENT,\n OPT_FOCUS,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_TEXT_TERTIARY,\n OPT_BADGE_NEUTRAL,\n OPT_DOT_RED,\n OPT_DOT_YELLOW,\n OPT_DOT_GREEN,\n} from \"../lib/styles\";\n\n/** Localized labels for the env panel component. */\nexport interface EnvPanelLabels {\n varCount?: (count: number) => string;\n envVarsLabel?: (env: string) => string;\n secretBadge?: string;\n}\n\nconst defaultLabels: Required<EnvPanelLabels> = {\n varCount: (count: number) => `${count}개 변수`,\n envVarsLabel: (env: string) => `${env} 환경 변수`,\n secretBadge: \"secret\",\n};\n\n/** Props for the env panel component. */\nexport interface EnvPanelProps {\n groups: EnvGroupDef[];\n labels?: EnvPanelLabels;\n}\n\nconst envDot: Record<string, string> = {\n Production: OPT_DOT_RED,\n Preview: OPT_DOT_YELLOW,\n Development: OPT_DOT_GREEN,\n};\n\n/** Renders the env panel component. */\nexport function EnvPanel({ groups, labels: customLabels }: EnvPanelProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n return (\n <div\n className={`rounded-lg ${OPT_BORDER} divide-y ${OPT_DIVIDER} bg-surface`}\n data-opt-id=\"ZBDWK\"\n data-opt-slug=\"env-panel.EnvPanel\"\n >\n {groups.map((group) => (\n <DisclosureProvider\n key={group.env}\n defaultOpen={group.env === \"Production\"}\n >\n <div>\n <Disclosure className={OPT_DISCLOSURE_TRIGGER}>\n <span className=\"gap-element flex items-center\">\n <span\n className={\n envDot[group.env] ?? \"bg-bg-muted h-2 w-2 rounded-full\"\n }\n />\n <span className=\"font-medium\">{group.env}</span>\n <span className={`text-xs ${OPT_TEXT_TERTIARY}`}>\n {labels.varCount(group.vars.length)}\n </span>\n </span>\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0 transition-transform [[data-open]>&]:rotate-180\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </Disclosure>\n <DisclosureContent className={OPT_DISCLOSURE_CONTENT}>\n <CompositeProvider focusLoop orientation=\"vertical\">\n <Composite\n role=\"list\"\n aria-label={labels.envVarsLabel(group.env)}\n className=\"px-4 pb-3\"\n >\n {group.vars.map((v) => (\n <CompositeItem\n key={v.key}\n role=\"listitem\"\n className={`gap-group flex scroll-m-2 items-center rounded px-2 py-1.5 text-sm ${OPT_FOCUS} data-[active-item]:bg-accent-subtle`}\n >\n <span\n className={`w-44 shrink-0 truncate font-mono text-xs font-medium ${OPT_TEXT_PRIMARY}`}\n >\n {v.key}\n </span>\n <span\n className={`flex-1 truncate font-mono text-xs ${OPT_TEXT_SECONDARY}`}\n >\n {v.isSecret ? \"••••••••\" : v.value}\n </span>\n {v.isSecret && (\n <span className={OPT_BADGE_NEUTRAL}>\n {labels.secretBadge}\n </span>\n )}\n </CompositeItem>\n ))}\n </Composite>\n </CompositeProvider>\n </DisclosureContent>\n </div>\n </DisclosureProvider>\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { BranchDef } from \"../lib/types\";\nimport {\n SelectRoot,\n SelectLabel,\n SelectTrigger,\n SelectPopover,\n SelectItem,\n} from \"../core/select\";\nimport {\n OPT_INPUT,\n OPT_ITEM_BASE,\n OPT_ACTIVE_ITEM,\n OPT_TEXT_LABEL,\n OPT_TEXT_TERTIARY,\n OPT_BADGE_BLUE,\n} from \"../lib/styles\";\n\n/** Localized labels for the branch select component. */\nexport interface BranchSelectLabels {\n selectLabel?: string;\n emptySelectionLabel?: string;\n emptyMessage?: string;\n defaultBadge?: string;\n}\n\nconst defaultLabels: Required<BranchSelectLabels> = {\n selectLabel: \"브랜치\",\n emptySelectionLabel: \"선택...\",\n emptyMessage: \"사용 가능한 브랜치가 없습니다.\",\n defaultBadge: \"default\",\n};\n\n/** Props for the branch select component. */\nexport interface BranchSelectProps {\n branches: BranchDef[];\n value?: string;\n onChange?: (name: string) => void;\n label?: string;\n labels?: BranchSelectLabels;\n}\n\n/** Renders the branch select component. */\nexport function BranchSelect({\n branches,\n value: controlledValue,\n onChange,\n label,\n labels: customLabels,\n}: BranchSelectProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const resolvedLabel = label ?? labels.selectLabel;\n const defaultBranch = branches.find((b) => b.isDefault);\n const [internalValue, setInternalValue] = useState(\n defaultBranch?.name ?? branches[0]?.name ?? \"\",\n );\n const value = controlledValue ?? internalValue;\n const selected = branches.find((b) => b.name === value);\n\n if (branches.length === 0) {\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"7EDEP\"\n data-opt-slug=\"branch-select.BranchSelect\"\n >\n <span className={OPT_TEXT_LABEL}>{resolvedLabel}</span>\n <span className={OPT_TEXT_TERTIARY}>{labels.emptyMessage}</span>\n </div>\n );\n }\n\n const handleChange = (v: string | string[]) => {\n const next = Array.isArray(v) ? (v[0] ?? \"\") : v;\n if (onChange) onChange(next);\n else setInternalValue(next);\n };\n\n return (\n <div\n className=\"gap-element flex flex-col\"\n data-opt-id=\"7EDEP\"\n data-opt-slug=\"branch-select.BranchSelect\"\n >\n <SelectRoot value={value} onValueChange={handleChange}>\n <SelectLabel className={OPT_TEXT_LABEL}>{resolvedLabel}</SelectLabel>\n <SelectTrigger\n className={`${OPT_INPUT} max-w-xs items-center justify-between gap-1`}\n >\n <span className=\"gap-element flex items-center truncate\">\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244\"\n />\n </svg>\n <span className=\"truncate\">\n {selected?.name ?? labels.emptySelectionLabel}\n </span>\n {selected?.isDefault && (\n <span className={OPT_BADGE_BLUE}>{labels.defaultBadge}</span>\n )}\n </span>\n <svg\n className=\"text-text-tertiary h-4 w-4 shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m19.5 8.25-7.5 7.5-7.5-7.5\"\n />\n </svg>\n </SelectTrigger>\n <SelectPopover className=\"max-w-xs\">\n {branches.map((branch) => (\n <SelectItem\n key={branch.name}\n value={branch.name}\n className={`gap-element flex scroll-m-2 items-center ${OPT_ITEM_BASE} ${OPT_ACTIVE_ITEM}`}\n >\n <span className=\"flex-1 truncate\">{branch.name}</span>\n {branch.isDefault && (\n <span className=\"bg-accent-subtle text-accent data-[active-item]:bg-accent-fg/20 data-[active-item]:text-accent-fg rounded-full px-2 py-0.5 text-[11px] font-medium\">\n {labels.defaultBadge}\n </span>\n )}\n {branch.lastCommit && (\n <span\n className={`font-mono text-xs ${OPT_TEXT_TERTIARY} data-[active-item]:text-accent-fg/60`}\n >\n {branch.lastCommit}\n </span>\n )}\n {branch.author && (\n <span\n className={`text-xs ${OPT_TEXT_TERTIARY} data-[active-item]:text-accent-fg/60`}\n >\n {branch.author}\n </span>\n )}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n </div>\n );\n}\n\nBranchSelect.displayName = \"BranchSelect\";\n","import {\n Composite,\n CompositeItem,\n CompositeProvider,\n CompositeRow,\n} from \"../core/composite-zone\";\nimport type { DomainDef } from \"../lib/types\";\nimport {\n OPT_BORDER,\n OPT_DIVIDER,\n OPT_TH,\n OPT_TD,\n OPT_TD_MUTED,\n OPT_TABLE_ROW_ACTIVE,\n OPT_BADGE_GREEN,\n OPT_BADGE_YELLOW,\n OPT_BADGE_RED,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n} from \"../lib/styles\";\n\n/** Localized labels for the domain table component. */\nexport interface DomainTableLabels {\n domain?: string;\n status?: string;\n ssl?: string;\n redirect?: string;\n added?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<DomainTableLabels> = {\n domain: \"Domain\",\n status: \"Status\",\n ssl: \"SSL\",\n redirect: \"Redirect\",\n added: \"Added\",\n emptyMessage: \"No domains configured\",\n};\n\n/** Props for the domain table component. */\nexport interface DomainTableProps {\n domains: DomainDef[];\n title?: string;\n labels?: DomainTableLabels;\n}\n\nconst statusBadge: Record<DomainDef[\"status\"], string> = {\n active: OPT_BADGE_GREEN,\n pending: OPT_BADGE_YELLOW,\n error: OPT_BADGE_RED,\n};\n\nconst sslBadge: Record<DomainDef[\"ssl\"], string> = {\n valid: OPT_BADGE_GREEN,\n pending: OPT_BADGE_YELLOW,\n expired: OPT_BADGE_RED,\n};\n\nconst statusLabel: Record<DomainDef[\"status\"], string> = {\n active: \"Active\",\n pending: \"Pending\",\n error: \"Error\",\n};\n\nconst sslLabel: Record<DomainDef[\"ssl\"], string> = {\n valid: \"Valid\",\n pending: \"Pending\",\n expired: \"Expired\",\n};\n\n/** Renders the domain table component. */\nexport function DomainTable({\n domains,\n title = \"도메인\",\n labels: customLabels,\n}: DomainTableProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n if (domains.length === 0) {\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"A7SRM\"\n data-opt-slug=\"domain-table.DomainTable\"\n >\n {title && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>\n {title}\n </h3>\n )}\n <div\n className={`rounded-lg px-4 py-6 text-sm ${OPT_BORDER} ${OPT_TEXT_SECONDARY} bg-surface`}\n >\n {labels.emptyMessage}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className=\"gap-group flex flex-col\"\n data-opt-id=\"A7SRM\"\n data-opt-slug=\"domain-table.DomainTable\"\n >\n {title && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>{title}</h3>\n )}\n <div className={`overflow-x-auto rounded-lg ${OPT_BORDER} bg-surface`}>\n <CompositeProvider focusLoop focusWrap>\n <Composite\n role=\"grid\"\n aria-label={title}\n className=\"w-full\"\n render={<table />}\n >\n <thead className=\"border-border-subtle bg-surface-inset border-b\">\n <tr>\n <th className={OPT_TH}>{labels.domain}</th>\n <th className={OPT_TH}>{labels.status}</th>\n <th className={OPT_TH}>{labels.ssl}</th>\n <th className={OPT_TH}>{labels.redirect}</th>\n <th className={OPT_TH}>{labels.added}</th>\n </tr>\n </thead>\n <tbody className={`divide-y ${OPT_DIVIDER}`}>\n {domains.map((d) => (\n <CompositeRow key={d.domain} render={<tr />}>\n <CompositeItem\n render={\n <td\n className={`${OPT_TD} font-mono font-medium`}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n >\n {d.domain}\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <span className={statusBadge[d.status]}>\n {statusLabel[d.status]}\n </span>\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <span className={sslBadge[d.ssl]}>{sslLabel[d.ssl]}</span>\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n {d.redirect ?? \"—\"}\n </CompositeItem>\n <CompositeItem\n render={<td className={OPT_TD_MUTED} role=\"gridcell\" />}\n className={OPT_TABLE_ROW_ACTIVE}\n >\n {d.addedAt ?? \"—\"}\n </CompositeItem>\n </CompositeRow>\n ))}\n </tbody>\n </Composite>\n </CompositeProvider>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n useState,\n useMemo,\n useCallback,\n Fragment,\n type ReactNode,\n} from \"react\";\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n CompositeRow,\n} from \"../core/composite-zone\";\nimport {\n OPT_BORDER,\n OPT_DIVIDER,\n OPT_TH,\n OPT_TD,\n OPT_TABLE_ROW_ACTIVE,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_FOCUS_VISIBLE,\n} from \"../lib/styles\";\nimport { cn } from \"../lib/cn\";\nimport { Checkbox } from \"../core/checkbox\";\nimport { Pagination } from \"../core/pagination\";\n\n/**\n * Column definition for DataTable.\n * `accessor` can be a property key for simple lookups or a render function\n * for computed/complex cells.\n */\nexport interface ColumnDef<T> {\n id: string;\n header: string;\n accessor: keyof T | ((row: T) => ReactNode);\n width?: string;\n align?: \"left\" | \"center\" | \"right\";\n sortable?: boolean;\n /** Show an inline progress bar in the cell. Return a 0-1 ratio. */\n bar?: (row: T) => number;\n /** Bar color class (default: \"bg-accent\") */\n barColor?: string;\n}\n\n/** Localized labels for the data table component. */\nexport type DataTableLabels = Record<never, never>;\n\n/** Props for the data table component. */\nexport interface DataTableProps<T> {\n data: T[];\n columns: ColumnDef<T>[];\n keyExtractor: (row: T) => string;\n title?: string;\n onRowClick?: (row: T) => void;\n emptyMessage?: string;\n /** Highlight a single row by its key */\n activeRowId?: string;\n /** Enable column sorting */\n sortable?: boolean;\n /** Enable row selection with checkboxes */\n selectable?: boolean;\n selectedKeys?: string[];\n onSelectionChange?: (keys: string[]) => void;\n /** Enable expandable rows */\n expandable?: boolean;\n renderExpanded?: (row: T) => ReactNode;\n /** Enable pagination */\n pageSize?: number;\n /** Sticky table header */\n stickyHeader?: boolean;\n /** Enable column resizing via drag handle */\n resizableColumns?: boolean;\n /** External (server-side) sort callback */\n onSort?: (columnId: string, direction: \"asc\" | \"desc\" | null) => void;\n className?: string;\n}\n\ntype SortDir = \"asc\" | \"desc\" | null;\n\nconst MIN_COLUMN_WIDTH = 40;\nconst DEFAULT_COLUMN_RESIZE_MAX = 1200;\n\nconst alignmentClass: Record<\n NonNullable<ColumnDef<unknown>[\"align\"]>,\n string\n> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n};\n\nfunction getCellValue<T>(\n row: T,\n accessor: ColumnDef<T>[\"accessor\"],\n): ReactNode {\n if (typeof accessor === \"function\") {\n try {\n return accessor(row);\n } catch {\n return \"—\";\n }\n }\n const value = row[accessor];\n if (\n value === null ||\n value === undefined ||\n (typeof value === \"number\" && !Number.isFinite(value))\n ) {\n return \"—\";\n }\n return String(value);\n}\n\nfunction getRawValue<T>(row: T, accessor: ColumnDef<T>[\"accessor\"]): unknown {\n if (typeof accessor === \"function\") {\n return accessor(row);\n }\n return row[accessor];\n}\n\nfunction isMissingSortValue(value: unknown): boolean {\n return (\n value == null || (typeof value === \"number\" && !Number.isFinite(value))\n );\n}\n\nfunction compareSortValues(aVal: unknown, bVal: unknown, dir: SortDir): number {\n const aMissing = isMissingSortValue(aVal);\n const bMissing = isMissingSortValue(bVal);\n\n if (aMissing && bMissing) return 0;\n if (aMissing) return 1;\n if (bMissing) return -1;\n\n const cmp =\n typeof aVal === \"number\" && typeof bVal === \"number\"\n ? aVal - bVal\n : String(aVal).localeCompare(String(bVal));\n\n return dir === \"desc\" ? -cmp : cmp;\n}\n\nfunction clampPercent(ratio: number): number {\n if (!Number.isFinite(ratio)) return 0;\n return Math.min(100, Math.max(0, Math.round(ratio * 100)));\n}\n\nfunction getResizeHandleValue(\n currentWidth: number | undefined,\n configuredWidth: string | undefined,\n): number {\n if (typeof currentWidth === \"number\" && Number.isFinite(currentWidth)) {\n return Math.max(MIN_COLUMN_WIDTH, Math.round(currentWidth));\n }\n\n const pxWidth = configuredWidth?.trim().match(/^(\\d+(?:\\.\\d+)?)px$/);\n if (pxWidth) {\n return Math.max(MIN_COLUMN_WIDTH, Math.round(Number(pxWidth[1])));\n }\n\n return MIN_COLUMN_WIDTH;\n}\n\nfunction DataTableProgressBar({\n value,\n barColor,\n label,\n}: {\n value: number;\n barColor?: string;\n label: string;\n}) {\n const percent = clampPercent(value);\n\n return (\n <div\n className=\"bg-bg-subtle mt-1 h-1.5 w-full overflow-hidden rounded-full\"\n role=\"progressbar\"\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuetext={`${percent}%`}\n aria-label={label}\n >\n <div\n className={cn(\"h-full rounded-full transition-all\", barColor)}\n style={{ width: `${percent}%` }}\n />\n </div>\n );\n}\n\n/** Renders the data table component. */\nexport function DataTable<T>({\n data,\n columns,\n keyExtractor,\n title = \"Data Table\",\n onRowClick,\n emptyMessage = \"No data available\",\n activeRowId,\n sortable = false,\n selectable = false,\n selectedKeys,\n onSelectionChange,\n expandable = false,\n renderExpanded,\n pageSize,\n stickyHeader = false,\n resizableColumns = false,\n onSort: onSortExternal,\n className,\n}: DataTableProps<T>) {\n const [sortCol, setSortCol] = useState<string | null>(null);\n const [sortDir, setSortDir] = useState<SortDir>(null);\n const [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set());\n const [page, setPage] = useState(0);\n const [colWidths, setColWidths] = useState<Record<string, number>>({});\n\n // Client-side sorting: numeric values compared directly, others via localeCompare.\n // Nullish and non-finite numeric values are sorted to the end regardless of direction.\n // Skipped when onSort (external/server-side sort) is provided — caller handles ordering.\n const sortedData = useMemo(() => {\n if (!sortable || !sortCol || !sortDir) return data;\n const col = columns.find((c) => c.id === sortCol);\n if (!col) return data;\n return [...data].sort((a, b) => {\n const aVal = getRawValue(a, col.accessor);\n const bVal = getRawValue(b, col.accessor);\n return compareSortValues(aVal, bVal, sortDir);\n });\n }, [data, sortable, sortCol, sortDir, columns]);\n\n // Pagination\n const totalPages = pageSize ? Math.ceil(sortedData.length / pageSize) : 1;\n const pagedData = pageSize\n ? sortedData.slice(page * pageSize, (page + 1) * pageSize)\n : sortedData;\n\n // Sort cycles: null → asc → desc → null (tri-state toggle).\n // Resets pagination to page 0 on each sort change.\n const handleSort = useCallback(\n (colId: string) => {\n if (!sortable) return;\n let nextDir: SortDir;\n if (sortCol === colId) {\n nextDir =\n sortDir === \"asc\" ? \"desc\" : sortDir === \"desc\" ? null : \"asc\";\n setSortDir(nextDir);\n if (nextDir === null) setSortCol(null);\n } else {\n setSortCol(colId);\n setSortDir(\"asc\");\n nextDir = \"asc\";\n }\n setPage(0);\n if (onSortExternal) {\n onSortExternal(colId, nextDir);\n }\n },\n [sortable, sortCol, sortDir, onSortExternal],\n );\n\n const toggleExpand = useCallback((key: string) => {\n setExpandedKeys((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n }, []);\n\n // Selection — membership lookups go through a Set so select-all and the\n // per-row `isSelected` check stay O(1) instead of O(selected) on every row.\n // Keyed on the `selectedKeys` prop (not the `selected` fallback array, which\n // gets a fresh reference each render when the prop is undefined).\n const selected = selectedKeys ?? [];\n const selectedSet = useMemo(\n () => new Set(selectedKeys ?? []),\n [selectedKeys],\n );\n const allKeys = data.map(keyExtractor);\n const allSelected =\n allKeys.length > 0 && allKeys.every((k) => selectedSet.has(k));\n const toggleSelectAll = useCallback(() => {\n if (!onSelectionChange) return;\n onSelectionChange(allSelected ? [] : allKeys);\n }, [allSelected, allKeys, onSelectionChange]);\n\n const toggleSelectRow = useCallback(\n (key: string) => {\n if (!onSelectionChange) return;\n onSelectionChange(\n selectedSet.has(key)\n ? selected.filter((k) => k !== key)\n : [...selected, key],\n );\n },\n [selected, selectedSet, onSelectionChange],\n );\n\n const sortIndicator = (colId: string) => {\n if (sortCol !== colId) return null;\n return sortDir === \"asc\" ? \" ▲\" : sortDir === \"desc\" ? \" ▼\" : null;\n };\n\n const colCount = columns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0);\n\n return (\n <div\n className={cn(\"gap-group flex flex-col\", className)}\n data-opt-id=\"J1KN4\"\n data-opt-slug=\"data-table.DataTable\"\n >\n {title && (\n <h3 className={cn(\"text-sm font-semibold\", OPT_TEXT_PRIMARY)}>\n {title}\n </h3>\n )}\n <div\n className={cn(\"overflow-x-auto rounded-lg\", OPT_BORDER, \"bg-surface\")}\n >\n {data.length === 0 ? (\n <div\n className={cn(\"px-4 py-8 text-center text-sm\", OPT_TEXT_SECONDARY)}\n >\n {emptyMessage}\n </div>\n ) : (\n <CompositeProvider focusLoop focusWrap>\n <Composite\n role=\"grid\"\n aria-label={title}\n className=\"w-full\"\n render={<table />}\n >\n <thead\n className={cn(\n \"border-border-subtle bg-surface-inset border-b\",\n stickyHeader && \"sticky top-0 z-10\",\n )}\n >\n <tr>\n {selectable && (\n <th className={cn(OPT_TH, \"w-10\")}>\n <Checkbox\n checked={allSelected}\n onChange={toggleSelectAll}\n aria-label=\"Select all\"\n />\n </th>\n )}\n {expandable && <th className={cn(OPT_TH, \"w-10\")} />}\n {columns.map((col) => {\n const isSortable = sortable && col.sortable !== false;\n const resizeValue = getResizeHandleValue(\n colWidths[col.id],\n col.width,\n );\n const resizeMax = Math.max(\n DEFAULT_COLUMN_RESIZE_MAX,\n resizeValue,\n );\n return (\n <th\n key={col.id}\n className={cn(\n OPT_TH,\n \"relative\",\n alignmentClass[col.align ?? \"left\"],\n isSortable &&\n \"hover:text-text-primary cursor-pointer select-none\",\n isSortable && OPT_FOCUS_VISIBLE,\n )}\n style={{\n width: colWidths[col.id] || col.width || undefined,\n }}\n onClick={\n isSortable ? () => handleSort(col.id) : undefined\n }\n onKeyDown={(event) => {\n if (\n !isSortable ||\n (event.key !== \"Enter\" && event.key !== \" \")\n ) {\n return;\n }\n event.preventDefault();\n handleSort(col.id);\n }}\n tabIndex={isSortable ? 0 : undefined}\n aria-sort={\n sortCol === col.id && sortDir\n ? sortDir === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : undefined\n }\n >\n <span className=\"flex items-center\">\n {col.header}\n {sortIndicator(col.id)}\n </span>\n {resizableColumns && (\n <span\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${col.header}`}\n aria-valuemin={MIN_COLUMN_WIDTH}\n aria-valuemax={resizeMax}\n aria-valuenow={resizeValue}\n aria-valuetext={`${resizeValue} pixels`}\n tabIndex={0}\n className=\"bg-border absolute top-0 right-0 bottom-0 w-1 cursor-col-resize opacity-0 hover:opacity-100\"\n onKeyDown={(e) => {\n if (\n e.key !== \"ArrowLeft\" &&\n e.key !== \"ArrowRight\" &&\n e.key !== \"Home\" &&\n e.key !== \"End\"\n ) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n if (e.key === \"Home\" || e.key === \"End\") {\n setColWidths((prev) => ({\n ...prev,\n [col.id]:\n e.key === \"Home\"\n ? MIN_COLUMN_WIDTH\n : resizeMax,\n }));\n return;\n }\n const delta = e.shiftKey ? 40 : 10;\n const direction = e.key === \"ArrowRight\" ? 1 : -1;\n setColWidths((prev) => {\n const current = getResizeHandleValue(\n prev[col.id],\n col.width,\n );\n return {\n ...prev,\n [col.id]: Math.max(\n MIN_COLUMN_WIDTH,\n current + direction * delta,\n ),\n };\n });\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const startX = e.clientX;\n const th = (e.target as HTMLElement)\n .parentElement!;\n const startW = th.offsetWidth;\n const onMove = (ev: MouseEvent) => {\n const newW = Math.max(\n MIN_COLUMN_WIDTH,\n startW + ev.clientX - startX,\n );\n setColWidths((prev) => ({\n ...prev,\n [col.id]: newW,\n }));\n };\n const onUp = () => {\n document.removeEventListener(\n \"mousemove\",\n onMove,\n );\n document.removeEventListener(\"mouseup\", onUp);\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n }}\n />\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody className={cn(\"divide-y\", OPT_DIVIDER)}>\n {pagedData.map((row) => {\n const key = keyExtractor(row);\n const isExpanded = expandedKeys.has(key);\n const isSelected = selectedSet.has(key);\n const isActive = activeRowId === key;\n\n return (\n <Fragment key={key}>\n <CompositeRow\n render={\n <tr\n className={cn(\n onRowClick ? \"cursor-pointer\" : undefined,\n (isSelected || isActive) && \"bg-accent-subtle\",\n )}\n onClick={\n onRowClick ? () => onRowClick(row) : undefined\n }\n />\n }\n >\n {selectable && (\n <CompositeItem\n render={\n <td\n className={cn(OPT_TD, \"w-10\")}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <Checkbox\n checked={isSelected}\n onChange={() => toggleSelectRow(key)}\n aria-label={`Select row ${key}`}\n />\n </CompositeItem>\n )}\n {expandable && (\n <CompositeItem\n render={\n <td\n className={cn(OPT_TD, \"w-10\")}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n toggleExpand(key);\n }}\n className={cn(\n \"rounded p-0.5 text-sm transition-transform\",\n OPT_TEXT_SECONDARY,\n OPT_FOCUS_VISIBLE,\n isExpanded && \"rotate-90\",\n )}\n aria-expanded={isExpanded}\n aria-label={`${isExpanded ? \"Collapse\" : \"Expand\"} row ${key}`}\n >\n &#x25B6;\n </button>\n </CompositeItem>\n )}\n {columns.map((col, colIndex) => (\n <CompositeItem\n key={col.id}\n render={\n <td\n className={cn(\n OPT_TD,\n alignmentClass[col.align ?? \"left\"],\n colIndex === 0 ? \"font-medium\" : \"\",\n )}\n role=\"gridcell\"\n />\n }\n className={OPT_TABLE_ROW_ACTIVE}\n onKeyDown={(event) => {\n if (\n !onRowClick ||\n event.target !== event.currentTarget ||\n (event.key !== \"Enter\" && event.key !== \" \")\n ) {\n return;\n }\n event.preventDefault();\n onRowClick(row);\n }}\n >\n {getCellValue(row, col.accessor)}\n {col.bar && (\n <DataTableProgressBar\n value={col.bar(row)}\n barColor={col.barColor ?? \"bg-accent\"}\n label={col.header}\n />\n )}\n </CompositeItem>\n ))}\n </CompositeRow>\n {expandable && isExpanded && renderExpanded && (\n <tr>\n <td\n colSpan={colCount}\n className=\"border-border-subtle bg-surface-inset border-t px-4 py-3\"\n >\n {renderExpanded(row)}\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </Composite>\n </CompositeProvider>\n )}\n </div>\n\n {/* Pagination */}\n {pageSize && totalPages > 1 && (\n <Pagination\n totalItems={sortedData.length}\n pageSize={pageSize}\n currentPage={page + 1}\n onPageChange={(p) => setPage(p - 1)}\n />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Alert } from \"../core/alert\";\n\n/** Defines the toast action shape. */\nexport interface ToastAction {\n label: string;\n onClick: () => void;\n}\n\n/** Toast severity. */\nexport type ToastVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\n/** Defines the toast message shape. */\nexport interface ToastMessage {\n id: string;\n variant: ToastVariant;\n title?: string;\n message: string;\n duration?: number;\n actions?: ToastAction[];\n}\n\n/** Options accepted by the imperative `toast()` API. */\nexport interface ToastOptions {\n variant?: ToastVariant;\n title?: string;\n message: string;\n duration?: number;\n actions?: ToastAction[];\n}\n\n/** Defines the toast context value shape. */\nexport interface ToastContextValue {\n toasts: ToastMessage[];\n addToast: (toast: Omit<ToastMessage, \"id\">) => string;\n removeToast: (id: string) => void;\n}\n\n/* ─── Imperative store ───\n *\n * A module-level store lets any code (event handlers, non-React modules) fire a\n * toast via `toast.success(\"Saved\")` without threading the `useToast` hook\n * through props. A mounted `ToastProvider` subscribes and renders the queue.\n */\n\nlet toastCounter = 0;\nlet toasts: ToastMessage[] = [];\nconst listeners = new Set<() => void>();\n\nfunction emitChange() {\n for (const l of listeners) l();\n}\n\nconst toastStore = {\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return toasts;\n },\n add(input: ToastOptions): string {\n const id = `toast-${++toastCounter}`;\n toasts = [...toasts, { id, variant: input.variant ?? \"info\", ...input }];\n emitChange();\n return id;\n },\n dismiss(id: string) {\n const next = toasts.filter((t) => t.id !== id);\n if (next.length !== toasts.length) {\n toasts = next;\n emitChange();\n }\n },\n clear() {\n if (toasts.length) {\n toasts = [];\n emitChange();\n }\n },\n};\n\nfunction makeVariant(variant: ToastVariant) {\n return (\n message: string,\n options?: Omit<ToastOptions, \"message\" | \"variant\">,\n ) => toastStore.add({ ...options, message, variant });\n}\n\n/**\n * Imperative toast API. Call from anywhere (no hook required):\n * `toast.success(\"Saved\")`, `toast.error(\"Failed\", { title: \"Oops\" })`,\n * `toast.dismiss(id)`, `toast.clear()`. Requires a mounted `ToastProvider`.\n */\nexport const toast = Object.assign(\n (options: ToastOptions) => toastStore.add(options),\n {\n info: makeVariant(\"info\"),\n success: makeVariant(\"success\"),\n warning: makeVariant(\"warning\"),\n error: makeVariant(\"error\"),\n dismiss: (id: string) => toastStore.dismiss(id),\n clear: () => toastStore.clear(),\n },\n);\n\nconst ToastContext = createContext<ToastContextValue | null>(null);\n\n/** Localized labels for the notification toast component. */\nexport type NotificationToastLabels = Record<never, never>;\n\n/** Props for the toast provider component. */\nexport interface ToastProviderProps {\n children: ReactNode;\n position?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n defaultDuration?: number;\n stackLimit?: number;\n}\n\nconst positionStyles: Record<\n NonNullable<ToastProviderProps[\"position\"]>,\n string\n> = {\n \"top-right\": \"top-4 right-4\",\n \"top-left\": \"top-4 left-4\",\n \"bottom-right\": \"bottom-4 right-4\",\n \"bottom-left\": \"bottom-4 left-4\",\n};\n\n/** Renders the toast provider component. */\nexport function ToastProvider({\n children,\n position = \"top-right\",\n defaultDuration = 5000,\n stackLimit = 5,\n}: ToastProviderProps) {\n const allToasts = useSyncExternalStore(\n toastStore.subscribe,\n toastStore.getSnapshot,\n toastStore.getSnapshot,\n );\n // Newest toasts win when the queue exceeds the stack limit.\n const visibleToasts =\n allToasts.length > stackLimit ? allToasts.slice(-stackLimit) : allToasts;\n\n const addToast = useCallback(\n (t: Omit<ToastMessage, \"id\">) => toastStore.add(t),\n [],\n );\n const removeToast = useCallback((id: string) => toastStore.dismiss(id), []);\n\n return (\n <ToastContext.Provider\n value={{ toasts: visibleToasts, addToast, removeToast }}\n >\n {children}\n <div\n className={cn(\n \"gap-element fixed z-50 flex flex-col\",\n positionStyles[position],\n )}\n role=\"region\"\n aria-label=\"Notifications\"\n data-opt-id=\"M0KTS\"\n data-opt-slug=\"notification-toast.ToastProvider\"\n >\n {visibleToasts.map((t) => (\n <NotificationToast\n key={t.id}\n toast={t}\n defaultDuration={defaultDuration}\n onDismiss={() => toastStore.dismiss(t.id)}\n />\n ))}\n </div>\n </ToastContext.Provider>\n );\n}\n\n/** Provides toast. */\nexport function useToast() {\n const context = useContext(ToastContext);\n if (!context) {\n throw new Error(\"useToast must be used within a ToastProvider\");\n }\n return context;\n}\n\ninterface NotificationToastProps {\n toast: ToastMessage;\n onDismiss: () => void;\n /** Falls back here when the toast itself sets no duration. */\n defaultDuration?: number;\n}\n\n/** Renders the notification toast component. */\nexport function NotificationToast({\n toast,\n onDismiss,\n defaultDuration = 5000,\n}: NotificationToastProps) {\n const duration = toast.duration ?? defaultDuration;\n const isUrgent = toast.variant === \"error\" || toast.variant === \"warning\";\n const onDismissRef = useRef(onDismiss);\n const dismissedRef = useRef(false);\n const timerStartedAtRef = useRef<number | null>(null);\n const remainingDurationRef = useRef(duration);\n const [paused, setPaused] = useState(false);\n\n useEffect(() => {\n onDismissRef.current = onDismiss;\n }, [onDismiss]);\n\n const dismissOnce = useCallback(() => {\n if (dismissedRef.current) return;\n dismissedRef.current = true;\n onDismissRef.current();\n }, []);\n\n useEffect(() => {\n dismissedRef.current = false;\n remainingDurationRef.current = duration;\n }, [toast.id, duration]);\n\n useEffect(() => {\n if (!duration || duration <= 0 || paused || dismissedRef.current) {\n return;\n }\n\n timerStartedAtRef.current = Date.now();\n const timer = setTimeout(() => {\n dismissOnce();\n }, remainingDurationRef.current);\n\n return () => {\n clearTimeout(timer);\n if (timerStartedAtRef.current !== null) {\n const elapsed = Date.now() - timerStartedAtRef.current;\n remainingDurationRef.current = Math.max(\n 0,\n remainingDurationRef.current - elapsed,\n );\n timerStartedAtRef.current = null;\n }\n };\n }, [dismissOnce, duration, paused]);\n\n return (\n <div\n className=\"animate-in slide-in-from-right-full fade-in w-80 duration-200\"\n role={isUrgent ? \"alert\" : \"status\"}\n aria-live={isUrgent ? \"assertive\" : \"polite\"}\n aria-atomic=\"true\"\n onMouseEnter={() => setPaused(true)}\n onMouseLeave={() => setPaused(false)}\n onFocus={() => setPaused(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) {\n setPaused(false);\n }\n }}\n data-opt-id=\"26YVM\"\n data-opt-slug=\"notification-toast.NotificationToast\"\n >\n <Alert\n variant={toast.variant}\n title={toast.title}\n dismissible\n onDismiss={dismissOnce}\n >\n {toast.message}\n {toast.actions && toast.actions.length > 0 && (\n <div className=\"gap-element mt-2 flex\">\n {toast.actions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n onClick={action.onClick}\n className=\"text-xs font-medium underline hover:no-underline\"\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </Alert>\n </div>\n );\n}\n","\"use client\";\n\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport {\n Composite,\n CompositeItem,\n CompositeProvider,\n} from \"../core/composite-zone\";\nimport type { FailureItem } from \"../lib/types\";\nimport {\n OPT_FOCUS,\n OPT_FOCUS_VISIBLE,\n OPT_TEXT_PRIMARY,\n OPT_TEXT_SECONDARY,\n OPT_TEXT_TERTIARY,\n OPT_BORDER,\n} from \"../lib/styles\";\nimport { cn } from \"../lib/cn\";\nimport { Badge } from \"../core/badge\";\n\n// ── Labels ──\n\ninterface TimeAgoLabels {\n justNow: string;\n minutesAgo: string;\n hoursAgo: string;\n daysAgo: string;\n}\n\n/** Localized labels for the failure list component. */\nexport interface FailureListLabels {\n title?: string;\n emptyMessage?: string;\n moreItems?: string;\n severityLabels?: Partial<Record<\"critical\" | \"error\" | \"warning\", string>>;\n timeAgo?: Partial<TimeAgoLabels>;\n}\n\ninterface DefaultLabels {\n title: string;\n emptyMessage: string;\n moreItems: string;\n severityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n timeAgo: TimeAgoLabels;\n}\n\nconst defaultLabels: DefaultLabels = {\n title: \"최근 실패\",\n emptyMessage: \"실패 항목이 없습니다\",\n moreItems: \"{count}개 더 보기\",\n severityLabels: {\n critical: \"심각\",\n error: \"오류\",\n warning: \"경고\",\n },\n timeAgo: {\n justNow: \"방금 전\",\n minutesAgo: \"{minutes}분 전\",\n hoursAgo: \"{hours}시간 전\",\n daysAgo: \"{days}일 전\",\n },\n};\n\n// ── Severity ──\n\nconst severityVariant: Record<FailureItem[\"severity\"], \"error\" | \"warning\"> = {\n critical: \"error\",\n error: \"error\",\n warning: \"warning\",\n};\n\nconst severityBorder: Record<FailureItem[\"severity\"], string> = {\n critical: \"border-l-2 border-l-danger\",\n error: \"border-l-2 border-l-danger\",\n warning: \"border-l-2 border-l-warning\",\n};\n\n// ── Props ──\n\n/** Props for the failure list component. */\nexport interface FailureListProps {\n failures: FailureItem[];\n title?: string;\n maxItems?: number;\n /** Group failures by `group` field */\n grouped?: boolean;\n onFailureClick?: (failure: FailureItem) => void;\n onShowMore?: () => void;\n labels?: FailureListLabels;\n locale?: string;\n loading?: boolean;\n renderActions?: (failure: FailureItem) => ReactNode;\n className?: string;\n}\n\n// ── Helpers ──\n\nfunction formatRelativeTime(\n timestamp: string,\n timeLabels: TimeAgoLabels,\n locale: string,\n): string {\n const now = new Date();\n const date = new Date(timestamp);\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return timeLabels.justNow;\n if (diffMins < 60)\n return timeLabels.minutesAgo.replace(\"{minutes}\", String(diffMins));\n if (diffHours < 24)\n return timeLabels.hoursAgo.replace(\"{hours}\", String(diffHours));\n if (diffDays < 7)\n return timeLabels.daysAgo.replace(\"{days}\", String(diffDays));\n return date.toLocaleDateString(locale);\n}\n\nfunction groupBy<T>(items: T[], key: (item: T) => string): Map<string, T[]> {\n const map = new Map<string, T[]>();\n for (const item of items) {\n const k = key(item);\n const existing = map.get(k);\n if (existing) {\n existing.push(item);\n } else {\n map.set(k, [item]);\n }\n }\n return map;\n}\n\n// ── Component ──\n\nfunction FailureItemRow({\n failure,\n isLast,\n onFailureClick,\n renderActions,\n mergedSeverityLabels,\n mergedTimeAgo,\n locale,\n}: {\n failure: FailureItem;\n isLast: boolean;\n onFailureClick?: (failure: FailureItem) => void;\n renderActions?: (failure: FailureItem) => ReactNode;\n mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n mergedTimeAgo: TimeAgoLabels;\n locale: string;\n}) {\n const itemId = `failure-${failure.id}`;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!onFailureClick) return;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onFailureClick(failure);\n };\n\n return (\n <CompositeItem\n render={<article />}\n key={failure.id}\n role=\"article\"\n aria-labelledby={itemId}\n className={cn(\n \"group gap-group relative flex w-full items-start p-3\",\n OPT_FOCUS_VISIBLE,\n \"data-[active-item]:bg-accent-subtle\",\n onFailureClick && \"cursor-pointer\",\n !isLast && \"border-border-subtle border-b\",\n severityBorder[failure.severity],\n )}\n onClick={() => onFailureClick?.(failure)}\n onKeyDown={handleKeyDown}\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"gap-element flex items-center\">\n <Badge variant={severityVariant[failure.severity]} size=\"sm\">\n {mergedSeverityLabels[failure.severity]}\n </Badge>\n <span\n id={itemId}\n className={`text-sm font-medium ${OPT_TEXT_PRIMARY} truncate`}\n >\n {failure.title}\n </span>\n </div>\n\n {failure.message && (\n <p className={`mt-1 text-xs ${OPT_TEXT_SECONDARY} line-clamp-2`}>\n {failure.message}\n </p>\n )}\n\n <time\n dateTime={failure.timestamp}\n className={`mt-1 block text-xs ${OPT_TEXT_TERTIARY}`}\n >\n {formatRelativeTime(failure.timestamp, mergedTimeAgo, locale)}\n </time>\n </div>\n\n {renderActions && (\n <div className=\"flex shrink-0 items-center gap-1\">\n {renderActions(failure)}\n </div>\n )}\n </CompositeItem>\n );\n}\n\n/** Renders the failure list component. */\nexport function FailureList({\n failures,\n title,\n maxItems,\n grouped = false,\n onFailureClick,\n onShowMore,\n labels: customLabels,\n locale = \"ko-KR\",\n loading = false,\n renderActions,\n className,\n}: FailureListProps) {\n const mergedTimeAgo: TimeAgoLabels = {\n justNow: customLabels?.timeAgo?.justNow ?? defaultLabels.timeAgo.justNow,\n minutesAgo:\n customLabels?.timeAgo?.minutesAgo ?? defaultLabels.timeAgo.minutesAgo,\n hoursAgo: customLabels?.timeAgo?.hoursAgo ?? defaultLabels.timeAgo.hoursAgo,\n daysAgo: customLabels?.timeAgo?.daysAgo ?? defaultLabels.timeAgo.daysAgo,\n };\n const mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string> =\n {\n critical:\n customLabels?.severityLabels?.critical ??\n defaultLabels.severityLabels.critical,\n error:\n customLabels?.severityLabels?.error ??\n defaultLabels.severityLabels.error,\n warning:\n customLabels?.severityLabels?.warning ??\n defaultLabels.severityLabels.warning,\n };\n const labels = {\n title: customLabels?.title ?? defaultLabels.title,\n emptyMessage: customLabels?.emptyMessage ?? defaultLabels.emptyMessage,\n moreItems: customLabels?.moreItems ?? defaultLabels.moreItems,\n };\n\n const displayTitle = title ?? labels.title;\n\n const allItems = maxItems ? failures.slice(0, maxItems) : failures;\n const remainingCount = maxItems ? Math.max(0, failures.length - maxItems) : 0;\n\n const rowProps = {\n onFailureClick,\n renderActions,\n mergedSeverityLabels,\n mergedTimeAgo,\n locale,\n };\n\n return (\n <div\n className={className}\n data-opt-id=\"ZAM3R\"\n data-opt-slug=\"failure-list.FailureList\"\n >\n <div className=\"gap-group flex flex-col\">\n {displayTitle && (\n <h3 className={`text-sm font-semibold ${OPT_TEXT_PRIMARY}`}>\n {displayTitle}\n </h3>\n )}\n\n {failures.length === 0 ? (\n <div\n role=\"status\"\n className={`py-8 text-center text-sm ${OPT_TEXT_SECONDARY}`}\n >\n {labels.emptyMessage}\n </div>\n ) : (\n <CompositeProvider focusLoop orientation=\"vertical\">\n <Composite\n role=\"feed\"\n aria-label={displayTitle}\n aria-busy={loading}\n className={`rounded-lg ${OPT_BORDER} bg-surface`}\n >\n {grouped\n ? renderGrouped(\n allItems,\n remainingCount,\n rowProps,\n labels,\n onShowMore,\n )\n : renderFlat(\n allItems,\n remainingCount,\n rowProps,\n labels,\n onShowMore,\n )}\n </Composite>\n </CompositeProvider>\n )}\n </div>\n </div>\n );\n}\n\nfunction renderFlat(\n items: FailureItem[],\n remainingCount: number,\n rowProps: {\n onFailureClick?: (failure: FailureItem) => void;\n renderActions?: (failure: FailureItem) => ReactNode;\n mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n mergedTimeAgo: TimeAgoLabels;\n locale: string;\n },\n labels: { moreItems: string },\n onShowMore?: () => void,\n) {\n return (\n <>\n {items.map((failure, index) => (\n <FailureItemRow\n key={failure.id}\n failure={failure}\n isLast={index === items.length - 1 && remainingCount === 0}\n {...rowProps}\n />\n ))}\n {remainingCount > 0 && (\n <CompositeItem\n render={<button type=\"button\" />}\n onClick={onShowMore}\n className={`border-border-subtle w-full border-t p-3 text-center text-xs font-medium ${OPT_TEXT_SECONDARY} ${OPT_FOCUS} hover:text-accent data-[active-item]:bg-accent-subtle transition-colors`}\n aria-label={`${remainingCount}개의 실패 더 보기`}\n >\n {labels.moreItems.replace(\"{count}\", String(remainingCount))}\n </CompositeItem>\n )}\n </>\n );\n}\n\nfunction renderGrouped(\n items: FailureItem[],\n remainingCount: number,\n rowProps: {\n onFailureClick?: (failure: FailureItem) => void;\n renderActions?: (failure: FailureItem) => ReactNode;\n mergedSeverityLabels: Record<\"critical\" | \"error\" | \"warning\", string>;\n mergedTimeAgo: TimeAgoLabels;\n locale: string;\n },\n labels: { moreItems: string },\n onShowMore?: () => void,\n) {\n const groups = groupBy(items, (f) => f.group ?? \"\");\n const groupEntries = Array.from(groups.entries());\n\n return (\n <>\n {groupEntries.map(([groupName, groupItems], groupIndex) => {\n const isLastGroup =\n groupIndex === groupEntries.length - 1 && remainingCount === 0;\n\n return (\n <div key={groupName || \"__ungrouped__\"}>\n {groupName && (\n <div\n className={cn(\n `px-3 py-2 text-xs font-semibold ${OPT_TEXT_TERTIARY} tracking-wider uppercase`,\n groupIndex > 0 && \"border-border-subtle border-t\",\n )}\n >\n {groupName}\n </div>\n )}\n {groupItems.map((failure, index) => (\n <FailureItemRow\n key={failure.id}\n failure={failure}\n isLast={isLastGroup && index === groupItems.length - 1}\n {...rowProps}\n />\n ))}\n </div>\n );\n })}\n {remainingCount > 0 && (\n <CompositeItem\n render={<button type=\"button\" />}\n onClick={onShowMore}\n className={`border-border-subtle w-full border-t p-3 text-center text-xs font-medium ${OPT_TEXT_SECONDARY} ${OPT_FOCUS} hover:text-accent data-[active-item]:bg-accent-subtle transition-colors`}\n aria-label={`${remainingCount}개의 실패 더 보기`}\n >\n {labels.moreItems.replace(\"{count}\", String(remainingCount))}\n </CompositeItem>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback, useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/** Defines the key value entry shape. */\nexport interface KeyValueEntry {\n id: string;\n key: string;\n value: string;\n isSecret?: boolean;\n}\n\n/** Localized labels for the key value editor component. */\nexport interface KeyValueEditorLabels {\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n addButton?: string;\n removeAriaLabel?: string;\n toggleSecretAriaLabel?: string;\n emptyMessage?: string;\n}\n\nconst defaultLabels: Required<KeyValueEditorLabels> = {\n keyPlaceholder: \"키\",\n valuePlaceholder: \"값\",\n addButton: \"추가\",\n removeAriaLabel: \"항목 삭제\",\n toggleSecretAriaLabel: \"비밀값 토글\",\n emptyMessage: \"항목이 없습니다. 추가 버튼을 눌러주세요.\",\n};\n\n/** Props for the key value editor component. */\nexport interface KeyValueEditorProps {\n /** Current entries (controlled) */\n value?: KeyValueEntry[];\n /** Initial entries (uncontrolled) */\n defaultValue?: KeyValueEntry[];\n /** Called when entries change */\n onChange?: (entries: KeyValueEntry[]) => void;\n /** Allow toggling secret/password visibility */\n showSecretToggle?: boolean;\n /** Maximum number of entries allowed */\n maxEntries?: number;\n /** Whether entries are read-only */\n readOnly?: boolean;\n /** Custom labels for i18n */\n labels?: KeyValueEditorLabels;\n /** Render custom actions per entry */\n renderActions?: (entry: KeyValueEntry, index: number) => ReactNode;\n /** Validate key on change. Return error message or undefined. */\n validateKey?: (key: string, entries: KeyValueEntry[]) => string | undefined;\n className?: string;\n}\n\nlet idCounter = 0;\nfunction generateId() {\n return `kv-${++idCounter}`;\n}\n\n/** Renders the key value editor component. */\nexport function KeyValueEditor({\n value: controlledValue,\n defaultValue,\n onChange,\n showSecretToggle = false,\n maxEntries,\n readOnly = false,\n labels: customLabels,\n renderActions,\n validateKey,\n className,\n}: KeyValueEditorProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [internalEntries, setInternalEntries] = useState<KeyValueEntry[]>(\n () => defaultValue ?? [],\n );\n const entries = controlledValue ?? internalEntries;\n const keyInputRef = useRef<HTMLInputElement>(null);\n\n const updateEntries = useCallback(\n (next: KeyValueEntry[]) => {\n if (!controlledValue) {\n setInternalEntries(next);\n }\n onChange?.(next);\n },\n [controlledValue, onChange],\n );\n\n const addEntry = useCallback(() => {\n if (maxEntries && entries.length >= maxEntries) return;\n const newEntry: KeyValueEntry = {\n id: generateId(),\n key: \"\",\n value: \"\",\n isSecret: false,\n };\n updateEntries([...entries, newEntry]);\n // Focus the new key input after render\n requestAnimationFrame(() => {\n keyInputRef.current\n ?.closest(\"[data-kv-list]\")\n ?.querySelector<HTMLInputElement>(\n `[data-kv-id=\"${newEntry.id}\"] [data-kv-key]`,\n )\n ?.focus();\n });\n }, [entries, maxEntries, updateEntries]);\n\n const removeEntry = useCallback(\n (id: string) => {\n updateEntries(entries.filter((e) => e.id !== id));\n },\n [entries, updateEntries],\n );\n\n const updateEntry = useCallback(\n (id: string, field: \"key\" | \"value\", val: string) => {\n updateEntries(\n entries.map((e) => (e.id === id ? { ...e, [field]: val } : e)),\n );\n },\n [entries, updateEntries],\n );\n\n const toggleSecret = useCallback(\n (id: string) => {\n updateEntries(\n entries.map((e) => (e.id === id ? { ...e, isSecret: !e.isSecret } : e)),\n );\n },\n [entries, updateEntries],\n );\n\n const canAdd = !readOnly && (!maxEntries || entries.length < maxEntries);\n\n return (\n <div\n className={cn(\"gap-group flex flex-col\", className)}\n data-opt-id=\"NCBWA\"\n data-opt-slug=\"key-value-editor.KeyValueEditor\"\n >\n {entries.length === 0 ? (\n <p className=\"text-text-tertiary py-4 text-center text-sm\">\n {labels.emptyMessage}\n </p>\n ) : (\n <div className=\"gap-element flex flex-col\" data-kv-list>\n {entries.map((entry, index) => {\n const keyError = validateKey?.(entry.key, entries);\n return (\n <div\n key={entry.id}\n data-kv-id={entry.id}\n className={cn(\n \"gap-element flex items-start\",\n \"border-border rounded-lg border p-3\",\n \"bg-surface\",\n )}\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <input\n data-kv-key\n ref={index === entries.length - 1 ? keyInputRef : undefined}\n type=\"text\"\n value={entry.key}\n onChange={(e) =>\n updateEntry(entry.id, \"key\", e.target.value)\n }\n placeholder={labels.keyPlaceholder}\n readOnly={readOnly}\n aria-label={`${labels.keyPlaceholder} ${index + 1}`}\n className={cn(\n \"border-border bg-bg-subtle text-text-primary placeholder:text-text-tertiary w-full rounded-md border px-3 py-1.5 font-mono text-sm\",\n \"focus:border-accent focus-visible:ring-ring focus-visible:ring-offset-ring-offset focus-visible:ring-2 focus-visible:ring-offset-1\",\n readOnly && \"cursor-default opacity-70\",\n keyError && \"border-error\",\n )}\n />\n {keyError && (\n <span className=\"text-error text-xs\">{keyError}</span>\n )}\n </div>\n <span className=\"text-text-tertiary px-1 py-1.5\">=</span>\n <div className=\"min-w-0 flex-1\">\n <input\n type={entry.isSecret ? \"password\" : \"text\"}\n value={entry.value}\n onChange={(e) =>\n updateEntry(entry.id, \"value\", e.target.value)\n }\n placeholder={labels.valuePlaceholder}\n readOnly={readOnly}\n aria-label={`${labels.valuePlaceholder} ${index + 1}`}\n className={cn(\n \"border-border bg-bg-subtle text-text-primary placeholder:text-text-tertiary w-full rounded-md border px-3 py-1.5 font-mono text-sm\",\n \"focus:border-accent focus-visible:ring-ring focus-visible:ring-offset-ring-offset focus-visible:ring-2 focus-visible:ring-offset-1\",\n readOnly && \"cursor-default opacity-70\",\n )}\n />\n </div>\n {showSecretToggle && !readOnly && (\n <button\n type=\"button\"\n onClick={() => toggleSecret(entry.id)}\n aria-label={labels.toggleSecretAriaLabel}\n aria-pressed={entry.isSecret}\n className=\"text-text-tertiary hover:text-text-primary shrink-0 rounded p-1.5 transition-colors\"\n >\n {entry.isSecret ? (\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88\"\n />\n </svg>\n ) : (\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n )}\n </button>\n )}\n {renderActions?.(entry, index)}\n {!readOnly && (\n <button\n type=\"button\"\n onClick={() => removeEntry(entry.id)}\n aria-label={labels.removeAriaLabel}\n className=\"text-text-tertiary hover:text-error shrink-0 rounded p-1.5 transition-colors\"\n >\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n })}\n </div>\n )}\n {canAdd && (\n <button\n type=\"button\"\n onClick={addEntry}\n className={cn(\n \"border-border text-text-secondary rounded-lg border border-dashed px-4 py-2 text-sm transition-colors\",\n \"hover:border-accent hover:text-accent\",\n )}\n >\n {labels.addButton}\n </button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Badge } from \"../core/badge\";\n\n/** Defines the workflow canvas step shape. */\nexport interface WorkflowCanvasStep {\n id: string;\n title: string;\n row: number;\n col: number;\n status?: \"idle\" | \"running\" | \"success\" | \"error\";\n}\n\n/** Defines the workflow canvas connection shape. */\nexport interface WorkflowCanvasConnection {\n from: string;\n to: string;\n label?: string;\n}\n\n/** Localized labels for the workflow canvas component. */\nexport type WorkflowCanvasLabels = Record<never, never>;\n\n/** Props for the workflow canvas component. */\nexport interface WorkflowCanvasProps {\n steps: WorkflowCanvasStep[];\n connections?: WorkflowCanvasConnection[];\n rows?: number;\n cols?: number;\n cellSize?: number;\n gap?: number;\n title?: string;\n emptyMessage?: string;\n selectedStepId?: string;\n onSelectStep?: (step: WorkflowCanvasStep) => void;\n onStepMove?: (stepId: string, row: number, col: number) => void;\n renderStep?: (step: WorkflowCanvasStep, selected: boolean) => React.ReactNode;\n className?: string;\n}\n\nconst statusVariant = {\n idle: \"default\",\n running: \"info\",\n success: \"success\",\n error: \"error\",\n} as const;\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/** Renders the workflow canvas component. */\nexport function WorkflowCanvas({\n steps,\n connections = [],\n rows = 9,\n cols = 9,\n cellSize = 72,\n gap = 12,\n title = \"Workflow Canvas\",\n emptyMessage = \"No workflow steps\",\n selectedStepId,\n onSelectStep,\n onStepMove,\n renderStep,\n className,\n}: WorkflowCanvasProps) {\n const stepMap = React.useMemo(\n () => new Map(steps.map((step) => [step.id, step])),\n [steps],\n );\n\n const width = cols * cellSize + (cols - 1) * gap;\n const height = rows * cellSize + (rows - 1) * gap;\n\n const renderDefaultStep = React.useCallback(\n (step: WorkflowCanvasStep, selected: boolean) => (\n <button\n type=\"button\"\n onClick={() => onSelectStep?.(step)}\n className={cn(\n \"group absolute flex h-full w-full flex-col justify-between rounded-lg border p-2 text-left transition-colors\",\n selected\n ? \"border-accent bg-accent-subtle\"\n : \"border-border bg-surface hover:bg-bg-subtle\",\n )}\n >\n <span className=\"text-text-primary truncate text-xs font-medium\">\n {step.title}\n </span>\n {step.status && (\n <Badge\n variant={statusVariant[step.status]}\n size=\"sm\"\n className=\"w-fit\"\n >\n {step.status}\n </Badge>\n )}\n </button>\n ),\n [onSelectStep],\n );\n\n const handleStepKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>, step: WorkflowCanvasStep) => {\n if (!onStepMove) {\n return;\n }\n\n let nextRow = step.row;\n let nextCol = step.col;\n\n switch (event.key) {\n case \"ArrowUp\":\n nextRow -= 1;\n break;\n case \"ArrowDown\":\n nextRow += 1;\n break;\n case \"ArrowLeft\":\n nextCol -= 1;\n break;\n case \"ArrowRight\":\n nextCol += 1;\n break;\n default:\n return;\n }\n\n event.preventDefault();\n onStepMove(\n step.id,\n clamp(nextRow, 0, rows - 1),\n clamp(nextCol, 0, cols - 1),\n );\n },\n [onStepMove, rows, cols],\n );\n\n return (\n <div\n className={cn(\"gap-group flex flex-col\", className)}\n data-opt-id=\"4TX11\"\n data-opt-slug=\"workflow-canvas.WorkflowCanvas\"\n >\n <h3 className=\"text-text-primary text-sm font-semibold\">{title}</h3>\n\n {steps.length === 0 ? (\n <div className=\"text-text-secondary border-border rounded-lg border border-dashed p-8 text-center text-sm\">\n {emptyMessage}\n </div>\n ) : (\n <div className=\"border-border bg-bg-subtle relative overflow-auto rounded-lg border p-3\">\n <div\n role=\"grid\"\n aria-label={title}\n className=\"relative\"\n style={{ width, height }}\n >\n <div\n className=\"grid\"\n style={{\n gridTemplateColumns: `repeat(${cols}, ${cellSize}px)`,\n gridTemplateRows: `repeat(${rows}, ${cellSize}px)`,\n gap,\n }}\n >\n {Array.from({ length: rows * cols }, (_, i) => (\n <div\n key={i}\n aria-hidden=\"true\"\n className=\"border-border-subtle bg-surface/30 rounded-md border border-dashed\"\n />\n ))}\n </div>\n\n <svg\n className=\"pointer-events-none absolute inset-0\"\n width={width}\n height={height}\n aria-hidden=\"true\"\n >\n {connections.map((connection) => {\n const from = stepMap.get(connection.from);\n const to = stepMap.get(connection.to);\n if (!from || !to) {\n return null;\n }\n\n const x1 = from.col * (cellSize + gap) + cellSize / 2;\n const y1 = from.row * (cellSize + gap) + cellSize / 2;\n const x2 = to.col * (cellSize + gap) + cellSize / 2;\n const y2 = to.row * (cellSize + gap) + cellSize / 2;\n\n return (\n <g key={`${connection.from}-${connection.to}`}>\n <line\n x1={x1}\n y1={y1}\n x2={x2}\n y2={y2}\n stroke=\"currentColor\"\n strokeOpacity=\"0.35\"\n strokeWidth=\"2\"\n />\n {connection.label && (\n <text\n x={(x1 + x2) / 2}\n y={(y1 + y2) / 2 - 4}\n textAnchor=\"middle\"\n className=\"fill-text-secondary text-[10px]\"\n >\n {connection.label}\n </text>\n )}\n </g>\n );\n })}\n </svg>\n\n {steps.map((step) => {\n const selected = selectedStepId === step.id;\n\n return (\n <div\n key={step.id}\n role=\"gridcell\"\n tabIndex={0}\n aria-selected={selected}\n aria-label={`${step.title} (${step.row + 1}, ${step.col + 1})`}\n onKeyDown={(event) => handleStepKeyDown(event, step)}\n className=\"focus-visible:ring-ring absolute focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-white focus-visible:outline-none\"\n style={{\n width: cellSize,\n height: cellSize,\n left: step.col * (cellSize + gap),\n top: step.row * (cellSize + gap),\n }}\n >\n {renderStep\n ? renderStep(step, selected)\n : renderDefaultStep(step, selected)}\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n\nWorkflowCanvas.displayName = \"WorkflowCanvas\";\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n/** Configuration for {@link useAutoRefresh}. */\nexport interface AutoRefreshOptions {\n /** Milliseconds between runs. `0` disables the timer. */\n interval: number;\n paused?: boolean;\n /** Called on each tick. If it returns a promise, the next wait starts after it settles. */\n onRefresh?: () => void | Promise<unknown>;\n}\n\n/**\n * A refresh timer that waits for its own work.\n *\n * A plain `setInterval` fires on a schedule regardless of whether the previous\n * query came back, so a five-second interval over a seven-second query stacks\n * requests until something gives. Chaining the next wait onto the settled\n * promise keeps exactly one refresh in flight, and a rejection stops the loop\n * instead of hammering an endpoint that is already failing.\n */\nexport function useAutoRefresh({\n interval,\n paused = false,\n onRefresh,\n}: AutoRefreshOptions): void {\n const callbackRef = useRef(onRefresh);\n callbackRef.current = onRefresh;\n\n useEffect(() => {\n if (paused || interval <= 0 || !callbackRef.current) return;\n\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const schedule = () => {\n timer = setTimeout(async () => {\n if (cancelled) return;\n try {\n await callbackRef.current?.();\n } catch {\n // The caller owns error reporting; stop the loop rather than\n // retrying against something that is already broken.\n return;\n }\n if (!cancelled) schedule();\n }, interval);\n };\n\n schedule();\n\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [interval, paused]);\n}\n","\"use client\";\n\nimport {\n ChevronLeft,\n ChevronRight,\n Clock,\n RefreshCw,\n ZoomIn,\n ZoomOut,\n} from \"lucide-react\";\nimport { useCallback, useMemo, useState, type KeyboardEvent } from \"react\";\nimport {\n formatCountUnit,\n formatDuration,\n formatInstant,\n isDateOnly,\n isExactMinutes,\n isRelativeExpression,\n isRelativeToNow,\n measureTimeWindow,\n parseRelativeParts,\n parseTimeExpression,\n shiftTimeRange,\n zoomTimeRange,\n type TimeRange,\n} from \"@reopt-ai/opt-charts\";\nimport { Button } from \"../core/button\";\nimport { Input } from \"../core/input\";\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from \"../core/popover\";\nimport {\n SelectItem,\n SelectPopover,\n SelectRoot,\n SelectTrigger,\n} from \"../core/select\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_TEXT_SECONDARY } from \"../lib/styles\";\nimport { useAutoRefresh } from \"../lib/use-auto-refresh\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type { TimeRange };\n\n/** A named window offered in the quick-select list. */\nexport interface TimeRangePreset {\n label: string;\n range: TimeRange;\n}\n\n/** How often the control asks its owner to re-query. */\nexport interface RefreshSetting {\n /** Milliseconds. `0` means off. */\n interval: number;\n paused: boolean;\n}\n\n/** Localized strings for the time range control. */\nexport interface TimeRangeControlLabels {\n trigger?: string;\n invalid?: string;\n last?: (duration: string) => string;\n next?: (duration: string) => string;\n quickSelect?: string;\n apply?: string;\n update?: string;\n refresh?: string;\n commonlyUsed?: string;\n recentlyUsed?: string;\n start?: string;\n end?: string;\n startHint?: string;\n autoRefresh?: string;\n autoRefreshOff?: string;\n every?: (duration: string) => string;\n previous?: string;\n nextWindow?: string;\n zoomIn?: string;\n zoomOut?: string;\n /** e.g. \"This day\" for a window snapped to a calendar unit. */\n thisUnit?: (unit: string) => string;\n units?: Partial<Record<TimeUnitKey, string>>;\n}\n\n/** Units the control can name. `s` only shows up in a parsed expression. */\ntype TimeUnitKey = \"s\" | \"m\" | \"h\" | \"d\" | \"w\" | \"M\" | \"y\";\n\nconst defaultLabels: Required<Omit<TimeRangeControlLabels, \"units\">> & {\n units: Record<TimeUnitKey, string>;\n} = {\n trigger: \"Select time range\",\n invalid: \"Invalid time range\",\n last: (duration) => `Last ${duration}`,\n next: (duration) => `Next ${duration}`,\n quickSelect: \"Quick select\",\n apply: \"Apply\",\n update: \"Update\",\n refresh: \"Refresh\",\n commonlyUsed: \"Commonly used\",\n recentlyUsed: \"Recently used\",\n start: \"Start\",\n end: \"End\",\n startHint: \"Absolute time or date math, e.g. now-7d\",\n autoRefresh: \"Auto refresh\",\n autoRefreshOff: \"Off\",\n every: (duration) => `Every ${duration}`,\n previous: \"Previous window\",\n nextWindow: \"Next window\",\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n thisUnit: (unit) => `This ${unit}`,\n units: {\n s: \"seconds\",\n m: \"minutes\",\n h: \"hours\",\n d: \"days\",\n w: \"weeks\",\n M: \"months\",\n y: \"years\",\n },\n};\n\n/** Props for the time range control. */\nexport interface TimeRangeControlProps {\n value: TimeRange;\n onChange: (range: TimeRange) => void;\n\n /** Named windows shown in the popover. */\n presets?: TimeRangePreset[];\n /** Windows the user picked before, newest first. Owned by the caller. */\n recentRanges?: TimeRangePreset[];\n\n /** IANA zone used for rounding and display. */\n timeZone?: string;\n locale?: string;\n\n /**\n * Hold edits until the user commits them. A queried window is expensive;\n * typing \"now-3\" should not fire three requests.\n */\n showUpdateButton?: boolean;\n /** Step the window back and forth, and widen or narrow it. */\n showWindowButtons?: boolean;\n /** Zoom-out step, as a fraction of the current width. */\n zoomFactor?: number;\n\n refresh?: RefreshSetting;\n onRefreshChange?: (setting: RefreshSetting) => void;\n /** Called by the refresh button and by each auto-refresh tick. */\n onRefresh?: () => void | Promise<unknown>;\n\n isLoading?: boolean;\n disabled?: boolean;\n className?: string;\n labels?: TimeRangeControlLabels;\n \"aria-label\"?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nconst QUICK_UNITS = [\"m\", \"h\", \"d\", \"w\", \"M\", \"y\"] as const;\ntype QuickUnit = (typeof QUICK_UNITS)[number];\n\nconst REFRESH_INTERVALS = [0, 5_000, 10_000, 30_000, 60_000, 300_000];\n\nfunction selectValue(value: string | string[]): string {\n return Array.isArray(value) ? (value[0] ?? \"\") : value;\n}\n\n/**\n * What the trigger says.\n *\n * A window anchored to `now` deserves its intent (\"Last 7 days\"), not two\n * timestamps the reader has to subtract. Everything else gets both ends\n * spelled out. A duration that does not divide into whole minutes is prefixed\n * with `~` rather than rounded silently.\n */\nfunction describeRange(\n range: TimeRange,\n labels: typeof defaultLabels,\n options: { locale?: string; timeZone?: string; now?: number },\n): { text: string; isInvalid: boolean } {\n const window = measureTimeWindow(range, {\n timeZone: options.timeZone,\n now: options.now,\n });\n if (window.isInvalid) return { text: labels.invalid, isInvalid: true };\n\n // A window that snaps to a calendar unit on both ends is that unit:\n // `now/d – now/d` is \"This day\", not two timestamps a day apart.\n const fromParts = parseRelativeParts(range.from);\n const toParts = parseRelativeParts(range.to);\n if (\n fromParts?.roundUnit &&\n fromParts.count === 0 &&\n toParts?.roundUnit === fromParts.roundUnit &&\n toParts.count === 0\n ) {\n return {\n text: labels.thisUnit(\n formatCountUnit(1, fromParts.roundUnit, options.locale).replace(\n /^1\\s*/,\n \"\",\n ),\n ),\n isInvalid: false,\n };\n }\n\n if (isRelativeToNow(range)) {\n const anchoredAtEnd = (toParts?.count ?? 0) === 0;\n const parts = anchoredAtEnd ? fromParts : toParts;\n // Say it back in the unit it was asked in: `now-90d` is \"90 days\", and\n // re-deriving from milliseconds would answer \"3 months\" to a different\n // question.\n //\n // A window snapped to whole units counts inclusively: `now-29d/d … now/d`\n // covers thirty days, not the twenty-nine its offset names. Counting in\n // the expression's own unit is also the only way to get that right —\n // measuring the milliseconds lands on \"1 month\", which is a different\n // claim about the same window.\n const bothSnapped =\n parts?.roundUnit === parts?.unit && toParts?.roundUnit === parts?.unit;\n const counted =\n parts && parts.count > 0\n ? formatCountUnit(\n parts.roundUnit && bothSnapped ? parts.count + 1 : parts.count,\n parts.unit,\n options.locale,\n )\n : null;\n const exact = counted !== null && (!parts?.roundUnit || bothSnapped);\n const duration = exact\n ? counted\n : formatDuration(window.duration, options.locale);\n const prefix = exact || isExactMinutes(window.duration) ? \"\" : \"~\";\n const text = anchoredAtEnd\n ? labels.last(`${prefix}${duration}`)\n : labels.next(`${prefix}${duration}`);\n return { text, isInvalid: false };\n }\n\n // A bound written as a calendar day is a day; printing a clock beside it\n // invents a precision the caller did not ask for.\n const dateOnly = isDateOnly(range.from) && isDateOnly(range.to);\n const from = formatInstant(window.from, { ...options, dateOnly });\n const to = formatInstant(window.to, { ...options, dateOnly });\n return { text: from === to ? from : `${from} – ${to}`, isInvalid: false };\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\n/**\n * TimeRangeControl — the window as an expression, not two frozen instants.\n *\n * Holding `{ from: \"now-7d\", to: \"now\" }` instead of a resolved pair is what\n * makes a saved board, a shared link and an auto-refresh timer all mean the\n * same thing tomorrow that they mean today. Around that sit the moves people\n * actually make on a chart: jump to a named window, step the same width back\n * and forth to compare, widen when the interesting thing is just off screen,\n * and let it re-query on a timer while they watch.\n *\n * @example\n * ```tsx\n * const [range, setRange] = useState<TimeRange>({ from: \"now-7d\", to: \"now\" });\n *\n * <TimeRangeControl\n * value={range}\n * onChange={setRange}\n * timeZone=\"Asia/Seoul\"\n * showWindowButtons\n * onRefresh={() => refetch()}\n * />\n * ```\n */\nexport function TimeRangeControl({\n value,\n onChange,\n presets,\n recentRanges,\n timeZone,\n locale,\n showUpdateButton = true,\n showWindowButtons = true,\n zoomFactor = 0.5,\n refresh,\n onRefreshChange,\n onRefresh,\n isLoading = false,\n disabled = false,\n className,\n labels: customLabels,\n \"aria-label\": ariaLabel,\n}: TimeRangeControlProps) {\n const labels = {\n ...defaultLabels,\n ...customLabels,\n units: { ...defaultLabels.units, ...customLabels?.units },\n };\n\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState<TimeRange | null>(null);\n const [quickCount, setQuickCount] = useState(\"15\");\n const [quickUnit, setQuickUnit] = useState<QuickUnit>(\"m\");\n\n const editing = draft ?? value;\n const hasChanges =\n draft !== null && (draft.from !== value.from || draft.to !== value.to);\n\n const description = useMemo(\n () => describeRange(value, labels, { locale, timeZone }),\n // `labels` is rebuilt each render by design; its content is what matters.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [value, locale, timeZone, customLabels],\n );\n\n const boundState = useCallback(\n (expression: string) =>\n parseTimeExpression(expression, { timeZone }) === null\n ? labels.invalid\n : undefined,\n [timeZone, labels],\n );\n\n const commit = useCallback(\n (range: TimeRange) => {\n setDraft(null);\n onChange(range);\n },\n [onChange],\n );\n\n const apply = useCallback(() => {\n if (draft) commit(draft);\n else onRefresh?.();\n }, [draft, commit, onRefresh]);\n\n // Enter commits from either bound input. The single Update button outside\n // the popover stays the one place a change is applied — two of them would\n // read as two different actions.\n const commitOnEnter = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key !== \"Enter\") return;\n apply();\n setOpen(false);\n },\n [apply],\n );\n\n const applyQuick = useCallback(() => {\n const count = Number(quickCount);\n if (!Number.isFinite(count) || count <= 0) return;\n commit({ from: `now-${Math.round(count)}${quickUnit}`, to: \"now\" });\n setOpen(false);\n }, [quickCount, quickUnit, commit]);\n\n const step = useCallback(\n (direction: 1 | -1) => {\n const next = shiftTimeRange(value, direction, { timeZone });\n if (next) commit(next);\n },\n [value, timeZone, commit],\n );\n\n const zoom = useCallback(\n (factor: number) => {\n const next = zoomTimeRange(value, factor, { timeZone });\n if (next) commit(next);\n },\n [value, timeZone, commit],\n );\n\n useAutoRefresh({\n interval: refresh?.interval ?? 0,\n paused: refresh?.paused ?? true,\n onRefresh,\n });\n\n const refreshLabel =\n !refresh || refresh.paused || refresh.interval === 0\n ? labels.autoRefreshOff\n : labels.every(formatDuration(refresh.interval, locale));\n\n return (\n <div\n className={cn(\n \"bg-surface inline-flex items-center rounded-lg border\",\n OPT_BORDER,\n className,\n )}\n role=\"group\"\n aria-label={ariaLabel ?? labels.trigger}\n data-opt-id=\"3WJ8H\"\n data-opt-slug=\"time-range-control.TimeRangeControl\"\n >\n <PopoverRoot open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n className={cn(\n \"text-text-primary h-10 gap-2\",\n description.isInvalid && \"text-danger-fg\",\n )}\n disabled={disabled}\n >\n <Clock className=\"text-text-tertiary h-4 w-4\" aria-hidden=\"true\" />\n <span className=\"truncate text-sm\">{description.text}</span>\n </PopoverTrigger>\n\n <PopoverContent className=\"gap-group flex w-80 flex-col\">\n {/* Quick select: \"Last N units\", the move people make most. */}\n <div className=\"gap-element flex flex-col\">\n <p className=\"text-text-primary text-xs font-medium\">\n {labels.quickSelect}\n </p>\n <div className=\"flex items-end gap-2\">\n <Input\n aria-label={labels.quickSelect}\n type=\"number\"\n min={1}\n size=\"sm\"\n className=\"w-20\"\n value={quickCount}\n onChange={(event) => setQuickCount(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") applyQuick();\n }}\n />\n <SelectRoot\n value={quickUnit}\n setValue={(next) =>\n setQuickUnit(selectValue(next) as QuickUnit)\n }\n >\n <SelectTrigger minWidth={110} aria-label={labels.quickSelect} />\n <SelectPopover>\n {QUICK_UNITS.map((unit) => (\n <SelectItem key={unit} value={unit}>\n {labels.units[unit]}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n <Button variant=\"secondary\" size=\"sm\" onClick={applyQuick}>\n {labels.apply}\n </Button>\n </div>\n </div>\n\n {/* Both bounds, editable as date math or an absolute timestamp. */}\n <div className=\"gap-element flex flex-col\">\n <Input\n label={labels.start}\n size=\"sm\"\n value={editing.from}\n error={boundState(editing.from)}\n hint={labels.startHint}\n onChange={(event) =>\n setDraft({ ...editing, from: event.target.value })\n }\n onKeyDown={commitOnEnter}\n />\n <Input\n label={labels.end}\n size=\"sm\"\n value={editing.to}\n error={boundState(editing.to)}\n onChange={(event) =>\n setDraft({ ...editing, to: event.target.value })\n }\n onKeyDown={commitOnEnter}\n />\n </div>\n\n {presets && presets.length > 0 && (\n <RangeList\n title={labels.commonlyUsed}\n items={presets}\n onPick={(range) => {\n commit(range);\n setOpen(false);\n }}\n />\n )}\n\n {recentRanges && recentRanges.length > 0 && (\n <RangeList\n title={labels.recentlyUsed}\n items={recentRanges.slice(0, 5)}\n onPick={(range) => {\n commit(range);\n setOpen(false);\n }}\n />\n )}\n\n {onRefreshChange && (\n <div className=\"gap-element flex flex-col\">\n <p className=\"text-text-primary text-xs font-medium\">\n {labels.autoRefresh}\n </p>\n <SelectRoot\n value={String(refresh?.paused ? 0 : (refresh?.interval ?? 0))}\n setValue={(next) => {\n const interval = Number(selectValue(next));\n onRefreshChange({ interval, paused: interval === 0 });\n }}\n >\n <SelectTrigger minWidth={140} aria-label={labels.autoRefresh} />\n <SelectPopover>\n {REFRESH_INTERVALS.map((interval) => (\n <SelectItem key={interval} value={String(interval)}>\n {interval === 0\n ? labels.autoRefreshOff\n : labels.every(formatDuration(interval, locale))}\n </SelectItem>\n ))}\n </SelectPopover>\n </SelectRoot>\n </div>\n )}\n </PopoverContent>\n </PopoverRoot>\n\n {showWindowButtons && (\n <div\n className={cn(\"flex items-center border-l\", OPT_BORDER)}\n role=\"group\"\n aria-label={labels.previous}\n >\n <IconButton\n label={labels.previous}\n disabled={disabled || description.isInvalid}\n onClick={() => step(-1)}\n >\n <ChevronLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton\n label={labels.zoomIn}\n disabled={disabled || description.isInvalid}\n onClick={() => zoom(-zoomFactor)}\n >\n <ZoomIn className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton\n label={labels.zoomOut}\n disabled={disabled || description.isInvalid}\n onClick={() => zoom(zoomFactor)}\n >\n <ZoomOut className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton\n label={labels.nextWindow}\n disabled={disabled || description.isInvalid}\n onClick={() => step(1)}\n >\n <ChevronRight className=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n )}\n\n {(onRefresh || showUpdateButton) && (\n <div className={cn(\"border-l pl-2 pr-2\", OPT_BORDER)}>\n <Button\n variant={hasChanges ? \"primary\" : \"secondary\"}\n size=\"sm\"\n loading={isLoading}\n disabled={disabled || description.isInvalid}\n onClick={apply}\n leftIcon={\n hasChanges ? undefined : (\n <RefreshCw className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n )\n }\n title={refreshLabel}\n >\n {hasChanges ? labels.update : labels.refresh}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nTimeRangeControl.displayName = \"TimeRangeControl\";\n\n/* ------------------------------------------------------------------ */\n/* Internals */\n/* ------------------------------------------------------------------ */\n\nfunction IconButton({\n label,\n disabled,\n onClick,\n children,\n}: {\n label: string;\n disabled?: boolean;\n onClick: () => void;\n children: React.ReactNode;\n}) {\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={label}\n title={label}\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </Button>\n );\n}\n\nfunction RangeList({\n title,\n items,\n onPick,\n}: {\n title: string;\n items: TimeRangePreset[];\n onPick: (range: TimeRange) => void;\n}) {\n return (\n <div className=\"gap-element flex flex-col\">\n <p className=\"text-text-primary text-xs font-medium\">{title}</p>\n <ul className=\"grid grid-cols-2 gap-1\">\n {items.map((item, index) => (\n <li key={`${item.label}-${index}`}>\n <button\n type=\"button\"\n className={cn(\n \"hover:bg-bg-subtle w-full cursor-pointer rounded px-2 py-1 text-left text-xs\",\n OPT_TEXT_SECONDARY,\n )}\n onClick={() => onPick(item.range)}\n >\n {item.label}\n </button>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\n/**\n * The windows most analytics tools open with. Exported so a caller gets a\n * sensible list without inventing date math of their own.\n */\nexport const DEFAULT_TIME_PRESETS: TimeRangePreset[] = [\n { label: \"Last 15 minutes\", range: { from: \"now-15m\", to: \"now\" } },\n { label: \"Last hour\", range: { from: \"now-1h\", to: \"now\" } },\n { label: \"Last 24 hours\", range: { from: \"now-24h\", to: \"now\" } },\n { label: \"Last 7 days\", range: { from: \"now-7d\", to: \"now\" } },\n { label: \"Last 30 days\", range: { from: \"now-30d\", to: \"now\" } },\n { label: \"Last 90 days\", range: { from: \"now-90d\", to: \"now\" } },\n { label: \"Today\", range: { from: \"now/d\", to: \"now/d\" } },\n { label: \"This week\", range: { from: \"now/w\", to: \"now/w\" } },\n];\n\nexport { isRelativeExpression };\n","\"use client\";\n\nimport { Undo2 } from \"lucide-react\";\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport {\n resolveTimeRange,\n TimeSeriesChart,\n toAbsoluteRange,\n type TimeGranularity,\n type TimeRange,\n type TimeSeriesAnnotation,\n type TimeSeriesChartProps,\n type TimeSeriesDef,\n type TimeSeriesPoint,\n} from \"@reopt-ai/opt-charts\";\nimport { Button } from \"../core/button\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_SURFACE, OPT_TEXT_SECONDARY } from \"../lib/styles\";\nimport {\n TimeRangeControl,\n type RefreshSetting,\n type TimeRangeControlLabels,\n type TimeRangePreset,\n} from \"./time-range-control\";\n\n/** Localized strings for the time series panel. */\nexport interface TimeSeriesPanelLabels {\n back?: string;\n legend?: string;\n control?: TimeRangeControlLabels;\n}\n\nconst defaultLabels: Required<Omit<TimeSeriesPanelLabels, \"control\">> = {\n back: \"Back to previous range\",\n legend: \"Series\",\n};\n\n/** Props for the time series panel. */\nexport interface TimeSeriesPanelProps {\n title?: ReactNode;\n description?: ReactNode;\n /** Extra controls for the header's right side. */\n actions?: ReactNode;\n\n data: TimeSeriesPoint[];\n series: TimeSeriesDef[];\n\n /** The queried window. Also pins the chart's axis. */\n range: TimeRange;\n onRangeChange: (range: TimeRange) => void;\n\n granularity?: TimeGranularity | \"auto\";\n timeZone?: string;\n locale?: string;\n\n /** Render the built-in time range control in the header. */\n showRangeControl?: boolean;\n presets?: TimeRangePreset[];\n recentRanges?: TimeRangePreset[];\n refresh?: RefreshSetting;\n onRefreshChange?: (setting: RefreshSetting) => void;\n onRefresh?: () => void | Promise<unknown>;\n\n /** Legend entries can be clicked to hide a series. */\n toggleableLegend?: boolean;\n annotations?: TimeSeriesAnnotation[];\n isLoading?: boolean;\n height?: number;\n className?: string;\n /** Anything the chart itself accepts, for the cases this shell does not name. */\n chartProps?: Omit<\n TimeSeriesChartProps,\n \"data\" | \"series\" | \"from\" | \"to\" | \"granularity\" | \"timeZone\" | \"locale\"\n >;\n labels?: TimeSeriesPanelLabels;\n \"aria-label\"?: string;\n}\n\n/**\n * TimeSeriesPanel — a chart you can steer.\n *\n * The point of putting the control and the chart in one component is the\n * loop between them: drag across the plot and the window narrows to what you\n * dragged, which re-queries, which redraws the axis you just picked. That\n * only works if someone owns the step back out again — so zoom keeps a\n * history, and the header offers the way back rather than leaving the reader\n * to retype the range they came from.\n *\n * @example\n * ```tsx\n * const [range, setRange] = useState<TimeRange>({ from: \"now-7d\", to: \"now\" });\n *\n * <TimeSeriesPanel\n * title=\"Sessions\"\n * data={points}\n * series={[{ dataKey: \"sessions\", name: \"Sessions\" }]}\n * range={range}\n * onRangeChange={setRange}\n * onRefresh={() => refetch()}\n * toggleableLegend\n * />\n * ```\n */\nexport function TimeSeriesPanel({\n title,\n description,\n actions,\n data,\n series,\n range,\n onRangeChange,\n granularity = \"auto\",\n timeZone,\n locale,\n showRangeControl = true,\n presets,\n recentRanges,\n refresh,\n onRefreshChange,\n onRefresh,\n toggleableLegend = false,\n annotations,\n isLoading = false,\n height = 280,\n className,\n chartProps,\n labels: customLabels,\n \"aria-label\": ariaLabel,\n}: TimeSeriesPanelProps) {\n const labels = { ...defaultLabels, ...customLabels };\n\n const [history, setHistory] = useState<TimeRange[]>([]);\n const [hidden, setHidden] = useState<string[]>([]);\n\n // The chart needs instants; the control speaks date math. Resolving here is\n // what lets \"now-7d\" pin an axis at all.\n const resolved = useMemo(\n () => resolveTimeRange(range, { timeZone }),\n [range, timeZone],\n );\n\n const visibleSeries = useMemo(\n () => series.filter((def) => !hidden.includes(def.dataKey)),\n [series, hidden],\n );\n\n const handleRangeSelect = useCallback(\n (selection: { from: number; to: number }) => {\n setHistory((current) => [...current, range].slice(-10));\n onRangeChange(toAbsoluteRange(selection));\n },\n [range, onRangeChange],\n );\n\n const goBack = useCallback(() => {\n setHistory((current) => {\n const previous = current[current.length - 1];\n if (previous) onRangeChange(previous);\n return current.slice(0, -1);\n });\n }, [onRangeChange]);\n\n const setRange = useCallback(\n (next: TimeRange) => {\n // A range chosen from the control is a fresh start, not a zoom step.\n setHistory([]);\n onRangeChange(next);\n },\n [onRangeChange],\n );\n\n const toggleSeries = useCallback((dataKey: string) => {\n setHidden((current) =>\n current.includes(dataKey)\n ? current.filter((key) => key !== dataKey)\n : [...current, dataKey],\n );\n }, []);\n\n return (\n <section\n className={cn(OPT_SURFACE, OPT_BORDER, \"flex flex-col\", className)}\n aria-label={ariaLabel}\n data-opt-id=\"Y0XCY\"\n data-opt-slug=\"time-series-panel.TimeSeriesPanel\"\n >\n <header className=\"gap-group flex flex-wrap items-start justify-between px-5 pt-5 pb-3\">\n <div className=\"gap-element flex min-w-0 flex-col\">\n {title && (\n <h3 className=\"text-text-primary truncate text-base font-semibold\">\n {title}\n </h3>\n )}\n {description && (\n <p className={cn(OPT_TEXT_SECONDARY, \"truncate text-sm\")}>\n {description}\n </p>\n )}\n </div>\n <div className=\"gap-element flex flex-wrap items-center\">\n {history.length > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={goBack}\n leftIcon={<Undo2 className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />}\n >\n {labels.back}\n </Button>\n )}\n {actions}\n {showRangeControl && (\n <TimeRangeControl\n value={range}\n onChange={setRange}\n presets={presets}\n recentRanges={recentRanges}\n timeZone={timeZone}\n locale={locale}\n refresh={refresh}\n onRefreshChange={onRefreshChange}\n onRefresh={onRefresh}\n isLoading={isLoading}\n labels={customLabels?.control}\n />\n )}\n </div>\n </header>\n\n <div className=\"px-2 pb-4\">\n <TimeSeriesChart\n data={data}\n series={visibleSeries}\n from={resolved?.from}\n to={resolved?.to}\n granularity={granularity}\n timeZone={timeZone}\n locale={locale}\n height={height}\n selectable\n onRangeSelect={handleRangeSelect}\n annotations={annotations}\n showLegend={series.length > 1}\n legendOptions={\n toggleableLegend\n ? { onClick: toggleSeries, inactiveKeys: hidden }\n : undefined\n }\n aria-label={\n typeof title === \"string\" ? `${title} time series` : ariaLabel\n }\n {...chartProps}\n />\n </div>\n </section>\n );\n}\n\nTimeSeriesPanel.displayName = \"TimeSeriesPanel\";\n","\"use client\";\n\nimport {\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n Minus,\n Plus,\n} from \"lucide-react\";\nimport {\n forwardRef,\n memo,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type Ref,\n type UIEvent,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_TEXT_TERTIARY } from \"../lib/styles\";\nimport { Spinner } from \"../core/spinner\";\n\n/* ------------------------------------------------------------------ */\n/* Columns */\n/* ------------------------------------------------------------------ */\n\n/**\n * When a column gives up its space.\n *\n * Named steps rather than arbitrary widths because the breakpoints are\n * container queries compiled by Tailwind, which cannot see a value computed at\n * runtime. They are also the honest unit here: what matters is the order\n * columns drop in, not the pixel each one leaves at.\n */\nexport type LogColumnPriority = \"always\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nconst HIDE_BELOW: Record<LogColumnPriority, string> = {\n always: \"\",\n sm: \"hidden @[40rem]/log:flex\",\n md: \"hidden @[46rem]/log:flex\",\n lg: \"hidden @[58rem]/log:flex\",\n xl: \"hidden @[70rem]/log:flex\",\n};\n\n/** One column of the log. */\nexport interface LogColumn<Row> {\n id: string;\n header: ReactNode;\n /**\n * The field this column reads, as the query language names it. Set it and the\n * cell offers \"filter for / filter out\"; leave it off for a derived column\n * that no filter could express.\n */\n field?: string;\n /** CSS width. Omit on exactly one column to let it take the slack. */\n width?: string;\n priority?: LogColumnPriority;\n align?: \"left\" | \"right\";\n mono?: boolean;\n sortable?: boolean;\n /** The cell's text — also what a cell action filters on. */\n value: (row: Row) => string | number | null | undefined;\n /** Richer cell content. Falls back to `value`. */\n render?: (row: Row) => ReactNode;\n /**\n * Draw a colour marker before the value, hashed from the value itself so the\n * same one lands on the same hue in every session.\n */\n marker?: boolean;\n}\n\n/** Where a column should move to. */\nexport type LogColumnMove = \"left\" | \"right\";\n\n/** Which column the rows are ordered by. */\nexport interface LogSort {\n columnId: string;\n direction: \"asc\" | \"desc\";\n}\n\n/** What a cell action asks the caller to do. */\nexport interface LogCellAction {\n field: string;\n value: string;\n intent: \"include\" | \"exclude\";\n}\n\nexport type LogDensity = \"compact\" | \"normal\" | \"comfortable\";\n\nconst ROW_HEIGHT: Record<LogDensity, number> = {\n compact: 26,\n normal: 32,\n comfortable: 40,\n};\n\nconst DENSITY_TEXT: Record<LogDensity, string> = {\n compact: \"text-[11px]\",\n normal: \"text-xs\",\n comfortable: \"text-sm\",\n};\n\n/** Localized strings for the log table. */\nexport interface LogTableLabels {\n listLabel?: string;\n loadingMore?: string;\n endOfResults?: string;\n filterFor?: (value: string) => string;\n filterOut?: (value: string) => string;\n sortAscending?: string;\n sortDescending?: string;\n moveLeft?: (column: string) => string;\n moveRight?: (column: string) => string;\n}\n\nconst defaultLabels: Required<LogTableLabels> = {\n listLabel: \"Log\",\n loadingMore: \"Loading earlier entries…\",\n endOfResults: \"That is every entry in this range.\",\n filterFor: (value) => `Filter for ${value}`,\n filterOut: (value) => `Filter out ${value}`,\n sortAscending: \"Sort ascending\",\n sortDescending: \"Sort descending\",\n moveLeft: (column) => `Move ${column} left`,\n moveRight: (column) => `Move ${column} right`,\n};\n\nexport interface LogTableProps<Row> {\n rows: Row[];\n columns: LogColumn<Row>[];\n getRowId: (row: Row) => string;\n\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n\n /** Fetch the next page. Called once when the viewport nears the end. */\n onLoadMore?: () => void;\n hasMore?: boolean;\n loadingMore?: boolean;\n\n /**\n * Rows arrive at the top while the reader is scrolled down — a live tail.\n * Turning this on holds their place when that happens and reports whether\n * they are pinned to the newest row.\n */\n prepending?: boolean;\n onFollowChange?: (following: boolean) => void;\n /** Highlight a row once, for entries that just arrived. */\n isNew?: (row: Row) => boolean;\n\n sort?: LogSort | null;\n onSortChange?: (sort: LogSort) => void;\n\n /** Offer \"filter for / filter out\" on cells whose column names a field. */\n onCellAction?: (action: LogCellAction) => void;\n /**\n * Let the reader move a column. Set it and each header offers to shift left\n * or right — buttons rather than a drag, so the reordering is reachable\n * without a pointer and states what it will do.\n */\n onColumnMove?: (columnId: string, direction: LogColumnMove) => void;\n\n density?: LogDensity;\n showHeader?: boolean;\n emptyState?: ReactNode;\n labels?: LogTableLabels;\n className?: string;\n}\n\nexport interface LogTableHandle {\n /** Jump to the newest row. */\n scrollToTop: () => void;\n /** Bring a row into view, leaving the scroll alone if it already is. */\n revealRow: (id: string) => void;\n}\n\n/** Rows rendered beyond the viewport on each side, so a fast scroll stays filled. */\nconst OVERSCAN = 10;\n\n/**\n * A stable hue per value. Colour does real work in a log — the eye groups by it\n * long before it reads the text — so the same event name has to land on the\n * same hue on every render and in every session, which rules out an index into\n * a palette.\n */\nfunction hueOf(value: string): number {\n let hash = 0;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 31 + value.charCodeAt(index)) | 0;\n }\n return Math.abs(hash) % 360;\n}\n\nconst EM_DASH = \"—\";\n/**\n * A column with nothing in it is a fact about the entry, not a value. Dimming\n * every absence the same way lets the eye skip the gaps while scanning, instead\n * of reading a dash as though it were data.\n */\nconst ABSENT = \"text-text-tertiary/50\";\n\nfunction columnStyle<Row>(column: LogColumn<Row>) {\n return column.width\n ? { width: column.width, flex: \"0 0 auto\" }\n : { flex: \"1 1 0%\", minWidth: 0 };\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\n/**\n * LogTable — a windowed table for entries that keep arriving.\n *\n * Written by hand rather than delegated to a data grid for the two things a log\n * needs that a grid does not: rows are inserted at the *top* while the reader\n * is partway down, which needs a scroll correction applied before paint, and\n * \"am I at the newest row?\" has to be answerable from the scroll container to\n * decide whether to follow the tail or hold position.\n *\n * What it takes from a data grid is the part readers actually reach for:\n * columns are data, so a caller can let people add, drop and reorder them; a\n * cell offers to filter for or against its own value; and density is a setting\n * rather than a constant.\n *\n * @example\n * ```tsx\n * <LogTable\n * rows={rows}\n * getRowId={(row) => row.id}\n * columns={[\n * { id: \"time\", header: \"Time\", width: \"9rem\", mono: true, value: (r) => r.time },\n * { id: \"name\", header: \"Event\", width: \"14rem\", field: \"name\", marker: true, value: (r) => r.name },\n * { id: \"path\", header: \"Path\", field: \"path\", value: (r) => r.path },\n * ]}\n * onCellAction={(action) => setQuery(applyCellAction(query, action))}\n * />\n * ```\n */\nfunction LogTableInner<Row>(\n {\n rows,\n columns,\n getRowId,\n selectedId = null,\n onSelect,\n onLoadMore,\n hasMore = false,\n loadingMore = false,\n prepending = false,\n onFollowChange,\n isNew,\n sort = null,\n onSortChange,\n onCellAction,\n onColumnMove,\n density = \"normal\",\n showHeader = true,\n emptyState,\n labels: customLabels,\n className,\n }: LogTableProps<Row>,\n ref: Ref<LogTableHandle>,\n) {\n const labels = { ...defaultLabels, ...customLabels };\n const rowHeight = ROW_HEIGHT[density];\n\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [viewportHeight, setViewportHeight] = useState(0);\n const followingRef = useRef(true);\n\n // What the list looked like before this render, so a prepend can be measured.\n const previousTopIdRef = useRef<string | null>(null);\n const previousLengthRef = useRef(0);\n\n useImperativeHandle(\n ref,\n () => ({\n scrollToTop: () => {\n const container = scrollRef.current;\n if (!container) return;\n // Instant, not smooth. A smooth scroll is still in flight when flushed\n // rows land, so the position-holding correction below would read the\n // old offset and fight it — and \"jump to newest\" is a destination, not\n // a journey.\n container.scrollTop = 0;\n setScrollTop(0);\n if (!followingRef.current) {\n followingRef.current = true;\n onFollowChange?.(true);\n }\n },\n revealRow: (id: string) => {\n const index = rows.findIndex((row) => getRowId(row) === id);\n const container = scrollRef.current;\n if (index === -1 || !container) return;\n const top = index * rowHeight;\n const bottom = top + rowHeight;\n if (top < container.scrollTop) container.scrollTop = top;\n else if (bottom > container.scrollTop + container.clientHeight) {\n container.scrollTop = bottom - container.clientHeight;\n }\n },\n }),\n [onFollowChange, rows, getRowId, rowHeight],\n );\n\n useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() =>\n setViewportHeight(container.clientHeight),\n );\n observer.observe(container);\n setViewportHeight(container.clientHeight);\n return () => observer.disconnect();\n }, []);\n\n /**\n * Report whether the list is pinned to the newest row.\n *\n * Called from more than the scroll handler on purpose: the list can arrive at\n * the top without a scroll event — a reset, a jump to newest, a shorter\n * result set — and a stale \"not following\" would silently divert every live\n * row into a held-back pile.\n */\n const syncFollowing = useCallback(\n (container: HTMLDivElement) => {\n const following = container.scrollTop <= rowHeight;\n if (following === followingRef.current) return;\n followingRef.current = following;\n onFollowChange?.(following);\n },\n [onFollowChange, rowHeight],\n );\n\n /**\n * Hold the reader's place when rows arrive above them.\n *\n * Runs before paint: by the time the browser draws, the scroll offset has\n * already absorbed the inserted height, so the content under the cursor never\n * moves. Skipped while following, where the whole point is to stay at the top.\n */\n useLayoutEffect(() => {\n const container = scrollRef.current;\n const previousTopId = previousTopIdRef.current;\n previousTopIdRef.current = rows.length ? getRowId(rows[0]!) : null;\n const previousLength = previousLengthRef.current;\n previousLengthRef.current = rows.length;\n\n if (!container) return;\n syncFollowing(container);\n\n if (!prepending || followingRef.current || !previousTopId) return;\n // Only a genuine prepend shifts the reader; appended pages do not.\n if (rows.length <= previousLength) return;\n\n const prepended = rows.findIndex((row) => getRowId(row) === previousTopId);\n if (prepended <= 0) return;\n\n container.scrollTop += prepended * rowHeight;\n setScrollTop(container.scrollTop);\n }, [rows, getRowId, prepending, rowHeight, syncFollowing]);\n\n /**\n * Page forward when the rows do not reach the bottom of the viewport.\n *\n * Without this the list only advances on a scroll event, so a tall screen —\n * or a filter matching few rows per page — stops at the first page with no\n * way to ask for more.\n */\n useEffect(() => {\n const container = scrollRef.current;\n if (!container || !hasMore || loadingMore || !onLoadMore) return;\n if (container.scrollHeight <= container.clientHeight) onLoadMore();\n }, [hasMore, loadingMore, onLoadMore, rows.length, viewportHeight]);\n\n const handleScroll = useCallback(\n (event: UIEvent<HTMLDivElement>) => {\n const container = event.currentTarget;\n setScrollTop(container.scrollTop);\n syncFollowing(container);\n // One viewport of slack, so the next page is in flight before the reader\n // reaches the end of the current one.\n const remaining =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n if (hasMore && !loadingMore && remaining < container.clientHeight) {\n onLoadMore?.();\n }\n },\n [hasMore, loadingMore, onLoadMore, syncFollowing],\n );\n\n const totalHeight = rows.length * rowHeight;\n const firstVisible = Math.max(\n 0,\n Math.floor(scrollTop / rowHeight) - OVERSCAN,\n );\n const visibleCount =\n Math.ceil((viewportHeight || 480) / rowHeight) + OVERSCAN * 2;\n const lastVisible = Math.min(rows.length, firstVisible + visibleCount);\n const visibleRows = useMemo(\n () => rows.slice(firstVisible, lastVisible),\n [rows, firstVisible, lastVisible],\n );\n\n return (\n <div\n className={cn(\"@container/log flex min-h-0 flex-col\", className)}\n data-opt-id=\"NJ4N9\"\n data-opt-slug=\"log-table.LogTable\"\n >\n {showHeader && (\n <LogTableHeader\n columns={columns}\n sort={sort}\n onSortChange={onSortChange}\n onColumnMove={onColumnMove}\n density={density}\n labels={labels}\n />\n )}\n\n <div\n ref={scrollRef}\n onScroll={handleScroll}\n className=\"relative min-h-0 flex-1 overflow-x-hidden overflow-y-auto\"\n // A log with one open row is a listbox: the rows are selectable options\n // and the detail view renders the selected one. `<option>` is not a\n // substitute — it is only valid inside a select, and these rows are\n // absolutely positioned by the windowing math.\n // eslint-disable-next-line jsx-a11y/prefer-tag-over-role -- see above\n role=\"listbox\"\n aria-label={labels.listLabel}\n aria-activedescendant={selectedId ? `log-row-${selectedId}` : undefined}\n tabIndex={0}\n >\n {rows.length === 0 ? (\n emptyState\n ) : (\n <div style={{ height: totalHeight }} className=\"relative\">\n {visibleRows.map((row, index) => {\n const id = getRowId(row);\n return (\n <LogTableRow\n key={id}\n id={id}\n row={row}\n columns={columns}\n top={(firstVisible + index) * rowHeight}\n height={rowHeight}\n density={density}\n selected={id === selectedId}\n isNew={isNew?.(row) ?? false}\n onSelect={onSelect}\n onCellAction={onCellAction}\n labels={labels}\n />\n );\n })}\n </div>\n )}\n\n {loadingMore && (\n <div className=\"gap-element text-text-tertiary flex items-center justify-center py-3 text-xs\">\n <Spinner size=\"sm\" aria-hidden />\n {labels.loadingMore}\n </div>\n )}\n\n {!hasMore && rows.length > 0 && (\n <p className={cn(OPT_TEXT_TERTIARY, \"py-3 text-center text-xs\")}>\n {labels.endOfResults}\n </p>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * LogTable — see {@link LogTableInner}.\n *\n * The cast preserves the row generic through `forwardRef`, which otherwise\n * widens it to its constraint and takes the column callbacks' types with it.\n */\nexport const LogTable = forwardRef(LogTableInner) as <Row>(\n props: LogTableProps<Row> & { ref?: Ref<LogTableHandle> },\n) => ReturnType<typeof LogTableInner>;\n\n/* ------------------------------------------------------------------ */\n/* Header */\n/* ------------------------------------------------------------------ */\n\nfunction LogTableHeader<Row>({\n columns,\n sort,\n onSortChange,\n onColumnMove,\n density,\n labels,\n}: {\n columns: LogColumn<Row>[];\n sort: LogSort | null;\n onSortChange?: (sort: LogSort) => void;\n onColumnMove?: (columnId: string, direction: LogColumnMove) => void;\n density: LogDensity;\n labels: Required<LogTableLabels>;\n}) {\n return (\n <div\n role=\"row\"\n className={cn(\n \"border-border-subtle text-text-tertiary flex shrink-0 items-center gap-3 border-b px-3\",\n DENSITY_TEXT[density],\n )}\n style={{ height: ROW_HEIGHT[density] }}\n >\n {columns.map((column, index) => {\n const active = sort?.columnId === column.id;\n const sortable = column.sortable && onSortChange;\n const columnLabel =\n typeof column.header === \"string\" ? column.header : column.id;\n const content = (\n <>\n {/* The marker's width, so the header sits over its own column. */}\n {column.marker && (\n <span aria-hidden className=\"size-1.5 shrink-0\" />\n )}\n <span className=\"truncate\">{column.header}</span>\n {active &&\n (sort!.direction === \"asc\" ? (\n <ChevronUp className=\"size-3 shrink-0\" aria-hidden />\n ) : (\n <ChevronDown className=\"size-3 shrink-0\" aria-hidden />\n ))}\n </>\n );\n\n return (\n <div\n key={column.id}\n role=\"columnheader\"\n aria-sort={\n active\n ? sort!.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : undefined\n }\n className={cn(\n \"group/header flex items-center gap-1.5\",\n column.align === \"right\" && \"justify-end\",\n HIDE_BELOW[column.priority ?? \"always\"],\n )}\n style={columnStyle(column)}\n >\n {sortable ? (\n <button\n type=\"button\"\n className=\"hover:text-text-primary flex cursor-pointer items-center gap-1.5 truncate\"\n title={\n active && sort!.direction === \"desc\"\n ? labels.sortAscending\n : labels.sortDescending\n }\n onClick={() =>\n onSortChange({\n columnId: column.id,\n direction:\n active && sort!.direction === \"desc\" ? \"asc\" : \"desc\",\n })\n }\n >\n {content}\n </button>\n ) : (\n content\n )}\n {onColumnMove && (\n <span\n className={cn(\n \"ml-auto flex shrink-0 items-center gap-0.5\",\n // Same reasoning as the cell actions: opacity, not `display`,\n // so these stay in the tab order.\n \"opacity-0 transition-opacity\",\n \"group-hover/header:opacity-100 focus-within:opacity-100\",\n )}\n >\n {index > 0 && (\n <button\n type=\"button\"\n className=\"hover:text-text-primary cursor-pointer\"\n aria-label={labels.moveLeft(columnLabel)}\n title={labels.moveLeft(columnLabel)}\n onClick={() => onColumnMove(column.id, \"left\")}\n >\n <ChevronLeft className=\"size-3\" aria-hidden />\n </button>\n )}\n {index < columns.length - 1 && (\n <button\n type=\"button\"\n className=\"hover:text-text-primary cursor-pointer\"\n aria-label={labels.moveRight(columnLabel)}\n title={labels.moveRight(columnLabel)}\n onClick={() => onColumnMove(column.id, \"right\")}\n >\n <ChevronRight className=\"size-3\" aria-hidden />\n </button>\n )}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Row */\n/* ------------------------------------------------------------------ */\n\ninterface LogTableRowProps<Row> {\n id: string;\n row: Row;\n columns: LogColumn<Row>[];\n top: number;\n height: number;\n density: LogDensity;\n selected: boolean;\n isNew: boolean;\n onSelect?: (id: string) => void;\n onCellAction?: (action: LogCellAction) => void;\n labels: Required<LogTableLabels>;\n}\n\nfunction LogTableRowImpl<Row>({\n id,\n row,\n columns,\n top,\n height,\n density,\n selected,\n isNew,\n onSelect,\n onCellAction,\n labels,\n}: LogTableRowProps<Row>) {\n return (\n <div\n // See the listbox note above: these rows are options, positioned by the\n // windowing math rather than laid out by the browser.\n // eslint-disable-next-line jsx-a11y/prefer-tag-over-role -- see above\n role=\"option\"\n aria-selected={selected}\n tabIndex={-1}\n id={`log-row-${id}`}\n data-log-row-id={id}\n onClick={() => onSelect?.(id)}\n onKeyDown={(event) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onSelect?.(id);\n }}\n style={{ top, height }}\n className={cn(\n \"border-border-subtle/60 absolute inset-x-0 flex items-center gap-3 border-b px-3\",\n DENSITY_TEXT[density],\n onSelect && \"cursor-pointer\",\n \"transition-colors duration-100\",\n \"hover:bg-surface-hover\",\n selected && \"bg-accent-subtle hover:bg-accent-subtle\",\n isNew && !selected && \"opt-log-row-enter\",\n )}\n >\n {columns.map((column) => {\n const raw = column.value(row);\n const text =\n raw === null || raw === undefined || raw === \"\" ? \"\" : String(raw);\n return (\n <div\n key={column.id}\n className={cn(\n \"group/cell relative flex min-w-0 items-center gap-1.5\",\n column.align === \"right\" && \"justify-end\",\n HIDE_BELOW[column.priority ?? \"always\"],\n )}\n style={columnStyle(column)}\n >\n {column.marker && text && (\n <span\n aria-hidden\n className=\"size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: `hsl(${hueOf(text)} 65% 55%)` }}\n />\n )}\n <span\n className={cn(\n \"truncate\",\n column.mono && \"font-mono\",\n text ? \"text-text-secondary\" : ABSENT,\n )}\n title={text || undefined}\n >\n {column.render ? column.render(row) : text || EM_DASH}\n </span>\n {onCellAction && column.field && text && (\n <CellActions\n field={column.field}\n value={text}\n onAction={onCellAction}\n labels={labels}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Memoized because a live log re-renders several times a second while almost\n * every visible row is unchanged.\n */\nconst LogTableRow = memo(LogTableRowImpl) as typeof LogTableRowImpl;\n\n/**\n * The two questions a reader has about a value they just spotted: show me only\n * these, and get these out of my way.\n *\n * Revealed on hover rather than always drawn — a log is scanned, and a pair of\n * buttons on every cell of every row is a wall of chrome. They stay in the tab\n * order regardless, since hover is not an interaction everyone has.\n */\nfunction CellActions({\n field,\n value,\n onAction,\n labels,\n}: {\n field: string;\n value: string;\n onAction: (action: LogCellAction) => void;\n labels: Required<LogTableLabels>;\n}) {\n const button =\n \"cursor-pointer rounded-sm p-0.5 text-text-tertiary hover:bg-bg-muted hover:text-text-primary\";\n return (\n <span\n className={cn(\n \"bg-surface/90 ml-auto flex shrink-0 items-center gap-0.5 rounded pl-1\",\n // Hidden by opacity rather than `display`, which would take the buttons\n // out of the tab order entirely — `focus-within` can never fire on\n // something that cannot be focused, so a keyboard user would have no\n // way to reach a cell action at all.\n \"opacity-0 transition-opacity\",\n \"group-hover/cell:opacity-100 focus-within:opacity-100\",\n )}\n >\n <button\n type=\"button\"\n className={button}\n title={labels.filterFor(value)}\n aria-label={labels.filterFor(value)}\n onClick={(event) => {\n event.stopPropagation();\n onAction({ field, value, intent: \"include\" });\n }}\n >\n <Plus className=\"size-3\" aria-hidden />\n </button>\n <button\n type=\"button\"\n className={button}\n title={labels.filterOut(value)}\n aria-label={labels.filterOut(value)}\n onClick={(event) => {\n event.stopPropagation();\n onAction({ field, value, intent: \"exclude\" });\n }}\n >\n <Minus className=\"size-3\" aria-hidden />\n </button>\n </span>\n );\n}\n","/**\n * A search query, as a value.\n *\n * Free-text search and a row of filter pickers answer different halves of the\n * same question, and neither can express the other: a picker cannot say \"not\n * this\", and a text box cannot say \"this field, exactly\". A parsed query is one\n * thing that does both, and — because it is a value rather than a widget's\n * internal state — it survives a URL, a saved view, and the trip to a server\n * that has to turn it into a database filter.\n *\n * The grammar follows the one analytics tools have converged on (Elastic's\n * `EuiSearchBar`, Kibana, GitHub's issue search), minus the parts that only\n * make sense against a Lucene index:\n *\n * error a term anywhere in the row\n * \"connection reset\" a phrase, kept together\n * -health a term that must not appear\n * path:/checkout a field equal to a value\n * path:(/a or /b) a field equal to any of several values\n * -status:200 a field that must not equal a value\n * status>=500 a comparison\n * path:*checkout* the field contains this somewhere\n * utm_source:* the field is present at all\n *\n * Clauses combine with AND; `or` only groups values inside one field. That is\n * a deliberate ceiling: arbitrary boolean nesting reads worse than it queries,\n * and every backend this targets can express the restricted form directly.\n */\n\n/** How a field clause compares. */\nexport type QueryOperator =\n | \"eq\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"exists\";\n\n/** A bare or quoted word matched against the whole row. */\nexport interface QueryTermClause {\n type: \"term\";\n value: string;\n negated: boolean;\n}\n\n/** A constraint on one named field. Several values read as \"any of\". */\nexport interface QueryFieldClause {\n type: \"field\";\n field: string;\n operator: QueryOperator;\n values: string[];\n negated: boolean;\n}\n\nexport type QueryClause = QueryTermClause | QueryFieldClause;\n\n/** A parsed query: clauses combined with AND. */\nexport interface Query {\n clauses: QueryClause[];\n}\n\nexport const EMPTY_QUERY: Query = { clauses: [] };\n\n/** Whether a query constrains anything at all. */\nexport function isEmptyQuery(query: Query | null | undefined): boolean {\n return !query || query.clauses.length === 0;\n}\n\n/* ------------------------------------------------------------------ */\n/* Editing */\n/* ------------------------------------------------------------------ */\n\nfunction sameClause(a: QueryClause, b: QueryClause): boolean {\n if (a.type !== b.type) return false;\n if (a.type === \"term\" && b.type === \"term\") {\n return a.value === b.value && a.negated === b.negated;\n }\n const fieldA = a as QueryFieldClause;\n const fieldB = b as QueryFieldClause;\n return (\n fieldA.field === fieldB.field &&\n fieldA.operator === fieldB.operator &&\n fieldA.negated === fieldB.negated &&\n fieldA.values.length === fieldB.values.length &&\n fieldA.values.every((value, index) => value === fieldB.values[index])\n );\n}\n\n/** Add a clause unless an identical one is already there. */\nexport function addClause(query: Query, clause: QueryClause): Query {\n if (query.clauses.some((existing) => sameClause(existing, clause))) {\n return query;\n }\n return { clauses: [...query.clauses, clause] };\n}\n\n/**\n * Constrain a field to a value — what a cell's \"filter for this\" action does.\n *\n * Applying the opposite of a constraint already present replaces it rather than\n * adding it: `status:200` then \"filter out 200\" should read as one changed\n * mind, not as a query that can never match.\n */\nexport function withFieldValue(\n query: Query,\n field: string,\n value: string,\n options: { negated?: boolean; operator?: QueryOperator } = {},\n): Query {\n const negated = options.negated ?? false;\n const operator = options.operator ?? \"eq\";\n const clauses = query.clauses.filter(\n (clause) =>\n !(\n clause.type === \"field\" &&\n clause.field === field &&\n clause.operator === operator &&\n clause.values.length === 1 &&\n clause.values[0] === value\n ),\n );\n return {\n clauses: [\n ...clauses,\n { type: \"field\", field, operator, values: [value], negated },\n ],\n };\n}\n\n/** Drop every clause naming `field`. */\nexport function withoutField(query: Query, field: string): Query {\n return {\n clauses: query.clauses.filter(\n (clause) => clause.type !== \"field\" || clause.field !== field,\n ),\n };\n}\n\n/** Drop the clause at `index`, for a removable chip. */\nexport function removeClause(query: Query, index: number): Query {\n return { clauses: query.clauses.filter((_, at) => at !== index) };\n}\n\n/** Every field the query names, in the order they first appear. */\nexport function queryFields(query: Query): string[] {\n const seen: string[] = [];\n for (const clause of query.clauses) {\n if (clause.type === \"field\" && !seen.includes(clause.field)) {\n seen.push(clause.field);\n }\n }\n return seen;\n}\n\n/** The values a field is constrained to, if any — for showing a filter as active. */\nexport function fieldValues(query: Query, field: string): string[] {\n return query.clauses.flatMap((clause) =>\n clause.type === \"field\" && clause.field === field && !clause.negated\n ? clause.values\n : [],\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Cell actions */\n/* ------------------------------------------------------------------ */\n\n/** What a \"filter for / filter out\" control on a value asks for. */\nexport interface QueryCellAction {\n field: string;\n value: string;\n intent: \"include\" | \"exclude\";\n}\n\n/**\n * Fold a cell action into the query.\n *\n * The pair of buttons on a log cell is the fastest path from \"I noticed this\n * value\" to a filtered view, and the reason it works is that the result is a\n * query the reader can then see, edit and share — not a hidden filter stack\n * with its own rules.\n */\nexport function applyCellAction(query: Query, action: QueryCellAction): Query {\n return withFieldValue(query, action.field, action.value, {\n negated: action.intent === \"exclude\",\n });\n}\n","/**\n * Text in, {@link Query} out — and never an exception.\n *\n * A search box is edited one keystroke at a time, so most of the strings this\n * sees are half-written: `path:`, `status>`, `\"unclosed`. A parser that throws\n * on those turns every intermediate state into an error banner, which trains\n * people to type somewhere else and paste. Instead, anything that cannot be\n * read as a clause is kept as a plain term, and the caller is told separately\n * (via {@link parseQueryWithDiagnostics}) if it wants to warn.\n *\n * Written by hand rather than generated. EUI compiles a PEG grammar for the\n * same job, which buys arbitrary nesting we deliberately do not offer, at the\n * cost of a build-time plugin in every consumer.\n */\nimport type {\n Query,\n QueryClause,\n QueryFieldClause,\n QueryOperator,\n} from \"./query-ast\";\n\n/** A part of the input that could not be read as intended. */\nexport interface QueryDiagnostic {\n /** Character offset into the original string. */\n at: number;\n text: string;\n message: string;\n}\n\nexport interface ParsedQuery {\n query: Query;\n diagnostics: QueryDiagnostic[];\n /** The final clause is still being typed — the caller can complete it. */\n trailing: { field: string; operator: QueryOperator; value: string } | null;\n}\n\nconst FIELD_NAME = /^[A-Za-z_][A-Za-z0-9_.-]*$/;\n\ninterface Token {\n text: string;\n at: number;\n /** The token was written inside quotes, so it is a phrase, not syntax. */\n quoted: boolean;\n}\n\n/**\n * Split on whitespace, but keep quoted runs and parenthesised groups whole.\n *\n * An unterminated quote or group swallows the rest of the line rather than\n * erroring: the reader is mid-word, and the alternative is the query flickering\n * between two different meanings as they type the closing character.\n */\nfunction tokenize(input: string): Token[] {\n const tokens: Token[] = [];\n let index = 0;\n\n while (index < input.length) {\n while (index < input.length && /\\s/.test(input[index]!)) index += 1;\n if (index >= input.length) break;\n\n const start = index;\n let text = \"\";\n // Only a token that *opens* with a quote is a phrase. `name:\"a b\"` quotes\n // its value, not the constraint — reading the whole token as a phrase there\n // would turn a field filter into a search for the literal text.\n let quoted = false;\n let atTokenStart = true;\n let depth = 0;\n\n while (index < input.length) {\n const char = input[index]!;\n\n if (char === '\"') {\n if (atTokenStart) quoted = true;\n atTokenStart = false;\n index += 1;\n while (index < input.length && input[index] !== '\"') {\n text += input[index];\n index += 1;\n }\n index += 1; // closing quote, or the end of the input\n continue;\n }\n\n if (char === \"(\") depth += 1;\n if (char === \")\") depth = Math.max(0, depth - 1);\n if (/\\s/.test(char) && depth === 0) break;\n\n atTokenStart = false;\n text += char;\n index += 1;\n }\n\n if (text.length > 0 || quoted) tokens.push({ text, at: start, quoted });\n }\n\n return tokens;\n}\n\n/** `(a or b)` → `[\"a\", \"b\"]`; anything else is a single value. */\nfunction readValues(raw: string): string[] {\n const trimmed = raw.trim();\n if (!trimmed.startsWith(\"(\")) {\n return [stripQuotes(trimmed)];\n }\n const inner = trimmed.replace(/^\\(/, \"\").replace(/\\)$/, \"\");\n return inner\n .split(/\\s+or\\s+/i)\n .map((part) => stripQuotes(part.trim()))\n .filter((part) => part.length > 0);\n}\n\nfunction stripQuotes(value: string): string {\n if (value.length >= 2 && value.startsWith('\"') && value.endsWith('\"')) {\n return value.slice(1, -1);\n }\n return value.replace(/^\"/, \"\");\n}\n\nconst OPERATORS: { symbol: string; operator: QueryOperator }[] = [\n { symbol: \">=\", operator: \"gte\" },\n { symbol: \"<=\", operator: \"lte\" },\n { symbol: \":\", operator: \"eq\" },\n { symbol: \">\", operator: \"gt\" },\n { symbol: \"<\", operator: \"lt\" },\n];\n\n/** Where a field operator starts in the token, or `-1`. */\nfunction findOperator(\n text: string,\n): { index: number; symbol: string; operator: QueryOperator } | null {\n let best: { index: number; symbol: string; operator: QueryOperator } | null =\n null;\n for (const { symbol, operator } of OPERATORS) {\n const index = text.indexOf(symbol);\n if (index <= 0) continue;\n // `>=` must win over the `>` inside it.\n if (\n !best ||\n index < best.index ||\n (index === best.index && symbol.length > best.symbol.length)\n ) {\n best = { index, symbol, operator };\n }\n }\n return best;\n}\n\n/** Parse, keeping whatever could not be understood as a plain term. */\nexport function parseQueryWithDiagnostics(input: string): ParsedQuery {\n const diagnostics: QueryDiagnostic[] = [];\n const clauses: QueryClause[] = [];\n let trailing: ParsedQuery[\"trailing\"] = null;\n\n for (const token of tokenize(input)) {\n let text = token.text;\n let negated = false;\n\n if (!token.quoted && text.startsWith(\"-\") && text.length > 1) {\n negated = true;\n text = text.slice(1);\n }\n\n const operator = token.quoted ? null : findOperator(text);\n if (!operator) {\n if (text.length > 0) clauses.push({ type: \"term\", value: text, negated });\n continue;\n }\n\n const field = text.slice(0, operator.index);\n const rawValue = text.slice(operator.index + operator.symbol.length);\n\n if (!FIELD_NAME.test(field)) {\n // `12:30` is a time, not a field constraint.\n clauses.push({ type: \"term\", value: text, negated });\n continue;\n }\n\n if (rawValue === \"\") {\n // Mid-typing: remember it so the caller can offer completions, but do not\n // constrain anything yet — an empty value would match nothing.\n trailing = { field, operator: operator.operator, value: \"\" };\n continue;\n }\n\n if (rawValue === \"*\" && operator.operator === \"eq\") {\n clauses.push({\n type: \"field\",\n field,\n operator: \"exists\",\n values: [],\n negated,\n });\n continue;\n }\n\n // `path:*checkout*` — the wildcards are the syntax, the middle is the value.\n // Distinct from a bare `*`, which asks whether the field is there at all.\n if (\n operator.operator === \"eq\" &&\n rawValue.length > 2 &&\n rawValue.startsWith(\"*\") &&\n rawValue.endsWith(\"*\")\n ) {\n clauses.push({\n type: \"field\",\n field,\n operator: \"contains\",\n values: [stripQuotes(rawValue.slice(1, -1))],\n negated,\n });\n continue;\n }\n\n const values = readValues(rawValue);\n if (values.length === 0) {\n diagnostics.push({\n at: token.at,\n text: token.text,\n message: \"Empty value group\",\n });\n continue;\n }\n\n if (operator.operator !== \"eq\" && values.length > 1) {\n diagnostics.push({\n at: token.at,\n text: token.text,\n message: \"A comparison takes a single value\",\n });\n }\n\n const clause: QueryFieldClause = {\n type: \"field\",\n field,\n operator: operator.operator,\n values: operator.operator === \"eq\" ? values : values.slice(0, 1),\n negated,\n };\n clauses.push(clause);\n if (!rawValue.startsWith(\"(\")) {\n trailing = { field, operator: operator.operator, value: values[0] ?? \"\" };\n }\n }\n\n return { query: { clauses }, diagnostics, trailing };\n}\n\n/** Parse, discarding diagnostics. */\nexport function parseQuery(input: string): Query {\n return parseQueryWithDiagnostics(input).query;\n}\n","/**\n * {@link Query} back to text, so the box shows what the chips mean.\n *\n * Round-tripping matters more than prettiness: whatever a cell action or a\n * sidebar click adds to the query has to appear in the input as something the\n * reader could have typed themselves, and could edit by hand from there.\n */\nimport type { Query, QueryClause, QueryOperator } from \"./query-ast\";\n\nconst OPERATOR_SYMBOL: Record<QueryOperator, string> = {\n eq: \":\",\n contains: \":\",\n gt: \">\",\n gte: \">=\",\n lt: \"<\",\n lte: \"<=\",\n exists: \":\",\n};\n\n/** Quote a value that would otherwise re-parse as something else. */\nexport function quoteValue(value: string): string {\n return /[\\s\"()]/.test(value) || value === \"\"\n ? `\"${value.replace(/\"/g, \"\")}\"`\n : value;\n}\n\n/** One clause as text. */\nexport function formatClause(clause: QueryClause): string {\n const prefix = clause.negated ? \"-\" : \"\";\n if (clause.type === \"term\") return `${prefix}${quoteValue(clause.value)}`;\n if (clause.operator === \"exists\") return `${prefix}${clause.field}:*`;\n if (clause.operator === \"contains\") {\n return `${prefix}${clause.field}:*${clause.values[0] ?? \"\"}*`;\n }\n\n const symbol = OPERATOR_SYMBOL[clause.operator];\n if (clause.values.length > 1) {\n return `${prefix}${clause.field}${symbol}(${clause.values.map(quoteValue).join(\" or \")})`;\n }\n return `${prefix}${clause.field}${symbol}${quoteValue(clause.values[0] ?? \"\")}`;\n}\n\n/** The whole query as text. */\nexport function formatQuery(query: Query): string {\n return query.clauses.map(formatClause).join(\" \");\n}\n\n/** A short human label for a clause chip. */\nexport function describeClause(clause: QueryClause): string {\n if (clause.type === \"term\") {\n return clause.negated ? `not \"${clause.value}\"` : `\"${clause.value}\"`;\n }\n if (clause.operator === \"exists\") {\n return clause.negated\n ? `${clause.field} missing`\n : `${clause.field} present`;\n }\n if (clause.operator === \"contains\") {\n return `${clause.negated ? \"not \" : \"\"}${clause.field} ⊃ ${clause.values[0] ?? \"\"}`;\n }\n const values = clause.values.join(\", \");\n const symbol = OPERATOR_SYMBOL[clause.operator];\n return `${clause.negated ? \"not \" : \"\"}${clause.field} ${symbol === \":\" ? \"=\" : symbol} ${values}`;\n}\n","\"use client\";\n\nimport { Search, X } from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_FOCUS_VISIBLE } from \"../lib/styles\";\nimport {\n describeClause,\n formatQuery,\n parseQueryWithDiagnostics,\n removeClause,\n type Query,\n type QueryDiagnostic,\n} from \"../lib/query\";\n\n/** A field the query can constrain, offered as a completion. */\nexport interface QueryField {\n name: string;\n /** Shown beside the name — a type, a count, whatever tells them apart. */\n hint?: string;\n /** Known values, offered once the reader has typed `field:`. */\n values?: string[];\n}\n\n/** Localized strings for the query bar. */\nexport interface QueryBarLabels {\n placeholder?: string;\n ariaLabel?: string;\n clear?: string;\n removeClause?: (clause: string) => string;\n fieldsHeading?: string;\n valuesHeading?: string;\n syntaxHint?: ReactNode;\n}\n\nconst defaultLabels: Required<Omit<QueryBarLabels, \"syntaxHint\">> & {\n syntaxHint: ReactNode;\n} = {\n placeholder: \"Search, or filter with field:value\",\n ariaLabel: \"Search query\",\n clear: \"Clear query\",\n removeClause: (clause) => `Remove ${clause}`,\n fieldsHeading: \"Fields\",\n valuesHeading: \"Values\",\n syntaxHint: null,\n};\n\nexport interface QueryBarProps {\n value: Query;\n onChange: (query: Query) => void;\n /** Fields offered as completions, with their known values. */\n fields?: QueryField[];\n /** Show each clause as a removable chip below the input. */\n showClauses?: boolean;\n /** Commit on every keystroke instead of on Enter and blur. */\n live?: boolean;\n disabled?: boolean;\n className?: string;\n labels?: QueryBarLabels;\n}\n\nconst MAX_SUGGESTIONS = 8;\n\n/**\n * QueryBar — one control for \"find this\" and \"only these\".\n *\n * A search box and a row of filter pickers answer halves of the same question\n * and neither can express the other, so people end up using both and holding\n * the combination in their head. Typing the filter is what closes that: the\n * whole question is one string, which means it can be read back, corrected in\n * place, pasted to a colleague, and stored in a URL.\n *\n * The text is the source of truth while the reader is typing; the parsed query\n * is committed on Enter or blur. Anything half-written parses to a plain term\n * rather than an error, so the bar never argues with someone mid-word.\n *\n * @example\n * ```tsx\n * <QueryBar\n * value={query}\n * onChange={setQuery}\n * fields={[{ name: \"path\", values: [\"/checkout\", \"/cart\"] }]}\n * showClauses\n * />\n * ```\n */\nexport function QueryBar({\n value,\n onChange,\n fields = [],\n showClauses = false,\n live = false,\n disabled = false,\n className,\n labels: customLabels,\n}: QueryBarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const inputRef = useRef<HTMLInputElement>(null);\n const [text, setText] = useState(() => formatQuery(value));\n const [focused, setFocused] = useState(false);\n const [highlighted, setHighlighted] = useState(0);\n\n // Follow the query when it changes elsewhere — a cell action, a preset, the\n // back button — but never while the reader is mid-word in this very input.\n const committedRef = useRef(formatQuery(value));\n useEffect(() => {\n const next = formatQuery(value);\n if (next === committedRef.current) return;\n committedRef.current = next;\n if (!focused) setText(next);\n }, [value, focused]);\n\n const parsed = useMemo(() => parseQueryWithDiagnostics(text), [text]);\n\n const commit = useCallback(\n (nextText: string) => {\n const nextQuery = parseQueryWithDiagnostics(nextText).query;\n committedRef.current = formatQuery(nextQuery);\n onChange(nextQuery);\n },\n [onChange],\n );\n\n const suggestions = useSuggestions(text, parsed.trailing, fields);\n\n const applySuggestion = useCallback(\n (suggestion: Suggestion) => {\n const nextText = suggestion.replace(text);\n setText(nextText);\n if (suggestion.kind === \"value\") commit(nextText);\n inputRef.current?.focus();\n setHighlighted(0);\n },\n [text, commit],\n );\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (suggestions.length > 0 && focused) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setHighlighted((current) => (current + 1) % suggestions.length);\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setHighlighted(\n (current) => (current - 1 + suggestions.length) % suggestions.length,\n );\n return;\n }\n if (event.key === \"Tab\" || (event.key === \"Enter\" && highlighted > 0)) {\n event.preventDefault();\n applySuggestion(suggestions[highlighted]!);\n return;\n }\n }\n if (event.key === \"Enter\") {\n event.preventDefault();\n commit(text);\n return;\n }\n if (event.key === \"Escape\") {\n setText(committedRef.current);\n inputRef.current?.blur();\n }\n };\n\n const showSuggestions = focused && suggestions.length > 0;\n\n return (\n <div\n className={cn(\"relative flex min-w-0 flex-col gap-1.5\", className)}\n data-opt-id=\"JSVZ1\"\n data-opt-slug=\"query-bar.QueryBar\"\n >\n <div\n className={cn(\n \"bg-surface flex h-9 items-center gap-2 rounded-md border px-2.5\",\n OPT_BORDER,\n \"focus-within:border-accent transition-colors\",\n disabled && \"opacity-60\",\n )}\n >\n <Search className=\"text-text-tertiary size-4 shrink-0\" aria-hidden />\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={showSuggestions}\n aria-controls=\"query-bar-suggestions\"\n aria-autocomplete=\"list\"\n aria-label={labels.ariaLabel}\n placeholder={labels.placeholder}\n disabled={disabled}\n className={cn(\n \"text-text-primary placeholder:text-text-tertiary min-w-0 flex-1\",\n // The focus ring lives on the wrapper (`focus-within:border-accent`),\n // so the input drawing its own would double it.\n \"bg-transparent font-mono text-sm outline-none focus-visible:outline-none\",\n )}\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n setHighlighted(0);\n if (live) commit(event.target.value);\n }}\n onFocus={() => setFocused(true)}\n onBlur={() => {\n // Let a click on a suggestion land before the list unmounts.\n window.setTimeout(() => setFocused(false), 120);\n if (!live) commit(text);\n }}\n onKeyDown={handleKeyDown}\n />\n {text.length > 0 && (\n <button\n type=\"button\"\n aria-label={labels.clear}\n title={labels.clear}\n className={cn(\n \"text-text-tertiary hover:text-text-primary cursor-pointer rounded-sm p-0.5\",\n OPT_FOCUS_VISIBLE,\n )}\n onClick={() => {\n setText(\"\");\n commit(\"\");\n }}\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n\n {showSuggestions && (\n <ul\n id=\"query-bar-suggestions\"\n role=\"listbox\"\n className={cn(\n \"bg-surface-overlay absolute top-10 z-40 max-h-64 w-full overflow-y-auto rounded-md border p-1 shadow-lg\",\n OPT_BORDER,\n )}\n >\n {suggestions.map((suggestion, index) => (\n <li key={`${suggestion.kind}-${suggestion.label}`}>\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={index === highlighted}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between gap-3 rounded px-2 py-1 text-left text-sm\",\n index === highlighted ? \"bg-bg-subtle\" : \"hover:bg-bg-subtle\",\n )}\n onMouseEnter={() => setHighlighted(index)}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => applySuggestion(suggestion)}\n >\n <span className=\"text-text-primary truncate font-mono\">\n {suggestion.label}\n </span>\n {suggestion.hint && (\n <span className=\"text-text-tertiary shrink-0 text-xs\">\n {suggestion.hint}\n </span>\n )}\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {showClauses && value.clauses.length > 0 && (\n <ul className=\"flex flex-wrap items-center gap-1.5\">\n {value.clauses.map((clause, index) => {\n const label = describeClause(clause);\n return (\n <li\n key={`${label}-${index}`}\n className={cn(\n \"bg-bg-subtle text-text-secondary flex items-center gap-1 rounded px-1.5 py-0.5 text-xs\",\n clause.negated && \"text-danger-fg\",\n )}\n >\n <span className=\"truncate\">{label}</span>\n <button\n type=\"button\"\n aria-label={labels.removeClause(label)}\n className=\"hover:text-text-primary cursor-pointer\"\n onClick={() => {\n const next = removeClause(value, index);\n setText(formatQuery(next));\n committedRef.current = formatQuery(next);\n onChange(next);\n }}\n >\n <X className=\"size-3\" aria-hidden />\n </button>\n </li>\n );\n })}\n </ul>\n )}\n\n {parsed.diagnostics.length > 0 && (\n <QueryDiagnostics diagnostics={parsed.diagnostics} />\n )}\n\n {labels.syntaxHint && !showSuggestions && (\n <p className=\"text-text-tertiary text-xs\">{labels.syntaxHint}</p>\n )}\n </div>\n );\n}\n\nQueryBar.displayName = \"QueryBar\";\n\nfunction QueryDiagnostics({ diagnostics }: { diagnostics: QueryDiagnostic[] }) {\n return (\n <ul className=\"text-warning-fg flex flex-col gap-0.5 text-xs\">\n {diagnostics.map((diagnostic, index) => (\n <li key={`${diagnostic.at}-${index}`}>\n <code className=\"font-mono\">{diagnostic.text}</code> —{\" \"}\n {diagnostic.message}\n </li>\n ))}\n </ul>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Completions */\n/* ------------------------------------------------------------------ */\n\ninterface Suggestion {\n kind: \"field\" | \"value\";\n label: string;\n hint?: string;\n /** Rewrite the whole input, since only the last token is being completed. */\n replace: (text: string) => string;\n}\n\n/**\n * What to offer, based on the token under the cursor.\n *\n * Completing fields is the part that makes the syntax discoverable at all —\n * nobody guesses that `utm_source` is a field they can filter on. Once the\n * field is chosen, its known values are the second half of the same guess.\n */\nfunction useSuggestions(\n text: string,\n trailing: { field: string; operator: string; value: string } | null,\n fields: QueryField[],\n): Suggestion[] {\n return useMemo(() => {\n const lastSpace = text.lastIndexOf(\" \");\n const head = lastSpace === -1 ? \"\" : text.slice(0, lastSpace + 1);\n const token = text.slice(lastSpace + 1);\n\n if (trailing) {\n const field = fields.find(\n (candidate) => candidate.name === trailing.field,\n );\n const values = field?.values ?? [];\n const typed = trailing.value.toLowerCase();\n return values\n .filter((value) => value.toLowerCase().includes(typed))\n .slice(0, MAX_SUGGESTIONS)\n .map((value) => ({\n kind: \"value\" as const,\n label: `${trailing.field}:${value}`,\n replace: () =>\n `${head}${trailing.field}:${/[\\s\"()]/.test(value) ? `\"${value}\"` : value} `,\n }));\n }\n\n const bare = token.replace(/^-/, \"\").toLowerCase();\n if (bare.length === 0) return [];\n return fields\n .filter((field) => field.name.toLowerCase().includes(bare))\n .slice(0, MAX_SUGGESTIONS)\n .map((field) => ({\n kind: \"field\" as const,\n label: `${field.name}:`,\n hint: field.hint,\n replace: () =>\n `${head}${token.startsWith(\"-\") ? \"-\" : \"\"}${field.name}:`,\n }));\n }, [text, trailing, fields]);\n}\n","\"use client\";\n\nimport { Columns3, Minus, Plus, Search } from \"lucide-react\";\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { OPT_BORDER, OPT_TEXT_TERTIARY } from \"../lib/styles\";\nimport { Spinner } from \"../core/spinner\";\n\n/** One value a field takes, with how often. */\nexport interface FieldValueCount {\n value: string;\n count: number;\n /** Share of the sampled rows, 0–1. Derived from counts when omitted. */\n share?: number;\n}\n\n/** A field the reader can inspect, filter on, or put in the table. */\nexport interface FieldSummary {\n name: string;\n /** Shown beside the name — \"string\", \"number\", a source, whatever separates them. */\n type?: string;\n /** Grouping header. Fields with the same group are listed together. */\n group?: string;\n /** True when the field is currently a column. */\n inTable?: boolean;\n /** False for fields that exist but cannot be a column (a nested object, say). */\n columnable?: boolean;\n}\n\n/** Localized strings for the field sidebar. */\nexport interface FieldSidebarLabels {\n heading?: string;\n searchPlaceholder?: string;\n searchLabel?: string;\n empty?: string;\n addColumn?: (field: string) => string;\n removeColumn?: (field: string) => string;\n filterFor?: (value: string) => string;\n filterOut?: (value: string) => string;\n topValues?: (count: number) => string;\n noValues?: string;\n loadingValues?: string;\n otherGroup?: string;\n}\n\nconst defaultLabels: Required<FieldSidebarLabels> = {\n heading: \"Fields\",\n searchPlaceholder: \"Find a field\",\n searchLabel: \"Find a field\",\n empty: \"No fields match.\",\n addColumn: (field) => `Show ${field} as a column`,\n removeColumn: (field) => `Remove the ${field} column`,\n filterFor: (value) => `Filter for ${value}`,\n filterOut: (value) => `Filter out ${value}`,\n topValues: (count) => `Top ${count} values`,\n noValues: \"No values in this range.\",\n loadingValues: \"Counting…\",\n otherGroup: \"Other\",\n};\n\nexport interface FieldSidebarProps {\n fields: FieldSummary[];\n /** The field whose values are open. Controlled so the caller can fetch them. */\n expandedField?: string | null;\n onExpandedFieldChange?: (field: string | null) => void;\n /** Values for the expanded field. The caller fetches them on expansion. */\n values?: FieldValueCount[];\n valuesLoading?: boolean;\n /** Rows the counts were taken over, for the reader to judge the sample by. */\n sampledRows?: number;\n\n onToggleColumn?: (field: string, next: boolean) => void;\n onFilter?: (\n field: string,\n value: string,\n intent: \"include\" | \"exclude\",\n ) => void;\n\n header?: ReactNode;\n className?: string;\n labels?: FieldSidebarLabels;\n}\n\n/**\n * FieldSidebar — what is in this data, and what does it contain.\n *\n * Without it, a log answers only the questions you already knew to ask: you can\n * filter on `utm_source` if you remember it exists, and you can read a value if\n * you open a row and scroll to it. Listing the fields turns that around — the\n * data tells the reader what is available — and the value counts answer the\n * question that actually follows (\"mostly which?\") before they have to run a\n * query to find out.\n *\n * Three actions live here because they are the three things people do next:\n * put the field in the table, keep only rows with a value, drop rows with it.\n *\n * @example\n * ```tsx\n * <FieldSidebar\n * fields={fields}\n * expandedField={openField}\n * onExpandedFieldChange={setOpenField}\n * values={valuesQuery.data}\n * valuesLoading={valuesQuery.isLoading}\n * onToggleColumn={(field, next) => setColumns(...)}\n * onFilter={(field, value, intent) => setQuery(applyCellAction(query, { field, value, intent }))}\n * />\n * ```\n */\nexport function FieldSidebar({\n fields,\n expandedField = null,\n onExpandedFieldChange,\n values,\n valuesLoading = false,\n sampledRows,\n onToggleColumn,\n onFilter,\n header,\n className,\n labels: customLabels,\n}: FieldSidebarProps) {\n const labels = { ...defaultLabels, ...customLabels };\n const [search, setSearch] = useState(\"\");\n\n const groups = useMemo(() => {\n const needle = search.trim().toLowerCase();\n const matching = needle\n ? fields.filter((field) => field.name.toLowerCase().includes(needle))\n : fields;\n\n const byGroup = new Map<string, FieldSummary[]>();\n for (const field of matching) {\n const key = field.group ?? \"\";\n const bucket = byGroup.get(key);\n if (bucket) bucket.push(field);\n else byGroup.set(key, [field]);\n }\n return [...byGroup.entries()];\n }, [fields, search]);\n\n const total = useMemo(\n () => (values ?? []).reduce((sum, entry) => sum + entry.count, 0),\n [values],\n );\n\n return (\n <aside\n className={cn(\"flex min-h-0 flex-col\", className)}\n aria-label={labels.heading}\n data-opt-id=\"17D4Y\"\n data-opt-slug=\"field-sidebar.FieldSidebar\"\n >\n {header}\n\n <div\n className={cn(\n \"flex items-center gap-2 border-b px-3 py-2\",\n \"focus-within:border-accent transition-colors\",\n OPT_BORDER,\n )}\n >\n <Search className=\"text-text-tertiary size-3.5 shrink-0\" aria-hidden />\n <input\n type=\"search\"\n aria-label={labels.searchLabel}\n placeholder={labels.searchPlaceholder}\n className={cn(\n \"text-text-primary placeholder:text-text-tertiary min-w-0 flex-1\",\n // Focus is shown on the row's border; a second ring inside it reads\n // as two controls.\n \"bg-transparent text-sm outline-none focus-visible:outline-none\",\n )}\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n />\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {groups.length === 0 ? (\n <p className={cn(OPT_TEXT_TERTIARY, \"px-3 py-4 text-xs\")}>\n {labels.empty}\n </p>\n ) : (\n groups.map(([group, groupFields]) => (\n <section key={group || \"__ungrouped__\"}>\n {group && (\n <h4\n className={cn(\n OPT_TEXT_TERTIARY,\n \"px-3 pt-3 pb-1 text-[11px] font-medium tracking-wide uppercase\",\n )}\n >\n {group}\n </h4>\n )}\n <ul>\n {groupFields.map((field) => (\n <FieldRow\n key={field.name}\n field={field}\n expanded={expandedField === field.name}\n onToggleExpanded={() =>\n onExpandedFieldChange?.(\n expandedField === field.name ? null : field.name,\n )\n }\n onToggleColumn={onToggleColumn}\n labels={labels}\n >\n {expandedField === field.name && (\n <FieldValues\n values={values}\n loading={valuesLoading}\n total={total}\n sampledRows={sampledRows}\n onFilter={\n onFilter\n ? (value, intent) =>\n onFilter(field.name, value, intent)\n : undefined\n }\n labels={labels}\n />\n )}\n </FieldRow>\n ))}\n </ul>\n </section>\n ))\n )}\n </div>\n </aside>\n );\n}\n\nFieldSidebar.displayName = \"FieldSidebar\";\n\n/* ------------------------------------------------------------------ */\n/* Internals */\n/* ------------------------------------------------------------------ */\n\nfunction FieldRow({\n field,\n expanded,\n onToggleExpanded,\n onToggleColumn,\n labels,\n children,\n}: {\n field: FieldSummary;\n expanded: boolean;\n onToggleExpanded: () => void;\n onToggleColumn?: (field: string, next: boolean) => void;\n labels: Required<FieldSidebarLabels>;\n children?: ReactNode;\n}) {\n const columnable = field.columnable ?? true;\n return (\n <li>\n <div className=\"hover:bg-bg-subtle group/field flex items-center gap-1.5 px-3 py-1\">\n <button\n type=\"button\"\n className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-left\"\n aria-expanded={expanded}\n onClick={onToggleExpanded}\n >\n {field.type && (\n <span\n className={cn(\n OPT_TEXT_TERTIARY,\n \"w-8 shrink-0 truncate font-mono text-[10px] uppercase\",\n )}\n >\n {field.type}\n </span>\n )}\n <span className=\"text-text-primary truncate font-mono text-xs\">\n {field.name}\n </span>\n </button>\n\n {onToggleColumn && columnable && (\n <button\n type=\"button\"\n className={cn(\n \"cursor-pointer rounded-sm p-0.5\",\n field.inTable\n ? \"text-accent\"\n : \"text-text-tertiary hover:text-text-primary opacity-0 group-hover/field:opacity-100 focus-visible:opacity-100\",\n )}\n aria-label={\n field.inTable\n ? labels.removeColumn(field.name)\n : labels.addColumn(field.name)\n }\n title={\n field.inTable\n ? labels.removeColumn(field.name)\n : labels.addColumn(field.name)\n }\n aria-pressed={field.inTable ?? false}\n onClick={() => onToggleColumn(field.name, !field.inTable)}\n >\n <Columns3 className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n {children}\n </li>\n );\n}\n\n/**\n * The distribution, as bars.\n *\n * A count alone (\"342\") means nothing without the denominator, and a reader\n * scanning for \"what is this field mostly\" reads the bar before the number.\n * The sample size is stated rather than implied — these are the top values in\n * the rows that were counted, not in all of history, and a chart that hides\n * that invites the wrong conclusion.\n */\nfunction FieldValues({\n values,\n loading,\n total,\n sampledRows,\n onFilter,\n labels,\n}: {\n values?: FieldValueCount[];\n loading: boolean;\n total: number;\n sampledRows?: number;\n onFilter?: (value: string, intent: \"include\" | \"exclude\") => void;\n labels: Required<FieldSidebarLabels>;\n}) {\n if (loading) {\n return (\n <p\n className={cn(\n OPT_TEXT_TERTIARY,\n \"flex items-center gap-2 px-3 pb-2 text-xs\",\n )}\n >\n <Spinner size=\"sm\" aria-hidden />\n {labels.loadingValues}\n </p>\n );\n }\n\n if (!values || values.length === 0) {\n return (\n <p className={cn(OPT_TEXT_TERTIARY, \"px-3 pb-2 text-xs\")}>\n {labels.noValues}\n </p>\n );\n }\n\n const denominator = sampledRows ?? total;\n\n return (\n <div className=\"flex flex-col gap-1 px-3 pt-1 pb-2\">\n <p className={cn(OPT_TEXT_TERTIARY, \"text-[11px]\")}>\n {labels.topValues(values.length)}\n {sampledRows ? ` · ${sampledRows.toLocaleString()}` : \"\"}\n </p>\n {values.map((entry) => {\n const share =\n entry.share ?? (denominator > 0 ? entry.count / denominator : 0);\n return (\n <div key={entry.value} className=\"group/value flex flex-col gap-0.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span\n className=\"text-text-secondary min-w-0 flex-1 truncate font-mono text-[11px]\"\n title={entry.value}\n >\n {entry.value || \"—\"}\n </span>\n <span\n className={cn(\n OPT_TEXT_TERTIARY,\n \"shrink-0 text-[11px] tabular-nums\",\n )}\n >\n {Math.round(share * 100)}%\n </span>\n {onFilter && (\n <span\n className={cn(\n \"flex shrink-0 items-center gap-0.5\",\n // Opacity, not `display`: a hidden element cannot be\n // focused, so `focus-within` would never fire and a\n // keyboard user could not reach these at all.\n \"opacity-0 transition-opacity\",\n \"group-hover/value:opacity-100 focus-within:opacity-100\",\n )}\n >\n <button\n type=\"button\"\n className=\"text-text-tertiary hover:text-text-primary cursor-pointer\"\n aria-label={labels.filterFor(entry.value)}\n title={labels.filterFor(entry.value)}\n onClick={() => onFilter(entry.value, \"include\")}\n >\n <Plus className=\"size-3\" aria-hidden />\n </button>\n <button\n type=\"button\"\n className=\"text-text-tertiary hover:text-text-primary cursor-pointer\"\n aria-label={labels.filterOut(entry.value)}\n title={labels.filterOut(entry.value)}\n onClick={() => onFilter(entry.value, \"exclude\")}\n >\n <Minus className=\"size-3\" aria-hidden />\n </button>\n </span>\n )}\n </div>\n <div className=\"bg-bg-muted h-1 w-full overflow-hidden rounded-full\">\n <div\n className=\"bg-accent h-full rounded-full\"\n style={{ width: `${Math.max(2, Math.round(share * 100))}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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"}