@camstack/ui-library 0.1.38 → 0.1.39

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,"sources":["../src/index.ts","../src/theme/defaults.ts","../src/theme/create-theme.ts","../src/theme/theme-to-css.ts","../src/theme/theme-provider.tsx","../src/theme/use-theme-mode.ts","../src/lib/cn.ts","../src/icons/provider-icons.ts","../src/icons/status-icons.ts","../src/primitives/button.tsx","../src/primitives/icon-button.tsx","../src/primitives/badge.tsx","../src/primitives/card.tsx","../src/primitives/label.tsx","../src/primitives/separator.tsx","../src/primitives/skeleton.tsx","../src/primitives/input.tsx","../src/primitives/select.tsx","../src/primitives/checkbox.tsx","../src/primitives/switch.tsx","../src/primitives/dialog.tsx","../src/primitives/dropdown.tsx","../src/primitives/tooltip.tsx","../src/primitives/popover.tsx","../src/hooks/use-is-mobile.ts","../src/primitives/bottom-sheet.tsx","../src/primitives/tabs.tsx","../src/primitives/scroll-area.tsx","../src/primitives/floating-panel.tsx","../src/primitives/mobile-drawer.tsx","../src/composites/status-badge.tsx","../src/composites/provider-badge.tsx","../src/composites/version-badge.tsx","../src/composites/form-field.tsx","../src/composites/page-header.tsx","../src/composites/empty-state.tsx","../src/composites/confirm-dialog.tsx","../src/composites/stat-card.tsx","../src/composites/key-value-list.tsx","../src/composites/code-block.tsx","../src/composites/filter-bar.tsx","../src/composites/app-shell/sidebar-item.tsx","../src/composites/app-shell/sidebar.tsx","../src/composites/app-shell/app-shell.tsx","../src/composites/data-table/data-table.tsx","../src/composites/data-table/data-table-header.tsx","../src/composites/data-table/data-table-row.tsx","../src/composites/data-table/data-table-pagination.tsx","../src/composites/device-card.tsx","../src/composites/device-grid.tsx","../src/composites/pipeline-step.tsx","../src/composites/pipeline-runtime-selector.tsx","../src/composites/pipeline-builder.tsx","../src/lib/validate-template.ts","../src/composites/detection-colors.ts","../src/composites/detection-canvas.tsx","../src/composites/detection-result-tree.tsx","../src/composites/step-timings.tsx","../src/composites/image-selector.tsx","../src/composites/inference-config-selector.tsx","../src/composites/mount-addon-page.tsx","../src/composites/dev-shell.tsx","../src/composites/login-form.tsx"],"sourcesContent":["export * from './theme'\nexport * from './lib'\nexport * from './icons'\nexport * from './primitives'\nexport * from './composites'\nexport * from './hooks'\n","import type { CamStackColorTokens, CamStackTheme } from './types'\n\nconst providerColors: CamStackColorTokens['provider'] = {\n frigate: '#3b82f6',\n scrypted: '#a855f7',\n reolink: '#06b6d4',\n homeAssistant: '#22d3ee',\n rtsp: '#78716c',\n}\n\nexport const darkColors: CamStackColorTokens = {\n primary: '#f59e42',\n primaryForeground: '#0c0a09',\n background: '#0c0a09',\n backgroundElevated: '#1c1917',\n surface: '#1c1917',\n surfaceHover: '#292524',\n border: '#292524',\n borderSubtle: '#1c1917',\n foreground: '#fafaf9',\n foregroundMuted: '#a8a29e',\n foregroundSubtle: '#78716c',\n foregroundDisabled: '#57534e',\n success: '#4ade80',\n warning: '#fbbf24',\n danger: '#f87171',\n info: '#60a5fa',\n provider: providerColors,\n}\n\nexport const lightColors: CamStackColorTokens = {\n primary: '#e67e22',\n primaryForeground: '#ffffff',\n background: '#fafaf9',\n backgroundElevated: '#ffffff',\n surface: '#f5f5f4',\n surfaceHover: '#e7e5e4',\n border: '#d6d3d1',\n borderSubtle: '#e7e5e4',\n foreground: '#1c1917',\n foregroundMuted: '#57534e',\n foregroundSubtle: '#78716c',\n foregroundDisabled: '#a8a29e',\n success: '#16a34a',\n warning: '#d97706',\n danger: '#dc2626',\n info: '#2563eb',\n provider: providerColors,\n}\n\nexport const defaultTheme: CamStackTheme = {\n colors: {\n dark: darkColors,\n light: lightColors,\n },\n spacing: {\n xs: 2,\n sm: 4,\n md: 8,\n lg: 12,\n xl: 16,\n '2xl': 24,\n '3xl': 32,\n },\n radius: {\n sm: 4,\n md: 6,\n lg: 8,\n xl: 12,\n },\n typography: {\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n sizes: {\n xs: { fontSize: 10, lineHeight: 14 },\n sm: { fontSize: 11, lineHeight: 16 },\n base: { fontSize: 12, lineHeight: 18 },\n lg: { fontSize: 13, lineHeight: 18 },\n xl: { fontSize: 14, lineHeight: 20 },\n '2xl': { fontSize: 16, lineHeight: 22 },\n '3xl': { fontSize: 20, lineHeight: 28 },\n },\n weights: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n },\n table: {\n rowHeight: 28,\n headerHeight: 24,\n cellPaddingX: 8,\n cellPaddingY: 6,\n },\n sidebar: {\n width: 176,\n itemHeight: 28,\n iconSize: 14,\n },\n}\n","import type { CamStackTheme, DeepPartial } from './types'\nimport { defaultTheme } from './defaults'\n\nfunction deepMerge<T extends object>(target: T, source: DeepPartial<T>): T {\n const result = { ...target }\n for (const key in source) {\n const sourceVal = source[key]\n const targetVal = target[key]\n if (\n sourceVal !== undefined &&\n typeof sourceVal === 'object' &&\n sourceVal !== null &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === 'object' &&\n targetVal !== null\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n ) as T[typeof key]\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal as T[typeof key]\n }\n }\n return result\n}\n\nexport function createTheme(overrides?: DeepPartial<CamStackTheme>): CamStackTheme {\n if (!overrides) return structuredClone(defaultTheme)\n return deepMerge(structuredClone(defaultTheme), overrides)\n}\n","import type { CamStackColorTokens, CamStackTheme } from './types'\n\nfunction camelToKebab(str: string): string {\n return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)\n}\n\nfunction colorTokenToCssVar(key: string): string {\n return `--color-${camelToKebab(key)}`\n}\n\nfunction generateColorBlock(colors: CamStackColorTokens): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(colors)) {\n if (key === 'provider') continue\n lines.push(` ${colorTokenToCssVar(key)}: ${value};`)\n }\n return lines.join('\\n')\n}\n\nfunction generateProviderColors(provider: CamStackColorTokens['provider']): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(provider)) {\n lines.push(` --color-provider-${camelToKebab(key)}: ${value};`)\n }\n return lines.join('\\n')\n}\n\nfunction generateSpacingTokens(spacing: CamStackTheme['spacing']): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(spacing)) {\n lines.push(` --spacing-${key}: ${value}px;`)\n }\n return lines.join('\\n')\n}\n\nfunction generateRadiusTokens(radius: CamStackTheme['radius']): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(radius)) {\n lines.push(` --radius-${key}: ${value}px;`)\n }\n return lines.join('\\n')\n}\n\nexport function themeToCss(theme: CamStackTheme): string {\n const darkColorBlock = generateColorBlock(theme.colors.dark)\n const lightColorBlock = generateColorBlock(theme.colors.light)\n const providerBlock = generateProviderColors(theme.colors.dark.provider)\n const spacingBlock = generateSpacingTokens(theme.spacing)\n const radiusBlock = generateRadiusTokens(theme.radius)\n\n return `@theme {\n${providerBlock}\n${spacingBlock}\n${radiusBlock}\n}\n\n.dark {\n${darkColorBlock}\n}\n\n.light {\n${lightColorBlock}\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n${darkColorBlock.replace(/^ /gm, ' ')}\n }\n}\n\n@media (prefers-color-scheme: light) {\n :root {\n${lightColorBlock.replace(/^ /gm, ' ')}\n }\n}\n`\n}\n","import { createContext, useCallback, useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { ThemeMode, UseThemeModeReturn } from './types'\n\nexport const ThemeContext = createContext<UseThemeModeReturn | null>(null)\n\ninterface ThemeProviderProps {\n children: ReactNode\n defaultMode?: ThemeMode\n storageKey?: string\n}\n\nconst TOGGLE_ORDER: readonly ThemeMode[] = ['dark', 'light', 'system'] as const\n\nfunction getSystemPreference(): 'dark' | 'light' {\n if (typeof window === 'undefined') return 'dark'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction getInitialMode(storageKey: string, defaultMode: ThemeMode): ThemeMode {\n if (typeof window === 'undefined') return defaultMode\n const stored = localStorage.getItem(storageKey)\n if (stored === 'dark' || stored === 'light' || stored === 'system') {\n return stored\n }\n return defaultMode\n}\n\nfunction resolveMode(mode: ThemeMode): 'dark' | 'light' {\n if (mode === 'system') return getSystemPreference()\n return mode\n}\n\nexport function ThemeProvider({\n children,\n defaultMode = 'system',\n storageKey = 'camstack-theme-mode',\n}: ThemeProviderProps) {\n const [mode, setModeState] = useState<ThemeMode>(() => getInitialMode(storageKey, defaultMode))\n const [resolvedMode, setResolvedMode] = useState<'dark' | 'light'>(() => resolveMode(mode))\n\n const setMode = useCallback(\n (newMode: ThemeMode) => {\n setModeState(newMode)\n setResolvedMode(resolveMode(newMode))\n if (typeof window !== 'undefined') {\n localStorage.setItem(storageKey, newMode)\n }\n },\n [storageKey],\n )\n\n const toggleMode = useCallback(() => {\n const currentIndex = TOGGLE_ORDER.indexOf(mode)\n const nextIndex = (currentIndex + 1) % TOGGLE_ORDER.length\n setMode(TOGGLE_ORDER[nextIndex] ?? 'dark')\n }, [mode, setMode])\n\n // Apply CSS class on document.documentElement\n useEffect(() => {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n root.classList.remove('dark', 'light')\n // Always apply the resolved class — even in 'system' mode, the CSS\n // variables need the .dark or .light class to activate\n root.classList.add(resolvedMode)\n }, [mode, resolvedMode])\n\n // Listen for system theme changes when in 'system' mode\n useEffect(() => {\n if (typeof window === 'undefined' || mode !== 'system') return\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n const handleChange = () => {\n setResolvedMode(getSystemPreference())\n }\n\n mediaQuery.addEventListener('change', handleChange)\n return () => mediaQuery.removeEventListener('change', handleChange)\n }, [mode])\n\n const value = useMemo<UseThemeModeReturn>(\n () => ({ mode, resolvedMode, setMode, toggleMode }),\n [mode, resolvedMode, setMode, toggleMode],\n )\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n}\n","import { useContext } from 'react'\nimport { ThemeContext } from './theme-provider'\nimport type { UseThemeModeReturn } from './types'\n\nexport function useThemeMode(): UseThemeModeReturn {\n const context = useContext(ThemeContext)\n if (!context) {\n throw new Error('useThemeMode must be used within a ThemeProvider')\n }\n return context\n}\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import { Ship, Shield, Radio, Home, Cast, type LucideIcon } from 'lucide-react'\n\nexport type ProviderType = 'frigate' | 'scrypted' | 'reolink' | 'homeAssistant' | 'rtsp'\n\nexport const providerIcons: Record<ProviderType, LucideIcon> = {\n frigate: Ship,\n scrypted: Shield,\n reolink: Radio,\n homeAssistant: Home,\n rtsp: Cast,\n}\n","import { CircleCheck, CircleX, CircleAlert, CircleHelp, type LucideIcon } from 'lucide-react'\n\nexport type StatusType = 'online' | 'offline' | 'degraded' | 'unknown'\n\nexport const statusIcons: Record<StatusType, LucideIcon> = {\n online: CircleCheck,\n offline: CircleX,\n degraded: CircleAlert,\n unknown: CircleHelp,\n}\n","import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center rounded-md font-medium transition-colors disabled:opacity-50 disabled:pointer-events-none',\n {\n variants: {\n variant: {\n primary: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary: 'bg-surface text-foreground hover:bg-surface-hover',\n ghost: 'hover:bg-surface-hover text-foreground-muted',\n danger: 'bg-danger text-white hover:bg-danger/90',\n outline: 'border border-border bg-transparent hover:bg-surface-hover',\n },\n size: {\n sm: 'h-7 px-2.5 text-xs gap-1.5',\n md: 'h-8 px-3 text-sm gap-2',\n lg: 'h-9 px-4 text-sm gap-2',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'sm',\n },\n }\n)\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n )\n }\n)\n\nButton.displayName = 'Button'\n","import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type LucideIcon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nconst iconButtonVariants = cva(\n 'inline-flex items-center justify-center rounded-md font-medium transition-colors disabled:opacity-50 disabled:pointer-events-none',\n {\n variants: {\n variant: {\n primary: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary: 'bg-surface text-foreground hover:bg-surface-hover',\n ghost: 'hover:bg-surface-hover text-foreground-muted',\n danger: 'bg-danger text-white hover:bg-danger/90',\n outline: 'border border-border bg-transparent hover:bg-surface-hover',\n },\n size: {\n sm: 'h-7 w-7',\n md: 'h-8 w-8',\n lg: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'sm',\n },\n }\n)\n\nexport interface IconButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'>,\n VariantProps<typeof iconButtonVariants> {\n icon: LucideIcon\n 'aria-label': string\n}\n\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ className, variant, size, icon: Icon, ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(iconButtonVariants({ variant, size }), className)}\n {...props}\n >\n <Icon className=\"h-4 w-4\" />\n </button>\n )\n }\n)\n\nIconButton.displayName = 'IconButton'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst badgeVariants = cva(\n 'inline-flex items-center rounded-full text-xs font-medium px-2 py-0.5',\n {\n variants: {\n variant: {\n default: 'bg-surface-hover text-foreground',\n success: 'bg-success/15 text-success',\n warning: 'bg-warning/15 text-warning',\n danger: 'bg-danger/15 text-danger',\n info: 'bg-info/15 text-info',\n },\n styleVariant: {\n solid: '',\n outline: 'border bg-transparent',\n },\n },\n defaultVariants: {\n variant: 'default',\n styleVariant: 'solid',\n },\n }\n)\n\nexport interface BadgeProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, 'style'>,\n VariantProps<typeof badgeVariants> {\n style?: 'solid' | 'outline'\n}\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant, style, ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(badgeVariants({ variant, styleVariant: style }), className)}\n {...props}\n />\n )\n }\n)\n\nBadge.displayName = 'Badge'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst cardVariants = cva('rounded-lg p-3', {\n variants: {\n variant: {\n flat: 'bg-surface',\n bordered: 'bg-surface border border-border',\n },\n },\n defaultVariants: {\n variant: 'bordered',\n },\n})\n\nexport interface CardProps\n extends HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof cardVariants> {}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(cardVariants({ variant }), className)}\n {...props}\n />\n )\n }\n)\n\nCard.displayName = 'Card'\n","import { type LabelHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {}\n\nexport const Label = forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => {\n return (\n <label\n ref={ref}\n className={cn(\n 'text-[10px] uppercase tracking-wider text-foreground-muted font-medium',\n className\n )}\n {...props}\n />\n )\n }\n)\n\nLabel.displayName = 'Label'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst separatorVariants = cva('', {\n variants: {\n orientation: {\n horizontal: 'h-px w-full bg-border-subtle',\n vertical: 'w-px h-full bg-border-subtle',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n})\n\nexport interface SeparatorProps\n extends HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof separatorVariants> {}\n\nexport const Separator = forwardRef<HTMLDivElement, SeparatorProps>(\n ({ className, orientation, ...props }, ref) => {\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cn(separatorVariants({ orientation }), className)}\n {...props}\n />\n )\n }\n)\n\nSeparator.displayName = 'Separator'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('animate-pulse bg-surface-hover rounded-md h-4 w-full', className)}\n {...props}\n />\n )\n }\n)\n\nSkeleton.displayName = 'Skeleton'\n","import { type InputHTMLAttributes, type ReactNode, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst inputVariants = cva(\n 'h-7 w-full px-2.5 text-xs bg-surface border rounded-md text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-primary transition-colors',\n {\n variants: {\n state: {\n default: 'border-border',\n error: 'border-danger',\n },\n },\n defaultVariants: {\n state: 'default',\n },\n }\n)\n\nexport interface InputProps\n extends InputHTMLAttributes<HTMLInputElement>,\n VariantProps<typeof inputVariants> {\n leftSlot?: ReactNode\n rightSlot?: ReactNode\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n ({ className, state, leftSlot, rightSlot, ...props }, ref) => {\n if (leftSlot || rightSlot) {\n return (\n <div className=\"relative flex items-center w-full\">\n {leftSlot && (\n <div className=\"absolute left-2.5 flex items-center pointer-events-none\">\n {leftSlot}\n </div>\n )}\n <input\n ref={ref}\n className={cn(\n inputVariants({ state }),\n leftSlot ? 'pl-7' : '',\n rightSlot ? 'pr-7' : '',\n className\n )}\n {...props}\n />\n {rightSlot && (\n <div className=\"absolute right-2.5 flex items-center pointer-events-none\">\n {rightSlot}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <input\n ref={ref}\n className={cn(inputVariants({ state }), className)}\n {...props}\n />\n )\n }\n)\n\nInput.displayName = 'Input'\n","import { type SelectHTMLAttributes, forwardRef } from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface SelectOption {\n value: string\n label: string\n}\n\nexport interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {\n options: SelectOption[]\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, options, ...props }, ref) => {\n return (\n <div className=\"relative w-full\">\n <select\n ref={ref}\n className={cn(\n 'h-7 w-full px-2.5 text-xs bg-surface border border-border rounded-md text-foreground appearance-none pr-7 focus:outline-none focus:ring-1 focus:ring-primary',\n className\n )}\n {...props}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <div className=\"absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none text-foreground-muted\">\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </div>\n </div>\n )\n }\n)\n\nSelect.displayName = 'Select'\n","import { type InputHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, ...props }, ref) => {\n return (\n <input\n ref={ref}\n type=\"checkbox\"\n className={cn(\n 'w-3.5 h-3.5 rounded-sm border border-border accent-primary',\n className\n )}\n {...props}\n />\n )\n }\n)\n\nCheckbox.displayName = 'Checkbox'\n","import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface SwitchProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {\n checked: boolean\n onCheckedChange: (checked: boolean) => void\n label?: string\n}\n\nexport const Switch = forwardRef<HTMLButtonElement, SwitchProps>(\n ({ className, checked, onCheckedChange, label, ...props }, ref) => {\n return (\n <button\n ref={ref}\n role=\"switch\"\n aria-checked={checked}\n type=\"button\"\n onClick={() => onCheckedChange(!checked)}\n className={cn('inline-flex items-center gap-2', className)}\n {...props}\n >\n <span\n className={cn(\n 'w-8 h-4 rounded-full transition-colors',\n checked ? 'bg-primary' : 'bg-surface-hover'\n )}\n >\n <span\n className={cn(\n 'block w-3.5 h-3.5 rounded-full bg-white transition-transform',\n checked ? 'translate-x-4' : 'translate-x-0.5'\n )}\n />\n </span>\n {label && <span className=\"text-xs text-foreground\">{label}</span>}\n </button>\n )\n }\n)\n\nSwitch.displayName = 'Switch'\n","import {\n type HTMLAttributes,\n type ReactNode,\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\ninterface DialogContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n contentId: string\n}\n\nconst DialogContext = createContext<DialogContextValue | null>(null)\n\nfunction useDialogContext() {\n const ctx = useContext(DialogContext)\n if (!ctx) throw new Error('Dialog compound components must be used within <Dialog>')\n return ctx\n}\n\n/* ── Root ── */\n\ninterface DialogProps {\n children: ReactNode\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nexport function Dialog({ children, open: controlledOpen, onOpenChange }: DialogProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false)\n const open = controlledOpen ?? uncontrolledOpen\n const contentId = useId()\n\n const setOpen = useCallback(\n (next: boolean) => {\n onOpenChange?.(next)\n if (controlledOpen === undefined) setUncontrolledOpen(next)\n },\n [controlledOpen, onOpenChange]\n )\n\n return (\n <DialogContext.Provider value={{ open, setOpen, contentId }}>\n {children}\n </DialogContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function DialogTrigger({ children, ...props }: HTMLAttributes<HTMLButtonElement>) {\n const { setOpen } = useDialogContext()\n return (\n <button type=\"button\" onClick={() => setOpen(true)} {...props}>\n {children}\n </button>\n )\n}\n\n/* ── Content ── */\n\nconst contentVariants = cva(\n 'bg-background-elevated border border-border rounded-lg p-4 backdrop:bg-black/50 backdrop:backdrop-blur-sm max-w-[calc(100vw-2rem)] max-h-[calc(100dvh-2rem)] overflow-y-auto',\n {\n variants: {\n width: {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n },\n },\n defaultVariants: { width: 'md' },\n }\n)\n\nexport interface DialogContentProps\n extends HTMLAttributes<HTMLDialogElement>,\n VariantProps<typeof contentVariants> {}\n\nexport const DialogContent = forwardRef<HTMLDialogElement, DialogContentProps>(\n ({ className, width, children, ...props }, ref) => {\n const { open, setOpen, contentId } = useDialogContext()\n const innerRef = useRef<HTMLDialogElement>(null)\n const dialogRef = (ref as React.RefObject<HTMLDialogElement>) ?? innerRef\n\n useEffect(() => {\n const el = dialogRef.current\n if (!el) return\n if (open && !el.open) el.showModal()\n if (!open && el.open) el.close()\n }, [open, dialogRef])\n\n const handleClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === e.currentTarget) setOpen(false)\n }\n\n return (\n <dialog\n ref={dialogRef}\n id={contentId}\n className={cn(contentVariants({ width }), 'w-full', className)}\n onClick={handleClick}\n onClose={() => setOpen(false)}\n {...props}\n >\n {children}\n </dialog>\n )\n }\n)\n\nDialogContent.displayName = 'DialogContent'\n\n/* ── Header / Footer / Title / Description ── */\n\nexport function DialogHeader({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('flex flex-col gap-1 mb-3', className)} {...props} />\n}\n\nexport function DialogFooter({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('flex justify-end gap-2 mt-4', className)} {...props} />\n}\n\nexport function DialogTitle({ className, ...props }: HTMLAttributes<HTMLHeadingElement>) {\n return <h2 className={cn('text-sm font-semibold text-foreground', className)} {...props} />\n}\n\nexport function DialogDescription({ className, ...props }: HTMLAttributes<HTMLParagraphElement>) {\n return <p className={cn('text-xs text-foreground-muted', className)} {...props} />\n}\n","import {\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { type LucideIcon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\ninterface DropdownContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n triggerId: string\n contentId: string\n}\n\nconst DropdownContext = createContext<DropdownContextValue | null>(null)\n\nfunction useDropdownContext() {\n const ctx = useContext(DropdownContext)\n if (!ctx) throw new Error('Dropdown compound components must be used within <Dropdown>')\n return ctx\n}\n\n/* ── Root ── */\n\nexport function Dropdown({ children }: { children: ReactNode }) {\n const [open, setOpen] = useState(false)\n const triggerId = useId()\n const contentId = useId()\n\n return (\n <DropdownContext.Provider value={{ open, setOpen, triggerId, contentId }}>\n <div className=\"relative inline-block\">{children}</div>\n </DropdownContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function DropdownTrigger({ children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {\n const { open, setOpen, triggerId, contentId } = useDropdownContext()\n return (\n <button\n type=\"button\"\n id={triggerId}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n onClick={() => setOpen(!open)}\n {...props}\n >\n {children}\n </button>\n )\n}\n\n/* ── Content ── */\n\nexport function DropdownContent({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { open, setOpen, contentId, triggerId } = useDropdownContext()\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n const el = ref.current\n const trigger = document.getElementById(triggerId)\n if (el && !el.contains(e.target as Node) && !trigger?.contains(e.target as Node)) {\n setOpen(false)\n }\n }\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n document.addEventListener('keydown', escHandler)\n return () => {\n document.removeEventListener('mousedown', handler)\n document.removeEventListener('keydown', escHandler)\n }\n }, [open, setOpen, triggerId])\n\n if (!open) return null\n\n return (\n <div\n ref={ref}\n id={contentId}\n role=\"menu\"\n aria-labelledby={triggerId}\n className={cn(\n 'absolute left-0 top-full z-50 mt-1 bg-background-elevated border border-border rounded-md shadow-lg py-1 min-w-[160px]',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\n/* ── Item ── */\n\ninterface DropdownItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n icon?: LucideIcon\n variant?: 'default' | 'danger'\n}\n\nexport function DropdownItem({\n className,\n icon: Icon,\n variant = 'default',\n children,\n onClick,\n ...props\n}: DropdownItemProps) {\n const { setOpen } = useDropdownContext()\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n setOpen(false)\n },\n [onClick, setOpen]\n )\n\n return (\n <button\n type=\"button\"\n role=\"menuitem\"\n className={cn(\n 'h-7 text-xs px-2 w-full text-left flex items-center gap-2',\n variant === 'danger'\n ? 'text-danger hover:bg-danger/10'\n : 'text-foreground hover:bg-surface-hover',\n className\n )}\n onClick={handleClick}\n {...props}\n >\n {Icon && <Icon size={14} />}\n {children}\n </button>\n )\n}\n","import {\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useContext,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { cn } from '../lib/cn'\n\ninterface TooltipContextValue {\n open: boolean\n show: () => void\n hide: () => void\n tooltipId: string\n}\n\nconst TooltipContext = createContext<TooltipContextValue | null>(null)\n\nfunction useTooltipContext() {\n const ctx = useContext(TooltipContext)\n if (!ctx) throw new Error('Tooltip compound components must be used within <Tooltip>')\n return ctx\n}\n\n/* ── Root ── */\n\nexport function Tooltip({ children }: { children: ReactNode }) {\n const [open, setOpen] = useState(false)\n const timerRef = useRef<ReturnType<typeof setTimeout>>(null)\n const tooltipId = useId()\n\n const show = () => {\n timerRef.current = setTimeout(() => setOpen(true), 300)\n }\n\n const hide = () => {\n if (timerRef.current) clearTimeout(timerRef.current)\n setOpen(false)\n }\n\n return (\n <TooltipContext.Provider value={{ open, show, hide, tooltipId }}>\n <div className=\"relative inline-block\">{children}</div>\n </TooltipContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function TooltipTrigger({ children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { show, hide, tooltipId, open } = useTooltipContext()\n\n return (\n <div\n onMouseEnter={show}\n onMouseLeave={hide}\n onFocus={show}\n onBlur={hide}\n aria-describedby={open ? tooltipId : undefined}\n {...props}\n >\n {children}\n </div>\n )\n}\n\n/* ── Content ── */\n\nexport function TooltipContent({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { open, tooltipId } = useTooltipContext()\n\n return (\n <div\n id={tooltipId}\n role=\"tooltip\"\n className={cn(\n 'absolute bottom-full left-1/2 -translate-x-1/2 mb-2 bg-foreground text-background text-xs px-2 py-1 rounded-md shadow-md whitespace-nowrap pointer-events-none transition-opacity duration-150',\n open ? 'opacity-100' : 'opacity-0',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import {\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { cn } from '../lib/cn'\nimport { useIsMobile } from '../hooks/use-is-mobile'\nimport { BottomSheet } from './bottom-sheet'\n\ninterface PopoverContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n triggerId: string\n contentId: string\n}\n\nconst PopoverContext = createContext<PopoverContextValue | null>(null)\n\nfunction usePopoverContext() {\n const ctx = useContext(PopoverContext)\n if (!ctx) throw new Error('Popover compound components must be used within <Popover>')\n return ctx\n}\n\n/* ── Root ── */\n\ninterface PopoverProps {\n children: ReactNode\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nexport function Popover({ children, open: controlledOpen, onOpenChange }: PopoverProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false)\n const open = controlledOpen ?? uncontrolledOpen\n const triggerId = useId()\n const contentId = useId()\n\n const setOpen = useCallback(\n (next: boolean) => {\n onOpenChange?.(next)\n if (controlledOpen === undefined) setUncontrolledOpen(next)\n },\n [controlledOpen, onOpenChange]\n )\n\n return (\n <PopoverContext.Provider value={{ open, setOpen, triggerId, contentId }}>\n <div className=\"relative inline-block\">{children}</div>\n </PopoverContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function PopoverTrigger({ children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {\n const { open, setOpen, triggerId, contentId } = usePopoverContext()\n return (\n <button\n type=\"button\"\n id={triggerId}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n onClick={() => setOpen(!open)}\n {...props}\n >\n {children}\n </button>\n )\n}\n\n/* ── Content ── */\n\nexport function PopoverContent({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { open, setOpen, contentId, triggerId } = usePopoverContext()\n const isMobile = useIsMobile()\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!open || isMobile) return\n const handler = (e: MouseEvent) => {\n const el = ref.current\n const trigger = document.getElementById(triggerId)\n if (el && !el.contains(e.target as Node) && !trigger?.contains(e.target as Node)) {\n setOpen(false)\n }\n }\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n document.addEventListener('keydown', escHandler)\n return () => {\n document.removeEventListener('mousedown', handler)\n document.removeEventListener('keydown', escHandler)\n }\n }, [open, setOpen, triggerId, isMobile])\n\n if (!open) return null\n\n if (isMobile) {\n return (\n <BottomSheet open={open} onClose={() => setOpen(false)}>\n {children}\n </BottomSheet>\n )\n }\n\n return (\n <div\n ref={ref}\n id={contentId}\n role=\"dialog\"\n aria-labelledby={triggerId}\n className={cn(\n 'absolute left-0 top-full z-50 mt-1 bg-background-elevated border border-border rounded-lg shadow-lg p-3',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import { useSyncExternalStore } from 'react'\n\nconst MOBILE_QUERY = '(max-width: 767px)'\n\nfunction subscribe(callback: () => void): () => void {\n const mql = window.matchMedia(MOBILE_QUERY)\n mql.addEventListener('change', callback)\n return () => mql.removeEventListener('change', callback)\n}\n\nfunction getSnapshot(): boolean {\n return window.matchMedia(MOBILE_QUERY).matches\n}\n\nfunction getServerSnapshot(): boolean {\n return false\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n","import { type ReactNode, useEffect } from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface BottomSheetProps {\n open: boolean\n onClose: () => void\n title?: string\n children: ReactNode\n className?: string\n}\n\nexport function BottomSheet({ open, onClose, title, children, className }: BottomSheetProps) {\n useEffect(() => {\n if (!open) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', handleKeyDown)\n document.body.style.overflow = ''\n }\n }, [open, onClose])\n\n return (\n <>\n {/* Backdrop */}\n <div\n className={cn(\n 'fixed inset-0 z-40 bg-black/50 transition-opacity duration-200',\n open ? 'opacity-100' : 'pointer-events-none opacity-0'\n )}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n {/* Sheet */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n className={cn(\n 'fixed inset-x-0 bottom-0 z-50 flex flex-col bg-background-elevated border-t border-border rounded-t-xl shadow-2xl transition-transform duration-200 ease-out',\n 'max-h-[80dvh]',\n open ? 'translate-y-0' : 'translate-y-full',\n className\n )}\n >\n {/* Handle bar */}\n <div className=\"flex justify-center pt-2 pb-1\">\n <div className=\"h-1 w-8 rounded-full bg-foreground-subtle/30\" />\n </div>\n\n {/* Header */}\n {title && (\n <div className=\"flex items-center justify-between px-4 pb-2\">\n <span className=\"text-sm font-medium text-foreground\">{title}</span>\n <button\n onClick={onClose}\n className=\"p-1 rounded-md hover:bg-surface-hover text-foreground-muted transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto px-4 pb-4\">\n {children}\n </div>\n </div>\n </>\n )\n}\n","import {\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useState,\n} from 'react'\nimport { cn } from '../lib/cn'\n\ninterface TabsContextValue {\n value: string\n setValue: (value: string) => void\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext() {\n const ctx = useContext(TabsContext)\n if (!ctx) throw new Error('Tabs compound components must be used within <Tabs>')\n return ctx\n}\n\n/* ── Root ── */\n\ninterface TabsProps extends HTMLAttributes<HTMLDivElement> {\n value?: string\n onValueChange?: (value: string) => void\n defaultValue?: string\n}\n\nexport function Tabs({\n value: controlledValue,\n onValueChange,\n defaultValue = '',\n className,\n ...props\n}: TabsProps) {\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue)\n const value = controlledValue ?? uncontrolledValue\n\n const setValue = useCallback(\n (next: string) => {\n onValueChange?.(next)\n if (controlledValue === undefined) setUncontrolledValue(next)\n },\n [controlledValue, onValueChange]\n )\n\n return (\n <TabsContext.Provider value={{ value, setValue }}>\n <div className={className} {...props} />\n </TabsContext.Provider>\n )\n}\n\n/* ── TabsList ── */\n\nexport function TabsList({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n role=\"tablist\"\n className={cn('flex flex-row border-b border-border-subtle', className)}\n {...props}\n />\n )\n}\n\n/* ── TabsTrigger ── */\n\ninterface TabsTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nexport function TabsTrigger({ value, className, ...props }: TabsTriggerProps) {\n const { value: activeValue, setValue } = useTabsContext()\n const isActive = value === activeValue\n const panelId = `tabpanel-${value}`\n\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={panelId}\n tabIndex={isActive ? 0 : -1}\n className={cn(\n 'h-7 text-xs px-3 transition-colors',\n isActive\n ? 'border-b-2 border-primary text-foreground font-medium'\n : 'text-foreground-muted hover:text-foreground',\n className\n )}\n onClick={() => setValue(value)}\n {...props}\n />\n )\n}\n\n/* ── TabsContent ── */\n\ninterface TabsContentProps extends HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nexport function TabsContent({ value, className, ...props }: TabsContentProps) {\n const { value: activeValue } = useTabsContext()\n if (value !== activeValue) return null\n\n return (\n <div\n role=\"tabpanel\"\n id={`tabpanel-${value}`}\n className={cn('pt-3', className)}\n {...props}\n />\n )\n}\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport const ScrollArea = forwardRef<HTMLDivElement, ScrollAreaProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'overflow-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-surface-hover [&::-webkit-scrollbar-thumb]:rounded-full',\n className\n )}\n {...props}\n />\n )\n }\n)\n\nScrollArea.displayName = 'ScrollArea'\n","import { useRef, useState, useCallback, useEffect, type ReactNode } from 'react';\nimport { X, Minimize2, Maximize2, GripHorizontal } from 'lucide-react';\nimport { cn } from '../lib/cn';\nimport { useIsMobile } from '../hooks/use-is-mobile';\n\nexport interface FloatingPanelProps {\n /** Panel title displayed in the title bar */\n title: string;\n /** Called when the close button is clicked */\n onClose: () => void;\n /** Panel content */\n children: ReactNode;\n /** Default width in pixels */\n defaultWidth?: number;\n /** Default height in pixels */\n defaultHeight?: number;\n /** Minimum width in pixels */\n minWidth?: number;\n /** Minimum height in pixels */\n minHeight?: number;\n /** Offset index to stagger multiple panels (adds 30px offset per index) */\n offsetIndex?: number;\n /** Additional CSS classes for the panel container */\n className?: string;\n}\n\nexport function FloatingPanel({\n title,\n onClose,\n children,\n defaultWidth = 360,\n defaultHeight = 280,\n minWidth = 280,\n minHeight = 160,\n offsetIndex = 0,\n className,\n}: FloatingPanelProps) {\n const [pos, setPos] = useState({ x: 80 + offsetIndex * 30, y: 80 + offsetIndex * 30 });\n const [size, setSize] = useState({ w: defaultWidth, h: defaultHeight });\n const [minimized, setMinimized] = useState(false);\n const dragging = useRef(false);\n const resizing = useRef(false);\n const offset = useRef({ x: 0, y: 0 });\n const isMobile = useIsMobile();\n\n const onDragStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n dragging.current = true;\n offset.current = { x: e.clientX - pos.x, y: e.clientY - pos.y };\n }, [pos]);\n\n const onResizeStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n resizing.current = true;\n offset.current = { x: e.clientX, y: e.clientY };\n }, []);\n\n useEffect(() => {\n const onMouseMove = (e: MouseEvent) => {\n if (dragging.current) setPos({ x: e.clientX - offset.current.x, y: e.clientY - offset.current.y });\n if (resizing.current) {\n const dx = e.clientX - offset.current.x;\n const dy = e.clientY - offset.current.y;\n offset.current = { x: e.clientX, y: e.clientY };\n setSize(prev => ({ w: Math.max(minWidth, prev.w + dx), h: Math.max(minHeight, prev.h + dy) }));\n }\n };\n const onMouseUp = () => { dragging.current = false; resizing.current = false; };\n window.addEventListener('mousemove', onMouseMove);\n window.addEventListener('mouseup', onMouseUp);\n return () => { window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); };\n }, [minWidth, minHeight]);\n\n if (isMobile) {\n return (\n <div\n className={cn(\n 'fixed inset-x-0 bottom-0 z-50 rounded-t-xl border-t border-border bg-background-elevated shadow-2xl flex flex-col overflow-hidden',\n className\n )}\n style={{ maxHeight: '60dvh' }}\n >\n <div className=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border shrink-0 bg-surface\">\n <span className=\"text-[11px] font-medium truncate\">{title}</span>\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n onClick={() => setMinimized(!minimized)}\n className=\"p-0.5 rounded hover:bg-surface-hover text-foreground-muted transition-colors\"\n >\n {minimized ? <Maximize2 size={12} /> : <Minimize2 size={12} />}\n </button>\n <button\n onClick={onClose}\n className=\"p-0.5 rounded hover:bg-danger/20 text-foreground-muted hover:text-danger transition-colors\"\n >\n <X size={12} />\n </button>\n </div>\n </div>\n {!minimized && (\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {children}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'fixed z-50 rounded-lg border border-border bg-background-elevated shadow-2xl flex flex-col overflow-hidden',\n className\n )}\n style={{ left: pos.x, top: pos.y, width: minimized ? 280 : size.w, height: minimized ? 'auto' : size.h }}\n >\n {/* Title bar — draggable */}\n <div\n onMouseDown={onDragStart}\n className=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border cursor-move select-none shrink-0 bg-surface\"\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <GripHorizontal size={12} className=\"text-foreground-subtle shrink-0\" />\n <span className=\"text-[11px] font-medium truncate\">{title}</span>\n </div>\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n onClick={() => setMinimized(!minimized)}\n className=\"p-0.5 rounded hover:bg-surface-hover text-foreground-muted transition-colors\"\n title={minimized ? 'Restore' : 'Minimize'}\n >\n {minimized ? <Maximize2 size={12} /> : <Minimize2 size={12} />}\n </button>\n <button\n onClick={onClose}\n className=\"p-0.5 rounded hover:bg-danger/20 text-foreground-muted hover:text-danger transition-colors\"\n title=\"Close\"\n >\n <X size={12} />\n </button>\n </div>\n </div>\n\n {/* Content */}\n {!minimized && (\n <div className=\"flex-1 min-h-0 overflow-y-auto relative\">\n {children}\n {/* Resize handle */}\n <div\n onMouseDown={onResizeStart}\n className=\"absolute bottom-0 right-0 w-4 h-4 cursor-nwse-resize\"\n style={{ background: 'linear-gradient(135deg, transparent 50%, var(--color-foreground-subtle) 50%)', opacity: 0.4 }}\n />\n </div>\n )}\n </div>\n );\n}\n","import { type ReactNode, useEffect, useRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface MobileDrawerProps {\n open: boolean\n onClose: () => void\n children: ReactNode\n className?: string\n /** Width of the drawer panel. Default: 'w-64' */\n width?: string\n}\n\nexport function MobileDrawer({ open, onClose, children, className, width = 'w-64' }: MobileDrawerProps) {\n const drawerRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!open) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', handleKeyDown)\n document.body.style.overflow = ''\n }\n }, [open, onClose])\n\n return (\n <>\n {/* Backdrop */}\n <div\n className={cn(\n 'fixed inset-0 z-40 bg-black/50 backdrop-blur-sm transition-opacity duration-200',\n open ? 'opacity-100' : 'pointer-events-none opacity-0'\n )}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n {/* Drawer panel */}\n <div\n ref={drawerRef}\n role=\"dialog\"\n aria-modal=\"true\"\n className={cn(\n 'fixed inset-y-0 left-0 z-50 flex flex-col bg-surface border-r border-border shadow-2xl transition-transform duration-200 ease-out',\n width,\n open ? 'translate-x-0' : '-translate-x-full',\n className\n )}\n >\n {children}\n </div>\n </>\n )\n}\n","import { cn } from '../lib/cn'\n\ntype Status = 'online' | 'offline' | 'degraded' | 'unknown'\n\nexport interface StatusBadgeProps {\n status: Status\n showDot?: boolean\n showLabel?: boolean\n size?: 'sm' | 'md'\n className?: string\n}\n\nconst statusConfig: Record<Status, { colorClass: string; label: string }> = {\n online: { colorClass: 'bg-success', label: 'Online' },\n offline: { colorClass: 'bg-danger', label: 'Offline' },\n degraded: { colorClass: 'bg-warning', label: 'Degraded' },\n unknown: { colorClass: 'bg-foreground-subtle', label: 'Unknown' },\n}\n\nexport function StatusBadge({\n status,\n showDot = true,\n showLabel = true,\n size = 'sm',\n className,\n}: StatusBadgeProps) {\n const config = statusConfig[status]\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5',\n size === 'sm' ? 'text-xs' : 'text-sm',\n className\n )}\n >\n {showDot && (\n <span\n className={cn('h-1.5 w-1.5 shrink-0 rounded-full', config.colorClass)}\n aria-hidden=\"true\"\n />\n )}\n {showLabel && (\n <span className=\"text-foreground\">{config.label}</span>\n )}\n </span>\n )\n}\n","import { cn } from '../lib/cn'\nimport type { ProviderType } from '../icons'\n\nexport interface ProviderBadgeProps {\n provider: ProviderType\n showLabel?: boolean\n className?: string\n}\n\nconst providerConfig: Record<ProviderType, { colorClass: string; label: string }> = {\n frigate: { colorClass: 'bg-provider-frigate', label: 'Frigate' },\n scrypted: { colorClass: 'bg-provider-scrypted', label: 'Scrypted' },\n reolink: { colorClass: 'bg-provider-reolink', label: 'Reolink' },\n homeAssistant: { colorClass: 'bg-provider-homeAssistant', label: 'Home Assistant' },\n rtsp: { colorClass: 'bg-provider-rtsp', label: 'RTSP' },\n}\n\nexport function ProviderBadge({\n provider,\n showLabel = true,\n className,\n}: ProviderBadgeProps) {\n const config = providerConfig[provider]\n\n return (\n <span className={cn('inline-flex items-center gap-1.5 text-xs', className)}>\n <span\n className={cn('h-1.5 w-1.5 shrink-0 rounded-sm', config.colorClass)}\n aria-hidden=\"true\"\n />\n {showLabel && (\n <span className=\"text-foreground\">{config.label}</span>\n )}\n </span>\n )\n}\n","import React from 'react'\nimport { cn } from '../lib/cn'\n\nexport type SemanticBadgeVariant = 'success' | 'warning' | 'danger' | 'info' | 'neutral'\n\nconst VARIANT_STYLES: Record<SemanticBadgeVariant, string> = {\n success: 'bg-emerald-400 text-emerald-950',\n warning: 'bg-amber-400 text-amber-950',\n danger: 'bg-red-400 text-red-950',\n info: 'bg-blue-400 text-blue-950',\n neutral: 'bg-foreground-subtle/20 text-foreground',\n}\n\nexport interface SemanticBadgeProps {\n children: React.ReactNode\n variant?: SemanticBadgeVariant\n /** Use monospace font (good for versions, codes) */\n mono?: boolean\n className?: string\n}\n\n/**\n * General-purpose badge with semantic color variants.\n * Solid background with dark text for maximum contrast.\n */\nexport function SemanticBadge({ children, variant = 'neutral', mono, className }: SemanticBadgeProps) {\n return (\n <span className={cn(\n 'inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-bold leading-tight',\n mono && 'font-mono',\n VARIANT_STYLES[variant],\n className,\n )}>\n {children}\n </span>\n )\n}\n\n// --- Convenience wrappers ---\n\nexport interface VersionBadgeProps {\n version: string\n preRelease?: boolean\n className?: string\n}\n\n/**\n * Version badge — auto-detects pre-release versions.\n * Stable = success (green), Pre-release = warning (amber).\n */\nexport function VersionBadge({ version, preRelease, className }: VersionBadgeProps) {\n const isPreRelease = preRelease ?? /-(alpha|beta|rc|dev|canary|next)/i.test(version)\n return (\n <SemanticBadge variant={isPreRelease ? 'warning' : 'success'} mono className={className}>\n {version}\n </SemanticBadge>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\nimport { Label } from '../primitives'\n\nexport interface FormFieldProps {\n label: string\n description?: string\n error?: string\n required?: boolean\n children: ReactNode\n orientation?: 'vertical' | 'horizontal'\n className?: string\n}\n\nexport function FormField({\n label,\n description,\n error,\n required,\n children,\n orientation = 'vertical',\n className,\n}: FormFieldProps) {\n const isHorizontal = orientation === 'horizontal'\n\n return (\n <div\n className={cn(\n 'flex gap-2',\n isHorizontal ? 'flex-row items-center justify-between' : 'flex-col',\n className\n )}\n >\n <div className={cn(isHorizontal ? 'flex-1' : '')}>\n <Label>\n {label}\n {required && <span className=\"text-danger ml-0.5\">*</span>}\n </Label>\n {description && (\n <p className=\"text-foreground-subtle text-xs mt-0.5\">{description}</p>\n )}\n </div>\n <div className={cn(isHorizontal ? 'shrink-0' : '')}>\n {children}\n </div>\n {error && (\n <p className=\"text-danger text-xs\">{error}</p>\n )}\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface PageHeaderProps {\n title: string\n subtitle?: string\n actions?: ReactNode\n className?: string\n}\n\nexport function PageHeader({ title, subtitle, actions, className }: PageHeaderProps) {\n return (\n <div className={cn('flex flex-col gap-2 mb-3 sm:flex-row sm:items-center sm:justify-between', className)}>\n <div>\n <h1 className=\"text-sm font-semibold text-foreground\">{title}</h1>\n {subtitle && (\n <p className=\"text-foreground-subtle text-xs\">{subtitle}</p>\n )}\n </div>\n {actions && <div className=\"flex items-center gap-2 flex-wrap\">{actions}</div>}\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { type LucideIcon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface EmptyStateProps {\n icon?: LucideIcon\n title: string\n description?: string\n action?: ReactNode\n className?: string\n}\n\nexport function EmptyState({\n icon: Icon,\n title,\n description,\n action,\n className,\n}: EmptyStateProps) {\n return (\n <div className={cn('flex flex-col items-center justify-center gap-3 py-12', className)}>\n {Icon && (\n <Icon className=\"h-12 w-12 text-foreground-subtle\" aria-hidden=\"true\" />\n )}\n <div className=\"flex flex-col items-center gap-1 text-center\">\n <p className=\"text-foreground-muted text-sm font-medium\">{title}</p>\n {description && (\n <p className=\"text-foreground-subtle text-xs max-w-xs\">{description}</p>\n )}\n </div>\n {action && <div className=\"mt-1\">{action}</div>}\n </div>\n )\n}\n","import {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n Button,\n} from '../primitives'\n\nexport interface ConfirmDialogProps {\n title: string\n message: string\n confirmLabel?: string\n cancelLabel?: string\n onConfirm: () => void\n onCancel: () => void\n variant?: 'danger' | 'default'\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nexport function ConfirmDialog({\n title,\n message,\n confirmLabel = 'Confirm',\n cancelLabel = 'Cancel',\n onConfirm,\n onCancel,\n variant = 'default',\n open,\n onOpenChange,\n}: ConfirmDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{message}</DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button\n variant={variant === 'danger' ? 'danger' : 'primary'}\n onClick={onConfirm}\n >\n {confirmLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import { TrendingUp, TrendingDown } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Card } from '../primitives'\n\nexport interface StatCardProps {\n value: string | number\n label: string\n trend?: { value: number; direction: 'up' | 'down' }\n className?: string\n}\n\nexport function StatCard({ value, label, trend, className }: StatCardProps) {\n return (\n <Card className={cn('flex flex-col gap-1', className)}>\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-2xl font-semibold text-foreground\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'inline-flex items-center gap-0.5 text-xs font-medium',\n trend.direction === 'up' ? 'text-success' : 'text-danger'\n )}\n >\n {trend.direction === 'up' ? (\n <TrendingUp className=\"h-3 w-3\" />\n ) : (\n <TrendingDown className=\"h-3 w-3\" />\n )}\n {trend.value}%\n </span>\n )}\n </div>\n <span className=\"text-xs text-foreground-muted\">{label}</span>\n </Card>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface KeyValueListProps {\n items: { key: string; value: ReactNode }[]\n className?: string\n}\n\nexport function KeyValueList({ items, className }: KeyValueListProps) {\n return (\n <dl className={cn('flex flex-col', className)}>\n {items.map((item) => (\n <div\n key={item.key}\n className=\"flex items-center h-7\"\n >\n <dt className=\"text-foreground-subtle text-xs w-1/3 shrink-0\">\n {item.key}\n </dt>\n <dd className=\"text-foreground text-xs\">{item.value}</dd>\n </div>\n ))}\n </dl>\n )\n}\n","import { useCallback, useState } from 'react'\nimport { Copy, Check } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { ScrollArea, IconButton } from '../primitives'\n\nexport interface CodeBlockProps {\n children: string\n maxHeight?: number\n className?: string\n}\n\nexport function CodeBlock({ children, maxHeight = 300, className }: CodeBlockProps) {\n const [copied, setCopied] = useState(false)\n\n const handleCopy = useCallback(() => {\n navigator.clipboard.writeText(children).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n })\n }, [children])\n\n return (\n <div className={cn('relative group', className)}>\n <ScrollArea style={{ maxHeight }}>\n <pre className=\"font-mono text-xs bg-surface p-3 rounded-md border border-border-subtle\">\n <code>{children}</code>\n </pre>\n </ScrollArea>\n <div className=\"absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity\">\n <IconButton\n icon={copied ? Check : Copy}\n aria-label=\"Copy code\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCopy}\n />\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport { Search, SlidersHorizontal } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Input, Select, Badge, BottomSheet } from '../primitives'\nimport { useIsMobile } from '../hooks/use-is-mobile'\n\ntype FilterDef =\n | { type: 'search'; key: string; placeholder?: string }\n | { type: 'select'; key: string; label: string; options: { value: string; label: string }[] }\n | { type: 'badge-toggle'; key: string; options: { value: string; label: string }[] }\n\nexport type { FilterDef }\n\nexport interface FilterBarProps {\n filters: FilterDef[]\n values: Record<string, unknown>\n onChange: (values: Record<string, unknown>) => void\n className?: string\n}\n\nexport function FilterBar({ filters, values, onChange, className }: FilterBarProps) {\n const isMobile = useIsMobile()\n const [sheetOpen, setSheetOpen] = useState(false)\n\n const handleChange = (key: string, value: unknown) => {\n onChange({ ...values, [key]: value })\n }\n\n const activeCount = Object.values(values).filter((v) => v !== undefined && v !== '').length\n\n if (isMobile) {\n const searchFilter = filters.find((f) => f.type === 'search')\n const hasNonSearchFilters = filters.some((f) => f.type !== 'search')\n\n return (\n <div className={cn('flex items-center gap-2', className)}>\n {searchFilter && (\n <Input\n placeholder={searchFilter.placeholder ?? 'Search...'}\n value={(values[searchFilter.key] as string) ?? ''}\n onChange={(e) => handleChange(searchFilter.key, e.target.value)}\n leftSlot={<Search className=\"h-3 w-3 text-foreground-subtle\" />}\n className=\"flex-1\"\n />\n )}\n {hasNonSearchFilters && (\n <>\n <button\n onClick={() => setSheetOpen(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1.5 text-xs text-foreground-muted hover:bg-surface-hover transition-colors shrink-0\"\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {activeCount > 0 && (\n <Badge variant=\"info\" className=\"ml-1 text-[10px] px-1 py-0\">{activeCount}</Badge>\n )}\n </button>\n <BottomSheet open={sheetOpen} onClose={() => setSheetOpen(false)} title=\"Filters\">\n <div className=\"flex flex-col gap-3\">\n {filters.filter((f) => f.type !== 'search').map((filter) => {\n switch (filter.type) {\n case 'select':\n return (\n <div key={filter.key}>\n <label className=\"text-xs text-foreground-muted mb-1 block\">{filter.label}</label>\n <Select\n options={filter.options}\n value={(values[filter.key] as string) ?? ''}\n onChange={(e) => handleChange(filter.key, e.target.value)}\n className=\"w-full\"\n />\n </div>\n )\n case 'badge-toggle':\n return (\n <div key={filter.key} className=\"flex items-center gap-1 flex-wrap\">\n {filter.options.map((option) => {\n const currentValue = values[filter.key]\n const isActive = currentValue === option.value\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => handleChange(filter.key, isActive ? undefined : option.value)}\n >\n <Badge variant={isActive ? 'info' : 'default'} className=\"cursor-pointer\">\n {option.label}\n </Badge>\n </button>\n )\n })}\n </div>\n )\n default:\n return null\n }\n })}\n </div>\n </BottomSheet>\n </>\n )}\n </div>\n )\n }\n\n return (\n <div className={cn('flex items-center gap-2 flex-wrap', className)}>\n {filters.map((filter) => {\n switch (filter.type) {\n case 'search':\n return (\n <Input\n key={filter.key}\n placeholder={filter.placeholder ?? 'Search...'}\n value={(values[filter.key] as string) ?? ''}\n onChange={(e) => handleChange(filter.key, e.target.value)}\n leftSlot={<Search className=\"h-3 w-3 text-foreground-subtle\" />}\n className=\"w-48\"\n />\n )\n case 'select':\n return (\n <Select\n key={filter.key}\n options={filter.options}\n value={(values[filter.key] as string) ?? ''}\n onChange={(e) => handleChange(filter.key, e.target.value)}\n className=\"w-36\"\n />\n )\n case 'badge-toggle':\n return (\n <div key={filter.key} className=\"flex items-center gap-1\">\n {filter.options.map((option) => {\n const currentValue = values[filter.key]\n const isActive = currentValue === option.value\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => handleChange(filter.key, isActive ? undefined : option.value)}\n >\n <Badge variant={isActive ? 'info' : 'default'} className=\"cursor-pointer\">\n {option.label}\n </Badge>\n </button>\n )\n })}\n </div>\n )\n default:\n return null\n }\n })}\n </div>\n )\n}\n","import { type LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport { Badge } from '../../primitives'\n\nexport interface SidebarItemProps {\n label: string\n icon: LucideIcon\n href: string\n badge?: string | number\n active?: boolean\n className?: string\n}\n\nexport function SidebarItem({\n label,\n icon: Icon,\n href,\n badge,\n active = false,\n className,\n}: SidebarItemProps) {\n return (\n <a\n href={href}\n className={cn(\n 'flex items-center gap-2 h-7 px-2 text-[11px] transition-colors',\n active\n ? 'border-l-2 border-primary bg-primary/[0.08] text-foreground rounded-r-md'\n : 'text-foreground-subtle hover:bg-surface-hover rounded-md',\n className\n )}\n >\n <Icon className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1\">{label}</span>\n {badge !== undefined && (\n <Badge className=\"ml-auto text-[10px] px-1.5 py-0\">{badge}</Badge>\n )}\n </a>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { Separator } from '../../primitives'\nimport { SidebarItem, type SidebarItemProps } from './sidebar-item'\n\nexport interface SidebarSection {\n label?: string\n items: SidebarItemProps[]\n}\n\nexport interface SidebarProps {\n logo?: ReactNode\n sections: SidebarSection[]\n footer?: SidebarItemProps[]\n onNavigate?: () => void\n className?: string\n}\n\nexport function Sidebar({ logo, sections, footer, onNavigate, className }: SidebarProps) {\n return (\n <nav\n className={cn(\n 'bg-surface border-r border-border h-full flex flex-col',\n className\n )}\n >\n {logo && <div className=\"px-3 py-2 shrink-0\">{logo}</div>}\n\n <div className=\"flex-1 overflow-auto px-1 py-1\">\n {sections.map((section, sectionIndex) => (\n <div key={sectionIndex} className={cn(sectionIndex > 0 ? 'mt-3' : '')}>\n {section.label && (\n <span className=\"text-[10px] text-foreground-disabled uppercase tracking-wider px-2 mb-1 block\">\n {section.label}\n </span>\n )}\n <div className=\"flex flex-col gap-0.5\" onClick={onNavigate}>\n {section.items.map((item) => (\n <SidebarItem key={item.href} {...item} />\n ))}\n </div>\n </div>\n ))}\n </div>\n\n {footer && footer.length > 0 && (\n <div className=\"shrink-0 px-1 pb-1\">\n <Separator className=\"mb-1\" />\n <div className=\"flex flex-col gap-0.5\" onClick={onNavigate}>\n {footer.map((item) => (\n <SidebarItem key={item.href} {...item} />\n ))}\n </div>\n </div>\n )}\n </nav>\n )\n}\n","import { type ReactNode, useState } from 'react'\nimport { ChevronRight, Menu } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport { useIsMobile } from '../../hooks/use-is-mobile'\nimport { MobileDrawer } from '../../primitives/mobile-drawer'\nimport { Sidebar, type SidebarProps } from './sidebar'\n\nexport interface AppShellProps {\n sidebar: SidebarProps\n header?: {\n breadcrumbs?: { label: string; href?: string }[]\n actions?: ReactNode\n }\n /** Content shown in the center of the mobile top bar (e.g. logo) */\n mobileLogo?: ReactNode\n /** Content shown on the right side of the mobile top bar (e.g. avatar menu) */\n mobileActions?: ReactNode\n children: ReactNode\n className?: string\n}\n\nexport function AppShell({ sidebar, header, mobileLogo, mobileActions, children, className }: AppShellProps) {\n const isMobile = useIsMobile()\n const [drawerOpen, setDrawerOpen] = useState(false)\n\n return (\n <div className={cn('flex h-screen', className)}>\n {/* Desktop sidebar */}\n {!isMobile && <Sidebar {...sidebar} className={cn('w-44', sidebar.className)} />}\n\n {/* Mobile drawer */}\n {isMobile && (\n <MobileDrawer open={drawerOpen} onClose={() => setDrawerOpen(false)} width=\"w-64\">\n <Sidebar\n {...sidebar}\n onNavigate={() => setDrawerOpen(false)}\n className=\"w-full border-r-0\"\n />\n </MobileDrawer>\n )}\n\n <div className=\"flex flex-1 flex-col min-w-0\">\n {/* Mobile top bar */}\n {isMobile && (\n <header className=\"flex items-center h-12 border-b border-border px-3 shrink-0 bg-surface/80 backdrop-blur-sm\">\n <button\n onClick={() => setDrawerOpen(true)}\n className=\"p-1.5 -ml-1.5 rounded-md hover:bg-surface-hover text-foreground-muted transition-colors\"\n aria-label=\"Open menu\"\n >\n <Menu className=\"h-5 w-5\" />\n </button>\n {mobileLogo && <div className=\"flex-1 flex justify-center\">{mobileLogo}</div>}\n {mobileActions && <div className=\"shrink-0\">{mobileActions}</div>}\n </header>\n )}\n\n {/* Desktop breadcrumb header */}\n {!isMobile && header && (\n <header className=\"flex items-center h-10 border-b border-border px-4 shrink-0\">\n {header.breadcrumbs && header.breadcrumbs.length > 0 && (\n <nav className=\"flex items-center gap-1 text-xs flex-1 min-w-0\">\n {header.breadcrumbs.map((crumb, index) => {\n const isLast = index === header.breadcrumbs!.length - 1\n return (\n <span key={index} className=\"flex items-center gap-1\">\n {index > 0 && (\n <ChevronRight className=\"h-3 w-3 text-foreground-subtle shrink-0\" />\n )}\n {crumb.href && !isLast ? (\n <a\n href={crumb.href}\n className=\"text-foreground-subtle hover:text-foreground transition-colors truncate\"\n >\n {crumb.label}\n </a>\n ) : (\n <span className=\"text-foreground truncate\">{crumb.label}</span>\n )}\n </span>\n )\n })}\n </nav>\n )}\n {header.actions && (\n <div className=\"flex items-center gap-2 ml-auto shrink-0\">\n {header.actions}\n </div>\n )}\n </header>\n )}\n\n <main className=\"flex-1 overflow-auto p-4\">{children}</main>\n </div>\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport { useIsMobile } from '../../hooks/use-is-mobile'\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n flexRender,\n type ColumnDef,\n} from '@tanstack/react-table'\nimport { cn } from '../../lib/cn'\nimport { Skeleton } from '../../primitives/skeleton'\nimport { Checkbox } from '../../primitives/checkbox'\nimport { DataTableHeader } from './data-table-header'\nimport { DataTableRow } from './data-table-row'\nimport { DataTablePagination } from './data-table-pagination'\nimport type { DataTableProps } from './types'\n\nexport function DataTable<T>({\n data,\n columns: userColumns,\n sorting,\n onSortingChange,\n filtering,\n onFilteringChange,\n pagination,\n onPaginationChange,\n loading = false,\n emptyState,\n rowActions,\n onRowClick,\n selectable = false,\n compact = true,\n stickyHeader = false,\n className,\n mobileMode = 'scroll',\n}: DataTableProps<T>) {\n const columns = useMemo(() => {\n if (!selectable) return userColumns\n\n const selectColumn: ColumnDef<T, unknown> = {\n id: '__select',\n header: ({ table }) => (\n <Checkbox\n checked={table.getIsAllPageRowsSelected()}\n onChange={table.getToggleAllPageRowsSelectedHandler()}\n aria-label=\"Select all\"\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n checked={row.getIsSelected()}\n onChange={row.getToggleSelectedHandler()}\n aria-label=\"Select row\"\n />\n ),\n enableSorting: false,\n }\n\n return [selectColumn, ...userColumns]\n }, [userColumns, selectable])\n\n const table = useReactTable({\n data,\n columns,\n state: {\n ...(sorting !== undefined && { sorting }),\n ...(filtering !== undefined && { columnFilters: filtering }),\n ...(pagination !== undefined && {\n pagination: { pageIndex: pagination.page, pageSize: pagination.pageSize },\n }),\n },\n onSortingChange: onSortingChange\n ? (updater) => {\n const next = typeof updater === 'function' ? updater(sorting ?? []) : updater\n onSortingChange(next)\n }\n : undefined,\n onColumnFiltersChange: onFilteringChange\n ? (updater) => {\n const next = typeof updater === 'function' ? updater(filtering ?? []) : updater\n onFilteringChange(next)\n }\n : undefined,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getPaginationRowModel: pagination ? getPaginationRowModel() : undefined,\n manualPagination: pagination !== undefined,\n pageCount: pagination ? Math.ceil(pagination.total / pagination.pageSize) : undefined,\n })\n\n const hasActions = !!rowActions\n\n const isMobile = useIsMobile()\n const showCards = isMobile && mobileMode === 'cards'\n\n if (showCards) {\n const rows = table.getRowModel().rows\n\n if (loading) {\n return (\n <div className={cn('space-y-2', className)}>\n {Array.from({ length: 3 }).map((_, i) => (\n <div key={i} className=\"rounded-lg border border-border bg-surface p-3 space-y-2\">\n <Skeleton className=\"h-3 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n ))}\n </div>\n )\n }\n\n if (rows.length === 0) {\n return (\n <div className={cn('text-center py-8 text-xs text-foreground-muted', className)}>\n {emptyState ?? 'No data'}\n </div>\n )\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n {rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n 'rounded-lg border border-border bg-surface p-3 space-y-1.5',\n onRowClick && 'cursor-pointer hover:bg-surface-hover transition-colors'\n )}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells()\n .filter((cell) => cell.column.id !== '__select')\n .map((cell) => {\n const header = cell.column.columnDef.header\n const label = typeof header === 'string' ? header : cell.column.id\n return (\n <div key={cell.id} className=\"flex items-baseline justify-between gap-2 text-xs\">\n <span className=\"text-foreground-muted shrink-0\">{label}</span>\n <span className=\"text-foreground text-right truncate\">\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </span>\n </div>\n )\n })}\n {rowActions && (\n <div className=\"flex items-center gap-1 pt-1 border-t border-border mt-1.5\">\n {rowActions(row.original).map((action, i) => (\n <button\n key={i}\n onClick={(e) => { e.stopPropagation(); action.onClick() }}\n className={cn(\n 'text-[11px] px-2 py-1 rounded-md transition-colors',\n action.variant === 'danger'\n ? 'text-danger hover:bg-danger/10'\n : 'text-foreground-muted hover:bg-surface-hover'\n )}\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </div>\n ))}\n {pagination && (\n <DataTablePagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n total={pagination.total}\n onPaginationChange={onPaginationChange}\n />\n )}\n </div>\n )\n }\n\n return (\n <div className={cn('overflow-x-auto', className)}>\n <table className=\"w-full border-collapse\">\n <DataTableHeader\n headerGroups={table.getHeaderGroups()}\n onSortingChange={onSortingChange}\n stickyHeader={stickyHeader}\n flexRender={flexRender}\n />\n <tbody>\n {loading ? (\n <LoadingRows colSpan={columns.length + (hasActions ? 1 : 0)} compact={compact} />\n ) : table.getRowModel().rows.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length + (hasActions ? 1 : 0)}\n className=\"text-center py-8 text-xs text-foreground-muted\"\n >\n {emptyState ?? 'No data'}\n </td>\n </tr>\n ) : (\n table.getRowModel().rows.map((row) => (\n <DataTableRow\n key={row.id}\n row={row}\n onRowClick={onRowClick}\n rowActions={rowActions}\n flexRender={flexRender}\n />\n ))\n )}\n </tbody>\n </table>\n {pagination && (\n <DataTablePagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n total={pagination.total}\n onPaginationChange={onPaginationChange}\n />\n )}\n </div>\n )\n}\n\nfunction LoadingRows({ colSpan, compact }: { colSpan: number; compact: boolean }) {\n return (\n <>\n {Array.from({ length: 5 }).map((_, rowIdx) => (\n <tr key={rowIdx} className={compact ? 'h-7' : 'h-9'}>\n {Array.from({ length: colSpan }).map((_, colIdx) => (\n <td key={colIdx} className=\"px-2 py-1.5\">\n <Skeleton className=\"h-3 w-full\" />\n </td>\n ))}\n </tr>\n ))}\n </>\n )\n}\n","import type { HeaderGroup, Header, flexRender } from '@tanstack/react-table'\nimport { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport type { SortingState } from './types'\n\ninterface DataTableHeaderProps<T> {\n headerGroups: HeaderGroup<T>[]\n onSortingChange?: (sorting: SortingState) => void\n stickyHeader?: boolean\n flexRender: typeof flexRender\n}\n\nexport function DataTableHeader<T>({\n headerGroups,\n onSortingChange,\n stickyHeader,\n flexRender: render,\n}: DataTableHeaderProps<T>) {\n return (\n <thead\n className={cn(\n stickyHeader && 'sticky top-0 z-10 bg-background',\n )}\n >\n {headerGroups.map((headerGroup) => (\n <tr key={headerGroup.id} className=\"h-6\">\n {headerGroup.headers.map((header) => (\n <HeaderCell\n key={header.id}\n header={header}\n sortable={header.column.getCanSort() && !!onSortingChange}\n flexRender={render}\n />\n ))}\n </tr>\n ))}\n </thead>\n )\n}\n\ninterface HeaderCellProps<T> {\n header: Header<T, unknown>\n sortable: boolean\n flexRender: typeof flexRender\n}\n\nfunction HeaderCell<T>({ header, sortable, flexRender: render }: HeaderCellProps<T>) {\n const sorted = header.column.getIsSorted()\n\n const SortIcon = sorted === 'asc' ? ArrowUp : sorted === 'desc' ? ArrowDown : ArrowUpDown\n\n return (\n <th\n className={cn(\n 'px-2 py-1 text-left text-[10px] text-foreground-subtle uppercase tracking-wider font-medium',\n sortable && 'cursor-pointer select-none',\n )}\n onClick={sortable ? header.column.getToggleSortingHandler() : undefined}\n >\n <span className=\"inline-flex items-center gap-1\">\n {header.isPlaceholder\n ? null\n : render(header.column.columnDef.header, header.getContext())}\n {sortable && <SortIcon className=\"h-3 w-3\" />}\n </span>\n </th>\n )\n}\n","import type { Row, Cell, flexRender } from '@tanstack/react-table'\nimport { MoreHorizontal } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport { Dropdown, DropdownTrigger, DropdownContent, DropdownItem as DropdownMenuItem } from '../../primitives/dropdown'\nimport type { DataTableAction } from './types'\n\ninterface DataTableRowProps<T> {\n row: Row<T>\n onRowClick?: (row: T) => void\n rowActions?: (row: T) => DataTableAction[]\n flexRender: typeof flexRender\n}\n\nexport function DataTableRow<T>({\n row,\n onRowClick,\n rowActions,\n flexRender: render,\n}: DataTableRowProps<T>) {\n const actions = rowActions ? rowActions(row.original) : []\n\n return (\n <tr\n className={cn(\n 'h-7 border-b border-border/50',\n onRowClick && 'cursor-pointer',\n 'hover:bg-surface-hover',\n )}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells().map((cell) => (\n <DataTableCell key={cell.id} cell={cell} flexRender={render} />\n ))}\n {actions.length > 0 && (\n <td className=\"px-2 py-1.5 w-8\">\n <Dropdown>\n <DropdownTrigger\n className=\"p-0.5 rounded hover:bg-surface-hover\"\n onClick={(e) => e.stopPropagation()}\n >\n <MoreHorizontal className=\"h-3.5 w-3.5 text-foreground-muted\" />\n </DropdownTrigger>\n <DropdownContent className=\"right-0 left-auto\">\n {actions.map((action) => (\n <DropdownMenuItem\n key={action.label}\n icon={action.icon}\n variant={action.variant}\n onClick={(e) => {\n e.stopPropagation()\n action.onClick()\n }}\n >\n {action.label}\n </DropdownMenuItem>\n ))}\n </DropdownContent>\n </Dropdown>\n </td>\n )}\n </tr>\n )\n}\n\ninterface DataTableCellProps<T> {\n cell: Cell<T, unknown>\n flexRender: typeof flexRender\n}\n\nfunction DataTableCell<T>({ cell, flexRender: render }: DataTableCellProps<T>) {\n return (\n <td className=\"px-2 py-1.5 text-xs text-foreground\">\n {render(cell.column.columnDef.cell, cell.getContext())}\n </td>\n )\n}\n","import { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { IconButton } from '../../primitives/icon-button'\nimport { Select } from '../../primitives/select'\nimport type { PaginationState } from './types'\n\ninterface DataTablePaginationProps {\n page: number\n pageSize: number\n total: number\n onPaginationChange?: (pagination: PaginationState) => void\n}\n\nconst PAGE_SIZE_OPTIONS = [\n { value: '10', label: '10' },\n { value: '25', label: '25' },\n { value: '50', label: '50' },\n { value: '100', label: '100' },\n]\n\nexport function DataTablePagination({\n page,\n pageSize,\n total,\n onPaginationChange,\n}: DataTablePaginationProps) {\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n const currentPage = page + 1\n\n return (\n <div className=\"flex items-center justify-between px-2 py-2 text-xs text-foreground-muted\">\n <div className=\"flex items-center gap-2\">\n <span>Rows per page</span>\n <div className=\"w-16\">\n <Select\n options={PAGE_SIZE_OPTIONS}\n value={String(pageSize)}\n onChange={(e) =>\n onPaginationChange?.({\n pageIndex: 0,\n pageSize: Number(e.target.value),\n })\n }\n />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <span>\n Page {currentPage} of {totalPages}\n </span>\n <IconButton\n icon={ChevronLeft}\n aria-label=\"Previous page\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={page <= 0}\n onClick={() =>\n onPaginationChange?.({ pageIndex: page - 1, pageSize })\n }\n />\n <IconButton\n icon={ChevronRight}\n aria-label=\"Next page\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={currentPage >= totalPages}\n onClick={() =>\n onPaginationChange?.({ pageIndex: page + 1, pageSize })\n }\n />\n </div>\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface DeviceCardBadge {\n /** Badge label text */\n label: string\n /** Optional icon rendered before the label */\n icon?: ReactNode\n /** Click handler — makes the badge interactive */\n onClick?: () => void\n}\n\nexport interface DeviceCardAction {\n /** Icon to render */\n icon: ReactNode\n /** Tooltip / aria-label */\n label: string\n /** Click handler */\n onClick: () => void\n}\n\nexport interface DeviceCardProps {\n /** Primary title (e.g., device name) */\n title: string\n /** Secondary text (e.g., model, IP) */\n subtitle?: string\n /** Status: determines the color of the status dot */\n status?: 'online' | 'offline' | 'warning' | 'unknown'\n /** Whether this card is currently selected */\n selected?: boolean\n /** Click handler for the card body */\n onClick?: () => void\n /** Clickable badges (e.g., stream profiles) */\n badges?: DeviceCardBadge[]\n /** Action icons shown at the bottom (e.g., PTZ, events) */\n actions?: DeviceCardAction[]\n /** Content rendered at the bottom when status is offline (e.g., Connect button) */\n offlineAction?: ReactNode\n /** Additional CSS classes */\n className?: string\n}\n\nconst STATUS_COLORS = {\n online: 'bg-success',\n offline: 'bg-danger',\n warning: 'bg-warning',\n unknown: 'bg-foreground-subtle',\n} as const\n\nexport function DeviceCard({\n title,\n subtitle,\n status,\n selected,\n onClick,\n badges,\n actions,\n offlineAction,\n className,\n}: DeviceCardProps) {\n const isOffline = status === 'offline'\n\n return (\n <div\n onClick={onClick}\n className={cn(\n 'w-full rounded-lg border p-3 text-left transition-colors',\n onClick && 'cursor-pointer',\n selected\n ? 'border-primary bg-primary/10'\n : 'border-border bg-surface hover:bg-surface-hover',\n isOffline && !selected && 'opacity-50',\n className,\n )}\n >\n {/* Header: title + status dot */}\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium truncate\">{title}</span>\n {status && (\n <span className={cn('h-2 w-2 rounded-full shrink-0', STATUS_COLORS[status])} />\n )}\n </div>\n\n {/* Subtitle */}\n {subtitle && (\n <div className=\"text-[11px] text-foreground-muted\">{subtitle}</div>\n )}\n\n {/* Badges */}\n {badges && badges.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mt-2\">\n {badges.map((badge, i) => {\n const cls = cn(\n 'rounded px-1.5 py-0.5 text-[10px] flex items-center gap-0.5',\n selected ? 'bg-primary/20' : 'bg-surface-hover',\n badge.onClick && 'hover:opacity-80 transition-opacity cursor-pointer',\n )\n return badge.onClick ? (\n <button\n key={i}\n onClick={(e) => { e.stopPropagation(); badge.onClick!(); }}\n className={cls}\n >\n {badge.icon}{badge.label}\n </button>\n ) : (\n <span key={i} className={cls}>\n {badge.icon}{badge.label}\n </span>\n )\n })}\n </div>\n )}\n\n {/* Actions (online) or offline action */}\n {!isOffline && actions && actions.length > 0 && (\n <div className=\"flex items-center gap-0.5 mt-2 -mb-1\">\n {actions.map((action, i) => (\n <button\n key={i}\n onClick={(e) => { e.stopPropagation(); action.onClick(); }}\n className=\"p-1 rounded hover:bg-surface-hover text-foreground-subtle hover:text-foreground transition-colors\"\n title={action.label}\n aria-label={action.label}\n >\n {action.icon}\n </button>\n ))}\n </div>\n )}\n\n {isOffline && offlineAction && (\n <div className=\"mt-2\" onClick={(e) => e.stopPropagation()}>\n {offlineAction}\n </div>\n )}\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface DeviceGridProps {\n /** Grid items */\n children: ReactNode\n /** Minimum card width in pixels (default 220) */\n minCardWidth?: number\n /** Gap between cards in Tailwind spacing units (default 3) */\n gap?: number\n /** Additional CSS classes */\n className?: string\n}\n\nexport function DeviceGrid({\n children,\n minCardWidth = 220,\n gap = 3,\n className,\n}: DeviceGridProps) {\n return (\n <div\n className={cn(\n 'p-4 overflow-y-auto flex-1 content-start',\n className,\n )}\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(auto-fill, minmax(${minCardWidth}px, 1fr))`,\n gap: `${gap * 4}px`,\n }}\n >\n {children}\n </div>\n )\n}\n","/**\n * PipelineStep — single step card in the pipeline builder.\n *\n * Driven entirely by PipelineAddonSchema. No hardcoded addon names or models.\n * Renders: colored left border, header with I/O class tags, expandable config\n * (Agent → Runtime → Backend → Model → Confidence), children recursively.\n */\nimport { useState } from 'react'\nimport { ChevronRight, ChevronDown } from 'lucide-react'\nimport type { PipelineSlot, PipelineAddonSchema, InferenceCapabilities, PipelineModelOption } from '@camstack/types'\nimport { cn } from '../lib/cn'\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\nexport interface PipelineStepDisplayConfig {\n readonly addonId: string\n readonly addonName: string\n readonly slot: PipelineSlot\n readonly inputClasses: readonly string[]\n readonly outputClasses: readonly string[]\n readonly enabled: boolean\n readonly agentId: string\n readonly runtime: string\n readonly backend: string\n readonly modelId: string\n readonly confidence: number\n readonly classFilters: readonly string[]\n readonly children: readonly PipelineStepDisplayConfig[]\n}\n\nexport interface PipelineStepProps {\n readonly step: PipelineStepDisplayConfig\n readonly schema: PipelineAddonSchema | null\n /** Full schema map so children can look up their own schema */\n readonly allSchemas: ReadonlyMap<string, PipelineAddonSchema>\n readonly capabilities: InferenceCapabilities\n readonly depth?: number\n readonly onChange: (updated: PipelineStepDisplayConfig) => void\n readonly onDelete?: (addonId: string) => void\n readonly readOnly?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Border colors — per addon ID with fallback by slot\n// ---------------------------------------------------------------------------\n\nconst ADDON_COLORS: Record<string, string> = {\n 'object-detection': 'border-l-blue-500',\n 'motion-detection': 'border-l-amber-500',\n 'face-detection': 'border-l-purple-500',\n 'face-recognition': 'border-l-violet-500',\n 'plate-detection': 'border-l-pink-500',\n 'plate-recognition': 'border-l-rose-500',\n 'animal-classifier': 'border-l-lime-500',\n 'bird-nabirds-classifier': 'border-l-emerald-500',\n 'bird-global-classifier': 'border-l-teal-500',\n 'audio-classification': 'border-l-green-500',\n 'segmentation-refiner': 'border-l-cyan-500',\n}\n\nconst SLOT_FALLBACK: Record<string, string> = {\n detector: 'border-l-blue-500',\n cropper: 'border-l-purple-500',\n classifier: 'border-l-lime-500',\n refiner: 'border-l-cyan-500',\n}\n\nfunction borderColor(addonId: string, slot: string): string {\n return ADDON_COLORS[addonId] ?? SLOT_FALLBACK[slot] ?? 'border-l-primary'\n}\n\n// ---------------------------------------------------------------------------\n// Helpers — compute available backends + models for a specific step\n// ---------------------------------------------------------------------------\n\n/** Map backend id → required model format */\nconst BACKEND_FORMAT: Record<string, string> = {\n cpu: 'onnx', coreml: 'coreml', openvino: 'openvino',\n cuda: 'onnx', tensorrt: 'onnx', 'onnx-py': 'onnx', pytorch: 'pt',\n}\n\nfunction backendsForRuntime(\n runtime: string,\n caps: InferenceCapabilities,\n schema: PipelineAddonSchema | null,\n): readonly { id: string; label: string; available: boolean }[] {\n const allBackends = runtime === 'node' ? caps.runtimes.node.backends : caps.runtimes.python.backends\n if (!schema) return allBackends\n\n // Filter: only show backends for which at least one model has the required format\n const availableFormats = new Set<string>()\n for (const m of schema.models) {\n for (const fmt of Object.keys(m.formats as Record<string, unknown>)) {\n availableFormats.add(fmt)\n }\n }\n // Node.js always uses ONNX\n if (runtime === 'node') availableFormats.add('onnx')\n\n return allBackends.map(b => {\n const neededFormat = BACKEND_FORMAT[b.id] ?? 'onnx'\n const hasFormat = availableFormats.has(neededFormat)\n return { ...b, available: b.available && hasFormat }\n })\n}\n\nfunction modelsForStep(\n schema: PipelineAddonSchema | null,\n runtime: string,\n backend: string,\n caps: InferenceCapabilities,\n): readonly { id: string; name: string; downloaded: boolean }[] {\n if (!schema) return []\n const fmt = runtime === 'node'\n ? 'onnx'\n : ((caps.runtimes.python.backends.find(b => b.id === backend) as any)?.modelFormat ?? 'onnx')\n return schema.models\n .filter(m => (m.formats as Record<string, unknown>)[fmt])\n .map(m => ({\n id: m.id,\n name: m.name,\n downloaded: ((m.formats as Record<string, { downloaded?: boolean }>)[fmt])?.downloaded ?? false,\n }))\n}\n\nfunction runtimeOptions(caps: InferenceCapabilities): readonly { id: string; label: string; available: boolean }[] {\n const opts: { id: string; label: string; available: boolean }[] = [\n { id: 'node', label: 'Node.js (ONNX)', available: true },\n ]\n if (caps.runtimes.python.available && caps.runtimes.python.backends.some(b => b.available)) {\n opts.unshift({ id: 'python', label: 'Python', available: true })\n }\n return opts\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function PipelineStep({\n step,\n schema,\n allSchemas,\n capabilities,\n depth = 0,\n onChange,\n onDelete,\n readOnly = false,\n}: PipelineStepProps) {\n const [expanded, setExpanded] = useState(false)\n\n const color = borderColor(step.addonId, step.slot)\n const backends = backendsForRuntime(step.runtime, capabilities, schema)\n const rtOptions = runtimeOptions(capabilities)\n\n // Auto-correct: if the selected backend is not available, switch to the first available one\n const currentBackendAvailable = backends.find(b => b.id === step.backend)?.available ?? false\n if (!currentBackendAvailable && !readOnly) {\n const firstAvailable = backends.find(b => b.available)\n if (firstAvailable && firstAvailable.id !== step.backend) {\n // Defer the update to avoid render-during-render\n queueMicrotask(() => onChange({ ...step, backend: firstAvailable.id }))\n }\n }\n\n const models = modelsForStep(schema, step.runtime, step.backend, capabilities)\n\n // Auto-correct: if the selected model is not in the filtered list, switch to default or first\n if (models.length > 0 && !models.some(m => m.id === step.modelId) && !readOnly) {\n const defaultModel = schema?.defaultModelId ? models.find(m => m.id === schema.defaultModelId) : null\n const fallback = defaultModel ?? models[0]\n if (fallback && fallback.id !== step.modelId) {\n queueMicrotask(() => onChange({ ...step, modelId: fallback.id }))\n }\n }\n\n function handleClick(e: React.MouseEvent) {\n // Don't toggle when clicking inside config panel\n if ((e.target as HTMLElement).closest('.step-config')) return\n setExpanded(v => !v)\n }\n\n return (\n <div className=\"space-y-2\">\n {/* ── Step card ─────────────────────────────────────────── */}\n <div\n className={cn(\n 'rounded-xl border border-border bg-surface overflow-hidden border-l-4 shadow-sm',\n color,\n !step.enabled && 'opacity-[0.45]',\n )}\n >\n {/* Header */}\n <div className=\"flex items-center gap-2.5 px-3 py-2.5 cursor-pointer select-none\" onClick={handleClick}>\n <span className=\"text-foreground-subtle\">\n {expanded ? <ChevronDown className=\"h-4 w-4\" /> : <ChevronRight className=\"h-4 w-4\" />}\n </span>\n\n {/* Slot type (small header) + Name (prominent) + class tags */}\n <div className=\"flex-1 min-w-0\">\n <span className=\"text-[10px] uppercase tracking-wider font-medium text-foreground-subtle/60 block leading-none\">{step.slot}</span>\n <span className=\"text-sm font-semibold text-foreground truncate block leading-tight\">{step.addonName}</span>\n <div className=\"flex items-center gap-1 mt-0.5 flex-wrap\">\n {step.inputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/12 text-blue-400\">{c}</span>\n ))}\n {step.inputClasses.length > 0 && step.outputClasses.length > 0 && (\n <span className=\"text-foreground-subtle/40 text-[10px]\">→</span>\n )}\n {step.outputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/12 text-green-400\">{c}</span>\n ))}\n </div>\n </div>\n\n {/* Toggle */}\n <button\n onClick={e => { e.stopPropagation(); onChange({ ...step, enabled: !step.enabled }) }}\n className={cn(\n 'relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors',\n step.enabled ? 'bg-success' : 'bg-foreground-subtle/30',\n )}\n >\n <span className={cn(\n 'inline-block h-4 w-4 rounded-full bg-white shadow transition-transform',\n step.enabled ? 'translate-x-6' : 'translate-x-1',\n )} />\n </button>\n\n {/* Delete button removed — toggle switch is sufficient */}\n </div>\n\n {/* ── Expanded config ──────────────────────────────────── */}\n {expanded && (\n <div className=\"step-config border-t border-border bg-background px-4 py-4 space-y-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <ConfigSelect label=\"Agent\" value={step.agentId} disabled={readOnly}\n options={[{ value: step.agentId || 'hub', label: step.agentId || 'Hub (local)' }]}\n onChange={v => onChange({ ...step, agentId: v })} />\n <ConfigSelect label=\"Runtime\" value={step.runtime} disabled={readOnly}\n options={rtOptions.map(r => ({ value: r.id, label: r.label, disabled: !r.available }))}\n onChange={v => onChange({ ...step, runtime: v })} />\n <ConfigSelect label=\"Backend\" value={step.backend} disabled={readOnly}\n options={backends.map(b => ({ value: b.id, label: b.label, disabled: !b.available }))}\n onChange={v => onChange({ ...step, backend: v })} />\n <ConfigSelect label=\"Model\" value={step.modelId} disabled={readOnly}\n options={models.map(m => ({ value: m.id, label: `${m.name}${m.downloaded ? ' ✓' : ''}` }))}\n onChange={v => onChange({ ...step, modelId: v })} />\n </div>\n <div>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-[10px] font-medium text-foreground-subtle uppercase tracking-wide\">Confidence</span>\n <span className=\"text-xs font-medium text-foreground tabular-nums\">{(step.confidence * 100).toFixed(0)}%</span>\n </div>\n <input type=\"range\" min={0} max={1} step={0.01} value={step.confidence} disabled={readOnly}\n onChange={e => onChange({ ...step, confidence: Number(e.target.value) })}\n className=\"w-full accent-primary h-1.5\" />\n </div>\n </div>\n )}\n </div>\n\n {/* Children are rendered by PipelineBuilder (it manages placeholders + nesting) */}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Small config select — reusable for Agent/Runtime/Backend/Model\n// ---------------------------------------------------------------------------\n\nfunction ConfigSelect({ label, value, options, disabled, onChange }: {\n label: string\n value: string\n options: readonly { value: string; label: string; disabled?: boolean }[]\n disabled?: boolean\n onChange: (value: string) => void\n}) {\n return (\n <div>\n <label className=\"block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1.5\">\n {label}\n </label>\n <select\n value={value}\n onChange={e => onChange(e.target.value)}\n disabled={disabled}\n className=\"w-full rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground focus:outline-none focus:border-primary/50\"\n >\n {options.length === 0 && <option value={value}>{value || 'default'}</option>}\n {options.map(o => (\n <option key={o.value} value={o.value} disabled={o.disabled}>{o.label}</option>\n ))}\n </select>\n </div>\n )\n}\n","import { Cpu, Star } from 'lucide-react'\n\nexport interface PipelineRuntimeOption {\n readonly id: string\n readonly label: string\n readonly available: boolean\n /** Platform score for this backend (higher = better) */\n readonly platformScore?: number\n /** Whether this is the best-scored backend */\n readonly isBest?: boolean\n}\n\ninterface PipelineRuntimeSelectorProps {\n readonly options: readonly PipelineRuntimeOption[]\n readonly value: string\n readonly onChange: (value: string) => void\n}\n\nexport function PipelineRuntimeSelector({ options, value, onChange }: PipelineRuntimeSelectorProps) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {options.map((opt) => {\n const active = opt.id === value\n return (\n <button\n key={opt.id}\n onClick={() => opt.available && onChange(opt.id)}\n disabled={!opt.available}\n className={`flex items-center gap-2 rounded-lg border px-3 py-2 text-xs font-medium transition-all ${\n active\n ? 'border-primary/40 bg-primary/10 text-primary'\n : opt.available\n ? 'border-border bg-surface text-foreground-subtle hover:bg-surface-hover hover:text-foreground'\n : 'border-border/40 bg-surface/40 text-foreground-subtle/40 cursor-not-allowed'\n }`}\n >\n <Cpu className=\"h-3.5 w-3.5 shrink-0\" />\n {opt.label}\n {opt.isBest && (\n <span className=\"inline-flex items-center gap-0.5 rounded-full bg-amber-500/15 px-1.5 py-0.5 text-[10px] font-semibold text-amber-400\">\n <Star className=\"h-2.5 w-2.5\" />\n Best\n </span>\n )}\n {opt.platformScore != null && (\n <span className=\"text-[10px] text-foreground-subtle/60\">({opt.platformScore})</span>\n )}\n <span\n className={`h-1.5 w-1.5 rounded-full ${\n opt.available ? 'bg-success' : 'bg-danger'\n }`}\n />\n </button>\n )\n })}\n </div>\n )\n}\n","/**\n * PipelineBuilder — orchestrates the pipeline step tree with template management.\n *\n * Renders: template bar (save/load/delete), step tree from schema with nested\n * children, placeholder steps for disabled addons, all driven by API schema.\n */\nimport { useMemo, useState } from 'react'\nimport { Save, CopyPlus, Trash2, PlusCircle, X } from 'lucide-react'\nimport type {\n PipelineSchema,\n PipelineTemplate,\n InferenceCapabilities,\n PipelineAddonSchema,\n} from '@camstack/types'\nimport { cn } from '../lib/cn'\nimport { validateTemplate } from '../lib/validate-template'\nimport { PipelineStep } from './pipeline-step'\nimport type { PipelineStepDisplayConfig } from './pipeline-step'\n\n// ---------------------------------------------------------------------------\n// Public interface\n// ---------------------------------------------------------------------------\n\nexport interface PipelineBuilderProps {\n readonly schema: PipelineSchema\n readonly capabilities: InferenceCapabilities\n readonly steps: readonly PipelineStepDisplayConfig[]\n readonly onChange: (steps: readonly PipelineStepDisplayConfig[]) => void\n readonly templates: readonly PipelineTemplate[]\n readonly selectedTemplateId: string | null\n readonly onSelectTemplate: (id: string | null) => void\n readonly onSaveTemplate: (name: string, steps: readonly PipelineStepDisplayConfig[]) => void\n readonly onUpdateTemplate: (id: string, steps: readonly PipelineStepDisplayConfig[]) => void\n readonly onDeleteTemplate: (id: string) => void\n readonly readOnly?: boolean\n /** Addon IDs to exclude from the pipeline (e.g. 'motion-detection' for benchmark) */\n readonly excludeAddons?: readonly string[]\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildSchemaMap(schema: PipelineSchema): Map<string, PipelineAddonSchema> {\n const map = new Map<string, PipelineAddonSchema>()\n for (const slot of schema.slots) {\n for (const addon of slot.addons) {\n map.set(addon.id, addon)\n }\n }\n return map\n}\n\nfunction createDefaultStep(\n addon: PipelineAddonSchema,\n fallbackRuntime?: string,\n fallbackBackend?: string,\n): PipelineStepDisplayConfig {\n return {\n addonId: addon.id,\n addonName: addon.name,\n slot: addon.slot,\n inputClasses: [...addon.inputClasses],\n outputClasses: [...addon.outputClasses],\n enabled: true,\n agentId: 'hub',\n // Use per-addon defaults from backend PlatformScorer, fallback to provided\n runtime: (addon as any).defaultRuntime ?? fallbackRuntime ?? 'node',\n backend: (addon as any).defaultBackend ?? fallbackBackend ?? 'cpu',\n modelId: addon.defaultModelId,\n confidence: addon.defaultConfidence,\n classFilters: [...addon.inputClasses],\n children: [],\n }\n}\n\n// ---------------------------------------------------------------------------\n// Placeholder step — dashed card with plus icon, class I/O tags\n// ---------------------------------------------------------------------------\n\nfunction PlaceholderStep({ addon, onClick }: {\n addon: PipelineAddonSchema\n onClick: () => void\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"w-full rounded-xl border-2 border-dashed border-border/60 px-4 py-3 text-left transition-all hover:border-primary/30 hover:bg-surface/60 group\"\n >\n <div className=\"flex items-center gap-3\">\n <PlusCircle className=\"h-[18px] w-[18px] text-foreground-subtle/30 group-hover:text-primary/60 shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <span className=\"text-[13px] font-medium text-foreground-subtle/50 group-hover:text-foreground-subtle block truncate\">\n {addon.name}\n </span>\n <div className=\"flex items-center gap-1 mt-0.5 flex-wrap\">\n {addon.inputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/8 text-blue-400/50\">{c}</span>\n ))}\n {addon.inputClasses.length > 0 && addon.outputClasses.length > 0 && (\n <span className=\"text-foreground-subtle/25 text-[10px]\">→</span>\n )}\n {addon.outputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/8 text-green-400/50\">{c}</span>\n ))}\n </div>\n </div>\n </div>\n </button>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nexport function PipelineBuilder({\n schema,\n capabilities,\n steps,\n onChange,\n templates,\n selectedTemplateId,\n onSelectTemplate,\n onSaveTemplate,\n onUpdateTemplate,\n onDeleteTemplate,\n readOnly = false,\n excludeAddons = [],\n}: PipelineBuilderProps) {\n const excluded = useMemo(() => new Set(excludeAddons), [excludeAddons])\n const schemaMap = useMemo(() => buildSchemaMap(schema), [schema])\n const [warnings, setWarnings] = useState<string[]>([])\n\n // Determine default runtime/backend for new steps — prefer platform scores\n const bestPlatformScore = capabilities.platformScores?.find(s => s.available)\n const hasPython = capabilities.runtimes.python.available &&\n capabilities.runtimes.python.backends.some(b => b.available)\n const defaultRuntime = bestPlatformScore?.runtime\n ?? (hasPython ? 'python' : 'node')\n const defaultBackend = bestPlatformScore?.backend\n ?? (hasPython\n ? (capabilities.runtimes.python.backends.find(b => b.available)?.id ?? 'cpu')\n : (capabilities.runtimes.node.backends.find(b => b.available && b.id !== 'cpu')?.id ?? 'cpu'))\n\n // Check unsaved changes\n const dirty = selectedTemplateId\n ? JSON.stringify(steps) !== JSON.stringify(templates.find(t => t.id === selectedTemplateId)?.steps)\n : false\n\n // ── Template handlers ──────────────────────────────────────────\n function handleSelectTemplate(e: React.ChangeEvent<HTMLSelectElement>) {\n const id = e.target.value || null\n if (id) {\n const tpl = templates.find(t => t.id === id)\n if (tpl) {\n const result = validateTemplate(tpl.steps, schema)\n setWarnings([...result.warnings])\n }\n } else {\n setWarnings([])\n }\n onSelectTemplate(id)\n }\n\n function handleSave() {\n if (selectedTemplateId) onUpdateTemplate(selectedTemplateId, steps)\n }\n\n function handleSaveAs() {\n const name = window.prompt('Template name:')\n if (name?.trim()) onSaveTemplate(name.trim(), steps)\n }\n\n function handleDelete() {\n if (!selectedTemplateId) return\n const tpl = templates.find(t => t.id === selectedTemplateId)\n if (tpl && window.confirm(`Delete template \"${tpl.name}\"?`)) {\n onDeleteTemplate(selectedTemplateId)\n }\n }\n\n // ── Step handlers ──────────────────────────────────────────────\n\n /**\n * When a step is updated, auto-enable the entire ancestor chain if a\n * child/grandchild was just enabled. This ensures enabling face-recognition\n * automatically enables face-detection and object-detection.\n */\n function handleStepChange(updated: PipelineStepDisplayConfig) {\n onChange(steps.map(s => {\n if (s.addonId !== updated.addonId) return s\n return autoEnableAncestors(updated)\n }))\n }\n\n /** If any child or grandchild is enabled, ensure the parent is too */\n function autoEnableAncestors(step: PipelineStepDisplayConfig): PipelineStepDisplayConfig {\n const hasEnabledChild = step.children.some(c => c.enabled || c.children.some(gc => gc.enabled))\n return {\n ...step,\n enabled: step.enabled || hasEnabledChild,\n children: step.children.map(c => {\n const hasEnabledGrandchild = c.children.some(gc => gc.enabled)\n return {\n ...c,\n enabled: c.enabled || hasEnabledGrandchild,\n }\n }),\n }\n }\n\n function handleAddChildToStep(parentAddonId: string, addon: PipelineAddonSchema) {\n const child = createDefaultStep(addon, defaultRuntime, defaultBackend)\n onChange(steps.map(s => {\n if (s.addonId !== parentAddonId) return s\n return { ...s, children: [...s.children, child] }\n }))\n }\n\n // ── Rendering ──────────────────────────────────────────────────\n\n // Collect all addon IDs already in the tree (including nested)\n function collectIds(list: readonly PipelineStepDisplayConfig[]): Set<string> {\n const ids = new Set<string>()\n for (const s of list) {\n ids.add(s.addonId)\n for (const c of s.children) ids.add(c.addonId)\n // Recurse deeper\n const childIds = collectIds(s.children)\n for (const id of childIds) ids.add(id)\n }\n return ids\n }\n\n const existingIds = collectIds(steps)\n\n // Get child-slot addons that could be children of a given step\n function getChildPlaceholders(step: PipelineStepDisplayConfig): PipelineAddonSchema[] {\n const stepSchema = schemaMap.get(step.addonId)\n if (!stepSchema) return []\n const childSlotIds = stepSchema.childSlots\n const childIds = new Set(step.children.map(c => c.addonId))\n const placeholders: PipelineAddonSchema[] = []\n for (const slot of schema.slots) {\n if (!childSlotIds.includes(slot.id)) continue\n for (const addon of slot.addons) {\n if (childIds.has(addon.id) || excluded.has(addon.id)) continue\n // Check class compatibility: addon's input must overlap with step's output\n const compatible = addon.inputClasses.some(ic => step.outputClasses.includes(ic))\n if (compatible) placeholders.push(addon)\n }\n }\n return placeholders\n }\n\n function renderStep(step: PipelineStepDisplayConfig) {\n const childPlaceholders = getChildPlaceholders(step)\n\n return (\n <div key={step.addonId} className=\"space-y-1.5\">\n <PipelineStep\n step={step}\n schema={schemaMap.get(step.addonId) ?? null}\n allSchemas={schemaMap}\n capabilities={capabilities}\n onChange={handleStepChange}\n onDelete={readOnly ? undefined : (id) => onChange(steps.filter(s => s.addonId !== id))}\n readOnly={readOnly}\n />\n\n {/* Children + child placeholders — nested visually */}\n {(step.children.length > 0 || childPlaceholders.length > 0) && (\n <div className=\"ml-6 pl-4 border-l-2 border-dashed border-border/40 space-y-1.5\">\n {/* Slot label for children */}\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/40\">\n Slot: Cropper / Classifier\n </span>\n\n {/* Existing child steps */}\n {step.children.map(child => {\n const childChildPlaceholders = getChildPlaceholders(child)\n return (\n <div key={child.addonId} className=\"space-y-1.5\">\n <PipelineStep\n step={child}\n schema={schemaMap.get(child.addonId) ?? null}\n allSchemas={schemaMap}\n capabilities={capabilities}\n depth={1}\n onChange={updated => {\n handleStepChange({\n ...step,\n children: step.children.map(c => c.addonId === updated.addonId ? updated : c),\n })\n }}\n onDelete={readOnly ? undefined : (id) => {\n handleStepChange({\n ...step,\n children: step.children.filter(c => c.addonId !== id),\n })\n }}\n readOnly={readOnly}\n />\n\n {/* Sub-sub children (recognizers) + placeholders */}\n {(child.children.length > 0 || childChildPlaceholders.length > 0) && (\n <div className=\"ml-6 pl-4 border-l-2 border-dashed border-border/30 space-y-1.5\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/30\">\n Slot: Recognizer\n </span>\n\n {/* Existing recognizer steps */}\n {child.children.map(grandchild => (\n <PipelineStep\n key={grandchild.addonId}\n step={grandchild}\n schema={schemaMap.get(grandchild.addonId) ?? null}\n allSchemas={schemaMap}\n capabilities={capabilities}\n depth={2}\n onChange={updatedGrandchild => {\n handleStepChange({\n ...step,\n children: step.children.map(c =>\n c.addonId === child.addonId\n ? { ...c, children: c.children.map(gc => gc.addonId === updatedGrandchild.addonId ? updatedGrandchild : gc) }\n : c\n ),\n })\n }}\n onDelete={readOnly ? undefined : (id) => {\n handleStepChange({\n ...step,\n children: step.children.map(c =>\n c.addonId === child.addonId\n ? { ...c, children: c.children.filter(gc => gc.addonId !== id) }\n : c\n ),\n })\n }}\n readOnly={readOnly}\n />\n ))}\n\n {/* Placeholder recognizers */}\n {!readOnly && childChildPlaceholders.map(addon => (\n <PlaceholderStep\n key={addon.id}\n addon={addon}\n onClick={() => {\n const newChild = createDefaultStep(addon, defaultRuntime, defaultBackend)\n handleStepChange({\n ...step,\n children: step.children.map(c =>\n c.addonId === child.addonId\n ? { ...c, children: [...c.children, newChild] }\n : c\n ),\n })\n }}\n />\n ))}\n </div>\n )}\n </div>\n )\n })}\n\n {/* Placeholders for missing child addons */}\n {!readOnly && childPlaceholders.map(addon => (\n <PlaceholderStep\n key={addon.id}\n addon={addon}\n onClick={() => handleAddChildToStep(step.addonId, addon)}\n />\n ))}\n </div>\n )}\n </div>\n )\n }\n\n // Root slots (detectors)\n const rootSlots = schema.slots.filter(s => s.parentSlot === null).sort((a, b) => a.priority - b.priority)\n\n return (\n <div className=\"space-y-4\">\n {/* ── Template bar ────────────────────────────────────────── */}\n <div className=\"rounded-xl border border-border bg-surface p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"relative flex-1 min-w-0\">\n <select\n value={selectedTemplateId ?? ''}\n onChange={handleSelectTemplate}\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary/50\"\n >\n <option value=\"\">No template</option>\n {templates.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}\n </select>\n </div>\n {dirty && <span className=\"h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0\" />}\n <button onClick={handleSave} disabled={!selectedTemplateId || readOnly} title=\"Save\"\n className={cn('p-2 rounded-lg border border-border transition-colors',\n selectedTemplateId && !readOnly ? 'text-foreground-subtle hover:bg-surface-hover' : 'text-foreground-subtle/30 cursor-not-allowed')}>\n <Save className=\"h-4 w-4\" />\n </button>\n <button onClick={handleSaveAs} disabled={readOnly} title=\"Save As\"\n className={cn('p-2 rounded-lg border border-border transition-colors',\n !readOnly ? 'text-foreground-subtle hover:bg-surface-hover' : 'text-foreground-subtle/30 cursor-not-allowed')}>\n <CopyPlus className=\"h-4 w-4\" />\n </button>\n <button onClick={handleDelete} disabled={!selectedTemplateId || readOnly} title=\"Delete\"\n className={cn('p-2 rounded-lg border border-border transition-colors',\n selectedTemplateId && !readOnly ? 'text-foreground-subtle hover:text-danger' : 'text-foreground-subtle/30 cursor-not-allowed')}>\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n {/* ── Warnings ────────────────────────────────────────────── */}\n {warnings.length > 0 && (\n <div className=\"rounded-lg border border-amber-500/30 bg-amber-500/5 p-3 text-xs text-amber-400 space-y-1\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-medium\">Template loaded with warnings:</span>\n <button onClick={() => setWarnings([])} className=\"text-amber-400/60 hover:text-amber-400\"><X className=\"h-3.5 w-3.5\" /></button>\n </div>\n {warnings.map((w, i) => <div key={i}>• {w}</div>)}\n </div>\n )}\n\n {/* ── Step tree ───────────────────────────────────────────── */}\n {rootSlots.map(slot => {\n const slotSteps = steps.filter(s => s.slot === slot.id && !excluded.has(s.addonId))\n const missingRootAddons = slot.addons.filter(a => !existingIds.has(a.id) && !excluded.has(a.id))\n\n return (\n <div key={slot.id} className=\"space-y-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/50\">\n Slot: {slot.label}\n </span>\n\n {slotSteps.map(step => renderStep(step))}\n\n {/* Root placeholders (e.g. add another detector) */}\n {!readOnly && missingRootAddons.map(addon => (\n <PlaceholderStep key={addon.id} addon={addon} onClick={() => {\n onChange([...steps, createDefaultStep(addon, defaultRuntime, defaultBackend)])\n }} />\n ))}\n </div>\n )\n })}\n </div>\n )\n}\n","// packages/ui-library/src/lib/validate-template.ts\nimport type { PipelineSchema, PipelineTemplateStep, TemplateValidationResult } from '@camstack/types'\n\nexport function validateTemplate(\n steps: readonly PipelineTemplateStep[],\n schema: PipelineSchema,\n): TemplateValidationResult {\n const availableAddonIds = new Set(\n schema.slots.flatMap(s => s.addons.map(a => a.id))\n )\n const warnings: string[] = []\n\n function validateStep(step: PipelineTemplateStep): PipelineTemplateStep | null {\n if (!availableAddonIds.has(step.addonId)) {\n warnings.push(`Addon \"${step.addonId}\" is no longer available — step removed`)\n return null\n }\n const addon = schema.slots\n .flatMap(s => s.addons)\n .find(a => a.id === step.addonId)\n\n let modelId = step.modelId\n if (addon && !addon.models.some(m => m.id === modelId)) {\n const fallback = addon.defaultModelId\n warnings.push(`Model \"${modelId}\" not available for ${step.addonId} — using \"${fallback}\"`)\n modelId = fallback\n }\n\n const validChildren = step.children\n .map(c => validateStep(c))\n .filter((c): c is PipelineTemplateStep => c !== null)\n\n return { ...step, modelId, children: validChildren }\n }\n\n const validSteps = steps\n .map(s => validateStep(s))\n .filter((s): s is PipelineTemplateStep => s !== null)\n\n return {\n valid: warnings.length === 0,\n steps: validSteps,\n warnings,\n }\n}\n","/**\n * Detection class colors — single source of truth.\n *\n * Used by: DetectionCanvas (UI), result-annotator (server-side SVG),\n * admin-ui event viewer, and any other place that visualizes detections.\n */\n\n/** Fixed colors for known detection classes */\nexport const CLASS_COLORS: Readonly<Record<string, string>> = {\n // Primary detection classes\n person: '#3b82f6', // blue-500\n vehicle: '#f59e0b', // amber-500\n animal: '#22c55e', // green-500\n\n // Sub-detection classes\n face: '#a855f7', // purple-500\n plate: '#ec4899', // pink-500\n\n // Specific animal types\n bird: '#14b8a6', // teal-500\n dog: '#84cc16', // lime-500\n cat: '#f97316', // orange-500\n\n // Specific vehicle types\n car: '#f59e0b', // amber-500\n truck: '#d97706', // amber-600\n bus: '#b45309', // amber-700\n motorcycle:'#eab308', // yellow-500\n bicycle: '#ca8a04', // yellow-600\n\n // Other\n motion: '#facc15', // yellow-400\n}\n\n/** Fallback color palette for unknown classes (deterministic hash-based) */\nconst FALLBACK_PALETTE: readonly string[] = [\n '#ef4444', // red-500\n '#8b5cf6', // violet-500\n '#06b6d4', // cyan-500\n '#f97316', // orange-500\n '#10b981', // emerald-500\n '#6366f1', // indigo-500\n '#e11d48', // rose-600\n '#0891b2', // cyan-600\n '#7c3aed', // violet-600\n '#059669', // emerald-600\n]\n\n/** Primary/default color when nothing else matches */\nexport const DEFAULT_COLOR = '#f59e42'\n\n/**\n * Get the color for a detection class name.\n * Returns a fixed color for known classes, or a deterministic hash-based color for unknown ones.\n */\nexport function getClassColor(className: string, customColors?: Readonly<Record<string, string>>): string {\n // Check custom overrides first\n if (customColors?.[className]) return customColors[className]!\n if (customColors?.[className.toLowerCase()]) return customColors[className.toLowerCase()]!\n\n // Check known classes\n if (CLASS_COLORS[className]) return CLASS_COLORS[className]!\n if (CLASS_COLORS[className.toLowerCase()]) return CLASS_COLORS[className.toLowerCase()]!\n\n // Deterministic hash for unknown classes\n let hash = 0\n for (let i = 0; i < className.length; i++) {\n hash = (hash * 31 + (className.codePointAt(i) ?? 0)) >>> 0\n }\n return FALLBACK_PALETTE[hash % FALLBACK_PALETTE.length] ?? DEFAULT_COLOR\n}\n","/**\n * DetectionCanvas — renders an image with overlaid bounding boxes.\n *\n * Supports hierarchical detections (parent → children) with configurable\n * class-based colors. Used by benchmark Image Tester and admin-ui event viewer.\n */\nimport { type ReactNode, useRef, useEffect } from 'react'\nimport { cn } from '../lib/cn'\nimport { CLASS_COLORS, getClassColor } from './detection-colors'\n\n/** @deprecated Use CLASS_COLORS from detection-colors instead */\nexport const DEFAULT_CLASS_COLORS = CLASS_COLORS\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n// Re-export LabelData from @camstack/types for consumers of this component\nexport type { LabelData, LabelOrigin } from '@camstack/types'\nimport type { LabelData } from '@camstack/types'\n\nexport interface Detection {\n /** Display class name (e.g., 'person', 'vehicle', 'face') */\n readonly className: string\n /** Confidence score 0-1 */\n readonly confidence: number\n /** Bounding box [x1, y1, x2, y2] in pixel coordinates */\n readonly bbox: readonly [number, number, number, number]\n /** Sub-detections from cropper steps (face box, plate box) — for debug */\n readonly children?: readonly Detection[]\n /** Accumulated labels from all classifier/recognizer steps */\n readonly labelsData?: readonly LabelData[]\n /** Base64-encoded binary segmentation mask (from -seg models) */\n readonly mask?: string\n /** Mask pixel width */\n readonly maskWidth?: number\n /** Mask pixel height */\n readonly maskHeight?: number\n}\n\nexport interface DetectionCanvasProps {\n /** Image source (data URL or regular URL) */\n readonly src: string | null\n /** Image dimensions (used for bbox coordinate mapping) */\n readonly imageWidth: number\n readonly imageHeight: number\n /** Detections to overlay */\n readonly detections?: readonly Detection[]\n /** Custom class → hex color mapping (merged with defaults) */\n readonly classColors?: Readonly<Record<string, string>>\n /** Aspect ratio CSS value (default: auto based on image dimensions) */\n readonly aspectRatio?: string\n /** Additional CSS classes on the container */\n readonly className?: string\n /** Placeholder content when no image is loaded */\n readonly placeholder?: ReactNode\n /** Show confidence percentage in bbox labels */\n readonly showConfidence?: boolean\n /** Minimum confidence to display (0-1, default: 0) */\n readonly minConfidence?: number\n /** Border width for bboxes in px (default: 2) */\n readonly borderWidth?: number\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function DetectionCanvas({\n src,\n imageWidth,\n imageHeight,\n detections = [],\n classColors,\n aspectRatio,\n className,\n placeholder,\n showConfidence = true,\n minConfidence = 0,\n borderWidth = 2,\n}: DetectionCanvasProps) {\n function getColor(className: string): string {\n return getClassColor(className, classColors)\n }\n\n const ratio = aspectRatio ?? (imageWidth && imageHeight ? `${imageWidth}/${imageHeight}` : '16/9')\n\n const filteredDetections = detections.filter(d => d.confidence >= minConfidence)\n\n return (\n <div\n className={cn(\n 'rounded-lg border border-border bg-surface overflow-hidden relative',\n className,\n )}\n style={{ aspectRatio: ratio }}\n >\n {src ? (\n <>\n {/* Image — absolute so it shares coordinate space with bbox overlays */}\n <img src={src} className=\"absolute inset-0 w-full h-full object-fill\" alt=\"\" />\n\n {/* Segmentation mask overlays (rendered behind bounding boxes) */}\n {filteredDetections.map((d, i) =>\n d.mask && d.maskWidth && d.maskHeight ? (\n <MaskOverlay\n key={`mask-${i}`}\n mask={d.mask}\n maskWidth={d.maskWidth}\n maskHeight={d.maskHeight}\n bbox={d.bbox}\n imageWidth={imageWidth}\n imageHeight={imageHeight}\n color={getColor(d.className)}\n />\n ) : null,\n )}\n\n {/* Parent detection boxes */}\n {filteredDetections.map((d, i) => (\n <BoundingBox\n key={`det-${i}`}\n detection={d}\n imageWidth={imageWidth}\n imageHeight={imageHeight}\n color={getColor(d.className)}\n showConfidence={showConfidence}\n borderWidth={d.mask ? 1 : borderWidth}\n >\n {/* Child detection boxes — only cropper outputs with distinct bbox (face/plate) */}\n {d.children?.filter(c => {\n if (c.confidence < minConfidence) return false\n const [cx1, cy1, cx2, cy2] = c.bbox\n const cw = cx2 - cx1\n const ch = cy2 - cy1\n // Skip zero-size bbox (classifier outputs with no spatial info)\n if (cw <= 0 || ch <= 0) return false\n // Skip if bbox is same as parent (classifier ran on whole detection)\n const [px1, py1, px2, py2] = d.bbox\n const pw = px2 - px1\n const ph = py2 - py1\n if (pw > 0 && ph > 0 && (cw * ch) / (pw * ph) > 0.8) return false\n return true\n }).map((child, j) => (\n <ChildBoundingBox\n key={`child-${j}`}\n child={child}\n parentBbox={d.bbox}\n color={getColor(child.className)}\n showConfidence={showConfidence}\n />\n ))}\n </BoundingBox>\n ))}\n </>\n ) : (\n <div className=\"w-full h-full flex items-center justify-center text-foreground-subtle text-sm\">\n {placeholder ?? 'No image loaded'}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction BoundingBox({\n detection,\n imageWidth,\n imageHeight,\n color,\n showConfidence,\n borderWidth,\n children,\n}: {\n detection: Detection\n imageWidth: number\n imageHeight: number\n color: string\n showConfidence: boolean\n borderWidth: number\n children?: ReactNode\n}) {\n const [x1, y1, x2, y2] = detection.bbox\n\n // Smart label placement: if bbox is near the top of the image, show labels below instead\n const labelCount = 1 + (detection.labelsData?.length ?? 0)\n const labelHeightPx = labelCount * 16 + 4 // ~16px per label row + margin\n const topPct = (y1 / imageHeight) * 100\n const containerRef = useRef<HTMLDivElement>(null)\n\n // Estimate if there's enough space above the bbox\n // Each label row is ~16px, we need labelHeightPx above\n // Container height varies, so use percentage: labelHeightPx / containerHeight * 100\n const showBelow = topPct < (labelHeightPx / imageHeight) * 100 * 1.5\n\n const labelsElement = (\n <div\n className={`absolute left-0 flex flex-col items-start gap-px ${\n showBelow ? '' : ''\n }`}\n style={showBelow\n ? { top: '100%', marginTop: '2px' }\n : { bottom: '100%', marginBottom: '2px' }\n }\n >\n <span\n className=\"text-[10px] px-1 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: color }}\n >\n {detection.className}\n {showConfidence && ` ${(detection.confidence * 100).toFixed(0)}%`}\n </span>\n {detection.labelsData?.map((l: LabelData, k: number) => (\n <span\n key={k}\n className=\"text-[9px] font-semibold px-1 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: getClassColor(l.addonId ?? l.label) }}\n >\n {l.label} {(l.score * 100).toFixed(0)}%\n </span>\n ))}\n </div>\n )\n\n return (\n <div\n ref={containerRef}\n className=\"absolute rounded-sm\"\n style={{\n left: `${(x1 / imageWidth) * 100}%`,\n top: `${(y1 / imageHeight) * 100}%`,\n width: `${((x2 - x1) / imageWidth) * 100}%`,\n height: `${((y2 - y1) / imageHeight) * 100}%`,\n borderWidth: `${borderWidth}px`,\n borderStyle: 'solid',\n borderColor: color,\n }}\n >\n {labelsElement}\n {children}\n </div>\n )\n}\n\n/** Renders a segmentation mask as a semi-transparent colored canvas overlay */\nfunction MaskOverlay({\n mask,\n maskWidth,\n maskHeight,\n bbox,\n imageWidth,\n imageHeight,\n color,\n}: {\n mask: string\n maskWidth: number\n maskHeight: number\n bbox: readonly [number, number, number, number]\n imageWidth: number\n imageHeight: number\n color: string\n}) {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n\n // Decode base64 mask — each byte is a pixel value (0 or 255)\n const binary = atob(mask)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n\n // Parse color\n const r = parseInt(color.slice(1, 3), 16)\n const g = parseInt(color.slice(3, 5), 16)\n const b = parseInt(color.slice(5, 7), 16)\n\n // Create mask image data at mask resolution (1 byte per pixel, not bit-packed)\n canvas.width = maskWidth\n canvas.height = maskHeight\n const imageData = ctx.createImageData(maskWidth, maskHeight)\n const totalPixels = maskWidth * maskHeight\n\n for (let i = 0; i < totalPixels; i++) {\n const val = i < bytes.length ? bytes[i]! : 0\n const px = i * 4\n if (val > 0) {\n imageData.data[px] = r\n imageData.data[px + 1] = g\n imageData.data[px + 2] = b\n imageData.data[px + 3] = 120 // semi-transparent\n }\n }\n\n ctx.putImageData(imageData, 0, 0)\n }, [mask, maskWidth, maskHeight, color])\n\n const [x1, y1, x2, y2] = bbox\n\n return (\n <canvas\n ref={canvasRef}\n className=\"absolute pointer-events-none\"\n style={{\n left: `${(x1 / imageWidth) * 100}%`,\n top: `${(y1 / imageHeight) * 100}%`,\n width: `${((x2 - x1) / imageWidth) * 100}%`,\n height: `${((y2 - y1) / imageHeight) * 100}%`,\n imageRendering: 'pixelated',\n }}\n />\n )\n}\n\nfunction ChildBoundingBox({\n child,\n parentBbox,\n color,\n showConfidence,\n}: {\n child: Detection\n parentBbox: readonly [number, number, number, number]\n color: string\n showConfidence: boolean\n}) {\n const [px1, py1, px2, py2] = parentBbox\n const [cx1, cy1, cx2, cy2] = child.bbox\n const pw = px2 - px1\n const ph = py2 - py1\n\n if (pw <= 0 || ph <= 0) return null\n\n return (\n <div\n className=\"absolute rounded-sm\"\n style={{\n left: `${Math.max(0, ((cx1 - px1) / pw) * 100)}%`,\n top: `${Math.max(0, ((cy1 - py1) / ph) * 100)}%`,\n width: `${Math.min(100, ((cx2 - cx1) / pw) * 100)}%`,\n height: `${Math.min(100, ((cy2 - cy1) / ph) * 100)}%`,\n borderWidth: '1px',\n borderStyle: 'solid',\n borderColor: color,\n }}\n >\n {/* Labels stack: className + labelsData, smart top/bottom placement */}\n {(() => {\n const labelCount = 1 + (child.labelsData?.length ?? 0)\n const relTop = ((cy1 - py1) / ph) * 100\n const showBelow = relTop < labelCount * 6 // ~6% per label row relative to parent\n return (\n <div\n className=\"absolute left-0 flex flex-col items-start gap-px\"\n style={showBelow\n ? { top: '100%', marginTop: '1px' }\n : { bottom: '100%', marginBottom: '1px' }\n }\n >\n <span\n className=\"text-[9px] px-0.5 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: color }}\n >\n {child.className}\n {showConfidence && ` ${(child.confidence * 100).toFixed(0)}%`}\n </span>\n {child.labelsData?.map((l: LabelData, k: number) => (\n <span\n key={k}\n className=\"text-[8px] font-semibold px-0.5 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: getClassColor(l.addonId ?? l.label) }}\n >\n {l.label} {(l.score * 100).toFixed(0)}%\n </span>\n ))}\n </div>\n )\n })()}\n </div>\n )\n}\n","/**\n * DetectionResultTree — displays detection results as a hierarchical tree.\n *\n * Shows parent detections with confidence badges, mask info, expandable children,\n * and visibility checkboxes that toggle overlays on the detection canvas.\n */\nimport { type Detection } from './detection-canvas'\nimport { getClassColor } from './detection-colors'\n\nexport interface DetectionResultTreeProps {\n readonly detections: readonly Detection[]\n readonly classColors?: Readonly<Record<string, string>>\n readonly className?: string\n /** Set of detection path keys that are hidden (e.g., \"0\", \"0.1\", \"0.1.2\") */\n readonly hiddenKeys?: ReadonlySet<string>\n /** Callback when a detection's visibility is toggled */\n readonly onToggleVisibility?: (key: string, visible: boolean) => void\n}\n\nexport function DetectionResultTree({\n detections,\n classColors,\n className,\n hiddenKeys,\n onToggleVisibility,\n}: DetectionResultTreeProps) {\n const colors = classColors\n\n if (detections.length === 0) {\n return (\n <div className=\"text-sm text-foreground-subtle italic text-center py-4\">\n No detections\n </div>\n )\n }\n\n return (\n <div className={className}>\n <div className=\"text-xs font-medium text-foreground-subtle uppercase tracking-wide mb-2\">\n Detections ({detections.length})\n </div>\n <div className=\"space-y-2\">\n {detections.map((d, i) => (\n <DetectionNode\n key={i}\n detection={d}\n path={String(i)}\n colors={colors}\n hiddenKeys={hiddenKeys}\n onToggleVisibility={onToggleVisibility}\n />\n ))}\n </div>\n </div>\n )\n}\n\nfunction DetectionNode({\n detection,\n path,\n colors,\n hiddenKeys,\n onToggleVisibility,\n}: {\n detection: Detection\n path: string\n colors?: Record<string, string>\n hiddenKeys?: ReadonlySet<string>\n onToggleVisibility?: (key: string, visible: boolean) => void\n}) {\n const color = getClassColor(detection.className, colors)\n const isVisible = !hiddenKeys?.has(path)\n\n return (\n <div className={`rounded-md border border-border bg-surface p-3 space-y-1 ${isVisible ? '' : 'opacity-40'}`}>\n <div className=\"flex justify-between items-center\">\n <div className=\"flex items-center gap-2\">\n {onToggleVisibility && (\n <input\n type=\"checkbox\"\n checked={isVisible}\n onChange={() => onToggleVisibility(path, !isVisible)}\n className=\"h-3.5 w-3.5 rounded border-border accent-primary cursor-pointer shrink-0\"\n />\n )}\n <span\n className=\"h-2.5 w-2.5 rounded-full shrink-0\"\n style={{ backgroundColor: color }}\n />\n <span className=\"text-sm font-medium text-foreground\">\n {detection.className}\n </span>\n {detection.mask && detection.maskWidth && detection.maskHeight && (\n <span className=\"text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary\">\n mask {detection.maskWidth}x{detection.maskHeight}\n </span>\n )}\n </div>\n <ConfidenceBadge confidence={detection.confidence} />\n </div>\n\n <div className=\"text-[10px] text-foreground-subtle font-mono\">\n bbox: [{detection.bbox.map(v => Math.round(v)).join(', ')}]\n </div>\n\n {/* Pipeline labelsData (species, plate text, vehicle type, face name, etc.) */}\n {detection.labelsData && detection.labelsData.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {detection.labelsData.map((l: any, k: number) => (\n <span\n key={k}\n className=\"inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full\"\n style={{ backgroundColor: getClassColor(l.addonId ?? l.label, colors) + '20', color: getClassColor(l.addonId ?? l.label, colors) }}\n >\n {l.label}\n <span className=\"opacity-60\">{(l.score * 100).toFixed(0)}%</span>\n {l.addonId && <span className=\"opacity-40 text-[8px]\">{l.addonId}</span>}\n </span>\n ))}\n </div>\n )}\n\n {/* Children tree — recursive */}\n {detection.children && detection.children.length > 0 && (\n <ChildrenTree\n children={detection.children}\n parentPath={path}\n colors={colors}\n hiddenKeys={hiddenKeys}\n onToggleVisibility={onToggleVisibility}\n />\n )}\n </div>\n )\n}\n\nfunction ChildrenTree({\n children,\n parentPath,\n colors,\n hiddenKeys,\n onToggleVisibility,\n}: {\n children: readonly Detection[]\n parentPath: string\n colors?: Record<string, string>\n hiddenKeys?: ReadonlySet<string>\n onToggleVisibility?: (key: string, visible: boolean) => void\n}) {\n return (\n <div className=\"ml-4 mt-1.5 space-y-1.5 border-l-2 border-border pl-3\">\n {children.map((child, j) => {\n const childPath = `${parentPath}.${j}`\n const childColor = getClassColor(child.className, colors)\n const isVisible = !hiddenKeys?.has(childPath)\n\n return (\n <div key={j} className={`text-xs space-y-0.5 ${isVisible ? '' : 'opacity-40'}`}>\n <div className=\"flex items-center gap-1.5\">\n {onToggleVisibility && (\n <input\n type=\"checkbox\"\n checked={isVisible}\n onChange={() => onToggleVisibility(childPath, !isVisible)}\n className=\"h-3 w-3 rounded border-border accent-primary cursor-pointer shrink-0\"\n />\n )}\n <span\n className=\"h-1.5 w-1.5 rounded-full shrink-0\"\n style={{ backgroundColor: childColor }}\n />\n <span className=\"font-medium\" style={{ color: childColor }}>\n {child.className}\n </span>\n <span className=\"text-foreground-subtle\">\n {(child.confidence * 100).toFixed(0)}%\n </span>\n {child.mask && child.maskWidth && child.maskHeight && (\n <span className=\"text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary\">\n mask {child.maskWidth}x{child.maskHeight}\n </span>\n )}\n </div>\n {/* labelsData on child */}\n {child.labelsData && child.labelsData.length > 0 && (\n <div className=\"flex flex-wrap gap-1 ml-5 mt-0.5\">\n {child.labelsData.map((l: any, k: number) => (\n <span key={k} className=\"inline-flex items-center gap-0.5 text-[9px] font-medium px-1 py-0.5 rounded-full\"\n style={{ backgroundColor: getClassColor(l.addonId ?? l.label, colors) + '20', color: getClassColor(l.addonId ?? l.label, colors) }}>\n {l.label} <span className=\"opacity-60\">{(l.score * 100).toFixed(0)}%</span>\n </span>\n ))}\n </div>\n )}\n {/* Recursive children */}\n {child.children && child.children.length > 0 && (\n <ChildrenTree\n children={child.children}\n parentPath={childPath}\n colors={colors}\n hiddenKeys={hiddenKeys}\n onToggleVisibility={onToggleVisibility}\n />\n )}\n </div>\n )\n })}\n </div>\n )\n}\n\nfunction ConfidenceBadge({ confidence }: { confidence: number }) {\n const level =\n confidence >= 0.8 ? 'bg-success/10 text-success' :\n confidence >= 0.5 ? 'bg-warning/10 text-warning' :\n 'bg-danger/10 text-danger'\n\n return (\n <span className={`text-xs font-medium px-2 py-0.5 rounded-full ${level}`}>\n {(confidence * 100).toFixed(1)}%\n </span>\n )\n}\n","/**\n * StepTimings — displays pipeline execution timings per step.\n */\n\nexport interface StepTimingsProps {\n readonly timings: Readonly<Record<string, number>>\n readonly totalMs?: number\n readonly className?: string\n}\n\nexport function StepTimings({ timings, totalMs, className }: StepTimingsProps) {\n const entries = Object.entries(timings)\n if (entries.length === 0 && totalMs === undefined) return null\n\n return (\n <div className={`rounded-lg border border-border bg-surface p-3 space-y-2 ${className ?? ''}`}>\n <div className=\"text-xs font-medium text-foreground-subtle uppercase tracking-wide\">\n Timings\n </div>\n <div className=\"space-y-1 text-xs\">\n {entries.map(([step, ms]) => (\n <div key={step} className=\"flex justify-between\">\n <span className=\"text-foreground-subtle\">{step}</span>\n <span className=\"font-mono text-foreground\">{ms.toFixed(1)}ms</span>\n </div>\n ))}\n {totalMs !== undefined && (\n <div className=\"flex justify-between pt-1 border-t border-border font-medium text-foreground\">\n <span>Total</span>\n <span className=\"font-mono\">{totalMs.toFixed(1)}ms</span>\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * ImageSelector — select from reference images or upload custom image.\n * Used by benchmark Image Tester and any addon page that needs image input.\n */\n\nexport interface ReferenceImage {\n readonly id: string\n readonly filename: string\n readonly sizeKB?: number\n}\n\nexport interface ImageSelectorProps {\n readonly images: readonly ReferenceImage[]\n readonly selectedFilename: string\n readonly uploadedName?: string\n readonly onSelect: (filename: string) => void\n readonly onUpload: (base64: string, filename: string, dataUrl: string) => void\n readonly className?: string\n}\n\nexport function ImageSelector({\n images,\n selectedFilename,\n uploadedName,\n onSelect,\n onUpload,\n className,\n}: ImageSelectorProps) {\n const handleUploadClick = () => {\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = 'image/*'\n input.onchange = (ev: any) => {\n const file = ev.target.files?.[0]\n if (!file) return\n const reader = new FileReader()\n reader.onload = (e: any) => {\n const dataUrl = e.target?.result as string\n const b64 = dataUrl.split(',')[1]\n if (b64) onUpload(b64, file.name, dataUrl)\n }\n reader.readAsDataURL(file)\n }\n input.click()\n }\n\n return (\n <div className={`flex flex-wrap items-center gap-2 ${className ?? ''}`}>\n {images.map(img => (\n <button\n key={img.filename}\n onClick={() => onSelect(img.filename)}\n className={`px-3 py-1.5 text-xs rounded-md border transition-colors ${\n selectedFilename === img.filename\n ? 'bg-primary text-primary-foreground border-primary'\n : 'bg-surface border-border text-foreground hover:border-primary/50'\n }`}\n >\n {img.id}\n </button>\n ))}\n <button\n onClick={handleUploadClick}\n className=\"px-3 py-1.5 text-xs rounded-md border border-border bg-surface text-foreground hover:bg-surface-hover transition-colors\"\n >\n Upload...\n </button>\n {uploadedName && (\n <span className=\"text-xs text-foreground-subtle\">{uploadedName}</span>\n )}\n </div>\n )\n}\n","/**\n * InferenceConfigSelector — cascading selectors for runtime/backend/model.\n *\n * Used by benchmark Engine tab, Image Tester pipeline steps, and admin-ui\n * pipeline configuration. Shows only valid combinations based on capabilities.\n */\n\nexport interface InferenceBackendOption {\n readonly id: string\n readonly label: string\n readonly available: boolean\n}\n\nexport interface InferenceModelOption {\n readonly id: string\n readonly name: string\n readonly downloaded?: boolean\n}\n\nexport interface InferenceAgentOption {\n readonly id: string\n readonly name: string\n readonly status: 'online' | 'offline' | 'busy'\n}\n\nexport interface InferenceConfigSelectorProps {\n // Values\n readonly runtime: 'node' | 'python'\n readonly backend: string\n readonly modelId: string\n readonly agentId?: string\n\n // Options\n readonly runtimes: readonly { value: string; label: string; available: boolean }[]\n readonly backends: readonly InferenceBackendOption[]\n readonly models: readonly InferenceModelOption[]\n readonly agents?: readonly InferenceAgentOption[]\n\n // Callbacks\n readonly onRuntimeChange: (rt: 'node' | 'python') => void\n readonly onBackendChange: (id: string) => void\n readonly onModelChange: (id: string) => void\n readonly onAgentChange?: (id: string) => void\n\n // Layout\n readonly layout?: 'horizontal' | 'vertical' | 'grid'\n readonly className?: string\n /** Show agent selector (default: false) */\n readonly showAgent?: boolean\n}\n\nconst SELECT_CLASS = 'w-full px-3 py-2 text-sm rounded-md border border-border bg-surface text-foreground focus:outline-none focus:ring-2 focus:ring-primary/50'\n\nexport function InferenceConfigSelector({\n runtime,\n backend,\n modelId,\n agentId = 'hub',\n runtimes,\n backends,\n models,\n agents = [],\n onRuntimeChange,\n onBackendChange,\n onModelChange,\n onAgentChange,\n layout = 'grid',\n className,\n showAgent = false,\n}: InferenceConfigSelectorProps) {\n const containerClass = layout === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4'\n : layout === 'horizontal'\n ? 'flex flex-wrap items-end gap-4'\n : 'space-y-3'\n\n return (\n <div className={`${containerClass} ${className ?? ''}`}>\n {/* Agent (optional) */}\n {showAgent && agents.length > 0 && (\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Agent</span>\n <select\n value={agentId}\n onChange={e => onAgentChange?.(e.target.value)}\n className={SELECT_CLASS}\n >\n {agents.map(a => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.status})\n </option>\n ))}\n </select>\n </label>\n )}\n\n {/* Runtime */}\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Runtime</span>\n <select\n value={runtime}\n onChange={e => onRuntimeChange(e.target.value as 'node' | 'python')}\n className={SELECT_CLASS}\n >\n {runtimes.map(r => (\n <option key={r.value} value={r.value} disabled={!r.available}>\n {r.label}{!r.available ? ' (unavailable)' : ''}\n </option>\n ))}\n </select>\n </label>\n\n {/* Backend */}\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Backend</span>\n <select\n value={backend}\n onChange={e => onBackendChange(e.target.value)}\n className={SELECT_CLASS}\n >\n {backends.map(b => (\n <option key={b.id} value={b.id} disabled={!b.available}>\n {b.label}{!b.available ? ' (unavailable)' : ''}\n </option>\n ))}\n </select>\n </label>\n\n {/* Model */}\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Model</span>\n <select\n value={modelId}\n onChange={e => onModelChange(e.target.value)}\n className={SELECT_CLASS}\n >\n {models.length === 0\n ? <option value=\"\">No compatible models</option>\n : models.map(m => (\n <option key={m.id} value={m.id}>\n {m.name}{m.downloaded ? ' ✓' : ''}\n </option>\n ))\n }\n </select>\n </label>\n </div>\n )\n}\n","/**\n * mountAddonPage — one-liner to mount an addon page in dev mode.\n *\n * Handles everything: CSS import, React DOM mount, DevShell (login + theme + tRPC),\n * and wiring props in the standard AddonPageProps format.\n *\n * Usage in the addon's dev-shell.tsx:\n * ```tsx\n * import { mountAddonPage } from '@camstack/ui'\n * import MyPage from './page'\n * mountAddonPage(MyPage)\n * ```\n *\n * Or with options:\n * ```tsx\n * mountAddonPage(MyPage, { serverUrl: 'https://localhost:4443', title: 'My Addon' })\n * ```\n */\nimport { createElement } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { DevShell } from './dev-shell'\nimport type { AddonPageProps } from './addon-page-props'\n\nexport interface MountAddonPageOptions {\n /** Backend server URL (default: 'https://localhost:4443') */\n serverUrl?: string\n /** Title shown in the dev toolbar */\n title?: string\n /** Root element ID (default: 'root') */\n rootId?: string\n}\n\n/**\n * Mount an addon page component with the full dev shell.\n *\n * @param PageComponent - The addon page component (must accept AddonPageProps)\n * @param options - Configuration options\n */\nexport function mountAddonPage(\n PageComponent: (props: AddonPageProps) => any,\n options: MountAddonPageOptions = {},\n): void {\n const {\n serverUrl = 'https://localhost:4443',\n title,\n rootId = 'root',\n } = options\n\n const root = document.getElementById(rootId)\n if (!root) {\n console.error(`[mountAddonPage] Element #${rootId} not found`)\n return\n }\n\n createRoot(root).render(\n createElement(DevShell, {\n serverUrl,\n title,\n children: ({ trpc, theme }) =>\n createElement(PageComponent, {\n trpc,\n theme: { isDark: theme.resolvedMode === 'dark' },\n navigate: (path: string) => {\n console.log('[dev] navigate:', path)\n },\n }),\n }),\n )\n}\n","import { createContext, useCallback, useContext, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { createTRPCClient, createWSClient, wsLink, httpLink, splitLink } from '@trpc/client'\nimport superjson from 'superjson'\nimport { ThemeProvider } from '../theme/theme-provider'\nimport { useThemeMode } from '../theme/use-theme-mode'\nimport type { UseThemeModeReturn } from '../theme/types'\nimport { LoginForm } from './login-form'\n\nconst STORAGE_KEY = 'camstack_dev_token'\n\nexport interface DevShellProps {\n children: (props: { trpc: ReturnType<typeof createTRPCClient>; theme: UseThemeModeReturn }) => ReactNode\n serverUrl?: string\n title?: string\n}\n\ninterface DevShellContextValue {\n trpc: ReturnType<typeof createTRPCClient>\n token: string\n logout: () => void\n}\n\nconst DevShellContext = createContext<DevShellContextValue | null>(null)\n\nexport function useDevShell(): DevShellContextValue {\n const ctx = useContext(DevShellContext)\n if (!ctx) {\n throw new Error('useDevShell must be used within a DevShell')\n }\n return ctx\n}\n\nfunction getStoredToken(): string | null {\n if (typeof window === 'undefined') return null\n return localStorage.getItem(STORAGE_KEY)\n}\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2\" />\n <path d=\"M12 20v2\" />\n <path d=\"m4.93 4.93 1.41 1.41\" />\n <path d=\"m17.66 17.66 1.41 1.41\" />\n <path d=\"M2 12h2\" />\n <path d=\"M20 12h2\" />\n <path d=\"m6.34 17.66-1.41 1.41\" />\n <path d=\"m19.07 4.93-1.41 1.41\" />\n </svg>\n )\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\" />\n </svg>\n )\n}\n\nfunction DevShellInner({\n children,\n serverUrl,\n title,\n token,\n onLogout,\n}: {\n children: DevShellProps['children']\n serverUrl: string\n title?: string\n token: string\n onLogout: () => void\n}) {\n const theme = useThemeMode()\n\n const trpc = useMemo(\n () => {\n const wsUrl = serverUrl.replace(/^http/, 'ws') + '/trpc'\n const wsClient = createWSClient({\n url: wsUrl,\n connectionParams: () => ({ token }),\n })\n\n return createTRPCClient({\n links: [\n splitLink({\n condition: (op) => op.type === 'subscription',\n true: wsLink({ client: wsClient, transformer: superjson }),\n false: httpLink({\n url: `${serverUrl}/trpc`,\n transformer: superjson,\n headers: () => ({ authorization: `Bearer ${token}` }),\n }),\n }),\n ],\n })\n },\n [serverUrl, token],\n )\n\n const contextValue = useMemo<DevShellContextValue>(\n () => ({ trpc, token, logout: onLogout }),\n [trpc, token, onLogout],\n )\n\n return (\n <DevShellContext.Provider value={contextValue}>\n <div className=\"min-h-screen bg-background text-foreground\">\n <div className=\"flex items-center justify-between border-b border-border bg-surface px-4 py-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"rounded bg-warning/20 px-2 py-0.5 text-xs font-bold text-warning\">\n DEV MODE\n </span>\n {title && (\n <span className=\"text-sm font-medium text-foreground\">\n {title}\n </span>\n )}\n <span className=\"text-xs text-foreground-subtle\">\n {serverUrl}\n </span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={theme.toggleMode}\n className=\"flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors\"\n title={`Theme: ${theme.mode}`}\n >\n {theme.resolvedMode === 'dark' ? (\n <SunIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <MoonIcon className=\"h-3.5 w-3.5\" />\n )}\n {theme.mode === 'dark' ? 'Dark' : theme.mode === 'light' ? 'Light' : 'System'}\n </button>\n\n <button\n type=\"button\"\n onClick={onLogout}\n className=\"rounded-md px-2.5 py-1 text-xs font-medium text-danger hover:bg-danger/10 transition-colors\"\n >\n Logout\n </button>\n </div>\n </div>\n\n <div className=\"p-4\">{children({ trpc, theme })}</div>\n </div>\n </DevShellContext.Provider>\n )\n}\n\nexport function DevShell({\n children,\n serverUrl = 'https://localhost:4443',\n title,\n}: DevShellProps) {\n const [token, setToken] = useState<string | null>(getStoredToken)\n\n const handleLogin = useCallback(\n async (username: string, password: string) => {\n // Use tRPC client for auth (no token yet)\n const anonClient = createTRPCClient({\n links: [\n httpLink({\n url: `${serverUrl}/trpc`,\n transformer: superjson,\n }),\n ],\n })\n\n const res: any = await (anonClient as any).auth.login.mutate({ username, password })\n if (!res?.token) throw new Error('No token returned')\n\n localStorage.setItem(STORAGE_KEY, res.token)\n setToken(res.token)\n },\n [serverUrl],\n )\n\n const handleLogout = useCallback(() => {\n localStorage.removeItem(STORAGE_KEY)\n setToken(null)\n }, [])\n\n if (!token) {\n return (\n <ThemeProvider>\n <LoginForm onLogin={handleLogin} serverUrl={serverUrl} />\n </ThemeProvider>\n )\n }\n\n return (\n <ThemeProvider>\n <DevShellInner\n serverUrl={serverUrl}\n title={title}\n token={token}\n onLogout={handleLogout}\n >\n {children}\n </DevShellInner>\n </ThemeProvider>\n )\n}\n","import { type FormEvent, useState } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface LoginFormProps {\n onLogin: (username: string, password: string) => Promise<void>\n serverUrl?: string\n logoSrc?: string\n error?: string\n className?: string\n}\n\nfunction EyeIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )\n}\n\nfunction EyeOffIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n )\n}\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n )\n}\n\nexport function LoginForm({\n onLogin,\n serverUrl,\n logoSrc,\n error: externalError,\n className,\n}: LoginFormProps) {\n const [username, setUsername] = useState('')\n const [password, setPassword] = useState('')\n const [showPassword, setShowPassword] = useState(false)\n const [submitting, setSubmitting] = useState(false)\n const [internalError, setInternalError] = useState<string | null>(null)\n\n const error = externalError ?? internalError\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault()\n if (submitting) return\n\n setInternalError(null)\n setSubmitting(true)\n\n try {\n await onLogin(username, password)\n } catch (err) {\n const message =\n err instanceof Error ? err.message : 'Login failed. Please try again.'\n setInternalError(message)\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-screen items-center justify-center bg-background p-4',\n className,\n )}\n >\n <div className=\"w-full max-w-sm\">\n {logoSrc && (\n <div className=\"flex justify-center mb-8\">\n <img src={logoSrc} alt=\"Logo\" className=\"h-12\" />\n </div>\n )}\n\n {serverUrl && (\n <p className=\"mb-4 text-center text-xs text-foreground-subtle truncate\">\n {serverUrl}\n </p>\n )}\n\n <form\n onSubmit={handleSubmit}\n className=\"space-y-4 rounded-xl border border-border bg-surface p-6 shadow-xl shadow-black/10\"\n >\n {error && (\n <div className=\"rounded-md bg-danger/10 border border-danger/20 px-3 py-2 text-xs text-danger\">\n {error}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-foreground-subtle\">\n Username\n </label>\n <input\n type=\"text\"\n value={username}\n onChange={(e) => setUsername(e.target.value)}\n autoComplete=\"username\"\n required\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary\"\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-foreground-subtle\">\n Password\n </label>\n <div className=\"relative\">\n <input\n type={showPassword ? 'text' : 'password'}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n autoComplete=\"current-password\"\n required\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2.5 pr-10 text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary\"\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword((prev) => !prev)}\n className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground\"\n tabIndex={-1}\n >\n {showPassword ? (\n <EyeOffIcon className=\"h-4 w-4\" />\n ) : (\n <EyeIcon className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </div>\n\n <button\n type=\"submit\"\n disabled={submitting}\n className=\"w-full rounded-lg bg-primary px-4 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center justify-center gap-2\"\n >\n {submitting && (\n <SpinnerIcon className=\"h-4 w-4 animate-spin\" />\n )}\n {submitting ? 'Logging in...' : 'Log in'}\n </button>\n </form>\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["import_react","import_lucide_react","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","table","_","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","className","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_client","import_react","import_react","import_jsx_runtime","import_jsx_runtime","superjson"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/theme/defaults.ts","../src/theme/create-theme.ts","../src/theme/theme-to-css.ts","../src/theme/theme-provider.tsx","../src/theme/use-theme-mode.ts","../src/lib/cn.ts","../src/lib/responsive.ts","../src/lib/pipeline-mirror.ts","../src/lib/phase-config.ts","../src/lib/shared-context.ts","../src/lib/mf-runtime-init.ts","../src/icons/provider-icons.ts","../src/icons/status-icons.ts","../src/primitives/button.tsx","../src/primitives/icon-button.tsx","../src/primitives/badge.tsx","../src/primitives/card.tsx","../src/primitives/collapsible-card.tsx","../src/primitives/label.tsx","../src/primitives/separator.tsx","../src/primitives/skeleton.tsx","../src/primitives/input.tsx","../src/primitives/select.tsx","../src/primitives/checkbox.tsx","../src/primitives/switch.tsx","../src/primitives/dialog.tsx","../src/primitives/dropdown.tsx","../src/primitives/tooltip.tsx","../src/primitives/popover.tsx","../src/hooks/use-is-mobile.ts","../src/primitives/bottom-sheet.tsx","../src/primitives/tabs.tsx","../src/primitives/scroll-area.tsx","../src/primitives/floating-panel.tsx","../src/primitives/mobile-drawer.tsx","../src/composites/breadcrumb.tsx","../src/composites/slide-over-panel.tsx","../src/composites/step-tree-master.tsx","../src/composites/agent-step-editor.tsx","../src/composites/pipeline-step.tsx","../src/composites/pipeline-tree-matrix.tsx","../src/composites/node-picker.tsx","../src/hooks/use-cluster-nodes.ts","../src/trpc-react.ts","../src/hooks/use-event-stream.ts","../src/hooks/use-live-event.ts","../src/contexts/system-context.tsx","../src/composites/status-badge.tsx","../src/composites/provider-badge.tsx","../src/composites/version-badge.tsx","../src/composites/form-field.tsx","../src/composites/page-header.tsx","../src/composites/empty-state.tsx","../src/composites/confirm-dialog.tsx","../src/composites/stat-card.tsx","../src/composites/key-value-list.tsx","../src/composites/code-block.tsx","../src/composites/filter-bar.tsx","../src/composites/app-shell/sidebar-item.tsx","../src/composites/app-shell/sidebar.tsx","../src/composites/app-shell/app-shell.tsx","../src/composites/data-table/data-table.tsx","../src/composites/data-table/data-table-header.tsx","../src/composites/data-table/data-table-row.tsx","../src/composites/data-table/data-table-pagination.tsx","../src/composites/device-card.tsx","../src/composites/device-grid.tsx","../src/composites/device-item/index.tsx","../src/composites/device-item/children-accordion.tsx","../src/hooks/use-device-proxy.ts","../src/hooks/use-device-capability.ts","../src/composites/device-item/helpers.ts","../src/composites/device-item/actions.tsx","../src/composites/device-item/features.tsx","../src/hooks/use-device-features.ts","../src/composites/device-item/header.tsx","../src/composites/device-item/preview.tsx","../src/hooks/use-device-battery.ts","../src/hooks/use-device-snapshot.ts","../src/composites/battery-badge.tsx","../src/composites/device-item/status-dot.tsx","../src/composites/device-list/index.tsx","../src/hooks/use-debounced-string.ts","../src/composites/device-list/group.ts","../src/composites/device-list/pagination.tsx","../src/composites/device-list/filter-chips.tsx","../src/composites/device-list/empty-state.tsx","../src/composites/device-list/url-state.ts","../src/composites/pipeline-runtime-selector.tsx","../src/composites/pipeline-builder.tsx","../src/lib/validate-template.ts","../src/composites/detection-colors.ts","../src/composites/detection-canvas.tsx","../src/composites/detection-result-tree.tsx","../src/composites/step-timings.tsx","../src/composites/image-selector.tsx","../src/composites/inference-config-selector.tsx","../src/composites/mount-addon-page.tsx","../src/composites/dev-shell.tsx","../src/composites/login-form.tsx","../src/composites/config-form-builder.tsx","../src/composites/config-form-field.tsx","../src/contexts/custom-field-renderers.tsx","../src/contexts/device-context.tsx","../src/composites/widget-slot.tsx","../src/contexts/widget-registry.tsx","../src/generated/system-hooks.ts","../src/composites/addon-global-settings-form.tsx","../src/composites/detection-overlay.tsx","../src/composites/camera-stream-player.tsx","../src/composites/stream-panel.tsx","../src/contexts/player-overlays.tsx","../src/composites/audio-waveform.tsx","../src/composites/audio-level-waveform.tsx","../src/composites/audio-classification-list.tsx","../src/composites/response-log.tsx","../src/composites/phase-icon.tsx","../src/composites/log-stream.tsx","../src/hooks/use-live-buffer.ts","../src/composites/event-stream.tsx","../src/composites/discovery-panel.tsx","../src/composites/state-values-stream.tsx","../src/composites/device-activity-panel.tsx","../src/composites/confirm-action-button.tsx","../src/composites/ptz-overlay.tsx","../src/composites/snapshot-button.tsx","../src/composites/doorbell-recent-panel.tsx","../src/composites/kebab-menu.tsx","../src/contexts/zone-editing.tsx","../src/hooks/use-device-detections.ts","../src/hooks/use-device-webrtc.ts","../src/hooks/use-ptz.ts","../src/hooks/use-doorbell-events.ts","../src/hooks/use-devices.ts","../src/hooks/use-system-query.ts","../src/hooks/use-event-invalidation.ts"],"sourcesContent":["export * from './theme'\nexport * from './lib'\nexport * from './icons'\nexport * from './primitives'\nexport * from './composites'\nexport * from './contexts/custom-field-renderers'\nexport * from './contexts/device-context'\nexport * from './contexts/player-overlays'\nexport * from './contexts/zone-editing'\nexport {\n SystemProvider,\n useSystem,\n useOptionalSystem,\n type SystemProviderProps,\n} from './contexts/system-context'\nexport {\n WidgetRegistryProvider,\n useWidgetRegistry,\n useOptionalWidgetRegistry,\n useWidget,\n useWidgetMetadata,\n useAllWidgets,\n type WidgetRegistry,\n type WidgetRegistryProviderProps,\n type WidgetProps,\n type WidgetMetadataEntry,\n} from './contexts/widget-registry'\nexport * from './hooks'\nexport * from './generated/system-hooks'\n// `core-hooks` removed in Phase E — the 6 hand-written core routers\n// are now caps so `system-hooks` covers them via the standard walker.\nexport { trpc } from './trpc-react'\n","import type { CamStackColorTokens, CamStackTheme } from './types'\n\nconst providerColors: CamStackColorTokens['provider'] = {\n frigate: '#3b82f6',\n scrypted: '#a855f7',\n reolink: '#06b6d4',\n homeAssistant: '#22d3ee',\n rtsp: '#78716c',\n}\n\nexport const darkColors: CamStackColorTokens = {\n primary: '#f59e42',\n primaryForeground: '#0c0a09',\n background: '#0c0a09',\n backgroundElevated: '#1c1917',\n surface: '#1c1917',\n surfaceHover: '#292524',\n border: '#292524',\n borderSubtle: '#1c1917',\n foreground: '#fafaf9',\n foregroundMuted: '#a8a29e',\n foregroundSubtle: '#78716c',\n foregroundDisabled: '#57534e',\n success: '#4ade80',\n warning: '#fbbf24',\n danger: '#f87171',\n info: '#60a5fa',\n provider: providerColors,\n}\n\nexport const lightColors: CamStackColorTokens = {\n primary: '#e67e22',\n primaryForeground: '#ffffff',\n background: '#fafaf9',\n backgroundElevated: '#ffffff',\n surface: '#f5f5f4',\n surfaceHover: '#e7e5e4',\n border: '#d6d3d1',\n borderSubtle: '#e7e5e4',\n foreground: '#1c1917',\n foregroundMuted: '#57534e',\n foregroundSubtle: '#78716c',\n foregroundDisabled: '#a8a29e',\n success: '#16a34a',\n warning: '#d97706',\n danger: '#dc2626',\n info: '#2563eb',\n provider: providerColors,\n}\n\nexport const defaultTheme: CamStackTheme = {\n colors: {\n dark: darkColors,\n light: lightColors,\n },\n spacing: {\n xs: 2,\n sm: 4,\n md: 8,\n lg: 12,\n xl: 16,\n '2xl': 24,\n '3xl': 32,\n },\n radius: {\n sm: 4,\n md: 6,\n lg: 8,\n xl: 12,\n },\n typography: {\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n sizes: {\n xs: { fontSize: 10, lineHeight: 14 },\n sm: { fontSize: 11, lineHeight: 16 },\n base: { fontSize: 12, lineHeight: 18 },\n lg: { fontSize: 13, lineHeight: 18 },\n xl: { fontSize: 14, lineHeight: 20 },\n '2xl': { fontSize: 16, lineHeight: 22 },\n '3xl': { fontSize: 20, lineHeight: 28 },\n },\n weights: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n },\n table: {\n rowHeight: 28,\n headerHeight: 24,\n cellPaddingX: 8,\n cellPaddingY: 6,\n },\n sidebar: {\n width: 176,\n itemHeight: 28,\n iconSize: 14,\n },\n}\n","import type { CamStackTheme, DeepPartial } from './types'\nimport { defaultTheme } from './defaults'\n\nfunction deepMerge<T extends object>(target: T, source: DeepPartial<T>): T {\n const result = { ...target }\n for (const key in source) {\n const sourceVal = source[key]\n const targetVal = target[key]\n if (\n sourceVal !== undefined &&\n typeof sourceVal === 'object' &&\n sourceVal !== null &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === 'object' &&\n targetVal !== null\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n ) as T[typeof key]\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal as T[typeof key]\n }\n }\n return result\n}\n\nexport function createTheme(overrides?: DeepPartial<CamStackTheme>): CamStackTheme {\n if (!overrides) return structuredClone(defaultTheme)\n return deepMerge(structuredClone(defaultTheme), overrides)\n}\n","import type { CamStackColorTokens, CamStackTheme } from './types'\n\nfunction camelToKebab(str: string): string {\n return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)\n}\n\nfunction colorTokenToCssVar(key: string): string {\n return `--color-${camelToKebab(key)}`\n}\n\nfunction generateColorBlock(colors: CamStackColorTokens): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(colors)) {\n if (key === 'provider') continue\n lines.push(` ${colorTokenToCssVar(key)}: ${value};`)\n }\n return lines.join('\\n')\n}\n\nfunction generateProviderColors(provider: CamStackColorTokens['provider']): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(provider)) {\n lines.push(` --color-provider-${camelToKebab(key)}: ${value};`)\n }\n return lines.join('\\n')\n}\n\nfunction generateSpacingTokens(spacing: CamStackTheme['spacing']): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(spacing)) {\n lines.push(` --spacing-${key}: ${value}px;`)\n }\n return lines.join('\\n')\n}\n\nfunction generateRadiusTokens(radius: CamStackTheme['radius']): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(radius)) {\n lines.push(` --radius-${key}: ${value}px;`)\n }\n return lines.join('\\n')\n}\n\nexport function themeToCss(theme: CamStackTheme): string {\n const darkColorBlock = generateColorBlock(theme.colors.dark)\n const lightColorBlock = generateColorBlock(theme.colors.light)\n const providerBlock = generateProviderColors(theme.colors.dark.provider)\n const spacingBlock = generateSpacingTokens(theme.spacing)\n const radiusBlock = generateRadiusTokens(theme.radius)\n\n return `@theme {\n${providerBlock}\n${spacingBlock}\n${radiusBlock}\n}\n\n.dark {\n${darkColorBlock}\n}\n\n.light {\n${lightColorBlock}\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n${darkColorBlock.replace(/^ {2}/gm, ' ')}\n }\n}\n\n@media (prefers-color-scheme: light) {\n :root {\n${lightColorBlock.replace(/^ {2}/gm, ' ')}\n }\n}\n`\n}\n","import { createContext, useCallback, useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { ThemeMode, UseThemeModeReturn } from './types'\n\nexport const ThemeContext = createContext<UseThemeModeReturn | null>(null)\n\ninterface ThemeProviderProps {\n children: ReactNode\n defaultMode?: ThemeMode\n storageKey?: string\n}\n\nconst TOGGLE_ORDER: readonly ThemeMode[] = ['dark', 'light', 'system'] as const\n\nfunction getSystemPreference(): 'dark' | 'light' {\n if (typeof window === 'undefined') return 'dark'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction getInitialMode(storageKey: string, defaultMode: ThemeMode): ThemeMode {\n if (typeof window === 'undefined') return defaultMode\n const stored = localStorage.getItem(storageKey)\n if (stored === 'dark' || stored === 'light' || stored === 'system') {\n return stored\n }\n return defaultMode\n}\n\nfunction resolveMode(mode: ThemeMode): 'dark' | 'light' {\n if (mode === 'system') return getSystemPreference()\n return mode\n}\n\nexport function ThemeProvider({\n children,\n defaultMode = 'system',\n storageKey = 'camstack-theme-mode',\n}: ThemeProviderProps) {\n const [mode, setModeState] = useState<ThemeMode>(() => getInitialMode(storageKey, defaultMode))\n const [resolvedMode, setResolvedMode] = useState<'dark' | 'light'>(() => resolveMode(mode))\n\n const setMode = useCallback(\n (newMode: ThemeMode) => {\n setModeState(newMode)\n setResolvedMode(resolveMode(newMode))\n if (typeof window !== 'undefined') {\n localStorage.setItem(storageKey, newMode)\n }\n },\n [storageKey],\n )\n\n const toggleMode = useCallback(() => {\n const currentIndex = TOGGLE_ORDER.indexOf(mode)\n const nextIndex = (currentIndex + 1) % TOGGLE_ORDER.length\n setMode(TOGGLE_ORDER[nextIndex] ?? 'dark')\n }, [mode, setMode])\n\n // Apply CSS class on document.documentElement\n useEffect(() => {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n root.classList.remove('dark', 'light')\n // Always apply the resolved class — even in 'system' mode, the CSS\n // variables need the .dark or .light class to activate\n root.classList.add(resolvedMode)\n }, [mode, resolvedMode])\n\n // Listen for system theme changes when in 'system' mode\n useEffect(() => {\n if (typeof window === 'undefined' || mode !== 'system') return\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n const handleChange = () => {\n setResolvedMode(getSystemPreference())\n }\n\n mediaQuery.addEventListener('change', handleChange)\n return () => mediaQuery.removeEventListener('change', handleChange)\n }, [mode])\n\n const value = useMemo<UseThemeModeReturn>(\n () => ({ mode, resolvedMode, setMode, toggleMode }),\n [mode, resolvedMode, setMode, toggleMode],\n )\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>\n}\n","import { useContext } from 'react'\nimport { ThemeContext } from './theme-provider'\nimport type { UseThemeModeReturn } from './types'\n\nexport function useThemeMode(): UseThemeModeReturn {\n const context = useContext(ThemeContext)\n if (!context) {\n throw new Error('useThemeMode must be used within a ThemeProvider')\n }\n return context\n}\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","/**\n * Responsive design tokens — three-tier system.\n *\n * The admin-ui targets three width tiers; every component should pick\n * the right token from this file instead of hand-coding breakpoints.\n * Adopting the tokens uniformly is what makes the app feel consistent\n * across operator devices (mobile / tablet / desktop) and what unlocks\n * targeted tuning (e.g. shrink every label by 1px in one place).\n *\n * Tier definitions (Tailwind breakpoints):\n *\n * • **L1 — Compact** (`< 640px`, default = mobile portrait)\n * Single column, tight padding, smallest text, icon-only buttons\n * where labels can be inferred. The operator can still see every\n * stat / action — no horizontal scroll, no clipped text. The user\n * directive: \"molta informazione in poco spazio quando la width è\n * bassa.\"\n *\n * • **L2 — Standard** (`sm` — `640–1023px`, tablet + small laptop)\n * 2-column grids, side panels become visible, button labels return.\n * Targets ~768px–1024px viewports — the most common operator sizes.\n *\n * • **L3 — Spacious** (`lg+` — `≥ 1024px`, desktop)\n * 4-column grids, generous padding, full-width header text,\n * side-by-side composite layouts. The operator has elbow room.\n *\n * Conventions:\n * - **Always start from L1** — the bare class is always the compact\n * variant, then `sm:` adds room at 640px, `lg:` at 1024px. No\n * desktop-first breakpoints; no max-width queries.\n * - **Token strings are static** — kept as `as const` so callers can\n * compose them via `cn()` / template literals without running a\n * class generator at runtime.\n * - **Pair the token with a comment** — the comment in the file\n * names every breakpoint it crosses, so a reader can predict the\n * layout without going to Tailwind docs.\n */\n\n// ---------------------------------------------------------------------------\n// Spacing — section / card / row padding + grid gap\n// ---------------------------------------------------------------------------\n\n/** Container padding for a card-style section (header + body). */\nexport const SECTION_CARD = 'rounded-lg border border-border bg-surface overflow-hidden' as const\n\n/** Header strip inside a card (between border-b lines). */\nexport const SECTION_HEADER = 'border-b border-border px-3 sm:px-4 py-1.5 sm:py-2' as const\n\n/** Body padding for a card-style section. */\nexport const SECTION_BODY = 'p-2 sm:p-3 lg:p-4' as const\n\n/** Gap between cards in a vertical stack. */\nexport const STACK_GAP = 'space-y-3 sm:space-y-4' as const\n\n/** Gap between cards in a grid (4 cells / row at lg). */\nexport const GRID_GAP = 'gap-2 sm:gap-3' as const\n\n/** Row padding inside a divided list (e.g. InfoRow). */\nexport const LIST_ROW = 'px-3 sm:px-4 py-1.5 sm:py-2' as const\n\n// ---------------------------------------------------------------------------\n// Grids — opinionated column counts per tier\n// ---------------------------------------------------------------------------\n\n/** 1-up at L1, 2-up at L2, 4-up at L3 — quick-stat row. */\nexport const GRID_QUICK_STATS = 'grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-4' as const\n\n/** 1-up at L1, 2-up at L2+ — paired panels (motion + detection rules). */\nexport const GRID_PAIRED = 'grid grid-cols-1 lg:grid-cols-2' as const\n\n/** Side-by-side layout that stacks below md (canvas + side panel). */\nexport const SPLIT_PANEL_OUTER = 'flex flex-col-reverse md:flex-row' as const\n\n/** Sidebar narrow lane in a SPLIT_PANEL_OUTER layout. */\nexport const SPLIT_PANEL_SIDE = 'w-full md:w-44 lg:w-52 md:flex-shrink-0 border-b md:border-b-0 md:border-l border-border' as const\n\n// ---------------------------------------------------------------------------\n// Typography — labels, values, sub-text\n// ---------------------------------------------------------------------------\n\n/** Section header label (uppercase tracking-wider). */\nexport const TEXT_SECTION_LABEL =\n 'text-[10px] sm:text-[11px] font-semibold text-foreground uppercase tracking-wider' as const\n\n/** Field label inside a row. */\nexport const TEXT_FIELD_LABEL = 'text-[11px] sm:text-xs text-foreground' as const\n\n/** Sub-label / hint text. */\nexport const TEXT_HINT = 'text-[10px] text-foreground-subtle' as const\n\n/** Primary value (a metric, badge, …). */\nexport const TEXT_VALUE = 'text-[11px] sm:text-xs font-medium text-foreground' as const\n\n/** Big metric value (StatCard). */\nexport const TEXT_METRIC = 'text-base sm:text-lg font-semibold leading-tight text-foreground' as const\n\n// ---------------------------------------------------------------------------\n// Buttons — compact at L1, comfortable at L2+\n// ---------------------------------------------------------------------------\n\n/** Default compact button. */\nexport const BTN_COMPACT =\n 'inline-flex items-center justify-center gap-1 rounded border border-border bg-surface px-1.5 py-0.5 sm:px-2 sm:py-1 text-[10px] sm:text-[11px] font-medium text-foreground hover:bg-surface-hover transition-colors disabled:opacity-40' as const\n\n/** Primary compact button. */\nexport const BTN_COMPACT_PRIMARY =\n 'inline-flex items-center justify-center gap-1 rounded border border-primary/40 bg-primary/15 px-1.5 py-0.5 sm:px-2 sm:py-1 text-[10px] sm:text-[11px] font-medium text-primary hover:bg-primary/25 transition-colors disabled:opacity-40' as const\n\n/** Danger compact button. */\nexport const BTN_COMPACT_DANGER =\n 'inline-flex items-center justify-center gap-1 rounded border border-danger/40 bg-danger/10 px-1.5 py-0.5 sm:px-2 sm:py-1 text-[10px] sm:text-[11px] font-medium text-danger hover:bg-danger/20 transition-colors disabled:opacity-40' as const\n\n/** Warning compact button (e.g. cancel-drawing). */\nexport const BTN_COMPACT_WARNING =\n 'inline-flex items-center justify-center gap-1 rounded border border-warning/40 bg-warning/10 px-1.5 py-0.5 sm:px-2 sm:py-1 text-[10px] sm:text-[11px] font-medium text-warning hover:bg-warning/20 transition-colors disabled:opacity-40' as const\n\n// ---------------------------------------------------------------------------\n// Inputs — height matches the compact button so they line up in a row\n// ---------------------------------------------------------------------------\n\n/** Compact text/select/number input. */\nexport const INPUT_COMPACT =\n 'w-full rounded border border-border bg-background px-1.5 py-0.5 sm:px-2 sm:py-1 text-[11px] sm:text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none' as const\n\n/** Chip-style toggle (zone / class selectors in ZoneRulesEditor). */\nexport const CHIP_BASE =\n 'inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium transition-colors' as const\n\nexport const CHIP_ACTIVE = 'border-primary/50 bg-primary/15 text-primary' as const\n\nexport const CHIP_INACTIVE = 'border-border bg-surface text-foreground-subtle hover:bg-surface-hover' as const\n","import type {\n AgentAddonConfig,\n CameraStepOverridePatch,\n PipelineSchema,\n PipelineAddonSchema,\n PipelineModelOption,\n} from '@camstack/types'\n\nexport interface MirrorSource {\n readonly nodeId: string\n readonly engine: { readonly format: string }\n readonly defaults: Readonly<Record<string, AgentAddonConfig>>\n}\n\nexport interface MirrorInput {\n readonly source: MirrorSource\n readonly target: MirrorSource\n readonly catalog: PipelineSchema\n readonly addonIds: readonly string[]\n}\n\nexport type MirrorOutcome = 'exact' | 'mapped' | 'skip'\n\nexport interface MirrorResultEntry {\n readonly addonId: string\n readonly outcome: MirrorOutcome\n readonly modelId: string | null\n readonly reason?: string\n readonly patch: CameraStepOverridePatch | null\n}\n\nfunction findAddonInCatalog(catalog: PipelineSchema, addonId: string): PipelineAddonSchema | null {\n for (const slot of catalog.slots) {\n for (const addon of slot.addons) {\n if (addon.id === addonId) return addon\n }\n }\n return null\n}\n\nfunction findModel(addon: PipelineAddonSchema, modelId: string): PipelineModelOption | null {\n return addon.models.find((m) => m.id === modelId) ?? null\n}\n\nfunction firstModelFor(addon: PipelineAddonSchema, format: string): PipelineModelOption | null {\n return addon.models.find((m) => Boolean(m.formats[format])) ?? null\n}\n\nfunction dropModelSpecific(\n settings: Readonly<Record<string, unknown>>,\n targetAddon: PipelineAddonSchema,\n): Record<string, unknown> {\n const allowedKeys = new Set((targetAddon.configSchema ?? []).map((f) => f.key))\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(settings)) {\n if (allowedKeys.has(k)) out[k] = v\n }\n return out\n}\n\nexport function mirror(input: MirrorInput): readonly MirrorResultEntry[] {\n const { source, target, catalog, addonIds } = input\n const out: MirrorResultEntry[] = []\n\n for (const addonId of addonIds) {\n const srcCfg = source.defaults[addonId]\n if (!srcCfg) {\n out.push({ addonId, outcome: 'skip', modelId: null, reason: 'no source entry', patch: null })\n continue\n }\n const targetAddon = findAddonInCatalog(catalog, addonId)\n if (!targetAddon) {\n out.push({ addonId, outcome: 'skip', modelId: null, reason: 'addon not in target catalog', patch: null })\n continue\n }\n const srcModel = findModel(targetAddon, srcCfg.modelId)\n const canUseSource = srcModel !== null && Boolean(srcModel.formats[target.engine.format])\n\n let chosenModelId: string\n let outcome: MirrorOutcome\n\n if (canUseSource) {\n chosenModelId = srcCfg.modelId\n outcome = 'exact'\n } else {\n const fallback = firstModelFor(targetAddon, target.engine.format)\n if (!fallback) {\n out.push({ addonId, outcome: 'skip', modelId: null, reason: 'no compatible model for target format', patch: null })\n continue\n }\n chosenModelId = fallback.id\n outcome = 'mapped'\n }\n\n const patch: CameraStepOverridePatch = {\n enabled: srcCfg.enabled,\n modelId: chosenModelId,\n settings: dropModelSpecific(srcCfg.settings, targetAddon),\n }\n\n out.push({ addonId, outcome, modelId: chosenModelId, patch })\n }\n\n return out\n}\n","/**\n * phase-config — canonical visual config for CameraPhase values.\n *\n * Single source of truth for label, color classes, dot class, and\n * lucide icon name. Every UI surface (PhaseBadge, CameraStatusStrip,\n * CameraAssignmentsTable, DeviceDetail, OverviewTab, NodeLiveTab)\n * imports from here instead of hardcoding phase → style mappings.\n *\n * Icon components are NOT imported here (would pull lucide-react into\n * the config module). Consumers import the icon by name themselves:\n * `import { [cfg.icon] } from 'lucide-react'`\n * or use the provided `PhaseIcon` component from `./phase-icon.tsx`.\n */\nimport type { CameraPhase } from '@camstack/types'\n\nexport interface PhaseVisual {\n /** Human-readable label (e.g. \"Active\", \"Load-Shed\"). */\n readonly label: string\n /** Tailwind text color class (e.g. \"text-success\"). */\n readonly textColor: string\n /** Tailwind border+bg classes for pill/badge containers. */\n readonly badgeClass: string\n /** Tailwind class for the status dot (circle indicator). */\n readonly dotClass: string\n /** Lucide icon name to use for this phase. */\n readonly icon: 'Activity' | 'Eye' | 'AlertTriangle' | 'PauseCircle' | 'PowerOff'\n}\n\nexport const PHASE_CONFIG: Record<CameraPhase, PhaseVisual> = {\n idle: {\n label: 'Idle',\n textColor: 'text-foreground-subtle',\n badgeClass: 'border-border bg-surface-hover text-foreground-subtle',\n dotClass: 'bg-gray-400',\n icon: 'PowerOff',\n },\n active: {\n label: 'Active',\n textColor: 'text-success',\n badgeClass: 'border-success/40 bg-success/10 text-success',\n dotClass: 'bg-red-500 animate-pulse',\n icon: 'Activity',\n },\n watching: {\n label: 'Watching',\n textColor: 'text-foreground-subtle',\n badgeClass: 'border-border bg-surface-hover text-foreground-subtle',\n dotClass: 'bg-emerald-500',\n icon: 'Eye',\n },\n 'load-shed': {\n label: 'Load-Shed',\n textColor: 'text-amber-500',\n badgeClass: 'border-amber-500/40 bg-amber-500/10 text-amber-500',\n dotClass: 'bg-amber-500',\n icon: 'AlertTriangle',\n },\n paused: {\n label: 'Paused',\n textColor: 'text-gray-400',\n badgeClass: 'border-gray-500/40 bg-gray-500/10 text-gray-400',\n dotClass: 'bg-gray-400',\n icon: 'PauseCircle',\n },\n}\n\n/** Look up phase config with a safe fallback to `watching` for unknown values. */\nexport function getPhaseVisual(phase: string): PhaseVisual {\n return PHASE_CONFIG[phase as CameraPhase] ?? PHASE_CONFIG.watching\n}\n","/**\n * Cross-bundle React Context sharing.\n *\n * Addon page bundles (benchmark, etc.) ship their own bundled copy of\n * `@camstack/ui-library`. Without sharing, each bundle calls\n * `createContext()` and gets a fresh Context instance — so when the\n * bundle's hook reads from this Context, it doesn't match the host\n * admin-ui's <Provider> tree, and `useContext()` returns the default\n * value (typically `null`) which often causes a `must be used within\n * Provider` throw.\n *\n * This helper stashes Context instances on `globalThis` keyed by a\n * unique name, so the SECOND-evaluated copy reuses the host's\n * instance instead of creating a duplicate.\n *\n * Boot order:\n * 1. admin-ui's main.tsx evaluates first → globalThis Map is empty\n * → creates Context, stores it under `name`.\n * 2. Addon bundle evaluates later → globalThis Map has the entry\n * → returns the host's Context.\n *\n * Critical: pick UNIQUE `name`s. Two distinct contexts with the same\n * name will silently collide (and TypeScript can't catch it because\n * the Map is typed as `Context<unknown>`).\n */\nimport { createContext, type Context } from 'react'\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __camstackSharedContexts: Map<string, Context<unknown>> | undefined\n}\n\nexport function createSharedContext<T>(name: string, defaultValue: T): Context<T> {\n if (typeof globalThis === 'undefined') {\n return createContext<T>(defaultValue)\n }\n const existingMap = globalThis.__camstackSharedContexts\n const map: Map<string, Context<unknown>> = existingMap ?? new Map<string, Context<unknown>>()\n if (!existingMap) {\n globalThis.__camstackSharedContexts = map\n }\n const existing = map.get(name)\n if (existing) {\n return existing as Context<T>\n }\n const ctx = createContext<T>(defaultValue)\n map.set(name, ctx as Context<unknown>)\n return ctx\n}\n","/**\n * Module Federation runtime — host-side init guard, shared across\n * `WidgetRegistryProvider` (widget remotes) and admin-ui's\n * `AddonPageLoader` (page remotes). Both kinds of remote share the same\n * MF runtime instance once initialized — `init` is idempotent and\n * `registerRemotes`/`loadRemote` will work for any name registered after\n * boot.\n *\n * Why a shared module: the production admin-ui build wires the host\n * through `@module-federation/vite`'s injected bootstrap, which seeds\n * the runtime against the host's bundled instances automatically. In\n * dev mode the plugin is intentionally skipped (it conflicts with\n * Vite's CJS dep prebundler — see `addon-admin-ui/vite.config.ts`), so\n * we manually init the runtime AND populate the shared module cache\n * here.\n *\n * The shared module cache is the critical bit. Every remote chunk that\n * `import: false`-shareds a workspace package emits a top-level guard:\n *\n * const exportModule = __mfModuleCache.share[pkg]\n * if (exportModule === undefined)\n * throw new Error('imported before federation bootstrap finished')\n *\n * (see `node_modules/@module-federation/vite/lib/index.mjs` line 1233\n * for the generated code). The cache lives on\n * `globalThis['__mf_module_cache__']` and must be populated with the\n * actual namespace object for each shared package BEFORE the remote\n * evaluates. In production the plugin's host-auto-init module\n * synchronously imports the local instance and assigns it; in dev we\n * do the equivalent here. Without this step the remote fetches its\n * remoteEntry, evaluates the loadShare wrapper, and hits the throw.\n *\n * - npm packages (react, react-dom, @tanstack/react-query, @trpc/*)\n * are read off the bundler's import graph via namespace imports.\n * - workspace packages (`@camstack/{ui-library,sdk,types}`) come off\n * `window.__camstack{UiLibrary,Sdk,Types}` globals set by\n * `addon-admin-ui/src/main.tsx` to avoid double-bundling them here.\n *\n * The runtime `init({ shared: ... })` call is still required so that\n * `loadRemote('name/...')` can resolve the same shared instance through\n * the runtime's own share-scope map. The cache populated here is just\n * the synchronous fast path that the per-remote `loadShare` wrappers\n * depend on.\n *\n * No-op in production builds — `getInstance()` is non-null because the\n * plugin's host bootstrap has already created and seeded the runtime.\n */\n// We use `init()` (marked @deprecated upstream) instead of `createInstance()`\n// because in MF runtime 2.4.0 the standalone-imported `registerRemotes` /\n// `loadRemote` functions read from a module-private `FederationInstance`\n// var that ONLY `init()` populates. `createInstance()` only sets the\n// global federation instance, leaving the standalone exports asserting on\n// a null local — manifests as runtime-009 \"Please call createInstance\".\n// See node_modules/@module-federation/runtime/dist/index.cjs.js source map.\nimport { init, getInstance } from '@module-federation/runtime'\n\nimport * as __mfHostReact from 'react'\nimport * as __mfHostReactDOM from 'react-dom'\nimport * as __mfHostReactDOMClient from 'react-dom/client'\nimport * as __mfHostReactJsxRuntime from 'react/jsx-runtime'\nimport * as __mfHostTanstackQuery from '@tanstack/react-query'\nimport * as __mfHostTrpcClient from '@trpc/client'\nimport * as __mfHostTrpcReactQuery from '@trpc/react-query'\n\ntype GlobalKey = '__camstackUiLibrary' | '__camstackSdk' | '__camstackTypes'\n\nfunction readHostGlobal(name: GlobalKey): Record<string, unknown> {\n const win = (typeof globalThis !== 'undefined' ? globalThis : undefined) as { [k: string]: unknown } | undefined\n const value = win?.[name]\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : {}\n}\n\nconst sharedConfig = { singleton: true, requiredVersion: false, eager: true } as const\nconst npmShared = (lib: () => unknown) => ({\n version: '0.0.0' as const,\n scope: 'default' as const,\n lib: lib as () => Record<string, unknown>,\n shareConfig: sharedConfig,\n})\n\n// Must match `MODULE_CACHE_GLOBAL_KEY` in\n// `@module-federation/vite/lib/index.mjs` — the per-remote loadShare\n// wrappers read from `globalThis[this exact key]`. If the constant\n// drifts in a future MF version, update this string.\nconst MODULE_CACHE_GLOBAL_KEY = '__mf_module_cache__' as const\n\ninterface ModuleCache {\n share: Record<string, unknown>\n remote: Record<string, unknown>\n}\n\nfunction getModuleCache(): ModuleCache {\n const g = globalThis as { [k: string]: unknown }\n const existing = g[MODULE_CACHE_GLOBAL_KEY]\n if (existing && typeof existing === 'object') {\n const cache = existing as Partial<ModuleCache>\n cache.share ??= {}\n cache.remote ??= {}\n return cache as ModuleCache\n }\n const fresh: ModuleCache = { share: {}, remote: {} }\n g[MODULE_CACHE_GLOBAL_KEY] = fresh\n return fresh\n}\n\n// Synchronous share cache the per-remote `loadShare` wrappers read from.\n// Each entry must be a module namespace object (the result of\n// `import * as Foo from 'pkg'`) — the wrappers pluck named exports off\n// it via destructuring + re-export. Generated by the MF Vite plugin's\n// `writeLoadShareModule` (line ~1220 of `index.mjs`).\nfunction populateShareCache(): void {\n const cache = getModuleCache()\n cache.share['react'] ??= __mfHostReact\n cache.share['react-dom'] ??= __mfHostReactDOM\n cache.share['react-dom/client'] ??= __mfHostReactDOMClient\n cache.share['react/jsx-runtime'] ??= __mfHostReactJsxRuntime\n cache.share['@tanstack/react-query'] ??= __mfHostTanstackQuery\n cache.share['@trpc/client'] ??= __mfHostTrpcClient\n cache.share['@trpc/react-query'] ??= __mfHostTrpcReactQuery\n cache.share['@camstack/ui-library'] ??= readHostGlobal('__camstackUiLibrary')\n cache.share['@camstack/sdk'] ??= readHostGlobal('__camstackSdk')\n cache.share['@camstack/types'] ??= readHostGlobal('__camstackTypes')\n}\n\nexport function ensureMfHostInit(): void {\n // The share cache is populated unconditionally — `??=` makes it\n // idempotent across HMR re-evaluations and across multiple callers.\n // `createInstance` is gated on `getInstance()` because creating a\n // second runtime with the same name would log a warning and shadow\n // the first one's remotes registry.\n populateShareCache()\n if (getInstance() !== null) return\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- intentional, see import comment\n init({\n name: 'admin_ui_host',\n remotes: [],\n shared: {\n 'react': npmShared(() => __mfHostReact),\n 'react-dom': npmShared(() => __mfHostReactDOM),\n 'react-dom/client': npmShared(() => __mfHostReactDOMClient),\n 'react/jsx-runtime': npmShared(() => __mfHostReactJsxRuntime),\n '@tanstack/react-query': npmShared(() => __mfHostTanstackQuery),\n '@trpc/client': npmShared(() => __mfHostTrpcClient),\n '@trpc/react-query': npmShared(() => __mfHostTrpcReactQuery),\n '@camstack/ui-library': npmShared(() => readHostGlobal('__camstackUiLibrary')),\n '@camstack/sdk': npmShared(() => readHostGlobal('__camstackSdk')),\n '@camstack/types': npmShared(() => readHostGlobal('__camstackTypes')),\n },\n })\n}\n","import { Ship, Shield, Radio, Home, Cast, type LucideIcon } from 'lucide-react'\n\nexport type ProviderType = 'frigate' | 'scrypted' | 'reolink' | 'homeAssistant' | 'rtsp'\n\nexport const providerIcons: Record<ProviderType, LucideIcon> = {\n frigate: Ship,\n scrypted: Shield,\n reolink: Radio,\n homeAssistant: Home,\n rtsp: Cast,\n}\n","import { CircleCheck, CircleX, CircleAlert, CircleHelp, type LucideIcon } from 'lucide-react'\n\nexport type StatusType = 'online' | 'offline' | 'degraded' | 'unknown'\n\nexport const statusIcons: Record<StatusType, LucideIcon> = {\n online: CircleCheck,\n offline: CircleX,\n degraded: CircleAlert,\n unknown: CircleHelp,\n}\n","import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center rounded-md font-medium transition-colors cursor-pointer disabled:opacity-50 disabled:pointer-events-none',\n {\n variants: {\n variant: {\n primary: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary: 'bg-surface text-foreground hover:bg-surface-hover',\n ghost: 'hover:bg-surface-hover text-foreground-muted',\n danger: 'bg-danger text-white hover:bg-danger/90',\n outline: 'border border-border bg-transparent hover:bg-surface-hover',\n },\n size: {\n sm: 'h-7 px-2.5 text-xs gap-1.5',\n md: 'h-8 px-3 text-sm gap-2',\n lg: 'h-9 px-4 text-sm gap-2',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'sm',\n },\n }\n)\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n )\n }\n)\n\nButton.displayName = 'Button'\n","import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type LucideIcon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nconst iconButtonVariants = cva(\n 'inline-flex items-center justify-center rounded-md font-medium transition-colors cursor-pointer disabled:opacity-50 disabled:pointer-events-none',\n {\n variants: {\n variant: {\n primary: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary: 'bg-surface text-foreground hover:bg-surface-hover',\n ghost: 'hover:bg-surface-hover text-foreground-muted',\n danger: 'bg-danger text-white hover:bg-danger/90',\n outline: 'border border-border bg-transparent hover:bg-surface-hover',\n },\n size: {\n sm: 'h-7 w-7',\n md: 'h-8 w-8',\n lg: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'sm',\n },\n }\n)\n\nexport interface IconButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'>,\n VariantProps<typeof iconButtonVariants> {\n icon: LucideIcon\n 'aria-label': string\n}\n\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ className, variant, size, icon: Icon, ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(iconButtonVariants({ variant, size }), className)}\n {...props}\n >\n <Icon className=\"h-4 w-4\" />\n </button>\n )\n }\n)\n\nIconButton.displayName = 'IconButton'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst badgeVariants = cva(\n 'inline-flex items-center rounded-full text-xs font-medium px-2 py-0.5',\n {\n variants: {\n variant: {\n default: 'bg-surface-hover text-foreground',\n success: 'bg-success/15 text-success',\n warning: 'bg-warning/15 text-warning',\n danger: 'bg-danger/15 text-danger',\n info: 'bg-info/15 text-info',\n },\n styleVariant: {\n solid: '',\n outline: 'border bg-transparent',\n },\n },\n defaultVariants: {\n variant: 'default',\n styleVariant: 'solid',\n },\n }\n)\n\nexport interface BadgeProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, 'style'>,\n VariantProps<typeof badgeVariants> {\n style?: 'solid' | 'outline'\n}\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant, style, ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(badgeVariants({ variant, styleVariant: style }), className)}\n {...props}\n />\n )\n }\n)\n\nBadge.displayName = 'Badge'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst cardVariants = cva('rounded-lg p-3', {\n variants: {\n variant: {\n flat: 'bg-surface',\n bordered: 'bg-surface border border-border',\n },\n },\n defaultVariants: {\n variant: 'bordered',\n },\n})\n\nexport interface CardProps\n extends HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof cardVariants> {}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(cardVariants({ variant }), className)}\n {...props}\n />\n )\n }\n)\n\nCard.displayName = 'Card'\n","/**\n * CollapsibleCard — neutral card with a clickable header + optional\n * expanded body. Same visual language as `FormBuilder` sections so\n * every settings-style container in the app shares one style\n * (`rounded-lg border border-border bg-surface`, no shadow, no\n * coloured left accent).\n *\n * Used by `PipelineStep`; reusable for any \"click to expand\" settings\n * row where we want FormBuilder-matching chrome.\n */\nimport { type ReactNode } from 'react'\nimport { ChevronRight, ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface CollapsibleCardProps {\n readonly expanded: boolean\n readonly onExpandedChange: (next: boolean) => void\n /** Rendered inside the clickable header row, to the right of the chevron. */\n readonly header: ReactNode\n /** Expanded body — rendered below a subtle divider when `expanded === true`. */\n readonly children?: ReactNode\n /** Dims the entire card — for steps flagged as disabled/inactive. */\n readonly dimmed?: boolean\n /** Hide the chevron (header still click-toggles). Useful for always-expanded views. */\n readonly hideChevron?: boolean\n readonly className?: string\n}\n\nexport function CollapsibleCard({\n expanded,\n onExpandedChange,\n header,\n children,\n dimmed = false,\n hideChevron = false,\n className,\n}: CollapsibleCardProps) {\n return (\n <div\n className={cn(\n 'rounded-lg border border-border bg-surface overflow-hidden',\n dimmed && 'opacity-[0.45]',\n className,\n )}\n >\n <div\n role=\"button\"\n tabIndex={0}\n className=\"flex items-center gap-2.5 px-3 py-2.5 cursor-pointer select-none\"\n onClick={() => onExpandedChange(!expanded)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onExpandedChange(!expanded)\n }\n }}\n >\n {!hideChevron && (\n <span className=\"text-foreground-subtle shrink-0\">\n {expanded ? <ChevronDown className=\"h-4 w-4\" /> : <ChevronRight className=\"h-4 w-4\" />}\n </span>\n )}\n {header}\n </div>\n {expanded && children && (\n <div className=\"border-t border-border px-3 py-3\">\n {children}\n </div>\n )}\n </div>\n )\n}\n","import { type LabelHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {}\n\nexport const Label = forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => {\n return (\n <label\n ref={ref}\n className={cn(\n 'text-[10px] uppercase tracking-wider text-foreground-muted font-medium',\n className\n )}\n {...props}\n />\n )\n }\n)\n\nLabel.displayName = 'Label'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst separatorVariants = cva('', {\n variants: {\n orientation: {\n horizontal: 'h-px w-full bg-border-subtle',\n vertical: 'w-px h-full bg-border-subtle',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n})\n\nexport interface SeparatorProps\n extends HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof separatorVariants> {}\n\nexport const Separator = forwardRef<HTMLDivElement, SeparatorProps>(\n ({ className, orientation, ...props }, ref) => {\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cn(separatorVariants({ orientation }), className)}\n {...props}\n />\n )\n }\n)\n\nSeparator.displayName = 'Separator'\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('animate-pulse bg-surface-hover rounded-md h-4 w-full', className)}\n {...props}\n />\n )\n }\n)\n\nSkeleton.displayName = 'Skeleton'\n","import { type InputHTMLAttributes, type ReactNode, forwardRef } from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\nconst inputVariants = cva(\n 'h-7 w-full px-2.5 text-xs bg-surface border rounded-md text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-primary transition-colors',\n {\n variants: {\n state: {\n default: 'border-border',\n error: 'border-danger',\n },\n },\n defaultVariants: {\n state: 'default',\n },\n }\n)\n\nexport interface InputProps\n extends InputHTMLAttributes<HTMLInputElement>,\n VariantProps<typeof inputVariants> {\n leftSlot?: ReactNode\n rightSlot?: ReactNode\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n ({ className, state, leftSlot, rightSlot, ...props }, ref) => {\n if (leftSlot || rightSlot) {\n return (\n <div className=\"relative flex items-center w-full\">\n {leftSlot && (\n <div className=\"absolute left-2.5 flex items-center pointer-events-none\">\n {leftSlot}\n </div>\n )}\n <input\n ref={ref}\n className={cn(\n inputVariants({ state }),\n leftSlot ? 'pl-7' : '',\n rightSlot ? 'pr-7' : '',\n className\n )}\n {...props}\n />\n {rightSlot && (\n <div className=\"absolute right-2.5 flex items-center pointer-events-none\">\n {rightSlot}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <input\n ref={ref}\n className={cn(inputVariants({ state }), className)}\n {...props}\n />\n )\n }\n)\n\nInput.displayName = 'Input'\n","import { type SelectHTMLAttributes, forwardRef } from 'react'\nimport { ChevronDown } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface SelectOption {\n value: string\n label: string\n}\n\nexport interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {\n options: SelectOption[]\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, options, ...props }, ref) => {\n return (\n <div className=\"relative w-full\">\n <select\n ref={ref}\n className={cn(\n 'h-7 w-full px-2.5 text-xs bg-surface border border-border rounded-md text-foreground appearance-none pr-7 focus:outline-none focus:ring-1 focus:ring-primary',\n className\n )}\n {...props}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <div className=\"absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none text-foreground-muted\">\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </div>\n </div>\n )\n }\n)\n\nSelect.displayName = 'Select'\n","import { type InputHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, ...props }, ref) => {\n return (\n <input\n ref={ref}\n type=\"checkbox\"\n className={cn(\n 'w-3.5 h-3.5 rounded-sm border border-border accent-primary',\n className\n )}\n {...props}\n />\n )\n }\n)\n\nCheckbox.displayName = 'Checkbox'\n","import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface SwitchProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {\n checked: boolean\n onCheckedChange: (checked: boolean) => void\n label?: string\n}\n\nexport const Switch = forwardRef<HTMLButtonElement, SwitchProps>(\n ({ className, checked, onCheckedChange, label, ...props }, ref) => {\n return (\n <button\n ref={ref}\n role=\"switch\"\n aria-checked={checked}\n type=\"button\"\n onClick={() => onCheckedChange(!checked)}\n className={cn('inline-flex items-center gap-2', className)}\n {...props}\n >\n <span\n className={cn(\n 'w-8 h-4 rounded-full transition-colors',\n checked ? 'bg-primary' : 'bg-surface-hover'\n )}\n >\n <span\n className={cn(\n 'block w-3.5 h-3.5 rounded-full bg-white transition-transform',\n checked ? 'translate-x-4' : 'translate-x-0.5'\n )}\n />\n </span>\n {label && <span className=\"text-xs text-foreground\">{label}</span>}\n </button>\n )\n }\n)\n\nSwitch.displayName = 'Switch'\n","import {\n type HTMLAttributes,\n type ReactNode,\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/cn'\n\ninterface DialogContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n contentId: string\n}\n\nconst DialogContext = createContext<DialogContextValue | null>(null)\n\nfunction useDialogContext() {\n const ctx = useContext(DialogContext)\n if (!ctx) throw new Error('Dialog compound components must be used within <Dialog>')\n return ctx\n}\n\n/* ── Root ── */\n\ninterface DialogProps {\n children: ReactNode\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nexport function Dialog({ children, open: controlledOpen, onOpenChange }: DialogProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false)\n const open = controlledOpen ?? uncontrolledOpen\n const contentId = useId()\n\n const setOpen = useCallback(\n (next: boolean) => {\n onOpenChange?.(next)\n if (controlledOpen === undefined) setUncontrolledOpen(next)\n },\n [controlledOpen, onOpenChange]\n )\n\n return (\n <DialogContext.Provider value={{ open, setOpen, contentId }}>\n {children}\n </DialogContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function DialogTrigger({ children, ...props }: HTMLAttributes<HTMLButtonElement>) {\n const { setOpen } = useDialogContext()\n return (\n <button type=\"button\" onClick={() => setOpen(true)} {...props}>\n {children}\n </button>\n )\n}\n\n/* ── Content ── */\n\nconst contentVariants = cva(\n 'bg-background-elevated border border-border rounded-lg p-4 backdrop:bg-black/50 backdrop:backdrop-blur-sm max-w-[calc(100vw-2rem)] max-h-[calc(100dvh-2rem)] overflow-y-auto',\n {\n variants: {\n width: {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n },\n },\n defaultVariants: { width: 'md' },\n }\n)\n\nexport interface DialogContentProps\n extends HTMLAttributes<HTMLDialogElement>,\n VariantProps<typeof contentVariants> {}\n\nexport const DialogContent = forwardRef<HTMLDialogElement, DialogContentProps>(\n ({ className, width, children, ...props }, ref) => {\n const { open, setOpen, contentId } = useDialogContext()\n const innerRef = useRef<HTMLDialogElement>(null)\n const dialogRef = (ref as React.RefObject<HTMLDialogElement>) ?? innerRef\n\n useEffect(() => {\n const el = dialogRef.current\n if (!el) return\n if (open && !el.open) el.showModal()\n if (!open && el.open) el.close()\n }, [open, dialogRef])\n\n const handleClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === e.currentTarget) setOpen(false)\n }\n\n return (\n <dialog\n ref={dialogRef}\n id={contentId}\n className={cn(contentVariants({ width }), 'w-full', className)}\n onClick={handleClick}\n onClose={() => setOpen(false)}\n {...props}\n >\n {children}\n </dialog>\n )\n }\n)\n\nDialogContent.displayName = 'DialogContent'\n\n/* ── Header / Footer / Title / Description ── */\n\nexport function DialogHeader({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('flex flex-col gap-1 mb-3', className)} {...props} />\n}\n\nexport function DialogFooter({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('flex justify-end gap-2 mt-4', className)} {...props} />\n}\n\nexport function DialogTitle({ className, ...props }: HTMLAttributes<HTMLHeadingElement>) {\n return <h2 className={cn('text-sm font-semibold text-foreground', className)} {...props} />\n}\n\nexport function DialogDescription({ className, ...props }: HTMLAttributes<HTMLParagraphElement>) {\n return <p className={cn('text-xs text-foreground-muted', className)} {...props} />\n}\n","import {\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { type LucideIcon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\ninterface DropdownContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n triggerId: string\n contentId: string\n /** Live ref to the trigger element so the portal-rendered content can anchor to it. */\n triggerRef: React.RefObject<HTMLButtonElement | null>\n}\n\nconst DropdownContext = createContext<DropdownContextValue | null>(null)\n\nfunction useDropdownContext() {\n const ctx = useContext(DropdownContext)\n if (!ctx) throw new Error('Dropdown compound components must be used within <Dropdown>')\n return ctx\n}\n\n/* ── Root ── */\n\nexport function Dropdown({ children }: { children: ReactNode }) {\n const [open, setOpen] = useState(false)\n const triggerId = useId()\n const contentId = useId()\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n\n return (\n <DropdownContext.Provider value={{ open, setOpen, triggerId, contentId, triggerRef }}>\n <div className=\"relative inline-block\">{children}</div>\n </DropdownContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function DropdownTrigger({ children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {\n const { open, setOpen, triggerId, contentId, triggerRef } = useDropdownContext()\n return (\n <button\n type=\"button\"\n ref={triggerRef}\n id={triggerId}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n onClick={() => setOpen(!open)}\n {...props}\n >\n {children}\n </button>\n )\n}\n\n/* ── Content ── */\n\ninterface DropdownContentProps extends HTMLAttributes<HTMLDivElement> {\n /** Horizontal alignment relative to the trigger. Default: 'start' (left-aligned). */\n align?: 'start' | 'end'\n /** Pixel offset between trigger and content. Default: 4. */\n offset?: number\n}\n\nexport function DropdownContent({ className, children, align = 'start', offset = 4, ...props }: DropdownContentProps) {\n const { open, setOpen, contentId, triggerId, triggerRef } = useDropdownContext()\n const ref = useRef<HTMLDivElement>(null)\n const [coords, setCoords] = useState<{ top: number; left: number; minWidth: number } | null>(null)\n\n // Compute absolute position from the trigger's bounding rect so the menu\n // renders in a portal (document.body) and escapes any ancestor overflow/clip.\n useLayoutEffect(() => {\n if (!open) { setCoords(null); return }\n const compute = () => {\n const trigger = triggerRef.current\n if (!trigger) return\n const rect = trigger.getBoundingClientRect()\n const left = align === 'end' ? rect.right : rect.left\n setCoords({\n top: rect.bottom + offset,\n left,\n minWidth: rect.width,\n })\n }\n compute()\n window.addEventListener('resize', compute)\n window.addEventListener('scroll', compute, true)\n return () => {\n window.removeEventListener('resize', compute)\n window.removeEventListener('scroll', compute, true)\n }\n }, [open, align, offset, triggerRef])\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n const el = ref.current\n const trigger = triggerRef.current\n if (el && !el.contains(e.target as Node) && !trigger?.contains(e.target as Node)) {\n setOpen(false)\n }\n }\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n document.addEventListener('keydown', escHandler)\n return () => {\n document.removeEventListener('mousedown', handler)\n document.removeEventListener('keydown', escHandler)\n }\n }, [open, setOpen, triggerRef])\n\n if (!open || !coords || typeof document === 'undefined') return null\n\n const style: React.CSSProperties = {\n position: 'fixed',\n top: coords.top,\n ...(align === 'end'\n ? { right: window.innerWidth - coords.left }\n : { left: coords.left }),\n minWidth: coords.minWidth,\n }\n\n return createPortal(\n <div\n ref={ref}\n id={contentId}\n role=\"menu\"\n aria-labelledby={triggerId}\n style={style}\n className={cn(\n 'z-50 bg-background-elevated border border-border rounded-md shadow-lg py-1 min-w-[160px]',\n className\n )}\n {...props}\n >\n {children}\n </div>,\n document.body,\n )\n}\n\n/* ── Item ── */\n\ninterface DropdownItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n icon?: LucideIcon\n variant?: 'default' | 'danger'\n}\n\nexport function DropdownItem({\n className,\n icon: Icon,\n variant = 'default',\n children,\n onClick,\n ...props\n}: DropdownItemProps) {\n const { setOpen } = useDropdownContext()\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n setOpen(false)\n },\n [onClick, setOpen]\n )\n\n return (\n <button\n type=\"button\"\n role=\"menuitem\"\n className={cn(\n 'h-7 text-xs px-2 w-full text-left flex items-center gap-2',\n variant === 'danger'\n ? 'text-danger hover:bg-danger/10'\n : 'text-foreground hover:bg-surface-hover',\n className\n )}\n onClick={handleClick}\n {...props}\n >\n {Icon && <Icon size={14} />}\n {children}\n </button>\n )\n}\n","import {\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useContext,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { cn } from '../lib/cn'\n\ninterface TooltipContextValue {\n open: boolean\n show: () => void\n hide: () => void\n tooltipId: string\n}\n\nconst TooltipContext = createContext<TooltipContextValue | null>(null)\n\nfunction useTooltipContext() {\n const ctx = useContext(TooltipContext)\n if (!ctx) throw new Error('Tooltip compound components must be used within <Tooltip>')\n return ctx\n}\n\n/* ── Root ── */\n\nexport function Tooltip({ children }: { children: ReactNode }) {\n const [open, setOpen] = useState(false)\n const timerRef = useRef<ReturnType<typeof setTimeout>>(null)\n const tooltipId = useId()\n\n const show = () => {\n timerRef.current = setTimeout(() => setOpen(true), 300)\n }\n\n const hide = () => {\n if (timerRef.current) clearTimeout(timerRef.current)\n setOpen(false)\n }\n\n return (\n <TooltipContext.Provider value={{ open, show, hide, tooltipId }}>\n <div className=\"relative inline-block\">{children}</div>\n </TooltipContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function TooltipTrigger({ children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { show, hide, tooltipId, open } = useTooltipContext()\n\n return (\n <div\n onMouseEnter={show}\n onMouseLeave={hide}\n onFocus={show}\n onBlur={hide}\n aria-describedby={open ? tooltipId : undefined}\n {...props}\n >\n {children}\n </div>\n )\n}\n\n/* ── Content ── */\n\nexport function TooltipContent({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { open, tooltipId } = useTooltipContext()\n\n return (\n <div\n id={tooltipId}\n role=\"tooltip\"\n className={cn(\n 'absolute bottom-full left-1/2 -translate-x-1/2 mb-2 bg-foreground text-background text-xs px-2 py-1 rounded-md shadow-md whitespace-nowrap pointer-events-none transition-opacity duration-150',\n open ? 'opacity-100' : 'opacity-0',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import {\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react'\nimport { cn } from '../lib/cn'\nimport { useIsMobile } from '../hooks/use-is-mobile'\nimport { BottomSheet } from './bottom-sheet'\n\ninterface PopoverContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n triggerId: string\n contentId: string\n}\n\nconst PopoverContext = createContext<PopoverContextValue | null>(null)\n\nfunction usePopoverContext() {\n const ctx = useContext(PopoverContext)\n if (!ctx) throw new Error('Popover compound components must be used within <Popover>')\n return ctx\n}\n\n/* ── Root ── */\n\ninterface PopoverProps {\n children: ReactNode\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nexport function Popover({ children, open: controlledOpen, onOpenChange }: PopoverProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false)\n const open = controlledOpen ?? uncontrolledOpen\n const triggerId = useId()\n const contentId = useId()\n\n const setOpen = useCallback(\n (next: boolean) => {\n onOpenChange?.(next)\n if (controlledOpen === undefined) setUncontrolledOpen(next)\n },\n [controlledOpen, onOpenChange]\n )\n\n return (\n <PopoverContext.Provider value={{ open, setOpen, triggerId, contentId }}>\n <div className=\"relative inline-block\">{children}</div>\n </PopoverContext.Provider>\n )\n}\n\n/* ── Trigger ── */\n\nexport function PopoverTrigger({ children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {\n const { open, setOpen, triggerId, contentId } = usePopoverContext()\n return (\n <button\n type=\"button\"\n id={triggerId}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n onClick={() => setOpen(!open)}\n {...props}\n >\n {children}\n </button>\n )\n}\n\n/* ── Content ── */\n\nexport function PopoverContent({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) {\n const { open, setOpen, contentId, triggerId } = usePopoverContext()\n const isMobile = useIsMobile()\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!open || isMobile) return\n const handler = (e: MouseEvent) => {\n const el = ref.current\n const trigger = document.getElementById(triggerId)\n if (el && !el.contains(e.target as Node) && !trigger?.contains(e.target as Node)) {\n setOpen(false)\n }\n }\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n document.addEventListener('keydown', escHandler)\n return () => {\n document.removeEventListener('mousedown', handler)\n document.removeEventListener('keydown', escHandler)\n }\n }, [open, setOpen, triggerId, isMobile])\n\n if (!open) return null\n\n if (isMobile) {\n return (\n <BottomSheet open={open} onClose={() => setOpen(false)}>\n {children}\n </BottomSheet>\n )\n }\n\n return (\n <div\n ref={ref}\n id={contentId}\n role=\"dialog\"\n aria-labelledby={triggerId}\n className={cn(\n 'absolute left-0 top-full z-50 mt-1 bg-background-elevated border border-border rounded-lg shadow-lg p-3',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n","import { useSyncExternalStore } from 'react'\n\nconst MOBILE_QUERY = '(max-width: 767px)'\n/**\n * Mid breakpoint — below this width the sidebar collapses to an\n * icons-only rail to reclaim canvas space. Above it (and outside\n * mobile) the full sidebar renders. Threshold matches Tailwind `lg`\n * so sidebar fans out at the same point grids switch to multi-column.\n */\nconst MID_QUERY = '(min-width: 768px) and (max-width: 1023px)'\n\nfunction subscribeQuery(query: string): (callback: () => void) => () => void {\n return (callback) => {\n const mql = window.matchMedia(query)\n mql.addEventListener('change', callback)\n return () => mql.removeEventListener('change', callback)\n }\n}\n\nfunction getSnapshot(query: string): () => boolean {\n return () => window.matchMedia(query).matches\n}\n\nfunction getServerSnapshot(): boolean {\n return false\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(subscribeQuery(MOBILE_QUERY), getSnapshot(MOBILE_QUERY), getServerSnapshot)\n}\n\n/**\n * True when the viewport is in the medium (`md`) Tailwind range —\n * 768px ≤ width < 1024px. Use to drive layouts that should pack denser\n * than full-desktop but more legibly than mobile (e.g. icons-only\n * sidebar rail, narrower stat tiles).\n */\nexport function useIsMidWidth(): boolean {\n return useSyncExternalStore(subscribeQuery(MID_QUERY), getSnapshot(MID_QUERY), getServerSnapshot)\n}\n","import { type ReactNode, useEffect } from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface BottomSheetProps {\n open: boolean\n onClose: () => void\n title?: string\n children: ReactNode\n className?: string\n}\n\nexport function BottomSheet({ open, onClose, title, children, className }: BottomSheetProps) {\n useEffect(() => {\n if (!open) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', handleKeyDown)\n document.body.style.overflow = ''\n }\n }, [open, onClose])\n\n return (\n <>\n {/* Backdrop */}\n <div\n className={cn(\n 'fixed inset-0 z-40 bg-black/50 transition-opacity duration-200',\n open ? 'opacity-100' : 'pointer-events-none opacity-0'\n )}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n {/* Sheet */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n className={cn(\n 'fixed inset-x-0 bottom-0 z-50 flex flex-col bg-background-elevated border-t border-border rounded-t-xl shadow-2xl transition-transform duration-200 ease-out',\n 'max-h-[80dvh]',\n open ? 'translate-y-0' : 'translate-y-full',\n className\n )}\n >\n {/* Handle bar */}\n <div className=\"flex justify-center pt-2 pb-1\">\n <div className=\"h-1 w-8 rounded-full bg-foreground-subtle/30\" />\n </div>\n\n {/* Header */}\n {title && (\n <div className=\"flex items-center justify-between px-4 pb-2\">\n <span className=\"text-sm font-medium text-foreground\">{title}</span>\n <button\n onClick={onClose}\n className=\"p-1 rounded-md hover:bg-surface-hover text-foreground-muted transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto px-4 pb-4\">\n {children}\n </div>\n </div>\n </>\n )\n}\n","import {\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n createContext,\n useCallback,\n useContext,\n useState,\n} from 'react'\nimport { cn } from '../lib/cn'\n\ninterface TabsContextValue {\n value: string\n setValue: (value: string) => void\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext() {\n const ctx = useContext(TabsContext)\n if (!ctx) throw new Error('Tabs compound components must be used within <Tabs>')\n return ctx\n}\n\n/* ── Root ── */\n\ninterface TabsProps extends HTMLAttributes<HTMLDivElement> {\n value?: string\n onValueChange?: (value: string) => void\n defaultValue?: string\n}\n\nexport function Tabs({\n value: controlledValue,\n onValueChange,\n defaultValue = '',\n className,\n ...props\n}: TabsProps) {\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue)\n const value = controlledValue ?? uncontrolledValue\n\n const setValue = useCallback(\n (next: string) => {\n onValueChange?.(next)\n if (controlledValue === undefined) setUncontrolledValue(next)\n },\n [controlledValue, onValueChange]\n )\n\n return (\n <TabsContext.Provider value={{ value, setValue }}>\n <div className={className} {...props} />\n </TabsContext.Provider>\n )\n}\n\n/* ── TabsList ── */\n\nexport function TabsList({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n role=\"tablist\"\n className={cn('flex flex-row border-b border-border-subtle', className)}\n {...props}\n />\n )\n}\n\n/* ── TabsTrigger ── */\n\ninterface TabsTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nexport function TabsTrigger({ value, className, ...props }: TabsTriggerProps) {\n const { value: activeValue, setValue } = useTabsContext()\n const isActive = value === activeValue\n const panelId = `tabpanel-${value}`\n\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={panelId}\n tabIndex={isActive ? 0 : -1}\n className={cn(\n 'h-7 text-xs px-3 transition-colors',\n isActive\n ? 'border-b-2 border-primary text-foreground font-medium'\n : 'text-foreground-muted hover:text-foreground',\n className\n )}\n onClick={() => setValue(value)}\n {...props}\n />\n )\n}\n\n/* ── TabsContent ── */\n\ninterface TabsContentProps extends HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nexport function TabsContent({ value, className, ...props }: TabsContentProps) {\n const { value: activeValue } = useTabsContext()\n if (value !== activeValue) return null\n\n return (\n <div\n role=\"tabpanel\"\n id={`tabpanel-${value}`}\n className={cn('pt-3', className)}\n {...props}\n />\n )\n}\n","import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport const ScrollArea = forwardRef<HTMLDivElement, ScrollAreaProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'overflow-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-surface-hover [&::-webkit-scrollbar-thumb]:rounded-full',\n className\n )}\n {...props}\n />\n )\n }\n)\n\nScrollArea.displayName = 'ScrollArea'\n","import { useRef, useState, useCallback, useEffect, type ReactNode } from 'react';\nimport { X, Minimize2, Maximize2, GripHorizontal } from 'lucide-react';\nimport { cn } from '../lib/cn';\nimport { useIsMobile } from '../hooks/use-is-mobile';\n\nexport interface FloatingPanelProps {\n /** Panel title displayed in the title bar */\n title: string;\n /** Called when the close button is clicked */\n onClose: () => void;\n /** Panel content */\n children: ReactNode;\n /** Default width in pixels */\n defaultWidth?: number;\n /** Default height in pixels */\n defaultHeight?: number;\n /** Minimum width in pixels */\n minWidth?: number;\n /** Minimum height in pixels */\n minHeight?: number;\n /** Offset index to stagger multiple panels (adds 30px offset per index) */\n offsetIndex?: number;\n /** Additional CSS classes for the panel container */\n className?: string;\n}\n\nexport function FloatingPanel({\n title,\n onClose,\n children,\n defaultWidth = 360,\n defaultHeight = 280,\n minWidth = 280,\n minHeight = 160,\n offsetIndex = 0,\n className,\n}: FloatingPanelProps) {\n const [pos, setPos] = useState({ x: 80 + offsetIndex * 30, y: 80 + offsetIndex * 30 });\n const [size, setSize] = useState({ w: defaultWidth, h: defaultHeight });\n const [minimized, setMinimized] = useState(false);\n const dragging = useRef(false);\n const resizing = useRef(false);\n const offset = useRef({ x: 0, y: 0 });\n const isMobile = useIsMobile();\n\n const onDragStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n dragging.current = true;\n offset.current = { x: e.clientX - pos.x, y: e.clientY - pos.y };\n }, [pos]);\n\n const onResizeStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n resizing.current = true;\n offset.current = { x: e.clientX, y: e.clientY };\n }, []);\n\n useEffect(() => {\n const onMouseMove = (e: MouseEvent) => {\n if (dragging.current) setPos({ x: e.clientX - offset.current.x, y: e.clientY - offset.current.y });\n if (resizing.current) {\n const dx = e.clientX - offset.current.x;\n const dy = e.clientY - offset.current.y;\n offset.current = { x: e.clientX, y: e.clientY };\n setSize(prev => ({ w: Math.max(minWidth, prev.w + dx), h: Math.max(minHeight, prev.h + dy) }));\n }\n };\n const onMouseUp = () => { dragging.current = false; resizing.current = false; };\n window.addEventListener('mousemove', onMouseMove);\n window.addEventListener('mouseup', onMouseUp);\n return () => { window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); };\n }, [minWidth, minHeight]);\n\n if (isMobile) {\n return (\n <div\n className={cn(\n 'fixed inset-x-0 bottom-0 z-50 rounded-t-xl border-t border-border bg-background-elevated shadow-2xl flex flex-col overflow-hidden',\n className\n )}\n style={{ maxHeight: '60dvh' }}\n >\n <div className=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border shrink-0 bg-surface\">\n <span className=\"text-[11px] font-medium truncate\">{title}</span>\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n onClick={() => setMinimized(!minimized)}\n className=\"p-0.5 rounded hover:bg-surface-hover text-foreground-muted transition-colors\"\n >\n {minimized ? <Maximize2 size={12} /> : <Minimize2 size={12} />}\n </button>\n <button\n onClick={onClose}\n className=\"p-0.5 rounded hover:bg-danger/20 text-foreground-muted hover:text-danger transition-colors\"\n >\n <X size={12} />\n </button>\n </div>\n </div>\n {!minimized && (\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n {children}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'fixed z-50 rounded-lg border border-border bg-background-elevated shadow-2xl flex flex-col overflow-hidden',\n className\n )}\n style={{ left: pos.x, top: pos.y, width: minimized ? 280 : size.w, height: minimized ? 'auto' : size.h }}\n >\n {/* Title bar — draggable */}\n <div\n onMouseDown={onDragStart}\n className=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border cursor-move select-none shrink-0 bg-surface\"\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <GripHorizontal size={12} className=\"text-foreground-subtle shrink-0\" />\n <span className=\"text-[11px] font-medium truncate\">{title}</span>\n </div>\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n onClick={() => setMinimized(!minimized)}\n className=\"p-0.5 rounded hover:bg-surface-hover text-foreground-muted transition-colors\"\n title={minimized ? 'Restore' : 'Minimize'}\n >\n {minimized ? <Maximize2 size={12} /> : <Minimize2 size={12} />}\n </button>\n <button\n onClick={onClose}\n className=\"p-0.5 rounded hover:bg-danger/20 text-foreground-muted hover:text-danger transition-colors\"\n title=\"Close\"\n >\n <X size={12} />\n </button>\n </div>\n </div>\n\n {/* Content */}\n {!minimized && (\n <div className=\"flex-1 min-h-0 overflow-y-auto relative\">\n {children}\n {/* Resize handle */}\n <div\n onMouseDown={onResizeStart}\n className=\"absolute bottom-0 right-0 w-4 h-4 cursor-nwse-resize\"\n style={{ background: 'linear-gradient(135deg, transparent 50%, var(--color-foreground-subtle) 50%)', opacity: 0.4 }}\n />\n </div>\n )}\n </div>\n );\n}\n","import { type ReactNode, useEffect, useRef } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface MobileDrawerProps {\n open: boolean\n onClose: () => void\n children: ReactNode\n className?: string\n /** Width of the drawer panel. Default: 'w-64' */\n width?: string\n}\n\nexport function MobileDrawer({ open, onClose, children, className, width = 'w-64' }: MobileDrawerProps) {\n const drawerRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!open) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', handleKeyDown)\n document.body.style.overflow = ''\n }\n }, [open, onClose])\n\n return (\n <>\n {/* Backdrop */}\n <div\n className={cn(\n 'fixed inset-0 z-40 bg-black/50 backdrop-blur-sm transition-opacity duration-200',\n open ? 'opacity-100' : 'pointer-events-none opacity-0'\n )}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n {/* Drawer panel */}\n <div\n ref={drawerRef}\n role=\"dialog\"\n aria-modal=\"true\"\n className={cn(\n 'fixed inset-y-0 left-0 z-50 flex flex-col bg-surface border-r border-border shadow-2xl transition-transform duration-200 ease-out',\n width,\n open ? 'translate-x-0' : '-translate-x-full',\n className\n )}\n >\n {children}\n </div>\n </>\n )\n}\n","import React from 'react'\nimport { ChevronRight } from 'lucide-react'\n\nexport interface BreadcrumbItem {\n /** Display label */\n label: string\n /** If provided, renders as a clickable link. Last item is never a link. */\n href?: string\n /** Click handler — used instead of href for SPA navigation */\n onClick?: () => void\n}\n\nexport interface BreadcrumbProps {\n items: BreadcrumbItem[]\n className?: string\n}\n\n/**\n * Breadcrumb navigation component.\n *\n * Usage with react-router:\n * ```tsx\n * <Breadcrumb items={[\n * { label: 'Integrations', onClick: () => navigate('/integrations') },\n * { label: 'RTSP Cameras', onClick: () => navigate('/integrations/int_0001') },\n * { label: 'Front Door' },\n * ]} />\n * ```\n */\nexport function Breadcrumb({ items, className }: BreadcrumbProps) {\n return (\n <nav className={`flex items-center gap-1 text-[11px] text-foreground-subtle ${className ?? ''}`}>\n {items.map((item, i) => {\n const isLast = i === items.length - 1\n const isClickable = !isLast && (item.onClick || item.href)\n\n return (\n <React.Fragment key={i}>\n {i > 0 && <ChevronRight className=\"h-3 w-3 flex-shrink-0\" />}\n {isClickable ? (\n item.onClick ? (\n <button\n type=\"button\"\n onClick={item.onClick}\n className=\"hover:text-foreground transition-colors\"\n >\n {item.label}\n </button>\n ) : (\n <a href={item.href} className=\"hover:text-foreground transition-colors\">\n {item.label}\n </a>\n )\n ) : (\n <span className={isLast ? 'text-foreground font-medium' : ''}>{item.label}</span>\n )}\n </React.Fragment>\n )\n })}\n </nav>\n )\n}\n","import { type ReactNode, useEffect } from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface SlideOverPanelProps {\n readonly open: boolean\n readonly onClose: () => void\n readonly title: ReactNode\n readonly subtitle?: ReactNode\n readonly footer?: ReactNode\n readonly children: ReactNode\n readonly widthClass?: string\n}\n\nexport function SlideOverPanel({\n open,\n onClose,\n title,\n subtitle,\n footer,\n children,\n widthClass = 'w-[360px]',\n}: SlideOverPanelProps) {\n useEffect(() => {\n if (!open) return\n const onEsc = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() }\n window.addEventListener('keydown', onEsc)\n return () => window.removeEventListener('keydown', onEsc)\n }, [open, onClose])\n\n if (!open) return null\n\n return (\n <aside\n className={cn(\n 'absolute top-0 right-0 bottom-0 z-20 flex flex-col',\n 'bg-surface border-l border-border shadow-xl',\n widthClass,\n )}\n role=\"dialog\"\n aria-modal=\"false\"\n >\n <header className=\"flex items-start justify-between gap-2 px-4 py-3 border-b border-border\">\n <div className=\"min-w-0\">\n <div className=\"text-sm font-semibold text-foreground truncate\">{title}</div>\n {subtitle !== undefined && (\n <div className=\"text-[11px] text-foreground-subtle mt-0.5 truncate\">{subtitle}</div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded hover:bg-muted text-foreground-subtle hover:text-foreground\"\n aria-label=\"Close panel\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </header>\n\n <div className=\"flex-1 min-h-0 overflow-y-auto px-4 py-3\">\n {children}\n </div>\n\n {footer !== undefined && (\n <footer className=\"flex items-center gap-2 justify-end px-4 py-3 border-t border-border\">\n {footer}\n </footer>\n )}\n </aside>\n )\n}\n","import type { ReactNode } from 'react'\nimport type { PipelineSchema, PipelineSlot } from '@camstack/types'\nimport { cn } from '../lib/cn'\n\nexport type StepDotState = 'inherit' | 'on' | 'off' | 'na'\n\nexport interface StepTreeNode {\n readonly addonId: string\n readonly addonName: string\n readonly slot: PipelineSlot\n readonly inputClasses: readonly string[]\n readonly outputClasses: readonly string[]\n readonly children: readonly StepTreeNode[]\n}\n\nexport interface StepTreeMasterProps {\n readonly tree: readonly StepTreeNode[]\n readonly selectedAddonId: string | null\n readonly onSelect: (addonId: string) => void\n readonly agentDots?: Readonly<Record<string, readonly { readonly agentNodeId: string; readonly state: StepDotState }[]>>\n readonly className?: string\n}\n\nconst DOT_COLOR: Record<StepDotState, string> = {\n inherit: 'bg-muted',\n on: 'bg-emerald-500',\n off: 'bg-orange-500',\n na: 'bg-gray-300 opacity-50',\n}\n\ninterface TreeRowProps {\n readonly node: StepTreeNode\n readonly depth: number\n readonly selectedAddonId: string | null\n readonly onSelect: (addonId: string) => void\n readonly agentDots?: StepTreeMasterProps['agentDots']\n}\n\nfunction TreeRow({ node, depth, selectedAddonId, onSelect, agentDots }: TreeRowProps): ReactNode {\n const isSelected = node.addonId === selectedAddonId\n const dots = agentDots?.[node.addonId] ?? []\n return (\n <div>\n <button\n type=\"button\"\n onClick={() => onSelect(node.addonId)}\n className={cn(\n 'w-full flex items-center justify-between gap-2 text-left px-3 py-1.5 text-xs',\n 'border-l-2',\n isSelected\n ? 'bg-accent border-primary text-foreground font-medium'\n : 'border-transparent hover:bg-muted/40 text-foreground',\n )}\n style={{ paddingLeft: `${12 + depth * 14}px` }}\n >\n <span className=\"truncate\">{node.addonName}</span>\n {dots.length > 0 && (\n <span className=\"flex items-center gap-1 shrink-0\">\n {dots.map((d) => (\n <span\n key={d.agentNodeId}\n title={`${d.agentNodeId}: ${d.state}`}\n className={cn('w-2 h-2 rounded-full', DOT_COLOR[d.state])}\n />\n ))}\n </span>\n )}\n </button>\n {node.children.map((child) => (\n <TreeRow\n key={child.addonId}\n node={child}\n depth={depth + 1}\n selectedAddonId={selectedAddonId}\n onSelect={onSelect}\n agentDots={agentDots}\n />\n ))}\n </div>\n )\n}\n\nexport function StepTreeMaster({\n tree,\n selectedAddonId,\n onSelect,\n agentDots,\n className,\n}: StepTreeMasterProps) {\n return (\n <div className={cn('flex flex-col py-2', className)}>\n {tree.map((node) => (\n <TreeRow\n key={node.addonId}\n node={node}\n depth={0}\n selectedAddonId={selectedAddonId}\n onSelect={onSelect}\n agentDots={agentDots}\n />\n ))}\n </div>\n )\n}\n\n/**\n * Helper: build a StepTreeNode[] from a `PipelineSchema` by chaining on\n * `inputClasses` ⇔ `outputClasses` compatibility. Mirrors the orchestrator\n * resolver's `buildTreeFromAddons` logic but yields names only (display\n * layer). Addons in the audio-classifier slot become separate roots.\n */\nexport function buildStepTreeFromSchema(schema: PipelineSchema): readonly StepTreeNode[] {\n // Mutable scaffold so we can attach children during the single-pass\n // compat walk; returned as readonly StepTreeNode[] at the end.\n interface MutableNode {\n readonly addonId: string\n readonly addonName: string\n readonly slot: PipelineSlot\n readonly inputClasses: readonly string[]\n readonly outputClasses: readonly string[]\n readonly children: MutableNode[]\n }\n\n const audioRoots: MutableNode[] = []\n const videoNodes: MutableNode[] = []\n const byId = new Map<string, MutableNode>()\n\n for (const slot of schema.slots) {\n for (const a of slot.addons) {\n const node: MutableNode = {\n addonId: a.id,\n addonName: a.name,\n slot: a.slot,\n inputClasses: a.inputClasses,\n outputClasses: a.outputClasses,\n children: [],\n }\n if (a.slot === 'audio-classifier') {\n audioRoots.push(node)\n } else {\n videoNodes.push(node)\n byId.set(a.id, node)\n }\n }\n }\n\n const roots: MutableNode[] = []\n for (const node of videoNodes) {\n if (node.inputClasses.length === 0) {\n roots.push(node)\n continue\n }\n const parent = videoNodes.find(\n (p) => p.addonId !== node.addonId && p.outputClasses.some((c) => node.inputClasses.includes(c)),\n )\n if (parent) {\n parent.children.push(node)\n }\n }\n\n return [...roots, ...audioRoots]\n}\n","import { useMemo } from 'react'\nimport type {\n PipelineAddonSchema,\n AgentAddonConfig,\n CameraStepOverridePatch,\n} from '@camstack/types'\nimport { cn } from '../lib/cn'\nimport { ConfigSchemaField, type PipelineStepDisplayConfig } from './pipeline-step'\n\nfunction buildDisplayStep(\n addon: PipelineAddonSchema,\n cfg: AgentAddonConfig,\n): PipelineStepDisplayConfig {\n return {\n addonId: addon.id,\n addonName: addon.name,\n slot: addon.slot,\n inputClasses: [...addon.inputClasses],\n outputClasses: [...addon.outputClasses],\n enabled: cfg.enabled,\n modelId: cfg.modelId,\n children: [],\n settings: { ...cfg.settings },\n }\n}\n\nexport type EditorMode = 'agent' | 'device'\n\nexport interface AgentStepEditorProps {\n readonly mode: EditorMode\n readonly addon: PipelineAddonSchema\n /** L1 base — always visible as the \"inherited\" baseline. */\n readonly agentDefault: AgentAddonConfig\n readonly agentNodeId: string\n /** Device mode only — current L2.5 patch for (agent, addon). */\n readonly currentPatch?: CameraStepOverridePatch | null\n readonly onChangeAgentConfig?: (next: AgentAddonConfig) => void\n readonly onChangePatch?: (next: CameraStepOverridePatch | null) => void\n readonly engineFormat: string\n}\n\ntype TriState = 'inherit' | 'on' | 'off'\n\nfunction computeEffective(\n mode: EditorMode,\n agentDefault: AgentAddonConfig,\n patch: CameraStepOverridePatch | null | undefined,\n): AgentAddonConfig {\n if (mode !== 'device' || !patch) return agentDefault\n return {\n enabled: patch.enabled ?? agentDefault.enabled,\n modelId: patch.modelId ?? agentDefault.modelId,\n settings: patch.settings ?? agentDefault.settings,\n }\n}\n\nfunction AgentModeEditor({\n addon,\n agentDefault,\n modelsForFormat,\n onChangeAgentConfig,\n}: {\n readonly addon: PipelineAddonSchema\n readonly agentDefault: AgentAddonConfig\n readonly modelsForFormat: readonly PipelineAddonSchema['models'][number][]\n readonly onChangeAgentConfig?: (next: AgentAddonConfig) => void\n}) {\n const update = (patch: Partial<AgentAddonConfig>): void => {\n onChangeAgentConfig?.({ ...agentDefault, ...patch })\n }\n return (\n <div className=\"space-y-4 text-xs\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={agentDefault.enabled}\n onChange={(e) => update({ enabled: e.target.checked })}\n />\n <span>Enabled on this agent ({addon.name})</span>\n </label>\n\n <div>\n <div className=\"text-[10px] uppercase tracking-widest text-foreground-subtle mb-1\">Model</div>\n <select\n className=\"w-full bg-surface border border-border rounded px-2 py-1 text-xs\"\n value={agentDefault.modelId}\n onChange={(e) => update({ modelId: e.target.value })}\n >\n {modelsForFormat.map((m) => (\n <option key={m.id} value={m.id}>{m.name}</option>\n ))}\n </select>\n </div>\n\n {(addon.configSchema?.length ?? 0) > 0 && (\n <div className=\"pt-2 border-t border-border/50 space-y-3\">\n <div className=\"text-[10px] uppercase tracking-widest text-foreground-subtle\">Settings</div>\n {addon.configSchema?.map((field) => (\n <ConfigSchemaField\n key={field.key}\n field={field}\n allFields={addon.configSchema ?? []}\n step={buildDisplayStep(addon, agentDefault)}\n disabled={false}\n onChange={(next) => update({ settings: { ...next.settings } })}\n />\n ))}\n </div>\n )}\n </div>\n )\n}\n\nfunction DeviceModeEditor({\n addon,\n agentDefault,\n agentNodeId,\n currentPatch,\n modelsForFormat,\n onChangePatch,\n}: {\n readonly addon: PipelineAddonSchema\n readonly agentDefault: AgentAddonConfig\n readonly agentNodeId: string\n readonly currentPatch: CameraStepOverridePatch | null | undefined\n readonly modelsForFormat: readonly PipelineAddonSchema['models'][number][]\n readonly onChangePatch?: (next: CameraStepOverridePatch | null) => void\n}) {\n const effective = computeEffective('device', agentDefault, currentPatch)\n\n const commitPatch = (next: CameraStepOverridePatch): void => {\n const hasAnyField =\n next.enabled !== undefined ||\n next.modelId !== undefined ||\n next.settings !== undefined\n onChangePatch?.(hasAnyField ? next : null)\n }\n\n const setEnabled = (state: TriState): void => {\n const { enabled: _prev, ...rest } = currentPatch ?? {}\n const next: CameraStepOverridePatch = state === 'inherit'\n ? rest\n : { ...rest, enabled: state === 'on' }\n commitPatch(next)\n }\n\n const setModel = (modelId: string | undefined): void => {\n const { modelId: _prev, ...rest } = currentPatch ?? {}\n const next: CameraStepOverridePatch = modelId === undefined\n ? rest\n : { ...rest, modelId }\n commitPatch(next)\n }\n\n const setSettings = (settings: Readonly<Record<string, unknown>> | undefined): void => {\n const { settings: _prev, ...rest } = currentPatch ?? {}\n const next: CameraStepOverridePatch = settings === undefined\n ? rest\n : { ...rest, settings }\n commitPatch(next)\n }\n\n const enabledTri: TriState = currentPatch?.enabled === undefined\n ? 'inherit'\n : currentPatch.enabled\n ? 'on'\n : 'off'\n const modelOverridden = currentPatch?.modelId !== undefined\n\n return (\n <div className=\"space-y-4 text-xs\">\n <div className=\"flex items-center gap-1\">\n {(['inherit', 'on', 'off'] as const).map((s) => (\n <button\n key={s}\n type=\"button\"\n onClick={() => setEnabled(s)}\n className={cn(\n 'px-3 py-1 border border-border rounded text-xs capitalize',\n enabledTri === s ? 'bg-primary text-primary-foreground border-primary' : 'bg-surface text-foreground hover:bg-muted',\n )}\n >\n {s}\n </button>\n ))}\n <span className=\"ml-2 text-[10px] text-foreground-subtle\">\n agent default: <span className=\"font-semibold\">{agentDefault.enabled ? 'on' : 'off'}</span>\n </span>\n </div>\n\n <div>\n <div className=\"flex items-center justify-between mb-1\">\n <div className=\"text-[10px] uppercase tracking-widest text-foreground-subtle\">Model</div>\n {modelOverridden ? (\n <button type=\"button\" className=\"text-[10px] text-foreground-subtle hover:text-foreground\" onClick={() => setModel(undefined)}>Clear</button>\n ) : (\n <button type=\"button\" className=\"text-[10px] text-primary hover:underline\" onClick={() => setModel(agentDefault.modelId)}>Override</button>\n )}\n </div>\n <select\n disabled={!modelOverridden}\n className=\"w-full bg-surface border border-border rounded px-2 py-1 text-xs disabled:opacity-50\"\n value={modelOverridden ? (currentPatch?.modelId ?? agentDefault.modelId) : agentDefault.modelId}\n onChange={(e) => setModel(e.target.value)}\n >\n {modelsForFormat.map((m) => (\n <option key={m.id} value={m.id}>{m.name}</option>\n ))}\n </select>\n {!modelOverridden && (\n <div className=\"text-[10px] text-foreground-subtle mt-1\">inherits from {agentNodeId}</div>\n )}\n </div>\n\n {(addon.configSchema?.length ?? 0) > 0 && (() => {\n const settingsOverridden = currentPatch?.settings !== undefined\n return (\n <div className=\"pt-2 border-t border-border/50 space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-[10px] uppercase tracking-widest text-foreground-subtle\">Settings</div>\n {settingsOverridden ? (\n <button type=\"button\" className=\"text-[10px] text-foreground-subtle hover:text-foreground\" onClick={() => setSettings(undefined)}>Clear</button>\n ) : (\n <button type=\"button\" className=\"text-[10px] text-primary hover:underline\" onClick={() => setSettings({ ...agentDefault.settings })}>Override</button>\n )}\n </div>\n {addon.configSchema?.map((field) => (\n <ConfigSchemaField\n key={field.key}\n field={field}\n allFields={addon.configSchema ?? []}\n step={buildDisplayStep(addon, effective)}\n disabled={!settingsOverridden}\n onChange={(next) => setSettings({ ...next.settings })}\n />\n ))}\n {!settingsOverridden && (\n <div className=\"text-[10px] text-foreground-subtle\">inherits from {agentNodeId}</div>\n )}\n </div>\n )\n })()}\n\n <div className=\"rounded bg-muted/40 px-3 py-2 text-[11px] text-foreground-subtle\">\n <div className=\"font-semibold text-foreground mb-0.5\">Effective config preview</div>\n <div className=\"font-mono truncate\">\n {addon.id} · model: {effective.modelId} · {effective.enabled ? 'on' : 'off'}\n </div>\n </div>\n </div>\n )\n}\n\nexport function AgentStepEditor(props: AgentStepEditorProps) {\n const { mode, addon, agentDefault, agentNodeId, currentPatch, onChangeAgentConfig, onChangePatch, engineFormat } = props\n const modelsForFormat = useMemo(\n () => addon.models.filter((m) => Boolean(m.formats[engineFormat])),\n [addon.models, engineFormat],\n )\n\n if (mode === 'agent') {\n return (\n <AgentModeEditor\n addon={addon}\n agentDefault={agentDefault}\n modelsForFormat={modelsForFormat}\n onChangeAgentConfig={onChangeAgentConfig}\n />\n )\n }\n return (\n <DeviceModeEditor\n addon={addon}\n agentDefault={agentDefault}\n agentNodeId={agentNodeId}\n currentPatch={currentPatch}\n modelsForFormat={modelsForFormat}\n onChangePatch={onChangePatch}\n />\n )\n}\n","/**\n * PipelineStep — single step card in the pipeline builder.\n *\n * Driven entirely by PipelineAddonSchema. No hardcoded addon names or models.\n * Renders: colored left border, header with I/O class tags, expandable config\n * (Model → Confidence), children recursively.\n */\nimport { useState } from 'react'\nimport type { PipelineSlot, PipelineAddonSchema, PipelineEngineChoice, ConfigField } from '@camstack/types'\nimport { cn } from '../lib/cn'\nimport { CollapsibleCard } from '../primitives/collapsible-card'\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\n// Phase 7 (settings redesign): the generic `confidence: number` field was\n// removed. Each step now declares its own threshold (if any) via its\n// `configSchema`, surfaced through the dynamic `ConfigSchemaField`\n// renderer below. Steps that don't need a user-tunable threshold use the\n// hardcoded `StepDefinition.defaultConfidence` read by the runtime\n// executor directly.\nexport interface PipelineStepDisplayConfig {\n readonly addonId: string\n readonly addonName: string\n readonly slot: PipelineSlot\n readonly inputClasses: readonly string[]\n readonly outputClasses: readonly string[]\n readonly enabled: boolean\n readonly modelId: string\n readonly children: readonly PipelineStepDisplayConfig[]\n /** Independent engine override — only used by audio-classifier steps */\n readonly engine?: PipelineEngineChoice\n /** UI grouping — steps with the same group are displayed under one heading */\n readonly group?: string\n /** Current values for the step's configSchema fields */\n readonly settings?: Record<string, unknown>\n}\n\nexport interface PipelineStepProps {\n readonly step: PipelineStepDisplayConfig\n readonly schema: PipelineAddonSchema | null\n /** Full schema map so children can look up their own schema */\n readonly allSchemas: ReadonlyMap<string, PipelineAddonSchema>\n readonly depth?: number\n readonly onChange: (updated: PipelineStepDisplayConfig) => void\n readonly onDelete?: (addonId: string) => void\n readonly readOnly?: boolean\n /**\n * Toggle mode:\n * - `'simple'` (default) — header shows a single on/off switch that drives\n * `step.enabled` directly. Used on the agent page (`NodePipelineTab`)\n * where toggling IS the final state.\n * - `'threeState'` — header shows a 3-button segmented control\n * `[Inherit | On | Off]`. `overrideState` is the current override value\n * (`true` / `false` / `null` for inherit). When the override changes,\n * `onOverrideChange` fires. `step.enabled` still renders the effective\n * state (inherited agent default OR override). Used on the camera page\n * where the user edits a SPARSE override over the agent baseline.\n */\n readonly toggleMode?: 'simple' | 'threeState'\n /**\n * 3-state override value when `toggleMode === 'threeState'`. `null` or\n * `undefined` means \"inherit\" (no override active). Ignored in `'simple'` mode.\n */\n readonly overrideState?: boolean | null\n /** Fired when the user flips the 3-state toggle in `'threeState'` mode. */\n readonly onOverrideChange?: (next: boolean | null) => void\n /** Agent's default enabled value, shown as an annotation in `'threeState'` mode. */\n readonly inheritedEnabled?: boolean\n /**\n * Hide the Model dropdown + dynamic configSchema controls inside the\n * expanded config panel. Used on the camera page where the step's\n * model + settings are agent-level — a camera can land on any agent,\n * so exposing agent-level knobs here would be misleading. Agent I/O\n * tags, engine selector (audio), and the step name stay visible.\n */\n readonly hideModelAndSettings?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Helpers — compute available models for a specific step\n// ---------------------------------------------------------------------------\n\nfunction modelsForStep(\n schema: PipelineAddonSchema | null,\n): readonly { id: string; name: string }[] {\n if (!schema) return []\n return schema.models.map(m => ({ id: m.id, name: m.name }))\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function PipelineStep({\n step,\n schema,\n allSchemas: _allSchemas,\n depth: _depth = 0,\n onChange,\n onDelete: _onDelete,\n readOnly = false,\n toggleMode = 'simple',\n overrideState = null,\n onOverrideChange,\n inheritedEnabled,\n hideModelAndSettings = false,\n}: PipelineStepProps) {\n const [expanded, setExpanded] = useState(false)\n\n const models = modelsForStep(schema)\n\n // Auto-correct: if the selected model is not in the list, switch to default or first\n if (models.length > 0 && !models.some(m => m.id === step.modelId) && !readOnly) {\n const defaultModel = schema?.defaultModelId ? models.find(m => m.id === schema.defaultModelId) : null\n const fallback = defaultModel ?? models[0]\n if (fallback && fallback.id !== step.modelId) {\n queueMicrotask(() => onChange({ ...step, modelId: fallback.id }))\n }\n }\n\n const header = (\n <>\n <div className=\"flex-1 min-w-0\">\n <span className=\"text-[10px] uppercase tracking-wider font-medium text-foreground-subtle/60 block leading-none\">{step.slot}</span>\n <span className=\"text-sm font-semibold text-foreground truncate block leading-tight\">{step.addonName}</span>\n <div className=\"flex items-center gap-1 mt-0.5 flex-wrap\">\n {step.inputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/12 text-blue-400\">{c}</span>\n ))}\n {step.inputClasses.length > 0 && step.outputClasses.length > 0 && (\n <span className=\"text-foreground-subtle/40 text-[10px]\">→</span>\n )}\n {step.outputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/12 text-green-400\">{c}</span>\n ))}\n </div>\n </div>\n\n {!readOnly && toggleMode === 'simple' && (\n <button\n onClick={e => { e.stopPropagation(); onChange({ ...step, enabled: !step.enabled }) }}\n className={cn(\n 'relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors',\n step.enabled ? 'bg-success' : 'bg-foreground-subtle/30',\n )}\n >\n <span className={cn(\n 'inline-block h-4 w-4 rounded-full bg-white shadow transition-transform',\n step.enabled ? 'translate-x-6' : 'translate-x-1',\n )} />\n </button>\n )}\n {!readOnly && toggleMode === 'threeState' && onOverrideChange && (\n <div\n className=\"flex items-center gap-0.5 rounded-md border border-border p-0.5\"\n onClick={e => e.stopPropagation()}\n >\n <ThreeStateButton label=\"Inherit\" active={overrideState === null} variant=\"inherit\"\n subtext={inheritedEnabled === undefined ? undefined : (inheritedEnabled ? 'on' : 'off')}\n onClick={() => onOverrideChange(null)} />\n <ThreeStateButton label=\"On\" active={overrideState === true} variant=\"on\"\n onClick={() => onOverrideChange(true)} />\n <ThreeStateButton label=\"Off\" active={overrideState === false} variant=\"off\"\n onClick={() => onOverrideChange(false)} />\n </div>\n )}\n </>\n )\n\n return (\n <CollapsibleCard\n expanded={expanded}\n onExpandedChange={setExpanded}\n dimmed={!step.enabled}\n header={header}\n >\n {hideModelAndSettings ? (\n <p className=\"text-[11px] text-foreground-subtle\">\n Model and detection settings are managed per agent — open the Pipeline page for this camera's agent to edit them.\n </p>\n ) : (\n <div className=\"space-y-3\">\n <ConfigSelect label=\"Model\" value={step.modelId} disabled={readOnly}\n options={models.map(m => ({ value: m.id, label: m.name }))}\n onChange={v => onChange({ ...step, modelId: v })} />\n\n {/* Engine selector — only for audio-classifier (independent runtime) */}\n {step.slot === 'audio-classifier' && step.engine && (\n <ConfigSelect\n label=\"Runtime\"\n value={`${step.engine.runtime}/${step.engine.backend}`}\n disabled={readOnly}\n options={[\n { value: 'node/cpu', label: 'Node.js — ONNX CPU' },\n { value: 'node/coreml', label: 'Node.js — Apple SoundAnalysis (macOS)' },\n { value: 'python/cpu', label: 'Python — ONNX CPU' },\n ]}\n onChange={v => {\n const [runtime, backend] = v.split('/') as [string, string]\n const format = backend === 'coreml' ? 'coreml' : 'onnx'\n onChange({ ...step, engine: { runtime: runtime as 'node' | 'python', backend, format: format as 'onnx' | 'coreml' } })\n }}\n />\n )}\n\n {/* ── Dynamic configSchema fields ─────────────────────── */}\n {schema?.configSchema?.map(field => (\n <ConfigSchemaField\n key={field.key}\n field={field}\n allFields={schema.configSchema ?? []}\n step={step}\n disabled={readOnly}\n onChange={onChange}\n />\n ))}\n </div>\n )}\n </CollapsibleCard>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Small config select — reusable for Model and other dropdowns\n// ---------------------------------------------------------------------------\n\nfunction ConfigSelect({ label, value, options, disabled, onChange }: {\n label: string\n value: string\n options: readonly { value: string; label: string; disabled?: boolean }[]\n disabled?: boolean\n onChange: (value: string) => void\n}) {\n return (\n <div>\n <label className=\"block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1.5\">\n {label}\n </label>\n <select\n value={value}\n onChange={e => onChange(e.target.value)}\n disabled={disabled}\n className=\"w-full rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground focus:outline-none focus:border-primary/50\"\n >\n {options.length === 0 && <option value={value}>{value || 'default'}</option>}\n {options.map(o => (\n <option key={o.value} value={o.value} disabled={o.disabled}>{o.label}</option>\n ))}\n </select>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// ConfigMultiSelect — chip-style toggle for multiselect fields\n// ---------------------------------------------------------------------------\n\nfunction ConfigMultiSelect({ label, description, value, options, disabled, onChange }: {\n label: string\n description?: string\n value: readonly string[]\n options: readonly { value: string; label: string }[]\n disabled?: boolean\n onChange: (selected: string[]) => void\n}) {\n function toggle(opt: string) {\n if (disabled) return\n const next = value.includes(opt)\n ? value.filter(v => v !== opt)\n : [...value, opt]\n onChange(next)\n }\n\n return (\n <div>\n <label className=\"block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1\">\n {label}\n </label>\n {description && (\n <p className=\"text-[10px] text-foreground-subtle/60 mb-1.5\">{description}</p>\n )}\n <div className=\"flex flex-wrap gap-1.5\">\n {options.map(o => {\n const selected = value.includes(o.value)\n return (\n <button\n key={o.value}\n type=\"button\"\n disabled={disabled}\n onClick={() => toggle(o.value)}\n className={cn(\n 'text-[10px] font-medium px-2 py-1 rounded-md border transition-colors',\n selected\n ? 'bg-primary/20 text-primary border-primary/40'\n : 'bg-surface text-foreground-subtle border-border hover:border-primary/30',\n disabled && 'opacity-50 cursor-not-allowed',\n )}\n >\n {o.label}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// ConfigSchemaField — resolves a single ConfigField to the right control\n// ---------------------------------------------------------------------------\n\nfunction resolveSettingValue(key: string, step: PipelineStepDisplayConfig, allFields: readonly ConfigField[]): unknown {\n const explicit = step.settings?.[key]\n if (explicit !== undefined) return explicit\n const sibling = allFields.find(f => 'key' in f && f.key === key)\n return sibling && 'default' in sibling ? sibling.default : undefined\n}\n\nexport function ConfigSchemaField({ field, allFields, step, disabled, onChange }: {\n field: ConfigField\n allFields: readonly ConfigField[]\n step: PipelineStepDisplayConfig\n disabled: boolean\n onChange: (updated: PipelineStepDisplayConfig) => void\n}) {\n // Evaluate showWhen condition — resolve value with default fallback\n const showWhen = field.type !== 'separator' && field.type !== 'info' ? (field as { showWhen?: import('@camstack/types').ConfigCondition }).showWhen : undefined\n if (showWhen) {\n const { field: condField, equals, notEquals, in: inList, notIn } = showWhen\n const current = resolveSettingValue(condField, step, allFields)\n if (equals !== undefined && current !== equals) return null\n if (notEquals !== undefined && current === notEquals) return null\n if (inList !== undefined && !inList.includes(current)) return null\n if (notIn !== undefined && notIn.includes(current)) return null\n }\n\n function handleChange(newValue: unknown) {\n onChange({ ...step, settings: { ...step.settings, [field.key]: newValue } })\n }\n\n if (field.type === 'select') {\n const raw = step.settings?.[field.key]\n const current = typeof raw === 'string' ? raw : (field.default as string | undefined) ?? ''\n return (\n <ConfigSelect\n label={field.label}\n value={current}\n disabled={disabled || field.disabled}\n options={field.options}\n onChange={handleChange}\n />\n )\n }\n\n if (field.type === 'multiselect') {\n const raw = step.settings?.[field.key]\n const current: readonly string[] = Array.isArray(raw)\n ? (raw as string[])\n : Array.isArray(field.default) ? (field.default as string[]) : []\n return (\n <ConfigMultiSelect\n label={field.label}\n description={field.description}\n value={current}\n options={field.options}\n disabled={disabled || field.disabled}\n onChange={handleChange}\n />\n )\n }\n\n if (field.type === 'slider' || field.type === 'number') {\n const raw = step.settings?.[field.key]\n const fallback = typeof field.default === 'number' ? field.default : field.min ?? 0\n const current = typeof raw === 'number' ? raw : fallback\n const min = field.min ?? 0\n const max = field.max ?? 1\n const step_ = field.step ?? 0.01\n const showValue = field.type === 'slider' ? field.showValue : true\n const unit = 'unit' in field ? field.unit : undefined\n const displayScale = field.type === 'slider' ? field.displayScale : undefined\n const display = displayScale ? current / displayScale : current\n return (\n <div>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-[10px] font-medium text-foreground-subtle uppercase tracking-wide\">\n {field.label}\n </span>\n {showValue && (\n <span className=\"text-xs font-medium text-foreground tabular-nums\">\n {typeof display === 'number' ? display.toFixed(2).replace(/\\.?0+$/, '') : display}\n {unit ? ` ${unit}` : ''}\n </span>\n )}\n </div>\n {field.description && (\n <p className=\"text-[10px] text-foreground-subtle/60 mb-1.5\">{field.description}</p>\n )}\n <input\n type=\"range\"\n min={min}\n max={max}\n step={step_}\n value={current}\n disabled={disabled || field.disabled}\n onChange={(e) => handleChange(Number(e.target.value))}\n className=\"w-full accent-primary h-1.5\"\n />\n </div>\n )\n }\n\n if (field.type === 'boolean') {\n const raw = step.settings?.[field.key]\n const current = typeof raw === 'boolean' ? raw : field.default === true\n return (\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={current}\n disabled={disabled || field.disabled}\n onChange={(e) => handleChange(e.target.checked)}\n className=\"h-3.5 w-3.5 accent-primary\"\n />\n <span className=\"text-[10px] font-medium text-foreground-subtle uppercase tracking-wide\">\n {field.label}\n </span>\n </label>\n )\n }\n\n if (field.type === 'text' || field.type === 'password' || field.type === 'textarea') {\n const raw = step.settings?.[field.key]\n const current = typeof raw === 'string' ? raw : (field.default as string | undefined) ?? ''\n const inputType = field.type === 'password' ? 'password' : 'text'\n return (\n <div>\n <label className=\"block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1.5\">\n {field.label}\n </label>\n {field.type === 'textarea' ? (\n <textarea\n value={current}\n disabled={disabled || field.disabled}\n placeholder={field.placeholder}\n onChange={(e) => handleChange(e.target.value)}\n rows={3}\n className=\"w-full rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground focus:outline-none focus:border-primary/50 resize-y\"\n />\n ) : (\n <input\n type={inputType}\n value={current}\n disabled={disabled || field.disabled}\n placeholder={field.placeholder}\n onChange={(e) => handleChange(e.target.value)}\n className=\"w-full rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground focus:outline-none focus:border-primary/50\"\n />\n )}\n </div>\n )\n }\n\n if (field.type === 'separator') {\n return <div className=\"border-t border-border my-2\" />\n }\n\n if (field.type === 'info') {\n return (\n <div className=\"rounded-md border border-border bg-surface px-2 py-1.5 text-[10px] text-foreground-subtle\">\n {field.content}\n </div>\n )\n }\n\n // Unsupported field type — render nothing rather than crash.\n // This branch should be unreachable for the field kinds used by pipeline\n // steps; if a new kind is introduced, add a case above.\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Three-state toggle button (camera-level override: Inherit / On / Off)\n// ---------------------------------------------------------------------------\n\ninterface ThreeStateButtonProps {\n readonly label: string\n readonly active: boolean\n readonly variant: 'inherit' | 'on' | 'off'\n readonly subtext?: string\n readonly onClick: () => void\n}\n\nfunction ThreeStateButton({ label, active, variant, subtext, onClick }: ThreeStateButtonProps) {\n const activeClasses = active\n ? variant === 'on' ? 'bg-green-500/20 text-green-400'\n : variant === 'off' ? 'bg-red-500/20 text-red-400'\n : 'bg-primary/20 text-primary'\n : 'text-foreground-subtle hover:bg-surface-hover'\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'px-2 py-1 text-[10px] font-medium rounded transition-colors',\n activeClasses,\n )}\n >\n {label}\n {subtext && active && <span className=\"ml-1 opacity-60\">({subtext})</span>}\n </button>\n )\n}\n","import { type ReactNode, useMemo } from 'react'\nimport type { StepTreeNode } from './step-tree-master'\nimport type { PipelineSlot } from '@camstack/types'\nimport { cn } from '../lib/cn'\n\nexport interface AgentColumn {\n readonly agentNodeId: string\n readonly engineLabel: string\n}\n\nexport type CellState =\n | { readonly kind: 'enabled'; readonly modelId: string }\n | { readonly kind: 'disabled' }\n | { readonly kind: 'na' }\n\nexport interface PipelineTreeMatrixProps {\n readonly tree: readonly StepTreeNode[]\n readonly agents: readonly AgentColumn[]\n readonly getCellState: (addonId: string, agentNodeId: string) => CellState\n readonly onCellClick: (addonId: string, agentNodeId: string) => void\n readonly selectedCell: { readonly addonId: string; readonly agentNodeId: string } | null\n /**\n * Optional inline on/off toggle next to each step name. Only useful\n * in single-agent mode (per-node pipeline tab) where the row already\n * targets one (agent, addon) pair unambiguously. The matrix renders\n * the toggle when this callback is set AND `agents.length === 1`.\n */\n readonly onToggleEnabled?: (addonId: string, next: boolean) => void\n}\n\ninterface FlatRow {\n readonly node: StepTreeNode\n readonly depth: number\n}\n\nfunction flattenTree(nodes: readonly StepTreeNode[]): readonly FlatRow[] {\n const out: FlatRow[] = []\n const walk = (list: readonly StepTreeNode[], depth: number): void => {\n for (const n of list) {\n out.push({ node: n, depth })\n walk(n.children, depth + 1)\n }\n }\n walk(nodes, 0)\n return out\n}\n\nconst SLOT_LABEL: Record<PipelineSlot, { readonly label: string; readonly className: string }> = {\n detector: {\n label: 'detector',\n className: 'text-emerald-500',\n },\n cropper: {\n label: 'cropper',\n className: 'text-blue-500',\n },\n classifier: {\n label: 'classifier',\n className: 'text-violet-500',\n },\n refiner: {\n label: 'refiner',\n className: 'text-amber-500',\n },\n 'audio-classifier': {\n label: 'audio classifier',\n className: 'text-pink-500',\n },\n}\n\nfunction SlotHeading({ slot }: { readonly slot: PipelineSlot }) {\n const cfg = SLOT_LABEL[slot] ?? SLOT_LABEL.classifier\n return (\n <span\n className={cn(\n 'text-[9px] font-semibold uppercase tracking-widest leading-none',\n cfg.className,\n )}\n >\n {cfg.label}\n </span>\n )\n}\n\nconst CLASS_PILL = 'inline-flex items-center rounded bg-muted px-1.5 py-px text-[9px] font-medium text-foreground-subtle'\n\nfunction ClassChips({\n inputs,\n outputs,\n}: {\n readonly inputs: readonly string[]\n readonly outputs: readonly string[]\n}) {\n if (inputs.length === 0 && outputs.length === 0) return null\n return (\n <span className=\"inline-flex items-center gap-1 flex-wrap\">\n {inputs.map((c) => (\n <span key={`in-${c}`} className={cn(CLASS_PILL, 'bg-blue-500/10 text-blue-500')}>\n {c}\n </span>\n ))}\n {inputs.length > 0 && outputs.length > 0 && (\n <span className=\"text-foreground-subtle/60 text-[9px]\">→</span>\n )}\n {outputs.map((c) => (\n <span key={`out-${c}`} className={cn(CLASS_PILL, 'bg-emerald-500/10 text-emerald-500')}>\n {c}\n </span>\n ))}\n </span>\n )\n}\n\ninterface ToggleProps {\n readonly enabled: boolean\n readonly onChange: (next: boolean) => void\n readonly disabled?: boolean\n}\n\nfunction QuickToggle({ enabled, onChange, disabled }: ToggleProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={enabled}\n disabled={disabled}\n onClick={(e) => {\n e.stopPropagation()\n onChange(!enabled)\n }}\n className={cn(\n 'relative inline-flex h-3.5 w-7 shrink-0 items-center rounded-full transition-colors',\n enabled ? 'bg-emerald-500' : 'bg-foreground-subtle/30',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n )}\n title={enabled ? 'Click to disable' : 'Click to enable'}\n >\n <span\n className={cn(\n 'inline-block h-3 w-3 rounded-full bg-white shadow transition-transform',\n enabled ? 'translate-x-3.5' : 'translate-x-0.5',\n )}\n />\n </button>\n )\n}\n\nfunction renderCellContent(state: CellState): ReactNode {\n if (state.kind === 'enabled') {\n return (\n <span className=\"inline-flex items-center gap-1\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 shrink-0\" />\n <span className=\"font-mono text-foreground\">{state.modelId}</span>\n </span>\n )\n }\n if (state.kind === 'disabled') {\n return (\n <span className=\"inline-flex items-center gap-1 text-foreground-subtle\">\n <span className=\"h-1.5 w-1.5 rounded-full border border-foreground-subtle/60 shrink-0\" />\n off\n </span>\n )\n }\n return (\n <span className=\"inline-flex items-center gap-1 text-foreground-subtle/70\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-muted shrink-0\" />\n n/a\n </span>\n )\n}\n\ninterface RowProps {\n readonly node: StepTreeNode\n readonly depth: number\n readonly agents: readonly AgentColumn[]\n readonly getCellState: (addonId: string, agentNodeId: string) => CellState\n readonly onCellClick: (addonId: string, agentNodeId: string) => void\n readonly selectedCell: { readonly addonId: string; readonly agentNodeId: string } | null\n readonly toggleProps?: { readonly enabled: boolean; readonly onChange: (next: boolean) => void; readonly disabled?: boolean }\n}\n\nfunction Row({ node, depth, agents, getCellState, onCellClick, selectedCell, toggleProps }: RowProps) {\n return (\n <>\n <div\n className=\"sticky left-0 z-10 bg-surface px-3 py-2 border-b border-border text-xs flex items-start gap-2\"\n style={{ paddingLeft: `${12 + depth * 14}px` }}\n >\n <div className=\"flex flex-col gap-1 min-w-0 flex-1\">\n <SlotHeading slot={node.slot} />\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-semibold truncate\">{node.addonName}</span>\n <ClassChips inputs={node.inputClasses} outputs={node.outputClasses} />\n </div>\n </div>\n {toggleProps && (\n <span className=\"pl-2 pt-0.5 shrink-0\">\n <QuickToggle\n enabled={toggleProps.enabled}\n onChange={toggleProps.onChange}\n disabled={toggleProps.disabled}\n />\n </span>\n )}\n </div>\n {agents.map((a) => {\n const state = getCellState(node.addonId, a.agentNodeId)\n const isSelected = selectedCell?.addonId === node.addonId && selectedCell.agentNodeId === a.agentNodeId\n return (\n <button\n key={a.agentNodeId}\n type=\"button\"\n onClick={() => onCellClick(node.addonId, a.agentNodeId)}\n className={cn(\n 'text-left px-3 py-1.5 border-b border-l border-border text-xs hover:bg-muted/40',\n state.kind === 'enabled' && 'bg-emerald-500/5',\n state.kind === 'na' && 'bg-muted/30',\n isSelected && 'ring-2 ring-primary ring-inset',\n )}\n >\n {renderCellContent(state)}\n </button>\n )\n })}\n </>\n )\n}\n\nexport function PipelineTreeMatrix({\n tree,\n agents,\n getCellState,\n onCellClick,\n selectedCell,\n onToggleEnabled,\n}: PipelineTreeMatrixProps) {\n const rows = useMemo(() => flattenTree(tree), [tree])\n const gridTemplate = `minmax(320px, 1fr) repeat(${agents.length}, minmax(160px, 220px))`\n const showToggle = onToggleEnabled !== undefined && agents.length === 1\n const onlyAgent = agents[0]?.agentNodeId\n\n return (\n <div className=\"overflow-auto border border-border rounded\">\n <div className=\"grid\" style={{ gridTemplateColumns: gridTemplate }}>\n <div className=\"sticky top-0 left-0 z-20 bg-muted/60 px-3 py-2 text-[10px] uppercase tracking-widest text-foreground-subtle border-b border-border\">\n Step\n </div>\n {agents.map((a) => (\n <div\n key={a.agentNodeId}\n className=\"sticky top-0 z-10 bg-muted/60 px-3 py-2 border-b border-l border-border\"\n >\n <div className=\"text-xs font-semibold text-foreground\">{a.agentNodeId}</div>\n <div className=\"text-[10px] text-foreground-subtle truncate\">{a.engineLabel}</div>\n </div>\n ))}\n\n {rows.map(({ node, depth }) => {\n const cellState = showToggle && onlyAgent !== undefined\n ? getCellState(node.addonId, onlyAgent)\n : null\n const toggleProps = showToggle && cellState !== null\n ? {\n enabled: cellState.kind === 'enabled',\n onChange: (next: boolean) => onToggleEnabled?.(node.addonId, next),\n disabled: cellState.kind === 'na',\n }\n : undefined\n return (\n <Row\n key={node.addonId}\n node={node}\n depth={depth}\n agents={agents}\n getCellState={getCellState}\n onCellClick={onCellClick}\n selectedCell={selectedCell}\n toggleProps={toggleProps}\n />\n )\n })}\n </div>\n </div>\n )\n}\n","/**\n * NodePicker — shared cluster-node pill bar.\n *\n * Uses `useClusterNodes` hook so every consumer hits the same React-Query\n * cache. Renders a `Server` icon + label + segmented pill bar with one\n * button per online node, hub first.\n *\n * Used by admin-ui Addons page, benchmark addon page, pipeline page, etc.\n */\nimport { Server } from 'lucide-react'\nimport { useClusterNodes } from '../hooks/use-cluster-nodes'\nimport { cn } from '../lib/cn'\n\nexport interface NodePickerProps {\n readonly selectedNodeId: string\n readonly onSelect: (nodeId: string) => void\n /** Caption shown before the pill bar. Defaults to `Node`. */\n readonly label?: string\n /** Hide the leading `Server` icon (compact toolbars). */\n readonly hideIcon?: boolean\n /**\n * When true, render even when only the hub is online. Useful when\n * the surrounding UI relies on the picker as a layout anchor; the\n * default hides the picker since there's nothing to choose.\n */\n readonly alwaysShow?: boolean\n}\n\nexport function NodePicker({\n selectedNodeId,\n onSelect,\n label = 'Node',\n hideIcon = false,\n alwaysShow = false,\n}: NodePickerProps) {\n const { nodes } = useClusterNodes()\n\n if (!alwaysShow && nodes.length <= 1) return null\n\n return (\n <div className=\"flex items-center gap-1.5\">\n {!hideIcon && <Server className=\"h-3.5 w-3.5 text-foreground-subtle\" />}\n {label && (\n <span className=\"text-[10px] uppercase tracking-wider text-foreground-subtle\">{label}</span>\n )}\n <div className=\"flex rounded-md border border-border overflow-hidden text-[11px] font-medium\">\n {nodes.map((node, idx) => {\n const isSelected = selectedNodeId === node.id\n return (\n <button\n key={node.id}\n type=\"button\"\n onClick={() => onSelect(node.id)}\n disabled={!node.isOnline}\n title={node.isOnline ? node.name : `${node.name} (offline)`}\n className={cn(\n 'px-2.5 py-1 transition-colors',\n isSelected\n ? 'bg-primary/15 text-primary'\n : 'bg-transparent text-foreground-subtle hover:bg-surface-hover hover:text-foreground',\n idx > 0 && 'border-l border-border',\n !node.isOnline && 'opacity-50 cursor-not-allowed',\n )}\n >\n {node.shortName}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n","/**\n * useClusterNodes — canonical cluster node topology hook.\n *\n * Bootstrap: fetches `nodes.topology` once on mount.\n * Live updates: subscribes to `cluster.topology-snapshot` events\n * which the hub emits on agent connect/disconnect/lifecycle changes.\n * Zero polling — pure event-driven.\n *\n * Shared across admin-ui, addon pages, and form fields (node-select,\n * node-multiselect, NodePicker).\n */\nimport { useMemo } from 'react'\nimport { trpc } from '../trpc-react'\nimport { useEventStreamLatest } from './use-event-stream'\n\nexport interface ClusterNode {\n readonly id: string\n readonly name: string\n /** Compact label for pill bars: \"HUB\" for the hub, agent name for agents. */\n readonly shortName: string\n readonly isHub: boolean\n readonly isOnline: boolean\n readonly localIps: readonly string[]\n readonly addons: readonly { readonly addonId: string; readonly capabilities: readonly string[] }[]\n}\n\ninterface TopologyNode {\n readonly id: string\n readonly name: string\n readonly isHub: boolean\n readonly isOnline: boolean\n readonly localIps?: readonly string[]\n readonly addons: ReadonlyArray<{ readonly id: string; readonly capabilities: readonly string[] }>\n}\n\nexport function useClusterNodes(): {\n readonly nodes: readonly ClusterNode[]\n readonly isLoading: boolean\n} {\n const { data: bootstrapTopology, isLoading } = trpc.nodes.topology.useQuery(undefined, {\n staleTime: 60_000,\n })\n\n // Live snapshot from hub — replaces bootstrap data once first event arrives\n const snapshot = useEventStreamLatest<{\n nodes: readonly TopologyNode[]\n timestamp: number\n }>('cluster.topology-snapshot')\n\n const sourceNodes: readonly TopologyNode[] | undefined =\n snapshot?.nodes ?? (bootstrapTopology as readonly TopologyNode[] | undefined)\n\n const nodes = useMemo<readonly ClusterNode[]>(() => {\n const list: ClusterNode[] = []\n for (const n of sourceNodes ?? []) {\n list.push({\n id: String(n.id ?? ''),\n name: String(n.name ?? n.id ?? ''),\n shortName: n.isHub ? 'HUB' : String(n.name ?? n.id ?? ''),\n isHub: Boolean(n.isHub),\n isOnline: Boolean(n.isOnline),\n localIps: (n.localIps ?? []) as string[],\n addons: (n.addons ?? []).map(a => ({ addonId: a.id, capabilities: a.capabilities })),\n })\n }\n list.sort((a, b) => {\n if (a.isHub !== b.isHub) return a.isHub ? -1 : 1\n return a.name.localeCompare(b.name)\n })\n return list\n }, [sourceNodes])\n\n return { nodes, isLoading }\n}\n","/**\n * Shared typed React Query proxy for the backend AppRouter.\n *\n * The proxy is exposed on `window.__camstackTrpcReact` so addon-page\n * bundles (which load AFTER the host admin-ui sets the global) reuse\n * the host's `createTRPCReact` instance instead of creating a separate\n * one. Sharing the instance is mandatory because the typed React-Query\n * hooks read from a Context registered inside the proxy — a duplicate\n * proxy would have its own Context, miss the host's `<trpc.Provider>`\n * tree, and crash with \"trpc client not found\" on first render.\n *\n * Boot order:\n * 1. admin-ui's `main.tsx` is the first script to evaluate this\n * module, sees `window.__camstackTrpcReact === undefined`,\n * creates the proxy, stashes it on the window.\n * 2. Addon bundles are loaded later by `AddonPageLoader` — when\n * their entrypoint evaluates this same module (resolved through\n * Vite alias to ui-library/src), the global is already set, so\n * they pick up the host instance and skip the second create.\n */\nimport { createTRPCReact, type CreateTRPCReact } from '@trpc/react-query'\nimport type { AppRouter } from '@camstack/types'\n\nexport type AppTrpcReact = CreateTRPCReact<AppRouter, unknown>\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __camstackTrpcReact: AppTrpcReact | undefined\n}\n\nconst existing: AppTrpcReact | undefined =\n typeof globalThis !== 'undefined' ? globalThis.__camstackTrpcReact : undefined\n\nexport const trpc: AppTrpcReact = existing ?? createTRPCReact<AppRouter>()\n\nif (typeof globalThis !== 'undefined' && !existing) {\n globalThis.__camstackTrpcReact = trpc\n}\n","/**\n * useEventStreamLatest — subscribe to a `live.onEvent` category and\n * keep the LATEST payload in React state. Zero polling — pure push.\n *\n * useEventStreamMap — same but accumulates per-key payloads into a map.\n */\nimport { useMemo, useRef, useState } from 'react'\nimport { useLiveEvent } from './use-live-event'\n\nfunction useFreshRef<T>(value: T): { readonly current: T } {\n const ref = useRef<T>(value)\n ref.current = value\n return ref\n}\n\nexport function useEventStreamLatest<T>(\n category: string,\n filter?: (data: T) => boolean,\n): T | null {\n const [data, setData] = useState<T | null>(null)\n const filterRef = useFreshRef(filter)\n useLiveEvent<T>(category, (evt) => {\n const payload = evt.data\n const f = filterRef.current\n if (f && !f(payload)) return\n setData(payload)\n })\n return data\n}\n\nexport function useEventStreamMap<T, K extends string | number>(\n category: string,\n keyOf: (data: T) => K,\n filter?: (data: T) => boolean,\n): { readonly map: ReadonlyMap<K, T>; readonly values: readonly T[] } {\n const [map, setMap] = useState<ReadonlyMap<K, T>>(() => new Map())\n const keyOfRef = useFreshRef(keyOf)\n const filterRef = useFreshRef(filter)\n useLiveEvent<T>(category, (evt) => {\n const payload = evt.data\n const f = filterRef.current\n if (f && !f(payload)) return\n const k = keyOfRef.current(payload)\n setMap((prev) => {\n const next = new Map(prev)\n next.set(k, payload)\n return next\n })\n })\n const values = useMemo(() => Array.from(map.values()), [map])\n return { map, values }\n}\n","/**\n * useLiveEvent — single-call subscription to the `live.onEvent` push\n * stream by category.\n *\n * Wraps `System.subscribeEvent` in a React-friendly shape: stable\n * callback ref so the consumer doesn't have to memoise, automatic\n * cleanup at unmount, and a tick on connection reset so subscriptions\n * re-bind to the freshly-rebuilt tRPC client after a forced reconnect\n * (login/logout, BFCache resume).\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { SystemLiveEvent } from '@camstack/sdk'\nimport { useSystem } from '../contexts/system-context.js'\n\nexport type LiveEventCallback<TData = unknown> = (event: SystemLiveEvent<TData>) => void\n\nexport function useLiveEvent<TData = unknown>(\n category: string,\n cb: LiveEventCallback<TData>,\n): void {\n const system = useSystem()\n // Latest-callback ref pattern — the effect captures the ref, not the\n // callback identity, so callers don't need to memoise their handler.\n const cbRef = useRef<LiveEventCallback<TData>>(cb)\n cbRef.current = cb\n\n // Bump on every fresh `'connected'` so the subscription rebuilds\n // against the new tRPC client after a reconnect.\n const [tick, setTick] = useState<number>(system.connectionVersion)\n useEffect(() => {\n return system.subscribeConnectionEvents((state, version) => {\n if (state === 'connected') setTick(version)\n })\n }, [system])\n\n useEffect(() => {\n const unsub = system.subscribeEvent<TData>(category, (evt) => {\n cbRef.current(evt)\n })\n return unsub\n }, [system, category, tick])\n}\n","/**\n * SystemContext — React-context plumbing for the unified `System` SDK\n * class.\n *\n * Phase 2 of the API consolidation makes `System` the single\n * client-side entry point. Pages/components reach the cluster through\n * the hooks in `../hooks/`; those hooks all read the `System`\n * instance from this context.\n *\n * The provider is intentionally stupid — it just stores the instance.\n * Lifecycle (`init()`, reconnect on auth change, watchdog) lives in\n * the host app (admin-ui's `App.tsx`) — the provider doesn't try to\n * own it because addon UIs may want to construct the System\n * differently (e.g. against a remote cluster).\n */\nimport { useContext, type ReactNode } from 'react'\nimport type { System } from '@camstack/sdk'\nimport { createSharedContext } from '../lib/shared-context'\n\n/**\n * Cross-bundle SystemContext sharing — see `lib/shared-context.ts` for\n * why this is global. Addon page bundles ship their own copy of\n * `@camstack/ui-library`, and without sharing each bundle's\n * `createContext()` produces a fresh instance that never matches the\n * host's `<SystemProvider>`.\n */\nconst SystemContext = createSharedContext<System | null>('camstack:system', null)\n\nexport interface SystemProviderProps {\n readonly system: System\n readonly children: ReactNode\n}\n\nexport function SystemProvider({ system, children }: SystemProviderProps) {\n return <SystemContext.Provider value={system}>{children}</SystemContext.Provider>\n}\n\n/**\n * Read the active `System` instance from the surrounding `<SystemProvider>`.\n * Throws when no provider is mounted — every hook in this directory\n * relies on the system, so a clear error beats a silent null.\n */\nexport function useSystem(): System {\n const sys = useContext(SystemContext)\n if (!sys) {\n throw new Error('useSystem(): no <SystemProvider> in tree')\n }\n return sys\n}\n\n/**\n * Variant that returns `null` instead of throwing — useful for\n * components that need to render before the provider is set up\n * (boot-time splash screens etc.).\n */\nexport function useOptionalSystem(): System | null {\n return useContext(SystemContext)\n}\n","import { cn } from '../lib/cn'\n\ntype Status = 'online' | 'offline' | 'degraded' | 'unknown'\n\nexport interface StatusBadgeProps {\n status: Status\n showDot?: boolean\n showLabel?: boolean\n size?: 'sm' | 'md'\n className?: string\n}\n\nconst statusConfig: Record<Status, { colorClass: string; label: string }> = {\n online: { colorClass: 'bg-success', label: 'Online' },\n offline: { colorClass: 'bg-danger', label: 'Offline' },\n degraded: { colorClass: 'bg-warning', label: 'Degraded' },\n unknown: { colorClass: 'bg-foreground-subtle', label: 'Unknown' },\n}\n\nexport function StatusBadge({\n status,\n showDot = true,\n showLabel = true,\n size = 'sm',\n className,\n}: StatusBadgeProps) {\n const config = statusConfig[status]\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5',\n size === 'sm' ? 'text-xs' : 'text-sm',\n className\n )}\n >\n {showDot && (\n <span\n className={cn('h-1.5 w-1.5 shrink-0 rounded-full', config.colorClass)}\n aria-hidden=\"true\"\n />\n )}\n {showLabel && (\n <span className=\"text-foreground\">{config.label}</span>\n )}\n </span>\n )\n}\n","import { cn } from '../lib/cn'\nimport type { ProviderType } from '../icons'\n\nexport interface ProviderBadgeProps {\n provider: ProviderType\n showLabel?: boolean\n className?: string\n}\n\nconst providerConfig: Record<ProviderType, { colorClass: string; label: string }> = {\n frigate: { colorClass: 'bg-provider-frigate', label: 'Frigate' },\n scrypted: { colorClass: 'bg-provider-scrypted', label: 'Scrypted' },\n reolink: { colorClass: 'bg-provider-reolink', label: 'Reolink' },\n homeAssistant: { colorClass: 'bg-provider-homeAssistant', label: 'Home Assistant' },\n rtsp: { colorClass: 'bg-provider-rtsp', label: 'RTSP' },\n}\n\nexport function ProviderBadge({\n provider,\n showLabel = true,\n className,\n}: ProviderBadgeProps) {\n const config = providerConfig[provider]\n\n return (\n <span className={cn('inline-flex items-center gap-1.5 text-xs', className)}>\n <span\n className={cn('h-1.5 w-1.5 shrink-0 rounded-sm', config.colorClass)}\n aria-hidden=\"true\"\n />\n {showLabel && (\n <span className=\"text-foreground\">{config.label}</span>\n )}\n </span>\n )\n}\n","import React from 'react'\nimport { cn } from '../lib/cn'\n\nexport type SemanticBadgeVariant = 'success' | 'warning' | 'danger' | 'info' | 'neutral'\n\nconst VARIANT_STYLES: Record<SemanticBadgeVariant, string> = {\n success: 'bg-emerald-400 text-emerald-950',\n warning: 'bg-amber-400 text-amber-950',\n danger: 'bg-red-400 text-red-950',\n info: 'bg-blue-400 text-blue-950',\n neutral: 'bg-foreground-subtle/20 text-foreground',\n}\n\nexport interface SemanticBadgeProps {\n children: React.ReactNode\n variant?: SemanticBadgeVariant\n /** Use monospace font (good for versions, codes) */\n mono?: boolean\n className?: string\n}\n\n/**\n * General-purpose badge with semantic color variants.\n * Solid background with dark text for maximum contrast.\n */\nexport function SemanticBadge({ children, variant = 'neutral', mono, className }: SemanticBadgeProps) {\n return (\n <span className={cn(\n 'inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-bold leading-tight',\n mono && 'font-mono',\n VARIANT_STYLES[variant],\n className,\n )}>\n {children}\n </span>\n )\n}\n\n// --- Convenience wrappers ---\n\nexport interface VersionBadgeProps {\n version: string\n preRelease?: boolean\n className?: string\n}\n\n/**\n * Version badge — auto-detects pre-release versions.\n * Stable = success (green), Pre-release = warning (amber).\n */\nexport function VersionBadge({ version, preRelease, className }: VersionBadgeProps) {\n const isPreRelease = preRelease ?? /-(alpha|beta|rc|dev|canary|next)/i.test(version)\n return (\n <SemanticBadge variant={isPreRelease ? 'warning' : 'success'} mono className={className}>\n {version}\n </SemanticBadge>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\nimport { Label } from '../primitives'\n\nexport interface FormFieldProps {\n label: string\n description?: string\n error?: string\n required?: boolean\n children: ReactNode\n orientation?: 'vertical' | 'horizontal'\n className?: string\n}\n\nexport function FormField({\n label,\n description,\n error,\n required,\n children,\n orientation = 'vertical',\n className,\n}: FormFieldProps) {\n const isHorizontal = orientation === 'horizontal'\n\n return (\n <div\n className={cn(\n 'flex gap-2',\n isHorizontal ? 'flex-row items-center justify-between' : 'flex-col',\n className\n )}\n >\n <div className={cn(isHorizontal ? 'flex-1' : '')}>\n <Label>\n {label}\n {required && <span className=\"text-danger ml-0.5\">*</span>}\n </Label>\n {description && (\n <p className=\"text-foreground-subtle text-xs mt-0.5\">{description}</p>\n )}\n </div>\n <div className={cn(isHorizontal ? 'shrink-0' : '')}>\n {children}\n </div>\n {error && (\n <p className=\"text-danger text-xs\">{error}</p>\n )}\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface PageHeaderProps {\n title: string\n subtitle?: string\n actions?: ReactNode\n className?: string\n}\n\nexport function PageHeader({ title, subtitle, actions, className }: PageHeaderProps) {\n return (\n <div className={cn('flex flex-col gap-2 mb-3 sm:flex-row sm:items-center sm:justify-between', className)}>\n <div>\n <h1 className=\"text-sm font-semibold text-foreground\">{title}</h1>\n {subtitle && (\n <p className=\"text-foreground-subtle text-xs\">{subtitle}</p>\n )}\n </div>\n {actions && <div className=\"flex items-center gap-2 flex-wrap\">{actions}</div>}\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { type LucideIcon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface EmptyStateProps {\n icon?: LucideIcon\n title: string\n description?: string\n action?: ReactNode\n className?: string\n}\n\nexport function EmptyState({\n icon: Icon,\n title,\n description,\n action,\n className,\n}: EmptyStateProps) {\n return (\n <div className={cn('flex flex-col items-center justify-center gap-3 py-12', className)}>\n {Icon && (\n <Icon className=\"h-12 w-12 text-foreground-subtle\" aria-hidden=\"true\" />\n )}\n <div className=\"flex flex-col items-center gap-1 text-center\">\n <p className=\"text-foreground-muted text-sm font-medium\">{title}</p>\n {description && (\n <p className=\"text-foreground-subtle text-xs max-w-xs\">{description}</p>\n )}\n </div>\n {action && <div className=\"mt-1\">{action}</div>}\n </div>\n )\n}\n","import { useState, useCallback, useContext, type ReactNode } from 'react'\nimport { createSharedContext } from '../lib/shared-context'\n\n// ---------------------------------------------------------------------------\n// Dialog state\n// ---------------------------------------------------------------------------\n\ninterface ConfirmOptions {\n title: string\n message: string\n confirmLabel?: string\n cancelLabel?: string\n variant?: 'danger' | 'warning' | 'default'\n}\n\ninterface ConfirmContextValue {\n confirm: (options: ConfirmOptions) => Promise<boolean>\n}\n\nconst ConfirmContext = createSharedContext<ConfirmContextValue | null>(\n 'camstack:confirm-dialog',\n null,\n)\n\nexport function useConfirm(): (options: ConfirmOptions) => Promise<boolean> {\n const ctx = useContext(ConfirmContext)\n if (!ctx) throw new Error('useConfirm must be used within ConfirmDialogProvider')\n return ctx.confirm\n}\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\ninterface DialogState extends ConfirmOptions {\n resolve: (value: boolean) => void\n}\n\nexport function ConfirmDialogProvider({ children }: { children: ReactNode }) {\n const [dialog, setDialog] = useState<DialogState | null>(null)\n\n const confirm = useCallback((options: ConfirmOptions): Promise<boolean> => {\n return new Promise<boolean>((resolve) => {\n setDialog({ ...options, resolve })\n })\n }, [])\n\n const handleConfirm = () => {\n dialog?.resolve(true)\n setDialog(null)\n }\n\n const handleCancel = () => {\n dialog?.resolve(false)\n setDialog(null)\n }\n\n const variantStyles = {\n danger: {\n icon: 'text-red-400',\n button: 'bg-red-500 hover:bg-red-600 text-white',\n },\n warning: {\n icon: 'text-orange-400',\n button: 'bg-orange-500 hover:bg-orange-600 text-white',\n },\n default: {\n icon: 'text-primary',\n button: 'bg-primary hover:bg-primary/90 text-white',\n },\n }\n\n const style = dialog ? variantStyles[dialog.variant ?? 'default'] : variantStyles.default\n\n return (\n <ConfirmContext.Provider value={{ confirm }}>\n {children}\n\n {/* Backdrop + Dialog */}\n {dialog && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={handleCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative z-10 w-full max-w-sm mx-4 rounded-xl border border-border bg-surface shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-150\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"px-5 pt-5 pb-4\">\n <h3 className=\"text-sm font-semibold text-foreground\">{dialog.title}</h3>\n <p className=\"mt-2 text-xs text-foreground-subtle leading-relaxed\">{dialog.message}</p>\n </div>\n\n <div className=\"flex justify-end gap-2 px-5 py-3 border-t border-border bg-surface-hover/30\">\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"px-3 py-1.5 text-xs font-medium rounded-md border border-border text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors\"\n >\n {dialog.cancelLabel ?? 'Cancel'}\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${style.button}`}\n >\n {dialog.confirmLabel ?? 'Confirm'}\n </button>\n </div>\n </div>\n </div>\n )}\n </ConfirmContext.Provider>\n )\n}\n","import { TrendingUp, TrendingDown } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Card } from '../primitives'\n\nexport interface StatCardProps {\n value: string | number\n label: string\n trend?: { value: number; direction: 'up' | 'down' }\n className?: string\n}\n\nexport function StatCard({ value, label, trend, className }: StatCardProps) {\n return (\n <Card className={cn('flex flex-col gap-1', className)}>\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-2xl font-semibold text-foreground\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'inline-flex items-center gap-0.5 text-xs font-medium',\n trend.direction === 'up' ? 'text-success' : 'text-danger'\n )}\n >\n {trend.direction === 'up' ? (\n <TrendingUp className=\"h-3 w-3\" />\n ) : (\n <TrendingDown className=\"h-3 w-3\" />\n )}\n {trend.value}%\n </span>\n )}\n </div>\n <span className=\"text-xs text-foreground-muted\">{label}</span>\n </Card>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface KeyValueListProps {\n items: { key: string; value: ReactNode }[]\n className?: string\n}\n\nexport function KeyValueList({ items, className }: KeyValueListProps) {\n return (\n <dl className={cn('flex flex-col', className)}>\n {items.map((item) => (\n <div\n key={item.key}\n className=\"flex items-center h-7\"\n >\n <dt className=\"text-foreground-subtle text-xs w-1/3 shrink-0\">\n {item.key}\n </dt>\n <dd className=\"text-foreground text-xs\">{item.value}</dd>\n </div>\n ))}\n </dl>\n )\n}\n","import { useCallback, useState } from 'react'\nimport { Copy, Check } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { ScrollArea, IconButton } from '../primitives'\n\nexport interface CodeBlockProps {\n children: string\n maxHeight?: number\n className?: string\n}\n\nexport function CodeBlock({ children, maxHeight = 300, className }: CodeBlockProps) {\n const [copied, setCopied] = useState(false)\n\n const handleCopy = useCallback(() => {\n navigator.clipboard.writeText(children).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n })\n }, [children])\n\n return (\n <div className={cn('relative group', className)}>\n <ScrollArea style={{ maxHeight }}>\n <pre className=\"font-mono text-xs bg-surface p-3 rounded-md border border-border-subtle\">\n <code>{children}</code>\n </pre>\n </ScrollArea>\n <div className=\"absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity\">\n <IconButton\n icon={copied ? Check : Copy}\n aria-label=\"Copy code\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCopy}\n />\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport { Search, SlidersHorizontal } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Input, Select, Badge, BottomSheet } from '../primitives'\nimport { useIsMobile } from '../hooks/use-is-mobile'\n\ntype FilterDef =\n | { type: 'search'; key: string; placeholder?: string }\n | { type: 'select'; key: string; label: string; options: { value: string; label: string }[] }\n | { type: 'badge-toggle'; key: string; options: { value: string; label: string }[] }\n\nexport type { FilterDef }\n\nexport interface FilterBarProps {\n filters: FilterDef[]\n values: Record<string, unknown>\n onChange: (values: Record<string, unknown>) => void\n className?: string\n}\n\nexport function FilterBar({ filters, values, onChange, className }: FilterBarProps) {\n const isMobile = useIsMobile()\n const [sheetOpen, setSheetOpen] = useState(false)\n\n const handleChange = (key: string, value: unknown) => {\n onChange({ ...values, [key]: value })\n }\n\n const activeCount = Object.values(values).filter((v) => v !== undefined && v !== '').length\n\n if (isMobile) {\n const searchFilter = filters.find((f) => f.type === 'search')\n const hasNonSearchFilters = filters.some((f) => f.type !== 'search')\n\n return (\n <div className={cn('flex items-center gap-2', className)}>\n {searchFilter && (\n <Input\n placeholder={searchFilter.placeholder ?? 'Search...'}\n value={(values[searchFilter.key] as string) ?? ''}\n onChange={(e) => handleChange(searchFilter.key, e.target.value)}\n leftSlot={<Search className=\"h-3 w-3 text-foreground-subtle\" />}\n className=\"flex-1\"\n />\n )}\n {hasNonSearchFilters && (\n <>\n <button\n onClick={() => setSheetOpen(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1.5 text-xs text-foreground-muted hover:bg-surface-hover transition-colors shrink-0\"\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {activeCount > 0 && (\n <Badge variant=\"info\" className=\"ml-1 text-[10px] px-1 py-0\">{activeCount}</Badge>\n )}\n </button>\n <BottomSheet open={sheetOpen} onClose={() => setSheetOpen(false)} title=\"Filters\">\n <div className=\"flex flex-col gap-3\">\n {filters.filter((f) => f.type !== 'search').map((filter) => {\n switch (filter.type) {\n case 'select':\n return (\n <div key={filter.key}>\n <label className=\"text-xs text-foreground-muted mb-1 block\">{filter.label}</label>\n <Select\n options={filter.options}\n value={(values[filter.key] as string) ?? ''}\n onChange={(e) => handleChange(filter.key, e.target.value)}\n className=\"w-full\"\n />\n </div>\n )\n case 'badge-toggle':\n return (\n <div key={filter.key} className=\"flex items-center gap-1 flex-wrap\">\n {filter.options.map((option) => {\n const currentValue = values[filter.key]\n const isActive = currentValue === option.value\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => handleChange(filter.key, isActive ? undefined : option.value)}\n >\n <Badge variant={isActive ? 'info' : 'default'} className=\"cursor-pointer\">\n {option.label}\n </Badge>\n </button>\n )\n })}\n </div>\n )\n default:\n return null\n }\n })}\n </div>\n </BottomSheet>\n </>\n )}\n </div>\n )\n }\n\n return (\n <div className={cn('flex items-center gap-2 flex-wrap', className)}>\n {filters.map((filter) => {\n switch (filter.type) {\n case 'search':\n return (\n <Input\n key={filter.key}\n placeholder={filter.placeholder ?? 'Search...'}\n value={(values[filter.key] as string) ?? ''}\n onChange={(e) => handleChange(filter.key, e.target.value)}\n leftSlot={<Search className=\"h-3 w-3 text-foreground-subtle\" />}\n className=\"w-48\"\n />\n )\n case 'select':\n return (\n <Select\n key={filter.key}\n options={filter.options}\n value={(values[filter.key] as string) ?? ''}\n onChange={(e) => handleChange(filter.key, e.target.value)}\n className=\"w-36\"\n />\n )\n case 'badge-toggle':\n return (\n <div key={filter.key} className=\"flex items-center gap-1\">\n {filter.options.map((option) => {\n const currentValue = values[filter.key]\n const isActive = currentValue === option.value\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => handleChange(filter.key, isActive ? undefined : option.value)}\n >\n <Badge variant={isActive ? 'info' : 'default'} className=\"cursor-pointer\">\n {option.label}\n </Badge>\n </button>\n )\n })}\n </div>\n )\n default:\n return null\n }\n })}\n </div>\n )\n}\n","import { type LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport { Badge } from '../../primitives'\n\nexport interface SidebarItemProps {\n label: string\n icon: LucideIcon\n href: string\n badge?: string | number\n active?: boolean\n className?: string\n}\n\nexport function SidebarItem({\n label,\n icon: Icon,\n href,\n badge,\n active = false,\n className,\n}: SidebarItemProps) {\n return (\n <a\n href={href}\n className={cn(\n 'flex items-center gap-2 h-7 px-2 text-[11px] transition-colors',\n active\n ? 'border-l-2 border-primary bg-primary/[0.08] text-foreground rounded-r-md'\n : 'text-foreground-subtle hover:bg-surface-hover rounded-md',\n className\n )}\n >\n <Icon className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1\">{label}</span>\n {badge !== undefined && (\n <Badge className=\"ml-auto text-[10px] px-1.5 py-0\">{badge}</Badge>\n )}\n </a>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { Separator } from '../../primitives'\nimport { SidebarItem, type SidebarItemProps } from './sidebar-item'\n\nexport interface SidebarSection {\n label?: string\n items: SidebarItemProps[]\n}\n\nexport interface SidebarProps {\n logo?: ReactNode\n sections: SidebarSection[]\n footer?: SidebarItemProps[]\n onNavigate?: () => void\n className?: string\n}\n\nexport function Sidebar({ logo, sections, footer, onNavigate, className }: SidebarProps) {\n return (\n <nav\n className={cn(\n 'bg-surface border-r border-border h-full flex flex-col',\n className\n )}\n >\n {logo && <div className=\"px-3 py-2 shrink-0\">{logo}</div>}\n\n <div className=\"flex-1 overflow-auto px-1 py-1\">\n {sections.map((section, sectionIndex) => (\n <div key={sectionIndex} className={cn(sectionIndex > 0 ? 'mt-3' : '')}>\n {section.label && (\n <span className=\"text-[10px] text-foreground-disabled uppercase tracking-wider px-2 mb-1 block\">\n {section.label}\n </span>\n )}\n <div className=\"flex flex-col gap-0.5\" onClick={onNavigate}>\n {section.items.map((item) => (\n <SidebarItem key={item.href} {...item} />\n ))}\n </div>\n </div>\n ))}\n </div>\n\n {footer && footer.length > 0 && (\n <div className=\"shrink-0 px-1 pb-1\">\n <Separator className=\"mb-1\" />\n <div className=\"flex flex-col gap-0.5\" onClick={onNavigate}>\n {footer.map((item) => (\n <SidebarItem key={item.href} {...item} />\n ))}\n </div>\n </div>\n )}\n </nav>\n )\n}\n","import { type ReactNode, useState } from 'react'\nimport { ChevronRight, Menu } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport { useIsMobile } from '../../hooks/use-is-mobile'\nimport { MobileDrawer } from '../../primitives/mobile-drawer'\nimport { Sidebar, type SidebarProps } from './sidebar'\n\nexport interface AppShellProps {\n sidebar: SidebarProps\n header?: {\n breadcrumbs?: { label: string; href?: string }[]\n actions?: ReactNode\n }\n /** Content shown in the center of the mobile top bar (e.g. logo) */\n mobileLogo?: ReactNode\n /** Content shown on the right side of the mobile top bar (e.g. avatar menu) */\n mobileActions?: ReactNode\n children: ReactNode\n className?: string\n}\n\nexport function AppShell({ sidebar, header, mobileLogo, mobileActions, children, className }: AppShellProps) {\n const isMobile = useIsMobile()\n const [drawerOpen, setDrawerOpen] = useState(false)\n\n return (\n <div className={cn('flex h-screen', className)}>\n {/* Desktop sidebar */}\n {!isMobile && <Sidebar {...sidebar} className={cn('w-44', sidebar.className)} />}\n\n {/* Mobile drawer */}\n {isMobile && (\n <MobileDrawer open={drawerOpen} onClose={() => setDrawerOpen(false)} width=\"w-64\">\n <Sidebar\n {...sidebar}\n onNavigate={() => setDrawerOpen(false)}\n className=\"w-full border-r-0\"\n />\n </MobileDrawer>\n )}\n\n <div className=\"flex flex-1 flex-col min-w-0\">\n {/* Mobile top bar */}\n {isMobile && (\n <header className=\"flex items-center h-12 border-b border-border px-3 shrink-0 bg-surface/80 backdrop-blur-sm\">\n <button\n onClick={() => setDrawerOpen(true)}\n className=\"p-1.5 -ml-1.5 rounded-md hover:bg-surface-hover text-foreground-muted transition-colors\"\n aria-label=\"Open menu\"\n >\n <Menu className=\"h-5 w-5\" />\n </button>\n {mobileLogo && <div className=\"flex-1 flex justify-center\">{mobileLogo}</div>}\n {mobileActions && <div className=\"shrink-0\">{mobileActions}</div>}\n </header>\n )}\n\n {/* Desktop breadcrumb header */}\n {!isMobile && header && (\n <header className=\"flex items-center h-10 border-b border-border px-4 shrink-0\">\n {header.breadcrumbs && header.breadcrumbs.length > 0 && (\n <nav className=\"flex items-center gap-1 text-xs flex-1 min-w-0\">\n {header.breadcrumbs.map((crumb, index) => {\n const isLast = index === header.breadcrumbs!.length - 1\n return (\n <span key={index} className=\"flex items-center gap-1\">\n {index > 0 && (\n <ChevronRight className=\"h-3 w-3 text-foreground-subtle shrink-0\" />\n )}\n {crumb.href && !isLast ? (\n <a\n href={crumb.href}\n className=\"text-foreground-subtle hover:text-foreground transition-colors truncate\"\n >\n {crumb.label}\n </a>\n ) : (\n <span className=\"text-foreground truncate\">{crumb.label}</span>\n )}\n </span>\n )\n })}\n </nav>\n )}\n {header.actions && (\n <div className=\"flex items-center gap-2 ml-auto shrink-0\">\n {header.actions}\n </div>\n )}\n </header>\n )}\n\n <main className=\"flex-1 overflow-auto p-4\">{children}</main>\n </div>\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport { useIsMobile } from '../../hooks/use-is-mobile'\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n flexRender,\n type ColumnDef,\n} from '@tanstack/react-table'\nimport { cn } from '../../lib/cn'\nimport { Skeleton } from '../../primitives/skeleton'\nimport { Checkbox } from '../../primitives/checkbox'\nimport { DataTableHeader } from './data-table-header'\nimport { DataTableRow } from './data-table-row'\nimport { DataTablePagination } from './data-table-pagination'\nimport type { DataTableProps } from './types'\n\nexport function DataTable<T>({\n data,\n columns: userColumns,\n sorting,\n onSortingChange,\n filtering,\n onFilteringChange,\n pagination,\n onPaginationChange,\n loading = false,\n emptyState,\n rowActions,\n onRowClick,\n selectable = false,\n compact = true,\n stickyHeader = false,\n className,\n mobileMode = 'scroll',\n}: DataTableProps<T>) {\n const columns = useMemo(() => {\n if (!selectable) return userColumns\n\n const selectColumn: ColumnDef<T, unknown> = {\n id: '__select',\n header: ({ table }) => (\n <Checkbox\n checked={table.getIsAllPageRowsSelected()}\n onChange={table.getToggleAllPageRowsSelectedHandler()}\n aria-label=\"Select all\"\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n checked={row.getIsSelected()}\n onChange={row.getToggleSelectedHandler()}\n aria-label=\"Select row\"\n />\n ),\n enableSorting: false,\n }\n\n return [selectColumn, ...userColumns]\n }, [userColumns, selectable])\n\n const table = useReactTable({\n data,\n columns,\n state: {\n ...(sorting !== undefined && { sorting }),\n ...(filtering !== undefined && { columnFilters: filtering }),\n ...(pagination !== undefined && {\n pagination: { pageIndex: pagination.page, pageSize: pagination.pageSize },\n }),\n },\n onSortingChange: onSortingChange\n ? (updater) => {\n const next = typeof updater === 'function' ? updater(sorting ?? []) : updater\n onSortingChange(next)\n }\n : undefined,\n onColumnFiltersChange: onFilteringChange\n ? (updater) => {\n const next = typeof updater === 'function' ? updater(filtering ?? []) : updater\n onFilteringChange(next)\n }\n : undefined,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getPaginationRowModel: pagination ? getPaginationRowModel() : undefined,\n manualPagination: pagination !== undefined,\n pageCount: pagination ? Math.ceil(pagination.total / pagination.pageSize) : undefined,\n })\n\n const hasActions = !!rowActions\n\n const isMobile = useIsMobile()\n const showCards = isMobile && mobileMode === 'cards'\n\n if (showCards) {\n const rows = table.getRowModel().rows\n\n if (loading) {\n return (\n <div className={cn('space-y-2', className)}>\n {Array.from({ length: 3 }).map((_, i) => (\n <div key={i} className=\"rounded-lg border border-border bg-surface p-3 space-y-2\">\n <Skeleton className=\"h-3 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n ))}\n </div>\n )\n }\n\n if (rows.length === 0) {\n return (\n <div className={cn('text-center py-8 text-xs text-foreground-muted', className)}>\n {emptyState ?? 'No data'}\n </div>\n )\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n {rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n 'rounded-lg border border-border bg-surface p-3 space-y-1.5',\n onRowClick && 'cursor-pointer hover:bg-surface-hover transition-colors'\n )}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells()\n .filter((cell) => cell.column.id !== '__select')\n .map((cell) => {\n const header = cell.column.columnDef.header\n const label = typeof header === 'string' ? header : cell.column.id\n return (\n <div key={cell.id} className=\"flex items-baseline justify-between gap-2 text-xs\">\n <span className=\"text-foreground-muted shrink-0\">{label}</span>\n <span className=\"text-foreground text-right truncate\">\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </span>\n </div>\n )\n })}\n {rowActions && (\n <div className=\"flex items-center gap-1 pt-1 border-t border-border mt-1.5\">\n {rowActions(row.original).map((action, i) => (\n <button\n key={i}\n onClick={(e) => { e.stopPropagation(); action.onClick() }}\n className={cn(\n 'text-[11px] px-2 py-1 rounded-md transition-colors',\n action.variant === 'danger'\n ? 'text-danger hover:bg-danger/10'\n : 'text-foreground-muted hover:bg-surface-hover'\n )}\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </div>\n ))}\n {pagination && (\n <DataTablePagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n total={pagination.total}\n onPaginationChange={onPaginationChange}\n />\n )}\n </div>\n )\n }\n\n return (\n <div className={cn('overflow-x-auto', className)}>\n <table className=\"w-full border-collapse\">\n <DataTableHeader\n headerGroups={table.getHeaderGroups()}\n onSortingChange={onSortingChange}\n stickyHeader={stickyHeader}\n flexRender={flexRender}\n />\n <tbody>\n {loading ? (\n <LoadingRows colSpan={columns.length + (hasActions ? 1 : 0)} compact={compact} />\n ) : table.getRowModel().rows.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length + (hasActions ? 1 : 0)}\n className=\"text-center py-8 text-xs text-foreground-muted\"\n >\n {emptyState ?? 'No data'}\n </td>\n </tr>\n ) : (\n table.getRowModel().rows.map((row) => (\n <DataTableRow\n key={row.id}\n row={row}\n onRowClick={onRowClick}\n rowActions={rowActions}\n flexRender={flexRender}\n />\n ))\n )}\n </tbody>\n </table>\n {pagination && (\n <DataTablePagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n total={pagination.total}\n onPaginationChange={onPaginationChange}\n />\n )}\n </div>\n )\n}\n\nfunction LoadingRows({ colSpan, compact }: { colSpan: number; compact: boolean }) {\n return (\n <>\n {Array.from({ length: 5 }).map((_, rowIdx) => (\n <tr key={rowIdx} className={compact ? 'h-7' : 'h-9'}>\n {Array.from({ length: colSpan }).map((_, colIdx) => (\n <td key={colIdx} className=\"px-2 py-1.5\">\n <Skeleton className=\"h-3 w-full\" />\n </td>\n ))}\n </tr>\n ))}\n </>\n )\n}\n","import type { HeaderGroup, Header, flexRender } from '@tanstack/react-table'\nimport { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport type { SortingState } from './types'\n\ninterface DataTableHeaderProps<T> {\n headerGroups: HeaderGroup<T>[]\n onSortingChange?: (sorting: SortingState) => void\n stickyHeader?: boolean\n flexRender: typeof flexRender\n}\n\nexport function DataTableHeader<T>({\n headerGroups,\n onSortingChange,\n stickyHeader,\n flexRender: render,\n}: DataTableHeaderProps<T>) {\n return (\n <thead\n className={cn(\n stickyHeader && 'sticky top-0 z-10 bg-background',\n )}\n >\n {headerGroups.map((headerGroup) => (\n <tr key={headerGroup.id} className=\"h-6\">\n {headerGroup.headers.map((header) => (\n <HeaderCell\n key={header.id}\n header={header}\n sortable={header.column.getCanSort() && !!onSortingChange}\n flexRender={render}\n />\n ))}\n </tr>\n ))}\n </thead>\n )\n}\n\ninterface HeaderCellProps<T> {\n header: Header<T, unknown>\n sortable: boolean\n flexRender: typeof flexRender\n}\n\nfunction HeaderCell<T>({ header, sortable, flexRender: render }: HeaderCellProps<T>) {\n const sorted = header.column.getIsSorted()\n\n const SortIcon = sorted === 'asc' ? ArrowUp : sorted === 'desc' ? ArrowDown : ArrowUpDown\n\n return (\n <th\n className={cn(\n 'px-2 py-1 text-left text-[10px] text-foreground-subtle uppercase tracking-wider font-medium',\n sortable && 'cursor-pointer select-none',\n )}\n onClick={sortable ? header.column.getToggleSortingHandler() : undefined}\n >\n <span className=\"inline-flex items-center gap-1\">\n {header.isPlaceholder\n ? null\n : render(header.column.columnDef.header, header.getContext())}\n {sortable && <SortIcon className=\"h-3 w-3\" />}\n </span>\n </th>\n )\n}\n","import type { Row, Cell, flexRender } from '@tanstack/react-table'\nimport { MoreHorizontal } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport { Dropdown, DropdownTrigger, DropdownContent, DropdownItem as DropdownMenuItem } from '../../primitives/dropdown'\nimport type { DataTableAction } from './types'\n\ninterface DataTableRowProps<T> {\n row: Row<T>\n onRowClick?: (row: T) => void\n rowActions?: (row: T) => DataTableAction[]\n flexRender: typeof flexRender\n}\n\nexport function DataTableRow<T>({\n row,\n onRowClick,\n rowActions,\n flexRender: render,\n}: DataTableRowProps<T>) {\n const actions = rowActions ? rowActions(row.original) : []\n\n return (\n <tr\n className={cn(\n 'h-7 border-b border-border/50',\n onRowClick && 'cursor-pointer',\n 'hover:bg-surface-hover',\n )}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells().map((cell) => (\n <DataTableCell key={cell.id} cell={cell} flexRender={render} />\n ))}\n {actions.length > 0 && (\n <td className=\"px-2 py-1.5 w-8\">\n <Dropdown>\n <DropdownTrigger\n className=\"p-0.5 rounded hover:bg-surface-hover\"\n onClick={(e) => e.stopPropagation()}\n >\n <MoreHorizontal className=\"h-3.5 w-3.5 text-foreground-muted\" />\n </DropdownTrigger>\n <DropdownContent className=\"right-0 left-auto\">\n {actions.map((action) => (\n <DropdownMenuItem\n key={action.label}\n icon={action.icon}\n variant={action.variant}\n onClick={(e) => {\n e.stopPropagation()\n action.onClick()\n }}\n >\n {action.label}\n </DropdownMenuItem>\n ))}\n </DropdownContent>\n </Dropdown>\n </td>\n )}\n </tr>\n )\n}\n\ninterface DataTableCellProps<T> {\n cell: Cell<T, unknown>\n flexRender: typeof flexRender\n}\n\nfunction DataTableCell<T>({ cell, flexRender: render }: DataTableCellProps<T>) {\n return (\n <td className=\"px-2 py-1.5 text-xs text-foreground\">\n {render(cell.column.columnDef.cell, cell.getContext())}\n </td>\n )\n}\n","import { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { IconButton } from '../../primitives/icon-button'\nimport { Select } from '../../primitives/select'\nimport type { PaginationState } from './types'\n\ninterface DataTablePaginationProps {\n page: number\n pageSize: number\n total: number\n onPaginationChange?: (pagination: PaginationState) => void\n}\n\nconst PAGE_SIZE_OPTIONS = [\n { value: '10', label: '10' },\n { value: '25', label: '25' },\n { value: '50', label: '50' },\n { value: '100', label: '100' },\n]\n\nexport function DataTablePagination({\n page,\n pageSize,\n total,\n onPaginationChange,\n}: DataTablePaginationProps) {\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n const currentPage = page + 1\n\n return (\n <div className=\"flex items-center justify-between px-2 py-2 text-xs text-foreground-muted\">\n <div className=\"flex items-center gap-2\">\n <span>Rows per page</span>\n <div className=\"w-16\">\n <Select\n options={PAGE_SIZE_OPTIONS}\n value={String(pageSize)}\n onChange={(e) =>\n onPaginationChange?.({\n pageIndex: 0,\n pageSize: Number(e.target.value),\n })\n }\n />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <span>\n Page {currentPage} of {totalPages}\n </span>\n <IconButton\n icon={ChevronLeft}\n aria-label=\"Previous page\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={page <= 0}\n onClick={() =>\n onPaginationChange?.({ pageIndex: page - 1, pageSize })\n }\n />\n <IconButton\n icon={ChevronRight}\n aria-label=\"Next page\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={currentPage >= totalPages}\n onClick={() =>\n onPaginationChange?.({ pageIndex: page + 1, pageSize })\n }\n />\n </div>\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface DeviceCardBadge {\n /** Badge label text */\n label: string\n /** Optional icon rendered before the label */\n icon?: ReactNode\n /** Click handler — makes the badge interactive */\n onClick?: () => void\n}\n\nexport interface DeviceCardAction {\n /** Icon to render */\n icon: ReactNode\n /** Tooltip / aria-label */\n label: string\n /** Click handler */\n onClick: () => void\n}\n\nexport interface DeviceCardProps {\n /** Primary title (e.g., device name) */\n title: string\n /** Secondary text (e.g., model, IP) */\n subtitle?: string\n /** Status: determines the color of the status dot */\n status?: 'online' | 'offline' | 'warning' | 'unknown'\n /** Whether this card is currently selected */\n selected?: boolean\n /** Click handler for the card body */\n onClick?: () => void\n /** Clickable badges (e.g., stream profiles) */\n badges?: DeviceCardBadge[]\n /** Action icons shown at the bottom (e.g., PTZ, events) */\n actions?: DeviceCardAction[]\n /** Content rendered at the bottom when status is offline (e.g., Connect button) */\n offlineAction?: ReactNode\n /** Additional CSS classes */\n className?: string\n}\n\nconst STATUS_COLORS = {\n online: 'bg-success',\n offline: 'bg-danger',\n warning: 'bg-warning',\n unknown: 'bg-foreground-subtle',\n} as const\n\nexport function DeviceCard({\n title,\n subtitle,\n status,\n selected,\n onClick,\n badges,\n actions,\n offlineAction,\n className,\n}: DeviceCardProps) {\n const isOffline = status === 'offline'\n\n return (\n <div\n onClick={onClick}\n className={cn(\n 'w-full rounded-lg border p-3 text-left transition-colors',\n onClick && 'cursor-pointer',\n selected\n ? 'border-primary bg-primary/10'\n : 'border-border bg-surface hover:bg-surface-hover',\n isOffline && !selected && 'opacity-50',\n className,\n )}\n >\n {/* Header: title + status dot */}\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium truncate\">{title}</span>\n {status && (\n <span className={cn('h-2 w-2 rounded-full shrink-0', STATUS_COLORS[status])} />\n )}\n </div>\n\n {/* Subtitle */}\n {subtitle && (\n <div className=\"text-[11px] text-foreground-muted\">{subtitle}</div>\n )}\n\n {/* Badges */}\n {badges && badges.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mt-2\">\n {badges.map((badge, i) => {\n const cls = cn(\n 'rounded px-1.5 py-0.5 text-[10px] flex items-center gap-0.5',\n selected ? 'bg-primary/20' : 'bg-surface-hover',\n badge.onClick && 'hover:opacity-80 transition-opacity cursor-pointer',\n )\n return badge.onClick ? (\n <button\n key={i}\n onClick={(e) => { e.stopPropagation(); badge.onClick!(); }}\n className={cls}\n >\n {badge.icon}{badge.label}\n </button>\n ) : (\n <span key={i} className={cls}>\n {badge.icon}{badge.label}\n </span>\n )\n })}\n </div>\n )}\n\n {/* Actions (online) or offline action */}\n {!isOffline && actions && actions.length > 0 && (\n <div className=\"flex items-center gap-0.5 mt-2 -mb-1\">\n {actions.map((action, i) => (\n <button\n key={i}\n onClick={(e) => { e.stopPropagation(); action.onClick(); }}\n className=\"p-1 rounded hover:bg-surface-hover text-foreground-subtle hover:text-foreground transition-colors\"\n title={action.label}\n aria-label={action.label}\n >\n {action.icon}\n </button>\n ))}\n </div>\n )}\n\n {isOffline && offlineAction && (\n <div className=\"mt-2\" onClick={(e) => e.stopPropagation()}>\n {offlineAction}\n </div>\n )}\n </div>\n )\n}\n","import { type ReactNode } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface DeviceGridProps {\n /** Grid items */\n children: ReactNode\n /** Minimum card width in pixels (default 220) */\n minCardWidth?: number\n /** Gap between cards in Tailwind spacing units (default 3) */\n gap?: number\n /** Additional CSS classes */\n className?: string\n}\n\nexport function DeviceGrid({\n children,\n minCardWidth = 220,\n gap = 3,\n className,\n}: DeviceGridProps) {\n return (\n <div\n className={cn(\n 'p-4 overflow-y-auto flex-1 content-start',\n className,\n )}\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(auto-fill, minmax(${minCardWidth}px, 1fr))`,\n gap: `${gap * 4}px`,\n }}\n >\n {children}\n </div>\n )\n}\n","/**\n * <DeviceItem> — orchestrator that composes Header / Preview /\n * Features / Actions / StatusDot in a flex row (`view='card'`) or a\n * `<tr>` with one `<td>` per logical column (`view='table'`).\n *\n * Public API contract: identical to the predecessor `device-item.tsx`\n * file so the 5 existing call sites compile unchanged. The new\n * `view` prop defaults to `'card'`.\n */\nimport { useState, type ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\nimport { ChildrenAccordion } from './children-accordion'\nimport { DeviceItemActions } from './actions'\nimport { DeviceItemFeatures } from './features'\nimport { DeviceItemHeader } from './header'\nimport { DeviceItemPreview } from './preview'\nimport { StatusDot } from './status-dot'\nimport {\n isAccessoryChild,\n resolveFlags,\n type DeviceItemDevice,\n type DeviceItemParent,\n type DeviceItemProps,\n type DeviceItemVariant,\n type VariantDefaults,\n} from './helpers'\n\nexport type {\n DeviceItemDevice,\n DeviceItemParent,\n DeviceItemKind,\n DeviceItemVariant,\n DeviceItemView,\n DeviceItemProps,\n} from './helpers'\nexport { deriveDeviceKind } from './helpers'\n\nexport function DeviceItem(props: DeviceItemProps): ReactNode {\n const { trpc, device, parent, integrationIcon, onNavigate, className } = props\n const flags = resolveFlags(props)\n const variant = props.variant ?? 'compact'\n const view = props.view ?? 'card'\n\n const enabled = !device.disabled\n const isCamera = device.isCamera ?? device.type.toLowerCase() === 'camera'\n\n const childrenList = props.children ?? []\n const accessoryChildren = childrenList.filter(isAccessoryChild)\n const adoptedChildren = childrenList.filter((c) => !isAccessoryChild(c))\n const hasChildren = childrenList.length > 0\n\n const [localExpanded, setLocalExpanded] = useState(false)\n const expanded = props.expanded ?? localExpanded\n const onToggleExpand = props.onToggleExpand ?? ((): void => setLocalExpanded((v) => !v))\n const navigate = (id: number): void => { onNavigate?.(id) }\n\n // Indent: caller may force a specific level; otherwise infer 2 from\n // the legacy `isAccessoryRow` flag for backwards compatibility, else\n // 0 (top-level).\n const indentLevel: 0 | 1 | 2 = props.indentLevel\n ?? (props.isAccessoryRow ? 2 : 0)\n\n const displayStatus: 'online' | 'offline' | 'disabled' = !enabled\n ? 'disabled'\n : device.online\n ? 'online'\n : 'offline'\n\n if (view === 'table') {\n return (\n <DeviceItemTableRow\n trpc={trpc}\n device={device}\n variant={variant}\n flags={flags}\n parent={parent ?? null}\n integrationIcon={integrationIcon ?? null}\n accessoryCount={accessoryChildren.length}\n adoptedCount={adoptedChildren.length}\n hasChildren={hasChildren}\n expanded={expanded}\n onToggleExpand={onToggleExpand}\n onNavigate={navigate}\n displayStatus={displayStatus}\n isCamera={isCamera}\n showSnapshot={flags.showSnapshot && isCamera}\n isAccessoryRow={props.isAccessoryRow ?? false}\n indentLevel={indentLevel}\n className={className}\n />\n )\n }\n\n return (\n <div\n className={cn(\n 'rounded-lg border border-border bg-surface transition-colors',\n !enabled && 'opacity-60',\n className,\n )}\n >\n <div\n onClick={() => navigate(device.id)}\n className={cn(\n 'flex items-center gap-2 cursor-pointer hover:border-foreground-subtle/30 w-full',\n variant === 'minimal' ? 'px-2.5 py-1.5' : 'px-3 py-2.5',\n )}\n >\n <DeviceItemHeader\n device={device}\n variant={variant}\n flags={flags}\n parent={parent ?? null}\n integrationIcon={integrationIcon ?? null}\n hasChildren={hasChildren}\n expanded={expanded}\n onToggleExpand={onToggleExpand}\n onNavigateToParent={navigate}\n />\n\n <DeviceItemFeatures\n trpc={trpc}\n device={device}\n flags={flags}\n accessoryCount={accessoryChildren.length}\n adoptedCount={adoptedChildren.length}\n showFeatureRow={false}\n />\n\n <DeviceItemPreview\n trpc={trpc}\n device={device}\n status={displayStatus}\n enabled={flags.showSnapshot && isCamera}\n showStatusPills\n />\n\n <DeviceItemActions trpc={trpc} device={device} flags={flags} />\n\n <StatusDot status={displayStatus} />\n </div>\n\n {expanded && hasChildren && (\n <ChildrenAccordion\n trpc={trpc}\n accessoryChildren={accessoryChildren}\n adoptedChildren={adoptedChildren}\n onNavigate={navigate}\n />\n )}\n </div>\n )\n}\n\n// ── view='table' branch ─────────────────────────────────────────────\n//\n// Placeholder until Task 10 lands the full table implementation. We\n// keep the orchestrator export self-consistent by stubbing here so\n// `npx tsc --noEmit` stays green between tasks.\n\ninterface DeviceItemTableRowProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly device: DeviceItemDevice\n readonly variant: DeviceItemVariant\n readonly flags: VariantDefaults\n readonly parent: DeviceItemParent | null\n readonly integrationIcon: ReactNode | null\n readonly accessoryCount: number\n readonly adoptedCount: number\n readonly hasChildren: boolean\n readonly expanded: boolean\n readonly onToggleExpand: () => void\n readonly onNavigate: (id: number) => void\n readonly displayStatus: 'online' | 'offline' | 'disabled'\n readonly isCamera: boolean\n readonly showSnapshot: boolean\n readonly isAccessoryRow: boolean\n readonly indentLevel: 0 | 1 | 2\n readonly className: string | undefined\n}\n\nconst INDENT_CLASS: Readonly<Record<0 | 1 | 2, string>> = {\n 0: 'pl-2',\n 1: 'pl-6',\n 2: 'pl-8',\n}\n\nfunction DeviceItemTableRow(props: DeviceItemTableRowProps): ReactNode {\n const {\n trpc,\n device,\n variant,\n flags,\n parent,\n integrationIcon,\n accessoryCount,\n adoptedCount,\n hasChildren,\n expanded,\n onToggleExpand,\n onNavigate,\n displayStatus,\n isCamera,\n showSnapshot,\n isAccessoryRow,\n indentLevel,\n className,\n } = props\n\n return (\n <tr\n onClick={() => onNavigate(device.id)}\n className={cn(\n 'cursor-pointer hover:bg-surface-hover transition-colors',\n !flags.showChildrenAccordion && 'border-b border-border-subtle/40',\n isAccessoryRow && 'bg-foreground-subtle/[0.03]',\n className,\n )}\n >\n {/* Header cell collapses to icon + name + meta + parent into\n one wide name column. The chevron, when applicable, sits\n beside the lead icon as in the card layout. Indent level is\n derived from `indentLevel` so adopted-under-hub rows render\n at pl-6 without the accessory tint. */}\n <td className={cn(\n 'py-2 align-middle pr-2',\n INDENT_CLASS[indentLevel],\n )}>\n <DeviceItemHeader\n device={device}\n variant={variant}\n flags={flags}\n parent={parent}\n integrationIcon={integrationIcon}\n hasChildren={hasChildren}\n expanded={expanded}\n onToggleExpand={onToggleExpand}\n onNavigateToParent={onNavigate}\n />\n </td>\n\n <td className=\"px-2 py-2 align-middle text-[10px] text-foreground-subtle whitespace-nowrap\">\n {device.type}\n </td>\n\n <td className=\"px-2 py-2 align-middle\">\n <DeviceItemFeatures\n trpc={trpc}\n device={device}\n flags={flags}\n accessoryCount={accessoryCount}\n adoptedCount={adoptedCount}\n showFeatureRow\n />\n </td>\n\n <td className=\"px-2 py-2 align-middle\">\n <DeviceItemPreview\n trpc={trpc}\n device={device}\n status={displayStatus}\n enabled={showSnapshot && isCamera}\n showStatusPills\n />\n </td>\n\n <td className=\"px-2 py-2 align-middle text-right whitespace-nowrap\">\n <span className=\"inline-flex items-center gap-1.5\">\n <DeviceItemActions trpc={trpc} device={device} flags={flags} />\n <StatusDot status={displayStatus} />\n </span>\n </td>\n </tr>\n )\n}\n","/**\n * <ChildrenAccordion> — accessory + adopted children rows shown when\n * the parent's chevron is expanded. The accessory/adopted split is\n * driven by `isAccessoryChild` (role-or-type-based, see helpers.ts).\n *\n * Each ChildRow surfaces the same quick-action toggles the parent's\n * actions slot exposes: switch toggle (when the device has a `switch`\n * cap) and on-motion toggle (when the device advertises `motion-trigger`).\n * Both gate via `useDeviceCapability` so they self-hide when the cap\n * isn't bound.\n */\nimport { useState, type CSSProperties, type ReactNode, type MouseEvent } from 'react'\nimport { Activity } from 'lucide-react'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\nimport { useDeviceCapability } from '../../hooks/use-device-capability'\nimport { cn } from '../../lib/cn'\nimport type { DeviceItemDevice } from './helpers'\nimport {\n deviceLeadIcon,\n hasMotionTriggerFeature,\n maySupportSwitch,\n} from './helpers'\n\ninterface ChildrenAccordionProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly accessoryChildren: readonly DeviceItemDevice[]\n readonly adoptedChildren: readonly DeviceItemDevice[]\n readonly onNavigate: (id: number) => void\n}\n\nexport function ChildrenAccordion({ trpc, accessoryChildren, adoptedChildren, onNavigate }: ChildrenAccordionProps): ReactNode {\n return (\n <div className=\"border-t border-border-subtle/50\">\n {adoptedChildren.length > 0 && (\n <ChildrenSection trpc={trpc} label=\"Adopted devices\" rows={adoptedChildren} onNavigate={onNavigate} />\n )}\n {accessoryChildren.length > 0 && (\n <ChildrenSection trpc={trpc} label=\"Accessories\" rows={accessoryChildren} onNavigate={onNavigate} />\n )}\n </div>\n )\n}\n\ninterface ChildrenSectionProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly label: string\n readonly rows: readonly DeviceItemDevice[]\n readonly onNavigate: (id: number) => void\n}\n\nfunction ChildrenSection({ trpc, label, rows, onNavigate }: ChildrenSectionProps): ReactNode {\n return (\n <div>\n <div className=\"px-3 pt-1.5 pb-1 text-[9px] font-semibold uppercase tracking-wide text-foreground-subtle\">\n {label}\n </div>\n <ul>\n {rows.map((child) => (\n <ChildRow key={child.id} trpc={trpc} child={child} onNavigate={onNavigate} />\n ))}\n </ul>\n </div>\n )\n}\n\ninterface ChildRowProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly child: DeviceItemDevice\n readonly onNavigate: (id: number) => void\n}\n\nfunction ChildRow({ trpc, child, onNavigate }: ChildRowProps): ReactNode {\n const enabled = !child.disabled\n const showSwitch = enabled && maySupportSwitch(child)\n const showMotionTrigger = enabled && hasMotionTriggerFeature(child)\n const ChildIcon = deviceLeadIcon(child)\n return (\n <li>\n <div\n onClick={(e) => { e.stopPropagation(); onNavigate(child.id) }}\n className=\"w-full flex items-center gap-2 px-3 py-1.5 text-left hover:bg-surface-hover transition-colors cursor-pointer\"\n >\n <ChildIcon className=\"h-3 w-3 text-foreground-subtle flex-shrink-0\" />\n <span className=\"text-[10.5px] text-foreground flex-1 truncate\">{child.name}</span>\n {showMotionTrigger && (\n <ChildMotionTriggerToggle trpc={trpc} deviceId={child.id} features={child.features} />\n )}\n {showSwitch && (\n <ChildSwitchToggle trpc={trpc} deviceId={child.id} />\n )}\n <span\n className={cn(\n 'h-1.5 w-1.5 rounded-full flex-shrink-0',\n child.online ? 'bg-success' : 'bg-foreground-subtle/40',\n )}\n title={child.online ? 'Online' : 'Offline'}\n />\n </div>\n </li>\n )\n}\n\n// ── Toggles (file-internal — actions.tsx has the public version) ────\n\ninterface ChildSwitchToggleProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly deviceId: number\n}\n\nfunction ChildSwitchToggle({ trpc, deviceId }: ChildSwitchToggleProps): ReactNode {\n const { dev, cap, slice, available } = useDeviceCapability({\n trpc, deviceId,\n cap: (d) => d.switch,\n slice: (d) => d.state.switch,\n })\n const [pending, setPending] = useState(false)\n\n if (dev !== null && !cap) return null\n\n const on = slice?.on === true\n const knobStyle: CSSProperties = {\n transform: on ? 'translateX(14px)' : 'translateX(2px)',\n }\n\n const handleClick = async (e: MouseEvent): Promise<void> => {\n e.stopPropagation()\n if (pending || !available || !cap) return\n setPending(true)\n try {\n await cap.setState({ on: !on })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={(e) => { void handleClick(e) }}\n disabled={pending || !available}\n className={cn(\n 'relative inline-flex h-4 w-7 items-center rounded-full border transition-colors flex-shrink-0',\n on ? 'bg-success/30 border-success/50' : 'bg-surface-hover border-border',\n pending && 'opacity-60',\n !available && 'opacity-40 cursor-not-allowed',\n )}\n title={!available ? 'Awaiting state…' : on ? 'Turn off' : 'Turn on'}\n aria-pressed={on}\n >\n <span\n className={cn('absolute h-3 w-3 rounded-full transition-all', on ? 'bg-success' : 'bg-foreground-subtle')}\n style={knobStyle}\n />\n </button>\n )\n}\n\ninterface ChildMotionTriggerToggleProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly deviceId: number\n readonly features: readonly string[] | undefined\n}\n\nfunction ChildMotionTriggerToggle({ trpc, deviceId, features }: ChildMotionTriggerToggleProps): ReactNode {\n const { dev, cap, slice, available } = useDeviceCapability({\n trpc, deviceId,\n cap: (d) => d.motionTrigger,\n slice: (d) => d.state.motionTrigger,\n requireFeature: 'motion-trigger',\n deviceFeatures: features,\n })\n const [pending, setPending] = useState(false)\n\n if (dev !== null && !cap) return null\n\n const on = slice?.enabled === true\n\n const handleClick = async (e: MouseEvent): Promise<void> => {\n e.stopPropagation()\n if (pending || !available || !cap) return\n setPending(true)\n try {\n await cap.setMotionTrigger({ enabled: !on })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={(e) => { void handleClick(e) }}\n disabled={pending || !available}\n className={cn(\n 'inline-flex h-4 w-4 items-center justify-center rounded transition-colors flex-shrink-0',\n on ? 'text-primary bg-primary/10' : 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n (pending || !available) && 'opacity-50',\n )}\n title={!available ? 'Awaiting state…' : on ? 'Motion-trigger: on (click to disable)' : 'Motion-trigger: off (click to enable)'}\n aria-pressed={on}\n >\n <Activity className=\"h-2.5 w-2.5\" />\n </button>\n )\n}\n","/**\n * useDeviceProxy — canonical React entry point for a device.\n *\n * Symmetric with the server's `ctx.fetchDevice(id)` and the SDK's\n * `BackendClient.fetchDevice(id)` — same `DeviceProxy` shape, same\n * routing semantics (cap-method calls go through the wrapper chain;\n * `state.<cap>.value` reads the kernel's mirrored snapshot, never\n * the provider).\n *\n * What you can do with the returned proxy:\n *\n * const dev = useDeviceProxy(trpc, deviceId)\n *\n * // Reactive runtime state — re-renders when the slice changes.\n * const battery = useDeviceStateSlice(dev?.state.battery)\n *\n * // Imperative cap-method calls — through the wrapper chain.\n * await dev?.snapshot?.getSnapshot({ streamId: 'high' })\n * await dev?.ptz?.move({ direction: 'left', steps: 1 })\n *\n * Lifecycle: the hook resolves bindings via `deviceManager.getBindings`\n * the first time `deviceId` becomes valid, and refreshes them on\n * `capability.binding-changed` events for that device. Returns `null`\n * until the first resolution completes (the proxy is not constructible\n * without a binding).\n *\n * Works in both admin-ui (`BackendClient.trpc`) and addon pages\n * (`AddonPageProps.trpc`) — parametrized by a minimal vanilla tRPC\n * proxy shape (matches both at runtime).\n */\nimport { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport type { DeviceBinding, DeviceProxy } from '@camstack/types'\nimport { createDeviceProxy } from '@camstack/types'\n\n/**\n * Reactive runtime-state read handle as exposed by the codegen\n * `DeviceProxy` factory. Same shape useDeviceStateSlice expects —\n * defined here so the combinator's selector parameter has a tight\n * type without re-importing the codegen file.\n */\ninterface StateSliceHandle<T> {\n readonly value: T | undefined\n subscribe(cb: (slice: T | undefined) => void): () => void\n}\n\ninterface QueryFn<I, O> {\n query(input: I): Promise<O>\n}\n\ninterface SubscribeFn<I, T> {\n subscribe(\n input: I,\n opts: { onData: (evt: { data: T }) => void; onError?: (err: unknown) => void },\n ): { unsubscribe: () => void }\n}\n\n/**\n * Minimal vanilla tRPC proxy shape. Same contract `useDeviceWebrtc`,\n * `useDeviceBattery` etc. use — both `BackendClient.trpc` and an\n * addon page's injected `trpc` satisfy this structurally.\n *\n * The proxy is also passed (cast) into `createDeviceProxy` as the\n * `AddonApi` argument — the cap-method dispatchers structurally\n * match `client.<cap>.<method>.{query|mutate|subscribe}`.\n */\nexport interface UseDeviceProxyTrpc {\n readonly deviceManager: {\n readonly getBindings: QueryFn<{ deviceId: number }, DeviceBinding>\n }\n readonly live?: {\n readonly onEvent: SubscribeFn<\n { category: string },\n { category?: string; data?: unknown; source?: { type: string; id: string | number } }\n >\n }\n}\n\nconst BINDING_CHANGED_CATEGORY = 'capability.binding-changed'\n\n/**\n * @returns the proxy, or `null` while bindings are still loading or\n * when `deviceId` is null. Re-rendered when bindings change.\n */\nexport function useDeviceProxy(\n trpc: UseDeviceProxyTrpc,\n deviceId: number | null,\n): DeviceProxy | null {\n const [binding, setBinding] = useState<DeviceBinding | null>(null)\n\n useEffect(() => {\n if (deviceId === null) {\n setBinding(null)\n return\n }\n let cancelled = false\n\n const refresh = async (): Promise<void> => {\n try {\n const next = await trpc.deviceManager.getBindings.query({ deviceId })\n if (!cancelled) setBinding(next)\n } catch {\n // Binding fetch failures leave the previous proxy in place —\n // a transient tRPC error shouldn't tear down active subscriptions.\n if (!cancelled) setBinding((prev) => prev)\n }\n }\n\n void refresh()\n\n // Live invalidation on binding changes — wrapper toggles, cap\n // (un)registrations etc. emit `capability.binding-changed` so we\n // re-fetch and rebuild the proxy fields the device exposes.\n const sub = trpc.live?.onEvent.subscribe(\n { category: BINDING_CHANGED_CATEGORY },\n {\n onData: (evt) => {\n const src = evt.data?.source\n if (!src) {\n void refresh()\n return\n }\n if (src.type === 'device' && src.id === deviceId) void refresh()\n },\n },\n )\n\n return () => {\n cancelled = true\n sub?.unsubscribe()\n }\n }, [trpc, deviceId])\n\n // The proxy is a thin closure over (trpc, binding) — rebuilding it\n // on every render is cheap, but memoising keeps `===` identity stable\n // for downstream effects/callbacks that depend on the proxy.\n return useMemo(() => {\n if (!binding) return null\n return createDeviceProxy(\n // Cast: the vanilla tRPC client is structurally compatible with\n // the AddonApi shape that `createDeviceProxy` expects (matching\n // <cap>.<method>.{query|mutate|subscribe} surface).\n trpc as unknown as Parameters<typeof createDeviceProxy>[0],\n binding,\n )\n }, [trpc, binding])\n}\n\n/**\n * Companion hook — reads a `SliceHandle` reactively, returning the\n * current value and re-rendering on every push from the kernel\n * mirror. Pass `dev?.state.battery` etc. as the handle.\n *\n * const dev = useDeviceProxy(trpc, deviceId)\n * const battery = useDeviceStateSlice(dev?.state.battery)\n *\n * Why a hook (and not just `dev.state.battery.subscribe(...)` inline)?\n * React doesn't observe external mutations on its own — a bare\n * subscribe call inside a render would fire on every render (memory\n * leak), wouldn't trigger a re-render on slice change, and wouldn't\n * clean up at unmount. The hook bridges the imperative\n * `(value, subscribe)` pair into React's declarative lifecycle via\n * `useSyncExternalStore` (the canonical React 18 primitive for\n * external stores — handles tearing in concurrent rendering and\n * de-dups identical pushes).\n */\nexport function useDeviceStateSlice<T>(\n handle: StateSliceHandle<T> | undefined,\n): T | undefined {\n const subscribe = useCallback(\n (notify: () => void) => {\n if (!handle) return () => undefined\n return handle.subscribe(() => notify())\n },\n [handle],\n )\n const getSnapshot = useCallback(() => handle?.value, [handle])\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n\n/**\n * One-line combinator — collapse the common\n * `useDeviceProxy + useDeviceStateSlice(dev?.state.<cap>)` pair into a\n * single hook. The selector receives the live `DeviceProxy['state']`\n * bag (typed against the codegen, so `s.battery` etc. autocomplete)\n * and returns one slice handle. Returns the slice value, undefined\n * while the binding resolves OR when the slice has no cached push yet.\n *\n * Idiomatic call-site:\n *\n * const battery = useDeviceState(trpc, deviceId, (s) => s.battery)\n * const zones = useDeviceState(trpc, deviceId, (s) => s.zones)\n *\n * vs. the manual pair:\n *\n * const dev = useDeviceProxy(trpc, deviceId)\n * const battery = useDeviceStateSlice(dev?.state.battery)\n * const zones = useDeviceStateSlice(dev?.state.zones)\n *\n * Use the manual pair when:\n * - you also need the proxy's cap method bag (`dev.zones?.addZone(...)`)\n * - you want to share the proxy across multiple slice reads with a\n * single binding fetch (the combinator calls useDeviceProxy\n * internally, which dedups bindings via React Query in practice\n * but spawns one extra subscription per call site)\n *\n * Use the combinator when reading just one slice — most common case.\n */\nexport function useDeviceState<T>(\n trpc: UseDeviceProxyTrpc,\n deviceId: number | null,\n select: (state: DeviceProxy['state']) => StateSliceHandle<T>,\n): T | undefined {\n const dev = useDeviceProxy(trpc, deviceId)\n const handle = dev ? select(dev.state) : undefined\n return useDeviceStateSlice(handle)\n}\n","/**\n * useDeviceCapability — accessor-based readiness wrapper around\n * `useDeviceProxy` + `useDeviceStateSlice`. Combines the three\n * preconditions a UI quick-action needs in one call:\n *\n * 1. Device proxy resolved (bindings landed)\n * 2. Cap handle present on the proxy (i.e. cap is bound)\n * 3. Slice has arrived (provider has published its first snapshot)\n *\n * Optional fourth precondition: a `DeviceFeature` flag advertised on\n * the device row. Useful for surfaces that only render a control when\n * the feature is declared (e.g. the on-motion toggle on a switch).\n *\n * Caller passes typed accessor callbacks so the cap + slice types\n * carry through TypeScript without casts:\n *\n * const { dev, cap, slice, available } = useDeviceCapability({\n * trpc, deviceId,\n * cap: (dev) => dev.switch,\n * slice: (dev) => dev.state.switch,\n * requireFeature: 'switch', // optional\n * deviceFeatures: device.features, // optional, only if feature gate used\n * })\n * if (available) await cap.setState({ on: !slice.on })\n */\nimport type { DeviceProxy, SliceHandle } from '@camstack/types'\nimport {\n useDeviceProxy,\n useDeviceStateSlice,\n type UseDeviceProxyTrpc,\n} from './use-device-proxy'\n\nexport interface UseDeviceCapabilityOptions<TCap, TSlice> {\n readonly trpc: UseDeviceProxyTrpc\n readonly deviceId: number | null\n readonly cap: (dev: DeviceProxy) => TCap | undefined\n readonly slice: (dev: DeviceProxy) => SliceHandle<TSlice> | undefined\n readonly requireFeature?: string\n readonly deviceFeatures?: readonly string[]\n}\n\nexport interface UseDeviceCapabilityResult<TCap, TSlice> {\n readonly dev: DeviceProxy | null\n readonly cap: TCap | undefined\n readonly slice: TSlice | undefined\n readonly available: boolean\n}\n\nexport function useDeviceCapability<TCap, TSlice>(\n options: UseDeviceCapabilityOptions<TCap, TSlice>,\n): UseDeviceCapabilityResult<TCap, TSlice> {\n const dev = useDeviceProxy(options.trpc, options.deviceId)\n const sliceHandle = dev !== null ? options.slice(dev) : undefined\n const slice = useDeviceStateSlice<TSlice>(sliceHandle)\n const cap = dev !== null ? options.cap(dev) : undefined\n\n const featureOk =\n options.requireFeature === undefined\n || (options.deviceFeatures ?? []).includes(options.requireFeature)\n const capPresent = cap !== undefined\n const sliceLanded = slice !== undefined\n const available = featureOk && capPresent && sliceLanded\n\n return { dev, cap, slice, available }\n}\n","/**\n * Shared types + helpers for the DeviceItem composite. Lives outside\n * the orchestrator file so every sub-component can import without\n * cycles.\n *\n * - `DeviceItemDevice` / `DeviceItemParent` / `DeviceItemKind` —\n * wire-shape mirrors of the `DeviceInfo` row.\n * - `DeviceItemVariant` + `VariantDefaults` + `DEFAULTS` +\n * `resolveFlags` — the variant→flags resolution pipeline.\n * - `ROLE_ICONS` / `TYPE_ICONS` / `deviceLeadIcon` — icon resolution\n * for the row's lead icon.\n * - `FEATURE_ICON_MAP` / `FEATURE_LABEL_MAP` — for the features\n * popover (NEW in Phase 1).\n * - Capability gates: `maySupportSwitch`, `isAccessoryChild`,\n * `hasMotionTriggerFeature`.\n * - `shortStableId` — display-token for stableId tail.\n */\nimport type { ReactNode } from 'react'\nimport {\n Camera as CameraIcon,\n Network,\n Wrench,\n Bell,\n Lightbulb,\n Sun,\n Radar,\n Music,\n Crosshair,\n Moon,\n EyeOff,\n DoorOpen,\n ToggleLeft,\n Thermometer,\n CircleDot,\n Activity,\n Mic,\n Image as ImageIcon,\n Battery,\n RotateCw,\n LocateFixed,\n} from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\n\n// ── Public types ────────────────────────────────────────────────────\n\n/**\n * Mirror of the canonical `DeviceInfo` wire shape (see\n * `packages/types/src/capabilities/device-manager.cap.ts`). Every\n * `deviceManager.listAll` / `getDevice` / `getChildren` row is\n * already this exact shape — call sites pass the raw row through\n * without remapping. Lives here as a structural type (not an\n * import) so this composite stays decoupled from `@camstack/types`.\n */\nexport interface DeviceItemDevice {\n readonly id: number\n readonly stableId: string\n readonly addonId: string\n readonly type: string\n readonly name: string\n readonly online: boolean\n /** Soft-disable flag — `true` dims the row + skips live fetches.\n * Matches `DeviceInfo.disabled` so the wire row passes through. */\n readonly disabled: boolean\n readonly parentDeviceId: number | null\n /** Optional `DeviceRole` string. Present ⇒ this is an accessory. */\n readonly role?: string | null\n /** DeviceFeature strings — gates BatteryBadge etc. */\n readonly features?: readonly string[]\n /** True for ICameraDevice instances — gates snapshot popover. */\n readonly isCamera?: boolean\n}\n\nexport interface DeviceItemParent {\n readonly id: number\n readonly name: string\n /**\n * Type of the parent device. Optional — when provided, callers can\n * distinguish \"adopted under a hub/nvr\" (renders with extra indent in\n * the table view) from a generic accessory parent.\n */\n readonly type?: string\n}\n\nexport type DeviceItemKind = 'top-level' | 'adopted' | 'accessory'\n\nexport function deriveDeviceKind(\n device: Pick<DeviceItemDevice, 'parentDeviceId' | 'role'>,\n): DeviceItemKind {\n if (device.parentDeviceId === null) return 'top-level'\n if (device.role) return 'accessory'\n return 'adopted'\n}\n\nexport type DeviceItemVariant = 'minimal' | 'compact' | 'expanded'\n\nexport type DeviceItemView = 'card' | 'table'\n\nexport interface DeviceItemProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly device: DeviceItemDevice\n readonly variant?: DeviceItemVariant\n /**\n * Render mode. `'card'` (default) = flex row + optional accordion\n * below. `'table'` = `<tr>` with one `<td>` per logical column.\n * Phase 2's `<DeviceList>` wrapper drives this prop; Phase 1\n * scaffolds both branches with no current consumer using table.\n */\n readonly view?: DeviceItemView\n /**\n * When true, the row is rendered as an accessory of a parent (Phase 2\n * nested-only mode). Adds a subtle background tint + indent on the\n * first cell. Has no effect on `view='card'`. Caller provides `true`\n * only for the accessory passes inside <DeviceList>.\n */\n readonly isAccessoryRow?: boolean\n /**\n * Indent level for the `<td>` first cell in `view='table'`. Controls\n * `pl-N` on the name cell so adopted-under-hub rows can be visually\n * nested below their parent without forcing the accessory tint.\n *\n * 0 → `pl-2` (top-level, no parent)\n * 1 → `pl-6` (adopted under a hub/nvr — visual hierarchy hint)\n * 2 → `pl-8` (accessory under any parent — strongest indent)\n *\n * When omitted, the orchestrator derives `2` from `isAccessoryRow` and\n * otherwise defaults to `0`. Caller may override (e.g. <DeviceList>\n * promoting \"adopted-under-hub\" rows from 0 → 1).\n */\n readonly indentLevel?: 0 | 1 | 2\n /**\n * Controlled expand state for the children-accordion chevron. When\n * BOTH `expanded` and `onToggleExpand` are passed, DeviceItem becomes\n * fully controlled; otherwise it falls back to internal state. Used\n * by `<TableRowGroup>` to lift expand state to the parent so the\n * accessory `<tr>` rows can render based on the same flag the chevron\n * flips.\n */\n readonly expanded?: boolean\n readonly onToggleExpand?: () => void\n readonly integrationIcon?: ReactNode\n readonly parent?: DeviceItemParent | null\n readonly showIntegrationIcon?: boolean\n readonly showParentBadge?: boolean\n readonly showSnapshot?: boolean\n readonly showBattery?: boolean\n readonly showStableId?: boolean\n readonly showId?: boolean\n readonly showSwitchToggle?: boolean\n readonly showChildrenAccordion?: boolean\n readonly children?: readonly DeviceItemDevice[]\n readonly onNavigate?: (deviceId: number) => void\n readonly className?: string\n}\n\n// ── Variant defaults ────────────────────────────────────────────────\n\nexport interface VariantDefaults {\n readonly showIntegrationIcon: boolean\n readonly showParentBadge: boolean\n readonly showSnapshot: boolean\n readonly showBattery: boolean\n readonly showStableId: boolean\n readonly showId: boolean\n readonly showSwitchToggle: boolean\n readonly showChildrenAccordion: boolean\n}\n\nconst DEFAULTS: Readonly<Record<DeviceItemVariant, VariantDefaults>> = {\n minimal: {\n showIntegrationIcon: false,\n showParentBadge: false,\n showSnapshot: false,\n showBattery: false,\n showStableId: false,\n showId: false,\n showSwitchToggle: true,\n showChildrenAccordion: false,\n },\n compact: {\n showIntegrationIcon: true,\n showParentBadge: true,\n showSnapshot: true,\n showBattery: true,\n showStableId: false,\n showId: false,\n showSwitchToggle: true,\n showChildrenAccordion: true,\n },\n expanded: {\n showIntegrationIcon: false,\n showParentBadge: true,\n showSnapshot: true,\n showBattery: true,\n showStableId: true,\n showId: true,\n showSwitchToggle: true,\n showChildrenAccordion: true,\n },\n}\n\nexport function resolveFlags(props: DeviceItemProps): VariantDefaults {\n const d = DEFAULTS[props.variant ?? 'compact']\n return {\n showIntegrationIcon: props.showIntegrationIcon ?? d.showIntegrationIcon,\n showParentBadge: props.showParentBadge ?? d.showParentBadge,\n showSnapshot: props.showSnapshot ?? d.showSnapshot,\n showBattery: props.showBattery ?? d.showBattery,\n showStableId: props.showStableId ?? d.showStableId,\n showId: props.showId ?? d.showId,\n showSwitchToggle: props.showSwitchToggle ?? d.showSwitchToggle,\n showChildrenAccordion: props.showChildrenAccordion ?? d.showChildrenAccordion,\n }\n}\n\n// ── Icon resolution ─────────────────────────────────────────────────\n\nexport const ROLE_ICONS: Readonly<Record<string, LucideIcon>> = {\n siren: Bell,\n floodlight: Lightbulb,\n spotlight: Sun,\n 'pir-sensor': Radar,\n chime: Music,\n autotrack: Crosshair,\n nightvision: Moon,\n 'privacy-mask': EyeOff,\n doorbell: DoorOpen,\n}\n\nexport const TYPE_ICONS: Readonly<Record<string, LucideIcon>> = {\n camera: CameraIcon,\n hub: Network,\n nvr: Network,\n light: Lightbulb,\n siren: Bell,\n switch: ToggleLeft,\n sensor: Radar,\n thermostat: Thermometer,\n button: CircleDot,\n generic: Wrench,\n}\n\nexport function deviceLeadIcon(device: DeviceItemDevice): LucideIcon {\n if (device.role) return ROLE_ICONS[device.role] ?? Wrench\n return TYPE_ICONS[device.type.toLowerCase()] ?? CameraIcon\n}\n\n// ── Feature icon + label maps (NEW in Phase 1) ──────────────────────\n\n/**\n * Icon for each `DeviceFeature` advertised on a device row. Used by\n * the features popover (`<DeviceItemFeatures>`) to render compact\n * feature chips. Keys mirror `DeviceFeature` enum string values from\n * `@camstack/types/device/device-type.ts`.\n */\nexport const FEATURE_ICON_MAP: Readonly<Record<string, LucideIcon>> = {\n 'native-snapshot': ImageIcon,\n 'two-way-audio': Mic,\n 'pan-tilt-zoom': Crosshair,\n 'ptz-autotrack': LocateFixed,\n 'doorbell-button': DoorOpen,\n 'motion-trigger': Activity,\n 'battery-operated': Battery,\n rebootable: RotateCw,\n}\n\nexport const FEATURE_LABEL_MAP: Readonly<Record<string, string>> = {\n 'native-snapshot': 'Native snapshot',\n 'two-way-audio': 'Two-way audio',\n 'pan-tilt-zoom': 'Pan-Tilt-Zoom',\n 'ptz-autotrack': 'PTZ autotrack',\n 'doorbell-button': 'Doorbell button',\n 'motion-trigger': 'Motion trigger',\n 'battery-operated': 'Battery operated',\n rebootable: 'Rebootable',\n}\n\n/**\n * Maps a wire-level `DeviceFeature` string to the cap name registered\n * in `deviceManager.getBindings` entries. A feature with NO entry here\n * is a pure informational marker (no cap to interrogate) — render but\n * without a native/enhanced label.\n *\n * Source of truth: live `getBindings` capNames observed against a\n * Reolink camera (snapshot, reboot, ptz, ptz-autotrack, intercom,\n * motion-trigger). Cap-name strings cross-checked against the\n * `name:` fields in `packages/types/src/capabilities/*.cap.ts`. When\n * a new feature ↔ cap pairing goes live, add the row here so the\n * popover picks it up.\n *\n * Pure markers (no cap to bind, intentionally absent):\n * - `battery-operated` — exposed as a plain `device.features` flag;\n * the runtime-state slice lives under the `battery` cap which has\n * its own dedicated reactive surface (`useDeviceBattery`).\n * - `doorbell-button` — UI marker only; the actual press events\n * flow through the `doorbell` cap which is already exercised by\n * `useDoorbellEvents`. Distinct from the marker.\n */\nexport const FEATURE_TO_CAP_NAME: Readonly<Record<string, string>> = {\n 'native-snapshot': 'snapshot',\n rebootable: 'reboot',\n 'pan-tilt-zoom': 'ptz',\n 'ptz-autotrack': 'ptz-autotrack',\n 'two-way-audio': 'intercom',\n 'motion-trigger': 'motion-trigger',\n}\n\n// ── Capability gates ────────────────────────────────────────────────\n\nconst FIRST_CLASS_TYPES: ReadonlySet<string> = new Set(['camera', 'hub', 'nvr'])\n\nexport function maySupportSwitch(device: DeviceItemDevice): boolean {\n return !FIRST_CLASS_TYPES.has(device.type.toLowerCase())\n}\n\nexport function isAccessoryChild(device: DeviceItemDevice): boolean {\n if (device.role) return true\n return !FIRST_CLASS_TYPES.has(device.type.toLowerCase())\n}\n\nexport function hasMotionTriggerFeature(device: DeviceItemDevice): boolean {\n return (device.features ?? []).includes('motion-trigger')\n}\n\n// ── stableId display helper ─────────────────────────────────────────\n\nexport function shortStableId(stableId: string): string {\n if (stableId.length <= 24) return stableId\n // Prefer the last segment after the LAST separator (':' wins over\n // '-' to keep stableIds like `provider-reolink-…:cam-9527…` visible\n // as `cam-9527…` rather than just `9527…`). Fall back to the last\n // 18 chars when no separator yields a useful tail.\n const colonAt = stableId.lastIndexOf(':')\n if (colonAt >= 0 && colonAt < stableId.length - 4) {\n return stableId.slice(colonAt + 1)\n }\n // For dash-segmented ids, take the last 2 segments to keep some\n // structure visible (`reolink-1777874716804-cam-9527…` → `cam-9527…`).\n const parts = stableId.split('-')\n if (parts.length > 2) {\n const tail = parts.slice(-2).join('-')\n if (tail.length >= 6) return tail\n }\n // Last resort — raw character clamp.\n return `…${stableId.slice(-18)}`\n}\n","/**\n * <DeviceItemActions> — type-aware dispatcher for inline quick actions.\n *\n * | Device shape | Atoms rendered |\n * |-------------------------------|-----------------------------------------|\n * | camera (any) | (snapshot opens via Preview slot) |\n * | light / siren / switch | OnMotionToggle (if feature) + SwitchToggle |\n * | sensor with switch cap | SwitchToggle |\n * | hub / nvr (rebootable) | Reboot — under the kebab MoreActionsMenu |\n * | button / generic | (none) |\n *\n * High-frequency toggles (Switch, OnMotion) stay inline. Destructive\n * or low-frequency actions (Reboot) move into a portal-positioned\n * kebab menu so the row stays compact and operators don't trip the\n * reboot by accident.\n *\n * Each atom self-gates via `useDeviceCapability` — the dispatcher\n * above is a coarse pre-flight only. An atom that finds its cap\n * unbound returns `null` so the row stays compact.\n */\nimport {\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type MouseEvent,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { Activity, MoreVertical, RotateCw } from 'lucide-react'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\nimport { useDeviceCapability } from '../../hooks/use-device-capability'\nimport { cn } from '../../lib/cn'\nimport type { DeviceItemDevice, VariantDefaults } from './helpers'\nimport { hasMotionTriggerFeature, maySupportSwitch } from './helpers'\n\nexport interface DeviceItemActionsProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly device: DeviceItemDevice\n readonly flags: VariantDefaults\n}\n\nexport function DeviceItemActions({ trpc, device, flags }: DeviceItemActionsProps): ReactNode {\n const enabled = !device.disabled\n if (!enabled) return null\n\n const type = device.type.toLowerCase()\n const showSwitchToggle = flags.showSwitchToggle && maySupportSwitch(device)\n const showOnMotion = hasMotionTriggerFeature(device)\n const isHubLike = type === 'hub' || type === 'nvr'\n const isRebootable = (device.features ?? []).includes('rebootable')\n const showReboot = isHubLike && isRebootable\n\n return (\n <>\n {showOnMotion && (\n <OnMotionToggle trpc={trpc} deviceId={device.id} features={device.features} />\n )}\n {showSwitchToggle && (\n <SwitchToggle trpc={trpc} deviceId={device.id} />\n )}\n {showReboot && (\n <MoreActionsMenu trpc={trpc} deviceId={device.id} />\n )}\n </>\n )\n}\n\n// ── SwitchToggle ────────────────────────────────────────────────────\n\ninterface SwitchToggleProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly deviceId: number\n}\n\nfunction SwitchToggle({ trpc, deviceId }: SwitchToggleProps): ReactNode {\n const { dev, cap, slice, available } = useDeviceCapability({\n trpc, deviceId,\n cap: (d) => d.switch,\n slice: (d) => d.state.switch,\n })\n const [pending, setPending] = useState(false)\n\n if (dev !== null && !cap) return null\n\n const on = slice?.on === true\n const knobStyle: CSSProperties = { transform: on ? 'translateX(14px)' : 'translateX(2px)' }\n\n const handleClick = async (e: MouseEvent): Promise<void> => {\n e.stopPropagation()\n if (pending || !available || !cap) return\n setPending(true)\n try {\n await cap.setState({ on: !on })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={(e) => { void handleClick(e) }}\n disabled={pending || !available}\n className={cn(\n 'relative inline-flex h-4 w-7 items-center rounded-full border transition-colors flex-shrink-0',\n on ? 'bg-success/30 border-success/50' : 'bg-surface-hover border-border',\n pending && 'opacity-60',\n !available && 'opacity-40 cursor-not-allowed',\n )}\n title={!available ? 'Awaiting state…' : on ? 'Turn off' : 'Turn on'}\n aria-pressed={on}\n >\n <span\n className={cn('absolute h-3 w-3 rounded-full transition-all', on ? 'bg-success' : 'bg-foreground-subtle')}\n style={knobStyle}\n />\n </button>\n )\n}\n\n// ── OnMotionToggle ──────────────────────────────────────────────────\n\ninterface OnMotionToggleProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly deviceId: number\n readonly features: readonly string[] | undefined\n}\n\nfunction OnMotionToggle({ trpc, deviceId, features }: OnMotionToggleProps): ReactNode {\n const { dev, cap, slice, available } = useDeviceCapability({\n trpc, deviceId,\n cap: (d) => d.motionTrigger,\n slice: (d) => d.state.motionTrigger,\n requireFeature: 'motion-trigger',\n deviceFeatures: features,\n })\n const [pending, setPending] = useState(false)\n\n if (dev !== null && !cap) return null\n\n const on = slice?.enabled === true\n\n const handleClick = async (e: MouseEvent): Promise<void> => {\n e.stopPropagation()\n if (pending || !available || !cap) return\n setPending(true)\n try {\n await cap.setMotionTrigger({ enabled: !on })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={(e) => { void handleClick(e) }}\n disabled={pending || !available}\n className={cn(\n 'inline-flex h-4 w-4 items-center justify-center rounded transition-colors flex-shrink-0',\n on ? 'text-primary bg-primary/10' : 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n (pending || !available) && 'opacity-50',\n )}\n title={!available ? 'Awaiting state…' : on ? 'Motion-trigger: on (click to disable)' : 'Motion-trigger: off (click to enable)'}\n aria-pressed={on}\n >\n <Activity className=\"h-2.5 w-2.5\" />\n </button>\n )\n}\n\n// ── MoreActionsMenu (kebab) ─────────────────────────────────────────\n//\n// Portal-positioned dropdown so the menu escapes the table wrapper's\n// `overflow-hidden`. Trigger is a 3-dot icon button; content is a\n// fixed-position `<div>` mounted on `document.body`. Closes on:\n// - clicking the trigger again (toggle)\n// - clicking outside (mousedown listener)\n// - pressing Escape (keydown listener)\n// - invoking any item handler\n// The trigger only renders when the menu has at least one available\n// action (today: reboot when bound). When `cap` resolves to undefined\n// after `dev` lands, the kebab itself returns `null` so the row stays\n// compact. Keyboard: Enter/Space activate the trigger natively;\n// Escape on the dropdown closes it.\n\ninterface MoreActionsMenuProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly deviceId: number\n}\n\ninterface MenuPosition {\n readonly top: number\n readonly left: number\n}\n\nconst MENU_WIDTH = 168\nconst MENU_GAP = 4\n\nfunction MoreActionsMenu({ trpc, deviceId }: MoreActionsMenuProps): ReactNode {\n const { dev, cap } = useDeviceCapability({\n trpc, deviceId,\n cap: (d) => d.reboot,\n slice: () => undefined,\n })\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const [position, setPosition] = useState<MenuPosition | null>(null)\n const [pending, setPending] = useState(false)\n\n const ready = dev !== null && cap !== undefined && cap !== null\n const isOpen = position !== null\n\n const close = (): void => setPosition(null)\n const openMenu = (): void => {\n const el = triggerRef.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n const desiredLeft = rect.right - MENU_WIDTH\n const left = Math.max(8, Math.min(desiredLeft, window.innerWidth - MENU_WIDTH - 8))\n const top = rect.bottom + MENU_GAP\n setPosition({ top, left })\n }\n\n useEffect(() => {\n if (!isOpen) return\n const onMouseDown = (e: globalThis.MouseEvent): void => {\n const trg = triggerRef.current\n const menu = menuRef.current\n const target = e.target as Node | null\n if (target === null) return\n if (trg && trg.contains(target)) return\n if (menu && menu.contains(target)) return\n close()\n }\n const onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n close()\n }\n }\n document.addEventListener('mousedown', onMouseDown)\n document.addEventListener('keydown', onKeyDown)\n return () => {\n document.removeEventListener('mousedown', onMouseDown)\n document.removeEventListener('keydown', onKeyDown)\n }\n }, [isOpen])\n\n // Hide the kebab if dev resolved but no reboot cap — no actions to show.\n if (dev !== null && !cap) return null\n\n const handleToggle = (e: MouseEvent): void => {\n e.stopPropagation()\n if (isOpen) close()\n else openMenu()\n }\n\n const handleReboot = async (): Promise<void> => {\n if (pending || !ready || !cap) return\n setPending(true)\n close()\n try {\n await cap.reboot({})\n } finally {\n setPending(false)\n }\n }\n\n return (\n <>\n <button\n ref={triggerRef}\n type=\"button\"\n onClick={handleToggle}\n disabled={pending || !ready}\n className={cn(\n 'inline-flex h-5 w-5 items-center justify-center rounded text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors flex-shrink-0',\n (pending || !ready) && 'opacity-50',\n isOpen && 'bg-surface-hover text-foreground',\n )}\n title=\"More actions\"\n aria-label=\"More actions\"\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n >\n <MoreVertical className=\"h-3 w-3\" />\n </button>\n {position && createPortal(\n <div\n ref={menuRef}\n role=\"menu\"\n style={{\n position: 'fixed',\n top: position.top,\n left: position.left,\n width: MENU_WIDTH,\n }}\n className=\"z-[9999] rounded-md border border-border bg-surface shadow-lg shadow-black/30 p-1\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n onClick={() => { void handleReboot() }}\n disabled={pending || !ready}\n className={cn(\n 'flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-[11px] text-foreground',\n 'hover:bg-surface-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed',\n )}\n >\n <RotateCw className=\"h-3 w-3 shrink-0 text-foreground-subtle\" />\n <span>Reboot device</span>\n </button>\n </div>,\n document.body,\n )}\n </>\n )\n}\n","/**\n * <DeviceItemFeatures> — children-count badge + optional feature-icon\n * row with hover popover.\n *\n * Battery / charging / sleeping pills moved to <DeviceItemPreview> in\n * Phase 2 (status pills belong with the preview/snapshot, not features).\n *\n * What this renders is now driven by `useDeviceFeatures` — the row\n * shows ONLY features whose corresponding cap is actually registered\n * on the device (or pure informational markers like `battery-operated`\n * / `doorbell-button` that have no cap to interrogate). The popover\n * labels each row `native` / `enhanced` / `marker` based on the live\n * `getBindings` entry's `kind` field. The previous conservative\n * advertised/no-slice/bound trio is gone — it under-reported wired\n * features (only 2 of 8 had a slice mapping) and gave operators\n * misleading \"advertised\" gray pills on Reolink cameras that fully\n * implement snapshot/reboot/ptz/intercom natively.\n */\nimport { useRef, useState, type ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\nimport type { LucideIcon } from 'lucide-react'\nimport { useDeviceFeatures, type ResolvedFeature } from '../../hooks/use-device-features'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\nimport { cn } from '../../lib/cn'\nimport {\n FEATURE_ICON_MAP,\n FEATURE_LABEL_MAP,\n type DeviceItemDevice,\n type VariantDefaults,\n} from './helpers'\n\nexport interface DeviceItemFeaturesProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly device: DeviceItemDevice\n readonly flags: VariantDefaults\n readonly accessoryCount: number\n readonly adoptedCount: number\n /**\n * When true, render the feature-icon row + popover (table view's\n * \"Features\" column). Off in card view — only battery + +N badge\n * to save horizontal space.\n */\n readonly showFeatureRow?: boolean\n}\n\nconst EMPTY_FEATURES: readonly string[] = []\n\nexport function DeviceItemFeatures({\n trpc,\n device,\n flags,\n accessoryCount,\n adoptedCount,\n showFeatureRow = false,\n}: DeviceItemFeaturesProps): ReactNode {\n const total = accessoryCount + adoptedCount\n const showChildrenBadge = flags.showChildrenAccordion && total > 0\n const rawFeatures = device.features ?? EMPTY_FEATURES\n const showFeaturesGate = showFeatureRow && rawFeatures.length > 0\n const { resolved } = useDeviceFeatures(trpc, showFeaturesGate ? device.id : null, rawFeatures)\n const showFeatures = showFeaturesGate && resolved.length > 0\n if (!showChildrenBadge && !showFeatures) return null\n\n return (\n <div className=\"flex items-center gap-1.5 flex-nowrap whitespace-nowrap min-w-0\">\n {showChildrenBadge && (\n <ChildrenCountBadge accessoryCount={accessoryCount} adoptedCount={adoptedCount} />\n )}\n {showFeatures && <FeatureRow resolved={resolved} />}\n </div>\n )\n}\n\n// ── ChildrenCountBadge (inline) ─────────────────────────────────────\n\ninterface ChildrenCountBadgeProps {\n readonly accessoryCount: number\n readonly adoptedCount: number\n}\n\nfunction ChildrenCountBadge({ accessoryCount, adoptedCount }: ChildrenCountBadgeProps): ReactNode {\n const total = accessoryCount + adoptedCount\n if (total === 0) return null\n const title = adoptedCount > 0 && accessoryCount > 0\n ? `${String(adoptedCount)} adopted · ${String(accessoryCount)} accessor${accessoryCount === 1 ? 'y' : 'ies'}`\n : adoptedCount > 0\n ? `${String(adoptedCount)} adopted`\n : `${String(accessoryCount)} accessor${accessoryCount === 1 ? 'y' : 'ies'}`\n return (\n <span\n className=\"text-[9px] font-medium text-foreground-subtle bg-surface-elevated/60 rounded px-1.5 py-0.5 flex-shrink-0\"\n title={title}\n >\n +{total}\n </span>\n )\n}\n\n// ── FeatureRow + FeatureRowPopover (inline) ─────────────────────────\n\ninterface FeatureRowProps {\n readonly resolved: readonly ResolvedFeature[]\n}\n\ninterface PopoverPosition {\n readonly top: number\n readonly left: number\n}\n\nconst POPOVER_WIDTH = 240\nconst POPOVER_MIN_HEIGHT = 200\n\nfunction FeatureRow({ resolved }: FeatureRowProps): ReactNode {\n const triggerRef = useRef<HTMLSpanElement | null>(null)\n const [position, setPosition] = useState<PopoverPosition | null>(null)\n\n const open = (): void => {\n const el = triggerRef.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n const spaceBelow = window.innerHeight - rect.bottom\n const placeBelow = spaceBelow >= POPOVER_MIN_HEIGHT\n const top = placeBelow\n ? rect.bottom + 4\n : rect.top - POPOVER_MIN_HEIGHT - 4\n const left = Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8))\n setPosition({ top, left })\n }\n const close = (): void => setPosition(null)\n\n return (\n <span\n ref={triggerRef}\n className=\"relative inline-flex items-center gap-1 cursor-help\"\n onMouseEnter={open}\n onMouseLeave={close}\n >\n {resolved.map((entry) => {\n const Icon = FEATURE_ICON_MAP[entry.feature]\n if (!Icon) return null\n return (\n <span\n key={entry.feature}\n className=\"inline-flex items-center justify-center h-4 w-4 rounded bg-surface-elevated/60 text-foreground-subtle\"\n title={FEATURE_LABEL_MAP[entry.feature] ?? entry.feature}\n >\n <Icon className=\"h-2.5 w-2.5\" />\n </span>\n )\n })}\n {position && createPortal(\n <FeatureRowPopover resolved={resolved} position={position} />,\n document.body,\n )}\n </span>\n )\n}\n\ninterface FeatureRowPopoverProps {\n readonly resolved: readonly ResolvedFeature[]\n readonly position: PopoverPosition\n}\n\nfunction FeatureRowPopover({ resolved, position }: FeatureRowPopoverProps): ReactNode {\n return (\n <div\n style={{\n position: 'fixed',\n top: position.top,\n left: position.left,\n width: POPOVER_WIDTH,\n pointerEvents: 'none',\n }}\n className=\"z-[9999] rounded-md border border-border bg-surface shadow-lg shadow-black/30 p-2\"\n >\n <h5 className=\"text-[9px] font-semibold uppercase tracking-wider text-foreground-subtle mb-1.5\">\n Features\n </h5>\n <ul className=\"space-y-0.5\">\n {resolved.map((entry) => (\n <FeaturePopoverRow key={entry.feature} entry={entry} />\n ))}\n </ul>\n </div>\n )\n}\n\ninterface FeaturePopoverRowProps {\n readonly entry: ResolvedFeature\n}\n\nfunction FeaturePopoverRow({ entry }: FeaturePopoverRowProps): ReactNode {\n const Icon: LucideIcon | undefined = FEATURE_ICON_MAP[entry.feature]\n const label = FEATURE_LABEL_MAP[entry.feature] ?? entry.feature\n return (\n <li className=\"flex items-center justify-between gap-2 text-[10px]\">\n <span className=\"flex items-center gap-1.5 text-foreground\">\n {Icon && <Icon className=\"h-3 w-3 text-foreground-subtle\" />}\n <span>{label}</span>\n </span>\n <FeatureKindPill kind={entry.kind} />\n </li>\n )\n}\n\ninterface FeatureKindPillProps {\n readonly kind: ResolvedFeature['kind']\n}\n\nfunction FeatureKindPill({ kind }: FeatureKindPillProps): ReactNode {\n if (kind === 'marker') {\n // Pure markers (battery-operated, doorbell-button) are\n // informational only — no cap to bind. A subtle title-tooltip\n // explains while keeping the row visually quiet.\n return (\n <span\n className=\"text-[8.5px] px-1 rounded text-foreground-subtle\"\n title=\"Informational marker (no cap registered)\"\n >\n marker\n </span>\n )\n }\n return (\n <span\n className={cn(\n 'text-[8.5px] px-1 rounded',\n kind === 'native'\n ? 'bg-success/15 text-success'\n : 'bg-primary/15 text-primary',\n )}\n >\n {kind}\n </span>\n )\n}\n","/**\n * useDeviceFeatures — resolve advertised `device.features` against the\n * live `deviceManager.getBindings` entries to produce a list that\n * tells the UI WHICH features are actually wired AND whether each\n * one comes from the native driver or an enhancing wrapper addon.\n *\n * Why this hook exists:\n * `device.features` is an addon-side advertisement (a static list\n * the driver pushes when probing the camera). It says \"I claim to\n * support X\" but does NOT prove the cap actually got registered.\n * `getBindings` is the runtime source of truth — every entry there\n * is a live (`registerNativeCap`-completed) provider on the kernel.\n *\n * Result semantics (intentional):\n * - feature has a cap mapping AND that cap IS in bindings →\n * show as `native` (binding.kind === 'native') or `enhanced`\n * (binding.kind === 'wrapped' — a wrapper addon enhances it).\n * - feature has NO cap mapping → it's an informational marker\n * (`battery-operated`, `doorbell-button`, etc.). Render but\n * don't claim a binding state.\n * - feature has a cap mapping but the cap is NOT in bindings →\n * hide. The driver advertised but didn't register — broken\n * state; honest answer is \"not wired\".\n *\n * While bindings are loading we return all raw features as markers\n * so the icon row renders without flickering on first paint.\n */\nimport { useEffect, useState } from 'react'\nimport type { DeviceBinding, DeviceBindingEntry } from '@camstack/types'\nimport { FEATURE_TO_CAP_NAME } from '../composites/device-item/helpers'\nimport type { UseDeviceProxyTrpc } from './use-device-proxy'\n\nexport type ResolvedFeatureKind = 'native' | 'enhanced' | 'marker'\n\nexport type ResolvedFeature =\n | { readonly kind: 'native', readonly feature: string, readonly capName: string }\n | { readonly kind: 'enhanced', readonly feature: string, readonly capName: string }\n | { readonly kind: 'marker', readonly feature: string }\n\nexport interface UseDeviceFeaturesResult {\n /** Pending or unresolved (during initial bindings fetch). */\n readonly loading: boolean\n /**\n * Resolved list — features whose corresponding cap is in bindings,\n * PLUS pure markers (FEATURE_TO_CAP_NAME has no entry). Features\n * with a cap mapping that is NOT in bindings are filtered out.\n */\n readonly resolved: readonly ResolvedFeature[]\n}\n\nconst EMPTY: readonly ResolvedFeature[] = Object.freeze([])\n\nfunction bindingKindToFeatureKind(kind: DeviceBindingEntry['kind']): 'native' | 'enhanced' {\n return kind === 'native' ? 'native' : 'enhanced'\n}\n\nfunction asMarkers(features: readonly string[]): readonly ResolvedFeature[] {\n return features.map((feature) => ({ kind: 'marker', feature } as const))\n}\n\nfunction buildResolved(\n rawFeatures: readonly string[],\n binding: DeviceBinding,\n): readonly ResolvedFeature[] {\n const byCap = new Map<string, DeviceBindingEntry>()\n // Defensive guard: a malformed/legacy binding payload (no `entries`)\n // is treated as an empty entry list — every advertised feature with\n // a cap mapping then falls into the \"advertised but cap not in\n // bindings → hide\" branch and only pure markers survive.\n const entries = binding.entries ?? []\n for (const entry of entries) byCap.set(entry.capName, entry)\n\n const out: ResolvedFeature[] = []\n for (const feature of rawFeatures) {\n const capName = FEATURE_TO_CAP_NAME[feature]\n if (capName === undefined) {\n // Pure marker (no cap to interrogate).\n out.push({ kind: 'marker', feature })\n continue\n }\n const entry = byCap.get(capName)\n if (!entry) {\n // Advertised but cap not registered — broken state, hide.\n continue\n }\n out.push({ kind: bindingKindToFeatureKind(entry.kind), feature, capName })\n }\n return out\n}\n\nexport function useDeviceFeatures(\n trpc: UseDeviceProxyTrpc,\n deviceId: number | null,\n rawFeatures: readonly string[],\n): UseDeviceFeaturesResult {\n const [binding, setBinding] = useState<DeviceBinding | null>(null)\n const [errored, setErrored] = useState<boolean>(false)\n const [loading, setLoading] = useState<boolean>(true)\n\n useEffect(() => {\n if (deviceId === null) {\n setBinding(null)\n setErrored(false)\n setLoading(false)\n return\n }\n let cancelled = false\n setLoading(true)\n setErrored(false)\n\n const refresh = async (): Promise<void> => {\n try {\n const next = await trpc.deviceManager.getBindings.query({ deviceId })\n if (cancelled) return\n setBinding(next)\n setLoading(false)\n } catch {\n if (cancelled) return\n // Fall back to \"show everything as marker\" so the operator at\n // least sees the addon's declarations on transient tRPC errors.\n setErrored(true)\n setLoading(false)\n }\n }\n\n void refresh()\n\n const sub = trpc.live?.onEvent.subscribe(\n { category: 'capability.binding-changed' },\n {\n onData: (evt) => {\n const src = evt.data?.source\n if (!src) {\n void refresh()\n return\n }\n if (src.type === 'device' && src.id === deviceId) void refresh()\n },\n },\n )\n\n return () => {\n cancelled = true\n sub?.unsubscribe()\n }\n }, [trpc, deviceId])\n\n if (rawFeatures.length === 0) {\n return { loading, resolved: EMPTY }\n }\n if (loading || errored || !binding) {\n return { loading, resolved: asMarkers(rawFeatures) }\n }\n return { loading: false, resolved: buildResolved(rawFeatures, binding) }\n}\n","/**\n * <DeviceItemHeader> — the leftmost segment of the row: chevron\n * (when accordion enabled + has children), lead icon, name + meta-line\n * (`#id · stableId-tail`), parent badge.\n *\n * `flex: 1; min-w-0` — eats every leftover horizontal pixel; name\n * truncates with ellipsis when the row gets narrow.\n */\nimport { type ReactNode } from 'react'\nimport { ChevronDown, ChevronRight, Network } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport type {\n DeviceItemDevice,\n DeviceItemParent,\n DeviceItemVariant,\n VariantDefaults,\n} from './helpers'\nimport { deviceLeadIcon, shortStableId } from './helpers'\n\nexport interface DeviceItemHeaderProps {\n readonly device: DeviceItemDevice\n readonly variant: DeviceItemVariant\n readonly flags: VariantDefaults\n readonly parent: DeviceItemParent | null\n readonly integrationIcon: ReactNode | null\n readonly hasChildren: boolean\n readonly expanded: boolean\n readonly onToggleExpand: () => void\n readonly onNavigateToParent: (id: number) => void\n}\n\nexport function DeviceItemHeader({\n device,\n variant,\n flags,\n parent,\n integrationIcon,\n hasChildren,\n expanded,\n onToggleExpand,\n onNavigateToParent,\n}: DeviceItemHeaderProps): ReactNode {\n const Icon = deviceLeadIcon(device)\n return (\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n {flags.showChildrenAccordion && hasChildren ? (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onToggleExpand()\n }}\n className=\"flex h-3.5 w-3.5 items-center justify-center text-foreground-subtle hover:text-foreground transition-colors flex-shrink-0\"\n aria-label={expanded ? 'Collapse children' : 'Expand children'}\n aria-expanded={expanded}\n >\n {expanded ? <ChevronDown className=\"h-3 w-3\" /> : <ChevronRight className=\"h-3 w-3\" />}\n </button>\n ) : flags.showChildrenAccordion ? (\n <span className=\"h-3.5 w-3.5 flex-shrink-0\" />\n ) : null}\n\n <Icon\n className={cn(\n 'text-foreground-subtle flex-shrink-0',\n variant === 'minimal' ? 'h-3 w-3' : 'h-3.5 w-3.5',\n )}\n />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\n {flags.showIntegrationIcon && integrationIcon && (\n <span className=\"flex-shrink-0\">{integrationIcon}</span>\n )}\n <span\n className={cn(\n 'font-semibold text-foreground truncate',\n variant === 'minimal' ? 'text-[10.5px]' : 'text-[11px]',\n )}\n title={device.name}\n >\n {device.name}\n </span>\n </div>\n\n {(flags.showId || flags.showStableId) && (\n <div\n className=\"mt-0.5 flex items-center gap-1 text-[9px] text-foreground-subtle font-mono truncate\"\n title={flags.showStableId ? `stableId: ${device.stableId}` : undefined}\n >\n {flags.showId && (\n <span className=\"flex-shrink-0 tabular-nums\">#{String(device.id)}</span>\n )}\n {flags.showId && flags.showStableId && (\n <span className=\"flex-shrink-0 opacity-50\">·</span>\n )}\n {flags.showStableId && (\n <span className=\"truncate\">{shortStableId(device.stableId)}</span>\n )}\n </div>\n )}\n\n {flags.showParentBadge && parent && (\n <button\n type=\"button\"\n onClick={(e) => { e.stopPropagation(); onNavigateToParent(parent.id) }}\n className=\"mt-0.5 inline-flex max-w-full items-center gap-1 text-[9px] text-foreground-subtle hover:text-primary transition-colors\"\n title={`Open parent: ${parent.name} (#${String(parent.id)})`}\n >\n <Network className=\"h-2.5 w-2.5 shrink-0\" />\n <span className=\"truncate\">Under: {parent.name}</span>\n </button>\n )}\n </div>\n </div>\n )\n}\n","/**\n * <DeviceItemPreview> — type-dispatched preview slot.\n *\n * Renders, in order:\n * 1. Status pills — battery %, charging plug, sleeping moon (when\n * the device exposes a battery slice). These were previously in\n * the Features cell; they belong here because they describe the\n * preview-relevant state (a sleeping cam can't snapshot, a low\n * battery cam may drop frames).\n * 2. Snapshot eye — opens a portal-positioned preview popover with\n * flip-on-collision so the device-grid's overflow ancestors don't\n * clip it. Gated on `enabled` (camera + showSnapshot flag) AND\n * device.online.\n *\n * The status-pills section renders for ANY battery-operated device,\n * camera or otherwise; the snapshot eye stays gated on cameras.\n */\nimport { useRef, useState, type ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Eye } from 'lucide-react'\nimport { useDeviceBattery } from '../../hooks/use-device-battery'\nimport { useDeviceSnapshotImage } from '../../hooks/use-device-snapshot'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\nimport { BatteryBadge } from '../battery-badge'\nimport type { DeviceItemDevice } from './helpers'\n\nexport interface DeviceItemPreviewProps {\n readonly trpc: UseDeviceProxyTrpc\n readonly device: DeviceItemDevice\n readonly status: 'online' | 'offline' | 'disabled'\n /**\n * Render gate for the snapshot eye icon (typically\n * `flags.showSnapshot && isCamera` from the orchestrator). Even when\n * `false`, the component still renders the status-pills row when\n * `showStatusPills` is on.\n */\n readonly enabled: boolean\n /**\n * When true, render the battery / charging / sleeping pills next to\n * the snapshot eye. Driven by table view (where the Preview cell is\n * the natural home for status indicators); off in card view to keep\n * the row narrow.\n */\n readonly showStatusPills?: boolean\n}\n\nexport function DeviceItemPreview({\n trpc,\n device,\n status,\n enabled,\n showStatusPills = false,\n}: DeviceItemPreviewProps): ReactNode {\n const liveActive = enabled && device.online\n const snapshot = useDeviceSnapshotImage(trpc, liveActive ? device.id : null)\n\n const isBatteryOperated = (device.features ?? []).includes('battery-operated')\n const wantPills = showStatusPills && isBatteryOperated && !device.disabled\n const batteryStatus = useDeviceBattery(trpc, wantPills ? device.id : null)\n\n if (!enabled && !wantPills) return null\n\n return (\n <span className=\"inline-flex items-center gap-1.5 flex-nowrap whitespace-nowrap\">\n {wantPills && batteryStatus && <BatteryBadge status={batteryStatus} />}\n {enabled && (\n <SnapshotPopoverInline\n deviceName={device.name}\n snapshotUrl={snapshot.src}\n status={status}\n />\n )}\n </span>\n )\n}\n\n// ── Internals — portal-positioned snapshot popover ──────────────────\n\ninterface SnapshotPopoverInlineProps {\n readonly deviceName: string\n readonly snapshotUrl: string | null\n readonly status: string\n}\n\ninterface PopoverPosition {\n readonly top: number\n readonly left: number\n readonly placeBelow: boolean\n}\n\nconst POPOVER_WIDTH = 288\nconst POPOVER_HEIGHT = 196\nconst TRIGGER_GAP = 8\n\nfunction SnapshotPopoverInline({ deviceName, snapshotUrl, status }: SnapshotPopoverInlineProps): ReactNode {\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const [position, setPosition] = useState<PopoverPosition | null>(null)\n const offline = status === 'offline' || status === 'disabled'\n\n const open = (): void => {\n const el = triggerRef.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n const spaceAbove = rect.top\n const spaceBelow = window.innerHeight - rect.bottom\n const placeBelow = spaceAbove < POPOVER_HEIGHT + TRIGGER_GAP && spaceBelow > spaceAbove\n const top = placeBelow\n ? rect.bottom + TRIGGER_GAP\n : rect.top - POPOVER_HEIGHT - TRIGGER_GAP\n const desiredLeft = rect.right - POPOVER_WIDTH\n const left = Math.max(8, Math.min(desiredLeft, window.innerWidth - POPOVER_WIDTH - 8))\n setPosition({ top, left, placeBelow })\n }\n const close = (): void => setPosition(null)\n\n return (\n <>\n <button\n ref={triggerRef}\n type=\"button\"\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={open}\n onMouseLeave={close}\n onFocus={open}\n onBlur={close}\n className=\"flex h-6 w-6 items-center justify-center rounded text-foreground-subtle hover:bg-surface-hover hover:text-foreground transition-colors flex-shrink-0\"\n title=\"Preview\"\n aria-label=\"Preview snapshot\"\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </button>\n {position && createPortal(\n <div\n style={{\n position: 'fixed',\n top: position.top,\n left: position.left,\n width: POPOVER_WIDTH,\n pointerEvents: 'none',\n }}\n className=\"rounded-lg border border-border bg-surface shadow-lg shadow-black/30 z-[9999] overflow-hidden\"\n >\n <div className=\"h-40 bg-background flex items-center justify-center\">\n {snapshotUrl && !offline ? (\n <img src={snapshotUrl} alt={deviceName} className=\"h-full w-full object-cover\" />\n ) : (\n <span className=\"text-xs text-foreground-subtle\">\n {status === 'offline' ? 'Offline — no snapshot' : status === 'disabled' ? 'Disabled' : 'No snapshot yet'}\n </span>\n )}\n </div>\n <div className=\"px-3 py-2\">\n <p className=\"text-xs font-semibold text-foreground truncate\">{deviceName}</p>\n </div>\n </div>,\n document.body,\n )}\n </>\n )\n}\n","/**\n * useDeviceBattery — battery status for a device.\n *\n * Thin wrapper over the `useDeviceState` combinator, which itself\n * wraps `useDeviceProxy + useDeviceStateSlice(dev?.state.battery)`.\n * The kernel runtime-state mirror keeps the slice value warm — one\n * initial fetch on first subscribe, then push updates on every\n * `setCapSlice` for the battery slice. No manual event subscription,\n * no parallel `getStatus` polling.\n *\n * Returns `null` when no provider has emitted yet (non-battery\n * camera, or initial fetch hasn't returned).\n */\nimport { useDeviceState, type UseDeviceProxyTrpc } from './use-device-proxy'\n\nexport interface BatteryStatus {\n readonly percentage: number\n readonly charging: 'dc' | 'solar' | 'none'\n readonly sleeping: boolean\n readonly lastUpdated: number\n}\n\n/**\n * Backwards-compatible alias for the trpc shape — historically the\n * hook took its own narrow contract; the proxy generalisation\n * supersedes that.\n */\nexport type UseDeviceBatteryTrpc = UseDeviceProxyTrpc\n\nexport function useDeviceBattery(\n trpc: UseDeviceProxyTrpc,\n deviceId: number | null,\n): BatteryStatus | null {\n const slice = useDeviceState(trpc, deviceId, (s) => s.battery)\n return (slice as BatteryStatus | undefined) ?? null\n}\n","/**\n * useDeviceSnapshotImage — autosufficient snapshot fetcher for a device.\n *\n * Wraps the entire `dev.snapshot.getSnapshot({force?})` boilerplate\n * (proxy lookup + react-query caching + force-refresh ref + data-URL\n * conversion) into a single hook so callers don't drill snapshot\n * state into their stream-player components.\n *\n * Caching: the result lives in react-query's global QueryClient\n * (the singleton at app scope), keyed by `['device', N, 'snapshot']`.\n * That IS the \"global context\" — every consumer mounting the hook\n * with the same `deviceId` shares the same cache entry, AND when a\n * consumer unmounts and remounts the cached value is served\n * instantly. We pin a long `gcTime` so the entry survives unmount\n * cycles, and a short `staleTime` so a remount after a real gap\n * re-validates against the camera in the background:\n * - `staleTime: 10_000` → fresh for 10s, then re-fetches on next mount\n * - `gcTime: 86400_000` → kept for 24h after last consumer leaves\n * Window-focus and reconnect refetch are off so the camera isn't\n * pinged on every tab switch. Manual refresh via `refresh()` always\n * bypasses the cache.\n *\n * Returns:\n * - `src`: data-URL ready to drop into `<img>` (or `null` until the\n * first successful fetch).\n * - `loading`: true while a fetch is in flight (initial OR refresh).\n * - `refresh()`: forces exactly ONE bypass-cache fetch.\n *\n * The hook is data-only — render decisions (placeholder, paused\n * preview, …) live in the component that consumes it.\n */\nimport { useRef } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { useDeviceProxy, type UseDeviceProxyTrpc } from './use-device-proxy'\n\nexport interface DeviceSnapshotImage {\n /** Data-URL for the most recently fetched snapshot, or `null`. */\n readonly src: string | null\n /** True while a fetch is in flight. */\n readonly loading: boolean\n /** Force the next fetch to bypass cache (single use). */\n readonly refresh: () => void\n}\n\nexport function useDeviceSnapshotImage(\n trpc: UseDeviceProxyTrpc,\n deviceId: number | null,\n): DeviceSnapshotImage {\n const dev = useDeviceProxy(trpc, deviceId)\n const forceRef = useRef(false)\n\n const { data, isLoading, isFetching, refetch } = useQuery({\n queryKey: ['device', deviceId, 'snapshot'],\n queryFn: () => {\n // `enabled` already gates this on `dev !== null`, but a defensive\n // throw covers the (in-practice never-observed-but-theoretically-\n // possible) race where `enabled` evaluates true during the same\n // render that `dev` is still null. Returning `null` here would\n // otherwise let react-query cache a `null` result against the\n // queryKey, and the 10s `staleTime` window would block the\n // next-render refetch when the proxy actually populates — exactly\n // the \"popover empty until full reload\" symptom.\n if (!dev) throw new Error('useDeviceSnapshotImage: device proxy not ready')\n const force = forceRef.current\n forceRef.current = false\n return dev.snapshot?.getSnapshot({ force }) ?? null\n },\n enabled: dev !== null && deviceId !== null,\n // Cache lives in react-query's global QueryClient (app scope), so\n // every consumer sharing the deviceId reads the same entry AND the\n // entry survives unmount/remount cycles. We pin a long `gcTime` so\n // the entry isn't evicted between navigations; `staleTime` stays\n // short so a remount after a real gap re-validates against the\n // camera in the background while showing the cached image.\n staleTime: 10_000,\n gcTime: 24 * 60 * 60 * 1000,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n retry: false,\n })\n\n const src = data\n ? `data:${data.contentType};base64,${data.base64}`\n : null\n\n function refresh(): void {\n forceRef.current = true\n void refetch()\n }\n\n return { src, loading: isLoading || isFetching, refresh }\n}\n","/**\n * BatteryBadge — compact battery indicator for camera tiles + headers.\n *\n * Renders a battery icon with the percentage, a charging glyph when the\n * device is on DC/solar, and a moon when the camera is sleeping (so\n * operators don't blame the platform for low fps on a sleeping cam).\n *\n * Self-contained on data: the caller passes a `status` snapshot from\n * `trpc.battery.getStatus.useQuery` or the `battery.onStatusChanged`\n * event subscription. Returns `null` when status is missing so the\n * call-site can drop the badge in unconditionally — non-battery\n * cameras simply produce no badge.\n */\nimport { Battery, BatteryLow, BatteryWarning, BatteryFull, Plug, Sun, Moon } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\nexport interface BatteryStatusLike {\n readonly percentage: number\n readonly charging: 'dc' | 'solar' | 'none'\n readonly sleeping: boolean\n}\n\nexport interface BatteryBadgeProps {\n readonly status: BatteryStatusLike | null | undefined\n /** `'compact'` shows only icon + %; `'full'` adds the source label. */\n readonly variant?: 'compact' | 'full'\n readonly className?: string\n}\n\nfunction pickIcon(percentage: number): typeof Battery {\n if (percentage <= 10) return BatteryWarning\n if (percentage <= 30) return BatteryLow\n if (percentage >= 95) return BatteryFull\n return Battery\n}\n\nfunction levelColor(percentage: number, charging: 'dc' | 'solar' | 'none'): string {\n if (charging !== 'none') return 'text-emerald-400'\n if (percentage <= 10) return 'text-rose-400'\n if (percentage <= 30) return 'text-amber-400'\n return 'text-foreground-subtle'\n}\n\nexport function BatteryBadge({ status, variant = 'compact', className }: BatteryBadgeProps) {\n if (!status) return null\n\n const Icon = pickIcon(status.percentage)\n const color = levelColor(status.percentage, status.charging)\n const ChargingGlyph = status.charging === 'solar' ? Sun\n : status.charging === 'dc' ? Plug\n : null\n const showSleeping = status.sleeping\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1 text-[10px] font-medium',\n color,\n className,\n )}\n title={\n `Battery: ${Math.round(status.percentage)}%`\n + (status.charging !== 'none' ? ` · charging (${status.charging})` : '')\n + (status.sleeping ? ' · sleeping' : '')\n }\n >\n <Icon className=\"h-3.5 w-3.5\" />\n <span>{Math.round(status.percentage)}%</span>\n {ChargingGlyph && <ChargingGlyph className=\"h-3 w-3\" />}\n {showSleeping && <Moon className=\"h-3 w-3 text-blue-300\" />}\n {variant === 'full' && status.charging !== 'none' && (\n <span className=\"text-foreground-subtle\">{status.charging}</span>\n )}\n </span>\n )\n}\n","/**\n * Status indicator dot — green online, yellow disabled, red offline.\n * Pure-render atom; no fetches, no internal state.\n */\nimport type { ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface StatusDotProps {\n readonly status: 'online' | 'offline' | 'disabled'\n}\n\nexport function StatusDot({ status }: StatusDotProps): ReactNode {\n const cls =\n status === 'disabled' ? 'bg-warning'\n : status === 'online' ? 'bg-success'\n : 'bg-danger'\n const title =\n status === 'disabled' ? 'Disabled'\n : status === 'online' ? 'Online'\n : 'Offline'\n return (\n <span\n className={cn('h-1.5 w-1.5 rounded-full flex-shrink-0', cls)}\n title={title}\n />\n )\n}\n","/**\n * <DeviceList> — paginated, filterable, view-toggleable device list.\n *\n * Composes:\n * - useDeviceListUrlState (URL+LS hybrid)\n * - groupTopLevelAndAccessories (top-level vs accessory split)\n * - <Pagination>, <FilterChips>, <DeviceListEmptyState>\n * - <DeviceItem view={view}> per row\n *\n * Realtime: per-page useEventInvalidation calls remain authoritative for\n * Phase 2. Lifting the sync into ui-library would require a context bridge\n * that's out of scope.\n *\n * Search: debounced 300 ms before pushing to URL state. Auto-expands\n * parent rows when search matches an accessory.\n */\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { Search } from 'lucide-react'\nimport { useDebouncedString } from '../../hooks/use-debounced-string'\nimport type { UseDeviceProxyTrpc } from '../../hooks/use-device-proxy'\nimport { DeviceItem } from '../device-item'\nimport type { DeviceItemDevice, DeviceItemParent } from '../device-item/helpers'\nimport { groupTopLevelAndAccessories } from './group'\nimport { Pagination } from './pagination'\nimport { FilterChips } from './filter-chips'\nimport { DeviceListEmptyState } from './empty-state'\nimport { useDeviceListUrlState, type DeviceListView } from './url-state'\n\nexport interface DeviceListAddonOption {\n readonly id: string\n readonly name: string\n readonly icon?: ReactNode\n}\n\nexport interface DeviceListProps {\n readonly devices: readonly DeviceItemDevice[]\n readonly trpc: UseDeviceProxyTrpc\n readonly defaultView?: DeviceListView\n readonly filters?: {\n readonly types?: readonly string[]\n readonly addons?: readonly DeviceListAddonOption[]\n }\n /** Pre-applied addon filter — hides the addon-chip group. */\n readonly forceAddon?: string\n readonly resolveIntegrationIcon?: (addonId: string) => ReactNode | null\n readonly resolveParent?: (parentId: number) => DeviceItemParent | null\n readonly onNavigate?: (deviceId: number) => void\n readonly pageSize?: { readonly cards: number; readonly table: number }\n readonly urlScope?: 'root' | 'nested'\n /** LocalStorage key prefix. Default 'devices' for root scope, 'integrations:nested' for nested. */\n readonly lsKey?: string\n}\n\nconst DEFAULT_PAGE_SIZE = { cards: 24, table: 50 }\n\nexport function DeviceList(props: DeviceListProps): ReactNode {\n const {\n devices,\n trpc,\n defaultView = 'table',\n filters,\n forceAddon,\n resolveIntegrationIcon,\n resolveParent,\n onNavigate,\n pageSize = DEFAULT_PAGE_SIZE,\n urlScope = 'root',\n lsKey = urlScope === 'root' ? 'devices' : 'integrations:nested',\n } = props\n\n const url = useDeviceListUrlState({ scope: urlScope, defaultView, lsKey })\n const view = url.state.view\n const currentPageSize = view === 'cards' ? pageSize.cards : pageSize.table\n\n const [searchInput, setSearchInput] = useState(url.state.q)\n const debouncedSearch = useDebouncedString(searchInput, 300)\n // Intentionally only depend on `debouncedSearch` — re-firing on every\n // url.state.q change would create a write-loop (effect writes setQ →\n // state changes → effect fires).\n useEffect(() => {\n if (debouncedSearch !== url.state.q) url.setQ(debouncedSearch)\n }, [debouncedSearch])\n\n const effectiveAddon = forceAddon ?? url.state.addon\n const filtered = useMemo(() => {\n const q = url.state.q.toLowerCase().trim()\n return devices.filter((d) => {\n if (effectiveAddon && d.addonId !== effectiveAddon) return false\n if (url.state.type && d.type !== url.state.type) return false\n if (q && !d.name.toLowerCase().includes(q) && !d.stableId.toLowerCase().includes(q)) {\n return false\n }\n return true\n })\n }, [devices, effectiveAddon, url.state.type, url.state.q])\n\n const grouped = useMemo(() => groupTopLevelAndAccessories(filtered), [filtered])\n\n const autoExpandedParents = useMemo<ReadonlySet<number>>(() => {\n if (url.state.q.trim() === '') return new Set()\n const q = url.state.q.toLowerCase().trim()\n const matching = new Set<number>()\n for (const [parentId, accessories] of grouped.accessoriesByParent.entries()) {\n if (accessories.some((a) =>\n a.name.toLowerCase().includes(q) || a.stableId.toLowerCase().includes(q),\n )) {\n matching.add(parentId)\n }\n }\n return matching\n }, [grouped.accessoriesByParent, url.state.q])\n\n const totalItems = grouped.topLevel.length\n const totalPages = Math.max(1, Math.ceil(totalItems / currentPageSize))\n const safePage = Math.min(url.state.page, totalPages)\n const startIdx = (safePage - 1) * currentPageSize\n const pageRows = grouped.topLevel.slice(startIdx, startIdx + currentPageSize)\n\n // Same intent as the search effect above — only fire on safePage\n // changes; depending on url.state.page or url.setPage would create\n // a write loop.\n useEffect(() => {\n if (safePage !== url.state.page) url.setPage(safePage)\n }, [safePage])\n\n useDeviceListRealtimeSync()\n\n const isFiltered = (effectiveAddon !== null && effectiveAddon !== undefined)\n || url.state.type !== null\n || url.state.q !== ''\n const isEmpty = totalItems === 0\n\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-between gap-3 flex-wrap\">\n <FilterChips\n view={view}\n onViewChange={url.setView}\n types={filters?.types}\n currentType={url.state.type}\n onTypeChange={url.setType}\n addons={filters?.addons}\n currentAddon={url.state.addon}\n onAddonChange={url.setAddon}\n hideAddons={forceAddon !== undefined}\n />\n <div className=\"relative\">\n <Search className=\"absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-foreground-subtle pointer-events-none\" />\n <input\n type=\"text\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n placeholder=\"Search by name or stableId\"\n aria-label=\"Search devices by name or stableId\"\n className=\"h-7 pl-7 pr-2.5 rounded-md border border-border bg-surface text-[11px] text-foreground placeholder:text-foreground-subtle/60 focus:outline-none focus:ring-1 focus:ring-primary/40 w-56\"\n />\n </div>\n </div>\n\n {isEmpty ? (\n <DeviceListEmptyState\n variant={isFiltered ? 'filtered' : 'nofilter'}\n onClearFilters={isFiltered ? url.clearFilters : undefined}\n />\n ) : view === 'cards' ? (\n <CardsLayout\n rows={pageRows}\n accessoriesByParent={grouped.accessoriesByParent}\n trpc={trpc}\n resolveIntegrationIcon={resolveIntegrationIcon ?? null}\n resolveParent={resolveParent ?? null}\n onNavigate={onNavigate ?? null}\n />\n ) : (\n <TableLayout\n rows={pageRows}\n accessoriesByParent={grouped.accessoriesByParent}\n autoExpandedParents={autoExpandedParents}\n // Pass the FILTERED list, not the unfiltered `devices` prop:\n // the indent computation looks up parent.type to flag adopted\n // rows. If the parent is filtered out (e.g. user picks\n // type='camera' and the Home hub disappears), we don't want\n // the orphaned child to keep its indent — the visual cue is\n // meaningful only when the parent is also visible.\n devices={filtered}\n trpc={trpc}\n resolveIntegrationIcon={resolveIntegrationIcon ?? null}\n resolveParent={resolveParent ?? null}\n onNavigate={onNavigate ?? null}\n />\n )}\n\n <Pagination\n currentPage={safePage}\n totalItems={totalItems}\n pageSize={currentPageSize}\n onPageChange={url.setPage}\n />\n\n {/* Footer hidden in nested mode (forceAddon = expanded inside a\n * parent table) — the surrounding context already names the\n * integration, so the \"filtered by X\" line is redundant. Pagination\n * is the only useful overall affordance there, and it lives above. */}\n {forceAddon === undefined && isFiltered && totalItems > 0 && (\n <p className=\"text-[11px] text-foreground-subtle\">\n Showing {totalItems} of {devices.length} devices\n {effectiveAddon && (\n <>\n {' '}· filtered by{' '}\n <strong className=\"text-primary\">\n {filters?.addons?.find((a) => a.id === effectiveAddon)?.name ?? effectiveAddon}\n </strong>\n </>\n )}\n </p>\n )}\n </div>\n )\n}\n\ninterface CardsLayoutProps {\n readonly rows: readonly DeviceItemDevice[]\n readonly accessoriesByParent: ReadonlyMap<number, readonly DeviceItemDevice[]>\n readonly trpc: UseDeviceProxyTrpc\n readonly resolveIntegrationIcon: ((addonId: string) => ReactNode | null) | null\n readonly resolveParent: ((parentId: number) => DeviceItemParent | null) | null\n readonly onNavigate: ((deviceId: number) => void) | null\n}\n\ninterface TableLayoutProps extends CardsLayoutProps {\n readonly autoExpandedParents: ReadonlySet<number>\n /** Full unfiltered device list — used to resolve parent.type for the\n * adopted-row indent. We can't rely on `resolveParent` returning the\n * parent's type (callers historically only project id+name). */\n readonly devices: readonly DeviceItemDevice[]\n}\n\nfunction CardsLayout({\n rows, accessoriesByParent,\n trpc, resolveIntegrationIcon, resolveParent, onNavigate,\n}: CardsLayoutProps): ReactNode {\n return (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {rows.map((d) => {\n const accessories = accessoriesByParent.get(d.id) ?? []\n return (\n <DeviceItem\n key={d.id}\n trpc={trpc}\n device={d}\n view=\"card\"\n integrationIcon={resolveIntegrationIcon?.(d.addonId) ?? null}\n parent={d.parentDeviceId !== null ? (resolveParent?.(d.parentDeviceId) ?? null) : null}\n children={accessories}\n onNavigate={onNavigate ?? undefined}\n />\n )\n })}\n </div>\n )\n}\n\n// Indent levels for the table-view first cell:\n// 0 → top-level (parentDeviceId null)\n// 1 → adopted under a hub/nvr (parent.type ∈ {hub, nvr}) — visual\n// hierarchy hint so operators see the parent-child relationship\n// without relying solely on the \"Under: <parent>\" badge\n// 2 → accessory under any parent (handled by `isAccessoryRow` →\n// index.tsx maps to indentLevel 2)\nconst HUB_LIKE_PARENT_TYPES: ReadonlySet<string> = new Set(['hub', 'nvr'])\n\nfunction topLevelIndentLevel(\n device: DeviceItemDevice,\n parentType: string | null,\n): 0 | 1 {\n if (device.parentDeviceId === null || parentType === null) return 0\n if (HUB_LIKE_PARENT_TYPES.has(parentType.toLowerCase())) return 1\n return 0\n}\n\nfunction TableLayout({\n rows, accessoriesByParent, autoExpandedParents, devices,\n trpc, resolveIntegrationIcon, resolveParent, onNavigate,\n}: TableLayoutProps): ReactNode {\n // Local index for parent.type lookup. The injected `resolveParent`\n // historically only projects {id, name}; cheaper to walk our own\n // `devices` list once than to widen every caller's signature.\n const parentTypeById = useMemo(() => {\n const m = new Map<number, string>()\n for (const d of devices) m.set(d.id, d.type)\n return m\n }, [devices])\n return (\n <div className=\"rounded-lg border border-border bg-surface overflow-hidden\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"border-b border-border\">\n <th className=\"text-left px-2 py-2 text-[9.5px] font-medium uppercase tracking-wider text-foreground-subtle\">Name</th>\n <th className=\"text-left px-2 py-2 text-[9.5px] font-medium uppercase tracking-wider text-foreground-subtle w-24\">Type</th>\n <th className=\"text-left px-2 py-2 text-[9.5px] font-medium uppercase tracking-wider text-foreground-subtle w-32\">Features</th>\n <th className=\"text-left px-2 py-2 text-[9.5px] font-medium uppercase tracking-wider text-foreground-subtle w-20\">Preview</th>\n <th className=\"text-right px-2 py-2 text-[9.5px] font-medium uppercase tracking-wider text-foreground-subtle w-32\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((d) => {\n const accessories = accessoriesByParent.get(d.id) ?? []\n const hasAccessories = accessories.length > 0\n const autoExpand = autoExpandedParents.has(d.id)\n const parentRowParent = d.parentDeviceId !== null\n ? (resolveParent?.(d.parentDeviceId) ?? null)\n : null\n const parentType = d.parentDeviceId !== null\n ? (parentTypeById.get(d.parentDeviceId) ?? null)\n : null\n return (\n <TableRowGroup\n key={d.id}\n parent={d}\n accessories={accessories}\n hasAccessories={hasAccessories}\n forceExpanded={autoExpand}\n trpc={trpc}\n integrationIcon={resolveIntegrationIcon?.(d.addonId) ?? null}\n parentRowParent={parentRowParent}\n indentLevel={topLevelIndentLevel(d, parentType)}\n onNavigate={onNavigate ?? null}\n />\n )\n })}\n </tbody>\n </table>\n </div>\n )\n}\n\ninterface TableRowGroupProps {\n readonly parent: DeviceItemDevice\n readonly accessories: readonly DeviceItemDevice[]\n readonly hasAccessories: boolean\n readonly forceExpanded: boolean\n readonly trpc: UseDeviceProxyTrpc\n readonly integrationIcon: ReactNode | null\n readonly parentRowParent: DeviceItemParent | null\n readonly indentLevel: 0 | 1\n readonly onNavigate: ((id: number) => void) | null\n}\n\nfunction TableRowGroup({\n parent, accessories, hasAccessories, forceExpanded,\n trpc, integrationIcon, parentRowParent, indentLevel, onNavigate,\n}: TableRowGroupProps): ReactNode {\n // Lift expand state here so the parent's chevron click drives the\n // accessory <tr> rendering BELOW. Previously the chevron flipped\n // DeviceItem-internal state that TableRowGroup never observed.\n //\n // Seed from `forceExpanded` (search auto-expand): when search opens\n // a parent, the local state follows. We track the previous forceValue\n // in a ref so we only push the seed on a flip, not on every render —\n // otherwise toggling search ON would lock the row open.\n const [expanded, setExpanded] = useState(forceExpanded)\n const prevForce = useRef(forceExpanded)\n useEffect(() => {\n if (prevForce.current !== forceExpanded) {\n setExpanded(forceExpanded)\n prevForce.current = forceExpanded\n }\n }, [forceExpanded])\n\n const onToggleExpand = (): void => setExpanded((v) => !v)\n const showAccessoryRows = hasAccessories && expanded\n\n return (\n <>\n <DeviceItem\n trpc={trpc}\n device={parent}\n view=\"table\"\n integrationIcon={integrationIcon}\n parent={parentRowParent}\n children={accessories}\n onNavigate={onNavigate ?? undefined}\n showChildrenAccordion={hasAccessories}\n expanded={expanded}\n onToggleExpand={onToggleExpand}\n indentLevel={indentLevel}\n />\n {showAccessoryRows && accessories.map((a) => (\n <DeviceItem\n key={a.id}\n trpc={trpc}\n device={a}\n view=\"table\"\n integrationIcon={null}\n parent={null}\n isAccessoryRow\n showChildrenAccordion={false}\n onNavigate={onNavigate ?? undefined}\n />\n ))}\n </>\n )\n}\n\nfunction useDeviceListRealtimeSync(): void {\n // TODO(post-phase-2): lift the realtime sync into ui-library once a\n // context bridge for the admin-ui-specific BackendClient exists.\n // Today, per-page useEventInvalidation calls in admin-ui (Devices.tsx\n // + Integrations.tsx) remain authoritative; this stub only enforces\n // that consumers have a QueryClient ancestor.\n useQueryClient()\n}\n","/**\n * useDebouncedString — return `value` after `delay` ms have passed\n * without further changes. Resets the timer on every change.\n *\n * Useful for search inputs that should NOT push to URL state on every\n * keystroke. The DOM input stays controlled by an external `value`\n * (caller's `useState`); this hook produces a debounced derivation.\n */\nimport { useEffect, useState } from 'react'\n\nexport function useDebouncedString(value: string, delayMs: number): string {\n const [debounced, setDebounced] = useState(value)\n useEffect(() => {\n const t = setTimeout(() => setDebounced(value), delayMs)\n return () => clearTimeout(t)\n }, [value, delayMs])\n return debounced\n}\n","/**\n * groupTopLevelAndAccessories — pure splitter for the DeviceList\n * row pipeline.\n *\n * Classification:\n * - Top-level rows: standalone devices (`parentDeviceId === null`)\n * plus adopted devices whose parent is a hub or NVR (e.g. cameras\n * under a `Home hub`). Adopted devices keep their parent badge but\n * render as primary rows + paginate.\n * - Accessories: devices whose parent is a CAMERA (or any non-\n * hub/nvr type). Render nested under the parent's chevron.\n *\n * Why parent-type and not the device's own `role`: the wire response\n * from `deviceManager.listAll` ships `role: null` even for siren /\n * floodlight / pir-sensor children — `device.role` is currently only\n * populated on the in-memory `IDevice` instance and is dropped during\n * `toDeviceInfo()` projection. Using parent-type gives the same answer\n * without depending on a field that's empty in practice. As a defensive\n * fallback we ALSO treat any row with a non-null `role` as an accessory\n * so a future wire fix doesn't accidentally re-flatten the table.\n *\n * - Orphan accessories (parentDeviceId references a device not in\n * the input list) fall through to topLevel — better to show them\n * once with a stale parent badge than hide them entirely.\n *\n * Pure: no side effects, no React; testable as a unit.\n */\nimport type { DeviceItemDevice } from '../device-item/helpers'\n\nexport interface GroupedDevices {\n readonly topLevel: readonly DeviceItemDevice[]\n readonly accessoriesByParent: ReadonlyMap<number, readonly DeviceItemDevice[]>\n}\n\nconst PARENT_AS_OWNER_TYPES: ReadonlySet<string> = new Set(['hub', 'nvr'])\n\nexport function groupTopLevelAndAccessories(\n devices: readonly DeviceItemDevice[],\n): GroupedDevices {\n const byId = new Map<number, DeviceItemDevice>()\n for (const d of devices) byId.set(d.id, d)\n const topLevel: DeviceItemDevice[] = []\n const accessoriesByParent = new Map<number, DeviceItemDevice[]>()\n\n for (const d of devices) {\n const parentId = d.parentDeviceId\n if (parentId === null || parentId === undefined) {\n topLevel.push(d)\n continue\n }\n const parent = byId.get(parentId)\n if (!parent) {\n // Orphan — parent missing from the input list. Show at top-level\n // so the operator at least sees the device.\n topLevel.push(d)\n continue\n }\n // Adopted: parent is a hub/NVR and the child has no role override.\n // Cameras adopted by a `Home hub` keep their primary-row treatment.\n const hasRole = d.role !== null && d.role !== undefined\n const parentIsOwner = PARENT_AS_OWNER_TYPES.has(parent.type)\n if (parentIsOwner && !hasRole) {\n topLevel.push(d)\n continue\n }\n // Otherwise: accessory of a camera (or other non-hub parent). Group\n // under the parent so the table renders it as a nested row.\n const list = accessoriesByParent.get(parentId)\n if (list) list.push(d)\n else accessoriesByParent.set(parentId, [d])\n }\n\n return { topLevel, accessoriesByParent }\n}\n","/**\n * <Pagination> — numbered-pages-with-ellipsis control.\n *\n * Layout: Showing 51–100 of 312 devices [<] 1 … 3 4 [5] 6 7 … 28 [>]\n *\n * Returns `null` when totalItems <= pageSize (single page — no nav).\n */\nimport { type ReactNode } from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { cn } from '../../lib/cn'\n\nexport interface PaginationProps {\n readonly currentPage: number // 1-indexed\n readonly totalItems: number\n readonly pageSize: number\n readonly onPageChange: (page: number) => void\n /** Singular noun for the showing-info label. Default `'devices'`. */\n readonly itemNoun?: string\n}\n\nexport type PageButton =\n | { readonly kind: 'page'; readonly n: number }\n | { readonly kind: 'ellipsis'; readonly side: 'left' | 'right' }\n\nconst NEIGHBORS = 2 // pages either side of current\n\nexport function computePageButtons(currentPage: number, totalPages: number): readonly PageButton[] {\n if (totalPages <= 1) return [{ kind: 'page', n: 1 }]\n if (totalPages <= 7) {\n const all: PageButton[] = []\n for (let i = 1; i <= totalPages; i++) all.push({ kind: 'page', n: i })\n return all\n }\n const result: PageButton[] = []\n const leftBound = Math.max(2, currentPage - NEIGHBORS)\n const rightBound = Math.min(totalPages - 1, currentPage + NEIGHBORS)\n\n result.push({ kind: 'page', n: 1 })\n if (leftBound > 2) result.push({ kind: 'ellipsis', side: 'left' })\n for (let i = leftBound; i <= rightBound; i++) result.push({ kind: 'page', n: i })\n if (rightBound < totalPages - 1) result.push({ kind: 'ellipsis', side: 'right' })\n result.push({ kind: 'page', n: totalPages })\n return result\n}\n\nexport function Pagination({\n currentPage,\n totalItems,\n pageSize,\n onPageChange,\n itemNoun = 'devices',\n}: PaginationProps): ReactNode {\n if (totalItems <= pageSize) return null\n\n const totalPages = Math.ceil(totalItems / pageSize)\n const startIdx = (currentPage - 1) * pageSize + 1\n const endIdx = Math.min(currentPage * pageSize, totalItems)\n const buttons = computePageButtons(currentPage, totalPages)\n\n return (\n <div className=\"flex items-center justify-between gap-4 flex-wrap pt-2 text-[11px] text-foreground-subtle\">\n <span>\n Showing {startIdx}–{endIdx} of {totalItems} {itemNoun}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n disabled={currentPage === 1}\n onClick={() => onPageChange(currentPage - 1)}\n className={cn(\n 'inline-flex items-center justify-center h-7 w-7 rounded border border-border bg-surface text-foreground-subtle',\n 'hover:text-foreground hover:bg-surface-hover transition-colors',\n 'disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-surface',\n )}\n >\n <ChevronLeft className=\"h-3 w-3\" />\n </button>\n {buttons.map((b, i) => {\n if (b.kind === 'ellipsis') {\n return <span key={`e-${i}`} className=\"px-1 text-foreground-subtle/60 select-none\">…</span>\n }\n const active = b.n === currentPage\n return (\n <button\n key={`p-${b.n}`}\n type=\"button\"\n onClick={() => onPageChange(b.n)}\n className={cn(\n 'inline-flex items-center justify-center h-7 min-w-7 px-1.5 rounded border text-[10.5px] font-medium transition-colors',\n active\n ? 'border-primary/40 bg-primary/10 text-primary'\n : 'border-border bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n )}\n >\n {b.n}\n </button>\n )\n })}\n <button\n type=\"button\"\n aria-label=\"Next page\"\n disabled={currentPage === totalPages}\n onClick={() => onPageChange(currentPage + 1)}\n className={cn(\n 'inline-flex items-center justify-center h-7 w-7 rounded border border-border bg-surface text-foreground-subtle',\n 'hover:text-foreground hover:bg-surface-hover transition-colors',\n 'disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-surface',\n )}\n >\n <ChevronRight className=\"h-3 w-3\" />\n </button>\n </span>\n </div>\n )\n}\n","/**\n * <FilterChips> — top-row filter UI for DeviceList.\n *\n * Layout: [View toggle] [Type chips] [Integration chips] (search input\n * lives separately; this component only handles chip-style selectors).\n *\n * All three groups are radio-like: clicking an active chip clears\n * (sets state to null). Addon chips show an X icon when active so\n * the operator sees the clear affordance up-front.\n */\nimport { type ReactNode } from 'react'\nimport { LayoutGrid, Table2, X } from 'lucide-react'\nimport { cn } from '../../lib/cn'\nimport type { DeviceListView } from './url-state'\n\nexport interface FilterChipsProps {\n readonly view: DeviceListView\n readonly onViewChange: (view: DeviceListView) => void\n readonly types?: readonly string[]\n readonly currentType: string | null\n readonly onTypeChange: (type: string | null) => void\n readonly addons?: readonly { readonly id: string; readonly name: string; readonly icon?: ReactNode }[]\n readonly currentAddon: string | null\n readonly onAddonChange: (addon: string | null) => void\n /** When true, the addon group is hidden (used by Integrations expand-row inner DeviceList). */\n readonly hideAddons?: boolean\n}\n\nexport function FilterChips({\n view, onViewChange,\n types, currentType, onTypeChange,\n addons, currentAddon, onAddonChange,\n hideAddons = false,\n}: FilterChipsProps): ReactNode {\n return (\n <div className=\"flex items-center gap-2 flex-wrap\">\n {/* View toggle */}\n <span className=\"inline-flex border border-border rounded-md overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => onViewChange('cards')}\n className={cn(\n 'inline-flex items-center justify-center h-7 w-8 transition-colors',\n view === 'cards'\n ? 'bg-primary/10 text-primary'\n : 'bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n )}\n aria-label=\"Cards view\"\n >\n <LayoutGrid className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onViewChange('table')}\n className={cn(\n 'inline-flex items-center justify-center h-7 w-8 border-l border-border transition-colors',\n view === 'table'\n ? 'bg-primary/10 text-primary'\n : 'bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n )}\n aria-label=\"Table view\"\n >\n <Table2 className=\"h-3.5 w-3.5\" />\n </button>\n </span>\n\n {/* Type chips */}\n {types && types.length > 0 && (\n <>\n <ChipLabel>Type</ChipLabel>\n <Chip\n active={currentType === null}\n onClick={() => onTypeChange(null)}\n >\n All\n </Chip>\n {types.map((t) => (\n <Chip\n key={t}\n active={currentType === t}\n onClick={() => onTypeChange(currentType === t ? null : t)}\n >\n {capitalize(t)}\n </Chip>\n ))}\n </>\n )}\n\n {/* Integration chips */}\n {!hideAddons && addons && addons.length > 0 && (\n <>\n <ChipLabel>Integration</ChipLabel>\n {addons.map((a) => (\n <Chip\n key={a.id}\n active={currentAddon === a.id}\n icon={a.icon}\n onClick={() => onAddonChange(currentAddon === a.id ? null : a.id)}\n showClearIcon={currentAddon === a.id}\n >\n {a.name}\n </Chip>\n ))}\n </>\n )}\n </div>\n )\n}\n\ninterface ChipLabelProps {\n readonly children: ReactNode\n}\n\nfunction ChipLabel({ children }: ChipLabelProps): ReactNode {\n return (\n <span className=\"text-[10px] font-medium uppercase tracking-wider text-foreground-subtle ml-1\">\n {children}\n </span>\n )\n}\n\ninterface ChipProps {\n readonly active: boolean\n readonly icon?: ReactNode\n readonly onClick: () => void\n readonly showClearIcon?: boolean\n readonly children: ReactNode\n}\n\nfunction Chip({ active, icon, onClick, showClearIcon, children }: ChipProps): ReactNode {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'inline-flex items-center gap-1.5 h-7 px-2.5 rounded-full border text-[10.5px] font-medium transition-colors',\n active\n ? 'border-primary/40 bg-primary/15 text-primary'\n : 'border-border bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n )}\n >\n {icon && <span className=\"inline-flex items-center\">{icon}</span>}\n <span>{children}</span>\n {active && showClearIcon && <X className=\"h-2.5 w-2.5 opacity-70\" />}\n </button>\n )\n}\n\nfunction capitalize(s: string): string {\n return s.length === 0 ? s : s[0]!.toUpperCase() + s.slice(1)\n}\n","/**\n * <DeviceListEmptyState> — shown when the filtered device list is empty.\n *\n * Two variants:\n * - `nofilter` — list is empty AND no filters applied. Operator\n * hasn't added any devices yet (or the addon hasn't discovered any).\n * - `filtered` — filters are applied but match nothing. Offer a\n * reset link to clear filters.\n */\nimport { type ReactNode } from 'react'\nimport { Inbox } from 'lucide-react'\n\nexport interface EmptyStateProps {\n readonly variant: 'nofilter' | 'filtered'\n readonly onClearFilters?: () => void\n}\n\nexport function DeviceListEmptyState({ variant, onClearFilters }: EmptyStateProps): ReactNode {\n return (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <Inbox className=\"h-8 w-8 text-foreground-subtle/40 mb-3\" />\n <p className=\"text-sm font-medium text-foreground-subtle\">\n {variant === 'filtered' ? 'No devices match the current filters' : 'No devices yet'}\n </p>\n {variant === 'filtered' && onClearFilters && (\n <button\n type=\"button\"\n onClick={onClearFilters}\n className=\"mt-2 text-[11px] text-primary hover:underline\"\n >\n Clear filters\n </button>\n )}\n </div>\n )\n}\n","/**\n * useDeviceListUrlState — URL-first hybrid state hook for DeviceList.\n *\n * - Source of truth: the URL query string. Reads on mount + on\n * `popstate` (back/forward navigation). Writes via\n * `history.replaceState` on every setter.\n * - Fallback: `localStorage[<lsKey>:lastFilters]` — JSON object\n * `{view, addon, type, q}` (NEVER page). Used to rehydrate when\n * the URL has no params.\n * - Defaults stripped from URL — when the value is the default AND\n * not pinned by LS, it's removed (URL stays canonical).\n *\n * Two scopes:\n * - 'root' — uses `view`, `page`, `addon`, `type`, `q`\n * - 'nested' — uses `deviceView`, `devicePage`, `deviceType`,\n * `deviceQ` (no `deviceAddon` — outer ?expand= locks it). Used\n * by Integrations page expanded row.\n *\n * Page reset rule: changing addon / type / q resets page to 1.\n * `clearFilters` clears addon / type / q; preserves view.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport type DeviceListView = 'cards' | 'table'\n\nexport interface DeviceListUrlState {\n readonly view: DeviceListView\n readonly page: number\n readonly addon: string | null\n readonly type: string | null\n readonly q: string\n}\n\nexport interface UseDeviceListUrlStateOptions {\n readonly scope: 'root' | 'nested'\n readonly defaultView: DeviceListView\n /** LocalStorage key prefix, e.g. `'devices'` → `camstack:devices:lastFilters`. */\n readonly lsKey: string\n}\n\nexport interface UseDeviceListUrlStateResult {\n readonly state: DeviceListUrlState\n readonly setView: (view: DeviceListView) => void\n readonly setPage: (page: number) => void\n readonly setAddon: (addon: string | null) => void\n readonly setType: (type: string | null) => void\n readonly setQ: (q: string) => void\n readonly clearFilters: () => void\n}\n\ninterface PersistedFilters {\n readonly view?: DeviceListView\n readonly addon?: string | null\n readonly type?: string | null\n readonly q?: string\n}\n\nfunction paramKey(scope: 'root' | 'nested', base: keyof DeviceListUrlState): string {\n if (scope === 'root') return base\n switch (base) {\n case 'view': return 'deviceView'\n case 'page': return 'devicePage'\n case 'type': return 'deviceType'\n case 'q': return 'deviceQ'\n case 'addon': return 'deviceAddon' // unused in practice — caller locks it\n }\n}\n\nfunction readFromLS(lsKey: string): PersistedFilters {\n try {\n const raw = localStorage.getItem(`camstack:${lsKey}:lastFilters`)\n if (!raw) return {}\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== 'object' || parsed === null) return {}\n return parsed as PersistedFilters\n } catch {\n return {}\n }\n}\n\nfunction writeToLS(lsKey: string, filters: PersistedFilters): void {\n try {\n localStorage.setItem(`camstack:${lsKey}:lastFilters`, JSON.stringify(filters))\n } catch { /* ignore quota */ }\n}\n\nfunction readUrlState(scope: 'root' | 'nested', defaultView: DeviceListView, ls: PersistedFilters): DeviceListUrlState {\n const params = new URLSearchParams(window.location.search)\n\n const rawView = params.get(paramKey(scope, 'view'))\n const view: DeviceListView = rawView === 'cards' || rawView === 'table'\n ? rawView\n : (ls.view ?? defaultView)\n\n const rawPage = params.get(paramKey(scope, 'page'))\n const pageNum = rawPage ? parseInt(rawPage, 10) : 1\n const page = Number.isFinite(pageNum) && pageNum >= 1 ? pageNum : 1\n\n const addon = params.get(paramKey(scope, 'addon')) ?? ls.addon ?? null\n const type = params.get(paramKey(scope, 'type')) ?? ls.type ?? null\n const q = params.get(paramKey(scope, 'q')) ?? ls.q ?? ''\n\n return { view, page, addon, type, q }\n}\n\nfunction writeUrlState(\n scope: 'root' | 'nested',\n next: DeviceListUrlState,\n defaultView: DeviceListView,\n): void {\n const params = new URLSearchParams(window.location.search)\n const set = (k: string, v: string | null) => {\n if (v === null || v === '') params.delete(k)\n else params.set(k, v)\n }\n set(paramKey(scope, 'view'), next.view === defaultView ? null : next.view)\n set(paramKey(scope, 'page'), next.page === 1 ? null : String(next.page))\n set(paramKey(scope, 'addon'), next.addon)\n set(paramKey(scope, 'type'), next.type)\n set(paramKey(scope, 'q'), next.q || null)\n const qs = params.toString()\n const url = qs ? `${window.location.pathname}?${qs}` : window.location.pathname\n window.history.replaceState(null, '', url)\n}\n\nexport function useDeviceListUrlState(\n options: UseDeviceListUrlStateOptions,\n): UseDeviceListUrlStateResult {\n const { scope, defaultView, lsKey } = options\n\n const [state, setState] = useState<DeviceListUrlState>(() => {\n const ls = readFromLS(lsKey)\n return readUrlState(scope, defaultView, ls)\n })\n // Mirror state in a ref so setters batched in a single render cycle\n // see each other's writes (URL is the source of truth, not React state).\n const stateRef = useRef<DeviceListUrlState>(state)\n stateRef.current = state\n\n // Listen for back/forward — popstate updates state from URL.\n useEffect(() => {\n const handler = (): void => {\n const ls = readFromLS(lsKey)\n const next = readUrlState(scope, defaultView, ls)\n stateRef.current = next\n setState(next)\n }\n window.addEventListener('popstate', handler)\n return () => window.removeEventListener('popstate', handler)\n }, [scope, defaultView, lsKey])\n\n const apply = useCallback(\n (mutate: (current: DeviceListUrlState) => DeviceListUrlState) => {\n const next = mutate(stateRef.current)\n stateRef.current = next\n setState(next)\n writeUrlState(scope, next, defaultView)\n writeToLS(lsKey, {\n view: next.view,\n addon: next.addon,\n type: next.type,\n q: next.q,\n })\n },\n [scope, defaultView, lsKey],\n )\n\n const setView = useCallback((view: DeviceListView) => apply((s) => ({ ...s, view })), [apply])\n const setPage = useCallback((page: number) => apply((s) => ({ ...s, page })), [apply])\n const setAddon = useCallback(\n (addon: string | null) => apply((s) => ({ ...s, addon, page: 1 })),\n [apply],\n )\n const setType = useCallback(\n (type: string | null) => apply((s) => ({ ...s, type, page: 1 })),\n [apply],\n )\n const setQ = useCallback((q: string) => apply((s) => ({ ...s, q, page: 1 })), [apply])\n const clearFilters = useCallback(\n () => apply((s) => ({ ...s, addon: null, type: null, q: '', page: 1 })),\n [apply],\n )\n\n return { state, setView, setPage, setAddon, setType, setQ, clearFilters }\n}\n","import { Cpu, Star } from 'lucide-react'\n\nexport interface PipelineRuntimeOption {\n readonly id: string\n readonly label: string\n readonly available: boolean\n /** Platform score for this backend (higher = better) */\n readonly platformScore?: number\n /** Whether this is the best-scored backend */\n readonly isBest?: boolean\n}\n\ninterface PipelineRuntimeSelectorProps {\n readonly options: readonly PipelineRuntimeOption[]\n readonly value: string\n readonly onChange: (value: string) => void\n}\n\nexport function PipelineRuntimeSelector({ options, value, onChange }: PipelineRuntimeSelectorProps) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {options.map((opt) => {\n const active = opt.id === value\n return (\n <button\n key={opt.id}\n onClick={() => opt.available && onChange(opt.id)}\n disabled={!opt.available}\n className={`flex items-center gap-2 rounded-lg border px-3 py-2 text-xs font-medium transition-all ${\n active\n ? 'border-primary/40 bg-primary/10 text-primary'\n : opt.available\n ? 'border-border bg-surface text-foreground-subtle hover:bg-surface-hover hover:text-foreground'\n : 'border-border/40 bg-surface/40 text-foreground-subtle/40 cursor-not-allowed'\n }`}\n >\n <Cpu className=\"h-3.5 w-3.5 shrink-0\" />\n {opt.label}\n {opt.isBest && (\n <span className=\"inline-flex items-center gap-0.5 rounded-full bg-amber-500/15 px-1.5 py-0.5 text-[10px] font-semibold text-amber-400\">\n <Star className=\"h-2.5 w-2.5\" />\n Best\n </span>\n )}\n {opt.platformScore != null && (\n <span className=\"text-[10px] text-foreground-subtle/60\">({opt.platformScore})</span>\n )}\n <span\n className={`h-1.5 w-1.5 rounded-full ${\n opt.available ? 'bg-success' : 'bg-danger'\n }`}\n />\n </button>\n )\n })}\n </div>\n )\n}\n","/**\n * PipelineBuilder — orchestrates the pipeline step tree with template management.\n *\n * Renders: template bar (save/load/delete), step tree from schema with nested\n * children, placeholder steps for disabled addons, all driven by API schema.\n */\nimport { useMemo, useState } from 'react'\nimport { Save, CopyPlus, Trash2, PlusCircle, X } from 'lucide-react'\nimport type {\n PipelineSchema,\n PipelineTemplate,\n PipelineAddonSchema,\n} from '@camstack/types'\nimport { cn } from '../lib/cn'\nimport { validateTemplate } from '../lib/validate-template'\nimport { PipelineStep } from './pipeline-step'\nimport type { PipelineStepDisplayConfig } from './pipeline-step'\n\n// ---------------------------------------------------------------------------\n// Public interface\n// ---------------------------------------------------------------------------\n\nexport interface PipelineBuilderProps {\n readonly schema: PipelineSchema\n readonly steps: readonly PipelineStepDisplayConfig[]\n readonly onChange: (steps: readonly PipelineStepDisplayConfig[]) => void\n readonly templates: readonly PipelineTemplate[]\n readonly selectedTemplateId: string | null\n readonly onSelectTemplate: (id: string | null) => void\n readonly onSaveTemplate: (name: string, steps: readonly PipelineStepDisplayConfig[]) => void\n readonly onUpdateTemplate: (id: string, steps: readonly PipelineStepDisplayConfig[]) => void\n readonly onDeleteTemplate: (id: string) => void\n readonly readOnly?: boolean\n /** Addon IDs to exclude from the pipeline (e.g. 'motion-detection' for benchmark) */\n readonly excludeAddons?: readonly string[]\n /** Hide the template bar (save/load/delete) */\n readonly hideTemplates?: boolean\n /** Only show enabled steps (hide disabled addons and placeholders) */\n readonly showOnlyEnabled?: boolean\n /** Show \"Slot: ...\" labels above step groups (default: false) */\n readonly showSlotLabels?: boolean\n /**\n * Toggle mode passed through to every `PipelineStep`:\n * - `'simple'` (default) — single on/off switch, edits `step.enabled` directly.\n * - `'threeState'` — segmented `[Inherit | On | Off]` control that emits\n * override changes via `onOverrideChange` (per addonId). `step.enabled`\n * still reflects the effective state (agent default OR override).\n */\n readonly toggleMode?: 'simple' | 'threeState'\n /** Current override map keyed on `addonId` when `toggleMode === 'threeState'`. */\n readonly overrides?: Readonly<Record<string, boolean>>\n /** Fires when the user flips a per-addon 3-state toggle. `null` = inherit. */\n readonly onOverrideChange?: (addonId: string, next: boolean | null) => void\n /** Agent default enabled state per addonId, shown as annotation in `'threeState'` mode. */\n readonly inheritedEnabledByAddon?: Readonly<Record<string, boolean>>\n /**\n * Hide the Model dropdown + dynamic configSchema controls on every\n * step (passes through to `PipelineStep.hideModelAndSettings`). Used\n * on the camera page where these knobs are agent-level.\n */\n readonly hideModelAndSettings?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildSchemaMap(schema: PipelineSchema): Map<string, PipelineAddonSchema> {\n const map = new Map<string, PipelineAddonSchema>()\n for (const slot of schema.slots) {\n for (const addon of slot.addons) {\n map.set(addon.id, addon)\n }\n }\n return map\n}\n\nfunction createDefaultStep(\n addon: PipelineAddonSchema,\n): PipelineStepDisplayConfig {\n return {\n addonId: addon.id,\n addonName: addon.name,\n slot: addon.slot,\n inputClasses: [...addon.inputClasses],\n outputClasses: [...addon.outputClasses],\n enabled: true,\n modelId: addon.defaultModelId,\n children: [],\n // Phase 7: no generic `confidence` field. Per-step thresholds live\n // in `settings` and are initialised by the dynamic `ConfigSchemaField`\n // defaults when the form builder mounts the step's `configSchema`.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Placeholder step — dashed card with plus icon, class I/O tags\n// ---------------------------------------------------------------------------\n\nfunction PlaceholderStep({ addon, onClick }: {\n addon: PipelineAddonSchema\n onClick: () => void\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"w-full rounded-lg border border-dashed border-border/60 px-3 py-2.5 text-left transition-all hover:border-primary/30 hover:bg-surface/60 group\"\n >\n <div className=\"flex items-center gap-3\">\n <PlusCircle className=\"h-[18px] w-[18px] text-foreground-subtle/30 group-hover:text-primary/60 shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <span className=\"text-[13px] font-medium text-foreground-subtle/50 group-hover:text-foreground-subtle block truncate\">\n {addon.name}\n </span>\n <div className=\"flex items-center gap-1 mt-0.5 flex-wrap\">\n {addon.inputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/8 text-blue-400/50\">{c}</span>\n ))}\n {addon.inputClasses.length > 0 && addon.outputClasses.length > 0 && (\n <span className=\"text-foreground-subtle/25 text-[10px]\">→</span>\n )}\n {addon.outputClasses.map(c => (\n <span key={c} className=\"text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/8 text-green-400/50\">{c}</span>\n ))}\n </div>\n </div>\n </div>\n </button>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nexport function PipelineBuilder({\n schema,\n steps,\n onChange,\n templates,\n selectedTemplateId,\n onSelectTemplate,\n onSaveTemplate,\n onUpdateTemplate,\n onDeleteTemplate,\n readOnly = false,\n excludeAddons = [],\n hideTemplates = false,\n showOnlyEnabled = false,\n showSlotLabels = false,\n toggleMode = 'simple',\n overrides = {},\n onOverrideChange,\n inheritedEnabledByAddon = {},\n hideModelAndSettings = false,\n}: PipelineBuilderProps) {\n const stepExtraProps = (addonId: string) => ({\n toggleMode,\n hideModelAndSettings,\n ...(toggleMode === 'threeState' ? {\n overrideState: (overrides[addonId] !== undefined ? overrides[addonId] : null) as boolean | null,\n onOverrideChange: onOverrideChange\n ? (next: boolean | null) => onOverrideChange(addonId, next)\n : undefined,\n inheritedEnabled: inheritedEnabledByAddon[addonId],\n } : {}),\n })\n const excluded = useMemo(() => new Set(excludeAddons), [excludeAddons])\n const schemaMap = useMemo(() => buildSchemaMap(schema), [schema])\n const [warnings, setWarnings] = useState<string[]>([])\n\n // Check unsaved changes\n const dirty = selectedTemplateId\n ? JSON.stringify(steps) !== JSON.stringify(templates.find(t => t.id === selectedTemplateId)?.steps)\n : false\n\n // ── Template handlers ──────────────────────────────────────────\n function handleSelectTemplate(e: React.ChangeEvent<HTMLSelectElement>) {\n const id = e.target.value || null\n if (id) {\n const tpl = templates.find(t => t.id === id)\n if (tpl) {\n const result = validateTemplate(tpl.steps, schema)\n setWarnings([...result.warnings])\n }\n } else {\n setWarnings([])\n }\n onSelectTemplate(id)\n }\n\n function handleSave() {\n if (selectedTemplateId) onUpdateTemplate(selectedTemplateId, steps)\n }\n\n function handleSaveAs() {\n const name = window.prompt('Template name:')\n if (name?.trim()) onSaveTemplate(name.trim(), steps)\n }\n\n function handleDelete() {\n if (!selectedTemplateId) return\n const tpl = templates.find(t => t.id === selectedTemplateId)\n if (tpl && window.confirm(`Delete template \"${tpl.name}\"?`)) {\n onDeleteTemplate(selectedTemplateId)\n }\n }\n\n // ── Step handlers ──────────────────────────────────────────────\n\n /**\n * When a step is updated, auto-enable the entire ancestor chain if a\n * child/grandchild was just enabled. This ensures enabling face-recognition\n * automatically enables face-detection and object-detection.\n */\n function handleStepChange(updated: PipelineStepDisplayConfig) {\n onChange(steps.map(s => {\n if (s.addonId !== updated.addonId) return s\n return autoEnableAncestors(updated)\n }))\n }\n\n /** If any child or grandchild is enabled, ensure the parent is too */\n function autoEnableAncestors(step: PipelineStepDisplayConfig): PipelineStepDisplayConfig {\n const hasEnabledChild = step.children.some(c => c.enabled || c.children.some(gc => gc.enabled))\n return {\n ...step,\n enabled: step.enabled || hasEnabledChild,\n children: step.children.map(c => {\n const hasEnabledGrandchild = c.children.some(gc => gc.enabled)\n return {\n ...c,\n enabled: c.enabled || hasEnabledGrandchild,\n }\n }),\n }\n }\n\n function handleAddChildToStep(parentAddonId: string, addon: PipelineAddonSchema) {\n const child = createDefaultStep(addon)\n onChange(steps.map(s => {\n if (s.addonId !== parentAddonId) return s\n return { ...s, children: [...s.children, child] }\n }))\n }\n\n // ── Rendering ──────────────────────────────────────────────────\n\n // Collect all addon IDs already in the tree (including nested)\n function collectIds(list: readonly PipelineStepDisplayConfig[]): Set<string> {\n const ids = new Set<string>()\n for (const s of list) {\n ids.add(s.addonId)\n for (const c of s.children) ids.add(c.addonId)\n // Recurse deeper\n const childIds = collectIds(s.children)\n for (const id of childIds) ids.add(id)\n }\n return ids\n }\n\n const existingIds = collectIds(steps)\n\n // Get child-slot addons that could be children of a given step\n function getChildPlaceholders(step: PipelineStepDisplayConfig): PipelineAddonSchema[] {\n const stepSchema = schemaMap.get(step.addonId)\n if (!stepSchema) return []\n const parentSlotInfo = schema.slots.find(s => s.id === stepSchema.slot)\n const parentIsRoot = parentSlotInfo?.parentSlot == null\n const childSlotIds = stepSchema.childSlots\n const childIds = new Set(step.children.map(c => c.addonId))\n const placeholders: PipelineAddonSchema[] = []\n for (const slot of schema.slots) {\n if (!childSlotIds.includes(slot.id)) continue\n for (const addon of slot.addons) {\n if (childIds.has(addon.id) || excluded.has(addon.id)) continue\n // A step with an empty `inputClasses` is a \"wildcard\" — its\n // definition used `inputClasses: null` and the schema encodes that\n // as an empty array. These steps (e.g. full-frame segmenters) are\n // only meaningful as direct children of a root-slot step (i.e. a\n // root detector like `object-detection`), so they must not appear\n // as placeholders under croppers or classifiers.\n const isWildcard = addon.inputClasses.length === 0\n if (isWildcard && !parentIsRoot) continue\n const compatible = isWildcard\n || addon.inputClasses.some(ic => step.outputClasses.includes(ic))\n if (compatible) placeholders.push(addon)\n }\n }\n return placeholders\n }\n\n function renderStep(rawStep: PipelineStepDisplayConfig) {\n // When showOnlyEnabled, filter out disabled children recursively\n const step = showOnlyEnabled\n ? { ...rawStep, children: rawStep.children.filter(c => c.enabled).map(c => ({ ...c, children: c.children.filter(gc => gc.enabled) })) }\n : rawStep\n const childPlaceholders = showOnlyEnabled ? [] : getChildPlaceholders(step)\n\n return (\n <div key={step.addonId} className=\"space-y-1.5\">\n <PipelineStep\n step={step}\n schema={schemaMap.get(step.addonId) ?? null}\n allSchemas={schemaMap}\n\n onChange={handleStepChange}\n onDelete={readOnly ? undefined : (id) => onChange(steps.filter(s => s.addonId !== id))}\n readOnly={readOnly}\n {...stepExtraProps(step.addonId)}\n />\n\n {/* Children + child placeholders — nested visually */}\n {(step.children.length > 0 || childPlaceholders.length > 0) && (\n <div className=\"ml-4 pl-3 border-l border-border/60 space-y-1.5\">\n {/* Slot label for children */}\n {showSlotLabels && (\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/40\">\n Slot: Cropper / Classifier\n </span>\n )}\n\n {/* Existing child steps */}\n {step.children.map(child => {\n const childChildPlaceholders = getChildPlaceholders(child)\n return (\n <div key={child.addonId} className=\"space-y-1.5\">\n <PipelineStep\n step={child}\n schema={schemaMap.get(child.addonId) ?? null}\n allSchemas={schemaMap}\n\n depth={1}\n onChange={updated => {\n handleStepChange({\n ...step,\n children: step.children.map(c => c.addonId === updated.addonId ? updated : c),\n })\n }}\n onDelete={readOnly ? undefined : (id) => {\n handleStepChange({\n ...step,\n children: step.children.filter(c => c.addonId !== id),\n })\n }}\n readOnly={readOnly}\n {...stepExtraProps(child.addonId)}\n />\n\n {/* Sub-sub children (recognizers) + placeholders */}\n {(child.children.length > 0 || childChildPlaceholders.length > 0) && (\n <div className=\"ml-4 pl-3 border-l border-border/40 space-y-1.5\">\n {showSlotLabels && (\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/30\">\n Slot: Recognizer\n </span>\n )}\n\n {/* Existing recognizer steps */}\n {child.children.map(grandchild => (\n <PipelineStep\n key={grandchild.addonId}\n step={grandchild}\n schema={schemaMap.get(grandchild.addonId) ?? null}\n allSchemas={schemaMap}\n \n depth={2}\n onChange={updatedGrandchild => {\n handleStepChange({\n ...step,\n children: step.children.map(c =>\n c.addonId === child.addonId\n ? { ...c, children: c.children.map(gc => gc.addonId === updatedGrandchild.addonId ? updatedGrandchild : gc) }\n : c\n ),\n })\n }}\n onDelete={readOnly ? undefined : (id) => {\n handleStepChange({\n ...step,\n children: step.children.map(c =>\n c.addonId === child.addonId\n ? { ...c, children: c.children.filter(gc => gc.addonId !== id) }\n : c\n ),\n })\n }}\n readOnly={readOnly}\n {...stepExtraProps(grandchild.addonId)}\n />\n ))}\n\n {/* Placeholder recognizers */}\n {!readOnly && childChildPlaceholders.map(addon => (\n <PlaceholderStep\n key={addon.id}\n addon={addon}\n onClick={() => {\n const newChild = createDefaultStep(addon)\n handleStepChange({\n ...step,\n children: step.children.map(c =>\n c.addonId === child.addonId\n ? { ...c, children: [...c.children, newChild] }\n : c\n ),\n })\n }}\n />\n ))}\n </div>\n )}\n </div>\n )\n })}\n\n {/* Placeholders for missing child addons */}\n {!readOnly && childPlaceholders.map(addon => (\n <PlaceholderStep\n key={addon.id}\n addon={addon}\n onClick={() => handleAddChildToStep(step.addonId, addon)}\n />\n ))}\n </div>\n )}\n </div>\n )\n }\n\n // Root slots (detectors)\n const rootSlots = schema.slots.filter(s => s.parentSlot === null).sort((a, b) => a.priority - b.priority)\n\n return (\n <div className=\"space-y-4\">\n {/* ── Template bar ────────────────────────────────────────── */}\n {!hideTemplates && <div className=\"rounded-lg border border-border bg-surface p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"relative flex-1 min-w-0\">\n <select\n value={selectedTemplateId ?? ''}\n onChange={handleSelectTemplate}\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary/50\"\n >\n <option value=\"\">No template</option>\n {templates.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}\n </select>\n </div>\n {dirty && <span className=\"h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0\" />}\n <button onClick={handleSave} disabled={!selectedTemplateId || readOnly} title=\"Save\"\n className={cn('p-2 rounded-lg border border-border transition-colors',\n selectedTemplateId && !readOnly ? 'text-foreground-subtle hover:bg-surface-hover' : 'text-foreground-subtle/30 cursor-not-allowed')}>\n <Save className=\"h-4 w-4\" />\n </button>\n <button onClick={handleSaveAs} disabled={readOnly} title=\"Save As\"\n className={cn('p-2 rounded-lg border border-border transition-colors',\n !readOnly ? 'text-foreground-subtle hover:bg-surface-hover' : 'text-foreground-subtle/30 cursor-not-allowed')}>\n <CopyPlus className=\"h-4 w-4\" />\n </button>\n <button onClick={handleDelete} disabled={!selectedTemplateId || readOnly} title=\"Delete\"\n className={cn('p-2 rounded-lg border border-border transition-colors',\n selectedTemplateId && !readOnly ? 'text-foreground-subtle hover:text-danger' : 'text-foreground-subtle/30 cursor-not-allowed')}>\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n }\n\n {/* ── Warnings ────────────────────────────────────────────── */}\n {warnings.length > 0 && (\n <div className=\"rounded-lg border border-amber-500/30 bg-amber-500/5 p-3 text-xs text-amber-400 space-y-1\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-medium\">Template loaded with warnings:</span>\n <button onClick={() => setWarnings([])} className=\"text-amber-400/60 hover:text-amber-400\"><X className=\"h-3.5 w-3.5\" /></button>\n </div>\n {warnings.map((w, i) => <div key={i}>• {w}</div>)}\n </div>\n )}\n\n {/* ── Step tree ───────────────────────────────────────────── */}\n {rootSlots.map(slot => {\n const allSlotSteps = steps.filter(s => s.slot === slot.id && !excluded.has(s.addonId))\n const slotSteps = showOnlyEnabled ? allSlotSteps.filter(s => s.enabled) : allSlotSteps\n const missingRootAddons = showOnlyEnabled ? [] : slot.addons.filter(a => !existingIds.has(a.id) && !excluded.has(a.id))\n\n // Group steps: steps with the same `group` field are rendered under one heading\n const groups = new Map<string, typeof slotSteps[number][]>()\n const ungrouped: typeof slotSteps[number][] = []\n for (const step of slotSteps) {\n if (step.group) {\n if (!groups.has(step.group)) groups.set(step.group, [])\n groups.get(step.group)!.push(step)\n } else {\n ungrouped.push(step)\n }\n }\n\n return (\n <div key={slot.id} className=\"space-y-2\">\n {showSlotLabels && (\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/50\">\n Slot: {slot.label}\n </span>\n )}\n\n {/* Ungrouped steps */}\n {ungrouped.map(step => renderStep(step))}\n\n {/* Grouped steps under shared heading */}\n {[...groups.entries()].map(([groupName, groupSteps]) => (\n <div key={groupName} className=\"space-y-2 rounded-lg border border-border/40 p-2\">\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/50 px-1\">\n {groupName}\n </span>\n {groupSteps.map(step => renderStep(step))}\n </div>\n ))}\n\n {/* Root placeholders (e.g. add another detector) */}\n {!readOnly && missingRootAddons.map(addon => (\n <PlaceholderStep key={addon.id} addon={addon} onClick={() => {\n onChange([...steps, createDefaultStep(addon)])\n }} />\n ))}\n </div>\n )\n })}\n </div>\n )\n}\n","// packages/ui-library/src/lib/validate-template.ts\nimport type { PipelineSchema, PipelineTemplateStep, TemplateValidationResult } from '@camstack/types'\n\nexport function validateTemplate(\n steps: readonly PipelineTemplateStep[],\n schema: PipelineSchema,\n): TemplateValidationResult {\n const availableAddonIds = new Set(\n schema.slots.flatMap(s => s.addons.map(a => a.id))\n )\n const warnings: string[] = []\n\n function validateStep(step: PipelineTemplateStep): PipelineTemplateStep | null {\n if (!availableAddonIds.has(step.addonId)) {\n warnings.push(`Addon \"${step.addonId}\" is no longer available — step removed`)\n return null\n }\n const addon = schema.slots\n .flatMap(s => s.addons)\n .find(a => a.id === step.addonId)\n\n let modelId = step.modelId\n if (addon && !addon.models.some(m => m.id === modelId)) {\n const fallback = addon.defaultModelId\n warnings.push(`Model \"${modelId}\" not available for ${step.addonId} — using \"${fallback}\"`)\n modelId = fallback\n }\n\n const validChildren = step.children\n .map(c => validateStep(c))\n .filter((c): c is PipelineTemplateStep => c !== null)\n\n return { ...step, modelId, children: validChildren }\n }\n\n const validSteps = steps\n .map(s => validateStep(s))\n .filter((s): s is PipelineTemplateStep => s !== null)\n\n return {\n valid: warnings.length === 0,\n steps: validSteps,\n warnings,\n }\n}\n","/**\n * Detection class colors — single source of truth.\n *\n * Used by: DetectionCanvas (UI), result-annotator (server-side SVG),\n * admin-ui event viewer, and any other place that visualizes detections.\n */\n\n/** Fixed colors for known detection classes */\nexport const CLASS_COLORS: Readonly<Record<string, string>> = {\n // Primary detection classes\n person: '#3b82f6', // blue-500\n vehicle: '#f59e0b', // amber-500\n animal: '#22c55e', // green-500\n\n // Sub-detection classes\n face: '#a855f7', // purple-500\n plate: '#ec4899', // pink-500\n\n // Specific animal types\n bird: '#14b8a6', // teal-500\n dog: '#84cc16', // lime-500\n cat: '#f97316', // orange-500\n\n // Specific vehicle types\n car: '#f59e0b', // amber-500\n truck: '#d97706', // amber-600\n bus: '#b45309', // amber-700\n motorcycle:'#eab308', // yellow-500\n bicycle: '#ca8a04', // yellow-600\n\n // Other\n motion: '#facc15', // yellow-400\n}\n\n/** Fallback color palette for unknown classes (deterministic hash-based) */\nconst FALLBACK_PALETTE: readonly string[] = [\n '#ef4444', // red-500\n '#8b5cf6', // violet-500\n '#06b6d4', // cyan-500\n '#f97316', // orange-500\n '#10b981', // emerald-500\n '#6366f1', // indigo-500\n '#e11d48', // rose-600\n '#0891b2', // cyan-600\n '#7c3aed', // violet-600\n '#059669', // emerald-600\n]\n\n/** Primary/default color when nothing else matches */\nexport const DEFAULT_COLOR = '#f59e42'\n\n/**\n * Get the color for a detection class name.\n * Returns a fixed color for known classes, or a deterministic hash-based color for unknown ones.\n */\nexport function getClassColor(className: string, customColors?: Readonly<Record<string, string>>): string {\n // Check custom overrides first\n if (customColors?.[className]) return customColors[className]!\n if (customColors?.[className.toLowerCase()]) return customColors[className.toLowerCase()]!\n\n // Check known classes\n if (CLASS_COLORS[className]) return CLASS_COLORS[className]!\n if (CLASS_COLORS[className.toLowerCase()]) return CLASS_COLORS[className.toLowerCase()]!\n\n // Deterministic hash for unknown classes\n let hash = 0\n for (let i = 0; i < className.length; i++) {\n hash = (hash * 31 + (className.codePointAt(i) ?? 0)) >>> 0\n }\n return FALLBACK_PALETTE[hash % FALLBACK_PALETTE.length] ?? DEFAULT_COLOR\n}\n","/**\n * DetectionCanvas — renders an image with overlaid bounding boxes.\n *\n * Adapted to the Phase 6 detection output rework: consumes the new\n * `ObjectDetection` shape (flat at root, `bbox: {x,y,width,height}`,\n * `labels: ScoredLabel[]`, `parentId` for details). Details (face,\n * plate) are drawn as inner boxes correlated with their parent via\n * `parentId`.\n */\nimport { type ReactNode, useRef, useEffect } from 'react'\nimport { cn } from '../lib/cn'\nimport { getClassColor } from './detection-colors'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type { ObjectDetection, ScoredLabel, DetectionBoundingBox } from '@camstack/types'\nimport type { ObjectDetection, ScoredLabel, DetectionBoundingBox } from '@camstack/types'\n\n/** Legacy alias kept so pre-rework consumers don't need a coordinated rename. */\nexport type Detection = ObjectDetection\n\nexport interface DetectionCanvasProps {\n /** Image source (data URL or regular URL) */\n readonly src: string | null\n /** Image dimensions (used for bbox coordinate mapping) */\n readonly imageWidth: number\n readonly imageHeight: number\n /** Detections to overlay — flat list (first-level + details). */\n readonly detections?: readonly ObjectDetection[]\n /** Custom class → hex color mapping (merged with defaults) */\n readonly classColors?: Readonly<Record<string, string>>\n /** Aspect ratio CSS value (default: auto based on image dimensions) */\n readonly aspectRatio?: string\n /** Additional CSS classes on the container */\n readonly className?: string\n /** Placeholder content when no image is loaded */\n readonly placeholder?: ReactNode\n /** Show confidence percentage in bbox labels */\n readonly showConfidence?: boolean\n /** Minimum confidence to display (0-1, default: 0) */\n readonly minConfidence?: number\n /** Border width for bboxes in px (default: 2) */\n readonly borderWidth?: number\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function DetectionCanvas({\n src,\n imageWidth,\n imageHeight,\n detections = [],\n classColors,\n aspectRatio,\n className,\n placeholder,\n showConfidence = true,\n minConfidence = 0,\n borderWidth = 2,\n}: DetectionCanvasProps) {\n function getColor(cls: string): string {\n return getClassColor(cls, classColors)\n }\n\n const ratio = aspectRatio ?? (imageWidth && imageHeight ? `${imageWidth}/${imageHeight}` : '16/9')\n\n const filtered = detections.filter((d) => d.score >= minConfidence)\n const firstLevel = filtered.filter((d) => d.kind === 'first-level')\n const details = filtered.filter((d) => d.kind === 'detail')\n const detailsByParent = groupBy(details, (d) => d.parentId ?? '')\n\n return (\n <div\n className={cn(\n 'rounded-lg border border-border bg-surface overflow-hidden relative',\n className,\n )}\n style={{ aspectRatio: ratio }}\n >\n {src ? (\n <>\n {/* Image — absolute so it shares coordinate space with bbox overlays */}\n <img src={src} className=\"absolute inset-0 w-full h-full object-fill\" alt=\"\" />\n\n {/* Segmentation mask overlays (rendered behind bounding boxes) */}\n {filtered.map((d, i) =>\n d.debug?.mask && d.debug.maskWidth && d.debug.maskHeight ? (\n <MaskOverlay\n key={`mask-${i}`}\n mask={d.debug.mask}\n maskWidth={d.debug.maskWidth}\n maskHeight={d.debug.maskHeight}\n bbox={d.bbox}\n imageWidth={imageWidth}\n imageHeight={imageHeight}\n color={getColor(d.macroClass)}\n />\n ) : null,\n )}\n\n {/* First-level detection boxes (person / vehicle / animal) */}\n {firstLevel.map((d) => {\n const children = detailsByParent.get(d.id) ?? []\n return (\n <BoundingBox\n key={`det-${d.id}`}\n detection={d}\n imageWidth={imageWidth}\n imageHeight={imageHeight}\n color={getColor(d.macroClass)}\n showConfidence={showConfidence}\n borderWidth={d.debug?.mask ? 1 : borderWidth}\n >\n {children.map((child) => (\n <ChildBoundingBox\n key={`child-${child.id}`}\n child={child}\n parentBbox={d.bbox}\n color={getColor(child.macroClass)}\n showConfidence={showConfidence}\n />\n ))}\n </BoundingBox>\n )\n })}\n\n {/* Orphan details (no parentId or parent not in view) */}\n {details\n .filter((d) => !d.parentId || !firstLevel.some((p) => p.id === d.parentId))\n .map((d) => (\n <BoundingBox\n key={`orphan-${d.id}`}\n detection={d}\n imageWidth={imageWidth}\n imageHeight={imageHeight}\n color={getColor(d.macroClass)}\n showConfidence={showConfidence}\n borderWidth={borderWidth}\n />\n ))}\n </>\n ) : (\n <div className=\"w-full h-full flex items-center justify-center text-foreground-subtle text-sm\">\n {placeholder ?? 'No image loaded'}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction BoundingBox({\n detection,\n imageWidth,\n imageHeight,\n color,\n showConfidence,\n borderWidth,\n children,\n}: {\n detection: ObjectDetection\n imageWidth: number\n imageHeight: number\n color: string\n showConfidence: boolean\n borderWidth: number\n children?: ReactNode\n}) {\n const { x, y, width, height } = detection.bbox\n\n const labelsElement = (\n <div\n className=\"absolute left-0 flex flex-col items-start gap-px\"\n style={{ bottom: '100%', marginBottom: '2px' }}\n >\n <span\n className=\"text-[10px] px-1 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: color }}\n >\n {detection.macroClass}\n {showConfidence && ` ${(detection.score * 100).toFixed(0)}%`}\n </span>\n {detection.labels.map((l: ScoredLabel, k: number) => (\n <span\n key={`${detection.id}-lbl-${k}`}\n className=\"text-[9px] font-semibold px-1 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: getClassColor(l.label) }}\n >\n {l.label} {(l.score * 100).toFixed(0)}%\n </span>\n ))}\n </div>\n )\n\n return (\n <div\n className=\"absolute rounded-sm\"\n style={{\n left: `${(x / imageWidth) * 100}%`,\n top: `${(y / imageHeight) * 100}%`,\n width: `${(width / imageWidth) * 100}%`,\n height: `${(height / imageHeight) * 100}%`,\n borderWidth: `${borderWidth}px`,\n borderStyle: 'solid',\n borderColor: color,\n }}\n >\n {labelsElement}\n {children}\n </div>\n )\n}\n\n/** Renders a segmentation mask as a semi-transparent colored canvas overlay */\nfunction MaskOverlay({\n mask,\n maskWidth,\n maskHeight,\n bbox,\n imageWidth,\n imageHeight,\n color,\n}: {\n mask: string\n maskWidth: number\n maskHeight: number\n bbox: DetectionBoundingBox\n imageWidth: number\n imageHeight: number\n color: string\n}) {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n\n const binary = atob(mask)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n\n const r = parseInt(color.slice(1, 3), 16)\n const g = parseInt(color.slice(3, 5), 16)\n const b = parseInt(color.slice(5, 7), 16)\n\n canvas.width = maskWidth\n canvas.height = maskHeight\n const imageData = ctx.createImageData(maskWidth, maskHeight)\n const totalPixels = maskWidth * maskHeight\n\n for (let i = 0; i < totalPixels; i++) {\n const val = i < bytes.length ? bytes[i]! : 0\n const px = i * 4\n if (val > 0) {\n imageData.data[px] = r\n imageData.data[px + 1] = g\n imageData.data[px + 2] = b\n imageData.data[px + 3] = 120 // semi-transparent\n }\n }\n\n ctx.putImageData(imageData, 0, 0)\n }, [mask, maskWidth, maskHeight, color])\n\n return (\n <canvas\n ref={canvasRef}\n className=\"absolute pointer-events-none\"\n style={{\n left: `${(bbox.x / imageWidth) * 100}%`,\n top: `${(bbox.y / imageHeight) * 100}%`,\n width: `${(bbox.width / imageWidth) * 100}%`,\n height: `${(bbox.height / imageHeight) * 100}%`,\n imageRendering: 'pixelated',\n }}\n />\n )\n}\n\nfunction ChildBoundingBox({\n child,\n parentBbox,\n color,\n showConfidence,\n}: {\n child: ObjectDetection\n parentBbox: DetectionBoundingBox\n color: string\n showConfidence: boolean\n}) {\n if (parentBbox.width <= 0 || parentBbox.height <= 0) return null\n\n const relLeft = ((child.bbox.x - parentBbox.x) / parentBbox.width) * 100\n const relTop = ((child.bbox.y - parentBbox.y) / parentBbox.height) * 100\n const relWidth = (child.bbox.width / parentBbox.width) * 100\n const relHeight = (child.bbox.height / parentBbox.height) * 100\n\n return (\n <div\n className=\"absolute rounded-sm\"\n style={{\n left: `${Math.max(0, relLeft)}%`,\n top: `${Math.max(0, relTop)}%`,\n width: `${Math.min(100, relWidth)}%`,\n height: `${Math.min(100, relHeight)}%`,\n borderWidth: '1px',\n borderStyle: 'solid',\n borderColor: color,\n }}\n >\n <div\n className=\"absolute left-0 flex flex-col items-start gap-px\"\n style={{ bottom: '100%', marginBottom: '1px' }}\n >\n <span\n className=\"text-[9px] px-0.5 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: color }}\n >\n {child.macroClass}\n {showConfidence && ` ${(child.score * 100).toFixed(0)}%`}\n </span>\n {child.labels.map((l: ScoredLabel, k: number) => (\n <span\n key={`${child.id}-lbl-${k}`}\n className=\"text-[8px] font-semibold px-0.5 rounded-sm whitespace-nowrap text-white\"\n style={{ backgroundColor: getClassColor(l.label) }}\n >\n {l.label} {(l.score * 100).toFixed(0)}%\n </span>\n ))}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction groupBy<T, K>(items: readonly T[], keyFn: (item: T) => K): Map<K, T[]> {\n const out = new Map<K, T[]>()\n for (const item of items) {\n const key = keyFn(item)\n const arr = out.get(key) ?? []\n arr.push(item)\n out.set(key, arr)\n }\n return out\n}\n","/**\n * DetectionResultTree — displays detection results as a hierarchical tree.\n *\n * Adapted to the Phase 6 output rework: the tree consumes flat\n * `ObjectDetection[]` and correlates details (face / plate) with\n * their parents via `parentId`. First-level entries are top-level\n * nodes; their details render as indented children. Each node shows:\n * - bbox (rectangle)\n * - macroClass + score badge\n * - `labels[]` (ScoredLabel — own + inherited)\n * - `debug.alternateLabels` (top-N per source) when present\n */\nimport { useState } from 'react'\nimport type { ObjectDetection, ScoredLabel } from '@camstack/types'\nimport { getClassColor } from './detection-colors'\n\nexport interface DetectionResultTreeProps {\n readonly detections: readonly ObjectDetection[]\n readonly classColors?: Readonly<Record<string, string>>\n readonly className?: string\n /** Set of detection ids that are hidden */\n readonly hiddenKeys?: ReadonlySet<string>\n /** Callback when a detection's visibility is toggled */\n readonly onToggleVisibility?: (key: string, visible: boolean) => void\n}\n\nexport function DetectionResultTree({\n detections,\n classColors,\n className,\n hiddenKeys,\n onToggleVisibility,\n}: DetectionResultTreeProps) {\n const colors = classColors\n\n if (detections.length === 0) {\n return (\n <div className=\"text-sm text-foreground-subtle italic text-center py-4\">\n No detections\n </div>\n )\n }\n\n const firstLevel = detections.filter((d) => d.kind === 'first-level')\n const details = detections.filter((d) => d.kind === 'detail')\n const detailsByParent = new Map<string, ObjectDetection[]>()\n for (const d of details) {\n if (!d.parentId) continue\n const arr = detailsByParent.get(d.parentId) ?? []\n arr.push(d)\n detailsByParent.set(d.parentId, arr)\n }\n const orphanDetails = details.filter((d) => !d.parentId || !firstLevel.some((p) => p.id === d.parentId))\n\n return (\n <div className={className}>\n <div className=\"text-xs font-medium text-foreground-subtle uppercase tracking-wide mb-2\">\n Detections ({detections.length})\n </div>\n <div className=\"space-y-2\">\n {firstLevel.map((d) => (\n <DetectionNode\n key={d.id}\n detection={d}\n children_={detailsByParent.get(d.id) ?? []}\n colors={colors}\n hiddenKeys={hiddenKeys}\n onToggleVisibility={onToggleVisibility}\n />\n ))}\n {orphanDetails.map((d) => (\n <DetectionNode\n key={d.id}\n detection={d}\n children_={[]}\n colors={colors}\n hiddenKeys={hiddenKeys}\n onToggleVisibility={onToggleVisibility}\n />\n ))}\n </div>\n </div>\n )\n}\n\nfunction DetectionNode({\n detection,\n children_,\n colors,\n hiddenKeys,\n onToggleVisibility,\n}: {\n detection: ObjectDetection\n children_: readonly ObjectDetection[]\n colors?: Record<string, string>\n hiddenKeys?: ReadonlySet<string>\n onToggleVisibility?: (key: string, visible: boolean) => void\n}) {\n const color = getClassColor(detection.macroClass, colors)\n const isVisible = !hiddenKeys?.has(detection.id)\n const mask = detection.debug?.mask\n const maskWidth = detection.debug?.maskWidth\n const maskHeight = detection.debug?.maskHeight\n const alternateLabels = detection.debug?.alternateLabels\n\n return (\n <div className={`rounded-md border border-border bg-surface p-3 space-y-1 ${isVisible ? '' : 'opacity-40'}`}>\n <div className=\"flex justify-between items-center\">\n <div className=\"flex items-center gap-2\">\n {onToggleVisibility && (\n <input\n type=\"checkbox\"\n checked={isVisible}\n onChange={() => onToggleVisibility(detection.id, !isVisible)}\n className=\"h-3.5 w-3.5 rounded border-border accent-primary cursor-pointer shrink-0\"\n />\n )}\n <span\n className=\"h-2.5 w-2.5 rounded-full shrink-0\"\n style={{ backgroundColor: color }}\n />\n <span className=\"text-sm font-medium text-foreground\">\n {detection.macroClass}\n </span>\n {detection.kind === 'detail' && (\n <span className=\"text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary\">detail</span>\n )}\n {mask && maskWidth && maskHeight && (\n <span className=\"text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary\">\n mask {maskWidth}x{maskHeight}\n </span>\n )}\n </div>\n <ConfidenceBadge confidence={detection.score} />\n </div>\n\n <div className=\"text-[10px] text-foreground-subtle font-mono\">\n bbox: [{Math.round(detection.bbox.x)}, {Math.round(detection.bbox.y)},{' '}\n {Math.round(detection.bbox.x + detection.bbox.width)},{' '}\n {Math.round(detection.bbox.y + detection.bbox.height)}]\n </div>\n\n {/* Labels — own + inherited from children details */}\n {detection.labels.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {detection.labels.map((l: ScoredLabel, k: number) => (\n <span\n key={k}\n className=\"inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full\"\n style={{\n backgroundColor: getClassColor(l.label, colors) + '20',\n color: getClassColor(l.label, colors),\n }}\n >\n {l.label}\n <span className=\"opacity-60\">{(l.score * 100).toFixed(0)}%</span>\n {l.detectionId && (\n <span className=\"opacity-40 text-[8px]\">→ {l.detectionId}</span>\n )}\n </span>\n ))}\n </div>\n )}\n\n {/* Alternate labels — full ranked list per source (debug/benchmark) */}\n {alternateLabels && Object.keys(alternateLabels).length > 0 && (\n <AlternateLabelsSection alternateLabels={alternateLabels} colors={colors} />\n )}\n\n {/* Detail children — face, plate, etc. */}\n {children_.length > 0 && (\n <ChildrenTree\n items={children_}\n colors={colors}\n hiddenKeys={hiddenKeys}\n onToggleVisibility={onToggleVisibility}\n />\n )}\n </div>\n )\n}\n\nfunction ChildrenTree({\n items,\n colors,\n hiddenKeys,\n onToggleVisibility,\n}: {\n items: readonly ObjectDetection[]\n colors?: Record<string, string>\n hiddenKeys?: ReadonlySet<string>\n onToggleVisibility?: (key: string, visible: boolean) => void\n}) {\n return (\n <div className=\"ml-4 mt-1.5 space-y-1.5 border-l-2 border-border pl-3\">\n {items.map((child) => {\n const childColor = getClassColor(child.macroClass, colors)\n const isVisible = !hiddenKeys?.has(child.id)\n const mask = child.debug?.mask\n const maskWidth = child.debug?.maskWidth\n const maskHeight = child.debug?.maskHeight\n\n return (\n <div key={child.id} className={`text-xs space-y-0.5 ${isVisible ? '' : 'opacity-40'}`}>\n <div className=\"flex items-center gap-1.5\">\n {onToggleVisibility && (\n <input\n type=\"checkbox\"\n checked={isVisible}\n onChange={() => onToggleVisibility(child.id, !isVisible)}\n className=\"h-3 w-3 rounded border-border accent-primary cursor-pointer shrink-0\"\n />\n )}\n <span\n className=\"h-1.5 w-1.5 rounded-full shrink-0\"\n style={{ backgroundColor: childColor }}\n />\n <span className=\"font-medium\" style={{ color: childColor }}>\n {child.macroClass}\n </span>\n <span className=\"text-foreground-subtle\">\n {(child.score * 100).toFixed(0)}%\n </span>\n {mask && maskWidth && maskHeight && (\n <span className=\"text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary\">\n mask {maskWidth}x{maskHeight}\n </span>\n )}\n </div>\n {child.labels.length > 0 && (\n <div className=\"flex flex-wrap gap-1 ml-5 mt-0.5\">\n {child.labels.map((l: ScoredLabel, k: number) => (\n <span\n key={k}\n className=\"inline-flex items-center gap-0.5 text-[9px] font-medium px-1 py-0.5 rounded-full\"\n style={{\n backgroundColor: getClassColor(l.label, colors) + '20',\n color: getClassColor(l.label, colors),\n }}\n >\n {l.label} <span className=\"opacity-60\">{(l.score * 100).toFixed(0)}%</span>\n </span>\n ))}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )\n}\n\nfunction AlternateLabelsSection({\n alternateLabels,\n colors,\n}: {\n readonly alternateLabels: Readonly<Record<string, readonly ScoredLabel[]>>\n readonly colors?: Record<string, string>\n}) {\n const [expanded, setExpanded] = useState(false)\n const sources = Object.keys(alternateLabels)\n\n return (\n <div className=\"mt-1\">\n <button\n onClick={() => setExpanded((v) => !v)}\n className=\"text-[9px] text-foreground-subtle hover:text-foreground transition-colors flex items-center gap-1\"\n >\n <span className={`transition-transform ${expanded ? 'rotate-90' : ''}`}>▶</span>\n Alternates ({sources.length} source{sources.length !== 1 ? 's' : ''})\n </button>\n {expanded && (\n <div className=\"mt-1 ml-3 space-y-1.5\">\n {sources.map((source) => {\n const labels = alternateLabels[source]\n if (!labels || labels.length === 0) return null\n return (\n <div key={source}>\n <div className=\"text-[9px] font-medium text-foreground-subtle mb-0.5\">{source}</div>\n <div className=\"flex flex-wrap gap-1\">\n {labels.map((l, k) => (\n <span\n key={k}\n className=\"inline-flex items-center gap-0.5 text-[9px] px-1 py-0.5 rounded-full\"\n style={{\n backgroundColor: getClassColor(source, colors) + '10',\n color: getClassColor(source, colors),\n opacity: Math.max(0.4, l.score),\n }}\n >\n {l.label}\n <span className=\"opacity-60\">{(l.score * 100).toFixed(1)}%</span>\n </span>\n ))}\n </div>\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction ConfidenceBadge({ confidence }: { confidence: number }) {\n const level =\n confidence >= 0.8 ? 'bg-success/10 text-success' :\n confidence >= 0.5 ? 'bg-warning/10 text-warning' :\n 'bg-danger/10 text-danger'\n\n return (\n <span className={`text-xs font-medium px-2 py-0.5 rounded-full ${level}`}>\n {(confidence * 100).toFixed(1)}%\n </span>\n )\n}\n","/**\n * StepTimings — displays pipeline execution timings per step.\n */\n\nexport interface StepTimingsProps {\n readonly timings: Readonly<Record<string, number>>\n readonly totalMs?: number\n readonly className?: string\n}\n\nexport function StepTimings({ timings, totalMs, className }: StepTimingsProps) {\n const entries = Object.entries(timings)\n if (entries.length === 0 && totalMs === undefined) return null\n\n return (\n <div className={`rounded-lg border border-border bg-surface p-3 space-y-2 ${className ?? ''}`}>\n <div className=\"text-xs font-medium text-foreground-subtle uppercase tracking-wide\">\n Timings\n </div>\n <div className=\"space-y-1 text-xs\">\n {entries.map(([step, ms]) => (\n <div key={step} className=\"flex justify-between\">\n <span className=\"text-foreground-subtle\">{step}</span>\n <span className=\"font-mono text-foreground\">{ms.toFixed(1)}ms</span>\n </div>\n ))}\n {totalMs !== undefined && (\n <div className=\"flex justify-between pt-1 border-t border-border font-medium text-foreground\">\n <span>Total</span>\n <span className=\"font-mono\">{totalMs.toFixed(1)}ms</span>\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * ImageSelector — chip-style picker for reference media + upload button.\n * Despite the historical name it's media-agnostic: pass `accept` to\n * filter the file picker (defaults to `image/*`). Used by both the\n * Image Tester and the Audio Tester so the two tabs share the exact\n * same selection UI.\n */\n\nexport interface ReferenceImage {\n readonly id?: string\n readonly filename: string\n readonly sizeKB?: number\n}\n\nexport interface ImageSelectorProps {\n readonly images: readonly ReferenceImage[]\n readonly selectedFilename: string\n readonly uploadedName?: string\n readonly onSelect: (filename: string) => void\n readonly onUpload: (base64: string, filename: string, dataUrl: string) => void\n readonly className?: string\n /** File picker `accept` value. Default: `image/*`. */\n readonly accept?: string\n /** Override the upload button label. Default: `Upload...`. */\n readonly uploadLabel?: string\n}\n\nexport function ImageSelector({\n images,\n selectedFilename,\n uploadedName,\n onSelect,\n onUpload,\n className,\n accept = 'image/*',\n uploadLabel = 'Upload...',\n}: ImageSelectorProps) {\n const handleUploadClick = () => {\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = accept\n input.onchange = () => {\n const file = input.files?.[0]\n if (!file) return\n const reader = new FileReader()\n reader.onload = () => {\n const dataUrl = reader.result as string\n const b64 = dataUrl.split(',')[1]\n if (b64) onUpload(b64, file.name, dataUrl)\n }\n reader.readAsDataURL(file)\n }\n input.click()\n }\n\n return (\n <div className={`flex flex-wrap items-center gap-2 ${className ?? ''}`}>\n {images.map(img => (\n <button\n key={img.filename}\n onClick={() => onSelect(img.filename)}\n className={`px-3 py-1.5 text-xs rounded-md border transition-colors ${\n selectedFilename === img.filename\n ? 'bg-primary text-primary-foreground border-primary'\n : 'bg-surface border-border text-foreground hover:border-primary/50'\n }`}\n >\n {img.id ?? img.filename.replace(/\\.[^.]+$/, '')}\n </button>\n ))}\n <button\n onClick={handleUploadClick}\n className=\"px-3 py-1.5 text-xs rounded-md border border-border bg-surface text-foreground hover:bg-surface-hover transition-colors\"\n >\n {uploadLabel}\n </button>\n {uploadedName && (\n <span className=\"text-xs text-foreground-subtle\">{uploadedName}</span>\n )}\n </div>\n )\n}\n","/**\n * InferenceConfigSelector — cascading selectors for runtime/backend/model.\n *\n * Used by benchmark Engine tab, Image Tester pipeline steps, and admin-ui\n * pipeline configuration. Shows only valid combinations based on capabilities.\n */\n\nexport interface InferenceBackendOption {\n readonly id: string\n readonly label: string\n readonly available: boolean\n}\n\nexport interface InferenceModelOption {\n readonly id: string\n readonly name: string\n readonly downloaded?: boolean\n}\n\nexport interface InferenceAgentOption {\n readonly id: string\n readonly name: string\n readonly status: 'online' | 'offline' | 'busy'\n}\n\nexport interface InferenceConfigSelectorProps {\n // Values\n readonly runtime: 'node' | 'python'\n readonly backend: string\n readonly modelId: string\n readonly agentId?: string\n\n // Options\n readonly runtimes: readonly { value: string; label: string; available: boolean }[]\n readonly backends: readonly InferenceBackendOption[]\n readonly models: readonly InferenceModelOption[]\n readonly agents?: readonly InferenceAgentOption[]\n\n // Callbacks\n readonly onRuntimeChange: (rt: 'node' | 'python') => void\n readonly onBackendChange: (id: string) => void\n readonly onModelChange: (id: string) => void\n readonly onAgentChange?: (id: string) => void\n\n // Layout\n readonly layout?: 'horizontal' | 'vertical' | 'grid'\n readonly className?: string\n /** Show agent selector (default: false) */\n readonly showAgent?: boolean\n}\n\nconst SELECT_CLASS = 'w-full px-3 py-2 text-sm rounded-md border border-border bg-surface text-foreground focus:outline-none focus:ring-2 focus:ring-primary/50'\n\nexport function InferenceConfigSelector({\n runtime,\n backend,\n modelId,\n agentId = 'hub',\n runtimes,\n backends,\n models,\n agents = [],\n onRuntimeChange,\n onBackendChange,\n onModelChange,\n onAgentChange,\n layout = 'grid',\n className,\n showAgent = false,\n}: InferenceConfigSelectorProps) {\n const containerClass = layout === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4'\n : layout === 'horizontal'\n ? 'flex flex-wrap items-end gap-4'\n : 'space-y-3'\n\n return (\n <div className={`${containerClass} ${className ?? ''}`}>\n {/* Agent (optional) */}\n {showAgent && agents.length > 0 && (\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Agent</span>\n <select\n value={agentId}\n onChange={e => onAgentChange?.(e.target.value)}\n className={SELECT_CLASS}\n >\n {agents.map(a => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.status})\n </option>\n ))}\n </select>\n </label>\n )}\n\n {/* Runtime */}\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Runtime</span>\n <select\n value={runtime}\n onChange={e => onRuntimeChange(e.target.value as 'node' | 'python')}\n className={SELECT_CLASS}\n >\n {runtimes.map(r => (\n <option key={r.value} value={r.value} disabled={!r.available}>\n {r.label}{!r.available ? ' (unavailable)' : ''}\n </option>\n ))}\n </select>\n </label>\n\n {/* Backend */}\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Backend</span>\n <select\n value={backend}\n onChange={e => onBackendChange(e.target.value)}\n className={SELECT_CLASS}\n >\n {backends.map(b => (\n <option key={b.id} value={b.id} disabled={!b.available}>\n {b.label}{!b.available ? ' (unavailable)' : ''}\n </option>\n ))}\n </select>\n </label>\n\n {/* Model */}\n <label className=\"space-y-1\">\n <span className=\"text-xs font-medium text-foreground-subtle\">Model</span>\n <select\n value={modelId}\n onChange={e => onModelChange(e.target.value)}\n className={SELECT_CLASS}\n >\n {models.length === 0\n ? <option value=\"\">No compatible models</option>\n : models.map(m => (\n <option key={m.id} value={m.id}>\n {m.name}{m.downloaded ? ' ✓' : ''}\n </option>\n ))\n }\n </select>\n </label>\n </div>\n )\n}\n","/**\n * mountAddonPage — one-liner to mount an addon page in dev mode.\n *\n * Handles everything: CSS import, React DOM mount, DevShell (login + theme + tRPC),\n * and wiring props in the standard AddonPageProps format.\n *\n * Usage in the addon's dev-shell.tsx:\n * ```tsx\n * import { mountAddonPage } from '@camstack/ui'\n * import MyPage from './page'\n * mountAddonPage(MyPage)\n * ```\n *\n * Or with options:\n * ```tsx\n * mountAddonPage(MyPage, { serverUrl: 'https://localhost:4443', title: 'My Addon' })\n * ```\n */\nimport { createElement } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { DevShell } from './dev-shell'\nimport type { AddonPageProps } from './addon-page-props'\n\nexport interface MountAddonPageOptions {\n /** Backend server URL (default: 'https://localhost:4443') */\n serverUrl?: string\n /** Title shown in the dev toolbar */\n title?: string\n /** Root element ID (default: 'root') */\n rootId?: string\n}\n\n/**\n * Mount an addon page component with the full dev shell.\n *\n * @param PageComponent - The addon page component (must accept AddonPageProps)\n * @param options - Configuration options\n */\nexport function mountAddonPage(\n PageComponent: (props: AddonPageProps) => React.ReactNode,\n options: MountAddonPageOptions = {},\n): void {\n const {\n serverUrl = 'https://localhost:4443',\n title,\n rootId = 'root',\n } = options\n\n const root = document.getElementById(rootId)\n if (!root) {\n console.error(`[mountAddonPage] Element #${rootId} not found`)\n return\n }\n\n createRoot(root).render(\n createElement(DevShell, {\n serverUrl,\n title,\n children: ({ trpc, theme }) =>\n createElement(PageComponent, {\n trpc,\n theme: { isDark: theme.resolvedMode === 'dark' },\n navigate: (path: string) => {\n console.log('[dev] navigate:', path)\n },\n }),\n }),\n )\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { createTRPCClient, createWSClient, wsLink, httpLink, splitLink, type TRPCClient } from '@trpc/client'\nimport type { AppRouter } from '@camstack/types'\nimport { createSystem, type System } from '@camstack/sdk'\nimport superjson from 'superjson'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ThemeProvider } from '../theme/theme-provider'\nimport { useThemeMode } from '../theme/use-theme-mode'\nimport type { UseThemeModeReturn } from '../theme/types'\nimport { trpc as trpcReact } from '../trpc-react'\nimport { SystemProvider } from '../contexts/system-context'\nimport { LoginForm } from './login-form'\n\nconst STORAGE_KEY = 'camstack_dev_token'\n\nexport interface DevShellProps {\n children: (props: { trpc: TRPCClient<AppRouter>; theme: UseThemeModeReturn }) => ReactNode\n serverUrl?: string\n title?: string\n}\n\ninterface DevShellContextValue {\n trpc: TRPCClient<AppRouter>\n token: string\n logout: () => void\n}\n\nconst DevShellContext = createContext<DevShellContextValue | null>(null)\n\nexport function useDevShell(): DevShellContextValue {\n const ctx = useContext(DevShellContext)\n if (!ctx) {\n throw new Error('useDevShell must be used within a DevShell')\n }\n return ctx\n}\n\nfunction getStoredToken(): string | null {\n if (typeof window === 'undefined') return null\n return localStorage.getItem(STORAGE_KEY)\n}\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2\" />\n <path d=\"M12 20v2\" />\n <path d=\"m4.93 4.93 1.41 1.41\" />\n <path d=\"m17.66 17.66 1.41 1.41\" />\n <path d=\"M2 12h2\" />\n <path d=\"M20 12h2\" />\n <path d=\"m6.34 17.66-1.41 1.41\" />\n <path d=\"m19.07 4.93-1.41 1.41\" />\n </svg>\n )\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\" />\n </svg>\n )\n}\n\nfunction DevShellInner({\n children,\n serverUrl,\n title,\n token,\n onLogout,\n}: {\n children: DevShellProps['children']\n serverUrl: string\n title?: string\n token: string\n onLogout: () => void\n}) {\n const theme = useThemeMode()\n\n const links = useMemo(() => {\n const wsUrl = serverUrl.replace(/^http/, 'ws') + '/trpc'\n const wsClient = createWSClient({\n url: wsUrl,\n connectionParams: () => ({ token }),\n })\n return [\n splitLink({\n condition: (op) => op.type === 'subscription',\n true: wsLink({ client: wsClient, transformer: superjson }),\n false: httpLink({\n url: `${serverUrl}/trpc`,\n transformer: superjson,\n headers: () => ({ authorization: `Bearer ${token}` }),\n }),\n }),\n ]\n }, [serverUrl, token])\n\n const trpc = useMemo(\n () => createTRPCClient<AppRouter>({ links }),\n [links],\n )\n\n const trpcReactClient = useMemo(\n () => trpcReact.createClient({ links }),\n [links],\n )\n\n // Build a `System` instance against the same backend so hooks that\n // read from `<SystemProvider>` (`useLiveEvent`, codegen'd\n // `use<Cap><Method>`, `useDevices`) work in the dev shell. The System\n // owns its own WebSocket distinct from the tRPC client above — both\n // hit `/trpc` on the same server, so the duplication is bounded to\n // dev mode and keeps the addon page identical to its production\n // mount inside the admin UI.\n const system: System = useMemo(\n () =>\n createSystem({\n serverUrl,\n token,\n }),\n [serverUrl, token],\n )\n useEffect(() => {\n void system.init().catch(() => undefined)\n return () => {\n system.close()\n }\n }, [system])\n\n const queryClient = useMemo(() => new QueryClient(), [])\n\n const contextValue = useMemo<DevShellContextValue>(\n () => ({ trpc, token, logout: onLogout }),\n [trpc, token, onLogout],\n )\n\n return (\n <SystemProvider system={system}>\n <trpcReact.Provider client={trpcReactClient} queryClient={queryClient}>\n <QueryClientProvider client={queryClient}>\n <DevShellContext.Provider value={contextValue}>\n <div className=\"min-h-screen bg-background text-foreground\">\n <div className=\"flex items-center justify-between border-b border-border bg-surface px-4 py-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"rounded bg-warning/20 px-2 py-0.5 text-xs font-bold text-warning\">\n DEV MODE\n </span>\n {title && (\n <span className=\"text-sm font-medium text-foreground\">\n {title}\n </span>\n )}\n <span className=\"text-xs text-foreground-subtle\">\n {serverUrl}\n </span>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={theme.toggleMode}\n className=\"flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors\"\n title={`Theme: ${theme.mode}`}\n >\n {theme.resolvedMode === 'dark' ? (\n <SunIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <MoonIcon className=\"h-3.5 w-3.5\" />\n )}\n {theme.mode === 'dark' ? 'Dark' : theme.mode === 'light' ? 'Light' : 'System'}\n </button>\n\n <button\n type=\"button\"\n onClick={onLogout}\n className=\"rounded-md px-2.5 py-1 text-xs font-medium text-danger hover:bg-danger/10 transition-colors\"\n >\n Logout\n </button>\n </div>\n </div>\n\n <div className=\"p-4\">{children({ trpc, theme })}</div>\n </div>\n </DevShellContext.Provider>\n </QueryClientProvider>\n </trpcReact.Provider>\n </SystemProvider>\n )\n}\n\nexport function DevShell({\n children,\n serverUrl = 'https://localhost:4443',\n title,\n}: DevShellProps) {\n const [token, setToken] = useState<string | null>(getStoredToken)\n\n const handleLogin = useCallback(\n async (username: string, password: string) => {\n // Use tRPC client for auth (no token yet)\n const anonClient = createTRPCClient<AppRouter>({\n links: [\n httpLink({\n url: `${serverUrl}/trpc`,\n transformer: superjson,\n }),\n ],\n })\n\n const res = await anonClient.auth.login.mutate({ username, password })\n const loginResult = res as { token?: string }\n if (!loginResult.token) throw new Error('No token returned')\n\n localStorage.setItem(STORAGE_KEY, loginResult.token)\n setToken(loginResult.token)\n },\n [serverUrl],\n )\n\n const handleLogout = useCallback(() => {\n localStorage.removeItem(STORAGE_KEY)\n setToken(null)\n }, [])\n\n if (!token) {\n return (\n <ThemeProvider>\n <LoginForm onLogin={handleLogin} serverUrl={serverUrl} />\n </ThemeProvider>\n )\n }\n\n return (\n <ThemeProvider>\n <DevShellInner\n serverUrl={serverUrl}\n title={title}\n token={token}\n onLogout={handleLogout}\n >\n {children}\n </DevShellInner>\n </ThemeProvider>\n )\n}\n","import { type SyntheticEvent, useState } from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface LoginFormProps {\n onLogin: (username: string, password: string) => Promise<void>\n serverUrl?: string\n logoSrc?: string\n error?: string\n className?: string\n}\n\nfunction EyeIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )\n}\n\nfunction EyeOffIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n )\n}\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n )\n}\n\nexport function LoginForm({\n onLogin,\n serverUrl,\n logoSrc,\n error: externalError,\n className,\n}: LoginFormProps) {\n const [username, setUsername] = useState('')\n const [password, setPassword] = useState('')\n const [showPassword, setShowPassword] = useState(false)\n const [submitting, setSubmitting] = useState(false)\n const [internalError, setInternalError] = useState<string | null>(null)\n\n const error = externalError ?? internalError\n\n const handleSubmit = async (e: SyntheticEvent) => {\n e.preventDefault()\n if (submitting) return\n\n setInternalError(null)\n setSubmitting(true)\n\n try {\n await onLogin(username, password)\n } catch (err) {\n const message =\n err instanceof Error ? err.message : 'Login failed. Please try again.'\n setInternalError(message)\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-screen items-center justify-center bg-background p-4',\n className,\n )}\n >\n <div className=\"w-full max-w-sm\">\n {logoSrc && (\n <div className=\"flex justify-center mb-8\">\n <img src={logoSrc} alt=\"Logo\" className=\"h-12\" />\n </div>\n )}\n\n {serverUrl && (\n <p className=\"mb-4 text-center text-xs text-foreground-subtle truncate\">\n {serverUrl}\n </p>\n )}\n\n <form\n onSubmit={handleSubmit}\n className=\"space-y-4 rounded-xl border border-border bg-surface p-6 shadow-xl shadow-black/10\"\n >\n {error && (\n <div className=\"rounded-md bg-danger/10 border border-danger/20 px-3 py-2 text-xs text-danger\">\n {error}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-foreground-subtle\">\n Username\n </label>\n <input\n type=\"text\"\n value={username}\n onChange={(e) => setUsername(e.target.value)}\n autoComplete=\"username\"\n required\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary\"\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-foreground-subtle\">\n Password\n </label>\n <div className=\"relative\">\n <input\n type={showPassword ? 'text' : 'password'}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n autoComplete=\"current-password\"\n required\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2.5 pr-10 text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary\"\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword((prev) => !prev)}\n className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground\"\n tabIndex={-1}\n >\n {showPassword ? (\n <EyeOffIcon className=\"h-4 w-4\" />\n ) : (\n <EyeIcon className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </div>\n\n <button\n type=\"submit\"\n disabled={submitting}\n className=\"w-full rounded-lg bg-primary px-4 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center justify-center gap-2\"\n >\n {submitting && (\n <SpinnerIcon className=\"h-4 w-4 animate-spin\" />\n )}\n {submitting ? 'Logging in...' : 'Log in'}\n </button>\n </form>\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { ConfigUISchema, ConfigSection, FieldProbeResult } from '@camstack/types'\nimport { ConfigFormField } from './config-form-field'\nimport type { ProbeState } from './config-form-field'\n\n// ---------------------------------------------------------------------------\n// Translation support\n// ---------------------------------------------------------------------------\n\nexport type TranslationFn = (key: string) => string\n\nfunction isI18nKey(value: string): boolean {\n return /^[a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+)+$/.test(value)\n}\n\nexport function resolveLabel(value: string | undefined, t?: TranslationFn): string | undefined {\n if (value === undefined) return undefined\n if (t && isI18nKey(value)) return t(value)\n return value\n}\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\ninterface FormBuilderProps {\n schema: ConfigUISchema\n values: Record<string, unknown>\n onChange: (values: Record<string, unknown>) => void\n disabled?: boolean\n translationFn?: TranslationFn\n onTestField?: (key: string, value: unknown) => Promise<FieldProbeResult>\n /** External probe results from useProbeAll hook */\n probeResults?: Record<string, ProbeState>\n /** Callback to clear a probe result when a field value changes */\n onClearProbe?: (key: string) => void\n}\n\n// ---------------------------------------------------------------------------\n// Section renderer\n// ---------------------------------------------------------------------------\n\nfunction SectionCard({\n section,\n values,\n onChange,\n disabled,\n translationFn,\n onTestField,\n probeResults,\n}: {\n section: ConfigSection\n values: Record<string, unknown>\n onChange: (key: string, value: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n onTestField?: (key: string, value: unknown) => Promise<FieldProbeResult>\n probeResults?: Record<string, ProbeState>\n}) {\n const [collapsed, setCollapsed] = useState(section.defaultCollapsed ?? false)\n const isAccordion = section.style === 'accordion'\n\n // Container-query driven responsive grid. Each section is its own\n // `@container` so the column count adapts to the SECTION's width\n // (not the viewport) — important inside narrow hosts like the\n // device-detail right column. Behavior:\n // columns=1 → always 1 col\n // columns=2 (default) → 1 col below 640px container, 2 cols above\n // columns=3 → 1 → 2 → 3 col at 480px / 880px\n // columns=4 → 1 → 2 → 4 col at 480px / 1140px\n // Pixel thresholds chosen so each cell stays readable: a labelled\n // text field with its descriptions needs ~280-300px to breathe.\n // Tailwind 4 supports arbitrary container-query values via\n // `@[Npx]:` prefix.\n const columns = section.columns ?? 2\n const gridClass =\n columns === 1\n ? 'grid-cols-1'\n : columns === 3\n ? 'grid-cols-1 @[480px]:grid-cols-2 @[880px]:grid-cols-3'\n : columns === 4\n ? 'grid-cols-1 @[480px]:grid-cols-2 @[1140px]:grid-cols-4'\n : 'grid-cols-1 @[640px]:grid-cols-2'\n\n return (\n <div\n className=\"@container rounded-lg border border-border bg-surface p-3\"\n style={{ containerType: 'inline-size' }}\n >\n <div\n className={[\n 'flex items-center justify-between mb-2',\n isAccordion ? 'cursor-pointer' : '',\n ].join(' ')}\n onClick={isAccordion ? () => setCollapsed((c) => !c) : undefined}\n >\n <div>\n <h3 className=\"text-[11px] font-semibold text-foreground-subtle uppercase tracking-wider\">\n {resolveLabel(section.title, translationFn)}\n </h3>\n {section.description && (\n <p className=\"text-[10px] text-foreground-subtle mt-0.5\">{resolveLabel(section.description, translationFn)}</p>\n )}\n </div>\n {isAccordion && (\n <span className=\"text-foreground-subtle text-xs ml-2\">{collapsed ? '▸' : '▾'}</span>\n )}\n </div>\n\n {!collapsed && (\n <div className={`grid ${gridClass} gap-x-3 gap-y-2.5`}>\n {section.fields.map((field) => (\n <ConfigFormField\n key={field.key}\n field={field}\n values={values}\n onChange={onChange}\n disabled={disabled}\n translationFn={translationFn}\n onTestField={onTestField}\n externalProbe={probeResults?.[field.key]}\n />\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// FormBuilder\n// ---------------------------------------------------------------------------\n\nexport function ConfigFormBuilder({ schema, values, onChange, disabled, translationFn, onTestField, probeResults, onClearProbe }: FormBuilderProps) {\n const handleFieldChange = (key: string, value: unknown) => {\n onChange({ ...values, [key]: value })\n onClearProbe?.(key)\n }\n\n return (\n <div className=\"space-y-4\">\n {schema.sections.map((section) => (\n <SectionCard\n key={section.id}\n section={section}\n values={values}\n onChange={handleFieldChange}\n disabled={disabled}\n translationFn={translationFn}\n onTestField={onTestField}\n probeResults={probeResults}\n />\n ))}\n </div>\n )\n}\n","import { useState, useCallback, useRef, useEffect } from 'react'\nimport { Eye, EyeOff, X, Wifi, Loader2, CheckCircle, AlertCircle, Copy, RefreshCw, ExternalLink, Trash2, Download, Upload, Wrench, Plus, Minus } from 'lucide-react'\nimport type {\n ConfigField,\n ConfigGroupField,\n ConfigSubTabsField,\n ConfigInfoField,\n ConfigObjectArrayField,\n ConfigMultiSelectField,\n ConfigNumberField,\n ConfigBooleanField,\n ConfigSelectField,\n ConfigColorField,\n ConfigTextAreaField,\n ConfigSliderField,\n ConfigTagsField,\n ConfigPasswordField,\n ConfigTextField,\n ConfigProbeField,\n ConfigButtonField,\n ConfigNodeSelectField,\n ConfigNodeMultiSelectField,\n ConfigWidgetField,\n FieldInlineAction,\n FieldProbeResult,\n} from '@camstack/types'\nimport { useClusterNodes as useClusterNodesHook } from '../hooks/use-cluster-nodes'\nimport type { TranslationFn } from './config-form-builder'\nimport { resolveLabel } from './config-form-builder'\nimport { useCustomFieldRenderer } from '../contexts/custom-field-renderers'\nimport { useConfirm } from './confirm-dialog'\nimport { useDeviceId } from '../contexts/device-context'\nimport { WidgetSlot } from './widget-slot'\n\n/** Probe state for a single field — exported for callers that need to track probe lifecycle externally. */\nexport interface ProbeState {\n status: 'probing' | 'ok' | 'error'\n result?: FieldProbeResult\n}\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\ninterface FormFieldProps {\n field: ConfigField\n values: Record<string, unknown>\n onChange: (key: string, value: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n /**\n * Dedicated probe callback — used by the device-creation dialog where\n * the device doesn't exist yet so the generic `onAction` routing\n * cannot resolve an addon owner. For existing-device forms prefer\n * `onAction` with action `'test-probe'`: the probe field falls back\n * to it when `onTestField` is absent, so the two paths converge.\n */\n onTestField?: (key: string, value: unknown) => Promise<FieldProbeResult>\n /** External probe result (from \"Test All\" button) */\n externalProbe?: { status: 'probing' | 'ok' | 'error'; result?: FieldProbeResult }\n /**\n * Inline-action callback. Fired by icon buttons on any field\n * (copy-value, regenerate-rtsp-token, …) and by the probe field's\n * Test button when `onTestField` is not provided — in that case the\n * action name is `'test-probe'` and the current field value flows\n * through the third arg so the handler can probe it.\n *\n * Returns `Promise<unknown>` (not `void`) because some actions yield\n * a result the caller wants (the probe returns a `FieldProbeResult`).\n */\n onAction?: (action: string, key: string, value?: unknown) => Promise<unknown>\n /** All fields in the section — used to resolve defaults for showWhen conditions */\n allFields?: readonly ConfigField[]\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst INPUT_CLASS =\n 'w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none disabled:opacity-50 disabled:cursor-not-allowed'\n\nconst LABEL_CLASS = 'block text-[11px] font-medium text-foreground mb-1'\nconst DESC_CLASS = 'text-[10px] text-foreground-subtle mt-0.5'\n\nfunction FieldWrapper({\n label,\n description,\n required,\n span,\n children,\n translationFn,\n}: {\n label?: string\n description?: string\n required?: boolean\n span?: number\n children: React.ReactNode\n translationFn?: TranslationFn\n}) {\n const colSpanClass =\n span === 2\n ? 'col-span-2'\n : span === 3\n ? 'col-span-3'\n : span === 4\n ? 'col-span-4'\n : 'col-span-1'\n\n const resolvedLabel = resolveLabel(label, translationFn)\n const resolvedDescription = resolveLabel(description, translationFn)\n\n // Treat empty-string labels as \"no label\" so the `<label>` element\n // doesn't occupy a header row that would push the input down (which\n // breaks alignment with sibling controls — notably the trailing\n // delete button on `multiple`-field rows, which needs to sit next\n // to the input, not its empty header).\n const hasLabel = resolvedLabel !== undefined && resolvedLabel !== ''\n return (\n <div className={colSpanClass}>\n {hasLabel && (\n <label className={LABEL_CLASS}>\n {resolvedLabel}\n {required && <span className=\"text-danger ml-0.5\">*</span>}\n </label>\n )}\n {children}\n {resolvedDescription && <p className={DESC_CLASS}>{resolvedDescription}</p>}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Field renderers\n// ---------------------------------------------------------------------------\n\nfunction TextField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigTextField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <input\n type={field.inputType ?? 'text'}\n className={INPUT_CLASS}\n value={value === undefined || value === null ? '' : String(value)}\n placeholder={field.placeholder}\n maxLength={field.maxLength}\n pattern={field.pattern}\n disabled={disabled || field.disabled}\n onChange={(e) => onChange(e.target.value)}\n />\n </FieldWrapper>\n )\n}\n\nfunction NumberField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigNumberField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n // Local string state preserves mid-typing states (e.g. empty string, \"-\", \"0.\")\n // that a numeric parse would discard. Upstream value only syncs back when the\n // prop changes externally (initial load, programmatic reset) — not while the\n // field is focused, so a user's empty input isn't auto-filled with 0.\n const [local, setLocal] = useState<string>(value === undefined || value === null ? '' : String(value))\n const focusedRef = useRef(false)\n\n useEffect(() => {\n if (focusedRef.current) return\n const next = value === undefined || value === null ? '' : String(value)\n setLocal(next)\n }, [value])\n\n const handleChange = (raw: string): void => {\n setLocal(raw)\n if (raw === '' || raw === '-') {\n onChange(undefined)\n return\n }\n const parsed = Number(raw)\n if (Number.isNaN(parsed)) return\n onChange(parsed)\n }\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"flex items-center gap-1\">\n <input\n type=\"number\"\n className={INPUT_CLASS}\n value={local}\n placeholder={field.placeholder}\n min={field.min}\n max={field.max}\n step={field.step}\n disabled={disabled || field.disabled}\n onFocus={() => { focusedRef.current = true }}\n onBlur={() => { focusedRef.current = false }}\n onChange={(e) => handleChange(e.target.value)}\n />\n {field.unit && (\n <span className=\"text-xs text-foreground-subtle whitespace-nowrap\">{field.unit}</span>\n )}\n </div>\n </FieldWrapper>\n )\n}\n\nfunction BooleanField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigBooleanField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const checked = Boolean(value)\n const isDisabled = disabled || field.disabled\n\n if (field.style === 'checkbox') {\n return (\n <FieldWrapper label={undefined} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <label className=\"flex items-center gap-2 cursor-pointer select-none\">\n <input\n type=\"checkbox\"\n className=\"h-3.5 w-3.5 rounded border-border accent-primary\"\n checked={checked}\n disabled={isDisabled}\n onChange={(e) => onChange(e.target.checked)}\n />\n <span className=\"text-xs font-medium text-foreground\">{resolveLabel(field.label, translationFn)}</span>\n {field.required && <span className=\"text-danger\">*</span>}\n </label>\n </FieldWrapper>\n )\n }\n\n // Default: toggle switch\n return (\n <FieldWrapper label={undefined} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"flex items-center justify-between\">\n <span className={LABEL_CLASS + ' mb-0'}>\n {resolveLabel(field.label, translationFn)}\n {field.required && <span className=\"text-danger ml-0.5\">*</span>}\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n disabled={isDisabled}\n onClick={() => !isDisabled && onChange(!checked)}\n className={[\n 'relative inline-flex h-4 w-8 shrink-0 items-center rounded-full transition-colors duration-150',\n checked ? 'bg-primary' : 'bg-foreground-subtle/30',\n isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n ].join(' ')}\n >\n <span\n className={[\n 'inline-block h-3 w-3 rounded-full bg-white shadow transition-transform duration-150',\n checked ? 'translate-x-4' : 'translate-x-0.5',\n ].join(' ')}\n />\n </button>\n </div>\n </FieldWrapper>\n )\n}\n\nfunction SelectField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigSelectField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n // Only prepend the placeholder when the schema's own options don't already\n // define a value=\"\" entry. Otherwise two options share the same value and\n // the DOM picks the placeholder over the schema's semantic option (e.g.\n // \"Auto (matches backend)\").\n const hasEmptyOption = field.options.some((o) => o.value === '')\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <select\n className={INPUT_CLASS}\n value={value === undefined || value === null ? '' : String(value)}\n disabled={disabled || field.disabled}\n onChange={(e) => onChange(e.target.value)}\n >\n {!field.required && !hasEmptyOption && <option value=\"\">— Select —</option>}\n {field.options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </FieldWrapper>\n )\n}\n\nfunction MultiSelectField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigMultiSelectField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const selected = Array.isArray(value) ? (value as string[]) : []\n\n const toggle = (optValue: string) => {\n if (selected.includes(optValue)) {\n onChange(selected.filter((v) => v !== optValue))\n } else {\n if (field.maxItems !== undefined && selected.length >= field.maxItems) return\n onChange([...selected, optValue])\n }\n }\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"flex flex-wrap gap-2\">\n {field.options.map((opt) => {\n const checked = selected.includes(opt.value)\n return (\n <label\n key={opt.value}\n className={[\n 'flex items-center gap-1.5 rounded-md border px-2 py-1 text-xs cursor-pointer select-none transition-colors',\n checked\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border bg-background text-foreground hover:bg-surface',\n (disabled || field.disabled) ? 'opacity-50 cursor-not-allowed' : '',\n ].join(' ')}\n >\n <input\n type=\"checkbox\"\n className=\"sr-only\"\n checked={checked}\n disabled={disabled || field.disabled}\n onChange={() => toggle(opt.value)}\n />\n {opt.label}\n </label>\n )\n })}\n </div>\n </FieldWrapper>\n )\n}\n\nfunction PasswordField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigPasswordField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const [show, setShow] = useState(false)\n const showToggle = field.showToggle !== false\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"relative\">\n <input\n type={show ? 'text' : 'password'}\n className={INPUT_CLASS + (showToggle ? ' pr-9' : '')}\n value={value === undefined || value === null ? '' : String(value)}\n placeholder={field.placeholder}\n disabled={disabled || field.disabled}\n onChange={(e) => onChange(e.target.value)}\n />\n {showToggle && (\n <button\n type=\"button\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground\"\n tabIndex={-1}\n onClick={() => setShow((s) => !s)}\n >\n {show ? <EyeOff className=\"h-3.5 w-3.5\" /> : <Eye className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n </div>\n </FieldWrapper>\n )\n}\n\nfunction TextAreaField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigTextAreaField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <textarea\n className={INPUT_CLASS + ' resize-y min-h-[60px]'}\n value={value === undefined || value === null ? '' : String(value)}\n placeholder={field.placeholder}\n rows={field.rows ?? 3}\n maxLength={field.maxLength}\n disabled={disabled || field.disabled}\n onChange={(e) => onChange(e.target.value)}\n />\n </FieldWrapper>\n )\n}\n\nfunction SliderField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigSliderField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const isNull = value === undefined || value === null\n const isNullable = field.nullable === true\n const numVal = isNull ? (field.default ?? field.min) : Number(value)\n const showValue = field.showValue !== false\n const nullLabel = field.nullLabel ?? 'Auto'\n const isDisabled = disabled || field.disabled\n const scale = field.displayScale ?? 1\n // Display values: convert stored value for UI (e.g., 10000ms → 10s)\n const displayMin = field.min / scale\n const displayMax = field.max / scale\n const displayVal = numVal / scale\n const displayStep = (field.step ?? 1) / scale\n\n // When nullable and value is null, show \"Auto\" toggle state\n if (isNullable && isNull) {\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <button\n className=\"w-full rounded-lg border border-dashed border-border px-3 py-2 text-xs text-foreground-subtle hover:border-primary/40 hover:text-primary transition-colors text-left\"\n disabled={isDisabled}\n onClick={() => onChange(field.default ?? field.min)}\n >\n {nullLabel} — click to set manually\n </button>\n </FieldWrapper>\n )\n }\n\n const stepperEnabled = field.showStepper === true && showValue\n const bumpBy = (deltaUnits: number): void => {\n // Step is in display units; multiply by `scale` to recover stored value.\n const next = numVal + deltaUnits * (field.step ?? 1)\n const clamped = Math.min(field.max, Math.max(field.min, next))\n if (clamped === numVal) return\n onChange(clamped)\n }\n const stepperBtnClass =\n 'flex h-6 w-6 shrink-0 items-center justify-center rounded border border-border bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors disabled:cursor-not-allowed disabled:opacity-40'\n\n // Two responsive sub-rows: the slider track (with min/max bookends)\n // and the value controls (steppers + number input + unit + nullable\n // reset). The outer flex wraps when the container is too narrow for\n // both groups on one line — typical when the form uses `columns: 2`\n // in a split-view panel. Each sub-row is `flex-shrink-0` so its own\n // contents stay together; only the inter-group break wraps.\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-2\">\n <div className=\"flex min-w-0 flex-1 basis-[160px] items-center gap-2\">\n <span className=\"text-[10px] text-foreground-subtle tabular-nums shrink-0\">{displayMin}</span>\n <input\n type=\"range\"\n className=\"min-w-0 flex-1 h-1 accent-primary cursor-pointer disabled:opacity-50\"\n min={displayMin}\n max={displayMax}\n step={displayStep}\n value={displayVal}\n disabled={isDisabled}\n onChange={(e) => onChange(Number(e.target.value) * scale)}\n />\n <span className=\"text-[10px] text-foreground-subtle tabular-nums shrink-0\">{displayMax}</span>\n </div>\n {(showValue || isNullable || field.unit) && (\n <div className=\"flex shrink-0 items-center gap-2\">\n {stepperEnabled && (\n <button\n type=\"button\"\n className={stepperBtnClass}\n disabled={isDisabled || numVal <= field.min}\n onClick={() => bumpBy(-1)}\n title={`Decrease by ${field.step ?? 1}`}\n aria-label=\"Decrement\"\n >\n <Minus className=\"h-3 w-3\" />\n </button>\n )}\n {showValue && (\n <input\n type=\"number\"\n className=\"w-16 rounded border border-border bg-surface px-1.5 py-0.5 text-xs text-center text-foreground tabular-nums focus:outline-none focus:ring-1 focus:ring-primary\"\n min={displayMin}\n max={displayMax}\n step={displayStep}\n value={displayVal}\n disabled={isDisabled}\n onChange={(e) => {\n if (e.target.value === '') { onChange(isNullable ? null : field.min); return }\n const raw = Number(e.target.value) * scale\n // Snap to the closest valid step so the discrete-grid contract\n // declared by `step` holds end-to-end (range thumb already\n // snaps natively; the number input would otherwise accept\n // arbitrary values like `25` when step=20).\n const stepUnits = field.step ?? 1\n const offset = raw - field.min\n const snapped = field.min + Math.round(offset / stepUnits) * stepUnits\n onChange(Math.min(field.max, Math.max(field.min, snapped)))\n }}\n />\n )}\n {stepperEnabled && (\n <button\n type=\"button\"\n className={stepperBtnClass}\n disabled={isDisabled || numVal >= field.max}\n onClick={() => bumpBy(1)}\n title={`Increase by ${field.step ?? 1}`}\n aria-label=\"Increment\"\n >\n <Plus className=\"h-3 w-3\" />\n </button>\n )}\n {field.unit && <span className=\"text-[10px] text-foreground-subtle\">{field.unit}</span>}\n {isNullable && (\n <button\n className=\"text-[10px] text-foreground-subtle hover:text-primary transition-colors\"\n title={`Reset to ${nullLabel}`}\n disabled={isDisabled}\n onClick={() => onChange(null)}\n >\n {nullLabel}\n </button>\n )}\n </div>\n )}\n </div>\n </FieldWrapper>\n )\n}\n\nfunction TagsField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigTagsField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const tags = Array.isArray(value) ? (value as string[]) : []\n const [input, setInput] = useState('')\n const inputRef = useRef<HTMLInputElement>(null)\n\n const addTag = useCallback(\n (tag: string) => {\n const trimmed = tag.trim()\n if (!trimmed || tags.includes(trimmed)) return\n if (field.maxTags !== undefined && tags.length >= field.maxTags) return\n onChange([...tags, trimmed])\n setInput('')\n },\n [tags, field.maxTags, onChange],\n )\n\n const removeTag = (tag: string) => onChange(tags.filter((t) => t !== tag))\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault()\n addTag(input)\n } else if (e.key === 'Backspace' && input === '' && tags.length > 0) {\n removeTag(tags[tags.length - 1]!)\n }\n }\n\n const isDisabled = disabled || field.disabled\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div\n className={[\n 'flex flex-wrap gap-1.5 rounded-md border border-border bg-background px-2 py-1.5 min-h-[38px] cursor-text',\n 'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/30',\n isDisabled ? 'opacity-50 cursor-not-allowed' : '',\n ].join(' ')}\n onClick={() => !isDisabled && inputRef.current?.focus()}\n >\n {tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-md bg-primary/10 px-1.5 py-0.5 text-xs text-primary\"\n >\n {tag}\n {!isDisabled && (\n <button type=\"button\" onClick={() => removeTag(tag)} className=\"hover:text-danger\">\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </span>\n ))}\n <input\n ref={inputRef}\n type=\"text\"\n className=\"flex-1 min-w-[80px] bg-transparent text-sm text-foreground outline-none placeholder:text-foreground-disabled\"\n value={input}\n placeholder={tags.length === 0 ? (field.placeholder ?? 'Add tags…') : ''}\n disabled={isDisabled}\n list={`tags-suggestions-${field.key}`}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n onBlur={() => { if (input.trim()) addTag(input) }}\n />\n {field.suggestions && (\n <datalist id={`tags-suggestions-${field.key}`}>\n {field.suggestions.map((s) => (\n <option key={s} value={s} />\n ))}\n </datalist>\n )}\n </div>\n </FieldWrapper>\n )\n}\n\nexport function NodeSelectField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigNodeSelectField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const { nodes } = useClusterNodesHook()\n const current = typeof value === 'string' ? value : ''\n const filtered = field.showOffline ? nodes : nodes.filter(n => n.isOnline)\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <select\n className=\"w-full px-3 py-2 text-sm bg-background border border-border rounded-lg text-foreground focus:outline-none focus:border-primary/50 disabled:opacity-50\"\n value={current}\n onChange={(e) => onChange(e.target.value)}\n disabled={disabled}\n >\n <option value=\"\">Select node…</option>\n {filtered.map((n) => (\n <option key={n.id} value={n.id} disabled={!n.isOnline}>\n {n.shortName}{!n.isOnline ? ' (offline)' : ''}\n </option>\n ))}\n </select>\n </FieldWrapper>\n )\n}\n\nexport function NodeMultiSelectField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigNodeMultiSelectField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const { nodes } = useClusterNodesHook()\n const selected = new Set(Array.isArray(value) ? value.map(String) : [])\n const filtered = field.showOffline ? nodes : nodes.filter(n => n.isOnline)\n const toggle = (id: string) => {\n const next = new Set(selected)\n if (next.has(id)) next.delete(id); else next.add(id)\n onChange([...next])\n }\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"flex flex-wrap gap-1.5\">\n {filtered.map((n) => {\n const isOn = selected.has(n.id)\n return (\n <button\n key={n.id}\n type=\"button\"\n onClick={() => toggle(n.id)}\n disabled={disabled || !n.isOnline}\n className={`px-2.5 py-1 text-xs font-medium rounded-md border transition-colors ${\n isOn\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border bg-surface text-foreground-subtle hover:bg-surface-hover'\n } ${!n.isOnline ? 'opacity-50 cursor-not-allowed' : ''}`}\n >\n {n.shortName}\n </button>\n )\n })}\n </div>\n </FieldWrapper>\n )\n}\n\nfunction ColorField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n}: {\n field: ConfigColorField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n}) {\n const strVal = value === undefined || value === null ? '#000000' : String(value)\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"color\"\n className=\"h-9 w-9 rounded-md border border-border bg-background cursor-pointer p-0.5 disabled:opacity-50\"\n value={strVal}\n disabled={disabled || field.disabled}\n onChange={(e) => onChange(e.target.value)}\n />\n <input\n type=\"text\"\n className={INPUT_CLASS + ' flex-1 font-mono'}\n value={strVal}\n placeholder=\"#000000\"\n disabled={disabled || field.disabled}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n {field.presets && field.presets.length > 0 && (\n <div className=\"flex gap-1.5 mt-1.5\">\n {field.presets.map((preset) => (\n <button\n key={preset}\n type=\"button\"\n className=\"h-5 w-5 rounded-md border border-border hover:scale-110 transition-transform disabled:opacity-50\"\n style={{ backgroundColor: preset }}\n disabled={disabled || field.disabled}\n title={preset}\n onClick={() => onChange(preset)}\n />\n ))}\n </div>\n )}\n </FieldWrapper>\n )\n}\n\nfunction ProbeField({\n field,\n value,\n onChange,\n disabled,\n translationFn,\n onTestField,\n onAction,\n externalProbe,\n}: {\n field: ConfigProbeField\n value: unknown\n onChange: (v: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n onTestField?: (key: string, value: unknown) => Promise<FieldProbeResult>\n onAction?: (action: string, key: string, value?: unknown) => Promise<unknown>\n externalProbe?: { status: 'probing' | 'ok' | 'error'; result?: FieldProbeResult }\n}) {\n const [localStatus, setLocalStatus] = useState<'idle' | 'probing' | 'ok' | 'error'>('idle')\n const [localResult, setLocalResult] = useState<FieldProbeResult | null>(null)\n\n // External probe (from \"Test All\") takes precedence over local state\n const probeStatus = externalProbe?.status ?? localStatus\n const probeResult = externalProbe?.result ?? localResult\n\n // Prefer the dedicated `onTestField` (creation dialog) when present —\n // its signature matches directly. Otherwise fall back to the generic\n // inline-action pipe via `onAction('test-probe', key, value)` so the\n // device-settings page unifies probing with its other actions\n // (copy-value, regenerate-rtsp-token).\n const hasTestHandler = !!onTestField || !!onAction\n\n const handleTest = useCallback(async () => {\n if (!hasTestHandler) return\n setLocalStatus('probing')\n setLocalResult(null)\n try {\n const result = onTestField\n ? await onTestField(field.key, value)\n : ((await onAction!('test-probe', field.key, value)) as FieldProbeResult | undefined)\n const safeResult: FieldProbeResult = result && typeof result === 'object'\n ? result\n : { status: 'error', error: 'Probe handler returned no result' }\n setLocalResult(safeResult)\n setLocalStatus(safeResult.status === 'ok' ? 'ok' : 'error')\n } catch (err) {\n setLocalResult({ status: 'error', error: err instanceof Error ? err.message : String(err) })\n setLocalStatus('error')\n }\n }, [onTestField, onAction, field.key, value, hasTestHandler])\n\n // Button styling per probe status — the test button IS the\n // status indicator, so it changes color + icon to reflect probe\n // state. Idle = neutral border (default look). Probing = primary\n // tint + spinner. OK = success tint + checkmark. Error = danger\n // tint + alert. The standalone status icon to the left of the\n // input is gone — the button color carries that signal.\n const buttonStateClass =\n probeStatus === 'probing'\n ? 'border-primary/40 bg-primary/10 text-primary'\n : probeStatus === 'ok'\n ? 'border-success/40 bg-success/10 text-success hover:bg-success/15'\n : probeStatus === 'error'\n ? 'border-danger/40 bg-danger/10 text-danger hover:bg-danger/15'\n : 'border-border text-foreground-subtle hover:text-foreground hover:bg-surface-hover'\n const buttonIcon =\n probeStatus === 'probing'\n ? <Loader2 className=\"h-3 w-3 animate-spin\" />\n : probeStatus === 'ok'\n ? <CheckCircle className=\"h-3 w-3\" />\n : probeStatus === 'error'\n ? <AlertCircle className=\"h-3 w-3\" />\n : <Wifi className=\"h-3 w-3\" />\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span} translationFn={translationFn}>\n <div\n className=\"@container flex items-center gap-2\"\n style={{ containerType: 'inline-size' }}\n >\n <button\n type=\"button\"\n onClick={handleTest}\n title=\"Test\"\n // Probe is orthogonal to save/edit disabling: a user wants to\n // verify an RTSP URL even while a batch save is mid-flight, so\n // we don't gate on the parent `disabled`. Only the field's own\n // `field.disabled`, an in-flight probe, a missing value, or\n // having neither handler can lock it out.\n disabled={field.disabled || probeStatus === 'probing' || !hasTestHandler || !value}\n className={`flex-shrink-0 inline-flex items-center gap-1.5 rounded-md border px-2 py-2 text-xs font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed @[280px]:px-3 ${buttonStateClass}`}\n >\n {buttonIcon}\n {/* Label only when the FIELD CELL is wide enough to fit\n button + input comfortably (~280px). Below that the\n status icon + button color carry the affordance. */}\n <span className=\"hidden @[280px]:inline\">Test</span>\n </button>\n <input\n type={field.inputType ?? 'url'}\n className={INPUT_CLASS + ' flex-1 min-w-0'}\n value={value === undefined || value === null ? '' : String(value)}\n placeholder={field.placeholder}\n disabled={disabled || field.disabled}\n onChange={(e) => {\n onChange(e.target.value)\n // Reset local probe state when input changes\n if (localStatus !== 'idle') {\n setLocalStatus('idle')\n setLocalResult(null)\n }\n }}\n />\n </div>\n {/* Success: show label chips */}\n {probeStatus === 'ok' && probeResult?.labels && probeResult.labels.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mt-1.5\">\n {probeResult.labels.map((label, i) => (\n <span\n key={i}\n className=\"text-xs bg-success/10 text-success rounded px-2 py-0.5 font-mono\"\n >\n {label}\n </span>\n ))}\n </div>\n )}\n {/* Error: show error message */}\n {probeStatus === 'error' && probeResult?.error && (\n <p className=\"text-xs text-danger mt-1 truncate\" title={probeResult.error}>\n {probeResult.error}\n </p>\n )}\n </FieldWrapper>\n )\n}\n\nfunction GroupField({\n field,\n values,\n onChange,\n disabled,\n translationFn,\n onTestField,\n}: {\n field: ConfigGroupField\n values: Record<string, unknown>\n onChange: (key: string, value: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n onTestField?: (key: string, value: unknown) => Promise<FieldProbeResult>\n}) {\n const [collapsed, setCollapsed] = useState(field.defaultCollapsed ?? false)\n const isAccordion = field.style === 'accordion'\n\n const colSpanClass =\n field.span === 2\n ? 'col-span-2'\n : field.span === 3\n ? 'col-span-3'\n : field.span === 4\n ? 'col-span-4'\n : 'col-span-1'\n\n return (\n <div className={colSpanClass}>\n <div className=\"rounded-lg border border-border bg-surface/50 overflow-hidden\">\n <div\n className={[\n 'px-3 py-2 flex items-center justify-between',\n isAccordion ? 'cursor-pointer hover:bg-surface' : '',\n ].join(' ')}\n onClick={isAccordion ? () => setCollapsed((c) => !c) : undefined}\n >\n <span className=\"text-xs font-semibold text-foreground\">{resolveLabel(field.label, translationFn)}</span>\n {isAccordion && (\n <span className=\"text-foreground-subtle text-xs\">{collapsed ? '▸' : '▾'}</span>\n )}\n </div>\n {!collapsed && (\n <div className=\"px-3 pb-3 grid grid-cols-2 gap-x-4 gap-y-3\">\n {field.fields.map((subField) => (\n <FormField\n key={subField.key}\n field={subField}\n values={values}\n onChange={onChange}\n disabled={disabled}\n translationFn={translationFn}\n onTestField={onTestField}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nfunction SubTabsField({\n field,\n values,\n onChange,\n disabled,\n translationFn,\n onTestField,\n onAction,\n}: {\n field: ConfigSubTabsField\n values: Record<string, unknown>\n onChange: (key: string, value: unknown) => void\n disabled?: boolean\n translationFn?: TranslationFn\n onTestField?: (key: string, value: unknown) => Promise<FieldProbeResult>\n onAction?: (action: string, key: string, value?: unknown) => Promise<unknown>\n}) {\n const firstId = field.tabs[0]?.id ?? ''\n const [active, setActive] = useState<string>(firstId)\n\n const colSpanClass =\n field.span === 2\n ? 'col-span-2'\n : field.span === 3\n ? 'col-span-3'\n : field.span === 4\n ? 'col-span-4'\n : 'col-span-1'\n\n if (field.tabs.length === 0) return null\n\n // Distinct visual treatment from the page-level tab bar:\n // - chip-shaped triggers laid out in a wrapping flex (no scrolling)\n // - active state uses solid primary background instead of an\n // underline so it reads as \"secondary nav inside this section\"\n // rather than another top-level tab bar\n // - container framed with a subdued border + background tint\n return (\n <div className={colSpanClass}>\n {field.label && (\n <div className={LABEL_CLASS}>{resolveLabel(field.label, translationFn)}</div>\n )}\n <div className=\"rounded-lg border border-border-subtle bg-surface-hover/40 overflow-hidden\">\n <div className=\"flex flex-wrap gap-1 p-1.5 border-b border-border-subtle bg-surface/40\" role=\"tablist\">\n {field.tabs.map((t) => {\n const isActive = t.id === active\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n onClick={() => setActive(t.id)}\n className={`inline-flex items-center gap-1.5 whitespace-nowrap rounded-md px-2.5 py-1 text-[11px] transition-colors ${\n isActive\n ? 'bg-primary text-primary-foreground font-medium shadow-sm'\n : 'bg-transparent text-foreground-subtle hover:bg-surface hover:text-foreground'\n }`}\n >\n <span>{resolveLabel(t.label, translationFn)}</span>\n {t.badge && (\n <span\n className={`text-[9px] px-1 py-0.5 rounded-full font-medium ${\n isActive\n ? 'bg-primary-foreground/20 text-primary-foreground'\n : 'bg-primary/10 text-primary'\n }`}\n >\n {t.badge}\n </span>\n )}\n </button>\n )\n })}\n </div>\n {field.tabs.map((t) => {\n if (t.id !== active) return null\n return (\n <div key={t.id} role=\"tabpanel\" className=\"px-3 pb-3 pt-2 grid grid-cols-2 gap-x-4 gap-y-3\">\n {t.fields.map((subField, idx) => {\n const stableKey = 'key' in subField && typeof subField.key === 'string'\n ? subField.key\n : `__${t.id}__${idx}`\n return (\n <FormField\n key={stableKey}\n field={subField}\n values={values}\n onChange={onChange}\n disabled={disabled}\n translationFn={translationFn}\n onTestField={onTestField}\n onAction={onAction}\n />\n )\n })}\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n\n// `model-selector` field type is no longer rendered natively — host\n// apps register a renderer via `<CustomFieldRenderersProvider>` that\n// can talk to the model catalog cap (admin-ui:\n// `components/form-builder/ModelSelector` adapter). Without a registered\n// renderer the field falls through `default:` and renders nothing.\n\nfunction SeparatorField({ span }: { span?: number }) {\n const colSpanClass =\n span === 2\n ? 'col-span-2'\n : span === 3\n ? 'col-span-3'\n : span === 4\n ? 'col-span-4'\n : 'col-span-full'\n\n return (\n <div className={colSpanClass}>\n <hr className=\"border-border\" />\n </div>\n )\n}\n\nconst INFO_VARIANT_STYLES: Record<string, { border: string; bg: string; text: string }> = {\n info: { border: 'border-info', bg: 'bg-info/5', text: 'text-info' },\n warning: { border: 'border-warning', bg: 'bg-warning/5', text: 'text-warning' },\n success: { border: 'border-success', bg: 'bg-success/5', text: 'text-success' },\n danger: { border: 'border-danger', bg: 'bg-danger/5', text: 'text-danger' },\n}\n\nfunction InfoBox({ field }: { field: ConfigInfoField }) {\n const variant = field.variant ?? 'info'\n const styles = INFO_VARIANT_STYLES[variant] ?? INFO_VARIANT_STYLES['info']!\n\n return (\n <div className=\"col-span-full\">\n <div className={`rounded-md border-l-4 px-3 py-2.5 ${styles.border} ${styles.bg}`}>\n {field.label && (\n <p className={`text-xs font-semibold mb-0.5 ${styles.text}`}>{field.label}</p>\n )}\n <p className=\"text-xs text-foreground-subtle leading-relaxed\">{field.content}</p>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Object Array (readonly diagnostic table)\n// ---------------------------------------------------------------------------\n\nconst STATUS_DOT_STYLES: Record<string, string> = {\n ok: 'bg-success',\n warn: 'bg-amber-500',\n danger: 'bg-danger',\n idle: 'bg-foreground-subtle/40',\n unknown: 'bg-foreground-subtle/40',\n}\n\nfunction formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '—'\n if (ms < 1000) return `${ms}ms`\n const totalSec = Math.round(ms / 1000)\n if (totalSec < 60) return `${totalSec}s`\n const m = Math.floor(totalSec / 60)\n const s = totalSec % 60\n return s === 0 ? `${m}m` : `${m}m ${s}s`\n}\n\nfunction formatTimestamp(ms: number): string {\n if (!Number.isFinite(ms) || ms <= 0) return '—'\n return new Date(ms).toLocaleTimeString()\n}\n\nfunction ObjectArrayCell({\n kind,\n value,\n}: {\n kind?: ConfigObjectArrayField['columns'][number]['kind']\n value: unknown\n}) {\n if (value === null || value === undefined || value === '') {\n return <span className=\"text-foreground-subtle/60\">—</span>\n }\n if (kind === 'monospace') {\n return <span className=\"font-mono text-[11px]\">{String(value)}</span>\n }\n if (kind === 'status') {\n const k = String(value).toLowerCase()\n const dot = STATUS_DOT_STYLES[k] ?? STATUS_DOT_STYLES['unknown']!\n return (\n <span className=\"inline-flex items-center gap-1.5\">\n <span className={`inline-block h-1.5 w-1.5 rounded-full ${dot}`} />\n <span>{String(value)}</span>\n </span>\n )\n }\n if (kind === 'duration' && typeof value === 'number') {\n return <span className=\"font-mono text-[11px]\">{formatDuration(value)}</span>\n }\n if (kind === 'timestamp' && typeof value === 'number') {\n return <span className=\"font-mono text-[11px]\">{formatTimestamp(value)}</span>\n }\n return <span>{String(value)}</span>\n}\n\nfunction ObjectArrayField({ field }: { field: ConfigObjectArrayField }) {\n const rows = field.value ?? []\n const description = field.description\n return (\n <div className=\"col-span-full\">\n {field.label && (\n <p className=\"text-[11px] font-semibold uppercase tracking-wider text-foreground-subtle mb-1\">\n {field.label}\n </p>\n )}\n {description && (\n <p className=\"text-xs text-foreground-subtle mb-2\">{description}</p>\n )}\n {rows.length === 0 ? (\n <div className=\"rounded-md border border-border bg-surface-subtle px-3 py-2 text-xs text-foreground-subtle\">\n {field.emptyMessage ?? 'No entries'}\n </div>\n ) : (\n <div className=\"rounded-md border border-border overflow-hidden\">\n <table className=\"w-full text-xs\">\n <thead className=\"bg-surface-subtle border-b border-border\">\n <tr>\n {field.columns.map((col) => (\n <th\n key={col.key}\n className=\"px-3 py-1.5 text-left font-medium text-foreground-subtle\"\n style={col.width ? { width: col.width } : undefined}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {rows.map((row, i) => (\n <tr key={i} className=\"hover:bg-surface-hover/40\">\n {field.columns.map((col) => (\n <td key={col.key} className=\"px-3 py-1.5 align-top text-foreground\">\n <ObjectArrayCell kind={col.kind} value={row[col.key]} />\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Button\n// ---------------------------------------------------------------------------\n\nfunction ButtonField({\n field,\n disabled,\n onAction,\n}: {\n readonly field: ConfigButtonField\n readonly disabled?: boolean\n readonly onAction?: (action: string, key: string, value?: unknown) => Promise<unknown>\n}) {\n const [loading, setLoading] = useState(false)\n const confirm = useConfirm()\n\n const handleClick = async () => {\n if (field.confirmMessage) {\n const ok = await confirm({\n title: field.label,\n message: field.confirmMessage,\n confirmLabel: field.buttonLabel,\n variant: field.variant === 'danger' ? 'danger' : 'default',\n })\n if (!ok) return\n }\n if (!onAction) return\n setLoading(true)\n try {\n await onAction(field.action, field.key)\n } finally {\n setLoading(false)\n }\n }\n\n const variantClasses: Record<string, string> = {\n default: 'border border-border text-foreground hover:bg-surface-hover',\n primary: 'bg-primary text-primary-foreground hover:bg-primary/90',\n danger: 'bg-danger text-white hover:bg-danger/90',\n }\n\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span}>\n <button\n onClick={handleClick}\n disabled={disabled || loading}\n className={`inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors disabled:opacity-50 ${\n variantClasses[field.variant ?? 'default'] ?? variantClasses['default']\n }`}\n >\n {loading ? 'Processing...' : field.buttonLabel}\n </button>\n </FieldWrapper>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Widget field — dispatches to <WidgetSlot> via the WidgetRegistry\n// ---------------------------------------------------------------------------\n//\n// Generic addon-widget mount point inside a settings/overview form. The\n// field declares the widget id (`<addonId>/<stableId>`) plus optional\n// per-instance config; deviceId is read from the current\n// `DeviceContext` so the field schema stays device-agnostic and addons\n// can ship static contributions.\n//\n// Replaces the legacy `'live-stats'` / `'zone-editor'` /\n// `'pipeline-stats'` / `'live-stream-viewer'` / `'stream-network-stats'`\n// / `'doorbell-recent'` / `'device-info'` bespoke field types. New\n// addon contributions should declare `type: 'widget'` and ship their\n// React code through `addon-widgets-source` instead of registering a\n// custom field renderer.\nfunction WidgetField({ field }: { readonly field: ConfigWidgetField }) {\n const deviceId = useDeviceId()\n return (\n <FieldWrapper label={field.label} description={field.description} required={field.required} span={field.span}>\n <WidgetSlot\n widgetId={field.widgetId}\n host=\"device-tab\"\n config={field.widgetConfig}\n deviceId={deviceId ?? undefined}\n instanceId={field.key}\n />\n </FieldWrapper>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Readonly display field (aggregator live contributions)\n// ---------------------------------------------------------------------------\n\nfunction formatReadonlyValue(value: unknown, unit?: string): string {\n if (value === null || value === undefined) return '—'\n if (typeof value === 'boolean') return value ? 'yes' : 'no'\n if (typeof value === 'number') {\n const formatted = Number.isInteger(value) ? String(value) : value.toFixed(2)\n return unit ? `${formatted} ${unit}` : formatted\n }\n if (typeof value === 'string') return value\n return JSON.stringify(value)\n}\n\nfunction ReadonlyDisplay({\n field,\n values,\n onAction,\n translationFn,\n}: {\n field: ConfigField\n values: Record<string, unknown>\n onAction?: (action: string, key: string, value?: unknown) => Promise<unknown>\n translationFn?: TranslationFn\n}) {\n const rawKey = 'key' in field ? field.key : undefined\n if (!rawKey) return null\n const rawValue = values[rawKey]\n const resolved = rawValue !== undefined ? rawValue : ('default' in field ? field.default : undefined)\n const unit = 'unit' in field ? (field as { unit?: string }).unit : undefined\n const display = formatReadonlyValue(resolved, unit)\n const label = 'label' in field ? field.label : undefined\n const description = 'description' in field ? field.description : undefined\n const span = 'span' in field ? (field as { span?: number }).span : undefined\n const actions = 'actions' in field ? (field as { actions?: readonly FieldInlineAction[] }).actions ?? [] : []\n\n return (\n <FieldWrapper label={label} description={description} span={span} translationFn={translationFn}>\n <div className=\"flex items-stretch gap-1\">\n <div className=\"flex-1 rounded-md border border-border bg-surface-alt px-2.5 py-1.5 text-xs text-foreground font-mono break-all\">\n {display}\n </div>\n {actions.length > 0 && (\n <div className=\"flex items-center gap-1\">\n {actions.map((a) => (\n <InlineActionIcon\n key={a.action}\n action={a}\n fieldKey={rawKey}\n value={resolved}\n onAction={onAction}\n />\n ))}\n </div>\n )}\n </div>\n </FieldWrapper>\n )\n}\n\n/**\n * Small lookup mapping icon ids emitted by addons to Lucide components.\n * Kept explicit (rather than a dynamic dictionary from `lucide-react`)\n * so the bundle only pulls in the icons we actually advertise. Unknown\n * icons fall back to a neutral wrench glyph.\n */\nfunction InlineIconGlyph({ name }: { readonly name: string }): React.ReactElement {\n const cls = 'h-3.5 w-3.5'\n switch (name) {\n case 'copy': return <Copy className={cls} />\n case 'refresh-cw': return <RefreshCw className={cls} />\n case 'external-link': return <ExternalLink className={cls} />\n case 'trash-2': return <Trash2 className={cls} />\n case 'download': return <Download className={cls} />\n case 'upload': return <Upload className={cls} />\n default: return <Wrench className={cls} />\n }\n}\n\n/**\n * Compact icon button used inline on readonly fields (and — later — on\n * editable ones via the same `actions?: FieldInlineAction[]` slot).\n * Handles the `copy-value` action locally (writes the displayed value\n * to the clipboard) and forwards everything else to the shared\n * `onAction(action, key)` pipeline the rest of the FormBuilder uses.\n * Keeps the button-field + inline-icon code paths converged: a single\n * handler at the Device*Section level routes every action.\n */\nfunction InlineActionIcon({\n action,\n fieldKey,\n value,\n onAction,\n}: {\n action: FieldInlineAction\n fieldKey: string\n value: unknown\n onAction?: (action: string, key: string, value?: unknown) => Promise<unknown>\n}) {\n const confirm = useConfirm()\n const [loading, setLoading] = useState(false)\n\n const variantClass =\n action.variant === 'danger'\n ? 'text-danger hover:bg-danger/10 border-danger/30'\n : action.variant === 'primary'\n ? 'text-primary hover:bg-primary/10 border-primary/30'\n : 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover border-border'\n\n const handleClick = async () => {\n if (action.confirmMessage) {\n const ok = await confirm({\n title: action.tooltip,\n message: action.confirmMessage,\n variant: action.variant === 'danger' ? 'danger' : 'default',\n })\n if (!ok) return\n }\n if (action.action === 'copy-value') {\n try {\n await navigator.clipboard.writeText(typeof value === 'string' ? value : String(value))\n } catch {\n /* clipboard unavailable — silently skip */\n }\n return\n }\n if (!onAction) return\n setLoading(true)\n try {\n await onAction(action.action, fieldKey)\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={loading}\n title={action.tooltip}\n className={`inline-flex items-center justify-center rounded-md border px-2 py-1.5 transition-colors disabled:opacity-50 ${variantClass}`}\n >\n <InlineIconGlyph name={action.icon} />\n </button>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Multiple-field wrapper — renders any scalar-valued field as an array\n// with per-item controls and a bounded +Add / Remove affordance.\n// ---------------------------------------------------------------------------\n\n/**\n * Any scalar-valued ConfigField carries ConfigFieldBase's full prop\n * surface (`key`, `label`, `multiple?`, `span?`, …). The structural\n * variants (`separator`, `info`) don't extend FieldBase and can't be\n * rendered as multiple. This predicate + its return type is what lets\n * `MultipleFieldWrapper` read `field.label` / spread the field without\n * TS erroring on the narrower shapes.\n */\ntype ConfigFieldWithMultiple = ConfigField & {\n readonly key: string\n readonly label: string\n readonly description?: string\n readonly required?: boolean\n readonly span?: 1 | 2 | 3 | 4\n readonly default?: unknown\n readonly multiple: NonNullable<Extract<ConfigField, { readonly multiple?: unknown }>['multiple']>\n}\n\nfunction hasMultiple(field: ConfigField): field is ConfigFieldWithMultiple {\n return 'multiple' in field && (field as { multiple?: unknown }).multiple != null\n}\n\nfunction MultipleFieldWrapper({\n field,\n values,\n onChange,\n disabled,\n translationFn,\n onTestField,\n externalProbe: _externalProbe,\n allFields,\n onAction,\n}: FormFieldProps & { field: ConfigFieldWithMultiple }) {\n const multiple = field.multiple\n const min = multiple.min\n const max = multiple.max\n\n const raw = values[field.key]\n const stored: readonly unknown[] = Array.isArray(raw) ? raw : (raw !== undefined && raw !== null ? [raw] : [])\n // Pad up to `min` so the user always sees at least the required slots.\n const items: unknown[] = [...stored]\n const itemFallback: unknown = multiple.itemDefault !== undefined\n ? multiple.itemDefault\n : ('default' in field && field.default !== undefined ? field.default : '')\n while (items.length < min) items.push(itemFallback)\n\n const update = (next: readonly unknown[]) => onChange(field.key, [...next])\n const setItem = (idx: number, v: unknown) => {\n const next = [...items]\n next[idx] = v\n update(next)\n }\n const addItem = () => {\n if (items.length >= max) return\n update([...items, itemFallback])\n }\n const removeItem = (idx: number) => {\n if (items.length <= min) return\n update(items.filter((_, i) => i !== idx))\n }\n\n // Strip `multiple` from the child so FormField renders the underlying\n // scalar control. Always clear the inner label — the outer wrapper\n // (below) now renders any `itemLabel` HEADER above the row so the\n // per-row input sits on the same horizontal line as the trailing\n // delete button. Previously the inner label carved a header slot\n // inside the flex child, pushing the input down and leaving the\n // delete button \"floating\" next to the label instead of the input.\n const makeChild = (): ConfigField => {\n const { multiple: _drop, ...rest } = field\n const overrides = { label: undefined, description: undefined, required: false }\n const child: unknown = { ...rest, ...overrides }\n return child as ConfigField\n }\n\n return (\n <FieldWrapper\n label={field.label}\n description={field.description}\n required={min > 0 ? field.required : false}\n span={field.span}\n translationFn={translationFn}\n >\n <div className=\"space-y-2\">\n {items.map((itemVal, idx) => {\n const itemLabel = multiple.itemLabel?.replace('${n}', String(idx + 1))\n return (\n <div key={idx} className=\"space-y-1\">\n {itemLabel && (\n <div className={LABEL_CLASS}>{itemLabel}</div>\n )}\n <div className=\"flex items-center gap-2\">\n <div className=\"flex-1 min-w-0\">\n <FormField\n field={makeChild()}\n // Inner FormField reads `values[field.key]` — project\n // the per-slot value under the SAME key so the scalar\n // renderer picks it up without a bespoke contract.\n values={{ ...values, [field.key]: itemVal }}\n onChange={(_k, v) => setItem(idx, v)}\n disabled={disabled}\n translationFn={translationFn}\n onTestField={onTestField}\n onAction={onAction}\n allFields={allFields}\n />\n </div>\n {items.length > min && (\n <button\n type=\"button\"\n onClick={() => removeItem(idx)}\n disabled={disabled}\n title=\"Remove\"\n className=\"flex-shrink-0 inline-flex items-center justify-center rounded-md border border-border p-1.5 text-foreground-subtle hover:text-danger hover:border-danger/50 transition-colors disabled:opacity-40\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n </div>\n )\n })}\n <div className=\"flex items-center justify-between pt-1\">\n {items.length < max ? (\n <button\n type=\"button\"\n onClick={addItem}\n disabled={disabled}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors disabled:opacity-40\"\n >\n <Plus className=\"h-3 w-3\" />\n {multiple.addLabel ?? 'Add'}\n </button>\n ) : <span />}\n <span className=\"text-[10px] text-foreground-subtle tabular-nums\">\n {items.length}/{max}\n </span>\n </div>\n </div>\n </FieldWrapper>\n )\n}\n\n// ---------------------------------------------------------------------------\n// showWhen evaluation\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a `ConfigCondition` against the form's flat values bag and the\n * sibling-field list (used to recover schema defaults when the\n * referenced field hasn't been touched yet). Returns `true` for fields\n * with no `showWhen` — i.e. always visible — and for fields whose\n * condition is missing a recognised operator (forward-compat: a future\n * operator added to `ConfigCondition` won't accidentally hide every\n * field on older clients).\n *\n * Exported so callers (FormBuilder section renderer, future\n * sub-tab visibility checks, …) can pre-evaluate which fields would be\n * rendered without instantiating a React subtree.\n */\nexport function isFieldVisible(\n field: ConfigField,\n values: Record<string, unknown>,\n allFields?: readonly ConfigField[],\n): boolean {\n if (!('showWhen' in field) || !field.showWhen) return true\n const condition = field.showWhen\n const rawCondVal = values[condition.field]\n const condField = allFields?.find((f): f is ConfigField & { key: string } => 'key' in f && f.key === condition.field)\n const condDefault = condField && 'default' in condField ? condField.default : undefined\n const condVal = rawCondVal !== undefined ? rawCondVal : condDefault\n\n if (condition.equals !== undefined) return condVal === condition.equals\n if (condition.notEquals !== undefined) return condVal !== condition.notEquals\n if (condition.in !== undefined) return condition.in.includes(condVal)\n if (condition.notIn !== undefined) return !condition.notIn.includes(condVal)\n if (condition.includes !== undefined) {\n return Array.isArray(condVal) && condVal.includes(condition.includes)\n }\n if (condition.notIncludes !== undefined) {\n return !Array.isArray(condVal) || !condVal.includes(condition.notIncludes)\n }\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Main FormField component\n// ---------------------------------------------------------------------------\n\nexport function FormField({ field, values, onChange, disabled, translationFn, onTestField, externalProbe, allFields, onAction }: FormFieldProps) {\n // Multiple-mode short-circuit: treat the field as a collection of its\n // primitive. The wrapper materialises each slot and re-enters\n // FormField with `multiple` stripped so the switch below picks the\n // underlying scalar renderer.\n if (hasMultiple(field)) {\n return (\n <MultipleFieldWrapper\n field={field}\n values={values}\n onChange={onChange}\n disabled={disabled}\n translationFn={translationFn}\n onTestField={onTestField}\n externalProbe={externalProbe}\n allFields={allFields}\n onAction={onAction}\n />\n )\n }\n\n // Device-aggregator readonlyField short-circuit — render a static display\n // so live/readonly contributions don't ship a focusable input the user\n // might accidentally interact with. The `readonlyField` flag is set by\n // the device-manager aggregator on live fields and on explicitly\n // readonly contributions (rtsp URL, agent assignment, ...).\n if ('readonlyField' in field && (field as { readonlyField?: boolean }).readonlyField === true) {\n return <ReadonlyDisplay field={field} values={values} onAction={onAction} translationFn={translationFn} />\n }\n\n // Evaluate showWhen via the shared helper so the section renderer can\n // pre-compute the same visibility (used to hide sections that would\n // collapse to zero visible fields).\n if (!isFieldVisible(field, values, allFields)) return null\n\n const rawValue = values[field.key]\n const value = rawValue !== undefined ? rawValue : ('default' in field ? field.default : undefined)\n const handleChange = (v: unknown) => onChange(field.key, v)\n\n // Custom-renderer dispatch — host apps register components for field\n // types ui-library doesn't natively render (e.g. `pipeline-editor`,\n // `zone-editor`). Hook fires unconditionally; only consulted on the\n // default branch so built-in cases retain priority.\n const customRenderer = useCustomFieldRenderer(field.type)\n\n switch (field.type) {\n case 'text':\n return <TextField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'number':\n return <NumberField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'boolean':\n return <BooleanField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'select':\n return <SelectField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'multiselect':\n return <MultiSelectField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'password':\n return <PasswordField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'textarea':\n return <TextAreaField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'slider':\n return <SliderField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'tags':\n return <TagsField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'color':\n return <ColorField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'node-select':\n return <NodeSelectField field={field as ConfigNodeSelectField} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'node-multiselect':\n return <NodeMultiSelectField field={field as ConfigNodeMultiSelectField} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} />\n case 'probe':\n return <ProbeField field={field} value={value} onChange={handleChange} disabled={disabled} translationFn={translationFn} onTestField={onTestField} onAction={onAction} externalProbe={externalProbe} />\n case 'group':\n return <GroupField field={field} values={values} onChange={onChange} disabled={disabled} translationFn={translationFn} onTestField={onTestField} />\n case 'sub-tabs':\n return <SubTabsField field={field} values={values} onChange={onChange} disabled={disabled} translationFn={translationFn} onTestField={onTestField} onAction={onAction} />\n case 'separator':\n return <SeparatorField />\n case 'info':\n return <InfoBox field={field} />\n case 'object-array':\n return <ObjectArrayField field={field} />\n case 'button':\n return <ButtonField field={field} disabled={disabled} onAction={onAction} />\n case 'widget':\n return <WidgetField field={field} />\n default: {\n if (customRenderer) {\n const Renderer = customRenderer\n return <Renderer field={field} value={value} onChange={handleChange} disabled={disabled} />\n }\n return null\n }\n }\n}\n\n// Backwards-compatible alias — the admin-ui FormBuilder used to\n// `import { FormField } from './FormField'`. After consolidation\n// it imports `FormField` from `@camstack/ui-library`; the original\n// `ConfigFormField` name is the stable canonical export, but `FormField`\n// is exported here to ease the migration without renaming every call site.\nexport { FormField as ConfigFormField }\n","/**\n * Custom field renderer registry.\n *\n * The ui-library's `config-form-field.tsx` switch handles built-in field\n * types (text, number, select, …). Field types declared in\n * `@camstack/types/interfaces/config-ui` that need heavy host-app\n * components (e.g. `zone-editor` → polygon canvas via konva) are\n * dispatched through this registry: a host app (admin-ui) wraps the\n * device-detail tree with `CustomFieldRenderersProvider`, supplying a\n * map of `field.type → React component`. The form renderer looks up\n * the type at the `default:` branch and renders the registered\n * component instead of returning `null`.\n *\n * Why a registry instead of static imports:\n * 1. ui-library stays free of heavy deps (konva, etc.) — host apps\n * that don't render the device page never pay the cost.\n * 2. New custom field types can be added by addon code without\n * modifying ui-library.\n * 3. The renderer can read host-only context (e.g. tRPC client,\n * device id) directly, instead of threading props through the\n * form's recursion.\n *\n * Usage (host app, e.g. admin-ui App.tsx):\n *\n * <CustomFieldRenderersProvider renderers={{\n * 'zone-editor': (props) => <DeviceZonesPanel field={props.field} />,\n * }}>\n * <Routes>...</Routes>\n * </CustomFieldRenderersProvider>\n *\n * The renderer receives the same props shape as built-in cases:\n * - `field`: the discriminated-union ConfigField (already narrowed by\n * the renderer's contract — but TypeScript can't see through the\n * dynamic dispatch, so the implementation must validate / cast).\n * - `value`, `onChange`, `disabled` — same as built-in fields.\n */\nimport { useContext, type ComponentType, type ReactNode } from 'react'\nimport type { ConfigField } from '@camstack/types'\nimport { createSharedContext } from '../lib/shared-context'\n\n/**\n * Props shape every custom renderer receives. Keep it congruent with\n * the built-in `case` branches so the dispatcher in `config-form-field`\n * can pass arguments uniformly.\n */\nexport interface CustomFieldRendererProps {\n readonly field: ConfigField\n readonly value: unknown\n readonly onChange: (value: unknown) => void\n readonly disabled?: boolean\n}\n\nexport type CustomFieldRenderer = ComponentType<CustomFieldRendererProps>\n\nexport type CustomFieldRendererMap = Readonly<Record<string, CustomFieldRenderer>>\n\nconst CustomFieldRenderersContext = createSharedContext<CustomFieldRendererMap>(\n 'camstack:custom-field-renderers',\n {},\n)\n\nexport interface CustomFieldRenderersProviderProps {\n readonly renderers: CustomFieldRendererMap\n readonly children: ReactNode\n}\n\nexport function CustomFieldRenderersProvider({\n renderers,\n children,\n}: CustomFieldRenderersProviderProps) {\n return (\n <CustomFieldRenderersContext.Provider value={renderers}>\n {children}\n </CustomFieldRenderersContext.Provider>\n )\n}\n\n/**\n * Look up a registered renderer by `field.type`. Returns null when no\n * renderer is registered — caller falls back to its built-in handling\n * (or renders nothing).\n */\nexport function useCustomFieldRenderer(type: string): CustomFieldRenderer | null {\n const map = useContext(CustomFieldRenderersContext)\n return map[type] ?? null\n}\n","/**\n * DeviceContext — current device id (and optional cached device\n * snapshot) for the page subtree.\n *\n * Provided by host pages (admin-ui DeviceDetail, addon device pages)\n * so that deeply-nested form/field renderers can resolve the device\n * they're acting on without prop drilling. Used by custom field\n * renderers (`zone-editor` → polygon canvas, `device-info` /\n * `live-stream-viewer` / `pipeline-stats` / `doorbell-recent` /\n * `stream-network-stats` → overview blocks) that need to call\n * device-scoped caps or read the device's static metadata.\n *\n * The `device` snapshot is optional — when the host has already\n * fetched the device (DeviceDetail loads it on mount) the renderer\n * can read static fields (name, type, addonId, features, stableId)\n * directly from context instead of round-tripping `deviceManager.get`.\n * Adapters that need it MUST also tolerate `null` so they can be\n * mounted in subtrees that don't carry the snapshot — they fall back\n * to their own query in that case.\n */\nimport { useContext, type ReactNode } from 'react'\nimport { createSharedContext } from '../lib/shared-context'\n\n/**\n * Cached device snapshot. Loose-typed (`Record<string, unknown>`) at\n * the boundary because the wire shape lives in different places\n * depending on the caller — DeviceDetail reads from\n * `deviceManager.list`, `addon-admin-ui` from a hand-loaded subset.\n * Renderers narrow the fields they actually need.\n */\nexport type DeviceSnapshot = Readonly<Record<string, unknown>>\n\ninterface DeviceContextValue {\n readonly deviceId: number\n readonly device: DeviceSnapshot | null\n}\n\nconst DeviceContext = createSharedContext<DeviceContextValue | null>(\n 'camstack:device-context',\n null,\n)\n\nexport interface DeviceContextProviderProps {\n readonly deviceId: number\n /** Optional cached device snapshot — readers narrow the fields they need. */\n readonly device?: DeviceSnapshot\n readonly children: ReactNode\n}\n\nexport function DeviceContextProvider({ deviceId, device, children }: DeviceContextProviderProps) {\n const value: DeviceContextValue = { deviceId, device: device ?? null }\n return <DeviceContext.Provider value={value}>{children}</DeviceContext.Provider>\n}\n\n/** @returns the device id of the current page subtree, or null if outside any provider. */\nexport function useDeviceId(): number | null {\n return useContext(DeviceContext)?.deviceId ?? null\n}\n\n/** @returns the cached device snapshot, or null when no snapshot is provided. */\nexport function useDeviceSnapshot(): DeviceSnapshot | null {\n return useContext(DeviceContext)?.device ?? null\n}\n","/**\n * <WidgetSlot> — single host-side mount point for any addon-contributed\n * widget. Consumers reference a widget by its public id\n * (`<addonId>/<stableId>`), the slot looks the component up in the\n * shared `WidgetRegistry`, validates host context against the widget's\n * `requires` metadata, and renders one of:\n * - skeleton placeholder while the bundle is still loading,\n * - inline error fallback when the widget id is unknown OR the host\n * didn't supply a required context (`deviceContext` /\n * `integrationContext`),\n * - the resolved component otherwise.\n *\n * The slot is intentionally STUPID — no styling beyond the skeleton/\n * error fallback. Layout (card vs inline, sizing) is the host's\n * responsibility.\n */\nimport { type ReactNode, useMemo } from 'react'\nimport { useWidget, useWidgetMetadata, type WidgetProps } from '../contexts/widget-registry.js'\n\nexport interface WidgetSlotProps {\n /** `<addonId>/<stableId>` — the public widget identifier. */\n readonly widgetId: string\n /** Host context — picked up by metadata `requires` validation. Defaults to `'device-tab'`. */\n readonly host?: WidgetProps['host']\n /** Forwarded to widget. */\n readonly config?: Readonly<Record<string, unknown>>\n /** Forwarded to widget. */\n readonly deviceId?: number\n readonly integrationId?: string\n /** Stable instance id — defaults to `widgetId` for non-dashboard hosts (single mount per page). */\n readonly instanceId?: string\n /** Dashboard sizing — placeholder for v1. */\n readonly size?: WidgetProps['size']\n readonly columns?: number\n readonly rows?: number\n}\n\nexport function WidgetSlot(props: WidgetSlotProps): ReactNode {\n const {\n widgetId,\n host = 'device-tab',\n config,\n deviceId,\n integrationId,\n instanceId,\n size,\n columns,\n rows,\n } = props\n const Component = useWidget(widgetId)\n const metadata = useWidgetMetadata(widgetId)\n\n const resolvedInstanceId = useMemo(() => instanceId ?? widgetId, [instanceId, widgetId])\n\n if (Component === undefined && metadata === undefined) {\n return <WidgetMissingError widgetId={widgetId} reason=\"unknown\" />\n }\n if (Component === undefined) {\n // Bundle resolved but the requested stableId isn't exported from it.\n return <WidgetMissingError widgetId={widgetId} reason=\"missing-export\" />\n }\n if (Component === null) {\n return <WidgetSkeleton />\n }\n\n // Host-context validation — gate AFTER load so a required-but-missing\n // context renders a clear message instead of a blank slot.\n if (metadata) {\n if (metadata.requires.deviceContext && deviceId === undefined) {\n return <WidgetMissingError widgetId={widgetId} reason=\"missing-device-context\" />\n }\n if (metadata.requires.integrationContext && integrationId === undefined) {\n return <WidgetMissingError widgetId={widgetId} reason=\"missing-integration-context\" />\n }\n }\n\n return (\n <Component\n instanceId={resolvedInstanceId}\n host={host}\n config={config}\n deviceId={deviceId}\n integrationId={integrationId}\n size={size}\n columns={columns}\n rows={rows}\n />\n )\n}\n\nfunction WidgetSkeleton(): ReactNode {\n return (\n <div className=\"rounded-lg border border-border bg-surface/40 p-4 animate-pulse\">\n <div className=\"h-3 w-24 bg-foreground-subtle/20 rounded mb-2\" />\n <div className=\"h-2 w-full bg-foreground-subtle/10 rounded mb-1\" />\n <div className=\"h-2 w-3/4 bg-foreground-subtle/10 rounded\" />\n </div>\n )\n}\n\ninterface WidgetMissingErrorProps {\n readonly widgetId: string\n readonly reason: 'unknown' | 'missing-export' | 'missing-device-context' | 'missing-integration-context'\n}\n\nfunction WidgetMissingError({ widgetId, reason }: WidgetMissingErrorProps): ReactNode {\n const message =\n reason === 'unknown'\n ? `Widget \"${widgetId}\" not registered`\n : reason === 'missing-export'\n ? `Widget \"${widgetId}\" bundle does not export this stableId`\n : reason === 'missing-device-context'\n ? `Widget \"${widgetId}\" requires a deviceId`\n : `Widget \"${widgetId}\" requires an integrationId`\n return (\n <div className=\"rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning\">\n {message}\n </div>\n )\n}\n","/**\n * WidgetRegistry — admin-ui side of the addon-widgets system.\n *\n * Backed by Module Federation (`@module-federation/runtime`). The host\n * (admin-ui) declares its shared singletons in `vite.config.ts`; every\n * widget addon publishes a remote at `dist/remoteEntry.js` (built by\n * `vite.widgets.config.ts`). At runtime we fetch the public list of\n * addon-contributed widgets via `useAddonWidgetsListWidgets()`, register\n * each remote (`registerRemotes`) once, then resolve a widget by\n * loading the exposed `./widgets` module (`loadRemote`) whose default\n * export is a `Record<stableId, ComponentType<WidgetProps>>` map.\n *\n * Why MF instead of raw ESM:\n * - automatic dedup of shared deps (react/react-dom/@tanstack/etc.)\n * against the host's instances — no more hand-rolled vendor stubs +\n * importmap shims pointing at `window.__camstack*` globals.\n * - version negotiation (we pin `singleton: true` everywhere; the host\n * wins by default).\n * - cross-bundle context invariant preserved automatically: every\n * remote's `@camstack/ui-library` import resolves to the host's\n * instance, so `createContext()` references match across bundles\n * (the duplicate-Context bug that motivated `createSharedContext`\n * falls out for free).\n *\n * Live-update — listens to `addon.widget-ready` so newly-loaded addons\n * surface their widgets without a manual page reload (the aggregator\n * stamps a fresh `?v=<mtime>` cache-buster on the entry URL).\n *\n * Cache resilience — same `staleTime: 0` + `refetchOnMount` + boot-\n * window poll fallback as `AppLayout`'s addon-pages query.\n */\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode,\n} from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { registerRemotes, loadRemote } from '@module-federation/runtime'\n\nimport { createSharedContext } from '../lib/shared-context'\nimport { ensureMfHostInit } from '../lib/mf-runtime-init'\nimport { useAddonWidgetsListWidgets } from '../generated/system-hooks.js'\nimport { useLiveEvent } from '../hooks/use-live-event.js'\n\n/** Standard props every addon-contributed widget receives. */\nexport interface WidgetProps {\n /** Stable id of THIS widget instance (form-builder field key, dashboard slot UUID, etc.). */\n readonly instanceId: string\n /** Host where this widget is rendered. */\n readonly host: 'device-tab' | 'dashboard' | 'integration-detail'\n /** Form/dashboard-supplied props. Shape depends on the widget. */\n readonly config?: Readonly<Record<string, unknown>>\n /** Provided when host has a device context. */\n readonly deviceId?: number\n /** Provided when host has an integration context. */\n readonly integrationId?: string\n /** Dashboard sizing hints (placeholder for v1 — widget can ignore). */\n readonly size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n readonly columns?: number\n readonly rows?: number\n}\n\n/** Public registry surface. */\nexport interface WidgetRegistry {\n /**\n * Returns the resolved widget component for `<addonId>/<stableId>`,\n * or `undefined` when the widget id is unknown to the registry, or\n * `null` while the bundle is still loading.\n */\n resolve(widgetId: string): ComponentType<WidgetProps> | null | undefined\n /** Metadata lookup — used by `<WidgetSlot>` to validate `requires`. */\n metadata(widgetId: string): WidgetMetadataEntry | undefined\n /** Every contributed widget. Used by host pickers (e.g. dashboard\n * add-widget modal) to enumerate the available widgets. */\n listAll(): readonly WidgetMetadataEntry[]\n}\n\n/** One enriched-aggregator entry exposed to consumers. */\nexport interface WidgetMetadataEntry {\n readonly widgetId: string // `<addonId>/<stableId>`\n readonly addonId: string\n readonly stableId: string\n readonly label: string\n readonly description?: string\n readonly icon?: string\n readonly remoteName: string\n readonly bundleUrl: string\n readonly hosts: readonly ('device-tab' | 'dashboard' | 'integration-detail')[]\n readonly requires: { readonly deviceContext: boolean; readonly integrationContext: boolean }\n readonly defaultSize: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n readonly allowedSizes: readonly ('xs' | 'sm' | 'md' | 'lg' | 'xl')[]\n readonly defaultColumns: number\n readonly defaultRows: number\n}\n\nconst WidgetRegistryContext = createSharedContext<WidgetRegistry | null>(\n 'camstack:widget-registry',\n null,\n)\n\n/**\n * Process-global cache for resolved widget bundles, keyed by\n * `remoteName` (every remote exposes a single `./widgets` module whose\n * default export is the `Record<stableId, Component>` map). Survives\n * provider remount — avoids a full re-fetch + re-init of the MF remote\n * when admin-ui's tree cycles.\n */\nconst bundleModuleCache = new Map<string, Record<string, ComponentType<WidgetProps>>>()\nconst bundleInflight = new Map<string, Promise<Record<string, ComponentType<WidgetProps>>>>()\n\n/**\n * Set of MF remote names already passed to `registerRemotes`. Calling\n * `registerRemotes` twice with the same name is a no-op (`force` is\n * intentionally left `false`) but the bookkeeping makes intent clear\n * and avoids a chunk of plugin-internal work on every aggregator\n * update.\n */\nconst registeredRemotes = new Set<string>()\n\ninterface AggregatorEntry {\n readonly addonId: string\n readonly stableId: string\n readonly label: string\n readonly description?: string\n readonly icon?: string\n readonly remoteName: string\n readonly bundle: string\n readonly bundleUrl: string\n readonly hosts: readonly ('device-tab' | 'dashboard' | 'integration-detail')[]\n readonly requires: { readonly deviceContext: boolean; readonly integrationContext: boolean }\n readonly defaultSize: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n readonly allowedSizes: readonly ('xs' | 'sm' | 'md' | 'lg' | 'xl')[]\n readonly defaultColumns: number\n readonly defaultRows: number\n}\n\n/** Shape of the remote's exposed module — same default-record contract\n * the previous raw-ESM bundle exported. */\ninterface RemoteWidgetsModule {\n readonly default: Record<string, ComponentType<WidgetProps>>\n}\n\nfunction isRemoteWidgetsModule(value: unknown): value is RemoteWidgetsModule {\n if (!value || typeof value !== 'object') return false\n const def = (value as { default?: unknown }).default\n return def !== null && typeof def === 'object'\n}\n\n/**\n * Diagnostic-only string for the \"Got: …\" tail in the not-a-record\n * error. Returns a JSON-friendly snapshot of the module's keys + proto\n * name without exposing the value itself (the value is the unknown\n * thing the module factory produced, may be huge or contain PII).\n */\nfunction describeRemoteShape(mod: unknown): string | { ownKeys: readonly string[]; allKeys: readonly string[]; proto: string | undefined } {\n if (!mod || typeof mod !== 'object') return typeof mod\n const obj = mod as Record<string, unknown>\n const proto: unknown = Object.getPrototypeOf(obj)\n const protoName = proto && typeof proto === 'object'\n ? (proto as { constructor?: { name?: unknown } }).constructor?.name\n : undefined\n return {\n ownKeys: Object.keys(obj),\n allKeys: Object.getOwnPropertyNames(obj),\n proto: typeof protoName === 'string' ? protoName : undefined,\n }\n}\n\n/**\n * Register the MF remote (idempotent) and load its `./widgets` module.\n * Returns the resolved `Record<stableId, Component>` map.\n */\nasync function loadRemoteBundle(\n remoteName: string,\n entryUrl: string,\n): Promise<Record<string, ComponentType<WidgetProps>>> {\n const cached = bundleModuleCache.get(remoteName)\n if (cached) return cached\n const inflight = bundleInflight.get(remoteName)\n if (inflight) return inflight\n\n if (!registeredRemotes.has(remoteName)) {\n ensureMfHostInit()\n // `type: 'module'` is mandatory because the Vite-built remote\n // entries are ESM (use `import` statements). MF's default loader\n // injects a plain `<script>` tag which would fail with \"Failed to\n // load script resource\" on any module-formatted entry.\n registerRemotes(\n [{ name: remoteName, entry: entryUrl, type: 'module' }],\n { force: false },\n )\n registeredRemotes.add(remoteName)\n }\n\n const promise = loadRemote<unknown>(`${remoteName}/widgets`).then(\n (mod): Record<string, ComponentType<WidgetProps>> => {\n if (!isRemoteWidgetsModule(mod)) {\n // Surface the actual shape so devs see what's missing — without\n // this it's a black-box \"default record missing\" message.\n const shape = describeRemoteShape(mod)\n throw new Error(\n `Widget remote ${remoteName} (${entryUrl}) does not expose a default record on './widgets'. ` +\n `Got: ${JSON.stringify(shape)}`,\n )\n }\n const map = mod.default\n bundleModuleCache.set(remoteName, map)\n bundleInflight.delete(remoteName)\n return map\n },\n ).catch((err: unknown) => {\n bundleInflight.delete(remoteName)\n throw err\n })\n bundleInflight.set(remoteName, promise)\n return promise\n}\n\nconst BOOT_WINDOW_MS = 30_000\nconst POLL_INTERVAL_MS = 2_000\n\nexport interface WidgetRegistryProviderProps {\n readonly children: ReactNode\n}\n\nexport function WidgetRegistryProvider({ children }: WidgetRegistryProviderProps) {\n const queryClient = useQueryClient()\n const mountedAtRef = useRef(Date.now())\n\n const { data: rawWidgets } = useAddonWidgetsListWidgets(\n undefined,\n {\n // Same boot-time race protection as AppLayout's addon-pages\n // query — see the extensive note there for the bug a long\n // staleTime introduces.\n staleTime: 0,\n refetchOnMount: 'always',\n refetchInterval: (query) => {\n const data = query.state.data\n if (data && data.length > 0) return false\n const elapsed = Date.now() - mountedAtRef.current\n if (elapsed >= BOOT_WINDOW_MS) return false\n return POLL_INTERVAL_MS\n },\n },\n )\n\n // Re-emit on `addon.widget-ready` so newly-loaded addons surface\n // their widgets without a page reload. Same key shape as AppLayout.\n useLiveEvent('addon.widget-ready', () => {\n queryClient.invalidateQueries({ queryKey: [['addonWidgets', 'listWidgets']] })\n })\n\n // Force a re-render whenever a bundle finishes loading — the\n // resolved component lives in the global cache; the registry surface\n // only needs a tick to flip from `null` (loading) to the component.\n const [resolvedTick, setResolvedTick] = useState(0)\n\n // Register every remote we don't have yet and kick off its\n // `./widgets` load. Dedup'd via `registeredRemotes` + `bundleInflight`\n // so flapping aggregator updates don't multi-load.\n useEffect(() => {\n if (!rawWidgets) return\n let cancelled = false\n const seenRemotes = new Set<string>()\n for (const w of rawWidgets) {\n if (seenRemotes.has(w.remoteName)) continue\n seenRemotes.add(w.remoteName)\n if (bundleModuleCache.has(w.remoteName)) continue\n const entryUrl = w.bundleUrl\n void loadRemoteBundle(w.remoteName, entryUrl).then(() => {\n if (!cancelled) setResolvedTick((t) => t + 1)\n }).catch((err: unknown) => {\n const reason = err instanceof Error ? err.message : String(err)\n // Surface to the host's logger if available — admin-ui's\n // logger capture hooks `window.console`. Avoid a hard\n // `console.*` dependency at module scope (eslint forbids it).\n const host = typeof globalThis !== 'undefined'\n ? (globalThis as { console?: { error?: (...args: unknown[]) => void } }).console\n : undefined\n host?.error?.('[WidgetRegistry] Failed to load widget remote', {\n remoteName: w.remoteName,\n entryUrl,\n reason,\n })\n })\n }\n return () => { cancelled = true }\n }, [rawWidgets])\n\n const registry: WidgetRegistry = useMemo(() => {\n const widgets: readonly AggregatorEntry[] = (rawWidgets ?? []) as readonly AggregatorEntry[]\n const byId = new Map<string, AggregatorEntry>()\n for (const w of widgets) {\n byId.set(`${w.addonId}/${w.stableId}`, w)\n }\n const toMetadata = (widgetId: string, entry: AggregatorEntry): WidgetMetadataEntry => ({\n widgetId,\n addonId: entry.addonId,\n stableId: entry.stableId,\n label: entry.label,\n description: entry.description,\n icon: entry.icon,\n remoteName: entry.remoteName,\n bundleUrl: entry.bundleUrl,\n hosts: entry.hosts,\n requires: entry.requires,\n defaultSize: entry.defaultSize,\n allowedSizes: entry.allowedSizes,\n defaultColumns: entry.defaultColumns,\n defaultRows: entry.defaultRows,\n })\n return {\n resolve: (widgetId: string): ComponentType<WidgetProps> | null | undefined => {\n const entry = byId.get(widgetId)\n if (!entry) return undefined\n const bundle = bundleModuleCache.get(entry.remoteName)\n if (!bundle) return null\n const Component = bundle[entry.stableId]\n if (!Component) return undefined\n return Component\n },\n metadata: (widgetId: string): WidgetMetadataEntry | undefined => {\n const entry = byId.get(widgetId)\n if (!entry) return undefined\n return toMetadata(widgetId, entry)\n },\n listAll: (): readonly WidgetMetadataEntry[] => {\n const out: WidgetMetadataEntry[] = []\n for (const [widgetId, entry] of byId) out.push(toMetadata(widgetId, entry))\n return out\n },\n }\n // resolvedTick is intentionally in deps — flips re-memo when a bundle\n // finishes loading so `resolve()` returns the component instead of `null`.\n }, [rawWidgets, resolvedTick])\n\n return (\n <WidgetRegistryContext.Provider value={registry}>\n {children}\n </WidgetRegistryContext.Provider>\n )\n}\n\n/** Returns the registered widget component, `null` while loading, or `undefined` if unknown. */\nexport function useWidget(widgetId: string): ComponentType<WidgetProps> | null | undefined {\n const reg = useWidgetRegistry()\n return reg.resolve(widgetId)\n}\n\n/** Returns the metadata entry for a widget, or `undefined` if unknown. */\nexport function useWidgetMetadata(widgetId: string): WidgetMetadataEntry | undefined {\n const reg = useWidgetRegistry()\n return reg.metadata(widgetId)\n}\n\n/** Returns every contributed widget — host pickers (dashboard\n * add-widget modal, settings UI palette) consume this to enumerate\n * the registry. Filter on the call site by `metadata.hosts.includes()`. */\nexport function useAllWidgets(): readonly WidgetMetadataEntry[] {\n const reg = useWidgetRegistry()\n return reg.listAll()\n}\n\n/** Read the registry instance — throws when no provider is mounted. */\nexport function useWidgetRegistry(): WidgetRegistry {\n const ctx = useOptionalWidgetRegistry()\n if (!ctx) {\n throw new Error('useWidgetRegistry(): no <WidgetRegistryProvider> in tree')\n }\n return ctx\n}\n\n/** Variant returning `null` when no provider is mounted — for boot splash etc. */\nexport function useOptionalWidgetRegistry(): WidgetRegistry | null {\n // Late import avoids the implicit-any from `Context<unknown>` typing\n // round-trips inside cross-bundle shared contexts.\n return useContextSafe(WidgetRegistryContext)\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nimport { useContext } from 'react'\nimport type { Context } from 'react'\n\nfunction useContextSafe<T>(ctx: Context<T>): T {\n return useContext(ctx)\n}\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-system-hooks.ts\n/* eslint-disable */\n\n/**\n * Per-method React-Query hooks for every `scope: 'system'` capability.\n *\n * Each hook is a thin pass-through to `trpc.<cap>.<method>.useQuery` /\n * `.useMutation` / `.useSubscription` so the typed inference + RQ\n * cache/dedup keep working — the generator only contributes a consistent\n * name and stable export surface so admin-ui pages can write\n * `useAddonsList()` instead of `trpc.addons.list.useQuery()`.\n *\n * Push-subscription methods (`kind: 'subscription'`) emit a typeof\n * alias over `useSubscription`, so the call shape is\n * `useToastOnToast(input, { onData: cb })` — same as the underlying\n * tRPC hook. The eventBus-backed `useLiveEvent` (see\n * `../hooks/use-live-event.ts`) covers events that don't ride a tRPC\n * subscription; the two surfaces coexist by design.\n */\nimport { trpc } from '../trpc-react.js'\n\n/** Generated alias around `trpc.accessories.getStatus.useQuery`. */\nexport const useAccessoriesGetStatus: typeof trpc.accessories.getStatus.useQuery = trpc.accessories.getStatus.useQuery\n\n/** Generated alias around `trpc.addonPages.listPages.useQuery`. */\nexport const useAddonPagesListPages: typeof trpc.addonPages.listPages.useQuery = trpc.addonPages.listPages.useQuery\n\n/** Generated alias around `trpc.addons.list.useQuery`. */\nexport const useAddonsList: typeof trpc.addons.list.useQuery = trpc.addons.list.useQuery\n\n/** Generated alias around `trpc.addons.getLogs.useQuery`. */\nexport const useAddonsGetLogs: typeof trpc.addons.getLogs.useQuery = trpc.addons.getLogs.useQuery\n\n/** Generated alias around `trpc.addons.listPackages.useQuery`. */\nexport const useAddonsListPackages: typeof trpc.addons.listPackages.useQuery = trpc.addons.listPackages.useQuery\n\n/** Generated alias around `trpc.addons.installPackage.useMutation`. */\nexport const useAddonsInstallPackage: typeof trpc.addons.installPackage.useMutation = trpc.addons.installPackage.useMutation\n\n/** Generated alias around `trpc.addons.installFromWorkspace.useMutation`. */\nexport const useAddonsInstallFromWorkspace: typeof trpc.addons.installFromWorkspace.useMutation = trpc.addons.installFromWorkspace.useMutation\n\n/** Generated alias around `trpc.addons.isWorkspaceAvailable.useQuery`. */\nexport const useAddonsIsWorkspaceAvailable: typeof trpc.addons.isWorkspaceAvailable.useQuery = trpc.addons.isWorkspaceAvailable.useQuery\n\n/** Generated alias around `trpc.addons.listWorkspacePackages.useQuery`. */\nexport const useAddonsListWorkspacePackages: typeof trpc.addons.listWorkspacePackages.useQuery = trpc.addons.listWorkspacePackages.useQuery\n\n/** Generated alias around `trpc.addons.uninstallPackage.useMutation`. */\nexport const useAddonsUninstallPackage: typeof trpc.addons.uninstallPackage.useMutation = trpc.addons.uninstallPackage.useMutation\n\n/** Generated alias around `trpc.addons.reloadPackages.useMutation`. */\nexport const useAddonsReloadPackages: typeof trpc.addons.reloadPackages.useMutation = trpc.addons.reloadPackages.useMutation\n\n/** Generated alias around `trpc.addons.searchAvailable.useQuery`. */\nexport const useAddonsSearchAvailable: typeof trpc.addons.searchAvailable.useQuery = trpc.addons.searchAvailable.useQuery\n\n/** Generated alias around `trpc.addons.listUpdates.useQuery`. */\nexport const useAddonsListUpdates: typeof trpc.addons.listUpdates.useQuery = trpc.addons.listUpdates.useQuery\n\n/** Generated alias around `trpc.addons.updatePackage.useMutation`. */\nexport const useAddonsUpdatePackage: typeof trpc.addons.updatePackage.useMutation = trpc.addons.updatePackage.useMutation\n\n/** Generated alias around `trpc.addons.forceRefresh.useMutation`. */\nexport const useAddonsForceRefresh: typeof trpc.addons.forceRefresh.useMutation = trpc.addons.forceRefresh.useMutation\n\n/** Generated alias around `trpc.addons.restartServer.useMutation`. */\nexport const useAddonsRestartServer: typeof trpc.addons.restartServer.useMutation = trpc.addons.restartServer.useMutation\n\n/** Generated alias around `trpc.addons.getVersions.useQuery`. */\nexport const useAddonsGetVersions: typeof trpc.addons.getVersions.useQuery = trpc.addons.getVersions.useQuery\n\n/** Generated alias around `trpc.addons.restartAddon.useMutation`. */\nexport const useAddonsRestartAddon: typeof trpc.addons.restartAddon.useMutation = trpc.addons.restartAddon.useMutation\n\n/** Generated alias around `trpc.addons.getAutoUpdateSettings.useQuery`. */\nexport const useAddonsGetAutoUpdateSettings: typeof trpc.addons.getAutoUpdateSettings.useQuery = trpc.addons.getAutoUpdateSettings.useQuery\n\n/** Generated alias around `trpc.addons.setAutoUpdateSettings.useMutation`. */\nexport const useAddonsSetAutoUpdateSettings: typeof trpc.addons.setAutoUpdateSettings.useMutation = trpc.addons.setAutoUpdateSettings.useMutation\n\n/** Generated alias around `trpc.addons.getAddonAutoUpdate.useQuery`. */\nexport const useAddonsGetAddonAutoUpdate: typeof trpc.addons.getAddonAutoUpdate.useQuery = trpc.addons.getAddonAutoUpdate.useQuery\n\n/** Generated alias around `trpc.addons.setAddonAutoUpdate.useMutation`. */\nexport const useAddonsSetAddonAutoUpdate: typeof trpc.addons.setAddonAutoUpdate.useMutation = trpc.addons.setAddonAutoUpdate.useMutation\n\n/** Generated alias around `trpc.addons.applyAutoUpdateToAll.useMutation`. */\nexport const useAddonsApplyAutoUpdateToAll: typeof trpc.addons.applyAutoUpdateToAll.useMutation = trpc.addons.applyAutoUpdateToAll.useMutation\n\n/** Generated alias around `trpc.addons.custom.useMutation`. */\nexport const useAddonsCustom: typeof trpc.addons.custom.useMutation = trpc.addons.custom.useMutation\n\n/** Generated alias around `trpc.addons.onAddonLogs.useSubscription`. */\nexport const useAddonsOnAddonLogs: typeof trpc.addons.onAddonLogs.useSubscription = trpc.addons.onAddonLogs.useSubscription\n\n/** Generated alias around `trpc.addonSettings.getGlobalSettings.useQuery`. */\nexport const useAddonSettingsGetGlobalSettings: typeof trpc.addonSettings.getGlobalSettings.useQuery = trpc.addonSettings.getGlobalSettings.useQuery\n\n/** Generated alias around `trpc.addonSettings.updateGlobalSettings.useMutation`. */\nexport const useAddonSettingsUpdateGlobalSettings: typeof trpc.addonSettings.updateGlobalSettings.useMutation = trpc.addonSettings.updateGlobalSettings.useMutation\n\n/** Generated alias around `trpc.addonSettings.getDeviceSettings.useQuery`. */\nexport const useAddonSettingsGetDeviceSettings: typeof trpc.addonSettings.getDeviceSettings.useQuery = trpc.addonSettings.getDeviceSettings.useQuery\n\n/** Generated alias around `trpc.addonSettings.updateDeviceSettings.useMutation`. */\nexport const useAddonSettingsUpdateDeviceSettings: typeof trpc.addonSettings.updateDeviceSettings.useMutation = trpc.addonSettings.updateDeviceSettings.useMutation\n\n/** Generated alias around `trpc.addonWidgets.listWidgets.useQuery`. */\nexport const useAddonWidgetsListWidgets: typeof trpc.addonWidgets.listWidgets.useQuery = trpc.addonWidgets.listWidgets.useQuery\n\n/** Generated alias around `trpc.alerts.emit.useMutation`. */\nexport const useAlertsEmit: typeof trpc.alerts.emit.useMutation = trpc.alerts.emit.useMutation\n\n/** Generated alias around `trpc.alerts.update.useMutation`. */\nexport const useAlertsUpdate: typeof trpc.alerts.update.useMutation = trpc.alerts.update.useMutation\n\n/** Generated alias around `trpc.alerts.list.useQuery`. */\nexport const useAlertsList: typeof trpc.alerts.list.useQuery = trpc.alerts.list.useQuery\n\n/** Generated alias around `trpc.alerts.getUnreadCount.useQuery`. */\nexport const useAlertsGetUnreadCount: typeof trpc.alerts.getUnreadCount.useQuery = trpc.alerts.getUnreadCount.useQuery\n\n/** Generated alias around `trpc.alerts.markRead.useMutation`. */\nexport const useAlertsMarkRead: typeof trpc.alerts.markRead.useMutation = trpc.alerts.markRead.useMutation\n\n/** Generated alias around `trpc.alerts.markAllRead.useMutation`. */\nexport const useAlertsMarkAllRead: typeof trpc.alerts.markAllRead.useMutation = trpc.alerts.markAllRead.useMutation\n\n/** Generated alias around `trpc.alerts.dismiss.useMutation`. */\nexport const useAlertsDismiss: typeof trpc.alerts.dismiss.useMutation = trpc.alerts.dismiss.useMutation\n\n/** Generated alias around `trpc.audioAnalysis.resolveDeviceSettings.useQuery`. */\nexport const useAudioAnalysisResolveDeviceSettings: typeof trpc.audioAnalysis.resolveDeviceSettings.useQuery = trpc.audioAnalysis.resolveDeviceSettings.useQuery\n\n/** Generated alias around `trpc.audioAnalysis.getDeviceSettingsContribution.useQuery`. */\nexport const useAudioAnalysisGetDeviceSettingsContribution: typeof trpc.audioAnalysis.getDeviceSettingsContribution.useQuery = trpc.audioAnalysis.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.audioAnalysis.getDeviceLiveContribution.useQuery`. */\nexport const useAudioAnalysisGetDeviceLiveContribution: typeof trpc.audioAnalysis.getDeviceLiveContribution.useQuery = trpc.audioAnalysis.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.audioAnalysis.applyDeviceSettingsPatch.useMutation`. */\nexport const useAudioAnalysisApplyDeviceSettingsPatch: typeof trpc.audioAnalysis.applyDeviceSettingsPatch.useMutation = trpc.audioAnalysis.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.audioAnalyzer.analyseChunk.useMutation`. */\nexport const useAudioAnalyzerAnalyseChunk: typeof trpc.audioAnalyzer.analyseChunk.useMutation = trpc.audioAnalyzer.analyseChunk.useMutation\n\n/** Generated alias around `trpc.audioAnalyzer.classify.useQuery`. */\nexport const useAudioAnalyzerClassify: typeof trpc.audioAnalyzer.classify.useQuery = trpc.audioAnalyzer.classify.useQuery\n\n/** Generated alias around `trpc.audioAnalyzer.isReady.useQuery`. */\nexport const useAudioAnalyzerIsReady: typeof trpc.audioAnalyzer.isReady.useQuery = trpc.audioAnalyzer.isReady.useQuery\n\n/** Generated alias around `trpc.audioAnalyzer.dispose.useMutation`. */\nexport const useAudioAnalyzerDispose: typeof trpc.audioAnalyzer.dispose.useMutation = trpc.audioAnalyzer.dispose.useMutation\n\n/** Generated alias around `trpc.audioAnalyzer.reprobeAudioEngine.useMutation`. */\nexport const useAudioAnalyzerReprobeAudioEngine: typeof trpc.audioAnalyzer.reprobeAudioEngine.useMutation = trpc.audioAnalyzer.reprobeAudioEngine.useMutation\n\n/** Generated alias around `trpc.audioCodec.listSupportedCodecs.useQuery`. */\nexport const useAudioCodecListSupportedCodecs: typeof trpc.audioCodec.listSupportedCodecs.useQuery = trpc.audioCodec.listSupportedCodecs.useQuery\n\n/** Generated alias around `trpc.audioCodec.canHandle.useQuery`. */\nexport const useAudioCodecCanHandle: typeof trpc.audioCodec.canHandle.useQuery = trpc.audioCodec.canHandle.useQuery\n\n/** Generated alias around `trpc.audioCodec.createDecodeSession.useMutation`. */\nexport const useAudioCodecCreateDecodeSession: typeof trpc.audioCodec.createDecodeSession.useMutation = trpc.audioCodec.createDecodeSession.useMutation\n\n/** Generated alias around `trpc.audioCodec.createEncodeSession.useMutation`. */\nexport const useAudioCodecCreateEncodeSession: typeof trpc.audioCodec.createEncodeSession.useMutation = trpc.audioCodec.createEncodeSession.useMutation\n\n/** Generated alias around `trpc.audioCodec.closeSession.useMutation`. */\nexport const useAudioCodecCloseSession: typeof trpc.audioCodec.closeSession.useMutation = trpc.audioCodec.closeSession.useMutation\n\n/** Generated alias around `trpc.audioCodec.pushEncodedFrame.useMutation`. */\nexport const useAudioCodecPushEncodedFrame: typeof trpc.audioCodec.pushEncodedFrame.useMutation = trpc.audioCodec.pushEncodedFrame.useMutation\n\n/** Generated alias around `trpc.audioCodec.pullPcm.useQuery`. */\nexport const useAudioCodecPullPcm: typeof trpc.audioCodec.pullPcm.useQuery = trpc.audioCodec.pullPcm.useQuery\n\n/** Generated alias around `trpc.audioCodec.pushPcm.useMutation`. */\nexport const useAudioCodecPushPcm: typeof trpc.audioCodec.pushPcm.useMutation = trpc.audioCodec.pushPcm.useMutation\n\n/** Generated alias around `trpc.audioCodec.pullEncoded.useQuery`. */\nexport const useAudioCodecPullEncoded: typeof trpc.audioCodec.pullEncoded.useQuery = trpc.audioCodec.pullEncoded.useQuery\n\n/** Generated alias around `trpc.audioCodec.flushEncode.useMutation`. */\nexport const useAudioCodecFlushEncode: typeof trpc.audioCodec.flushEncode.useMutation = trpc.audioCodec.flushEncode.useMutation\n\n/** Generated alias around `trpc.audioCodec.listActiveSessions.useQuery`. */\nexport const useAudioCodecListActiveSessions: typeof trpc.audioCodec.listActiveSessions.useQuery = trpc.audioCodec.listActiveSessions.useQuery\n\n/** Generated alias around `trpc.audioMetrics.getCurrentSnapshot.useQuery`. */\nexport const useAudioMetricsGetCurrentSnapshot: typeof trpc.audioMetrics.getCurrentSnapshot.useQuery = trpc.audioMetrics.getCurrentSnapshot.useQuery\n\n/** Generated alias around `trpc.audioMetrics.getHistory.useQuery`. */\nexport const useAudioMetricsGetHistory: typeof trpc.audioMetrics.getHistory.useQuery = trpc.audioMetrics.getHistory.useQuery\n\n/** Generated alias around `trpc.backup.trigger.useMutation`. */\nexport const useBackupTrigger: typeof trpc.backup.trigger.useMutation = trpc.backup.trigger.useMutation\n\n/** Generated alias around `trpc.backup.list.useQuery`. */\nexport const useBackupList: typeof trpc.backup.list.useQuery = trpc.backup.list.useQuery\n\n/** Generated alias around `trpc.backup.restore.useMutation`. */\nexport const useBackupRestore: typeof trpc.backup.restore.useMutation = trpc.backup.restore.useMutation\n\n/** Generated alias around `trpc.backup.delete.useMutation`. */\nexport const useBackupDelete: typeof trpc.backup.delete.useMutation = trpc.backup.delete.useMutation\n\n/** Generated alias around `trpc.battery.getStatus.useQuery`. */\nexport const useBatteryGetStatus: typeof trpc.battery.getStatus.useQuery = trpc.battery.getStatus.useQuery\n\n/** Generated alias around `trpc.brightness.setBrightness.useMutation`. */\nexport const useBrightnessSetBrightness: typeof trpc.brightness.setBrightness.useMutation = trpc.brightness.setBrightness.useMutation\n\n/** Generated alias around `trpc.brightness.getStatus.useQuery`. */\nexport const useBrightnessGetStatus: typeof trpc.brightness.getStatus.useQuery = trpc.brightness.getStatus.useQuery\n\n/** Generated alias around `trpc.cameraStreams.getCameraStreams.useQuery`. */\nexport const useCameraStreamsGetCameraStreams: typeof trpc.cameraStreams.getCameraStreams.useQuery = trpc.cameraStreams.getCameraStreams.useQuery\n\n/** Generated alias around `trpc.cameraStreams.getBrokerStreams.useQuery`. */\nexport const useCameraStreamsGetBrokerStreams: typeof trpc.cameraStreams.getBrokerStreams.useQuery = trpc.cameraStreams.getBrokerStreams.useQuery\n\n/** Generated alias around `trpc.cameraStreams.getRtspEntries.useQuery`. */\nexport const useCameraStreamsGetRtspEntries: typeof trpc.cameraStreams.getRtspEntries.useQuery = trpc.cameraStreams.getRtspEntries.useQuery\n\n/** Generated alias around `trpc.decoder.supportsCodec.useQuery`. */\nexport const useDecoderSupportsCodec: typeof trpc.decoder.supportsCodec.useQuery = trpc.decoder.supportsCodec.useQuery\n\n/** Generated alias around `trpc.decoder.getInfo.useQuery`. */\nexport const useDecoderGetInfo: typeof trpc.decoder.getInfo.useQuery = trpc.decoder.getInfo.useQuery\n\n/** Generated alias around `trpc.decoder.createSession.useQuery`. */\nexport const useDecoderCreateSession: typeof trpc.decoder.createSession.useQuery = trpc.decoder.createSession.useQuery\n\n/** Generated alias around `trpc.decoder.destroySession.useQuery`. */\nexport const useDecoderDestroySession: typeof trpc.decoder.destroySession.useQuery = trpc.decoder.destroySession.useQuery\n\n/** Generated alias around `trpc.decoder.pushPacket.useQuery`. */\nexport const useDecoderPushPacket: typeof trpc.decoder.pushPacket.useQuery = trpc.decoder.pushPacket.useQuery\n\n/** Generated alias around `trpc.decoder.openStream.useQuery`. */\nexport const useDecoderOpenStream: typeof trpc.decoder.openStream.useQuery = trpc.decoder.openStream.useQuery\n\n/** Generated alias around `trpc.decoder.pullFrames.useQuery`. */\nexport const useDecoderPullFrames: typeof trpc.decoder.pullFrames.useQuery = trpc.decoder.pullFrames.useQuery\n\n/** Generated alias around `trpc.decoder.updateConfig.useQuery`. */\nexport const useDecoderUpdateConfig: typeof trpc.decoder.updateConfig.useQuery = trpc.decoder.updateConfig.useQuery\n\n/** Generated alias around `trpc.decoder.getStats.useQuery`. */\nexport const useDecoderGetStats: typeof trpc.decoder.getStats.useQuery = trpc.decoder.getStats.useQuery\n\n/** Generated alias around `trpc.decoder.listActiveSessions.useQuery`. */\nexport const useDecoderListActiveSessions: typeof trpc.decoder.listActiveSessions.useQuery = trpc.decoder.listActiveSessions.useQuery\n\n/** Generated alias around `trpc.decoder.reprobeHwaccel.useMutation`. */\nexport const useDecoderReprobeHwaccel: typeof trpc.decoder.reprobeHwaccel.useMutation = trpc.decoder.reprobeHwaccel.useMutation\n\n/** Generated alias around `trpc.detectionPipeline.getDeviceSettingsContribution.useQuery`. */\nexport const useDetectionPipelineGetDeviceSettingsContribution: typeof trpc.detectionPipeline.getDeviceSettingsContribution.useQuery = trpc.detectionPipeline.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.detectionPipeline.getDeviceLiveContribution.useQuery`. */\nexport const useDetectionPipelineGetDeviceLiveContribution: typeof trpc.detectionPipeline.getDeviceLiveContribution.useQuery = trpc.detectionPipeline.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.detectionPipeline.applyDeviceSettingsPatch.useMutation`. */\nexport const useDetectionPipelineApplyDeviceSettingsPatch: typeof trpc.detectionPipeline.applyDeviceSettingsPatch.useMutation = trpc.detectionPipeline.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.deviceDiscovery.listDiscovered.useQuery`. */\nexport const useDeviceDiscoveryListDiscovered: typeof trpc.deviceDiscovery.listDiscovered.useQuery = trpc.deviceDiscovery.listDiscovered.useQuery\n\n/** Generated alias around `trpc.deviceDiscovery.refreshDiscovery.useMutation`. */\nexport const useDeviceDiscoveryRefreshDiscovery: typeof trpc.deviceDiscovery.refreshDiscovery.useMutation = trpc.deviceDiscovery.refreshDiscovery.useMutation\n\n/** Generated alias around `trpc.deviceDiscovery.adoptDevice.useMutation`. */\nexport const useDeviceDiscoveryAdoptDevice: typeof trpc.deviceDiscovery.adoptDevice.useMutation = trpc.deviceDiscovery.adoptDevice.useMutation\n\n/** Generated alias around `trpc.deviceDiscovery.releaseDevice.useMutation`. */\nexport const useDeviceDiscoveryReleaseDevice: typeof trpc.deviceDiscovery.releaseDevice.useMutation = trpc.deviceDiscovery.releaseDevice.useMutation\n\n/** Generated alias around `trpc.deviceDiscovery.getStatus.useQuery`. */\nexport const useDeviceDiscoveryGetStatus: typeof trpc.deviceDiscovery.getStatus.useQuery = trpc.deviceDiscovery.getStatus.useQuery\n\n/** Generated alias around `trpc.deviceManager.allocateDeviceId.useMutation`. */\nexport const useDeviceManagerAllocateDeviceId: typeof trpc.deviceManager.allocateDeviceId.useMutation = trpc.deviceManager.allocateDeviceId.useMutation\n\n/** Generated alias around `trpc.deviceManager.registerDevice.useMutation`. */\nexport const useDeviceManagerRegisterDevice: typeof trpc.deviceManager.registerDevice.useMutation = trpc.deviceManager.registerDevice.useMutation\n\n/** Generated alias around `trpc.deviceManager.removeDevice.useMutation`. */\nexport const useDeviceManagerRemoveDevice: typeof trpc.deviceManager.removeDevice.useMutation = trpc.deviceManager.removeDevice.useMutation\n\n/** Generated alias around `trpc.deviceManager.persistConfig.useMutation`. */\nexport const useDeviceManagerPersistConfig: typeof trpc.deviceManager.persistConfig.useMutation = trpc.deviceManager.persistConfig.useMutation\n\n/** Generated alias around `trpc.deviceManager.loadConfig.useQuery`. */\nexport const useDeviceManagerLoadConfig: typeof trpc.deviceManager.loadConfig.useQuery = trpc.deviceManager.loadConfig.useQuery\n\n/** Generated alias around `trpc.deviceManager.loadRuntimeState.useQuery`. */\nexport const useDeviceManagerLoadRuntimeState: typeof trpc.deviceManager.loadRuntimeState.useQuery = trpc.deviceManager.loadRuntimeState.useQuery\n\n/** Generated alias around `trpc.deviceManager.loadMeta.useQuery`. */\nexport const useDeviceManagerLoadMeta: typeof trpc.deviceManager.loadMeta.useQuery = trpc.deviceManager.loadMeta.useQuery\n\n/** Generated alias around `trpc.deviceManager.setName.useMutation`. */\nexport const useDeviceManagerSetName: typeof trpc.deviceManager.setName.useMutation = trpc.deviceManager.setName.useMutation\n\n/** Generated alias around `trpc.deviceManager.setLocation.useMutation`. */\nexport const useDeviceManagerSetLocation: typeof trpc.deviceManager.setLocation.useMutation = trpc.deviceManager.setLocation.useMutation\n\n/** Generated alias around `trpc.deviceManager.setMetadata.useMutation`. */\nexport const useDeviceManagerSetMetadata: typeof trpc.deviceManager.setMetadata.useMutation = trpc.deviceManager.setMetadata.useMutation\n\n/** Generated alias around `trpc.deviceManager.listLocations.useQuery`. */\nexport const useDeviceManagerListLocations: typeof trpc.deviceManager.listLocations.useQuery = trpc.deviceManager.listLocations.useQuery\n\n/** Generated alias around `trpc.deviceManager.addLocation.useMutation`. */\nexport const useDeviceManagerAddLocation: typeof trpc.deviceManager.addLocation.useMutation = trpc.deviceManager.addLocation.useMutation\n\n/** Generated alias around `trpc.deviceManager.removeLocation.useMutation`. */\nexport const useDeviceManagerRemoveLocation: typeof trpc.deviceManager.removeLocation.useMutation = trpc.deviceManager.removeLocation.useMutation\n\n/** Generated alias around `trpc.deviceManager.setDisabled.useMutation`. */\nexport const useDeviceManagerSetDisabled: typeof trpc.deviceManager.setDisabled.useMutation = trpc.deviceManager.setDisabled.useMutation\n\n/** Generated alias around `trpc.deviceManager.listPersistedByAddon.useQuery`. */\nexport const useDeviceManagerListPersistedByAddon: typeof trpc.deviceManager.listPersistedByAddon.useQuery = trpc.deviceManager.listPersistedByAddon.useQuery\n\n/** Generated alias around `trpc.deviceManager.listAll.useQuery`. */\nexport const useDeviceManagerListAll: typeof trpc.deviceManager.listAll.useQuery = trpc.deviceManager.listAll.useQuery\n\n/** Generated alias around `trpc.deviceManager.getDevice.useQuery`. */\nexport const useDeviceManagerGetDevice: typeof trpc.deviceManager.getDevice.useQuery = trpc.deviceManager.getDevice.useQuery\n\n/** Generated alias around `trpc.deviceManager.getChildren.useQuery`. */\nexport const useDeviceManagerGetChildren: typeof trpc.deviceManager.getChildren.useQuery = trpc.deviceManager.getChildren.useQuery\n\n/** Generated alias around `trpc.deviceManager.getStreamSources.useQuery`. */\nexport const useDeviceManagerGetStreamSources: typeof trpc.deviceManager.getStreamSources.useQuery = trpc.deviceManager.getStreamSources.useQuery\n\n/** Generated alias around `trpc.deviceManager.getConfigSchema.useQuery`. */\nexport const useDeviceManagerGetConfigSchema: typeof trpc.deviceManager.getConfigSchema.useQuery = trpc.deviceManager.getConfigSchema.useQuery\n\n/** Generated alias around `trpc.deviceManager.getSettingsSchema.useQuery`. */\nexport const useDeviceManagerGetSettingsSchema: typeof trpc.deviceManager.getSettingsSchema.useQuery = trpc.deviceManager.getSettingsSchema.useQuery\n\n/** Generated alias around `trpc.deviceManager.updateConfig.useMutation`. */\nexport const useDeviceManagerUpdateConfig: typeof trpc.deviceManager.updateConfig.useMutation = trpc.deviceManager.updateConfig.useMutation\n\n/** Generated alias around `trpc.deviceManager.enable.useMutation`. */\nexport const useDeviceManagerEnable: typeof trpc.deviceManager.enable.useMutation = trpc.deviceManager.enable.useMutation\n\n/** Generated alias around `trpc.deviceManager.disable.useMutation`. */\nexport const useDeviceManagerDisable: typeof trpc.deviceManager.disable.useMutation = trpc.deviceManager.disable.useMutation\n\n/** Generated alias around `trpc.deviceManager.remove.useMutation`. */\nexport const useDeviceManagerRemove: typeof trpc.deviceManager.remove.useMutation = trpc.deviceManager.remove.useMutation\n\n/** Generated alias around `trpc.deviceManager.getStreamProfileMap.useQuery`. */\nexport const useDeviceManagerGetStreamProfileMap: typeof trpc.deviceManager.getStreamProfileMap.useQuery = trpc.deviceManager.getStreamProfileMap.useQuery\n\n/** Generated alias around `trpc.deviceManager.setStreamProfileMap.useMutation`. */\nexport const useDeviceManagerSetStreamProfileMap: typeof trpc.deviceManager.setStreamProfileMap.useMutation = trpc.deviceManager.setStreamProfileMap.useMutation\n\n/** Generated alias around `trpc.deviceManager.probeStreams.useMutation`. */\nexport const useDeviceManagerProbeStreams: typeof trpc.deviceManager.probeStreams.useMutation = trpc.deviceManager.probeStreams.useMutation\n\n/** Generated alias around `trpc.deviceManager.getBindings.useQuery`. */\nexport const useDeviceManagerGetBindings: typeof trpc.deviceManager.getBindings.useQuery = trpc.deviceManager.getBindings.useQuery\n\n/** Generated alias around `trpc.deviceManager.getAllBindings.useQuery`. */\nexport const useDeviceManagerGetAllBindings: typeof trpc.deviceManager.getAllBindings.useQuery = trpc.deviceManager.getAllBindings.useQuery\n\n/** Generated alias around `trpc.deviceManager.setWrapperActive.useMutation`. */\nexport const useDeviceManagerSetWrapperActive: typeof trpc.deviceManager.setWrapperActive.useMutation = trpc.deviceManager.setWrapperActive.useMutation\n\n/** Generated alias around `trpc.deviceManager.listWrappersForCap.useQuery`. */\nexport const useDeviceManagerListWrappersForCap: typeof trpc.deviceManager.listWrappersForCap.useQuery = trpc.deviceManager.listWrappersForCap.useQuery\n\n/** Generated alias around `trpc.deviceManager.listBindableCapsForDeviceType.useQuery`. */\nexport const useDeviceManagerListBindableCapsForDeviceType: typeof trpc.deviceManager.listBindableCapsForDeviceType.useQuery = trpc.deviceManager.listBindableCapsForDeviceType.useQuery\n\n/** Generated alias around `trpc.deviceManager.getDeviceSettingsAggregate.useQuery`. */\nexport const useDeviceManagerGetDeviceSettingsAggregate: typeof trpc.deviceManager.getDeviceSettingsAggregate.useQuery = trpc.deviceManager.getDeviceSettingsAggregate.useQuery\n\n/** Generated alias around `trpc.deviceManager.getDeviceLiveInfoAggregate.useQuery`. */\nexport const useDeviceManagerGetDeviceLiveInfoAggregate: typeof trpc.deviceManager.getDeviceLiveInfoAggregate.useQuery = trpc.deviceManager.getDeviceLiveInfoAggregate.useQuery\n\n/** Generated alias around `trpc.deviceManager.getDeviceAggregate.useQuery`. */\nexport const useDeviceManagerGetDeviceAggregate: typeof trpc.deviceManager.getDeviceAggregate.useQuery = trpc.deviceManager.getDeviceAggregate.useQuery\n\n/** Generated alias around `trpc.deviceManager.updateDeviceField.useMutation`. */\nexport const useDeviceManagerUpdateDeviceField: typeof trpc.deviceManager.updateDeviceField.useMutation = trpc.deviceManager.updateDeviceField.useMutation\n\n/** Generated alias around `trpc.deviceManager.updateDeviceFieldsBatch.useMutation`. */\nexport const useDeviceManagerUpdateDeviceFieldsBatch: typeof trpc.deviceManager.updateDeviceFieldsBatch.useMutation = trpc.deviceManager.updateDeviceFieldsBatch.useMutation\n\n/** Generated alias around `trpc.deviceManager.discoverDevices.useMutation`. */\nexport const useDeviceManagerDiscoverDevices: typeof trpc.deviceManager.discoverDevices.useMutation = trpc.deviceManager.discoverDevices.useMutation\n\n/** Generated alias around `trpc.deviceManager.adoptDevice.useMutation`. */\nexport const useDeviceManagerAdoptDevice: typeof trpc.deviceManager.adoptDevice.useMutation = trpc.deviceManager.adoptDevice.useMutation\n\n/** Generated alias around `trpc.deviceManager.getCreationSchema.useQuery`. */\nexport const useDeviceManagerGetCreationSchema: typeof trpc.deviceManager.getCreationSchema.useQuery = trpc.deviceManager.getCreationSchema.useQuery\n\n/** Generated alias around `trpc.deviceManager.createDevice.useMutation`. */\nexport const useDeviceManagerCreateDevice: typeof trpc.deviceManager.createDevice.useMutation = trpc.deviceManager.createDevice.useMutation\n\n/** Generated alias around `trpc.deviceManager.testCreationField.useMutation`. */\nexport const useDeviceManagerTestCreationField: typeof trpc.deviceManager.testCreationField.useMutation = trpc.deviceManager.testCreationField.useMutation\n\n/** Generated alias around `trpc.deviceManager.testField.useMutation`. */\nexport const useDeviceManagerTestField: typeof trpc.deviceManager.testField.useMutation = trpc.deviceManager.testField.useMutation\n\n/** Generated alias around `trpc.deviceManager.getDeviceStatusAggregate.useQuery`. */\nexport const useDeviceManagerGetDeviceStatusAggregate: typeof trpc.deviceManager.getDeviceStatusAggregate.useQuery = trpc.deviceManager.getDeviceStatusAggregate.useQuery\n\n/** Generated alias around `trpc.deviceOps.getStreamSources.useQuery`. */\nexport const useDeviceOpsGetStreamSources: typeof trpc.deviceOps.getStreamSources.useQuery = trpc.deviceOps.getStreamSources.useQuery\n\n/** Generated alias around `trpc.deviceOps.getConfigEntries.useQuery`. */\nexport const useDeviceOpsGetConfigEntries: typeof trpc.deviceOps.getConfigEntries.useQuery = trpc.deviceOps.getConfigEntries.useQuery\n\n/** Generated alias around `trpc.deviceOps.setConfig.useMutation`. */\nexport const useDeviceOpsSetConfig: typeof trpc.deviceOps.setConfig.useMutation = trpc.deviceOps.setConfig.useMutation\n\n/** Generated alias around `trpc.deviceOps.removeDevice.useMutation`. */\nexport const useDeviceOpsRemoveDevice: typeof trpc.deviceOps.removeDevice.useMutation = trpc.deviceOps.removeDevice.useMutation\n\n/** Generated alias around `trpc.deviceOps.getSettingsSchema.useQuery`. */\nexport const useDeviceOpsGetSettingsSchema: typeof trpc.deviceOps.getSettingsSchema.useQuery = trpc.deviceOps.getSettingsSchema.useQuery\n\n/** Generated alias around `trpc.deviceProvider.start.useMutation`. */\nexport const useDeviceProviderStart: typeof trpc.deviceProvider.start.useMutation = trpc.deviceProvider.start.useMutation\n\n/** Generated alias around `trpc.deviceProvider.stop.useMutation`. */\nexport const useDeviceProviderStop: typeof trpc.deviceProvider.stop.useMutation = trpc.deviceProvider.stop.useMutation\n\n/** Generated alias around `trpc.deviceProvider.getStatus.useQuery`. */\nexport const useDeviceProviderGetStatus: typeof trpc.deviceProvider.getStatus.useQuery = trpc.deviceProvider.getStatus.useQuery\n\n/** Generated alias around `trpc.deviceProvider.getDevices.useQuery`. */\nexport const useDeviceProviderGetDevices: typeof trpc.deviceProvider.getDevices.useQuery = trpc.deviceProvider.getDevices.useQuery\n\n/** Generated alias around `trpc.deviceProvider.supportsDiscovery.useQuery`. */\nexport const useDeviceProviderSupportsDiscovery: typeof trpc.deviceProvider.supportsDiscovery.useQuery = trpc.deviceProvider.supportsDiscovery.useQuery\n\n/** Generated alias around `trpc.deviceProvider.discoverDevices.useMutation`. */\nexport const useDeviceProviderDiscoverDevices: typeof trpc.deviceProvider.discoverDevices.useMutation = trpc.deviceProvider.discoverDevices.useMutation\n\n/** Generated alias around `trpc.deviceProvider.adoptDiscoveredDevice.useMutation`. */\nexport const useDeviceProviderAdoptDiscoveredDevice: typeof trpc.deviceProvider.adoptDiscoveredDevice.useMutation = trpc.deviceProvider.adoptDiscoveredDevice.useMutation\n\n/** Generated alias around `trpc.deviceProvider.supportsManualCreation.useQuery`. */\nexport const useDeviceProviderSupportsManualCreation: typeof trpc.deviceProvider.supportsManualCreation.useQuery = trpc.deviceProvider.supportsManualCreation.useQuery\n\n/** Generated alias around `trpc.deviceProvider.getChildCreationSchema.useQuery`. */\nexport const useDeviceProviderGetChildCreationSchema: typeof trpc.deviceProvider.getChildCreationSchema.useQuery = trpc.deviceProvider.getChildCreationSchema.useQuery\n\n/** Generated alias around `trpc.deviceProvider.createDevice.useMutation`. */\nexport const useDeviceProviderCreateDevice: typeof trpc.deviceProvider.createDevice.useMutation = trpc.deviceProvider.createDevice.useMutation\n\n/** Generated alias around `trpc.deviceProvider.testCreationField.useMutation`. */\nexport const useDeviceProviderTestCreationField: typeof trpc.deviceProvider.testCreationField.useMutation = trpc.deviceProvider.testCreationField.useMutation\n\n/** Generated alias around `trpc.deviceState.getSnapshot.useQuery`. */\nexport const useDeviceStateGetSnapshot: typeof trpc.deviceState.getSnapshot.useQuery = trpc.deviceState.getSnapshot.useQuery\n\n/** Generated alias around `trpc.deviceState.getCapSlice.useQuery`. */\nexport const useDeviceStateGetCapSlice: typeof trpc.deviceState.getCapSlice.useQuery = trpc.deviceState.getCapSlice.useQuery\n\n/** Generated alias around `trpc.deviceState.getAllSnapshots.useQuery`. */\nexport const useDeviceStateGetAllSnapshots: typeof trpc.deviceState.getAllSnapshots.useQuery = trpc.deviceState.getAllSnapshots.useQuery\n\n/** Generated alias around `trpc.deviceState.setCapSlice.useMutation`. */\nexport const useDeviceStateSetCapSlice: typeof trpc.deviceState.setCapSlice.useMutation = trpc.deviceState.setCapSlice.useMutation\n\n/** Generated alias around `trpc.doorbell.getStatus.useQuery`. */\nexport const useDoorbellGetStatus: typeof trpc.doorbell.getStatus.useQuery = trpc.doorbell.getStatus.useQuery\n\n/** Generated alias around `trpc.events.getEvents.useQuery`. */\nexport const useEventsGetEvents: typeof trpc.events.getEvents.useQuery = trpc.events.getEvents.useQuery\n\n/** Generated alias around `trpc.events.getEventThumbnail.useQuery`. */\nexport const useEventsGetEventThumbnail: typeof trpc.events.getEventThumbnail.useQuery = trpc.events.getEventThumbnail.useQuery\n\n/** Generated alias around `trpc.events.getEventClipUrl.useQuery`. */\nexport const useEventsGetEventClipUrl: typeof trpc.events.getEventClipUrl.useQuery = trpc.events.getEventClipUrl.useQuery\n\n/** Generated alias around `trpc.integrations.list.useQuery`. */\nexport const useIntegrationsList: typeof trpc.integrations.list.useQuery = trpc.integrations.list.useQuery\n\n/** Generated alias around `trpc.integrations.get.useQuery`. */\nexport const useIntegrationsGet: typeof trpc.integrations.get.useQuery = trpc.integrations.get.useQuery\n\n/** Generated alias around `trpc.integrations.getByAddonId.useQuery`. */\nexport const useIntegrationsGetByAddonId: typeof trpc.integrations.getByAddonId.useQuery = trpc.integrations.getByAddonId.useQuery\n\n/** Generated alias around `trpc.integrations.create.useMutation`. */\nexport const useIntegrationsCreate: typeof trpc.integrations.create.useMutation = trpc.integrations.create.useMutation\n\n/** Generated alias around `trpc.integrations.update.useMutation`. */\nexport const useIntegrationsUpdate: typeof trpc.integrations.update.useMutation = trpc.integrations.update.useMutation\n\n/** Generated alias around `trpc.integrations.delete.useMutation`. */\nexport const useIntegrationsDelete: typeof trpc.integrations.delete.useMutation = trpc.integrations.delete.useMutation\n\n/** Generated alias around `trpc.integrations.getSettings.useQuery`. */\nexport const useIntegrationsGetSettings: typeof trpc.integrations.getSettings.useQuery = trpc.integrations.getSettings.useQuery\n\n/** Generated alias around `trpc.integrations.setSettings.useMutation`. */\nexport const useIntegrationsSetSettings: typeof trpc.integrations.setSettings.useMutation = trpc.integrations.setSettings.useMutation\n\n/** Generated alias around `trpc.integrations.getAvailableTypes.useQuery`. */\nexport const useIntegrationsGetAvailableTypes: typeof trpc.integrations.getAvailableTypes.useQuery = trpc.integrations.getAvailableTypes.useQuery\n\n/** Generated alias around `trpc.integrations.testConnection.useMutation`. */\nexport const useIntegrationsTestConnection: typeof trpc.integrations.testConnection.useMutation = trpc.integrations.testConnection.useMutation\n\n/** Generated alias around `trpc.intercom.startSession.useMutation`. */\nexport const useIntercomStartSession: typeof trpc.intercom.startSession.useMutation = trpc.intercom.startSession.useMutation\n\n/** Generated alias around `trpc.intercom.handleAnswer.useMutation`. */\nexport const useIntercomHandleAnswer: typeof trpc.intercom.handleAnswer.useMutation = trpc.intercom.handleAnswer.useMutation\n\n/** Generated alias around `trpc.intercom.stopSession.useMutation`. */\nexport const useIntercomStopSession: typeof trpc.intercom.stopSession.useMutation = trpc.intercom.stopSession.useMutation\n\n/** Generated alias around `trpc.intercom.getStatus.useQuery`. */\nexport const useIntercomGetStatus: typeof trpc.intercom.getStatus.useQuery = trpc.intercom.getStatus.useQuery\n\n/** Generated alias around `trpc.metricsProvider.collectSnapshot.useQuery`. */\nexport const useMetricsProviderCollectSnapshot: typeof trpc.metricsProvider.collectSnapshot.useQuery = trpc.metricsProvider.collectSnapshot.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getCached.useQuery`. */\nexport const useMetricsProviderGetCached: typeof trpc.metricsProvider.getCached.useQuery = trpc.metricsProvider.getCached.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getCurrent.useQuery`. */\nexport const useMetricsProviderGetCurrent: typeof trpc.metricsProvider.getCurrent.useQuery = trpc.metricsProvider.getCurrent.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getDiskSpace.useQuery`. */\nexport const useMetricsProviderGetDiskSpace: typeof trpc.metricsProvider.getDiskSpace.useQuery = trpc.metricsProvider.getDiskSpace.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getGpuInfo.useQuery`. */\nexport const useMetricsProviderGetGpuInfo: typeof trpc.metricsProvider.getGpuInfo.useQuery = trpc.metricsProvider.getGpuInfo.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getCpuTemperature.useQuery`. */\nexport const useMetricsProviderGetCpuTemperature: typeof trpc.metricsProvider.getCpuTemperature.useQuery = trpc.metricsProvider.getCpuTemperature.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getProcessStats.useQuery`. */\nexport const useMetricsProviderGetProcessStats: typeof trpc.metricsProvider.getProcessStats.useQuery = trpc.metricsProvider.getProcessStats.useQuery\n\n/** Generated alias around `trpc.metricsProvider.listAddonInstances.useQuery`. */\nexport const useMetricsProviderListAddonInstances: typeof trpc.metricsProvider.listAddonInstances.useQuery = trpc.metricsProvider.listAddonInstances.useQuery\n\n/** Generated alias around `trpc.metricsProvider.getAddonStats.useQuery`. */\nexport const useMetricsProviderGetAddonStats: typeof trpc.metricsProvider.getAddonStats.useQuery = trpc.metricsProvider.getAddonStats.useQuery\n\n/** Generated alias around `trpc.metricsProvider.listNodeProcesses.useQuery`. */\nexport const useMetricsProviderListNodeProcesses: typeof trpc.metricsProvider.listNodeProcesses.useQuery = trpc.metricsProvider.listNodeProcesses.useQuery\n\n/** Generated alias around `trpc.metricsProvider.killProcess.useMutation`. */\nexport const useMetricsProviderKillProcess: typeof trpc.metricsProvider.killProcess.useMutation = trpc.metricsProvider.killProcess.useMutation\n\n/** Generated alias around `trpc.motion.isDetected.useQuery`. */\nexport const useMotionIsDetected: typeof trpc.motion.isDetected.useQuery = trpc.motion.isDetected.useQuery\n\n/** Generated alias around `trpc.motion.getStatus.useQuery`. */\nexport const useMotionGetStatus: typeof trpc.motion.getStatus.useQuery = trpc.motion.getStatus.useQuery\n\n/** Generated alias around `trpc.motionDetection.analyze.useMutation`. */\nexport const useMotionDetectionAnalyze: typeof trpc.motionDetection.analyze.useMutation = trpc.motionDetection.analyze.useMutation\n\n/** Generated alias around `trpc.motionDetection.removeCamera.useMutation`. */\nexport const useMotionDetectionRemoveCamera: typeof trpc.motionDetection.removeCamera.useMutation = trpc.motionDetection.removeCamera.useMutation\n\n/** Generated alias around `trpc.motionDetection.reset.useMutation`. */\nexport const useMotionDetectionReset: typeof trpc.motionDetection.reset.useMutation = trpc.motionDetection.reset.useMutation\n\n/** Generated alias around `trpc.motionDetection.getDeviceSettingsContribution.useQuery`. */\nexport const useMotionDetectionGetDeviceSettingsContribution: typeof trpc.motionDetection.getDeviceSettingsContribution.useQuery = trpc.motionDetection.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.motionDetection.getDeviceLiveContribution.useQuery`. */\nexport const useMotionDetectionGetDeviceLiveContribution: typeof trpc.motionDetection.getDeviceLiveContribution.useQuery = trpc.motionDetection.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.motionDetection.applyDeviceSettingsPatch.useMutation`. */\nexport const useMotionDetectionApplyDeviceSettingsPatch: typeof trpc.motionDetection.applyDeviceSettingsPatch.useMutation = trpc.motionDetection.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.motionTrigger.setMotionTrigger.useMutation`. */\nexport const useMotionTriggerSetMotionTrigger: typeof trpc.motionTrigger.setMotionTrigger.useMutation = trpc.motionTrigger.setMotionTrigger.useMutation\n\n/** Generated alias around `trpc.motionTrigger.getStatus.useQuery`. */\nexport const useMotionTriggerGetStatus: typeof trpc.motionTrigger.getStatus.useQuery = trpc.motionTrigger.getStatus.useQuery\n\n/** Generated alias around `trpc.nativeObjectDetection.getStatus.useQuery`. */\nexport const useNativeObjectDetectionGetStatus: typeof trpc.nativeObjectDetection.getStatus.useQuery = trpc.nativeObjectDetection.getStatus.useQuery\n\n/** Generated alias around `trpc.networkQuality.getDeviceStats.useQuery`. */\nexport const useNetworkQualityGetDeviceStats: typeof trpc.networkQuality.getDeviceStats.useQuery = trpc.networkQuality.getDeviceStats.useQuery\n\n/** Generated alias around `trpc.networkQuality.getAllStats.useQuery`. */\nexport const useNetworkQualityGetAllStats: typeof trpc.networkQuality.getAllStats.useQuery = trpc.networkQuality.getAllStats.useQuery\n\n/** Generated alias around `trpc.networkQuality.reportClientStats.useMutation`. */\nexport const useNetworkQualityReportClientStats: typeof trpc.networkQuality.reportClientStats.useMutation = trpc.networkQuality.reportClientStats.useMutation\n\n/** Generated alias around `trpc.nodes.topology.useQuery`. */\nexport const useNodesTopology: typeof trpc.nodes.topology.useQuery = trpc.nodes.topology.useQuery\n\n/** Generated alias around `trpc.nodes.deployAddon.useMutation`. */\nexport const useNodesDeployAddon: typeof trpc.nodes.deployAddon.useMutation = trpc.nodes.deployAddon.useMutation\n\n/** Generated alias around `trpc.nodes.undeployAddon.useMutation`. */\nexport const useNodesUndeployAddon: typeof trpc.nodes.undeployAddon.useMutation = trpc.nodes.undeployAddon.useMutation\n\n/** Generated alias around `trpc.nodes.restartAddon.useMutation`. */\nexport const useNodesRestartAddon: typeof trpc.nodes.restartAddon.useMutation = trpc.nodes.restartAddon.useMutation\n\n/** Generated alias around `trpc.nodes.restartProcess.useMutation`. */\nexport const useNodesRestartProcess: typeof trpc.nodes.restartProcess.useMutation = trpc.nodes.restartProcess.useMutation\n\n/** Generated alias around `trpc.nodes.restartNode.useMutation`. */\nexport const useNodesRestartNode: typeof trpc.nodes.restartNode.useMutation = trpc.nodes.restartNode.useMutation\n\n/** Generated alias around `trpc.nodes.shutdownNode.useMutation`. */\nexport const useNodesShutdownNode: typeof trpc.nodes.shutdownNode.useMutation = trpc.nodes.shutdownNode.useMutation\n\n/** Generated alias around `trpc.nodes.renameNode.useMutation`. */\nexport const useNodesRenameNode: typeof trpc.nodes.renameNode.useMutation = trpc.nodes.renameNode.useMutation\n\n/** Generated alias around `trpc.nodes.clusterAddonStatus.useQuery`. */\nexport const useNodesClusterAddonStatus: typeof trpc.nodes.clusterAddonStatus.useQuery = trpc.nodes.clusterAddonStatus.useQuery\n\n/** Generated alias around `trpc.nodes.setProcessLogLevel.useMutation`. */\nexport const useNodesSetProcessLogLevel: typeof trpc.nodes.setProcessLogLevel.useMutation = trpc.nodes.setProcessLogLevel.useMutation\n\n/** Generated alias around `trpc.nodes.executeQuery.useMutation`. */\nexport const useNodesExecuteQuery: typeof trpc.nodes.executeQuery.useMutation = trpc.nodes.executeQuery.useMutation\n\n/** Generated alias around `trpc.notificationOutput.send.useMutation`. */\nexport const useNotificationOutputSend: typeof trpc.notificationOutput.send.useMutation = trpc.notificationOutput.send.useMutation\n\n/** Generated alias around `trpc.notificationOutput.sendTest.useMutation`. */\nexport const useNotificationOutputSendTest: typeof trpc.notificationOutput.sendTest.useMutation = trpc.notificationOutput.sendTest.useMutation\n\n/** Generated alias around `trpc.osd.setOverlay.useMutation`. */\nexport const useOsdSetOverlay: typeof trpc.osd.setOverlay.useMutation = trpc.osd.setOverlay.useMutation\n\n/** Generated alias around `trpc.osd.getStatus.useQuery`. */\nexport const useOsdGetStatus: typeof trpc.osd.getStatus.useQuery = trpc.osd.getStatus.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getActiveTracks.useQuery`. */\nexport const usePipelineAnalyticsGetActiveTracks: typeof trpc.pipelineAnalytics.getActiveTracks.useQuery = trpc.pipelineAnalytics.getActiveTracks.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getTrack.useQuery`. */\nexport const usePipelineAnalyticsGetTrack: typeof trpc.pipelineAnalytics.getTrack.useQuery = trpc.pipelineAnalytics.getTrack.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.listTracks.useQuery`. */\nexport const usePipelineAnalyticsListTracks: typeof trpc.pipelineAnalytics.listTracks.useQuery = trpc.pipelineAnalytics.listTracks.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.clearTracks.useMutation`. */\nexport const usePipelineAnalyticsClearTracks: typeof trpc.pipelineAnalytics.clearTracks.useMutation = trpc.pipelineAnalytics.clearTracks.useMutation\n\n/** Generated alias around `trpc.pipelineAnalytics.getMotionEvents.useQuery`. */\nexport const usePipelineAnalyticsGetMotionEvents: typeof trpc.pipelineAnalytics.getMotionEvents.useQuery = trpc.pipelineAnalytics.getMotionEvents.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getObjectEvents.useQuery`. */\nexport const usePipelineAnalyticsGetObjectEvents: typeof trpc.pipelineAnalytics.getObjectEvents.useQuery = trpc.pipelineAnalytics.getObjectEvents.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getAudioEvents.useQuery`. */\nexport const usePipelineAnalyticsGetAudioEvents: typeof trpc.pipelineAnalytics.getAudioEvents.useQuery = trpc.pipelineAnalytics.getAudioEvents.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getEventMedia.useQuery`. */\nexport const usePipelineAnalyticsGetEventMedia: typeof trpc.pipelineAnalytics.getEventMedia.useQuery = trpc.pipelineAnalytics.getEventMedia.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getTrackMedia.useQuery`. */\nexport const usePipelineAnalyticsGetTrackMedia: typeof trpc.pipelineAnalytics.getTrackMedia.useQuery = trpc.pipelineAnalytics.getTrackMedia.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getDeviceSettingsContribution.useQuery`. */\nexport const usePipelineAnalyticsGetDeviceSettingsContribution: typeof trpc.pipelineAnalytics.getDeviceSettingsContribution.useQuery = trpc.pipelineAnalytics.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.getDeviceLiveContribution.useQuery`. */\nexport const usePipelineAnalyticsGetDeviceLiveContribution: typeof trpc.pipelineAnalytics.getDeviceLiveContribution.useQuery = trpc.pipelineAnalytics.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.pipelineAnalytics.applyDeviceSettingsPatch.useMutation`. */\nexport const usePipelineAnalyticsApplyDeviceSettingsPatch: typeof trpc.pipelineAnalytics.applyDeviceSettingsPatch.useMutation = trpc.pipelineAnalytics.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.getAvailableEngines.useQuery`. */\nexport const usePipelineExecutorGetAvailableEngines: typeof trpc.pipelineExecutor.getAvailableEngines.useQuery = trpc.pipelineExecutor.getAvailableEngines.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getSelectedEngine.useQuery`. */\nexport const usePipelineExecutorGetSelectedEngine: typeof trpc.pipelineExecutor.getSelectedEngine.useQuery = trpc.pipelineExecutor.getSelectedEngine.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getDefaultSteps.useQuery`. */\nexport const usePipelineExecutorGetDefaultSteps: typeof trpc.pipelineExecutor.getDefaultSteps.useQuery = trpc.pipelineExecutor.getDefaultSteps.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.reprobeEngine.useMutation`. */\nexport const usePipelineExecutorReprobeEngine: typeof trpc.pipelineExecutor.reprobeEngine.useMutation = trpc.pipelineExecutor.reprobeEngine.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.getVideoPipelineSteps.useQuery`. */\nexport const usePipelineExecutorGetVideoPipelineSteps: typeof trpc.pipelineExecutor.getVideoPipelineSteps.useQuery = trpc.pipelineExecutor.getVideoPipelineSteps.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.setVideoPipelineSteps.useMutation`. */\nexport const usePipelineExecutorSetVideoPipelineSteps: typeof trpc.pipelineExecutor.setVideoPipelineSteps.useMutation = trpc.pipelineExecutor.setVideoPipelineSteps.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.getSchema.useQuery`. */\nexport const usePipelineExecutorGetSchema: typeof trpc.pipelineExecutor.getSchema.useQuery = trpc.pipelineExecutor.getSchema.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getGlobalSteps.useQuery`. */\nexport const usePipelineExecutorGetGlobalSteps: typeof trpc.pipelineExecutor.getGlobalSteps.useQuery = trpc.pipelineExecutor.getGlobalSteps.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getGlobalPipelineConfig.useQuery`. */\nexport const usePipelineExecutorGetGlobalPipelineConfig: typeof trpc.pipelineExecutor.getGlobalPipelineConfig.useQuery = trpc.pipelineExecutor.getGlobalPipelineConfig.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery`. */\nexport const usePipelineExecutorGetOrchestratorConfigSchema: typeof trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery = trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.listTemplates.useQuery`. */\nexport const usePipelineExecutorListTemplates: typeof trpc.pipelineExecutor.listTemplates.useQuery = trpc.pipelineExecutor.listTemplates.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.saveTemplate.useMutation`. */\nexport const usePipelineExecutorSaveTemplate: typeof trpc.pipelineExecutor.saveTemplate.useMutation = trpc.pipelineExecutor.saveTemplate.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.updateTemplate.useMutation`. */\nexport const usePipelineExecutorUpdateTemplate: typeof trpc.pipelineExecutor.updateTemplate.useMutation = trpc.pipelineExecutor.updateTemplate.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.deleteTemplate.useMutation`. */\nexport const usePipelineExecutorDeleteTemplate: typeof trpc.pipelineExecutor.deleteTemplate.useMutation = trpc.pipelineExecutor.deleteTemplate.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.getCapabilities.useQuery`. */\nexport const usePipelineExecutorGetCapabilities: typeof trpc.pipelineExecutor.getCapabilities.useQuery = trpc.pipelineExecutor.getCapabilities.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getAddonModels.useQuery`. */\nexport const usePipelineExecutorGetAddonModels: typeof trpc.pipelineExecutor.getAddonModels.useQuery = trpc.pipelineExecutor.getAddonModels.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.downloadModel.useMutation`. */\nexport const usePipelineExecutorDownloadModel: typeof trpc.pipelineExecutor.downloadModel.useMutation = trpc.pipelineExecutor.downloadModel.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.deleteModel.useMutation`. */\nexport const usePipelineExecutorDeleteModel: typeof trpc.pipelineExecutor.deleteModel.useMutation = trpc.pipelineExecutor.deleteModel.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.detect.useQuery`. */\nexport const usePipelineExecutorDetect: typeof trpc.pipelineExecutor.detect.useQuery = trpc.pipelineExecutor.detect.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.runPipeline.useMutation`. */\nexport const usePipelineExecutorRunPipeline: typeof trpc.pipelineExecutor.runPipeline.useMutation = trpc.pipelineExecutor.runPipeline.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.runPipelineBatch.useMutation`. */\nexport const usePipelineExecutorRunPipelineBatch: typeof trpc.pipelineExecutor.runPipelineBatch.useMutation = trpc.pipelineExecutor.runPipelineBatch.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.cacheFrameInPool.useMutation`. */\nexport const usePipelineExecutorCacheFrameInPool: typeof trpc.pipelineExecutor.cacheFrameInPool.useMutation = trpc.pipelineExecutor.cacheFrameInPool.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.inferCached.useMutation`. */\nexport const usePipelineExecutorInferCached: typeof trpc.pipelineExecutor.inferCached.useMutation = trpc.pipelineExecutor.inferCached.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.uncacheFrame.useMutation`. */\nexport const usePipelineExecutorUncacheFrame: typeof trpc.pipelineExecutor.uncacheFrame.useMutation = trpc.pipelineExecutor.uncacheFrame.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.getEffectiveTuning.useQuery`. */\nexport const usePipelineExecutorGetEffectiveTuning: typeof trpc.pipelineExecutor.getEffectiveTuning.useQuery = trpc.pipelineExecutor.getEffectiveTuning.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.listLoadedEngines.useQuery`. */\nexport const usePipelineExecutorListLoadedEngines: typeof trpc.pipelineExecutor.listLoadedEngines.useQuery = trpc.pipelineExecutor.listLoadedEngines.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.spinEngine.useMutation`. */\nexport const usePipelineExecutorSpinEngine: typeof trpc.pipelineExecutor.spinEngine.useMutation = trpc.pipelineExecutor.spinEngine.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.killEngine.useMutation`. */\nexport const usePipelineExecutorKillEngine: typeof trpc.pipelineExecutor.killEngine.useMutation = trpc.pipelineExecutor.killEngine.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.listReferenceImages.useQuery`. */\nexport const usePipelineExecutorListReferenceImages: typeof trpc.pipelineExecutor.listReferenceImages.useQuery = trpc.pipelineExecutor.listReferenceImages.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getReferenceImage.useQuery`. */\nexport const usePipelineExecutorGetReferenceImage: typeof trpc.pipelineExecutor.getReferenceImage.useQuery = trpc.pipelineExecutor.getReferenceImage.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getReferenceAudioFiles.useQuery`. */\nexport const usePipelineExecutorGetReferenceAudioFiles: typeof trpc.pipelineExecutor.getReferenceAudioFiles.useQuery = trpc.pipelineExecutor.getReferenceAudioFiles.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getReferenceAudio.useQuery`. */\nexport const usePipelineExecutorGetReferenceAudio: typeof trpc.pipelineExecutor.getReferenceAudio.useQuery = trpc.pipelineExecutor.getReferenceAudio.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.getAudioCapabilities.useQuery`. */\nexport const usePipelineExecutorGetAudioCapabilities: typeof trpc.pipelineExecutor.getAudioCapabilities.useQuery = trpc.pipelineExecutor.getAudioCapabilities.useQuery\n\n/** Generated alias around `trpc.pipelineExecutor.runAudioTest.useMutation`. */\nexport const usePipelineExecutorRunAudioTest: typeof trpc.pipelineExecutor.runAudioTest.useMutation = trpc.pipelineExecutor.runAudioTest.useMutation\n\n/** Generated alias around `trpc.pipelineExecutor.getDetectionConfigSchema.useQuery`. */\nexport const usePipelineExecutorGetDetectionConfigSchema: typeof trpc.pipelineExecutor.getDetectionConfigSchema.useQuery = trpc.pipelineExecutor.getDetectionConfigSchema.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.assignPipeline.useMutation`. */\nexport const usePipelineOrchestratorAssignPipeline: typeof trpc.pipelineOrchestrator.assignPipeline.useMutation = trpc.pipelineOrchestrator.assignPipeline.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.unassignPipeline.useMutation`. */\nexport const usePipelineOrchestratorUnassignPipeline: typeof trpc.pipelineOrchestrator.unassignPipeline.useMutation = trpc.pipelineOrchestrator.unassignPipeline.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.rebalance.useMutation`. */\nexport const usePipelineOrchestratorRebalance: typeof trpc.pipelineOrchestrator.rebalance.useMutation = trpc.pipelineOrchestrator.rebalance.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.getPipelineAssignments.useQuery`. */\nexport const usePipelineOrchestratorGetPipelineAssignments: typeof trpc.pipelineOrchestrator.getPipelineAssignments.useQuery = trpc.pipelineOrchestrator.getPipelineAssignments.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getPipelineAssignment.useQuery`. */\nexport const usePipelineOrchestratorGetPipelineAssignment: typeof trpc.pipelineOrchestrator.getPipelineAssignment.useQuery = trpc.pipelineOrchestrator.getPipelineAssignment.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getAgentLoad.useQuery`. */\nexport const usePipelineOrchestratorGetAgentLoad: typeof trpc.pipelineOrchestrator.getAgentLoad.useQuery = trpc.pipelineOrchestrator.getAgentLoad.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getGlobalMetrics.useQuery`. */\nexport const usePipelineOrchestratorGetGlobalMetrics: typeof trpc.pipelineOrchestrator.getGlobalMetrics.useQuery = trpc.pipelineOrchestrator.getGlobalMetrics.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getCameraMetrics.useQuery`. */\nexport const usePipelineOrchestratorGetCameraMetrics: typeof trpc.pipelineOrchestrator.getCameraMetrics.useQuery = trpc.pipelineOrchestrator.getCameraMetrics.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getCapabilityBindings.useQuery`. */\nexport const usePipelineOrchestratorGetCapabilityBindings: typeof trpc.pipelineOrchestrator.getCapabilityBindings.useQuery = trpc.pipelineOrchestrator.getCapabilityBindings.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.setCapabilityBinding.useMutation`. */\nexport const usePipelineOrchestratorSetCapabilityBinding: typeof trpc.pipelineOrchestrator.setCapabilityBinding.useMutation = trpc.pipelineOrchestrator.setCapabilityBinding.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.assignDecoder.useMutation`. */\nexport const usePipelineOrchestratorAssignDecoder: typeof trpc.pipelineOrchestrator.assignDecoder.useMutation = trpc.pipelineOrchestrator.assignDecoder.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.unassignDecoder.useMutation`. */\nexport const usePipelineOrchestratorUnassignDecoder: typeof trpc.pipelineOrchestrator.unassignDecoder.useMutation = trpc.pipelineOrchestrator.unassignDecoder.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.getDecoderAssignments.useQuery`. */\nexport const usePipelineOrchestratorGetDecoderAssignments: typeof trpc.pipelineOrchestrator.getDecoderAssignments.useQuery = trpc.pipelineOrchestrator.getDecoderAssignments.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.assignAudio.useMutation`. */\nexport const usePipelineOrchestratorAssignAudio: typeof trpc.pipelineOrchestrator.assignAudio.useMutation = trpc.pipelineOrchestrator.assignAudio.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.unassignAudio.useMutation`. */\nexport const usePipelineOrchestratorUnassignAudio: typeof trpc.pipelineOrchestrator.unassignAudio.useMutation = trpc.pipelineOrchestrator.unassignAudio.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.getAudioAssignment.useQuery`. */\nexport const usePipelineOrchestratorGetAudioAssignment: typeof trpc.pipelineOrchestrator.getAudioAssignment.useQuery = trpc.pipelineOrchestrator.getAudioAssignment.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getAudioNodeLoad.useQuery`. */\nexport const usePipelineOrchestratorGetAudioNodeLoad: typeof trpc.pipelineOrchestrator.getAudioNodeLoad.useQuery = trpc.pipelineOrchestrator.getAudioNodeLoad.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getAudioAssignments.useQuery`. */\nexport const usePipelineOrchestratorGetAudioAssignments: typeof trpc.pipelineOrchestrator.getAudioAssignments.useQuery = trpc.pipelineOrchestrator.getAudioAssignments.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getDecoderAssignment.useQuery`. */\nexport const usePipelineOrchestratorGetDecoderAssignment: typeof trpc.pipelineOrchestrator.getDecoderAssignment.useQuery = trpc.pipelineOrchestrator.getDecoderAssignment.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getAgentSettings.useQuery`. */\nexport const usePipelineOrchestratorGetAgentSettings: typeof trpc.pipelineOrchestrator.getAgentSettings.useQuery = trpc.pipelineOrchestrator.getAgentSettings.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.listAgentSettings.useQuery`. */\nexport const usePipelineOrchestratorListAgentSettings: typeof trpc.pipelineOrchestrator.listAgentSettings.useQuery = trpc.pipelineOrchestrator.listAgentSettings.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.setAgentAddonDefaults.useMutation`. */\nexport const usePipelineOrchestratorSetAgentAddonDefaults: typeof trpc.pipelineOrchestrator.setAgentAddonDefaults.useMutation = trpc.pipelineOrchestrator.setAgentAddonDefaults.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.removeAgentSettings.useMutation`. */\nexport const usePipelineOrchestratorRemoveAgentSettings: typeof trpc.pipelineOrchestrator.removeAgentSettings.useMutation = trpc.pipelineOrchestrator.removeAgentSettings.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.getCameraSettings.useQuery`. */\nexport const usePipelineOrchestratorGetCameraSettings: typeof trpc.pipelineOrchestrator.getCameraSettings.useQuery = trpc.pipelineOrchestrator.getCameraSettings.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.setCameraStepToggle.useMutation`. */\nexport const usePipelineOrchestratorSetCameraStepToggle: typeof trpc.pipelineOrchestrator.setCameraStepToggle.useMutation = trpc.pipelineOrchestrator.setCameraStepToggle.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.getCameraStepOverrides.useQuery`. */\nexport const usePipelineOrchestratorGetCameraStepOverrides: typeof trpc.pipelineOrchestrator.getCameraStepOverrides.useQuery = trpc.pipelineOrchestrator.getCameraStepOverrides.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.setCameraStepOverride.useMutation`. */\nexport const usePipelineOrchestratorSetCameraStepOverride: typeof trpc.pipelineOrchestrator.setCameraStepOverride.useMutation = trpc.pipelineOrchestrator.setCameraStepOverride.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.setCameraPipelineForAgent.useMutation`. */\nexport const usePipelineOrchestratorSetCameraPipelineForAgent: typeof trpc.pipelineOrchestrator.setCameraPipelineForAgent.useMutation = trpc.pipelineOrchestrator.setCameraPipelineForAgent.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.resolvePipeline.useQuery`. */\nexport const usePipelineOrchestratorResolvePipeline: typeof trpc.pipelineOrchestrator.resolvePipeline.useQuery = trpc.pipelineOrchestrator.resolvePipeline.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.listTemplates.useQuery`. */\nexport const usePipelineOrchestratorListTemplates: typeof trpc.pipelineOrchestrator.listTemplates.useQuery = trpc.pipelineOrchestrator.listTemplates.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.saveTemplate.useMutation`. */\nexport const usePipelineOrchestratorSaveTemplate: typeof trpc.pipelineOrchestrator.saveTemplate.useMutation = trpc.pipelineOrchestrator.saveTemplate.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.updateTemplate.useMutation`. */\nexport const usePipelineOrchestratorUpdateTemplate: typeof trpc.pipelineOrchestrator.updateTemplate.useMutation = trpc.pipelineOrchestrator.updateTemplate.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.deleteTemplate.useMutation`. */\nexport const usePipelineOrchestratorDeleteTemplate: typeof trpc.pipelineOrchestrator.deleteTemplate.useMutation = trpc.pipelineOrchestrator.deleteTemplate.useMutation\n\n/** Generated alias around `trpc.pipelineOrchestrator.getDeviceSettingsContribution.useQuery`. */\nexport const usePipelineOrchestratorGetDeviceSettingsContribution: typeof trpc.pipelineOrchestrator.getDeviceSettingsContribution.useQuery = trpc.pipelineOrchestrator.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.getDeviceLiveContribution.useQuery`. */\nexport const usePipelineOrchestratorGetDeviceLiveContribution: typeof trpc.pipelineOrchestrator.getDeviceLiveContribution.useQuery = trpc.pipelineOrchestrator.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.pipelineOrchestrator.applyDeviceSettingsPatch.useMutation`. */\nexport const usePipelineOrchestratorApplyDeviceSettingsPatch: typeof trpc.pipelineOrchestrator.applyDeviceSettingsPatch.useMutation = trpc.pipelineOrchestrator.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.pipelineRunner.attachCamera.useMutation`. */\nexport const usePipelineRunnerAttachCamera: typeof trpc.pipelineRunner.attachCamera.useMutation = trpc.pipelineRunner.attachCamera.useMutation\n\n/** Generated alias around `trpc.pipelineRunner.detachCamera.useMutation`. */\nexport const usePipelineRunnerDetachCamera: typeof trpc.pipelineRunner.detachCamera.useMutation = trpc.pipelineRunner.detachCamera.useMutation\n\n/** Generated alias around `trpc.pipelineRunner.reportMotion.useMutation`. */\nexport const usePipelineRunnerReportMotion: typeof trpc.pipelineRunner.reportMotion.useMutation = trpc.pipelineRunner.reportMotion.useMutation\n\n/** Generated alias around `trpc.pipelineRunner.getLocalLoad.useQuery`. */\nexport const usePipelineRunnerGetLocalLoad: typeof trpc.pipelineRunner.getLocalLoad.useQuery = trpc.pipelineRunner.getLocalLoad.useQuery\n\n/** Generated alias around `trpc.pipelineRunner.getLocalMetrics.useQuery`. */\nexport const usePipelineRunnerGetLocalMetrics: typeof trpc.pipelineRunner.getLocalMetrics.useQuery = trpc.pipelineRunner.getLocalMetrics.useQuery\n\n/** Generated alias around `trpc.pipelineRunner.getCameraMetrics.useQuery`. */\nexport const usePipelineRunnerGetCameraMetrics: typeof trpc.pipelineRunner.getCameraMetrics.useQuery = trpc.pipelineRunner.getCameraMetrics.useQuery\n\n/** Generated alias around `trpc.pipelineRunner.getAllCameraMetrics.useQuery`. */\nexport const usePipelineRunnerGetAllCameraMetrics: typeof trpc.pipelineRunner.getAllCameraMetrics.useQuery = trpc.pipelineRunner.getAllCameraMetrics.useQuery\n\n/** Generated alias around `trpc.pipelineRunner.getLocalCameras.useQuery`. */\nexport const usePipelineRunnerGetLocalCameras: typeof trpc.pipelineRunner.getLocalCameras.useQuery = trpc.pipelineRunner.getLocalCameras.useQuery\n\n/** Generated alias around `trpc.platformProbe.getCapabilities.useQuery`. */\nexport const usePlatformProbeGetCapabilities: typeof trpc.platformProbe.getCapabilities.useQuery = trpc.platformProbe.getCapabilities.useQuery\n\n/** Generated alias around `trpc.platformProbe.getHardware.useQuery`. */\nexport const usePlatformProbeGetHardware: typeof trpc.platformProbe.getHardware.useQuery = trpc.platformProbe.getHardware.useQuery\n\n/** Generated alias around `trpc.platformProbe.resolveInferenceConfig.useQuery`. */\nexport const usePlatformProbeResolveInferenceConfig: typeof trpc.platformProbe.resolveInferenceConfig.useQuery = trpc.platformProbe.resolveInferenceConfig.useQuery\n\n/** Generated alias around `trpc.platformProbe.resolveHwAccel.useQuery`. */\nexport const usePlatformProbeResolveHwAccel: typeof trpc.platformProbe.resolveHwAccel.useQuery = trpc.platformProbe.resolveHwAccel.useQuery\n\n/** Generated alias around `trpc.ptz.move.useMutation`. */\nexport const usePtzMove: typeof trpc.ptz.move.useMutation = trpc.ptz.move.useMutation\n\n/** Generated alias around `trpc.ptz.continuousMove.useMutation`. */\nexport const usePtzContinuousMove: typeof trpc.ptz.continuousMove.useMutation = trpc.ptz.continuousMove.useMutation\n\n/** Generated alias around `trpc.ptz.stop.useMutation`. */\nexport const usePtzStop: typeof trpc.ptz.stop.useMutation = trpc.ptz.stop.useMutation\n\n/** Generated alias around `trpc.ptz.getPresets.useQuery`. */\nexport const usePtzGetPresets: typeof trpc.ptz.getPresets.useQuery = trpc.ptz.getPresets.useQuery\n\n/** Generated alias around `trpc.ptz.goToPreset.useMutation`. */\nexport const usePtzGoToPreset: typeof trpc.ptz.goToPreset.useMutation = trpc.ptz.goToPreset.useMutation\n\n/** Generated alias around `trpc.ptz.goHome.useMutation`. */\nexport const usePtzGoHome: typeof trpc.ptz.goHome.useMutation = trpc.ptz.goHome.useMutation\n\n/** Generated alias around `trpc.ptz.getPosition.useQuery`. */\nexport const usePtzGetPosition: typeof trpc.ptz.getPosition.useQuery = trpc.ptz.getPosition.useQuery\n\n/** Generated alias around `trpc.ptz.getStatus.useQuery`. */\nexport const usePtzGetStatus: typeof trpc.ptz.getStatus.useQuery = trpc.ptz.getStatus.useQuery\n\n/** Generated alias around `trpc.ptzAutotrack.getStatus.useQuery`. */\nexport const usePtzAutotrackGetStatus: typeof trpc.ptzAutotrack.getStatus.useQuery = trpc.ptzAutotrack.getStatus.useQuery\n\n/** Generated alias around `trpc.ptzAutotrack.setEnabled.useMutation`. */\nexport const usePtzAutotrackSetEnabled: typeof trpc.ptzAutotrack.setEnabled.useMutation = trpc.ptzAutotrack.setEnabled.useMutation\n\n/** Generated alias around `trpc.ptzAutotrack.getSettings.useQuery`. */\nexport const usePtzAutotrackGetSettings: typeof trpc.ptzAutotrack.getSettings.useQuery = trpc.ptzAutotrack.getSettings.useQuery\n\n/** Generated alias around `trpc.ptzAutotrack.setSettings.useMutation`. */\nexport const usePtzAutotrackSetSettings: typeof trpc.ptzAutotrack.setSettings.useMutation = trpc.ptzAutotrack.setSettings.useMutation\n\n/** Generated alias around `trpc.reboot.reboot.useMutation`. */\nexport const useRebootReboot: typeof trpc.reboot.reboot.useMutation = trpc.reboot.reboot.useMutation\n\n/** Generated alias around `trpc.recording.getSegments.useQuery`. */\nexport const useRecordingGetSegments: typeof trpc.recording.getSegments.useQuery = trpc.recording.getSegments.useQuery\n\n/** Generated alias around `trpc.recording.getPlaybackUrl.useQuery`. */\nexport const useRecordingGetPlaybackUrl: typeof trpc.recording.getPlaybackUrl.useQuery = trpc.recording.getPlaybackUrl.useQuery\n\n/** Generated alias around `trpc.recording.getThumbnailAt.useQuery`. */\nexport const useRecordingGetThumbnailAt: typeof trpc.recording.getThumbnailAt.useQuery = trpc.recording.getThumbnailAt.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getStatus.useQuery`. */\nexport const useRecordingEngineGetStatus: typeof trpc.recordingEngine.getStatus.useQuery = trpc.recordingEngine.getStatus.useQuery\n\n/** Generated alias around `trpc.recordingEngine.enable.useMutation`. */\nexport const useRecordingEngineEnable: typeof trpc.recordingEngine.enable.useMutation = trpc.recordingEngine.enable.useMutation\n\n/** Generated alias around `trpc.recordingEngine.disable.useMutation`. */\nexport const useRecordingEngineDisable: typeof trpc.recordingEngine.disable.useMutation = trpc.recordingEngine.disable.useMutation\n\n/** Generated alias around `trpc.recordingEngine.getConfig.useQuery`. */\nexport const useRecordingEngineGetConfig: typeof trpc.recordingEngine.getConfig.useQuery = trpc.recordingEngine.getConfig.useQuery\n\n/** Generated alias around `trpc.recordingEngine.updateConfig.useMutation`. */\nexport const useRecordingEngineUpdateConfig: typeof trpc.recordingEngine.updateConfig.useMutation = trpc.recordingEngine.updateConfig.useMutation\n\n/** Generated alias around `trpc.recordingEngine.getPlaylist.useQuery`. */\nexport const useRecordingEngineGetPlaylist: typeof trpc.recordingEngine.getPlaylist.useQuery = trpc.recordingEngine.getPlaylist.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getThumbnail.useQuery`. */\nexport const useRecordingEngineGetThumbnail: typeof trpc.recordingEngine.getThumbnail.useQuery = trpc.recordingEngine.getThumbnail.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getSegments.useQuery`. */\nexport const useRecordingEngineGetSegments: typeof trpc.recordingEngine.getSegments.useQuery = trpc.recordingEngine.getSegments.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getAvailability.useQuery`. */\nexport const useRecordingEngineGetAvailability: typeof trpc.recordingEngine.getAvailability.useQuery = trpc.recordingEngine.getAvailability.useQuery\n\n/** Generated alias around `trpc.recordingEngine.estimateStorage.useQuery`. */\nexport const useRecordingEngineEstimateStorage: typeof trpc.recordingEngine.estimateStorage.useQuery = trpc.recordingEngine.estimateStorage.useQuery\n\n/** Generated alias around `trpc.recordingEngine.estimateGlobalStorage.useQuery`. */\nexport const useRecordingEngineEstimateGlobalStorage: typeof trpc.recordingEngine.estimateGlobalStorage.useQuery = trpc.recordingEngine.estimateGlobalStorage.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getStorageUsage.useQuery`. */\nexport const useRecordingEngineGetStorageUsage: typeof trpc.recordingEngine.getStorageUsage.useQuery = trpc.recordingEngine.getStorageUsage.useQuery\n\n/** Generated alias around `trpc.recordingEngine.setPolicy.useMutation`. */\nexport const useRecordingEngineSetPolicy: typeof trpc.recordingEngine.setPolicy.useMutation = trpc.recordingEngine.setPolicy.useMutation\n\n/** Generated alias around `trpc.recordingEngine.getPolicy.useQuery`. */\nexport const useRecordingEngineGetPolicy: typeof trpc.recordingEngine.getPolicy.useQuery = trpc.recordingEngine.getPolicy.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getPolicyStatus.useQuery`. */\nexport const useRecordingEngineGetPolicyStatus: typeof trpc.recordingEngine.getPolicyStatus.useQuery = trpc.recordingEngine.getPolicyStatus.useQuery\n\n/** Generated alias around `trpc.recordingEngine.getRetentionConfig.useQuery`. */\nexport const useRecordingEngineGetRetentionConfig: typeof trpc.recordingEngine.getRetentionConfig.useQuery = trpc.recordingEngine.getRetentionConfig.useQuery\n\n/** Generated alias around `trpc.recordingEngine.updateRetentionConfig.useMutation`. */\nexport const useRecordingEngineUpdateRetentionConfig: typeof trpc.recordingEngine.updateRetentionConfig.useMutation = trpc.recordingEngine.updateRetentionConfig.useMutation\n\n/** Generated alias around `trpc.recordingEngine.getMotionStats.useQuery`. */\nexport const useRecordingEngineGetMotionStats: typeof trpc.recordingEngine.getMotionStats.useQuery = trpc.recordingEngine.getMotionStats.useQuery\n\n/** Generated alias around `trpc.settingsStore.get.useQuery`. */\nexport const useSettingsStoreGet: typeof trpc.settingsStore.get.useQuery = trpc.settingsStore.get.useQuery\n\n/** Generated alias around `trpc.settingsStore.set.useMutation`. */\nexport const useSettingsStoreSet: typeof trpc.settingsStore.set.useMutation = trpc.settingsStore.set.useMutation\n\n/** Generated alias around `trpc.settingsStore.query.useQuery`. */\nexport const useSettingsStoreQuery: typeof trpc.settingsStore.query.useQuery = trpc.settingsStore.query.useQuery\n\n/** Generated alias around `trpc.settingsStore.insert.useMutation`. */\nexport const useSettingsStoreInsert: typeof trpc.settingsStore.insert.useMutation = trpc.settingsStore.insert.useMutation\n\n/** Generated alias around `trpc.settingsStore.update.useMutation`. */\nexport const useSettingsStoreUpdate: typeof trpc.settingsStore.update.useMutation = trpc.settingsStore.update.useMutation\n\n/** Generated alias around `trpc.settingsStore.delete.useMutation`. */\nexport const useSettingsStoreDelete: typeof trpc.settingsStore.delete.useMutation = trpc.settingsStore.delete.useMutation\n\n/** Generated alias around `trpc.settingsStore.count.useQuery`. */\nexport const useSettingsStoreCount: typeof trpc.settingsStore.count.useQuery = trpc.settingsStore.count.useQuery\n\n/** Generated alias around `trpc.settingsStore.isEmpty.useQuery`. */\nexport const useSettingsStoreIsEmpty: typeof trpc.settingsStore.isEmpty.useQuery = trpc.settingsStore.isEmpty.useQuery\n\n/** Generated alias around `trpc.settingsStore.declareCollection.useMutation`. */\nexport const useSettingsStoreDeclareCollection: typeof trpc.settingsStore.declareCollection.useMutation = trpc.settingsStore.declareCollection.useMutation\n\n/** Generated alias around `trpc.snapshot.getSnapshot.useQuery`. */\nexport const useSnapshotGetSnapshot: typeof trpc.snapshot.getSnapshot.useQuery = trpc.snapshot.getSnapshot.useQuery\n\n/** Generated alias around `trpc.snapshot.invalidateCache.useMutation`. */\nexport const useSnapshotInvalidateCache: typeof trpc.snapshot.invalidateCache.useMutation = trpc.snapshot.invalidateCache.useMutation\n\n/** Generated alias around `trpc.snapshot.getStatus.useQuery`. */\nexport const useSnapshotGetStatus: typeof trpc.snapshot.getStatus.useQuery = trpc.snapshot.getStatus.useQuery\n\n/** Generated alias around `trpc.snapshot.getDeviceSettingsContribution.useQuery`. */\nexport const useSnapshotGetDeviceSettingsContribution: typeof trpc.snapshot.getDeviceSettingsContribution.useQuery = trpc.snapshot.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.snapshot.getDeviceLiveContribution.useQuery`. */\nexport const useSnapshotGetDeviceLiveContribution: typeof trpc.snapshot.getDeviceLiveContribution.useQuery = trpc.snapshot.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.snapshot.applyDeviceSettingsPatch.useMutation`. */\nexport const useSnapshotApplyDeviceSettingsPatch: typeof trpc.snapshot.applyDeviceSettingsPatch.useMutation = trpc.snapshot.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.snapshotProvider.supportsDevice.useQuery`. */\nexport const useSnapshotProviderSupportsDevice: typeof trpc.snapshotProvider.supportsDevice.useQuery = trpc.snapshotProvider.supportsDevice.useQuery\n\n/** Generated alias around `trpc.snapshotProvider.getSnapshot.useQuery`. */\nexport const useSnapshotProviderGetSnapshot: typeof trpc.snapshotProvider.getSnapshot.useQuery = trpc.snapshotProvider.getSnapshot.useQuery\n\n/** Generated alias around `trpc.storage.resolve.useQuery`. */\nexport const useStorageResolve: typeof trpc.storage.resolve.useQuery = trpc.storage.resolve.useQuery\n\n/** Generated alias around `trpc.storage.write.useMutation`. */\nexport const useStorageWrite: typeof trpc.storage.write.useMutation = trpc.storage.write.useMutation\n\n/** Generated alias around `trpc.storage.read.useQuery`. */\nexport const useStorageRead: typeof trpc.storage.read.useQuery = trpc.storage.read.useQuery\n\n/** Generated alias around `trpc.storage.exists.useQuery`. */\nexport const useStorageExists: typeof trpc.storage.exists.useQuery = trpc.storage.exists.useQuery\n\n/** Generated alias around `trpc.storage.list.useQuery`. */\nexport const useStorageList: typeof trpc.storage.list.useQuery = trpc.storage.list.useQuery\n\n/** Generated alias around `trpc.storage.delete.useMutation`. */\nexport const useStorageDelete: typeof trpc.storage.delete.useMutation = trpc.storage.delete.useMutation\n\n/** Generated alias around `trpc.storage.getAvailableSpace.useQuery`. */\nexport const useStorageGetAvailableSpace: typeof trpc.storage.getAvailableSpace.useQuery = trpc.storage.getAvailableSpace.useQuery\n\n/** Generated alias around `trpc.streamBroker.publishCameraStream.useMutation`. */\nexport const useStreamBrokerPublishCameraStream: typeof trpc.streamBroker.publishCameraStream.useMutation = trpc.streamBroker.publishCameraStream.useMutation\n\n/** Generated alias around `trpc.streamBroker.retractCameraStream.useMutation`. */\nexport const useStreamBrokerRetractCameraStream: typeof trpc.streamBroker.retractCameraStream.useMutation = trpc.streamBroker.retractCameraStream.useMutation\n\n/** Generated alias around `trpc.streamBroker.assignProfile.useMutation`. */\nexport const useStreamBrokerAssignProfile: typeof trpc.streamBroker.assignProfile.useMutation = trpc.streamBroker.assignProfile.useMutation\n\n/** Generated alias around `trpc.streamBroker.unassignProfile.useMutation`. */\nexport const useStreamBrokerUnassignProfile: typeof trpc.streamBroker.unassignProfile.useMutation = trpc.streamBroker.unassignProfile.useMutation\n\n/** Generated alias around `trpc.streamBroker.listAllCameraStreams.useQuery`. */\nexport const useStreamBrokerListAllCameraStreams: typeof trpc.streamBroker.listAllCameraStreams.useQuery = trpc.streamBroker.listAllCameraStreams.useQuery\n\n/** Generated alias around `trpc.streamBroker.listAllProfileSlots.useQuery`. */\nexport const useStreamBrokerListAllProfileSlots: typeof trpc.streamBroker.listAllProfileSlots.useQuery = trpc.streamBroker.listAllProfileSlots.useQuery\n\n/** Generated alias around `trpc.streamBroker.getBrokerStats.useQuery`. */\nexport const useStreamBrokerGetBrokerStats: typeof trpc.streamBroker.getBrokerStats.useQuery = trpc.streamBroker.getBrokerStats.useQuery\n\n/** Generated alias around `trpc.streamBroker.listClients.useQuery`. */\nexport const useStreamBrokerListClients: typeof trpc.streamBroker.listClients.useQuery = trpc.streamBroker.listClients.useQuery\n\n/** Generated alias around `trpc.streamBroker.killClient.useMutation`. */\nexport const useStreamBrokerKillClient: typeof trpc.streamBroker.killClient.useMutation = trpc.streamBroker.killClient.useMutation\n\n/** Generated alias around `trpc.streamBroker.restartProfile.useMutation`. */\nexport const useStreamBrokerRestartProfile: typeof trpc.streamBroker.restartProfile.useMutation = trpc.streamBroker.restartProfile.useMutation\n\n/** Generated alias around `trpc.streamBroker.getStreamUrl.useQuery`. */\nexport const useStreamBrokerGetStreamUrl: typeof trpc.streamBroker.getStreamUrl.useQuery = trpc.streamBroker.getStreamUrl.useQuery\n\n/** Generated alias around `trpc.streamBroker.getBroker.useQuery`. */\nexport const useStreamBrokerGetBroker: typeof trpc.streamBroker.getBroker.useQuery = trpc.streamBroker.getBroker.useQuery\n\n/** Generated alias around `trpc.streamBroker.setPreBufferDuration.useMutation`. */\nexport const useStreamBrokerSetPreBufferDuration: typeof trpc.streamBroker.setPreBufferDuration.useMutation = trpc.streamBroker.setPreBufferDuration.useMutation\n\n/** Generated alias around `trpc.streamBroker.getPreBufferInfo.useQuery`. */\nexport const useStreamBrokerGetPreBufferInfo: typeof trpc.streamBroker.getPreBufferInfo.useQuery = trpc.streamBroker.getPreBufferInfo.useQuery\n\n/** Generated alias around `trpc.streamBroker.getRtspPort.useQuery`. */\nexport const useStreamBrokerGetRtspPort: typeof trpc.streamBroker.getRtspPort.useQuery = trpc.streamBroker.getRtspPort.useQuery\n\n/** Generated alias around `trpc.streamBroker.getAllRtspEntries.useQuery`. */\nexport const useStreamBrokerGetAllRtspEntries: typeof trpc.streamBroker.getAllRtspEntries.useQuery = trpc.streamBroker.getAllRtspEntries.useQuery\n\n/** Generated alias around `trpc.streamBroker.getRtspEntry.useQuery`. */\nexport const useStreamBrokerGetRtspEntry: typeof trpc.streamBroker.getRtspEntry.useQuery = trpc.streamBroker.getRtspEntry.useQuery\n\n/** Generated alias around `trpc.streamBroker.regenerateRtspToken.useMutation`. */\nexport const useStreamBrokerRegenerateRtspToken: typeof trpc.streamBroker.regenerateRtspToken.useMutation = trpc.streamBroker.regenerateRtspToken.useMutation\n\n/** Generated alias around `trpc.streamBroker.setRtspEnabled.useMutation`. */\nexport const useStreamBrokerSetRtspEnabled: typeof trpc.streamBroker.setRtspEnabled.useMutation = trpc.streamBroker.setRtspEnabled.useMutation\n\n/** Generated alias around `trpc.streamBroker.isRtspEnabled.useQuery`. */\nexport const useStreamBrokerIsRtspEnabled: typeof trpc.streamBroker.isRtspEnabled.useQuery = trpc.streamBroker.isRtspEnabled.useQuery\n\n/** Generated alias around `trpc.streamBroker.getDeviceSettingsContribution.useQuery`. */\nexport const useStreamBrokerGetDeviceSettingsContribution: typeof trpc.streamBroker.getDeviceSettingsContribution.useQuery = trpc.streamBroker.getDeviceSettingsContribution.useQuery\n\n/** Generated alias around `trpc.streamBroker.getDeviceLiveContribution.useQuery`. */\nexport const useStreamBrokerGetDeviceLiveContribution: typeof trpc.streamBroker.getDeviceLiveContribution.useQuery = trpc.streamBroker.getDeviceLiveContribution.useQuery\n\n/** Generated alias around `trpc.streamBroker.applyDeviceSettingsPatch.useMutation`. */\nexport const useStreamBrokerApplyDeviceSettingsPatch: typeof trpc.streamBroker.applyDeviceSettingsPatch.useMutation = trpc.streamBroker.applyDeviceSettingsPatch.useMutation\n\n/** Generated alias around `trpc.switch.setState.useMutation`. */\nexport const useSwitchSetState: typeof trpc.switch.setState.useMutation = trpc.switch.setState.useMutation\n\n/** Generated alias around `trpc.switch.getStatus.useQuery`. */\nexport const useSwitchGetStatus: typeof trpc.switch.getStatus.useQuery = trpc.switch.getStatus.useQuery\n\n/** Generated alias around `trpc.system.info.useQuery`. */\nexport const useSystemInfo: typeof trpc.system.info.useQuery = trpc.system.info.useQuery\n\n/** Generated alias around `trpc.system.health.useQuery`. */\nexport const useSystemHealth: typeof trpc.system.health.useQuery = trpc.system.health.useQuery\n\n/** Generated alias around `trpc.system.featureFlags.useQuery`. */\nexport const useSystemFeatureFlags: typeof trpc.system.featureFlags.useQuery = trpc.system.featureFlags.useQuery\n\n/** Generated alias around `trpc.system.networkAddresses.useQuery`. */\nexport const useSystemNetworkAddresses: typeof trpc.system.networkAddresses.useQuery = trpc.system.networkAddresses.useQuery\n\n/** Generated alias around `trpc.system.getRetentionConfig.useQuery`. */\nexport const useSystemGetRetentionConfig: typeof trpc.system.getRetentionConfig.useQuery = trpc.system.getRetentionConfig.useQuery\n\n/** Generated alias around `trpc.system.setRetentionConfig.useMutation`. */\nexport const useSystemSetRetentionConfig: typeof trpc.system.setRetentionConfig.useMutation = trpc.system.setRetentionConfig.useMutation\n\n/** Generated alias around `trpc.system.forceRetentionCleanup.useMutation`. */\nexport const useSystemForceRetentionCleanup: typeof trpc.system.forceRetentionCleanup.useMutation = trpc.system.forceRetentionCleanup.useMutation\n\n/** Generated alias around `trpc.toast.onToast.useSubscription`. */\nexport const useToastOnToast: typeof trpc.toast.onToast.useSubscription = trpc.toast.onToast.useSubscription\n\n/** Generated alias around `trpc.turnProvider.getTurnServers.useQuery`. */\nexport const useTurnProviderGetTurnServers: typeof trpc.turnProvider.getTurnServers.useQuery = trpc.turnProvider.getTurnServers.useQuery\n\n/** Generated alias around `trpc.userManagement.listUsers.useQuery`. */\nexport const useUserManagementListUsers: typeof trpc.userManagement.listUsers.useQuery = trpc.userManagement.listUsers.useQuery\n\n/** Generated alias around `trpc.userManagement.createUser.useMutation`. */\nexport const useUserManagementCreateUser: typeof trpc.userManagement.createUser.useMutation = trpc.userManagement.createUser.useMutation\n\n/** Generated alias around `trpc.userManagement.updateUser.useMutation`. */\nexport const useUserManagementUpdateUser: typeof trpc.userManagement.updateUser.useMutation = trpc.userManagement.updateUser.useMutation\n\n/** Generated alias around `trpc.userManagement.deleteUser.useMutation`. */\nexport const useUserManagementDeleteUser: typeof trpc.userManagement.deleteUser.useMutation = trpc.userManagement.deleteUser.useMutation\n\n/** Generated alias around `trpc.userManagement.resetPassword.useMutation`. */\nexport const useUserManagementResetPassword: typeof trpc.userManagement.resetPassword.useMutation = trpc.userManagement.resetPassword.useMutation\n\n/** Generated alias around `trpc.userManagement.validateCredentials.useMutation`. */\nexport const useUserManagementValidateCredentials: typeof trpc.userManagement.validateCredentials.useMutation = trpc.userManagement.validateCredentials.useMutation\n\n/** Generated alias around `trpc.userManagement.listApiKeys.useQuery`. */\nexport const useUserManagementListApiKeys: typeof trpc.userManagement.listApiKeys.useQuery = trpc.userManagement.listApiKeys.useQuery\n\n/** Generated alias around `trpc.userManagement.createApiKey.useMutation`. */\nexport const useUserManagementCreateApiKey: typeof trpc.userManagement.createApiKey.useMutation = trpc.userManagement.createApiKey.useMutation\n\n/** Generated alias around `trpc.userManagement.revokeApiKey.useMutation`. */\nexport const useUserManagementRevokeApiKey: typeof trpc.userManagement.revokeApiKey.useMutation = trpc.userManagement.revokeApiKey.useMutation\n\n/** Generated alias around `trpc.userManagement.validateApiKey.useMutation`. */\nexport const useUserManagementValidateApiKey: typeof trpc.userManagement.validateApiKey.useMutation = trpc.userManagement.validateApiKey.useMutation\n\n/** Generated alias around `trpc.userManagement.createScopedToken.useMutation`. */\nexport const useUserManagementCreateScopedToken: typeof trpc.userManagement.createScopedToken.useMutation = trpc.userManagement.createScopedToken.useMutation\n\n/** Generated alias around `trpc.userManagement.revokeScopedToken.useMutation`. */\nexport const useUserManagementRevokeScopedToken: typeof trpc.userManagement.revokeScopedToken.useMutation = trpc.userManagement.revokeScopedToken.useMutation\n\n/** Generated alias around `trpc.userManagement.validateScopedToken.useQuery`. */\nexport const useUserManagementValidateScopedToken: typeof trpc.userManagement.validateScopedToken.useQuery = trpc.userManagement.validateScopedToken.useQuery\n\n/** Generated alias around `trpc.userManagement.listScopedTokens.useQuery`. */\nexport const useUserManagementListScopedTokens: typeof trpc.userManagement.listScopedTokens.useQuery = trpc.userManagement.listScopedTokens.useQuery\n\n/** Generated alias around `trpc.webrtcSession.listStreams.useQuery`. */\nexport const useWebrtcSessionListStreams: typeof trpc.webrtcSession.listStreams.useQuery = trpc.webrtcSession.listStreams.useQuery\n\n/** Generated alias around `trpc.webrtcSession.createSession.useMutation`. */\nexport const useWebrtcSessionCreateSession: typeof trpc.webrtcSession.createSession.useMutation = trpc.webrtcSession.createSession.useMutation\n\n/** Generated alias around `trpc.webrtcSession.handleAnswer.useMutation`. */\nexport const useWebrtcSessionHandleAnswer: typeof trpc.webrtcSession.handleAnswer.useMutation = trpc.webrtcSession.handleAnswer.useMutation\n\n/** Generated alias around `trpc.webrtcSession.closeSession.useMutation`. */\nexport const useWebrtcSessionCloseSession: typeof trpc.webrtcSession.closeSession.useMutation = trpc.webrtcSession.closeSession.useMutation\n\n/** Generated alias around `trpc.webrtcSession.hasAdaptiveBitrate.useQuery`. */\nexport const useWebrtcSessionHasAdaptiveBitrate: typeof trpc.webrtcSession.hasAdaptiveBitrate.useQuery = trpc.webrtcSession.hasAdaptiveBitrate.useQuery\n\n/** Generated alias around `trpc.zoneAnalytics.getCurrentSnapshot.useQuery`. */\nexport const useZoneAnalyticsGetCurrentSnapshot: typeof trpc.zoneAnalytics.getCurrentSnapshot.useQuery = trpc.zoneAnalytics.getCurrentSnapshot.useQuery\n\n/** Generated alias around `trpc.zoneAnalytics.getZoneHistory.useQuery`. */\nexport const useZoneAnalyticsGetZoneHistory: typeof trpc.zoneAnalytics.getZoneHistory.useQuery = trpc.zoneAnalytics.getZoneHistory.useQuery\n\n/** Generated alias around `trpc.zoneAnalytics.getCameraHistory.useQuery`. */\nexport const useZoneAnalyticsGetCameraHistory: typeof trpc.zoneAnalytics.getCameraHistory.useQuery = trpc.zoneAnalytics.getCameraHistory.useQuery\n\n/** Generated alias around `trpc.zoneAnalytics.getUnzonedHistory.useQuery`. */\nexport const useZoneAnalyticsGetUnzonedHistory: typeof trpc.zoneAnalytics.getUnzonedHistory.useQuery = trpc.zoneAnalytics.getUnzonedHistory.useQuery\n\n/** Generated alias around `trpc.zoneRules.listRules.useQuery`. */\nexport const useZoneRulesListRules: typeof trpc.zoneRules.listRules.useQuery = trpc.zoneRules.listRules.useQuery\n\n/** Generated alias around `trpc.zoneRules.setRules.useMutation`. */\nexport const useZoneRulesSetRules: typeof trpc.zoneRules.setRules.useMutation = trpc.zoneRules.setRules.useMutation\n\n/** Generated alias around `trpc.zones.listZones.useQuery`. */\nexport const useZonesListZones: typeof trpc.zones.listZones.useQuery = trpc.zones.listZones.useQuery\n\n/** Generated alias around `trpc.zones.addZone.useMutation`. */\nexport const useZonesAddZone: typeof trpc.zones.addZone.useMutation = trpc.zones.addZone.useMutation\n\n/** Generated alias around `trpc.zones.removeZone.useMutation`. */\nexport const useZonesRemoveZone: typeof trpc.zones.removeZone.useMutation = trpc.zones.removeZone.useMutation\n\n/** Generated alias around `trpc.zones.updateZone.useMutation`. */\nexport const useZonesUpdateZone: typeof trpc.zones.updateZone.useMutation = trpc.zones.updateZone.useMutation\n","/**\n * `AddonGlobalSettingsForm` — mounts an addon's global-settings schema\n * via `api.addonSettings.getGlobalSettings` + `updateGlobalSettings`\n * and renders it with `ConfigFormBuilder`. Single source of truth for\n * the addon's settings — no hardcoded option lists anywhere in the UI.\n *\n * Used wherever an addon's settings need to be edited inline (e.g.\n * benchmark tabs, per-node pipeline editor). The caller passes the\n * tRPC client + (addonId, nodeId); the component handles the fetch\n * + patch loop. `onAfterChange` fires once the patch is applied so\n * consumers can re-read any derived state.\n */\nimport { useEffect, useMemo, useState } from 'react'\nimport type { ConfigUISchemaWithValues, ConfigUISchema, ConfigField } from '@camstack/types'\nimport { ConfigFormBuilder } from './config-form-builder.js'\n\nconst Chevron = ({ open }: { open: boolean }) => (\n <svg\n className={`h-3 w-3 transition-transform ${open ? 'rotate-90' : ''}`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n)\n\ninterface AddonGlobalSettingsFormTrpc {\n addonSettings: {\n getGlobalSettings: {\n query: (input: { addonId: string; nodeId?: string; overlay?: Record<string, unknown> }) => Promise<ConfigUISchemaWithValues | null>\n }\n updateGlobalSettings: {\n mutate: (input: { addonId: string; nodeId?: string; patch: Record<string, unknown> }) => Promise<unknown>\n }\n }\n}\n\ninterface AddonGlobalSettingsFormProps {\n readonly trpc: AddonGlobalSettingsFormTrpc\n readonly addonId: string\n readonly nodeId: string\n readonly title?: string\n readonly disabled?: boolean\n readonly onAfterChange?: () => void\n /** Bump to force refetch (e.g. after an external mutation). */\n readonly refreshToken?: number\n /**\n * Render as collapsible. When true, the form body is hidden until\n * the operator expands the header (click). Defaults to open so\n * callers that always want the form visible don't have to opt out.\n */\n readonly collapsible?: boolean\n /** When `collapsible`, start expanded (true) or collapsed (false). Defaults to false. */\n readonly defaultOpen?: boolean\n /**\n * - `'persist'` (default): edits call `updateGlobalSettings` and\n * re-fetch — the live store is mutated. Use in settings editors\n * (NodePipelineTab, device details).\n * - `'override'`: edits stay local (never touch the store).\n * `onOverrideChange` receives the current override values on\n * every edit so the caller can pass them to a per-run action.\n * Use in the benchmark tabs — operator tweaks for a single\n * bench run without mutating the addon's saved settings.\n */\n readonly mode?: 'persist' | 'override'\n /**\n * Called on every edit when `mode: 'override'`. `patch` is the sparse\n * diff vs the persisted baseline (only the fields the operator touched).\n * `effective` is the baseline merged with the patch — every field a\n * downstream action might need, with the operator's override applied.\n * Callers that need to emit a full engine triple (runtime+backend+format)\n * should read from `effective`, not `patch`, so partial edits (e.g.\n * operator tweaks only `device`) still produce a complete payload.\n */\n readonly onOverrideChange?: (patch: Record<string, unknown>, effective: Record<string, unknown>) => void\n}\n\nfunction extractValues(schema: ConfigUISchemaWithValues | null): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!schema) return out\n for (const s of schema.sections) {\n for (const f of s.fields) {\n if (f.type === 'separator' || f.type === 'info' || f.type === 'button' || f.type === 'group') continue\n const key = (f as { readonly key: string }).key\n out[key] = (f as { readonly value?: unknown }).value\n }\n }\n return out\n}\n\nfunction stripValues(schema: ConfigUISchemaWithValues): ConfigUISchema {\n return {\n ...schema,\n sections: schema.sections.map((s) => ({\n ...s,\n fields: s.fields.map((f) => {\n if (f.type === 'separator' || f.type === 'info' || f.type === 'button' || f.type === 'group') return f as ConfigField\n const { value: _drop, ...rest } = f as unknown as Record<string, unknown>\n return rest as unknown as ConfigField\n }),\n })),\n }\n}\n\nexport function AddonGlobalSettingsForm({\n trpc,\n addonId,\n nodeId,\n title,\n disabled,\n onAfterChange,\n refreshToken,\n collapsible,\n defaultOpen,\n mode,\n onOverrideChange,\n}: AddonGlobalSettingsFormProps) {\n const effectiveMode = mode ?? 'persist'\n const [hydrated, setHydrated] = useState<ConfigUISchemaWithValues | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [saving, setSaving] = useState(false)\n const [open, setOpen] = useState<boolean>(defaultOpen ?? false)\n const [overrideValues, setOverrideValues] = useState<Record<string, unknown>>({})\n // Snapshot of the addon's *persisted* values, captured once on first\n // hydrate. The patch diff must reference this stable baseline, not the\n // overlay-hydrated `values` — otherwise each overlay refetch shifts the\n // baseline and the user's earlier override fields silently drop out of\n // the emitted patch (e.g. setting runtime=python then backend=coreml\n // would lose `engineRuntime` from the patch).\n const [baseValues, setBaseValues] = useState<Record<string, unknown> | null>(null)\n\n // Reset baseline + override when the target addon / node / mode changes\n // or the caller bumps refreshToken. Keeps the snapshot stable across\n // overlay-triggered refetches within a single editing session.\n useEffect(() => {\n setBaseValues(null)\n setOverrideValues({})\n }, [trpc, addonId, nodeId, refreshToken, effectiveMode])\n\n const overlayKey = JSON.stringify(overrideValues)\n useEffect(() => {\n let cancelled = false\n setLoading(true)\n setError(null)\n // Pass the current override patch as a preview overlay so the\n // backend's dynamic-option logic (e.g. detection-pipeline's\n // `engineRuntime → engineBackend → engineDevice` cascade) derives\n // the next level's options against the operator's tentative\n // choice. Persist mode has overrideValues={} so this is a no-op.\n const overlay = effectiveMode === 'override' && Object.keys(overrideValues).length > 0\n ? overrideValues\n : undefined\n trpc.addonSettings.getGlobalSettings.query({ addonId, nodeId, ...(overlay ? { overlay } : {}) })\n .then((res) => {\n if (cancelled) return\n setHydrated(res)\n // Capture the baseline only on the first hydrate of this editing\n // session — overlay-driven refetches must not shift it.\n if (!overlay) {\n setBaseValues(extractValues(res))\n }\n setLoading(false)\n })\n .catch((err: unknown) => {\n if (cancelled) return\n setError(err instanceof Error ? err.message : String(err))\n setLoading(false)\n })\n return () => { cancelled = true }\n // `overlayKey` is the JSON of `overrideValues` — re-fetches when\n // the operator tweaks an upstream cascade field; `effectiveMode`\n // toggles overlay passthrough. Left `overrideValues` itself out\n // of deps on purpose (it's object-identity-unstable; the stable\n // string form is the signal).\n }, [trpc, addonId, nodeId, refreshToken, effectiveMode, overlayKey])\n\n const values = useMemo(() => extractValues(hydrated), [hydrated])\n const schemaNoValues = useMemo(() => (hydrated ? stripValues(hydrated) : null), [hydrated])\n\n const handleChange = async (nextValues: Record<string, unknown>) => {\n if (effectiveMode === 'override') {\n // Override mode — NEVER touch the addon's persisted store.\n // Diff against the *stable* baseline so previously-set override\n // fields stay in the emitted patch across overlay refetches.\n const ref = baseValues ?? values\n const patch: Record<string, unknown> = {}\n for (const k of Object.keys(nextValues)) {\n if (nextValues[k] !== ref[k]) patch[k] = nextValues[k]\n }\n // Effective = baseline merged with patch. Callers that need a\n // full field set (e.g. engine runtime+backend+format triple for\n // the benchmark's per-run override) must read this instead of the\n // sparse patch — otherwise touching only one field loses the\n // baseline context and the override emits incomplete payloads.\n const effective: Record<string, unknown> = { ...ref, ...patch }\n setOverrideValues(patch)\n onOverrideChange?.(patch, effective)\n return\n }\n // Build a minimal patch — only keys whose value differs from the\n // current hydrated snapshot. Keeps unrelated fields out of the\n // persisted store and lets the addon's `maybeAutoRestart` logic\n // only fire on real changes.\n const patch: Record<string, unknown> = {}\n for (const k of Object.keys(nextValues)) {\n if (nextValues[k] !== values[k]) patch[k] = nextValues[k]\n }\n if (Object.keys(patch).length === 0) return\n setSaving(true)\n try {\n await trpc.addonSettings.updateGlobalSettings.mutate({ addonId, nodeId, patch })\n // Re-fetch so derived fields (e.g. `probedBest*` hints refreshed\n // by a sibling action) stay in sync.\n const next = await trpc.addonSettings.getGlobalSettings.query({ addonId, nodeId })\n setHydrated(next)\n onAfterChange?.()\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setSaving(false)\n }\n }\n\n if (loading) return <div className=\"text-xs text-foreground-subtle animate-pulse\">Loading {title ?? addonId}…</div>\n if (error) return <div className=\"text-xs text-red-400\">{title ?? addonId}: {error}</div>\n if (!hydrated || !schemaNoValues) return <div className=\"text-xs text-foreground-subtle\">{title ?? addonId} not available on {nodeId}.</div>\n\n // In override mode the form renders (base ⊕ override) so the operator\n // always sees the effective value. In persist mode the form renders\n // the live store values.\n const effectiveValues = effectiveMode === 'override'\n ? { ...values, ...overrideValues }\n : values\n\n const body = (\n <>\n {effectiveMode === 'override' ? (\n <div className=\"mb-2 text-[11px] text-foreground-subtle\">\n Benchmark override — applies to this run only. The addon's saved settings are not changed.\n </div>\n ) : null}\n <ConfigFormBuilder\n schema={schemaNoValues}\n values={effectiveValues}\n onChange={handleChange}\n disabled={disabled === true || saving}\n />\n </>\n )\n\n if (collapsible === true) {\n return (\n <section className=\"rounded-lg border border-border bg-surface overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"w-full px-4 py-2 flex items-center gap-2 hover:bg-surface-hover text-left\"\n aria-expanded={open}\n >\n <Chevron open={open} />\n <h3 className=\"text-xs font-semibold text-foreground uppercase tracking-wide flex-1\">\n {title ?? addonId}\n </h3>\n <span className=\"text-[10px] text-foreground-subtle\">{open ? 'hide' : 'edit'}</span>\n </button>\n {open ? <div className=\"border-t border-border px-4 py-3\">{body}</div> : null}\n </section>\n )\n }\n\n // No title + not collapsible → render body only. The parent owns the\n // visual wrapper (card, section header, etc.) to avoid the \"bordered\n // panel nested inside another bordered panel\" pattern.\n if (!title) return <div>{body}</div>\n\n return (\n <section className=\"rounded-lg border border-border bg-surface overflow-hidden\">\n <div className=\"border-b border-border px-4 py-2\">\n <h3 className=\"text-xs font-semibold text-foreground uppercase tracking-wide\">{title}</h3>\n </div>\n <div className=\"px-4 py-3\">{body}</div>\n </section>\n )\n}\n","/**\n * DetectionOverlay — renders motion zones, raw motion boxes, detection bounding boxes,\n * and pipeline phase indicator as CSS overlay.\n *\n * Pure component — receives all data via props. Use with useDeviceDetections hook.\n * Positioned absolute inside a relative parent (e.g., video container).\n */\nimport { getClassColor } from './detection-colors'\nimport { getPhaseVisual } from '../lib/phase-config'\nimport type { DeviceDetections, MotionRawBox } from '../hooks/use-device-detections'\nimport type { ObjectDetection } from '@camstack/types'\n\nexport interface DetectionOverlayProps {\n readonly detections: DeviceDetections\n readonly showMotionZones?: boolean\n readonly showMotionRaw?: boolean\n readonly showDetections?: boolean\n readonly showPhaseIndicator?: boolean\n}\n\nexport function DetectionOverlay({\n detections: { motion, motionRaw, detection, phase },\n showMotionZones = true,\n showMotionRaw = true,\n showDetections = true,\n showPhaseIndicator = true,\n}: DetectionOverlayProps) {\n const hasMotion = showMotionZones && motion && motion.zones.length > 0\n const hasMotionRaw = showMotionRaw && motionRaw && motionRaw.boxes.length > 0\n const hasDets = showDetections && detection && detection.detections.length > 0\n\n if (!hasMotion && !hasMotionRaw && !hasDets && !showPhaseIndicator) return null\n\n return (\n <div className=\"absolute inset-0 pointer-events-none z-10\">\n {showPhaseIndicator && <PhaseBadge phase={phase} />}\n {hasMotionRaw && <MotionRawBoxes raw={motionRaw!} />}\n {hasMotion && <MotionZones motion={motion!} />}\n {hasDets && (\n <DetectionBoxes\n detections={detection!.detections}\n frameWidth={detection!.frameWidth}\n frameHeight={detection!.frameHeight}\n />\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction PhaseBadge({ phase }: { readonly phase: string }) {\n const cfg = getPhaseVisual(phase)\n return (\n <div className=\"absolute top-2 left-2 flex items-center gap-1.5 px-2 py-1 rounded-md bg-black/60 backdrop-blur-sm\">\n <span className={`w-2 h-2 rounded-full ${cfg.dotClass}`} />\n <span className=\"text-[10px] font-semibold text-white uppercase tracking-wider\">\n {cfg.label}\n </span>\n </div>\n )\n}\n\nfunction MotionRawBoxes({ raw }: { readonly raw: { boxes: readonly MotionRawBox[]; frameWidth: number; frameHeight: number } }) {\n if (raw.frameWidth === 0 || raw.frameHeight === 0) return null\n\n return (\n <>\n {raw.boxes.map((box, i) => {\n const [x1, y1, x2, y2] = box.bbox\n const left = (x1 / raw.frameWidth) * 100\n const top = (y1 / raw.frameHeight) * 100\n const width = ((x2 - x1) / raw.frameWidth) * 100\n const height = ((y2 - y1) / raw.frameHeight) * 100\n const opacity = Math.max(0.05, Math.min(0.25, box.changeScore * 0.3))\n\n return (\n <div\n key={`mr-${i}`}\n className=\"absolute rounded-sm\"\n style={{\n left: `${left}%`, top: `${top}%`, width: `${width}%`, height: `${height}%`,\n backgroundColor: `rgba(239, 68, 68, ${opacity})`,\n }}\n />\n )\n })}\n </>\n )\n}\n\nfunction MotionZones({ motion }: { readonly motion: { zones: readonly { x: number; y: number; w: number; h: number; intensity: number }[]; frameWidth: number; frameHeight: number } }) {\n if (motion.frameWidth === 0 || motion.frameHeight === 0) return null\n\n // Filter out near-full-frame zones (noise)\n const meaningful = motion.zones.filter((z) => {\n const coverage = (z.w * z.h) / (motion.frameWidth * motion.frameHeight)\n return coverage < 0.9\n })\n\n return (\n <>\n {meaningful.map((z, i) => {\n const alpha = Math.max(0.15, Math.min(0.5, z.intensity / 255))\n return (\n <div\n key={`mz-${i}`}\n className=\"absolute rounded-sm\"\n style={{\n left: `${(z.x / motion.frameWidth) * 100}%`,\n top: `${(z.y / motion.frameHeight) * 100}%`,\n width: `${(z.w / motion.frameWidth) * 100}%`,\n height: `${(z.h / motion.frameHeight) * 100}%`,\n border: `1px solid rgba(250, 204, 21, ${alpha})`,\n backgroundColor: `rgba(250, 204, 21, ${alpha * 0.15})`,\n }}\n />\n )\n })}\n </>\n )\n}\n\nfunction DetectionBoxes({\n detections,\n frameWidth,\n frameHeight,\n}: {\n readonly detections: readonly ObjectDetection[]\n readonly frameWidth: number\n readonly frameHeight: number\n}) {\n if (frameWidth === 0 || frameHeight === 0) return null\n\n return (\n <>\n {detections.map((d) => {\n const { x, y, width: bw, height: bh } = d.bbox\n const left = (x / frameWidth) * 100\n const top = (y / frameHeight) * 100\n const width = (bw / frameWidth) * 100\n const height = (bh / frameHeight) * 100\n const color = getClassColor(d.macroClass)\n\n const parts = [`${d.macroClass} ${(d.score * 100).toFixed(0)}%`]\n for (const l of d.labels) {\n parts.push(l.label)\n }\n\n return (\n <div\n key={`det-${d.id}`}\n className=\"absolute border-2 rounded-sm\"\n style={{ left: `${left}%`, top: `${top}%`, width: `${width}%`, height: `${height}%`, borderColor: color }}\n >\n <div\n className=\"absolute -top-4 left-0 px-1 py-0.5 text-[9px] font-bold text-white rounded-sm whitespace-nowrap\"\n style={{ backgroundColor: color }}\n >\n {parts.join(' | ')}\n </div>\n </div>\n )\n })}\n </>\n )\n}\n","import { useEffect, useRef, useState, useCallback, type ReactNode } from 'react'\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type PlayerConnectionState = 'connecting' | 'playing' | 'error' | 'disconnected' | 'idle'\n\n/**\n * Signaling function for WebRTC connection.\n * Called by the player to establish the WebRTC session.\n * Must return an RTCSessionDescription (the server's offer or answer depending on mode).\n *\n * Server-offer mode (default):\n * 1. signalingFn is called with streamId → returns { sessionId, sdpOffer }\n * 2. Player sets remote description (server offer), creates answer\n * 3. Player calls answerFn(sessionId, sdpAnswer) to complete\n *\n * WHEP mode (legacy):\n * 1. Player creates offer, gathers ICE\n * 2. signalingFn is called with the client SDP offer → returns sdpAnswer\n * 3. Player sets remote description (answer)\n */\nexport interface SignalingResult {\n /** Server-offer mode: session ID + SDP offer from server */\n sessionId: string\n sdpOffer: string\n}\n\n/**\n * Client-side capabilities sent to the server at session creation.\n * The server uses these to pick the best native source for adaptive\n * streams (e.g. a 320×180 thumbnail player on a slow link gets the\n * camera's low stream rather than ffmpeg-transcoded 4K).\n *\n * All fields are optional — when omitted the server defaults to its\n * highest-quality registered source.\n */\nexport interface ClientStreamHints {\n viewportWidth?: number\n viewportHeight?: number\n devicePixelRatio?: number\n downlinkMbps?: number\n prefersTier?: string\n}\n\n/**\n * Read viewport + browser network info to populate hints. Falls back\n * to `window` size if the container isn't measurable yet (StrictMode\n * double-mount during development can hit this path).\n */\nfunction computeClientHints(container: HTMLElement | null): ClientStreamHints {\n const hints: ClientStreamHints = {}\n if (typeof window !== 'undefined') {\n if (container) {\n const rect = container.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) {\n hints.viewportWidth = Math.round(rect.width)\n hints.viewportHeight = Math.round(rect.height)\n }\n }\n if (hints.viewportWidth === undefined) {\n hints.viewportWidth = window.innerWidth\n hints.viewportHeight = window.innerHeight\n }\n hints.devicePixelRatio = window.devicePixelRatio || 1\n // navigator.connection is non-standard but widely supported in Chromium\n // and used by Firefox behind a flag; absent on Safari. Skip silently.\n const conn = (navigator as unknown as { connection?: { downlink?: number } }).connection\n if (conn?.downlink && conn.downlink > 0) {\n hints.downlinkMbps = conn.downlink\n }\n }\n return hints\n}\n\nexport interface CameraStreamPlayerProps {\n /** Server base URL (e.g. window.location.origin) */\n serverUrl: string\n /**\n * Stable key used for React reconciliation (the player remounts when\n * this changes), the snapshot filename, and WHEP fallback URL. The\n * value is opaque to the player — no parsing, no semantic meaning.\n * Typical values: a `StreamChoice.id` (`'profile:high'`, `'stream:native:main'`).\n */\n streamKey: string\n /** Human-readable label shown in overlay */\n label?: string\n /** Auto-play on mount (default: true) */\n autoPlay?: boolean\n /** Start muted (default: true) */\n muted?: boolean\n /** Show toolbar controls (default: true) */\n showControls?: boolean\n /** Additional CSS classes for the root container */\n className?: string\n /** Called on connection state change */\n onStateChange?: (state: PlayerConnectionState) => void\n /** Called on error */\n onError?: (error: string) => void\n /** Custom overlay rendered on top of the video */\n overlay?: ReactNode\n /**\n * Create a WebRTC session (server-offer signaling). When provided,\n * uses server-offer mode instead of WHEP. The caller closes over the\n * target (profile / cam-stream / adaptive) and any device context;\n * the player just hands it the auto-derived `hints` (viewport,\n * downlink) so the server can score adaptive selections.\n */\n createSession?: (hints?: ClientStreamHints) => Promise<SignalingResult>\n /**\n * Send the client's SDP answer (server-offer signaling).\n * Required when createSession is provided.\n */\n sendAnswer?: (sessionId: string, sdpAnswer: string) => Promise<void>\n /** Explicitly close the WebRTC session on server (cleanup on unmount). */\n closeSession?: (sessionId: string) => Promise<void>\n /**\n * Override client hints sent to the server at session creation.\n * Values provided here replace the auto-computed browser values.\n * Use for network simulation (benchmark) or manual tier forcing.\n */\n hintsOverride?: Partial<ClientStreamHints>\n}\n\nconst RECONNECT_DELAY_MS = 3_000\nconst MAX_RECONNECT_ATTEMPTS = 5\n\n// ── Component ────────────────────────────────────────────────────────────────\n\nexport function CameraStreamPlayer({\n serverUrl,\n streamKey,\n label,\n autoPlay = true,\n muted: initialMuted = true,\n showControls = true,\n className = '',\n onStateChange,\n onError,\n overlay,\n createSession,\n sendAnswer,\n closeSession,\n hintsOverride,\n}: CameraStreamPlayerProps) {\n const videoRef = useRef<HTMLVideoElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const pcRef = useRef<RTCPeerConnection | null>(null)\n /** All session IDs created during this player's lifetime — closed on cleanup */\n const sessionIdsRef = useRef(new Set<string>())\n /** Abort controller to cancel in-flight connection attempts on cleanup */\n const connectAbortRef = useRef<AbortController | null>(null)\n const reconnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const reconnectAttemptsRef = useRef(0)\n const mountedRef = useRef(true)\n\n const [state, setState] = useState<PlayerConnectionState>('idle')\n const [errorMessage, setErrorMessage] = useState('')\n const [isMuted, setIsMuted] = useState(initialMuted)\n const [isFullscreen, setIsFullscreen] = useState(false)\n const [showToolbar, setShowToolbar] = useState(false)\n const hideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n // Mode is sticky-once-set: as soon as the parent supplies any of\n // the server-offer signaling callbacks we lock into server-offer\n // mode for the lifetime of the player. We bias toward \"server-\n // offer intended\" — `sendAnswer` is enough on its own because the\n // parent only wires it up when there's a server signaling channel.\n // `createSession` may briefly be `undefined` while\n // `useDeviceWebrtc.streams` is hydrating; we still need to know\n // we're in server-offer mode so we DON'T fall back to WHEP and\n // trigger a `/api/webrtc 404` on a backend that doesn't speak\n // WHEP. The `connectServerOffer` body itself early-returns when\n // `createSession` isn't ready yet, and the retrigger useEffect\n // below kicks the connection once the callback shows up.\n const serverOfferModeRef = useRef(false)\n if (sendAnswer || createSession) serverOfferModeRef.current = true\n const useServerOffer = serverOfferModeRef.current\n\n const updateState = useCallback((s: PlayerConnectionState) => {\n setState(s)\n onStateChange?.(s)\n }, [onStateChange])\n\n const cleanup = useCallback(() => {\n // Abort any in-flight connection attempt (prevents orphan sessions from StrictMode double-mount)\n connectAbortRef.current?.abort()\n connectAbortRef.current = null\n\n if (reconnectTimerRef.current) {\n clearTimeout(reconnectTimerRef.current)\n reconnectTimerRef.current = null\n }\n if (pcRef.current) {\n pcRef.current.close()\n pcRef.current = null\n }\n // Close ALL sessions created by this player\n if (closeSession && sessionIdsRef.current.size > 0) {\n for (const sid of sessionIdsRef.current) {\n closeSession(sid).catch(() => {})\n }\n sessionIdsRef.current.clear()\n }\n if (videoRef.current) {\n videoRef.current.srcObject = null\n }\n }, [closeSession])\n\n // ── Server-offer connection ──────────────────────────────────────────────\n\n const connectServerOffer = useCallback(async () => {\n if (!mountedRef.current || !createSession || !sendAnswer) return\n\n cleanup()\n updateState('connecting')\n\n const abort = new AbortController()\n connectAbortRef.current = abort\n\n try {\n // Step 1: get server offer (with hints derived from the live player)\n const autoHints = computeClientHints(containerRef.current)\n const mergedHints: ClientStreamHints = { ...autoHints, ...hintsOverride }\n const { sessionId, sdpOffer } = await createSession(mergedHints)\n sessionIdsRef.current.add(sessionId)\n if (!mountedRef.current || abort.signal.aborted) {\n // Cleanup raced — close the just-created session immediately\n closeSession?.(sessionId).catch(() => {})\n sessionIdsRef.current.delete(sessionId)\n return\n }\n\n // Step 2: create peer connection\n const pc = new RTCPeerConnection({\n iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],\n })\n pcRef.current = pc\n\n // Collect all tracks and attach them to the video element.\n // The server sends video and audio in separate streams (different msid),\n // so we aggregate them into a single MediaStream for the video element.\n const combinedStream = new MediaStream()\n\n pc.ontrack = (event) => {\n console.debug('[WebRTC] ontrack', event.track.kind, event.track.readyState)\n combinedStream.addTrack(event.track)\n if (videoRef.current) {\n videoRef.current.srcObject = combinedStream\n // Chrome won't auto-play a MediaStream that has no data yet.\n // Explicitly call play() each time a track arrives so the\n // element starts rendering as soon as RTP packets flow.\n videoRef.current.play().catch(() => {})\n }\n }\n\n pc.oniceconnectionstatechange = () => {\n if (!mountedRef.current) return\n const iceState = pc.iceConnectionState\n console.debug('[WebRTC] ICE state:', iceState)\n if (iceState === 'connected' || iceState === 'completed') {\n reconnectAttemptsRef.current = 0\n updateState('playing')\n // Ensure the video is actually playing — autoplay alone is\n // insufficient when the MediaStream had no data at attach time.\n if (videoRef.current?.paused) {\n console.debug('[WebRTC] video was paused at ICE connected — calling play()')\n videoRef.current.play().catch(() => {})\n }\n } else if (iceState === 'failed' || iceState === 'disconnected' || iceState === 'closed') {\n updateState('disconnected')\n scheduleReconnect()\n }\n }\n\n pc.onicecandidateerror = (event) => {\n console.debug('[WebRTC] ICE candidate error:', event)\n }\n\n // Step 3: set remote description (server offer) and create answer\n console.debug('[WebRTC] Setting remote description (server offer)...')\n await pc.setRemoteDescription({ type: 'offer', sdp: sdpOffer })\n const answer = await pc.createAnswer()\n await pc.setLocalDescription(answer)\n console.debug('[WebRTC] Local description set, waiting for ICE gathering...')\n\n // Wait for ICE gathering\n await waitForIceGathering(pc)\n if (!mountedRef.current) return\n\n const localCandidates = (pc.localDescription?.sdp ?? '').split('\\n').filter(l => l.startsWith('a=candidate:')).length\n console.debug('[WebRTC] Sending answer to server', { localCandidates, sessionId: sessionId.slice(0, 8) })\n\n // Step 4: send answer to server\n await sendAnswer(sessionId, pc.localDescription?.sdp ?? '')\n console.debug('[WebRTC] Answer sent successfully')\n\n // Step 5: Monitor actual media flow (diagnostic — remove after stabilisation)\n const savedPc = pc\n const checkMedia = () => {\n const connState = savedPc.connectionState\n if (connState === 'closed' || connState === 'failed') return\n const videoEl = videoRef.current\n if (videoEl && videoEl.readyState === 0) {\n console.log(`[WebRTC] no video data yet (ice=${savedPc.iceConnectionState})`)\n }\n }\n setTimeout(checkMedia, 3000)\n setTimeout(checkMedia, 8000)\n } catch (err) {\n if (!mountedRef.current) return\n const msg = err instanceof Error ? err.message : String(err)\n setErrorMessage(msg)\n updateState('error')\n onError?.(msg)\n scheduleReconnect()\n }\n }, [serverUrl, streamKey, createSession, sendAnswer, cleanup, updateState, onError, hintsOverride])\n\n // ── WHEP connection (legacy fallback) ────────────────────────────────────\n\n const connectWhep = useCallback(async () => {\n if (!mountedRef.current) return\n\n cleanup()\n updateState('connecting')\n\n try {\n const pc = new RTCPeerConnection({\n iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],\n })\n pcRef.current = pc\n\n pc.addTransceiver('video', { direction: 'recvonly' })\n pc.addTransceiver('audio', { direction: 'recvonly' })\n\n const whepStream = new MediaStream()\n\n pc.ontrack = (event) => {\n whepStream.addTrack(event.track)\n if (videoRef.current) {\n videoRef.current.srcObject = whepStream\n videoRef.current.play().catch(() => {})\n }\n }\n\n pc.oniceconnectionstatechange = () => {\n if (!mountedRef.current) return\n const iceState = pc.iceConnectionState\n if (iceState === 'connected' || iceState === 'completed') {\n reconnectAttemptsRef.current = 0\n updateState('playing')\n if (videoRef.current?.paused) {\n videoRef.current.play().catch(() => {})\n }\n } else if (iceState === 'failed' || iceState === 'disconnected' || iceState === 'closed') {\n updateState('disconnected')\n scheduleReconnect()\n }\n }\n\n const offer = await pc.createOffer()\n await pc.setLocalDescription(offer)\n await waitForIceGathering(pc)\n if (!mountedRef.current) return\n\n const whepUrl = `${serverUrl}/api/webrtc?src=${encodeURIComponent(streamKey)}`\n const response = await fetch(whepUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/sdp' },\n body: pc.localDescription?.sdp ?? '',\n })\n\n if (!response.ok) {\n throw new Error(`WHEP ${response.status}: ${response.statusText}`)\n }\n\n const answerSdp = await response.text()\n await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp })\n } catch (err) {\n if (!mountedRef.current) return\n const msg = err instanceof Error ? err.message : String(err)\n setErrorMessage(msg)\n updateState('error')\n onError?.(msg)\n scheduleReconnect()\n }\n }, [serverUrl, streamKey, cleanup, updateState, onError])\n\n // ── Shared logic ─────────────────────────────────────────────────────────\n\n const connect = useServerOffer ? connectServerOffer : connectWhep\n\n // Stash the latest `connect` in a ref. The setTimeout body inside\n // `scheduleReconnect` would otherwise capture whatever `connect` was\n // at the time `scheduleReconnect` was last memoized — and on the\n // very first render (before sticky server-offer mode is set or\n // `createSession` is supplied) that's `connectWhep`. Once the loop\n // is wedged on the WHEP path each retry re-arms a setTimeout that\n // STILL holds the old `connect`, so the 404 retries every\n // `RECONNECT_DELAY_MS` forever despite the sticky flag. Reading\n // through a ref breaks the closure capture without having to\n // memoize away the conditional.\n const connectRef = useRef<() => Promise<void> | void>(() => {})\n connectRef.current = connect\n\n const scheduleReconnect = useCallback(() => {\n if (!mountedRef.current) return\n if (reconnectAttemptsRef.current >= MAX_RECONNECT_ATTEMPTS) return\n reconnectAttemptsRef.current += 1\n reconnectTimerRef.current = setTimeout(() => {\n if (mountedRef.current) void connectRef.current()\n }, RECONNECT_DELAY_MS)\n }, [])\n\n useEffect(() => {\n mountedRef.current = true\n reconnectAttemptsRef.current = 0\n if (autoPlay) connect()\n return () => {\n mountedRef.current = false\n cleanup()\n }\n }, [serverUrl, streamKey])\n\n // Retrigger the initial connection once `createSession` resolves —\n // when the parent's `useDeviceWebrtc` is still hydrating its stream\n // list, `createSession` arrives `undefined`, our sticky mode flag\n // already locked in server-offer (so we don't fall back to WHEP),\n // but the early-return inside `connectServerOffer` skipped the\n // first attempt. As soon as the parent supplies the real callbacks,\n // kick off the handshake.\n const hasSignaledRef = useRef(false)\n useEffect(() => {\n if (!autoPlay || !useServerOffer) return\n if (!createSession || !sendAnswer) return\n if (hasSignaledRef.current) return\n if (pcRef.current) return // already connected\n hasSignaledRef.current = true\n connect()\n }, [autoPlay, useServerOffer, createSession, sendAnswer, connect])\n\n // ── Actions ──────────────────────────────────────────────────────────────\n\n const handleReconnect = () => {\n reconnectAttemptsRef.current = 0\n connect()\n }\n\n const toggleMute = () => {\n if (videoRef.current) {\n videoRef.current.muted = !videoRef.current.muted\n setIsMuted(videoRef.current.muted)\n }\n }\n\n const toggleFullscreen = async () => {\n if (!containerRef.current) return\n try {\n if (document.fullscreenElement) {\n await document.exitFullscreen()\n } else {\n await containerRef.current.requestFullscreen()\n }\n } catch (err) { console.warn(`Fullscreen toggle failed: ${err instanceof Error ? err.message : err}`) }\n }\n\n const takeSnapshot = () => {\n if (!videoRef.current) return\n const canvas = document.createElement('canvas')\n canvas.width = videoRef.current.videoWidth || 1280\n canvas.height = videoRef.current.videoHeight || 720\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n ctx.drawImage(videoRef.current, 0, 0)\n const link = document.createElement('a')\n link.download = `${streamKey.replace(/[/:]/g, '-')}-${Date.now()}.jpg`\n link.href = canvas.toDataURL('image/jpeg', 0.92)\n link.click()\n }\n\n useEffect(() => {\n const handler = () => setIsFullscreen(!!document.fullscreenElement)\n document.addEventListener('fullscreenchange', handler)\n return () => document.removeEventListener('fullscreenchange', handler)\n }, [])\n\n const showToolbarBriefly = () => {\n setShowToolbar(true)\n if (hideTimerRef.current) clearTimeout(hideTimerRef.current)\n hideTimerRef.current = setTimeout(() => setShowToolbar(false), 3000)\n }\n\n // ── Render ───────────────────────────────────────────────────────────────\n\n return (\n <div\n ref={containerRef}\n className={`relative bg-black overflow-hidden group ${className}`}\n onMouseMove={showToolbarBriefly}\n onMouseEnter={showToolbarBriefly}\n >\n <video\n ref={videoRef}\n autoPlay={autoPlay}\n muted={isMuted}\n playsInline\n className=\"w-full h-full object-contain\"\n />\n\n {label && state === 'playing' && (\n <div className=\"absolute top-2 left-2 px-2 py-0.5 rounded bg-black/60 text-[10px] text-white font-medium\">\n {label}\n </div>\n )}\n\n {overlay}\n\n {state === 'connecting' && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/70 gap-2\">\n <svg className=\"h-6 w-6 text-white/60 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeDasharray=\"32\" strokeDashoffset=\"32\" className=\"animate-[dash_1.5s_ease-in-out_infinite]\" />\n </svg>\n <span className=\"text-xs text-white/60\">Connecting…</span>\n </div>\n )}\n\n {(state === 'error' || state === 'disconnected') && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/70 gap-2\">\n <svg className=\"h-6 w-6 text-red-400\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M1 1l5.5 5.5M23 23l-5.5-5.5M8.11 15.89a8 8 0 0110.78-10.78M3.64 3.64A12 12 0 0020.36 20.36\" strokeLinecap=\"round\" />\n </svg>\n <span className=\"text-xs text-red-400 text-center px-4\">\n {state === 'error' ? errorMessage || 'Connection failed' : 'Disconnected'}\n </span>\n <button\n onClick={handleReconnect}\n className=\"mt-1 inline-flex items-center gap-1.5 rounded px-3 py-1 text-xs bg-white/10 text-white hover:bg-white/20 transition-colors\"\n >\n Reconnect\n </button>\n </div>\n )}\n\n {showControls && state === 'playing' && (\n <div\n className={`absolute bottom-0 inset-x-0 flex items-center justify-between px-3 py-1.5 bg-gradient-to-t from-black/80 to-transparent transition-opacity duration-200 ${\n showToolbar ? 'opacity-100' : 'opacity-0'\n }`}\n >\n <div className=\"flex items-center gap-1\">\n <ToolbarButton onClick={toggleMute} title={isMuted ? 'Unmute' : 'Mute'}>\n {isMuted ? (\n <svg className=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\n <line x1=\"23\" y1=\"9\" x2=\"17\" y2=\"15\" /><line x1=\"17\" y1=\"9\" x2=\"23\" y2=\"15\" />\n </svg>\n ) : (\n <svg className=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\n <path d=\"M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07\" />\n </svg>\n )}\n </ToolbarButton>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <ToolbarButton onClick={takeSnapshot} title=\"Take snapshot\">\n <svg className=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z\" />\n <circle cx=\"12\" cy=\"13\" r=\"4\" />\n </svg>\n </ToolbarButton>\n\n <ToolbarButton onClick={toggleFullscreen} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>\n {isFullscreen ? (\n <svg className=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M8 3v3a2 2 0 01-2 2H3m18 0h-3a2 2 0 01-2-2V3m0 18v-3a2 2 0 012-2h3M3 16h3a2 2 0 012 2v3\" />\n </svg>\n ) : (\n <svg className=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3\" />\n </svg>\n )}\n </ToolbarButton>\n </div>\n </div>\n )}\n </div>\n )\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction ToolbarButton({\n onClick,\n title,\n children,\n}: {\n onClick: () => void\n title: string\n children: ReactNode\n}) {\n return (\n <button\n onClick={onClick}\n title={title}\n className=\"rounded-full p-1.5 text-white/80 hover:text-white hover:bg-white/20 transition-colors\"\n >\n {children}\n </button>\n )\n}\n\nasync function waitForIceGathering(pc: RTCPeerConnection): Promise<void> {\n if (pc.iceGatheringState === 'complete') return\n return new Promise<void>((resolve) => {\n const handler = () => {\n if (pc.iceGatheringState === 'complete') {\n pc.removeEventListener('icegatheringstatechange', handler)\n resolve()\n }\n }\n pc.addEventListener('icegatheringstatechange', handler)\n setTimeout(resolve, 5000)\n })\n}\n","/**\n * StreamPanel — unified camera stream viewer with header bar, overlay toggles,\n * stream selector, pipeline phase, play/stop, and snapshot preview.\n *\n * Combines features from LiveStreamViewer (admin-ui) and PipelineTab (benchmark)\n * into a single reusable component in ui-library.\n *\n * The component is data-agnostic: callers fetch devices/streams/detections using\n * their own hooks and pass the results as props.\n */\nimport { useState, useMemo, useRef, useEffect, type ReactNode } from 'react'\nimport { CameraStreamPlayer, type SignalingResult, type ClientStreamHints } from './camera-stream-player'\nimport { DetectionOverlay } from './detection-overlay'\nimport type { DeviceDetections } from '../hooks/use-device-detections'\nimport { usePlayerToolbarButtons } from '../contexts/player-overlays'\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\n/**\n * Discriminated WebRTC target — same shape as the backend cap. Kept\n * locally on the StreamChoice so consumers don't need to import from\n * `@camstack/types` to render a panel.\n */\nexport type StreamChoiceTarget =\n | { readonly kind: 'adaptive' }\n | { readonly kind: 'profile'; readonly profile: 'high' | 'mid' | 'low' }\n | { readonly kind: 'cam-stream'; readonly camStreamId: string }\n\nexport interface StreamChoice {\n /**\n * Stable identifier for React keys, dropdown values, and the\n * player's `streamKey` prop. Opaque to the panel — typical values:\n * `'adaptive'`, `'profile:high'`, `'stream:native:main'`.\n */\n readonly id: string\n /** Display label (e.g. \"Adaptive\", \"HIGH (3840×2160)\", \"Native main\"). */\n readonly label: string\n /** Structured WebRTC target — passed verbatim to `createSession`. */\n readonly target: StreamChoiceTarget\n /** Live broker status (null if unavailable). */\n readonly status?: string | null\n /** Input FPS from camera (null if unavailable). */\n readonly inputFps?: number | null\n /** Decoded FPS (null if unavailable). */\n readonly decodeFps?: number | null\n /** Bitrate in kbps (null if unavailable). */\n readonly bitrateKbps?: number | null\n}\n\nexport interface StreamStats {\n readonly status: string\n readonly inputFps: number\n readonly decodeFps: number\n readonly uptimeMs: number\n}\n\nexport interface StreamPanelProps {\n // --- Required: WebRTC signaling ---\n readonly serverUrl: string\n readonly createSession: (target: StreamChoiceTarget, hints?: ClientStreamHints) => Promise<SignalingResult>\n readonly sendAnswer: (sessionId: string, sdpAnswer: string) => Promise<void>\n readonly closeSession?: (sessionId: string) => Promise<void>\n\n // --- Stream selection ---\n /** Available streams. If omitted or single entry, no dropdown shown. */\n readonly streams?: readonly StreamChoice[]\n /** Currently active StreamChoice id. Defaults to first stream. */\n readonly activeStreamId?: string\n /** Called when user selects a different stream (StreamChoice id). */\n readonly onStreamChange?: (id: string) => void\n\n // --- Device / header info ---\n readonly deviceName?: string\n /** Pipeline phase from useDeviceDetections (e.g. \"active\", \"watching\") */\n readonly phase?: string\n /** Pipeline metrics from useDeviceWebrtc. If provided, overrides phase and adds detection fps. */\n readonly pipelineMetrics?: { phase: string; detectionFps: number; avgInferenceMs: number } | null\n\n // --- Detection overlays ---\n /** Detection data from useDeviceDetections hook. If omitted, no overlays. */\n readonly detections?: DeviceDetections\n /** Initial state for detection overlay (default: true) */\n readonly defaultShowDetections?: boolean\n /** Initial state for motion overlay (default: false) */\n readonly defaultShowMotion?: boolean\n\n // --- Stream stats (optional) ---\n readonly streamStats?: StreamStats\n\n // --- Play/Stop + Snapshot ---\n /** Auto-play on mount (default: true) */\n readonly autoPlay?: boolean\n /** Show play/stop toggle + snapshot preview when stopped (default: false) */\n readonly showPlayStop?: boolean\n /** Snapshot source URL (data: URI). Only used when showPlayStop=true. */\n readonly snapshotSrc?: string | null\n /** Whether snapshot is currently loading */\n readonly snapshotLoading?: boolean\n /** Callback to refresh snapshot */\n readonly onRefreshSnapshot?: () => void\n\n // --- Visibility ---\n /** Show stream stats in header (fps, uptime) (default: false) */\n readonly showStreamStats?: boolean\n\n // --- Extra content below the video ---\n readonly children?: ReactNode\n\n /**\n * Extra overlay node composited on top of the video, alongside the\n * built-in detection overlay. Used by callers to layer device-scoped\n * controls (PTZOverlay, AudioPTT, ...) without forking the panel.\n */\n readonly extraOverlay?: ReactNode\n\n /**\n * Whether the device supports PTZ. When true, the header shows a\n * \"PTZ\" toggle next to detect/motion.\n */\n readonly ptzAvailable?: boolean\n /**\n * Controlled visibility of the PTZ overlay. Drives both the\n * header button highlight and (combined with `ptzOverlay`) overlay\n * rendering. Caller computes the final value (e.g. OR with an\n * external \"force on\" surface like a floating PTZ panel) and\n * passes it down here.\n */\n readonly ptzShown?: boolean\n /**\n * Overlay rendered ON the live video when `ptzShown` is true.\n * Typically a `<PTZOverlay controls={...} mode=\"overlay\" />` from\n * ui-library. Combined with `extraOverlay` in the player overlay\n * slot — both render together when active.\n */\n readonly ptzOverlay?: ReactNode\n /**\n * Notified when the user clicks the in-header PTZ toggle. The\n * caller updates its source of truth for `ptzShown`. No-op if\n * omitted (button stays inert).\n */\n readonly onPtzToggle?: () => void\n\n /**\n * Whether the device supports two-way audio (intercom). When true,\n * the header shows an \"Intercom\" toggle next to detect/motion that\n * lets the operator open the floating intercom panel without leaving\n * the stream view.\n */\n readonly intercomAvailable?: boolean\n /**\n * Controlled visibility of the intercom panel — drives the button's\n * highlight state. The caller (which owns the floating-panel state)\n * passes `true` while its intercom panel is open.\n */\n readonly intercomShown?: boolean\n /**\n * Notified when the user clicks the in-header intercom toggle. The\n * caller flips its panel state. No-op if omitted (button inert).\n */\n readonly onIntercomToggle?: () => void\n\n /**\n * When true, drops the panel's outer rounded card chrome (border,\n * rounded corners, background). Use when embedding into another\n * surface that already provides framing — e.g. the device-detail\n * left-column hero where the panel is one row of a larger card.\n */\n readonly chromeless?: boolean\n\n readonly className?: string\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction statusDot(st: string): string {\n if (st === 'streaming') return 'bg-emerald-500'\n if (st === 'connecting') return 'bg-amber-500'\n if (st === 'error') return 'bg-rose-500'\n return 'bg-zinc-500'\n}\n\nfunction fmtUptime(ms: number): string {\n const s = Math.floor(ms / 1000)\n if (s < 60) return `${s}s`\n if (s < 3600) return `${Math.floor(s / 60)}m`\n return `${Math.floor(s / 3600)}h${Math.floor((s % 3600) / 60)}m`\n}\n\n// ── Play icon (inline SVG to avoid lucide-react dependency in ui-library) ───\n\nfunction PlayIcon({ className }: { readonly className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polygon points=\"5 3 19 12 5 21 5 3\" />\n </svg>\n )\n}\n\nfunction StopIcon({ className }: { readonly className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"1\" />\n </svg>\n )\n}\n\nfunction MicIcon({ className }: { readonly className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\" />\n <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\" />\n </svg>\n )\n}\n\nfunction MoreIcon({ className }: { readonly className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"5\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"19\" cy=\"12\" r=\"2\" />\n </svg>\n )\n}\n\n// Sub-menu row used for boolean toggles in the kebab popover.\nfunction MenuToggle({ label, active, onClick }: { readonly label: string; readonly active: boolean; readonly onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"w-full flex items-center justify-between gap-3 px-3 py-1.5 text-[11px] text-foreground hover:bg-surface-hover transition-colors\"\n >\n <span>{label}</span>\n <span className={`inline-block h-3 w-5 rounded-full transition-colors ${active ? 'bg-primary' : 'bg-foreground-subtle/30'} relative`}>\n <span className={`absolute top-0.5 h-2 w-2 rounded-full bg-white transition-all ${active ? 'left-2.5' : 'left-0.5'}`} />\n </span>\n </button>\n )\n}\n\nfunction RefreshIcon({ className }: { readonly className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"23 4 23 10 17 10\" /><polyline points=\"1 20 1 14 7 14\" />\n <path d=\"M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15\" />\n </svg>\n )\n}\n\nfunction ImageOffIcon({ className }: { readonly className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"2\" y1=\"2\" x2=\"22\" y2=\"22\" />\n <path d=\"M10.41 10.41a2 2 0 11-2.83-2.83\" />\n <line x1=\"13.5\" y1=\"13.5\" x2=\"6\" y2=\"21\" />\n <path d=\"M18 12l-1.5-1.5\" />\n <path d=\"M21 15V5a2 2 0 00-2-2H5\" />\n <path d=\"M21 21H5a2 2 0 01-2-2V11\" />\n </svg>\n )\n}\n\n// ── Component ────────────────────────────────────────────────────────────────\n\nexport function StreamPanel({\n serverUrl,\n createSession,\n sendAnswer,\n closeSession,\n streams,\n activeStreamId: controlledStreamId,\n onStreamChange,\n deviceName,\n phase,\n pipelineMetrics,\n detections,\n defaultShowDetections = true,\n defaultShowMotion = false,\n streamStats,\n autoPlay = false,\n showPlayStop = false,\n snapshotSrc,\n snapshotLoading = false,\n onRefreshSnapshot,\n showStreamStats = false,\n children,\n extraOverlay,\n ptzAvailable = false,\n ptzShown = false,\n ptzOverlay,\n onPtzToggle,\n intercomAvailable = false,\n intercomShown = false,\n onIntercomToggle,\n chromeless = false,\n className,\n}: StreamPanelProps) {\n // Toolbar buttons registered by sibling tabs / addon UIs via\n // `usePlayerToolbarButton`. The host renders them uniformly next to\n // the always-on actions (Intercom + Play/Stop). Lets a tab (Detection\n // → Zones, Live stats → Speak, ...) own its button without forking\n // this composite.\n const registeredButtons = usePlayerToolbarButtons()\n // --- Internal state ---\n const [isPlaying, setIsPlaying] = useState(autoPlay)\n const [showDetections, setShowDetections] = useState(defaultShowDetections)\n const [showMotion, setShowMotion] = useState(defaultShowMotion)\n const [internalStreamId, setInternalStreamId] = useState<string | null>(null)\n\n // Sub-menu (kebab) for the secondary controls — Detect/Motion/PTZ\n // toggles + stream stats + adaptive picker. Only Intercom and\n // Play/Stop stay always-visible in the toolbar.\n const [menuOpen, setMenuOpen] = useState(false)\n const menuRef = useRef<HTMLDivElement>(null)\n useEffect(() => {\n if (!menuOpen) return\n function onClick(e: MouseEvent) {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setMenuOpen(false)\n }\n }\n document.addEventListener('mousedown', onClick)\n return () => document.removeEventListener('mousedown', onClick)\n }, [menuOpen])\n\n // Resolve effective stream by StreamChoice id.\n const effectiveStreamId = controlledStreamId\n ?? internalStreamId\n ?? streams?.[0]?.id\n ?? ''\n\n // Derive stats from the currently selected stream choice\n const selectedChoice = streams?.find(s => s.id === effectiveStreamId) ?? streams?.[0]\n const choiceStats = selectedChoice?.inputFps != null\n ? { status: selectedChoice.status ?? 'unknown', inputFps: selectedChoice.inputFps, bitrateKbps: selectedChoice.bitrateKbps ?? 0 }\n : null\n\n const handleStreamChange = (id: string) => {\n setInternalStreamId(id)\n onStreamChange?.(id)\n // Restart player on stream change\n if (isPlaying && showPlayStop) {\n setIsPlaying(false)\n setTimeout(() => setIsPlaying(true), 50)\n }\n }\n\n // Closure passed to the player — captures the selected target so the\n // player itself stays target-agnostic and only ships hints.\n const playerCreateSession = useMemo<((hints?: ClientStreamHints) => Promise<SignalingResult>) | undefined>(() => {\n const target = selectedChoice?.target\n if (!target) return undefined\n return (hints) => createSession(target, hints)\n }, [createSession, selectedChoice])\n\n const visibleStreams = streams\n\n const handlePlay = () => setIsPlaying(true)\n const handleStop = () => setIsPlaying(false)\n\n const effectivePhase = pipelineMetrics?.phase ?? phase\n const isPhaseActive = effectivePhase === 'active'\n const hasDetections = !!detections\n const anyOverlay = hasDetections && (showDetections || showMotion)\n // The overlay renders when the caller marks PTZ as shown AND\n // supplies an overlay node. `ptzShown` is fully controlled — the\n // caller is the source of truth, so external surfaces (a floating\n // PTZ panel) and the in-header toggle can OR cleanly without\n // mirroring state.\n const ptzOverlayVisible = ptzAvailable && ptzShown && Boolean(ptzOverlay)\n const showingVideo = showPlayStop ? isPlaying : true\n\n return (\n <div className={`overflow-hidden ${chromeless ? '' : 'rounded-xl border border-border bg-surface'} ${className ?? ''}`}>\n {/* ── Header bar ─────────────────────────────────────────────────── */}\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-border\">\n {/* Left: device name + stream selector */}\n <div className=\"flex items-center gap-2\">\n {(streamStats ?? choiceStats) && (\n <span className={`w-2 h-2 rounded-full ${statusDot((streamStats ?? choiceStats)!.status)}`} />\n )}\n {deviceName && (\n <span className=\"text-xs font-medium text-foreground\">{deviceName}</span>\n )}\n {/* Stream selector — styled to match the toolbar buttons.\n Uses the native `<select>` for accessibility but with\n custom chrome (no native arrow on macOS / Windows that\n looks out-of-context against the dark toolbar). */}\n {visibleStreams && visibleStreams.length > 1 && (\n <div className=\"relative\">\n <select\n data-testid=\"stream-profile-select\"\n value={effectiveStreamId}\n onChange={e => handleStreamChange(e.target.value)}\n className=\"appearance-none cursor-pointer rounded-md border border-border bg-surface-hover hover:bg-surface text-foreground text-[11px] font-medium pl-2 pr-6 py-1 focus:outline-none focus:ring-1 focus:ring-primary transition-colors\"\n >\n {visibleStreams.map(s => (\n <option key={s.id} value={s.id}>{s.label}</option>\n ))}\n </select>\n <span className=\"pointer-events-none absolute right-1.5 top-1/2 -translate-y-1/2 text-foreground-subtle\">\n <svg className=\"h-2.5 w-2.5\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"3 4.5 6 7.5 9 4.5\" />\n </svg>\n </span>\n </div>\n )}\n </div>\n\n {/* Right: only the always-on actions (Intercom + Play/Stop) +\n kebab. Stats / Detect / Motion / PTZ / RefreshSnapshot all\n collapse into the kebab so the toolbar fits the narrowest\n stream-column width on every breakpoint. */}\n <div className=\"flex items-center gap-1.5\">\n {/* Intercom toggle — when device advertises two-way audio.\n Always visible (label hides on narrow widths so the icon\n alone fits when the row gets cramped). */}\n {intercomAvailable && (\n <button\n data-testid=\"stream-intercom-toggle\"\n data-intercom-shown={intercomShown ? 'true' : 'false'}\n onClick={onIntercomToggle}\n className={`inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors ${intercomShown ? 'bg-primary/15 text-primary' : 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover'}`}\n title={intercomShown ? 'Close intercom' : 'Open intercom'}\n >\n <MicIcon className=\"h-3 w-3\" />\n <span className=\"hidden xl:inline\">Intercom</span>\n </button>\n )}\n\n {/* Toolbar buttons contributed by sibling tabs via the\n player-overlays registry. Same shell as the built-in\n Intercom button — registry entries pick their own icon,\n label, active flag and tone. */}\n {registeredButtons.map((b) => {\n const isPrimary = b.tone === 'primary'\n const activeCls = isPrimary\n ? 'bg-primary text-primary-foreground'\n : 'bg-primary/15 text-primary'\n const idleCls = 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover'\n return (\n <button\n key={b.id}\n type=\"button\"\n data-toolbar-button-id={b.id}\n data-toolbar-button-active={b.active ? 'true' : 'false'}\n onClick={b.onClick}\n disabled={b.disabled}\n className={`inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors disabled:opacity-50 ${b.active ? activeCls : idleCls}`}\n title={b.title ?? b.label}\n >\n {b.icon}\n <span className=\"hidden xl:inline\">{b.label}</span>\n </button>\n )\n })}\n\n {/* Play/Stop — always visible when showPlayStop is on. */}\n {showPlayStop && (\n <button\n data-testid=\"stream-play-toggle\"\n data-stream-playing={showingVideo ? 'true' : 'false'}\n onClick={showingVideo ? handleStop : handlePlay}\n className={`inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors ${\n showingVideo\n ? 'bg-danger/10 text-danger hover:bg-danger/20'\n : 'bg-primary/10 text-primary hover:bg-primary/20'\n }`}\n title={showingVideo ? 'Stop stream' : 'Start stream'}\n >\n {showingVideo ? <StopIcon className=\"h-3 w-3\" /> : <PlayIcon className=\"h-3 w-3\" />}\n <span className=\"hidden xl:inline\">{showingVideo ? 'Stop' : 'Play'}</span>\n </button>\n )}\n\n {/* Force-snapshot — always visible when a refresh handler is\n wired. Independent of play state so the operator can warm\n the cached snapshot (used by the camera grid + zones tab)\n while still watching live video. */}\n {onRefreshSnapshot && (\n <button\n data-testid=\"stream-snapshot-refresh\"\n onClick={onRefreshSnapshot}\n disabled={snapshotLoading}\n className=\"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors disabled:opacity-50\"\n title=\"Force snapshot refresh\"\n >\n <RefreshIcon className={`h-3 w-3 ${snapshotLoading ? 'animate-spin' : ''}`} />\n <span className=\"hidden xl:inline\">Snapshot</span>\n </button>\n )}\n\n {/* Kebab — secondary controls (toggles, stats, snapshot\n refresh). Only renders when there's at least one\n secondary action to surface, so non-camera stream-less\n hosts don't get an empty button. */}\n {(hasDetections || ptzAvailable || pipelineMetrics || effectivePhase || streamStats || (choiceStats && choiceStats.inputFps > 0)) && (\n <div ref={menuRef} className=\"relative\">\n <button\n onClick={() => setMenuOpen(o => !o)}\n title=\"More controls\"\n className=\"inline-flex items-center justify-center rounded-md p-1 text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors\"\n >\n <MoreIcon className=\"h-3.5 w-3.5\" />\n </button>\n {menuOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-30 min-w-[200px] rounded-lg border border-border bg-surface shadow-xl py-1.5\">\n {/* Stats */}\n {showStreamStats && streamStats && (\n <div className=\"px-3 py-1.5 text-[10px] text-foreground-subtle border-b border-border-subtle\">\n <div className=\"flex justify-between gap-3\"><span>Input</span><span className=\"tabular-nums text-foreground\">{streamStats.inputFps.toFixed(1)} fps</span></div>\n <div className=\"flex justify-between gap-3\"><span>Decode</span><span className=\"tabular-nums text-foreground\">{streamStats.decodeFps.toFixed(1)} fps</span></div>\n <div className=\"flex justify-between gap-3\"><span>Uptime</span><span className=\"tabular-nums text-foreground\">{fmtUptime(streamStats.uptimeMs)}</span></div>\n </div>\n )}\n {!showStreamStats && choiceStats && choiceStats.inputFps > 0 && (\n <div className=\"px-3 py-1.5 text-[10px] text-foreground-subtle border-b border-border-subtle\">\n <div className=\"flex justify-between gap-3\"><span>Input</span><span className=\"tabular-nums text-foreground\">{choiceStats.inputFps.toFixed(1)} fps</span></div>\n {choiceStats.bitrateKbps > 0 && (\n <div className=\"flex justify-between gap-3\"><span>Bitrate</span><span className=\"tabular-nums text-foreground\">{choiceStats.bitrateKbps} kbps</span></div>\n )}\n </div>\n )}\n {/* Phase */}\n {(pipelineMetrics || (hasDetections && effectivePhase)) && (\n <div className=\"px-3 py-1.5 text-[10px] text-foreground-subtle border-b border-border-subtle\">\n <div className=\"flex justify-between gap-3 items-center\">\n <span>Phase</span>\n <span className={`flex items-center gap-1 font-semibold uppercase tracking-wider ${isPhaseActive ? 'text-red-400' : 'text-emerald-400'}`}>\n <span className={`w-1.5 h-1.5 rounded-full ${isPhaseActive ? 'bg-red-500 animate-pulse' : 'bg-emerald-500'}`} />\n {isPhaseActive ? 'Active' : 'Watching'}\n </span>\n </div>\n {pipelineMetrics && pipelineMetrics.detectionFps > 0 && (\n <div className=\"flex justify-between gap-3\"><span>Detection</span><span className=\"tabular-nums text-foreground\">{pipelineMetrics.detectionFps.toFixed(1)} det/s</span></div>\n )}\n {pipelineMetrics && pipelineMetrics.avgInferenceMs > 0 && (\n <div className=\"flex justify-between gap-3\"><span>Inference</span><span className=\"tabular-nums text-foreground\">{pipelineMetrics.avgInferenceMs.toFixed(0)} ms</span></div>\n )}\n </div>\n )}\n {/* Toggles */}\n {hasDetections && (\n <>\n <MenuToggle\n label=\"Show detections\"\n active={showDetections}\n onClick={() => setShowDetections(v => !v)}\n />\n <MenuToggle\n label=\"Show motion\"\n active={showMotion}\n onClick={() => setShowMotion(v => !v)}\n />\n </>\n )}\n {ptzAvailable && (\n <MenuToggle\n label=\"PTZ controls\"\n active={ptzShown}\n onClick={() => { onPtzToggle?.(); setMenuOpen(false) }}\n />\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* ── Video area ─────────────────────────────────────────────────── */}\n {showingVideo ? (\n <div className=\"aspect-video relative\">\n <CameraStreamPlayer\n key={effectiveStreamId}\n serverUrl={serverUrl}\n streamKey={effectiveStreamId}\n autoPlay\n className=\"w-full h-full\"\n createSession={playerCreateSession}\n sendAnswer={sendAnswer}\n closeSession={closeSession}\n overlay={(anyOverlay || extraOverlay || ptzOverlayVisible) ? (\n <>\n {anyOverlay && (\n <DetectionOverlay\n detections={detections!}\n showPhaseIndicator={false}\n showMotionZones={showMotion}\n showMotionRaw={showMotion}\n showDetections={showDetections}\n />\n )}\n {extraOverlay}\n {ptzOverlayVisible && ptzOverlay}\n </>\n ) : undefined}\n />\n </div>\n ) : (\n <SnapshotPreview\n src={snapshotSrc ?? null}\n isLoading={snapshotLoading}\n onPlay={handlePlay}\n onRetry={onRefreshSnapshot}\n // Layered overlays (zones, PTZ) ride on top of the snapshot too,\n // so the operator can edit zones while the live stream is paused.\n // When at least one overlay is registered we suppress the\n // click-to-play hover layer — otherwise it would steal pointer\n // events from the Konva stage. The toolbar Play button stays\n // wired regardless.\n extraOverlay={(extraOverlay || ptzOverlayVisible) ? (\n <>\n {extraOverlay}\n {ptzOverlayVisible && ptzOverlay}\n </>\n ) : null}\n suppressPlayHover={Boolean(extraOverlay) || ptzOverlayVisible}\n />\n )}\n\n {children}\n </div>\n )\n}\n\n// ── SnapshotPreview ──────────────────────────────────────────────────────────\n\nfunction SnapshotPreview({\n src,\n isLoading,\n onPlay,\n onRetry,\n extraOverlay,\n suppressPlayHover = false,\n}: {\n readonly src: string | null\n readonly isLoading: boolean\n readonly onPlay: () => void\n readonly onRetry?: () => void\n /** Layered overlays (zones, PTZ, …) painted on top of the still\n * image so editing surfaces stay usable while paused. */\n readonly extraOverlay?: ReactNode\n /** Hide the click-to-play hover button — used when an overlay is\n * active so it doesn't steal pointer events from Konva-style\n * stages. The toolbar Play button stays available. */\n readonly suppressPlayHover?: boolean\n}) {\n // Keep the last-known image visible while a refresh is in flight.\n // The header refresh button already shows a spinner — flashing the\n // viewport to a full-screen loader on every refetch makes the page\n // feel broken, especially on the 30s grid polls. The black-screen\n // loader only appears on a TRUE cold start (no cached image yet).\n if (src) {\n return (\n <div className=\"relative w-full aspect-video bg-black/90 flex items-center justify-center\">\n <img src={src} alt=\"Camera snapshot\" className=\"w-full h-full object-contain\" />\n {!suppressPlayHover && (\n <button\n onClick={onPlay}\n className=\"absolute inset-0 flex items-center justify-center bg-black/30 opacity-0 hover:opacity-100 transition-opacity cursor-pointer\"\n >\n <div className=\"h-14 w-14 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center\">\n <PlayIcon className=\"h-7 w-7 text-white ml-0.5\" />\n </div>\n </button>\n )}\n {extraOverlay}\n </div>\n )\n }\n\n if (isLoading) {\n return (\n <div className=\"relative w-full aspect-video bg-black/90 flex items-center justify-center\">\n <div className=\"h-8 w-8 border-2 border-white/20 border-t-white/60 rounded-full animate-spin\" />\n </div>\n )\n }\n\n return (\n <div className=\"relative w-full aspect-video bg-black/90 flex items-center justify-center\">\n <div className=\"flex flex-col items-center gap-2 text-white/40\">\n <ImageOffIcon className=\"h-8 w-8\" />\n <span className=\"text-xs\">No snapshot available</span>\n <div className=\"flex items-center gap-2 mt-1\">\n {onRetry && (\n <button\n onClick={onRetry}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-white/20 px-3 py-1.5 text-xs font-medium text-white/60 hover:text-white hover:border-white/40 transition-colors\"\n >\n <RefreshIcon className=\"h-3 w-3\" />Retry\n </button>\n )}\n <button\n onClick={onPlay}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary/80 px-3 py-1.5 text-xs font-medium text-white hover:bg-primary transition-colors\"\n >\n <PlayIcon className=\"h-3 w-3\" />Play Live\n </button>\n </div>\n </div>\n </div>\n )\n}\n","/**\n * Player overlay registry — pluggable layers + toolbar buttons for\n * the device-detail live-frame `StreamPanel`.\n *\n * Why a registry: previously `StreamPanelContent` hardcoded each\n * overlay (PTZ, intercom toggle, zone editor) and threaded the\n * editing state by hand. Adding a new feature (audio waveform,\n * detection bbox tracker, recording controls, …) meant another\n * round of plumbing through the host file and StreamPanel's prop\n * surface. The registry lets a sibling component (Detection tab,\n * Live Stats tab, an addon-page extension) declare its own layer\n * imperatively via a hook, and the host renders whatever's\n * registered.\n *\n * Two registries live side-by-side:\n *\n * 1. **layers** — absolute-positioned React nodes drawn over the\n * video frame (zones polygon canvas, motion bbox overlay,\n * audio waveform). Rendered ordered by `order` (lower first\n * → bottom; higher → top); the last-registered layer wins\n * ties.\n *\n * 2. **toolbar buttons** — controls surfaced in the player's\n * always-visible toolbar cluster (next to Intercom + Play/Stop).\n * Each carries an icon, label, controlled `active` flag, and\n * a click handler. The host (StreamPanel) renders them\n * uniformly; tone variants stay simple (`'default' | 'primary'`).\n *\n * Lifecycle: hooks register their layer / button on mount and\n * unregister on unmount, so swapping tabs (e.g. leaving Detection)\n * automatically tears down the registration. Re-registering with\n * the same `id` replaces the prior entry — meaning a single hook\n * call can update its overlay/button props on every render without\n * leaking entries.\n *\n * Provider scope: typically wraps the whole device-detail subtree\n * so the StreamPanel + every tab share the same registry. One\n * provider per `deviceId`; switching device IDs unmounts the\n * provider naturally.\n */\nimport { useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react'\nimport { createSharedContext } from '../lib/shared-context'\n\n// ── Layer registry ────────────────────────────────────────────────────────────\n\nexport interface PlayerOverlayLayer {\n readonly id: string\n /** Lower = bottom. Built-in layers (PTZ overlay, detection overlay)\n * are drawn at order 0; addon-contributed layers should pick a\n * higher value (e.g. 100) to land on top. */\n readonly order: number\n readonly node: ReactNode\n}\n\n// ── Toolbar registry ─────────────────────────────────────────────────────────\n\nexport interface PlayerToolbarButton {\n readonly id: string\n /** Lower = leftmost in the toolbar cluster. */\n readonly order: number\n /** Icon node — typically a `<svg>` or lucide-react icon. The host\n * renders it inside a button shell; the icon component is\n * responsible for its own sizing (h-3 w-3 by convention). */\n readonly icon: ReactNode\n /** Visible label on wider breakpoints; collapses to icon-only on\n * narrow widths. */\n readonly label: string\n /** Title/tooltip for the rendered button. Defaults to `label`. */\n readonly title?: string\n /** Controlled active state — drives the highlight (primary tint). */\n readonly active: boolean\n /** Tone variant for the inactive state. `'primary'` reads as a\n * call-to-action (e.g. \"Snapshot\"); `'default'` is a neutral\n * toggle. */\n readonly tone?: 'default' | 'primary'\n /** Disable the button when the host is mid-transition. */\n readonly disabled?: boolean\n readonly onClick: () => void\n}\n\ninterface RegistryShape {\n readonly layers: ReadonlyMap<string, PlayerOverlayLayer>\n readonly buttons: ReadonlyMap<string, PlayerToolbarButton>\n}\n\ninterface RegistryActions {\n setLayer(layer: PlayerOverlayLayer): void\n removeLayer(id: string): void\n setButton(button: PlayerToolbarButton): void\n removeButton(id: string): void\n}\n\nconst PlayerOverlaysStateContext = createSharedContext<RegistryShape | null>(\n 'camstack:player-overlays-state',\n null,\n)\nconst PlayerOverlaysActionsContext = createSharedContext<RegistryActions | null>(\n 'camstack:player-overlays-actions',\n null,\n)\n\nexport interface PlayerOverlaysProviderProps {\n readonly children: ReactNode\n}\n\nexport function PlayerOverlaysProvider({ children }: PlayerOverlaysProviderProps) {\n const [layers, setLayers] = useState<ReadonlyMap<string, PlayerOverlayLayer>>(() => new Map())\n const [buttons, setButtons] = useState<ReadonlyMap<string, PlayerToolbarButton>>(() => new Map())\n\n const setLayer = useCallback((layer: PlayerOverlayLayer) => {\n setLayers((prev) => {\n const next = new Map(prev)\n next.set(layer.id, layer)\n return next\n })\n }, [])\n const removeLayer = useCallback((id: string) => {\n setLayers((prev) => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, [])\n const setButton = useCallback((button: PlayerToolbarButton) => {\n setButtons((prev) => {\n const next = new Map(prev)\n next.set(button.id, button)\n return next\n })\n }, [])\n const removeButton = useCallback((id: string) => {\n setButtons((prev) => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, [])\n\n const stateValue = useMemo<RegistryShape>(() => ({ layers, buttons }), [layers, buttons])\n const actionsValue = useMemo<RegistryActions>(\n () => ({ setLayer, removeLayer, setButton, removeButton }),\n [setLayer, removeLayer, setButton, removeButton],\n )\n\n return (\n <PlayerOverlaysStateContext.Provider value={stateValue}>\n <PlayerOverlaysActionsContext.Provider value={actionsValue}>\n {children}\n </PlayerOverlaysActionsContext.Provider>\n </PlayerOverlaysStateContext.Provider>\n )\n}\n\n// ── Read hooks ────────────────────────────────────────────────────────────────\n\n/** Snapshot of registered layers ordered by `order` (asc, ties resolved\n * by insertion order of the underlying Map). Returns `[]` outside a\n * provider. */\nexport function usePlayerOverlayLayers(): readonly PlayerOverlayLayer[] {\n const state = useContext(PlayerOverlaysStateContext)\n return useMemo(() => {\n if (!state) return []\n return [...state.layers.values()].sort((a, b) => a.order - b.order)\n }, [state])\n}\n\n/** Snapshot of registered toolbar buttons, ordered by `order` (asc). */\nexport function usePlayerToolbarButtons(): readonly PlayerToolbarButton[] {\n const state = useContext(PlayerOverlaysStateContext)\n return useMemo(() => {\n if (!state) return []\n return [...state.buttons.values()].sort((a, b) => a.order - b.order)\n }, [state])\n}\n\n// ── Registration hooks ───────────────────────────────────────────────────────\n\n/**\n * Register an overlay layer for the lifetime of the calling component.\n * Re-registers on every render with the latest spec; auto-unregisters\n * on unmount. Pass `null` to skip registration when the layer is\n * conditionally enabled (the hook still runs every render — keeps\n * react-hook order stable across spec === null toggles).\n *\n * Callers that build the spec inline should memoise it (`useMemo`)\n * to avoid re-registering on every parent render — context-write\n * effects depend on referential equality of the spec object.\n */\nexport function usePlayerOverlayLayer(spec: PlayerOverlayLayer | null): void {\n const actions = useContext(PlayerOverlaysActionsContext)\n useEffect(() => {\n if (!actions || !spec) return undefined\n actions.setLayer(spec)\n return () => actions.removeLayer(spec.id)\n }, [actions, spec])\n}\n\n/** Same shape as `usePlayerOverlayLayer`, scoped to toolbar buttons. */\nexport function usePlayerToolbarButton(spec: PlayerToolbarButton | null): void {\n const actions = useContext(PlayerOverlaysActionsContext)\n useEffect(() => {\n if (!actions || !spec) return undefined\n actions.setButton(spec)\n return () => actions.removeButton(spec.id)\n }, [actions, spec])\n}\n","import { useRef, useEffect, useCallback } from 'react'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioWaveformProps {\n /** Raw audio samples (mono Float32Array, -1..1 range) */\n readonly samples: Float32Array | null\n /** Sample rate in Hz (for time axis labels) */\n readonly sampleRate?: number\n /** Height in pixels */\n readonly height?: number\n /** CSS class for the container */\n readonly className?: string\n /** Waveform color (CSS color string) */\n readonly color?: string\n /** Background color */\n readonly bgColor?: string\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Canvas-based audio waveform visualization.\n * Renders a waveform from Float32Array audio samples.\n * Downsamples to pixel resolution for performance.\n */\nexport function AudioWaveform({\n samples,\n sampleRate = 16000,\n height = 96,\n className = '',\n color = '#3b82f6',\n bgColor = 'transparent',\n}: AudioWaveformProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n const draw = useCallback(() => {\n const canvas = canvasRef.current\n const container = containerRef.current\n if (!canvas || !container || !samples || samples.length === 0) return\n\n const width = container.clientWidth\n if (width === 0) return\n\n const dpr = window.devicePixelRatio || 1\n canvas.width = width * dpr\n canvas.height = height * dpr\n canvas.style.width = `${width}px`\n canvas.style.height = `${height}px`\n\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n\n ctx.scale(dpr, dpr)\n\n // Background\n if (bgColor !== 'transparent') {\n ctx.fillStyle = bgColor\n ctx.fillRect(0, 0, width, height)\n } else {\n ctx.clearRect(0, 0, width, height)\n }\n\n // Downsample: compute min/max per pixel column\n const samplesPerPixel = samples.length / width\n const midY = height / 2\n\n ctx.fillStyle = color\n ctx.globalAlpha = 0.7\n\n for (let px = 0; px < width; px++) {\n const startIdx = Math.floor(px * samplesPerPixel)\n const endIdx = Math.min(Math.floor((px + 1) * samplesPerPixel), samples.length)\n\n let min = 0\n let max = 0\n for (let i = startIdx; i < endIdx; i++) {\n const v = samples[i]!\n if (v < min) min = v\n if (v > max) max = v\n }\n\n const topY = midY - max * midY\n const bottomY = midY - min * midY\n const barHeight = Math.max(1, bottomY - topY)\n\n ctx.fillRect(px, topY, 1, barHeight)\n }\n\n ctx.globalAlpha = 1.0\n\n // Center line\n ctx.strokeStyle = color\n ctx.globalAlpha = 0.2\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(0, midY)\n ctx.lineTo(width, midY)\n ctx.stroke()\n ctx.globalAlpha = 1.0\n }, [samples, height, color, bgColor])\n\n // Draw on mount and when samples change\n useEffect(() => {\n draw()\n }, [draw])\n\n // Redraw on resize\n useEffect(() => {\n const observer = new ResizeObserver(() => draw())\n const el = containerRef.current\n if (el) observer.observe(el)\n return () => observer.disconnect()\n }, [draw])\n\n const durationMs = samples && sampleRate ? Math.round((samples.length / sampleRate) * 1000) : 0\n const durationSec = (durationMs / 1000).toFixed(1)\n\n return (\n <div ref={containerRef} className={`relative ${className}`}>\n <canvas ref={canvasRef} className=\"w-full rounded-md\" />\n {samples && samples.length > 0 && (\n <div className=\"absolute bottom-1 right-2 text-[10px] text-foreground-subtle/60 font-mono\">\n {durationSec}s · {sampleRate / 1000}kHz · {samples.length.toLocaleString()} samples\n </div>\n )}\n </div>\n )\n}\n","import { useRef, useEffect, useCallback, useState } from 'react'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioLevelSample {\n readonly dbfs: number\n readonly timestamp: number\n}\n\nexport interface AudioLevelWaveformProps {\n /** Current dBFS level — push a new value to append to the internal ring buffer. */\n readonly currentDbfs: number | null\n /** How many seconds of history to display (default 30) */\n readonly durationSec?: number\n /** Max samples to keep in memory (default 120 ≈ 60s at 2 samples/s) */\n readonly maxSamples?: number\n /** Height in pixels (default 64) */\n readonly height?: number\n /** CSS class for the container */\n readonly className?: string\n /** Bar color (CSS) */\n readonly color?: string\n /** Clipping color when dBFS > threshold (default red) */\n readonly clipColor?: string\n /** dBFS threshold for clipping color (default -6) */\n readonly clipThreshold?: number\n /** Min dBFS to display (default -96) */\n readonly minDbfs?: number\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Canvas-based live audio level waveform with internal state.\n *\n * Receives `currentDbfs` — each time it changes, a new sample is appended\n * to an internal ring buffer and the canvas is redrawn. The component\n * manages its own history, so callers just push the latest dBFS value.\n *\n * Designed to be fed from the `pipeline.audio-inference-result` event\n * (each chunk, ~0.5s, produces one sample via `frame.level.dbfs`).\n */\nexport function AudioLevelWaveform({\n currentDbfs,\n durationSec = 30,\n maxSamples = 120,\n height = 64,\n className = '',\n color = '#10b981',\n clipColor = '#ef4444',\n clipThreshold = -6,\n minDbfs = -96,\n}: AudioLevelWaveformProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const [samples, setSamples] = useState<readonly AudioLevelSample[]>([])\n\n // Append new sample when currentDbfs changes (skip null)\n useEffect(() => {\n if (currentDbfs === null) return\n setSamples(prev => {\n const next = [...prev, { dbfs: currentDbfs, timestamp: Date.now() }]\n return next.length > maxSamples ? next.slice(-maxSamples) : next\n })\n }, [currentDbfs, maxSamples])\n\n const draw = useCallback(() => {\n const canvas = canvasRef.current\n const container = containerRef.current\n if (!canvas || !container) return\n\n const width = container.clientWidth\n if (width === 0) return\n\n const dpr = window.devicePixelRatio || 1\n canvas.width = width * dpr\n canvas.height = height * dpr\n canvas.style.width = `${width}px`\n canvas.style.height = `${height}px`\n\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n\n ctx.scale(dpr, dpr)\n ctx.clearRect(0, 0, width, height)\n\n if (samples.length === 0) return\n\n const now = samples[samples.length - 1]!.timestamp\n const windowMs = durationSec * 1000\n const startTime = now - windowMs\n\n // Filter to visible window\n const visible = samples.filter(s => s.timestamp >= startTime)\n if (visible.length === 0) return\n\n // Each sample is one bar; bar width based on time density\n const barWidth = Math.max(1, Math.floor(width / (durationSec * 2)))\n const dbRange = Math.abs(minDbfs)\n\n for (const sample of visible) {\n const timeOffset = sample.timestamp - startTime\n const x = Math.floor((timeOffset / windowMs) * width)\n\n const clamped = Math.max(minDbfs, Math.min(0, sample.dbfs))\n const normalized = (clamped - minDbfs) / dbRange\n const barHeight = Math.max(1, normalized * height)\n\n const isClipping = sample.dbfs >= clipThreshold\n ctx.fillStyle = isClipping ? clipColor : color\n ctx.globalAlpha = 0.8\n ctx.fillRect(x, height - barHeight, barWidth, barHeight)\n }\n\n ctx.globalAlpha = 1.0\n\n // Clip threshold line\n const thresholdY = height - ((clipThreshold - minDbfs) / dbRange) * height\n ctx.strokeStyle = clipColor\n ctx.globalAlpha = 0.25\n ctx.lineWidth = 1\n ctx.setLineDash([4, 4])\n ctx.beginPath()\n ctx.moveTo(0, thresholdY)\n ctx.lineTo(width, thresholdY)\n ctx.stroke()\n ctx.setLineDash([])\n ctx.globalAlpha = 1.0\n }, [samples, durationSec, height, color, clipColor, clipThreshold, minDbfs])\n\n useEffect(() => { draw() }, [draw])\n\n useEffect(() => {\n const observer = new ResizeObserver(() => draw())\n const el = containerRef.current\n if (el) observer.observe(el)\n return () => observer.disconnect()\n }, [draw])\n\n const latestDbfs = samples.length > 0 ? samples[samples.length - 1]!.dbfs : null\n\n return (\n <div ref={containerRef} className={`relative ${className}`}>\n <canvas ref={canvasRef} className=\"w-full rounded-md\" />\n <div className=\"absolute top-1 left-2 text-[9px] text-foreground-subtle/50 font-mono\">\n {durationSec}s\n </div>\n {latestDbfs !== null && (\n <div className=\"absolute bottom-1 right-2 text-[9px] text-foreground-subtle/50 font-mono\">\n {latestDbfs.toFixed(1)} dBFS · {samples.length} samples\n </div>\n )}\n </div>\n )\n}\n","// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AudioClassification {\n readonly className: string\n readonly score: number\n}\n\nexport interface AudioClassificationListProps {\n /** Sorted classifications (highest score first) */\n readonly classifications: readonly AudioClassification[]\n /** Processing state indicator */\n readonly processing?: boolean\n /** Inference time in ms */\n readonly inferenceMs?: number\n /** Max items to show (default: 10) */\n readonly maxItems?: number\n /** Optional className */\n readonly className?: string\n}\n\n// ---------------------------------------------------------------------------\n// Score bar colors\n// ---------------------------------------------------------------------------\n\nfunction scoreColor(score: number): string {\n if (score >= 0.8) return 'bg-emerald-500'\n if (score >= 0.5) return 'bg-amber-500'\n if (score >= 0.3) return 'bg-orange-500'\n return 'bg-zinc-500'\n}\n\nfunction scoreTextColor(score: number): string {\n if (score >= 0.8) return 'text-emerald-400'\n if (score >= 0.5) return 'text-amber-400'\n if (score >= 0.3) return 'text-orange-400'\n return 'text-zinc-400'\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Displays audio classification results as a ranked list with score bars.\n */\nexport function AudioClassificationList({\n classifications,\n processing = false,\n inferenceMs,\n maxItems = 10,\n className = '',\n}: AudioClassificationListProps) {\n const items = classifications.slice(0, maxItems)\n const maxScore = items.length > 0 ? items[0]!.score : 1\n\n if (processing) {\n return (\n <div className={`rounded-xl border border-border bg-surface p-4 text-center ${className}`}>\n <div className=\"text-sm text-foreground-subtle animate-pulse\">Classifying audio...</div>\n </div>\n )\n }\n\n if (items.length === 0) {\n return (\n <div className={`rounded-xl border border-border bg-surface p-4 text-center ${className}`}>\n <div className=\"text-xs text-foreground-subtle\">No classifications yet</div>\n </div>\n )\n }\n\n return (\n <div className={`rounded-xl border border-border bg-surface overflow-hidden ${className}`}>\n <div className=\"px-3 py-2 border-b border-border flex items-center justify-between\">\n <h3 className=\"text-xs font-medium text-foreground\">\n Audio Classifications\n </h3>\n <div className=\"flex items-center gap-3 text-[10px] text-foreground-subtle\">\n {items.length < classifications.length && (\n <span>showing {items.length} of {classifications.length}</span>\n )}\n {inferenceMs !== undefined && (\n <span className=\"font-mono\">{inferenceMs.toFixed(1)}ms</span>\n )}\n </div>\n </div>\n <div className=\"divide-y divide-border/50\">\n {items.map((item, i) => {\n const barWidth = maxScore > 0 ? (item.score / maxScore) * 100 : 0\n return (\n <div key={`${item.className}-${i}`} className=\"px-3 py-1.5 flex items-center gap-3 hover:bg-surface-hover/30\">\n <span className=\"text-[10px] text-foreground-subtle w-5 text-right font-mono\">\n {i + 1}\n </span>\n <span className=\"text-xs font-medium text-foreground min-w-[120px]\">\n {item.className}\n </span>\n <div className=\"flex-1 h-2 rounded-full bg-zinc-800 overflow-hidden\">\n <div\n className={`h-full rounded-full transition-all duration-300 ${scoreColor(item.score)}`}\n style={{ width: `${barWidth}%` }}\n />\n </div>\n <span className={`text-xs font-mono font-semibold w-14 text-right ${scoreTextColor(item.score)}`}>\n {(item.score * 100).toFixed(1)}%\n </span>\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\n\nexport interface ResponseLogProps {\n readonly data: unknown\n readonly label?: string\n readonly className?: string\n}\n\n/**\n * Expandable log box showing the raw JSON response from a pipeline run.\n */\nexport function ResponseLog({ data, label = 'Response', className = '' }: ResponseLogProps) {\n const [expanded, setExpanded] = useState(false)\n\n if (!data) return null\n\n const json = JSON.stringify(data, null, 2)\n\n return (\n <div className={`rounded-xl border border-border bg-surface overflow-hidden ${className}`}>\n <div\n className=\"px-3 py-2 border-b border-border flex items-center justify-between cursor-pointer select-none hover:bg-surface-hover/30\"\n onClick={() => setExpanded(e => !e)}\n >\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[10px] text-foreground-subtle\">{expanded ? '▼' : '▶'}</span>\n <h3 className=\"text-xs font-medium text-foreground\">{label}</h3>\n </div>\n <span className=\"text-[10px] text-foreground-subtle font-mono\">\n {json.length > 1000 ? `${(json.length / 1024).toFixed(1)} KB` : `${json.length} bytes`}\n </span>\n </div>\n {expanded && (\n <div className=\"max-h-80 overflow-y-auto overflow-x-auto\">\n <pre className=\"p-3 text-[10px] leading-4 font-mono text-foreground-subtle whitespace-pre\">\n {json}\n </pre>\n </div>\n )}\n </div>\n )\n}\n","/**\n * PhaseIcon — renders the correct lucide icon for a CameraPhase.\n *\n * Wraps the PHASE_CONFIG icon name → component resolution so consumers\n * don't need to maintain their own icon switch/map.\n */\nimport { Activity, Eye, AlertTriangle, PauseCircle, PowerOff, type LucideProps } from 'lucide-react'\nimport { getPhaseVisual } from '../lib/phase-config'\n\nconst ICON_MAP = {\n Activity,\n Eye,\n AlertTriangle,\n PauseCircle,\n PowerOff,\n} as const\n\nexport interface PhaseIconProps extends LucideProps {\n readonly phase: string\n}\n\nexport function PhaseIcon({ phase, ...props }: PhaseIconProps) {\n const cfg = getPhaseVisual(phase)\n const Icon = ICON_MAP[cfg.icon]\n return <Icon {...props} />\n}\n","/**\n * LogStream — universal log viewer for ui-library.\n *\n * Hierarchical scope: agentId → addonId → deviceId.\n * Props lock the top levels; child selectors appear for unlocked levels.\n * Features: level filter, expandable metadata, copy all, load-more,\n * capped live buffer (ring), auto-scroll toggle.\n *\n * Used inline (tabs, cards) and as a floating panel via FloatingLogStream.\n */\nimport { useEffect, useRef, useState, useCallback, useMemo } from 'react'\nimport {\n X, Loader2, AlertTriangle, Info, AlertCircle, Bug,\n ArrowUpToLine, Check, Copy, Trash2, ChevronDown, ChevronRight,\n} from 'lucide-react'\nimport { trpc } from '../trpc-react'\nimport { cn } from '../lib/cn'\nimport { useLiveBuffer, type LiveBuffer } from '../hooks/use-live-buffer'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface LogEntry {\n readonly timestamp: string\n readonly level: string\n readonly message: string\n readonly scope?: string\n readonly tags?: Record<string, string | undefined>\n readonly meta?: Record<string, unknown>\n}\n\n/** Format a `meta` value for inline display. Strings pass through;\n * everything else gets JSON.stringified so structured payloads stay\n * readable instead of rendering as `[object Object]`. */\nfunction formatMetaValue(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n try { return JSON.stringify(value) } catch { return String(value) }\n}\n\nexport interface LogStreamProps {\n // ── Scope (hierarchical, all optional) ────────────────────────────\n /** Lock to a specific agent. When set, the agent selector is hidden. */\n readonly agentId?: string\n /** Lock to a specific addon. When set, the addon selector is hidden. */\n readonly addonId?: string\n /** Lock to a specific device. When set, the device selector is hidden. */\n readonly deviceId?: number\n /**\n * Lock to a specific integration. Filter is ALWAYS applied when\n * provided — current providers don't yet tag loggers with\n * `integrationId`, so the result will be empty until they do, but\n * the filter lets us light up integration-scoped logs incrementally\n * without changing the call sites here.\n */\n readonly integrationId?: string\n /**\n * Correlation id for short-lived operations that have no `deviceId`\n * yet (e.g. a creation-field probe). The matching surface (the\n * Add-Device modal) generates the id once per dialog open and the\n * provider plumbs it into its own scoped logger so the user sees\n * live socket / handshake lines streaming during the test.\n */\n readonly requestId?: string\n\n // ── Display ───────────────────────────────────────────────────────\n /** Initial log level filter. */\n readonly level?: 'debug' | 'info' | 'warn' | 'error'\n /** Max height CSS class (default: 'max-h-96'). */\n readonly maxHeight?: string\n /** Show the scope column. */\n readonly showScope?: boolean\n /** Show the filter bar with selectors. Set false for compact inline use. */\n readonly showFilters?: boolean\n /** Initial number of historical entries to fetch (default: 100). */\n readonly limit?: number\n /**\n * Optional controlled live buffer. When provided, the stream reads\n * + appends to this external store rather than its own `useState`,\n * so visible logs survive an unmount/remount of the component\n * (used by `DeviceActivityPanel` to preserve content across tab\n * switches without keeping subscriptions open in inactive tabs).\n */\n readonly liveBuffer?: LiveBuffer<LogEntry>\n /** Close button handler — when provided, renders a close button. */\n readonly onClose?: () => void\n readonly className?: string\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LEVEL_STYLES: Record<string, { icon: typeof Info; color: string }> = {\n error: { icon: AlertCircle, color: 'text-red-400' },\n warn: { icon: AlertTriangle, color: 'text-amber-400' },\n info: { icon: Info, color: 'text-blue-400' },\n debug: { icon: Bug, color: 'text-gray-500' },\n}\n\nconst LEVEL_SEVERITY: Record<string, number> = { debug: 0, info: 1, warn: 2, error: 3 }\nconst LEVEL_OPTIONS = ['all', 'debug', 'info', 'warn', 'error'] as const\n\n/** Max live entries kept in the ring buffer. */\nconst MAX_LIVE_ENTRIES = 500\n\nfunction passesLevel(logLevel: string, filterLevel: string | undefined): boolean {\n if (!filterLevel) return true\n return (LEVEL_SEVERITY[logLevel] ?? 0) >= (LEVEL_SEVERITY[filterLevel] ?? 0)\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function LogStream({\n agentId: propsAgentId,\n addonId: propsAddonId,\n deviceId: propsDeviceId,\n integrationId: propsIntegrationId,\n requestId: propsRequestId,\n level: initialLevel,\n maxHeight = 'max-h-96',\n showScope = false,\n showFilters = true,\n limit = 100,\n liveBuffer: externalBuffer,\n onClose,\n className,\n}: LogStreamProps) {\n // ── Local filter state (for unlocked scope levels) ────────────────\n const [localAddonId, setLocalAddonId] = useState<string>('')\n const [localDeviceId, setLocalDeviceId] = useState<string>('')\n const [levelFilter, setLevelFilter] = useState<string | undefined>(initialLevel)\n\n // Effective scope: props override local selectors\n const agentId = propsAgentId\n const addonId = propsAddonId ?? (localAddonId || undefined)\n const deviceId = propsDeviceId ?? (localDeviceId ? Number(localDeviceId) : undefined)\n const integrationId = propsIntegrationId\n const requestId = propsRequestId\n\n // Tags for the backend query.\n //\n // `deviceId` MUST stay a number — log entries carry it as a number\n // (`tags: { deviceId: this.id }` on every device-scoped emitter) and\n // the bus's `matchesLogTags` does a strict `!==` comparison, so\n // stringifying here would silently filter every entry out and the\n // Logs tab would render empty.\n const tags = useMemo(() => {\n const t: Record<string, string | number> = {}\n if (agentId) t.agentId = agentId\n if (addonId) t.addonId = addonId\n if (deviceId !== undefined && Number.isFinite(deviceId)) t.deviceId = deviceId\n if (integrationId) t.integrationId = integrationId\n if (requestId) t.requestId = requestId\n return Object.keys(t).length > 0 ? t : undefined\n }, [agentId, addonId, deviceId, integrationId, requestId])\n\n // ── Data ──────────────────────────────────────────────────────────\n const fallbackBuffer = useLiveBuffer<LogEntry>(MAX_LIVE_ENTRIES)\n const buffer = externalBuffer ?? fallbackBuffer\n const liveLogs = buffer.entries\n const [clearedAt, setClearedAt] = useState(0)\n // Auto-scroll defaults OFF: most operators are reading scroll-back\n // history when the panel is open, and getting pulled to the top\n // every tick is disruptive. They opt in via the toolbar button.\n const [autoScroll, setAutoScroll] = useState(false)\n const [copied, setCopied] = useState(false)\n // Tracks which rows are expanded. Keyed by a stable per-entry id\n // (timestamp + message + scope), NOT by list index — when a new log\n // streams in the merged list shifts down by one and an index-keyed\n // Set would silently switch the open row to whatever entry now sits\n // at the previously-expanded position. Stable keys keep the user on\n // the row they actually opened across arbitrary live churn.\n const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set())\n const [searchText, setSearchText] = useState('')\n const scrollRef = useRef<HTMLDivElement>(null)\n\n // Reset live logs + expanded when scope changes\n const scopeKey = `${agentId ?? ''}:${addonId ?? ''}:${String(deviceId ?? '')}:${integrationId ?? ''}:${requestId ?? ''}`\n const prevScopeRef = useRef(scopeKey)\n useEffect(() => {\n if (prevScopeRef.current !== scopeKey) {\n prevScopeRef.current = scopeKey\n buffer.reset()\n setClearedAt(0)\n setExpandedRows(new Set<string>())\n }\n }, [scopeKey, buffer])\n\n // Historical query\n const { data: initialLogs, isLoading } = trpc.logs.query.useQuery(\n { ...(tags ? { tags } : {}), limit },\n { staleTime: 30_000 },\n )\n\n // Live subscription\n trpc.logs.subscribe.useSubscription(\n { ...(tags ? { tags } : {}) },\n {\n onData: (entry) => {\n buffer.append(entry as LogEntry)\n },\n },\n )\n\n // Auto-scroll with anchor preservation. New entries are prepended\n // to the merged list (initial fetch + live entries reversed); when\n // the user is at the top we follow them, otherwise compensate by\n // scrolling down so the visually anchored row doesn't shift.\n const prevLiveCountRef = useRef(liveLogs.length)\n useEffect(() => {\n const el = scrollRef.current\n if (!el) {\n prevLiveCountRef.current = liveLogs.length\n return\n }\n const prevCount = prevLiveCountRef.current\n prevLiveCountRef.current = liveLogs.length\n if (liveLogs.length <= prevCount) return\n if (autoScroll && el.scrollTop <= 8) {\n el.scrollTo({ top: 0 })\n } else if (!autoScroll && el.scrollTop > 0) {\n const firstRow = el.querySelector('tbody tr')\n const rowHeight = firstRow instanceof HTMLElement ? firstRow.offsetHeight : 24\n el.scrollTop += rowHeight * (liveLogs.length - prevCount)\n }\n }, [liveLogs.length, autoScroll])\n\n // ── Merged + filtered log list ────────────────────────────────────\n const allLogs = useMemo(() => {\n const initial: LogEntry[] = (initialLogs ?? []).map((log) => ({\n timestamp: log.timestamp,\n level: log.level,\n message: log.message,\n scope: log.scope,\n tags: log.tags as Record<string, string | undefined> | undefined,\n meta: log.meta as Record<string, unknown> | undefined,\n }))\n\n // Dedupe at merge time — the historical query and the live\n // subscription overlap right after mount (the live entry that\n // triggered the next initialLogs refresh shows up in BOTH lists),\n // and the row-key derived below would collide. Live entries take\n // precedence (placed first so the iteration below records the\n // live tags/meta if both are present).\n const seen = new Set<string>()\n const merged: LogEntry[] = []\n for (const log of [...liveLogs].reverse()) {\n const key = `${log.timestamp}|${log.level}|${log.scope ?? ''}|${log.message}`\n if (seen.has(key)) continue\n seen.add(key)\n merged.push(log)\n }\n for (const log of initial) {\n const key = `${log.timestamp}|${log.level}|${log.scope ?? ''}|${log.message}`\n if (seen.has(key)) continue\n seen.add(key)\n merged.push(log)\n }\n\n const filtered = clearedAt > 0\n ? merged.filter((log) => new Date(log.timestamp).getTime() > clearedAt)\n : merged\n\n const levelFiltered = filtered.filter((log) => passesLevel(log.level, levelFilter))\n\n const needle = searchText.trim().toLowerCase()\n if (!needle) return levelFiltered\n // Substring match against everything an operator might be hunting\n // for in a log line: message, scope, every tag value, every meta\n // value (stringified). Case-insensitive.\n return levelFiltered.filter((log) => {\n if (log.message.toLowerCase().includes(needle)) return true\n if (log.scope && log.scope.toLowerCase().includes(needle)) return true\n if (log.tags) {\n for (const v of Object.values(log.tags)) {\n if (v !== undefined && String(v).toLowerCase().includes(needle)) return true\n }\n }\n if (log.meta) {\n for (const v of Object.values(log.meta)) {\n if (v === undefined || v === null) continue\n if (formatMetaValue(v).toLowerCase().includes(needle)) return true\n }\n }\n return false\n })\n }, [initialLogs, liveLogs, levelFilter, clearedAt, searchText])\n\n // ── Handlers ──────────────────────────────────────────────────────\n const handleCopyAll = useCallback(() => {\n const lines = allLogs.map((log) => {\n const time = new Date(log.timestamp).toLocaleTimeString()\n const tagsStr = log.tags\n ? ' ' + Object.entries(log.tags).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join(' ')\n : ''\n return `${time} [${log.level.toUpperCase()}]${log.scope ? ` [${log.scope}]` : ''}${tagsStr} ${log.message}`\n })\n void navigator.clipboard.writeText(lines.join('\\n')).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), 1500)\n })\n }, [allLogs])\n\n // Server-side mutation: drops matching entries from the log ring\n // buffer so closing+reopening the panel doesn't re-fetch the rows\n // we just cleared. The mutation is best-effort — if the user is a\n // viewer (no admin role) the server rejects and we still wipe the\n // local buffer, matching the prior behaviour.\n const clearMutation = trpc.logs.clear.useMutation()\n const handleClear = useCallback(() => {\n setClearedAt(Date.now())\n buffer.reset()\n clearMutation.mutate({ ...(tags ? { tags } : {}) })\n }, [buffer, clearMutation, tags])\n\n const toggleRow = useCallback((rowKey: string) => {\n setExpandedRows((prev) => {\n const next = new Set(prev)\n if (next.has(rowKey)) next.delete(rowKey)\n else next.add(rowKey)\n return next\n })\n }, [])\n\n // Tracks which row was just copied so the small per-row Copy\n // button can flash a Check for ~1s without dragging \"Copied!\"\n // text into the toolbar's `copied` state (that one is reserved\n // for Copy-All so the two indicators don't compete).\n const [copiedRowKey, setCopiedRowKey] = useState<string | null>(null)\n const copyOne = useCallback((log: LogEntry, key: string) => {\n const time = new Date(log.timestamp).toISOString()\n const tagsStr = log.tags\n ? ' ' + Object.entries(log.tags).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join(' ')\n : ''\n const metaStr = log.meta && Object.keys(log.meta).length > 0\n ? ` meta=${JSON.stringify(log.meta)}`\n : ''\n const text = `${time} [${log.level.toUpperCase()}]${log.scope ? ` [${log.scope}]` : ''}${tagsStr} ${log.message}${metaStr}`\n void navigator.clipboard.writeText(text).then(() => {\n setCopiedRowKey(key)\n setTimeout(() => setCopiedRowKey((prev) => (prev === key ? null : prev)), 1200)\n })\n }, [])\n\n // Stable per-entry identity used for both the React row key AND the\n // expanded-rows lookup. `timestamp + level + message + scope` is unique\n // enough in practice — the only way two entries collide is if the\n // SAME message fires from the SAME scope in the SAME millisecond,\n // which is harmless (both rows would expand together).\n const rowKey = useCallback((log: LogEntry): string =>\n `${log.timestamp}|${log.level}|${log.scope ?? ''}|${log.message}`,\n [])\n\n // ── Render ────────────────────────────────────────────────────────\n return (\n <div className={cn('h-full min-h-0 flex flex-col', className)} onClick={(e) => e.stopPropagation()}>\n {/* Toolbar */}\n <div className=\"flex items-center justify-between px-3 py-1.5 bg-surface-hover/30 gap-2 shrink-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] uppercase tracking-wide text-foreground-subtle font-medium\">Logs</span>\n\n {/* Scope badges */}\n {agentId && <ScopeBadge label=\"agent\" value={agentId} />}\n {addonId && <ScopeBadge label=\"addon\" value={addonId} />}\n {deviceId !== undefined && <ScopeBadge label=\"device\" value={`#${deviceId}`} />}\n\n {/* Level filter */}\n <div className=\"flex rounded border border-border overflow-hidden text-[9px]\">\n {LEVEL_OPTIONS.map((l) => (\n <button\n key={l}\n type=\"button\"\n onClick={() => setLevelFilter(l === 'all' ? undefined : l)}\n className={cn(\n 'px-1.5 py-0.5 capitalize transition-colors',\n (l === 'all' && !levelFilter) || levelFilter === l\n ? 'bg-primary/10 text-primary'\n : 'text-foreground-subtle hover:bg-surface-hover',\n l !== 'all' && 'border-l border-border',\n )}\n >\n {l}{l !== 'all' ? '+' : ''}\n </button>\n ))}\n </div>\n\n {/* Action buttons */}\n <ToolbarButton\n icon={ArrowUpToLine}\n label={autoScroll ? 'Auto' : 'Paused'}\n active={!autoScroll}\n onClick={() => {\n setAutoScroll((a) => !a)\n if (!autoScroll && scrollRef.current) scrollRef.current.scrollTo({ top: 0, behavior: 'smooth' })\n }}\n />\n <ToolbarButton icon={Copy} label={copied ? 'Copied!' : 'Copy'} onClick={handleCopyAll} disabled={allLogs.length === 0} />\n <ToolbarButton icon={Trash2} label=\"Clear\" onClick={handleClear} />\n\n {/* Free-text search — substring match across message, scope, tags, meta. */}\n <div className=\"relative\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search…\"\n className=\"w-32 pl-1.5 pr-5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50\"\n />\n {searchText && (\n <button\n type=\"button\"\n onClick={() => setSearchText('')}\n className=\"absolute right-1 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground\"\n title=\"Clear search\"\n >\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </div>\n\n {liveLogs.length > 0 && (\n <span className=\"text-[9px] text-emerald-400 font-medium\">+{liveLogs.length} live</span>\n )}\n </div>\n\n {onClose && (\n <button type=\"button\" onClick={onClose} className=\"text-foreground-subtle hover:text-foreground\">\n <X className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n\n {/* Inline scope selectors (only for unlocked levels) */}\n {showFilters && (!propsAddonId || !propsDeviceId) && (\n <div className=\"flex items-center gap-2 px-3 py-1 border-b border-border/50 bg-surface/50 text-[10px]\">\n {!propsAddonId && (\n <label className=\"flex items-center gap-1\">\n <span className=\"text-foreground-subtle\">Addon:</span>\n <input\n type=\"text\"\n value={localAddonId}\n onChange={(e) => setLocalAddonId(e.target.value)}\n placeholder=\"all\"\n className=\"w-28 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50\"\n />\n </label>\n )}\n {!propsDeviceId && (\n <label className=\"flex items-center gap-1\">\n <span className=\"text-foreground-subtle\">Device:</span>\n <input\n type=\"text\"\n inputMode=\"numeric\"\n value={localDeviceId}\n onChange={(e) => setLocalDeviceId(e.target.value)}\n placeholder=\"all\"\n className=\"w-16 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50\"\n />\n </label>\n )}\n </div>\n )}\n\n {/* Log content — flex-1 fills the panel; max-h-* applied on the\n panel root drives the actual height bound. */}\n <div ref={scrollRef} className={cn('flex-1 min-h-0 overflow-auto font-mono text-[10px]', maxHeight)}>\n {isLoading && (\n <div className=\"flex items-center justify-center gap-2 py-6 text-foreground-subtle\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n Loading logs...\n </div>\n )}\n {!isLoading && allLogs.length === 0 && (\n <div className=\"py-4 text-center text-foreground-subtle\">No logs found</div>\n )}\n {allLogs.length > 0 && (\n <table className=\"w-full\">\n <tbody>\n {allLogs.map((log) => {\n const style = LEVEL_STYLES[log.level] ?? LEVEL_STYLES['info']!\n const Icon = style.icon\n const key = rowKey(log)\n const expanded = expandedRows.has(key)\n const hasTags = log.tags && Object.keys(log.tags).length > 0\n const hasMeta = log.meta && Object.keys(log.meta).length > 0\n const hasContext = hasTags || hasMeta\n\n return (\n <tr\n key={key}\n className={cn(\n 'hover:bg-surface-hover/30 border-b border-border/30',\n hasContext && 'cursor-pointer',\n )}\n onClick={hasContext ? () => toggleRow(key) : undefined}\n >\n <td className=\"px-2 py-1 text-foreground-subtle whitespace-nowrap align-top w-[70px]\">\n {new Date(log.timestamp).toLocaleTimeString()}\n </td>\n <td className={cn('px-1 py-1 align-top w-5', style.color)}>\n <Icon className=\"h-3 w-3\" />\n </td>\n {showScope && (\n <td className=\"px-2 py-1 text-foreground-subtle align-top truncate max-w-[120px]\" title={log.scope}>\n {log.scope?.replace(/^addon:/, '') ?? ''}\n </td>\n )}\n <td className=\"px-2 py-1 text-foreground break-all\">\n <div className=\"flex items-start gap-1\">\n {hasContext && (\n expanded\n ? <ChevronDown className=\"h-3 w-3 text-foreground-subtle shrink-0 mt-0.5\" />\n : <ChevronRight className=\"h-3 w-3 text-foreground-subtle shrink-0 mt-0.5\" />\n )}\n <div className=\"flex-1 min-w-0\">\n {log.message}\n {expanded && hasContext && (\n <div className=\"mt-1 text-[9px] text-foreground-subtle bg-surface rounded px-2 py-1 space-y-0.5\">\n {hasMeta && Object.entries(log.meta!).filter(([, v]) => v !== undefined && v !== '').map(([k, v]) => (\n <div key={`m-${k}`}>\n <span className=\"text-amber-400/80 font-medium\">{k}</span>\n <span className=\"text-foreground-subtle\">: </span>\n <span className=\"text-foreground break-all\">{formatMetaValue(v)}</span>\n </div>\n ))}\n {hasTags && Object.entries(log.tags!).filter(([, v]) => v !== undefined).map(([k, v]) => (\n <div key={`t-${k}`}>\n <span className=\"text-primary/70 font-medium\">{k}</span>\n <span className=\"text-foreground-subtle\">: </span>\n <span className=\"text-foreground\">{v}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </td>\n <td className=\"px-1 py-1 align-top w-5\">\n <RowCopyButton\n copied={copiedRowKey === key}\n onCopy={() => copyOne(log, key)}\n />\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n )}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Floating variant\n// ---------------------------------------------------------------------------\n\nexport interface FloatingLogStreamProps extends LogStreamProps {\n /** Position: 'bottom' anchors to parent bottom, 'overlay' is absolute positioned. */\n readonly position?: 'bottom' | 'overlay'\n}\n\nexport function FloatingLogStream({ position = 'bottom', className, ...props }: FloatingLogStreamProps) {\n const posClass = position === 'bottom'\n ? 'absolute bottom-0 left-0 right-0 z-10 border-t border-border bg-surface/95 backdrop-blur-sm'\n : 'absolute inset-x-2 bottom-2 z-10 rounded-lg border border-border bg-surface/95 backdrop-blur-sm shadow-xl'\n\n return (\n <div className={cn(posClass, className)}>\n <LogStream maxHeight=\"max-h-48\" {...props} />\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction ScopeBadge({ label, value }: { readonly label: string; readonly value: string }) {\n return (\n <span className=\"text-[9px] px-1.5 py-0.5 rounded-full bg-primary/10 text-primary font-medium\">\n {label}: {value}\n </span>\n )\n}\n\n/**\n * Per-row Copy icon. Stops propagation so the click doesn't toggle\n * the row's expanded state. Shows a Check briefly after copy as a\n * \"did it work\" affordance — same UX language the toolbar Copy\n * button already uses for its `Copied!` label.\n */\nfunction RowCopyButton({\n copied,\n onCopy,\n}: {\n readonly copied: boolean\n readonly onCopy: () => void\n}) {\n return (\n <button\n type=\"button\"\n title=\"Copy this row\"\n onClick={(e) => {\n e.stopPropagation()\n onCopy()\n }}\n className={cn(\n 'rounded p-0.5 transition-colors',\n copied\n ? 'text-emerald-400'\n : 'text-foreground-subtle/60 hover:text-foreground hover:bg-surface-hover',\n )}\n >\n {copied\n ? <Check className=\"h-3 w-3\" />\n : <Copy className=\"h-3 w-3\" />}\n </button>\n )\n}\n\nfunction ToolbarButton({\n icon: Icon,\n label,\n onClick,\n disabled,\n active,\n}: {\n readonly icon: typeof Info\n readonly label: string\n readonly onClick: () => void\n readonly disabled?: boolean\n readonly active?: boolean\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n active\n ? 'border-amber-500/30 bg-amber-500/10 text-amber-400'\n : 'border-border text-foreground-subtle hover:text-foreground',\n disabled && 'opacity-40 cursor-not-allowed',\n )}\n >\n <Icon className=\"h-2.5 w-2.5\" />\n {label}\n </button>\n )\n}\n","/**\n * useLiveBuffer — capped FIFO buffer for live-pushed entries.\n *\n * The Log/Event/StateValues streams each accumulate WebSocket-pushed\n * entries into a ring. By default each component owns its own\n * `useState` ring, but those streams sit inside a tabbed panel\n * (`DeviceActivityPanel`) where switching away unmounts the active\n * stream — and with it, the local ring. Even though the server's\n * recent-events query repopulates initial history on remount, the\n * global event ring evicts low-volume `device.state-changed` entries\n * fast, so the panel looked \"reset\" every time.\n *\n * Callers that need the buffer to survive across mounts host this\n * hook in a parent and pass the returned handle into the stream\n * component as a controlled `liveBuffer` prop. The stream still\n * owns its tRPC subscription (so subscriptions only fire while the\n * inner component is mounted), but it appends into the parent-owned\n * array — preserving the visible list across tab switches without\n * keeping idle subscriptions alive.\n */\nimport { useCallback, useMemo, useState } from 'react'\n\nexport interface LiveBuffer<T> {\n readonly entries: readonly T[]\n /** Append one entry; oldest is evicted past `max`. */\n readonly append: (entry: T) => void\n /** Replace all entries — used by Clear / scope-change resets. */\n readonly reset: () => void\n}\n\nexport function useLiveBuffer<T>(max: number): LiveBuffer<T> {\n const [entries, setEntries] = useState<readonly T[]>([])\n\n const append = useCallback((entry: T) => {\n setEntries((prev) => {\n const next = [...prev, entry]\n return next.length > max ? next.slice(-max) : next\n })\n }, [max])\n\n const reset = useCallback(() => {\n setEntries([])\n }, [])\n\n return useMemo(() => ({ entries, append, reset }), [entries, append, reset])\n}\n","/**\n * EventStream — universal event viewer for ui-library.\n *\n * Hierarchical scope: agentId → addonId → deviceId (same as LogStream).\n * Two filtering layers:\n * 1. `defaultCategories` (or legacy `categories`) — initial active\n * whitelist. The user can mutate this through the toolbar's\n * multiselect popover; Reset restores the prop's set.\n * 2. Free-text search — case-insensitive substring match across\n * category, source, data, and the rendered summary line.\n *\n * The backend subscription is mounted only while this component is\n * rendered, so callers can mount/unmount it on tab switches and the\n * tRPC subscription cleans up automatically. The historical query\n * input refreshes when the active category set changes.\n */\nimport { useEffect, useRef, useState, useMemo, useCallback } from 'react'\nimport {\n X, Loader2, ArrowUpToLine, Check, Copy, ChevronDown, ChevronRight,\n Play, Square, RefreshCw, AlertTriangle, AlertCircle,\n Download, Trash2, Upload, Activity, Scan, Eye, Mic,\n Zap, Target, Filter, RotateCcw, Search,\n} from 'lucide-react'\nimport { EventCategory } from '@camstack/types'\nimport { trpc } from '../trpc-react'\nimport { cn } from '../lib/cn'\nimport { useLiveBuffer, type LiveBuffer } from '../hooks/use-live-buffer'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface EventEntry {\n readonly id: string\n readonly timestamp: string\n readonly source: {\n readonly type: string\n readonly id: string | number\n readonly nodeId?: string\n readonly addonId?: string\n readonly deviceId?: number\n }\n readonly category: string\n readonly data: Record<string, unknown>\n}\n\n/**\n * Match an event against the (agentId / addonId / deviceId) scope. The\n * server bus only filters by category pattern; this client-side check\n * narrows the live subscription to the device the panel is mounted on.\n *\n * Each scope dimension is independent — when a prop is undefined the\n * dimension is wildcard. `source.id` is treated as the deviceId when\n * `source.type === 'device'` (the bus emits both shapes for device-\n * scoped events).\n */\nfunction matchesScope(\n e: EventEntry,\n agentId?: string,\n addonId?: string,\n deviceId?: number,\n): boolean {\n if (deviceId !== undefined) {\n const evDeviceId = e.source.deviceId\n ?? (e.source.type === 'device' && typeof e.source.id === 'number' ? e.source.id : undefined)\n if (evDeviceId !== deviceId) return false\n }\n if (addonId !== undefined) {\n const evAddonId = e.source.addonId\n ?? (e.source.type === 'addon' && typeof e.source.id === 'string' ? e.source.id : undefined)\n if (evAddonId !== addonId) return false\n }\n if (agentId !== undefined) {\n const evNodeId = e.source.nodeId\n if (!evNodeId || (evNodeId !== agentId && !evNodeId.startsWith(`${agentId}/`))) return false\n }\n return true\n}\n\nexport interface EventStreamProps {\n // ── Scope (hierarchical, all optional) ────────────────────────────\n readonly agentId?: string\n readonly addonId?: string\n readonly deviceId?: number\n\n // ── Category filtering ────────────────────────────────────────────\n /** Initial whitelist — the user can mutate through the multiselect popover.\n * Defaults to ALL EventCategory values when both this and `categories`\n * are omitted. */\n readonly defaultCategories?: readonly string[]\n /** Legacy alias for `defaultCategories`. Kept for back-compat. */\n readonly categories?: readonly string[]\n /** Category glob/pattern passed to the backend subscription (e.g. 'addon.*'). */\n readonly category?: string\n\n // ── Display ───────────────────────────────────────────────────────\n readonly maxHeight?: string\n readonly limit?: number\n /** Show the multiselect filter button in the toolbar (default true). */\n readonly showCategoryFilter?: boolean\n readonly showFilters?: boolean\n /**\n * Optional controlled live buffer. When provided, the stream reads\n * + appends to this external store rather than its own `useState`,\n * so the visible list survives an unmount/remount of the component\n * (used by `DeviceActivityPanel` to keep tab content alive across\n * tab switches without keeping subscriptions open in inactive tabs).\n */\n readonly liveBuffer?: LiveBuffer<EventEntry>\n readonly onClose?: () => void\n readonly className?: string\n}\n\n// ---------------------------------------------------------------------------\n// Category styling\n// ---------------------------------------------------------------------------\n\ninterface CategoryStyle {\n readonly icon: typeof Play\n readonly color: string\n readonly label: string\n}\n\nconst CATEGORY_STYLES: Record<string, CategoryStyle> = {\n [EventCategory.AddonStarted]: { icon: Play, color: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30', label: 'Started' },\n [EventCategory.AddonInstalled]: { icon: Download, color: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30', label: 'Installed' },\n [EventCategory.AddonRestarted]: { icon: RefreshCw, color: 'bg-blue-500/15 text-blue-400 border-blue-500/30', label: 'Restarted' },\n [EventCategory.AddonUpdated]: { icon: Upload, color: 'bg-blue-500/15 text-blue-400 border-blue-500/30', label: 'Updated' },\n [EventCategory.AddonStopped]: { icon: Square, color: 'bg-foreground-subtle/10 text-foreground-subtle border-border', label: 'Stopped' },\n [EventCategory.AddonUninstalled]: { icon: Trash2, color: 'bg-foreground-subtle/10 text-foreground-subtle border-border', label: 'Uninstalled' },\n [EventCategory.AddonCrashed]: { icon: AlertCircle, color: 'bg-red-500/15 text-red-400 border-red-500/30', label: 'Crashed' },\n [EventCategory.AddonError]: { icon: AlertTriangle, color: 'bg-red-500/15 text-red-400 border-red-500/30', label: 'Error' },\n [EventCategory.DetectionPhaseTransition]: { icon: Activity, color: 'bg-violet-500/15 text-violet-400 border-violet-500/30', label: 'Phase' },\n [EventCategory.DetectionResult]: { icon: Scan, color: 'bg-purple-500/15 text-purple-400 border-purple-500/30', label: 'Detection' },\n [EventCategory.DetectionEvent]: { icon: Eye, color: 'bg-blue-500/15 text-blue-400 border-blue-500/30', label: 'Event' },\n [EventCategory.DetectionCameraNative]: { icon: Target, color: 'bg-cyan-500/15 text-cyan-400 border-cyan-500/30', label: 'Camera AI' },\n [EventCategory.ProviderMotion]: { icon: Zap, color: 'bg-orange-500/15 text-orange-400 border-orange-500/30', label: 'Motion' },\n [EventCategory.MotionOnMotionChanged]: { icon: Zap, color: 'bg-orange-500/15 text-orange-400 border-orange-500/30', label: 'Motion' },\n [EventCategory.MotionAnalysis]: { icon: Activity, color: 'bg-orange-500/10 text-orange-300 border-orange-500/20', label: 'Motion analysis' },\n [EventCategory.MotionZonesRaw]: { icon: Activity, color: 'bg-orange-500/10 text-orange-300 border-orange-500/20', label: 'Motion zones' },\n [EventCategory.ProviderDetection]: { icon: Target, color: 'bg-cyan-500/15 text-cyan-400 border-cyan-500/30', label: 'Provider Det' },\n [EventCategory.PipelineAudioInferenceResult]:{ icon: Mic, color: 'bg-pink-500/15 text-pink-400 border-pink-500/30', label: 'Audio' },\n [EventCategory.AgentOnline]: { icon: Play, color: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30', label: 'Agent Online' },\n [EventCategory.AgentOffline]: { icon: Square, color: 'bg-red-500/15 text-red-400 border-red-500/30', label: 'Agent Offline' },\n [EventCategory.DeviceRegistered]: { icon: Download, color: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30', label: 'Registered' },\n [EventCategory.DeviceUnregistered]: { icon: Trash2, color: 'bg-red-500/15 text-red-400 border-red-500/30', label: 'Unregistered' },\n [EventCategory.DeviceStateChanged]: { icon: Activity, color: 'bg-foreground-subtle/10 text-foreground-subtle border-border', label: 'State' },\n}\n\n/**\n * Resolve the badge style + label for an event row. Most categories\n * map to a fixed entry in `CATEGORY_STYLES`; `device.state-changed` is\n * special — every cap funnels through it, so a single \"State\"\n * label hides the actual signal. We derive the label from\n * `data.capName` (e.g. `audio-metrics`, `motion`, `camera-streams`)\n * so the operator can scan the events tab and tell which slice\n * actually changed.\n */\nfunction getStyle(category: string, data?: Record<string, unknown>): CategoryStyle {\n const base = CATEGORY_STYLES[category] ?? {\n icon: Play,\n color: 'bg-foreground-subtle/10 text-foreground-subtle border-border',\n label: category.split('.').pop() ?? category,\n }\n if (category === EventCategory.DeviceStateChanged && data && typeof data['capName'] === 'string') {\n const capName = data['capName'] as string\n return { ...base, label: capName }\n }\n return base\n}\n\n/** Every value in the EventCategory enum, sorted alphabetically.\n * Computed once at module load — drives the multiselect popover. */\nconst ALL_EVENT_CATEGORIES: readonly string[] = Object.freeze(\n [...new Set(Object.values(EventCategory) as string[])].sort(),\n)\n\n/**\n * Categories that are emitted at high frequency (~1 Hz per camera /\n * per node / per engine) and pollute the live events tab without\n * conveying anything an operator scans an event log to see. They\n * still fan out to dedicated UI panels that subscribe by name\n * (StreamPanel for stream-broker.metrics-snapshot, NodeDetailHeader\n * for pipeline.runner-load-snapshot, etc.) — the events-tab default\n * just opts them out of the catch-all \"All\" view. The operator can\n * opt back in via the multiselect popover.\n *\n * Mirrors `RING_BUFFER_DENY_PATTERNS` in `addon-context-factory.ts`\n * — same set, same rationale: high-frequency, low-value-for-the-\n * operator categories. Kept in sync manually because the UI bundle\n * doesn't import the kernel server module.\n */\nconst LIVE_NOISE_CATEGORIES: readonly string[] = Object.freeze([\n EventCategory.PipelineCameraMetricsSnapshot,\n EventCategory.PipelineRunnerLoadSnapshot,\n EventCategory.PipelineEngineMetricsSnapshot,\n EventCategory.PipelineInferenceResult,\n EventCategory.PipelineTrace,\n EventCategory.PipelineProgress,\n EventCategory.StreamBrokerMetricsSnapshot,\n EventCategory.MetricsNodeResourcesSnapshot,\n EventCategory.MetricsNodeProcessesSnapshot,\n EventCategory.ClusterTopologySnapshot,\n EventCategory.MotionAnalysis,\n EventCategory.MotionZonesRaw,\n EventCategory.DetectionResult,\n EventCategory.PipelineAudioInferenceResult,\n EventCategory.PlatformProbePhase,\n EventCategory.BenchmarkProgress,\n EventCategory.ModelDownloadProgress,\n])\n\nconst LIVE_NOISE_SET: ReadonlySet<string> = new Set(LIVE_NOISE_CATEGORIES)\n\n/** Categories visible in the events tab by default. The \"All\" badge\n * reflects this set, not the raw enum. */\nconst DEFAULT_EVENT_CATEGORIES: readonly string[] = Object.freeze(\n ALL_EVENT_CATEGORIES.filter((c) => !LIVE_NOISE_SET.has(c)),\n)\n\n// ---------------------------------------------------------------------------\n// Helpers — extract readable summary from event data\n// ---------------------------------------------------------------------------\n\nfunction summarizeEvent(category: string, data: Record<string, unknown>): string | null {\n if (category === EventCategory.DetectionPhaseTransition) {\n const to = data['to']\n const from = data['from']\n const source = typeof data['source'] === 'string' ? data['source'] : null\n const cooldownMs = typeof data['cooldownMs'] === 'number' ? data['cooldownMs'] : null\n const suffix = source ? ` (${source}${cooldownMs ? `, ${Math.round(cooldownMs / 1000)}s cooldown` : ''})` : ''\n if (to === 'active') return `Motion detected — phase active${suffix}`\n if (to === 'watching') return `Cooldown expired — phase watching${suffix}`\n return `Phase: ${String(from)} → ${String(to)}${suffix}`\n }\n\n if (category === EventCategory.DetectionResult) {\n const frame = data['frame'] as Record<string, unknown> | undefined\n const detections = (frame?.['detections'] ?? []) as readonly Record<string, unknown>[]\n if (detections.length === 0) return null\n const counts = new Map<string, number>()\n for (const d of detections) {\n const obj = d as { class?: unknown; macroClass?: unknown }\n const rawClass = obj.class ?? obj.macroClass\n const cls = typeof rawClass === 'string' ? rawClass : ''\n if (cls) counts.set(cls, (counts.get(cls) ?? 0) + 1)\n }\n return [...counts.entries()].map(([c, n]) => n > 1 ? `${c} ×${n}` : c).join(', ')\n }\n\n if (category === EventCategory.PipelineAudioInferenceResult) {\n const frame = data['frame'] as Record<string, unknown> | undefined\n const detections = (frame?.['detections'] ?? []) as readonly Record<string, unknown>[]\n if (detections.length === 0) return null\n return detections.map(d => {\n const obj = d as { class?: unknown; macroClass?: unknown; label?: unknown; score?: number }\n const rawLabel = obj.macroClass ?? obj.class ?? obj.label\n const label = typeof rawLabel === 'string' ? rawLabel : ''\n const score = obj.score\n return score ? `${label} (${Math.round(score * 100)}%)` : label\n }).filter(Boolean).join(', ')\n }\n\n if (category === EventCategory.DetectionEvent) {\n const label = data['label'] ?? data['class']\n const score = data['score'] ?? data['confidence']\n const parts: string[] = []\n if (typeof label === 'string') parts.push(label)\n if (typeof score === 'number') parts.push(`${Math.round(score * 100)}%`)\n return parts.length > 0 ? parts.join(' — ') : null\n }\n\n if (category === EventCategory.ProviderMotion) {\n return data['active'] === true ? 'motion start' : 'motion stop'\n }\n\n if (category === EventCategory.DeviceStateChanged) {\n // The badge already shows the capName (see getStyle). Surface the\n // top-level slice keys so the row body conveys what *changed*\n // (e.g. \"fps, queue\") instead of a generic \"State\".\n const slice = data['slice'] as Record<string, unknown> | undefined\n if (slice && typeof slice === 'object') {\n const keys = Object.keys(slice).filter((k) => k !== 'lastFetchedAt' && k !== 'ts')\n if (keys.length > 0) return keys.slice(0, 4).join(', ') + (keys.length > 4 ? '…' : '')\n }\n return null\n }\n\n if (category === EventCategory.MotionOnMotionChanged) {\n const detected = data['detected']\n const source = typeof data['source'] === 'string' ? data['source'] : null\n const verb = detected === true ? 'motion start' : detected === false ? 'motion stop' : 'motion'\n return source ? `${verb} (${source})` : verb\n }\n\n if (category === EventCategory.ProviderDetection || category === EventCategory.DetectionCameraNative) {\n const detections = (data['detections'] ?? []) as readonly Record<string, unknown>[]\n if (!Array.isArray(detections) || detections.length === 0) {\n // Fall through — provider events sometimes carry the AI class\n // as a top-level `class` field instead of a detections array.\n const cls = typeof data['class'] === 'string' ? data['class'] : null\n return cls ?? null\n }\n const counts = new Map<string, number>()\n for (const d of detections) {\n const obj = d as { class?: unknown; macroClass?: unknown }\n const rawClass = obj.class ?? obj.macroClass\n const cls = typeof rawClass === 'string' ? rawClass : ''\n if (cls) counts.set(cls, (counts.get(cls) ?? 0) + 1)\n }\n return [...counts.entries()].map(([c, n]) => (n > 1 ? `${c} ×${n}` : c)).join(', ')\n }\n\n // Generic: try common fields\n const addonId = data['addonId'] as string | undefined\n const error = data['error'] as string | undefined\n if (error) return error\n if (addonId) return `addon: ${addonId}`\n return null\n}\n\n/** Returns false for detection/audio events with empty frames. */\nfunction hasContent(entry: EventEntry): boolean {\n const cat = entry.category\n if (cat === EventCategory.DetectionResult || cat === EventCategory.PipelineAudioInferenceResult) {\n return summarizeEvent(cat, entry.data) !== null\n }\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst MAX_LIVE_ENTRIES = 300\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function EventStream({\n agentId,\n addonId,\n deviceId,\n defaultCategories,\n categories: legacyCategories,\n category: propsCategory,\n maxHeight = 'max-h-96',\n limit = 50,\n showCategoryFilter = true,\n showFilters: _showFilters = false,\n liveBuffer: externalBuffer,\n onClose,\n className,\n}: EventStreamProps) {\n // Defaults: explicit prop wins, then the legacy alias, then \"all\".\n const defaultsArray = useMemo<readonly string[]>(\n () => defaultCategories ?? legacyCategories ?? DEFAULT_EVENT_CATEGORIES,\n [defaultCategories, legacyCategories],\n )\n const defaultsKey = useMemo(() => [...defaultsArray].sort().join(','), [defaultsArray])\n const [activeCategories, setActiveCategories] = useState<Set<string>>(\n () => new Set(defaultsArray),\n )\n // Re-seed when the prop set changes (e.g. parent provides a new whitelist).\n const prevDefaultsKey = useRef(defaultsKey)\n useEffect(() => {\n if (prevDefaultsKey.current !== defaultsKey) {\n prevDefaultsKey.current = defaultsKey\n setActiveCategories(new Set(defaultsArray))\n }\n }, [defaultsKey, defaultsArray])\n\n // Always-live fallback buffer keeps the hook order stable. When the\n // parent provides an external buffer (DeviceActivityPanel) the local\n // one stays empty; when no parent provides one, the component still\n // works standalone with its own buffer.\n const fallbackBuffer = useLiveBuffer<EventEntry>(MAX_LIVE_ENTRIES)\n const buffer = externalBuffer ?? fallbackBuffer\n const liveEvents = buffer.entries\n const [autoScroll, setAutoScroll] = useState(true)\n const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set())\n const [searchText, setSearchText] = useState('')\n const [filterOpen, setFilterOpen] = useState(false)\n const [categorySearch, setCategorySearch] = useState('')\n const [clearedAt, setClearedAt] = useState(0)\n const scrollRef = useRef<HTMLDivElement>(null)\n const filterRootRef = useRef<HTMLDivElement>(null)\n\n // Reset on scope change\n const scopeKey = `${agentId ?? ''}:${addonId ?? ''}:${String(deviceId ?? '')}:${propsCategory ?? ''}`\n const prevScopeRef = useRef(scopeKey)\n useEffect(() => {\n if (prevScopeRef.current !== scopeKey) {\n prevScopeRef.current = scopeKey\n buffer.reset()\n setExpandedRows(new Set())\n setClearedAt(0)\n }\n }, [scopeKey, buffer])\n\n // Close the filter popover when clicking outside.\n useEffect(() => {\n if (!filterOpen) return\n const onDocClick = (e: MouseEvent) => {\n const root = filterRootRef.current\n if (root && e.target instanceof Node && !root.contains(e.target)) {\n setFilterOpen(false)\n }\n }\n document.addEventListener('mousedown', onDocClick)\n return () => { document.removeEventListener('mousedown', onDocClick) }\n }, [filterOpen])\n\n const scopeInput = useMemo(() => {\n const s: Record<string, unknown> = {}\n if (agentId) s.agentId = agentId\n if (addonId) s.addonId = addonId\n if (deviceId !== undefined) s.deviceId = deviceId\n if (propsCategory) s.category = propsCategory\n return s\n }, [agentId, addonId, deviceId, propsCategory])\n\n // Historical query — pass the active category set so the server's\n // ring buffer pre-filters to what the user wants. Without this,\n // noisy categories saturate the last-N window.\n const activeArray = useMemo(() => [...activeCategories].sort(), [activeCategories])\n const activeKey = useMemo(() => activeArray.join(','), [activeArray])\n // `activeKey` is a stable hash of `activeArray` — depending on\n // `activeKey` is functionally equivalent to depending on\n // `activeArray` but avoids a useMemo re-eval each time React makes\n // a new identity for the array even though its content is the\n // same.\n const getRecentInput = useMemo(() => {\n const s: Record<string, unknown> = { ...scopeInput, limit }\n if (activeArray.length > 0 && activeArray.length < ALL_EVENT_CATEGORIES.length) {\n s.category = activeArray\n }\n return s\n }, [scopeInput, limit, activeKey, activeArray])\n const { data: initialEvents, isLoading } = trpc.systemEvents.getRecent.useQuery(\n getRecentInput,\n { staleTime: 30_000 },\n )\n\n // Live subscription — see backend filter `matchesEventFilter`. Category\n // glob from props is forwarded; multi-category filtering is client-side\n // because the bus subscriber API is single-pattern.\n //\n // Pre-cap filter: drop events that don't match `activeCategories`\n // BEFORE pushing into the live buffer. The buffer is a fixed-size\n // ring (MAX_LIVE_ENTRIES=300); without this gate a noisy\n // background category (audio-metrics, motion-analysis, …) fills\n // the ring with rows the operator hides anyway, evicting the\n // matching entries they actually filtered for. The result was\n // \"filter loses entries over time\" — the live ring still rotated,\n // just with the wrong content.\n //\n // The activeCategories Set is read through a ref so the\n // subscription callback always sees the current filter without\n // resubscribing on toggle.\n const activeCategoriesRef = useRef(activeCategories)\n useEffect(() => {\n activeCategoriesRef.current = activeCategories\n }, [activeCategories])\n const subInput: Record<string, unknown> = scopeInput\n trpc.systemEvents.subscribe.useSubscription(\n subInput,\n {\n onData: (raw: unknown) => {\n const entry = raw as EventEntry\n if (!entry?.id) return\n if (!matchesScope(entry, agentId, addonId, deviceId)) return\n // Skip categories the user has filtered out. Prevents the\n // 300-slot ring from being clobbered by background noise.\n if (!activeCategoriesRef.current.has(entry.category)) return\n buffer.append(entry)\n },\n },\n )\n\n // Auto-scroll preserves the user's reading position. New entries\n // prepend (list is sorted desc by timestamp); when the user is at\n // the top we follow new entries, but if they've scrolled down we\n // increment scrollTop by the new rows' height so the visible\n // anchor row stays on screen instead of being pushed down.\n const prevLiveCountRef = useRef(liveEvents.length)\n useEffect(() => {\n const el = scrollRef.current\n if (!el) {\n prevLiveCountRef.current = liveEvents.length\n return\n }\n const prevCount = prevLiveCountRef.current\n prevLiveCountRef.current = liveEvents.length\n if (liveEvents.length <= prevCount) return\n if (autoScroll && el.scrollTop <= 8) {\n el.scrollTo({ top: 0 })\n } else if (!autoScroll && el.scrollTop > 0) {\n const firstRow = el.firstElementChild?.firstElementChild\n const rowHeight = firstRow instanceof HTMLElement ? firstRow.offsetHeight : 28\n el.scrollTop += rowHeight * (liveEvents.length - prevCount)\n }\n }, [liveEvents.length, autoScroll])\n\n // Merged + filtered (client-side)\n const allEvents = useMemo(() => {\n const byId = new Map<string, EventEntry>()\n for (const e of (initialEvents ?? []) as EventEntry[]) byId.set(e.id, e)\n for (const e of liveEvents) byId.set(e.id, e)\n\n let list = [...byId.values()].filter((e) => activeCategories.has(e.category)).filter(hasContent)\n if (clearedAt > 0) {\n list = list.filter((e) => new Date(e.timestamp).getTime() > clearedAt)\n }\n const needle = searchText.trim().toLowerCase()\n if (needle) {\n list = list.filter((e) => {\n // Raw category string (e.g. \"motion.on-motion-changed\") +\n // the rendered badge label (e.g. \"Motion\", \"Camera AI\") so\n // operators can search by either the wire identifier OR\n // the user-facing text they see on the row.\n if (e.category.toLowerCase().includes(needle)) return true\n const style = getStyle(e.category, e.data)\n if (style.label.toLowerCase().includes(needle)) return true\n const summary = summarizeEvent(e.category, e.data)\n if (summary && summary.toLowerCase().includes(needle)) return true\n // Formatted timestamp (\"20:14:36\") so a user can paste a\n // log-line time into the search and pin it on the events tab.\n try {\n if (new Date(e.timestamp).toLocaleTimeString().toLowerCase().includes(needle)) return true\n } catch { /* invalid timestamp — skip */ }\n try {\n if (JSON.stringify(e.data).toLowerCase().includes(needle)) return true\n if (JSON.stringify(e.source).toLowerCase().includes(needle)) return true\n } catch { /* ignore */ }\n return false\n })\n }\n return list.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())\n }, [initialEvents, liveEvents, activeCategories, searchText, clearedAt])\n\n const toggleRow = useCallback((id: string) => {\n setExpandedRows((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id); else next.add(id)\n return next\n })\n }, [])\n\n const toggleCategory = useCallback((cat: string) => {\n setActiveCategories((prev) => {\n const next = new Set(prev)\n if (next.has(cat)) next.delete(cat); else next.add(cat)\n return next\n })\n }, [])\n\n const handleReset = useCallback(() => {\n setActiveCategories(new Set(defaultsArray))\n setSearchText('')\n setClearedAt(0)\n }, [defaultsArray])\n\n const handleClear = useCallback(() => {\n setClearedAt(Date.now())\n buffer.reset()\n }, [buffer])\n\n // Copy support — toolbar Copy-All flashes the toolbar button,\n // per-row Copy flashes the row icon. Two distinct flags so they\n // don't overwrite each other when the user copies a row right\n // after copying the whole list.\n const [copiedAll, setCopiedAll] = useState(false)\n const [copiedRowId, setCopiedRowId] = useState<string | null>(null)\n const formatEventForCopy = useCallback((event: EventEntry): string => {\n const time = new Date(event.timestamp).toISOString()\n const summary = summarizeEvent(event.category, event.data) ?? ''\n const summaryStr = summary ? ` ${summary}` : ''\n return `${time} [${event.category}]${summaryStr} data=${JSON.stringify(event.data)}`\n }, [])\n const handleCopyAll = useCallback(() => {\n const lines = allEvents.map(formatEventForCopy)\n void navigator.clipboard.writeText(lines.join('\\n')).then(() => {\n setCopiedAll(true)\n setTimeout(() => setCopiedAll(false), 1500)\n })\n }, [allEvents, formatEventForCopy])\n const copyOne = useCallback((event: EventEntry) => {\n void navigator.clipboard.writeText(formatEventForCopy(event)).then(() => {\n setCopiedRowId(event.id)\n setTimeout(() => setCopiedRowId((prev) => (prev === event.id ? null : prev)), 1200)\n })\n }, [formatEventForCopy])\n\n const handleSelectAll = useCallback(() => {\n setActiveCategories(new Set(ALL_EVENT_CATEGORIES))\n }, [])\n\n const handleSelectNone = useCallback(() => {\n setActiveCategories(new Set())\n }, [])\n\n // Categories filtered by the in-popover search box\n const filteredPopoverCategories = useMemo(() => {\n const needle = categorySearch.trim().toLowerCase()\n if (!needle) return ALL_EVENT_CATEGORIES\n return ALL_EVENT_CATEGORIES.filter((c) => c.toLowerCase().includes(needle))\n }, [categorySearch])\n\n const totalAvailable = ALL_EVENT_CATEGORIES.length\n const totalActive = activeCategories.size\n const allSelected = totalActive === totalAvailable\n const filterLabel = allSelected ? 'All' : `${totalActive}/${totalAvailable}`\n\n return (\n <div className={cn('h-full min-h-0 flex flex-col', className)} onClick={(e) => e.stopPropagation()}>\n {/* Toolbar */}\n <div className=\"flex items-center justify-between px-3 py-1.5 bg-surface-hover/30 gap-2 shrink-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] uppercase tracking-wide text-foreground-subtle font-medium\">Events</span>\n {agentId && <ScopeBadge label=\"agent\" value={agentId} />}\n {addonId && <ScopeBadge label=\"addon\" value={addonId} />}\n {deviceId !== undefined && <ScopeBadge label=\"device\" value={`#${deviceId}`} />}\n {propsCategory && <ScopeBadge label=\"category\" value={propsCategory} />}\n\n <button\n type=\"button\"\n onClick={() => {\n setAutoScroll((a) => !a)\n if (!autoScroll && scrollRef.current) scrollRef.current.scrollTo({ top: 0, behavior: 'smooth' })\n }}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n autoScroll\n ? 'border-border text-foreground-subtle hover:text-foreground'\n : 'border-amber-500/30 bg-amber-500/10 text-amber-400',\n )}\n >\n <ArrowUpToLine className=\"h-2.5 w-2.5\" />\n {autoScroll ? 'Auto' : 'Paused'}\n </button>\n\n {showCategoryFilter && (\n <div className=\"relative\" ref={filterRootRef}>\n <button\n type=\"button\"\n onClick={() => setFilterOpen((v) => !v)}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n !allSelected\n ? 'border-violet-500/30 bg-violet-500/10 text-violet-400'\n : 'border-border text-foreground-subtle hover:text-foreground',\n )}\n title=\"Pick events to track\"\n >\n <Filter className=\"h-2.5 w-2.5\" />\n Filter ({filterLabel})\n </button>\n {filterOpen && (\n <CategoryFilterPopover\n search={categorySearch}\n onSearchChange={setCategorySearch}\n categories={filteredPopoverCategories}\n active={activeCategories}\n onToggle={toggleCategory}\n onSelectAll={handleSelectAll}\n onSelectNone={handleSelectNone}\n onResetDefaults={handleReset}\n />\n )}\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground transition-colors\"\n title=\"Reset filters to defaults\"\n >\n <RotateCcw className=\"h-2.5 w-2.5\" />\n Reset\n </button>\n\n <button\n type=\"button\"\n onClick={handleClear}\n className=\"inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground transition-colors\"\n title=\"Clear visible entries\"\n >\n <Trash2 className=\"h-2.5 w-2.5\" />\n Clear\n </button>\n\n <button\n type=\"button\"\n onClick={handleCopyAll}\n disabled={allEvents.length === 0}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n copiedAll\n ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-400'\n : 'border-border text-foreground-subtle hover:text-foreground',\n allEvents.length === 0 && 'opacity-40 cursor-not-allowed',\n )}\n title=\"Copy all visible events\"\n >\n <Copy className=\"h-2.5 w-2.5\" />\n {copiedAll ? 'Copied!' : 'Copy'}\n </button>\n\n <div className=\"relative\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search…\"\n className=\"w-32 pl-1.5 pr-5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50\"\n />\n {searchText && (\n <button\n type=\"button\"\n onClick={() => setSearchText('')}\n className=\"absolute right-1 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground\"\n title=\"Clear search\"\n >\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </div>\n\n {liveEvents.length > 0 && (\n <span className=\"text-[9px] text-emerald-400 font-medium\">+{liveEvents.length} live</span>\n )}\n </div>\n\n {onClose && (\n <button type=\"button\" onClick={onClose} className=\"text-foreground-subtle hover:text-foreground\">\n <X className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n\n {/* Events content — flex-1 fills the panel; max-h-* applied\n on the panel root drives the actual height bound. */}\n <div ref={scrollRef} className={cn('flex-1 min-h-0 overflow-auto text-[10px]', maxHeight)}>\n {isLoading && (\n <div className=\"flex items-center justify-center gap-2 py-6 text-foreground-subtle\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n Loading events...\n </div>\n )}\n {!isLoading && allEvents.length === 0 && (\n <div className=\"py-4 text-center text-foreground-subtle\">No events found</div>\n )}\n {allEvents.length > 0 && (\n <div className=\"divide-y divide-border/30\">\n {allEvents.map((event) => {\n const style = getStyle(event.category, event.data)\n const Icon = style.icon\n const summary = summarizeEvent(event.category, event.data)\n const expanded = expandedRows.has(event.id)\n return (\n <div\n key={event.id}\n className=\"flex items-start gap-2 px-3 py-1.5 hover:bg-surface-hover/30 cursor-pointer\"\n onClick={() => toggleRow(event.id)}\n >\n <span className=\"text-foreground-subtle whitespace-nowrap w-[70px] shrink-0 pt-0.5\">\n {new Date(event.timestamp).toLocaleTimeString()}\n </span>\n <RowCopyButton\n copied={copiedRowId === event.id}\n onCopy={() => copyOne(event)}\n />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n {expanded\n ? <ChevronDown className=\"h-3 w-3 text-foreground-subtle shrink-0\" />\n : <ChevronRight className=\"h-3 w-3 text-foreground-subtle shrink-0\" />}\n <span className={cn('inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[9px] font-medium', style.color)}>\n <Icon className=\"h-2.5 w-2.5\" />\n {style.label}\n </span>\n {event.source.nodeId && event.source.nodeId !== 'hub' && (\n <span className=\"text-[9px] px-1 py-0.5 rounded bg-foreground-subtle/10 text-foreground-subtle font-mono\">\n {event.source.nodeId}\n </span>\n )}\n </div>\n {summary && (\n <p className=\"text-foreground-subtle text-[10px] mt-0.5 ml-5\">{summary}</p>\n )}\n {expanded && (\n <div className=\"mt-1 ml-5 text-[9px] bg-surface rounded px-2 py-1.5 space-y-0.5 font-mono overflow-x-auto\">\n <div>\n <span className=\"text-primary/70\">source</span>\n <span className=\"text-foreground-subtle\">: </span>\n <span className=\"text-foreground\">{JSON.stringify(event.source)}</span>\n </div>\n <div>\n <span className=\"text-primary/70\">category</span>\n <span className=\"text-foreground-subtle\">: </span>\n <span className=\"text-foreground\">{event.category}</span>\n </div>\n {Object.entries(event.data).map(([k, v]) => (\n <div key={k}>\n <span className=\"text-primary/70\">{k}</span>\n <span className=\"text-foreground-subtle\">: </span>\n <span className=\"text-foreground break-all\">\n {typeof v === 'object' ? JSON.stringify(v) : String(v)}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n )}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Multiselect popover\n// ---------------------------------------------------------------------------\n\ninterface CategoryFilterPopoverProps {\n readonly search: string\n readonly onSearchChange: (next: string) => void\n readonly categories: readonly string[]\n readonly active: ReadonlySet<string>\n readonly onToggle: (cat: string) => void\n readonly onSelectAll: () => void\n readonly onSelectNone: () => void\n readonly onResetDefaults: () => void\n}\n\nfunction CategoryFilterPopover({\n search,\n onSearchChange,\n categories,\n active,\n onToggle,\n onSelectAll,\n onSelectNone,\n onResetDefaults,\n}: CategoryFilterPopoverProps) {\n return (\n <div\n className=\"absolute z-20 top-full mt-1 left-0 w-72 max-h-80 rounded-md border border-border bg-surface shadow-lg flex flex-col\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-border/50\">\n <Search className=\"h-3 w-3 text-foreground-subtle\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => onSearchChange(e.target.value)}\n placeholder=\"Filter categories…\"\n className=\"flex-1 bg-transparent text-[10px] focus:outline-none text-foreground placeholder:text-foreground-subtle\"\n autoFocus\n />\n {search && (\n <button type=\"button\" onClick={() => onSearchChange('')}\n className=\"text-foreground-subtle hover:text-foreground\">\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </div>\n <div className=\"flex items-center gap-1 px-2 py-1 border-b border-border/50 text-[9px]\">\n <button\n type=\"button\"\n onClick={onSelectAll}\n className=\"px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground\"\n >\n All\n </button>\n <button\n type=\"button\"\n onClick={onSelectNone}\n className=\"px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground\"\n >\n None\n </button>\n <button\n type=\"button\"\n onClick={onResetDefaults}\n className=\"px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground\"\n >\n Defaults\n </button>\n </div>\n <div className=\"overflow-y-auto flex-1\">\n {categories.length === 0 && (\n <div className=\"text-[10px] text-foreground-subtle italic px-2 py-3 text-center\">\n No matches\n </div>\n )}\n {categories.map((cat) => {\n const checked = active.has(cat)\n const style = getStyle(cat)\n const Icon = style.icon\n return (\n <button\n key={cat}\n type=\"button\"\n onClick={() => onToggle(cat)}\n className=\"w-full flex items-center gap-2 px-2 py-1 text-left hover:bg-surface-hover/40 text-[10px]\"\n >\n <input\n type=\"checkbox\"\n readOnly\n checked={checked}\n className=\"accent-violet-500\"\n />\n <span className={cn('inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[9px] font-medium shrink-0', style.color)}>\n <Icon className=\"h-2.5 w-2.5\" />\n {style.label}\n </span>\n <span className=\"text-foreground-subtle font-mono truncate\">{cat}</span>\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Floating variant\n// ---------------------------------------------------------------------------\n\nexport interface FloatingEventStreamProps extends EventStreamProps {\n readonly position?: 'bottom' | 'overlay'\n}\n\nexport function FloatingEventStream({ position = 'bottom', className, ...props }: FloatingEventStreamProps) {\n const posClass = position === 'bottom'\n ? 'absolute bottom-0 left-0 right-0 z-10 border-t border-border bg-surface/95 backdrop-blur-sm'\n : 'absolute inset-x-2 bottom-2 z-10 rounded-lg border border-border bg-surface/95 backdrop-blur-sm shadow-xl'\n\n return (\n <div className={cn(posClass, className)}>\n <EventStream maxHeight=\"max-h-48\" {...props} />\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction ScopeBadge({ label, value }: { readonly label: string; readonly value: string }) {\n return (\n <span className=\"text-[9px] px-1.5 py-0.5 rounded-full bg-primary/10 text-primary font-medium\">\n {label}: {value}\n </span>\n )\n}\n\n/**\n * Per-row Copy icon — same shape as the one in log-stream.tsx so\n * the three live-streams look symmetric. Stops propagation so the\n * click doesn't toggle the row's expand state. Flashes a Check\n * for ~1s after copy.\n */\nfunction RowCopyButton({\n copied,\n onCopy,\n}: {\n readonly copied: boolean\n readonly onCopy: () => void\n}) {\n return (\n <button\n type=\"button\"\n title=\"Copy this event\"\n onClick={(e) => {\n e.stopPropagation()\n onCopy()\n }}\n className={cn(\n 'rounded p-0.5 transition-colors mt-0.5',\n copied\n ? 'text-emerald-400'\n : 'text-foreground-subtle/60 hover:text-foreground hover:bg-surface-hover',\n )}\n >\n {copied\n ? <Check className=\"h-3 w-3\" />\n : <Copy className=\"h-3 w-3\" />}\n </button>\n )\n}\n","import { useState, useMemo } from 'react'\nimport { RefreshCw, Plus, Trash2, AlertTriangle, Loader2, Wifi, Moon, WifiOff, HelpCircle, ExternalLink } from 'lucide-react'\nimport { trpc } from '../trpc-react'\nimport type { DiscoveredChildDevice, DiscoveredChildStatus, DeviceDiscoveryStatus } from '@camstack/types'\n\n/**\n * Shared discovery panel — renders the `device-discovery` cap surface\n * for any parent device that registers it (Reolink Hub, future ONVIF\n * gateway, NVR-style integrations). Keeps the integration's UI\n * surface zero-effort: as long as the cap is mounted, the panel\n * renders the channel list with status badges, refresh, adopt, and\n * release controls.\n *\n * Mirrors the Scrypted device-discovery affordance pattern: a single\n * generic UI used by every plugin that exposes children behind a\n * gateway. Keeps the operator UX consistent across integrations.\n */\n\ninterface DiscoveryPanelProps {\n readonly deviceId: number\n readonly className?: string\n /**\n * Optional navigation callback fired when the operator clicks the\n * \"Open\" link on an adopted child row. ui-library deliberately\n * stays free of `react-router-dom` so it works in agent UIs +\n * embedded admin shells alike — host wires the actual navigation.\n * When omitted, the link is hidden.\n */\n readonly onOpenChild?: (childDeviceId: number) => void\n}\n\nexport function DiscoveryPanel({ deviceId, className = '', onOpenChild }: DiscoveryPanelProps): React.ReactElement {\n // tRPC handle for the device-discovery cap. Typed via the shared\n // proxy — every method gets a deviceId-aware input shape.\n const utils = trpc.useUtils()\n const listQuery = trpc.deviceDiscovery.listDiscovered.useQuery(\n { deviceId },\n { refetchInterval: 10_000, retry: false },\n )\n const statusQuery = trpc.deviceDiscovery.getStatus.useQuery(\n { deviceId },\n { refetchInterval: 10_000, retry: false },\n )\n const refreshMutation = trpc.deviceDiscovery.refreshDiscovery.useMutation({\n onSuccess: () => {\n void utils.deviceDiscovery.listDiscovered.invalidate({ deviceId })\n void utils.deviceDiscovery.getStatus.invalidate({ deviceId })\n },\n })\n const adoptMutation = trpc.deviceDiscovery.adoptDevice.useMutation({\n onSuccess: () => {\n void utils.deviceDiscovery.listDiscovered.invalidate({ deviceId })\n },\n })\n const releaseMutation = trpc.deviceDiscovery.releaseDevice.useMutation({\n onSuccess: () => {\n void utils.deviceDiscovery.listDiscovered.invalidate({ deviceId })\n },\n })\n\n const [busyChildId, setBusyChildId] = useState<string | null>(null)\n\n // Split the discovered list into two groups so the panel can render\n // them as separate sections — operators almost always care about\n // \"what's available to adopt\" first, \"what's already managed\" second.\n // Mirrors the Scrypted Discovery wizard split (adopted devices grey-\n // listed at the bottom, candidates highlighted at the top).\n const { available, adopted } = useMemo(() => {\n const list = listQuery.data ?? []\n // Sort: ascending by `rtspChannel` when both have one; entries\n // without a channel index (non-Reolink integrations that may\n // discover via UID-only) sort last by name. Avoids the magic\n // `?? 999` sentinel — the previous fallback would have ordered\n // a 1000-channel hub incorrectly. `Number.POSITIVE_INFINITY`\n // is semantically what \"no channel — push to end\" means.\n const sortKey = (c: DiscoveredChildDevice): number =>\n typeof c.metadata.rtspChannel === 'number' ? c.metadata.rtspChannel : Number.POSITIVE_INFINITY\n const byChannel = (a: DiscoveredChildDevice, b: DiscoveredChildDevice): number => {\n const ac = sortKey(a)\n const bc = sortKey(b)\n if (ac !== bc) return ac - bc\n return a.name.localeCompare(b.name)\n }\n return {\n available: list.filter((c) => !c.alreadyAdopted).sort(byChannel),\n adopted: list.filter((c) => c.alreadyAdopted).sort(byChannel),\n }\n }, [listQuery.data])\n\n // The auto-injected `getStatus` cap method returns a generic\n // `unknown`-typed payload through the codegen'd cap router (the\n // tightening per-cap status-shape is followup work — punch-list\n // #13). Cast to the cap's declared status schema here so the panel\n // can read the lastError / lastDiscoveryAt fields ergonomically.\n const status = statusQuery.data as DeviceDiscoveryStatus | null | undefined\n const lastErr = status?.lastError ?? null\n const lastDiscoveryAt = status?.lastDiscoveryAt ?? null\n\n async function handleRefresh(): Promise<void> {\n await refreshMutation.mutateAsync({ deviceId }).catch(() => { /* surfaced via mutation state */ })\n }\n\n async function handleAdopt(child: DiscoveredChildDevice): Promise<void> {\n setBusyChildId(child.childNativeId)\n try {\n await adoptMutation.mutateAsync({ deviceId, childNativeId: child.childNativeId })\n } finally {\n setBusyChildId(null)\n }\n }\n\n async function handleRelease(child: DiscoveredChildDevice): Promise<void> {\n if (child.adoptedDeviceId == null) return\n setBusyChildId(child.childNativeId)\n try {\n await releaseMutation.mutateAsync({ deviceId, childDeviceId: child.adoptedDeviceId })\n } finally {\n setBusyChildId(null)\n }\n }\n\n return (\n <div className={`rounded-xl border border-border bg-surface ${className}`}>\n <div className=\"flex items-start justify-between gap-2 border-b border-border px-3 py-2 sm:px-5 sm:py-3\">\n <div className=\"min-w-0\">\n <h3 className=\"text-sm font-semibold text-foreground\">Discovered devices</h3>\n <p className=\"text-[11px] text-foreground-subtle\">\n Channels behind this hub. Click <span className=\"font-medium\">Add</span> to promote a channel\n to a managed device, or <span className=\"font-medium\">Remove</span> to detach.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={handleRefresh}\n disabled={refreshMutation.isPending}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border px-2 py-1.5 sm:px-3 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors disabled:opacity-50 shrink-0\"\n >\n {refreshMutation.isPending\n ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n : <RefreshCw className=\"h-3.5 w-3.5\" />}\n <span className=\"hidden sm:inline\">Refresh</span>\n </button>\n </div>\n\n {lastErr ? (\n <div className=\"flex items-start gap-2 border-b border-border bg-destructive/10 px-5 py-2 text-[11px] text-destructive\">\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 shrink-0\" />\n <span>Last refresh failed: {lastErr}</span>\n </div>\n ) : null}\n\n {listQuery.isLoading ? (\n <div className=\"flex items-center justify-center py-8 text-foreground-subtle\">\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n </div>\n ) : (available.length === 0 && adopted.length === 0) ? (\n <div className=\"px-5 py-8 text-center text-xs text-foreground-subtle\">\n No channels reported by the hub yet. Click Refresh to enumerate.\n </div>\n ) : (\n <>\n {/* Available section: candidates the operator can promote\n into managed devices. Highlighted because this is the\n primary affordance of the discovery panel. */}\n {available.length > 0 ? (\n <Section\n title=\"Available to add\"\n count={available.length}\n tone=\"primary\"\n >\n {available.map((child) => (\n <ChildRow\n key={child.childNativeId}\n child={child}\n busy={busyChildId === child.childNativeId}\n onAdopt={handleAdopt}\n onRelease={handleRelease}\n onOpenChild={onOpenChild}\n />\n ))}\n </Section>\n ) : null}\n\n {/* Adopted section: already-managed children, kept here so\n the operator can release them without leaving the panel.\n De-emphasised vs Available so it doesn't compete for\n attention when the operator is mid-onboarding. */}\n {adopted.length > 0 ? (\n <Section\n title=\"Already adopted\"\n count={adopted.length}\n tone=\"muted\"\n >\n {adopted.map((child) => (\n <ChildRow\n key={child.childNativeId}\n child={child}\n busy={busyChildId === child.childNativeId}\n onAdopt={handleAdopt}\n onRelease={handleRelease}\n onOpenChild={onOpenChild}\n />\n ))}\n </Section>\n ) : null}\n </>\n )}\n\n {lastDiscoveryAt != null ? (\n <div className=\"border-t border-border px-5 py-2 text-[10px] text-foreground-subtle\">\n Last refreshed {new Date(lastDiscoveryAt).toLocaleString()}\n </div>\n ) : null}\n </div>\n )\n}\n\ninterface SectionProps {\n readonly title: string\n readonly count: number\n readonly tone: 'primary' | 'muted'\n readonly children: React.ReactNode\n}\n\nfunction Section({ title, count, tone, children }: SectionProps): React.ReactElement {\n const headerClass = tone === 'primary'\n ? 'bg-primary/5 text-primary border-primary/30'\n : 'bg-surface text-foreground-subtle border-border'\n return (\n <div className=\"border-t border-border\">\n <div className={`flex items-center justify-between border-b px-3 sm:px-5 py-1.5 text-[10px] uppercase tracking-wider ${headerClass}`}>\n <span className=\"font-semibold\">{title}</span>\n <span className=\"font-mono\">{count}</span>\n </div>\n <div className=\"divide-y divide-border\">\n {children}\n </div>\n </div>\n )\n}\n\ninterface ChildRowProps {\n readonly child: DiscoveredChildDevice\n readonly busy: boolean\n readonly onAdopt: (child: DiscoveredChildDevice) => Promise<void>\n readonly onRelease: (child: DiscoveredChildDevice) => Promise<void>\n readonly onOpenChild?: (childDeviceId: number) => void\n}\n\nfunction ChildRow({ child, busy, onAdopt, onRelease, onOpenChild }: ChildRowProps): React.ReactElement {\n return (\n <div className=\"flex flex-wrap items-center justify-between gap-2 px-3 py-2 sm:px-5 sm:py-3 sm:flex-nowrap sm:gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <StatusBadge status={child.status} />\n <span className=\"truncate text-sm font-medium text-foreground\">{child.name}</span>\n {child.metadata.isDoorbell ? (\n <span className=\"rounded bg-surface-hover px-1.5 py-0.5 text-[9px] uppercase tracking-wide text-foreground-subtle\">Doorbell</span>\n ) : null}\n {child.metadata.isBattery ? (\n <span className=\"rounded bg-surface-hover px-1.5 py-0.5 text-[9px] uppercase tracking-wide text-foreground-subtle\">Battery</span>\n ) : null}\n {child.metadata.isMultifocal ? (\n <span className=\"rounded bg-surface-hover px-1.5 py-0.5 text-[9px] uppercase tracking-wide text-foreground-subtle\">Multifocal</span>\n ) : null}\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-foreground-subtle\">\n {typeof child.metadata.rtspChannel === 'number' ? (\n <span>ch <span className=\"font-mono\">{child.metadata.rtspChannel}</span></span>\n ) : null}\n {child.metadata.model ? <span className=\"truncate max-w-[160px]\">{child.metadata.model}</span> : null}\n {child.metadata.uid ? <span className=\"font-mono truncate max-w-[140px]\">{child.metadata.uid.slice(0, 12)}…</span> : null}\n </div>\n </div>\n\n {child.alreadyAdopted ? (\n <div className=\"flex items-center gap-2\">\n {/* Open link — host wires `onOpenChild` to its router; we\n gate on both the callback being supplied AND a real\n adopted device id (the panel renders adopted rows even\n before the slice catches up post-create, so id may be\n null for one render tick). */}\n {onOpenChild && child.adoptedDeviceId !== null ? (\n <button\n type=\"button\"\n onClick={() => onOpenChild(child.adoptedDeviceId!)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border px-3 py-1.5 text-xs text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors\"\n title=\"Open device detail\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n Open\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={() => { void onRelease(child) }}\n disabled={busy}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-destructive/30 px-3 py-1.5 text-xs text-destructive hover:bg-destructive/10 transition-colors disabled:opacity-50\"\n >\n {busy\n ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n : <Trash2 className=\"h-3.5 w-3.5\" />}\n Remove\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => { void onAdopt(child) }}\n disabled={busy}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground shadow-sm disabled:opacity-50\"\n >\n {busy\n ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n : <Plus className=\"h-3.5 w-3.5\" />}\n Add\n </button>\n )}\n </div>\n )\n}\n\nfunction StatusBadge({ status }: { status: DiscoveredChildStatus }): React.ReactElement {\n switch (status) {\n case 'online':\n return (\n <span className=\"inline-flex items-center gap-1 rounded-full border border-emerald-500/40 bg-emerald-500/10 px-2 py-0.5 text-[10px] font-medium text-emerald-500\">\n <Wifi className=\"h-2.5 w-2.5\" /> online\n </span>\n )\n case 'sleeping':\n return (\n <span className=\"inline-flex items-center gap-1 rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[10px] font-medium text-amber-500\">\n <Moon className=\"h-2.5 w-2.5\" /> sleeping\n </span>\n )\n case 'offline':\n return (\n <span className=\"inline-flex items-center gap-1 rounded-full border border-destructive/40 bg-destructive/10 px-2 py-0.5 text-[10px] font-medium text-destructive\">\n <WifiOff className=\"h-2.5 w-2.5\" /> offline\n </span>\n )\n case 'unknown':\n default:\n return (\n <span className=\"inline-flex items-center gap-1 rounded-full border border-border bg-surface px-2 py-0.5 text-[10px] font-medium text-foreground-subtle\">\n <HelpCircle className=\"h-2.5 w-2.5\" /> unknown\n </span>\n )\n }\n}\n","/**\n * StateValuesStream — runtime-state change viewer for ui-library.\n *\n * Subscribes to `EventCategory.DeviceStateChanged` events scoped to a\n * single device. Each row shows: timestamp, capName, slice JSON.\n * Supports cap-name multiselect filter + free-text search.\n *\n * Live subscription is mounted only while this component is rendered,\n * so the parent can mount/unmount it on tab switches and the tRPC\n * subscription is torn down automatically when hidden.\n */\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react'\nimport {\n X, Loader2, ArrowUpToLine, Check, Copy, ChevronDown, ChevronRight,\n Trash2, RotateCcw, Filter, Search,\n} from 'lucide-react'\nimport { ALL_CAPABILITY_DEFINITIONS, EventCategory } from '@camstack/types'\nimport { trpc } from '../trpc-react'\nimport { cn } from '../lib/cn'\nimport { useLiveBuffer, type LiveBuffer } from '../hooks/use-live-buffer'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface StateChangeEntry {\n readonly id: string\n readonly timestamp: string\n readonly capName: string\n readonly slice: Record<string, unknown>\n}\n\ninterface RawEvent {\n readonly id?: unknown\n readonly timestamp?: unknown\n readonly source?: { readonly type?: unknown; readonly id?: unknown; readonly deviceId?: unknown }\n readonly category?: unknown\n readonly data?: { readonly deviceId?: unknown; readonly capName?: unknown; readonly slice?: unknown }\n}\n\nfunction isStateChangeForDevice(raw: unknown, deviceId: number): raw is RawEvent & {\n data: { deviceId: number; capName: string; slice: Record<string, unknown> }\n} {\n if (!raw || typeof raw !== 'object') return false\n const e = raw as RawEvent\n if (e.category !== EventCategory.DeviceStateChanged) return false\n const data = e.data\n if (!data || typeof data !== 'object') return false\n if (data.deviceId !== deviceId) return false\n if (typeof data.capName !== 'string') return false\n if (!data.slice || typeof data.slice !== 'object') return false\n return true\n}\n\nfunction toEntry(raw: unknown): StateChangeEntry | null {\n if (!raw || typeof raw !== 'object') return null\n const e = raw as RawEvent & { id?: string; timestamp?: string }\n const id = typeof e.id === 'string' ? e.id : null\n const timestamp = typeof e.timestamp === 'string' ? e.timestamp : null\n const data = e.data\n if (!id || !timestamp || !data || typeof data !== 'object') return null\n if (typeof data.capName !== 'string' || !data.slice || typeof data.slice !== 'object') return null\n return {\n id,\n timestamp,\n capName: data.capName,\n slice: data.slice as Record<string, unknown>,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface StateValuesStreamProps {\n /** Device whose runtime-state changes we want to track. Required. */\n readonly deviceId: number\n /** Initial cap-name filter — empty = all caps visible. */\n readonly defaultCaps?: readonly string[]\n /** Max height CSS class. */\n readonly maxHeight?: string\n /** Initial number of historical entries to fetch. */\n readonly limit?: number\n /**\n * Optional controlled live buffer. When provided the stream appends\n * to this external store instead of its own internal `useState`,\n * so the entries survive an unmount/remount of the component (used\n * by `DeviceActivityPanel` to keep tab content visible across\n * tab switches without leaving subscriptions alive in inactive\n * tabs).\n */\n readonly liveBuffer?: LiveBuffer<StateChangeEntry>\n readonly onClose?: () => void\n readonly className?: string\n}\n\nconst MAX_LIVE_ENTRIES = 300\n\n/**\n * Every device-scoped cap name, sorted alphabetically — same shape\n * as `ALL_EVENT_CATEGORIES` in event-stream.tsx so the filter\n * surface is symmetric across the three live-streams (Logs, Events,\n * State). Computed once at module load; the user can pick from this\n * full list rather than only the caps that have already emitted at\n * least one slice change in the current session.\n */\nconst ALL_DEVICE_CAP_NAMES: readonly string[] = Object.freeze(\n [...new Set(\n ALL_CAPABILITY_DEFINITIONS\n .filter((c) => c.scope === 'device')\n .map((c) => c.name),\n )].sort(),\n)\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function StateValuesStream({\n deviceId,\n defaultCaps,\n maxHeight = 'max-h-96',\n limit = 50,\n liveBuffer: externalBuffer,\n onClose,\n className,\n}: StateValuesStreamProps) {\n const initialActiveCaps = useMemo(\n () => new Set<string>(defaultCaps ?? []),\n [defaultCaps],\n )\n const [activeCaps, setActiveCaps] = useState<Set<string>>(initialActiveCaps)\n const [searchText, setSearchText] = useState('')\n const [autoScroll, setAutoScroll] = useState(true)\n const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set())\n const [clearedAt, setClearedAt] = useState(0)\n const [filterOpen, setFilterOpen] = useState(false)\n const [filterSearch, setFilterSearch] = useState('')\n const filterRootRef = useRef<HTMLDivElement>(null)\n // Always create a fallback local buffer so the hook order is stable\n // regardless of whether the parent provides one. When the external\n // buffer is supplied (DeviceActivityPanel hosts it), the local one\n // sits unused — its memory cost is one empty array.\n const fallbackBuffer = useLiveBuffer<StateChangeEntry>(MAX_LIVE_ENTRIES)\n const buffer = externalBuffer ?? fallbackBuffer\n const liveEvents = buffer.entries\n const scrollRef = useRef<HTMLDivElement>(null)\n\n // Reset live buffer + expanded rows when device changes\n const prevDeviceRef = useRef(deviceId)\n useEffect(() => {\n if (prevDeviceRef.current !== deviceId) {\n prevDeviceRef.current = deviceId\n buffer.reset()\n setExpandedRows(new Set())\n setClearedAt(0)\n }\n }, [deviceId, buffer])\n\n // Initial historical query\n const recentInput = useMemo(\n () => ({ deviceId, category: EventCategory.DeviceStateChanged, limit }),\n [deviceId, limit],\n )\n const { data: initialEvents, isLoading } = trpc.systemEvents.getRecent.useQuery(\n recentInput,\n { staleTime: 30_000 },\n )\n\n // Live subscription. Pre-cap filter: drop entries whose capName\n // isn't in `activeCaps` BEFORE pushing into the 300-slot live\n // ring. Without this, a chatty cap (audio-metrics emits ~1Hz)\n // fills the ring with rows the operator hides via the multiselect\n // popover, evicting the matching entries they actually wanted to\n // see. The activeCaps Set is read through a ref so the\n // subscription callback always picks up filter toggles without\n // resubscribing.\n const activeCapsRef = useRef(activeCaps)\n useEffect(() => {\n activeCapsRef.current = activeCaps\n }, [activeCaps])\n trpc.systemEvents.subscribe.useSubscription(\n { deviceId, category: EventCategory.DeviceStateChanged },\n {\n onData: (raw: unknown) => {\n if (!isStateChangeForDevice(raw, deviceId)) return\n const entry = toEntry(raw)\n if (!entry) return\n // Empty active set means \"All\" — no filter applied.\n // Otherwise drop entries outside the active selection.\n const active = activeCapsRef.current\n if (active.size > 0 && !active.has(entry.capName)) return\n buffer.append(entry)\n },\n },\n )\n\n // Auto-scroll to top on new entries — but ONLY when the user is\n // already viewing the head of the list. If they've scrolled down to\n // read older entries, a new item arriving must NOT yank them back\n // to the top. We measure the scroll position before the prepend and\n // re-anchor afterwards.\n const prevLiveCountRef = useRef(liveEvents.length)\n useEffect(() => {\n const el = scrollRef.current\n if (!el) {\n prevLiveCountRef.current = liveEvents.length\n return\n }\n const prevCount = prevLiveCountRef.current\n prevLiveCountRef.current = liveEvents.length\n if (liveEvents.length <= prevCount) return // no new entries\n if (autoScroll && el.scrollTop <= 8) {\n el.scrollTo({ top: 0 })\n }\n // When NOT auto-scrolling, the browser keeps scrollTop fixed\n // relative to the top of the scrollable area. Because new entries\n // are PREPENDED (the list is sorted desc by timestamp), the old\n // content shifts down by the new rows' height. Compensate so the\n // visually anchored row stays put.\n else if (!autoScroll && el.scrollTop > 0) {\n // Estimate row height from the first child; falls back to 28px.\n const firstRow = el.firstElementChild?.firstElementChild\n const rowHeight = firstRow instanceof HTMLElement ? firstRow.offsetHeight : 28\n const newCount = liveEvents.length - prevCount\n el.scrollTop += rowHeight * newCount\n }\n }, [liveEvents.length, autoScroll])\n\n // Merge initial + live, dedupe by id, filter by activeCaps + searchText\n const allEntries = useMemo(() => {\n const byId = new Map<string, StateChangeEntry>()\n for (const e of (initialEvents ?? []) as unknown[]) {\n const entry = toEntry(e)\n if (entry) byId.set(entry.id, entry)\n }\n for (const e of liveEvents) byId.set(e.id, e)\n\n let list = [...byId.values()]\n if (clearedAt > 0) {\n list = list.filter((e) => new Date(e.timestamp).getTime() > clearedAt)\n }\n if (activeCaps.size > 0) {\n list = list.filter((e) => activeCaps.has(e.capName))\n }\n const needle = searchText.trim().toLowerCase()\n if (needle) {\n list = list.filter((e) => {\n // capName badge is the displayed \"title\" of the row.\n if (e.capName.toLowerCase().includes(needle)) return true\n // Formatted timestamp (\"20:14:36\") so an operator can paste\n // a log-line time into the search and pin the matching state\n // change.\n try {\n if (new Date(e.timestamp).toLocaleTimeString().toLowerCase().includes(needle)) return true\n } catch { /* invalid timestamp — skip */ }\n // Formatted summary as the user sees it on the row\n // (`enabled=true · sensitivity=80`). The slice JSON below\n // covers the same data with `:` separators, but the operator\n // may search by what they actually see.\n try {\n const summary = Object.entries(e.slice)\n .map(([k, v]) => `${k}=${formatValue(v)}`)\n .join(' · ')\n if (summary.toLowerCase().includes(needle)) return true\n } catch { /* fall through */ }\n try {\n if (JSON.stringify(e.slice).toLowerCase().includes(needle)) return true\n } catch { /* fall through */ }\n return false\n })\n }\n return list.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())\n }, [initialEvents, liveEvents, activeCaps, searchText, clearedAt])\n\n // Filter source — every device-scoped cap from the codegen\n // capability map, merged with whatever extra cap names appear in\n // the live stream (defensive: a freshly-added cap that hasn't been\n // re-codegen'd would otherwise be missing). Mirrors EventStream's\n // ALL_EVENT_CATEGORIES surface so the three live-streams (Logs,\n // Events, State) share the same \"filter against the full universe,\n // not just observed entries\" semantics.\n const visibleCaps = useMemo(() => {\n const caps = new Set<string>(ALL_DEVICE_CAP_NAMES)\n for (const e of (initialEvents ?? []) as unknown[]) {\n const entry = toEntry(e)\n if (entry) caps.add(entry.capName)\n }\n for (const e of liveEvents) caps.add(e.capName)\n return [...caps].sort()\n }, [initialEvents, liveEvents])\n\n const toggleRow = useCallback((id: string) => {\n setExpandedRows((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id); else next.add(id)\n return next\n })\n }, [])\n\n const toggleCap = useCallback((cap: string) => {\n setActiveCaps((prev) => {\n const next = new Set(prev)\n if (next.has(cap)) next.delete(cap); else next.add(cap)\n return next\n })\n }, [])\n\n const handleReset = useCallback(() => {\n setActiveCaps(new Set<string>(defaultCaps ?? []))\n setSearchText('')\n }, [defaultCaps])\n\n const handleClear = useCallback(() => {\n setClearedAt(Date.now())\n buffer.reset()\n }, [buffer])\n\n // Copy support — toolbar + per-row, mirroring log-stream + event-stream.\n const [copiedAll, setCopiedAll] = useState(false)\n const [copiedRowId, setCopiedRowId] = useState<string | null>(null)\n const formatEntryForCopy = useCallback((entry: StateChangeEntry): string => {\n const time = new Date(entry.timestamp).toISOString()\n return `${time} [${entry.capName}] slice=${JSON.stringify(entry.slice)}`\n }, [])\n const handleCopyAll = useCallback(() => {\n const lines = allEntries.map(formatEntryForCopy)\n void navigator.clipboard.writeText(lines.join('\\n')).then(() => {\n setCopiedAll(true)\n setTimeout(() => setCopiedAll(false), 1500)\n })\n }, [allEntries, formatEntryForCopy])\n const copyOne = useCallback((entry: StateChangeEntry) => {\n void navigator.clipboard.writeText(formatEntryForCopy(entry)).then(() => {\n setCopiedRowId(entry.id)\n setTimeout(() => setCopiedRowId((prev) => (prev === entry.id ? null : prev)), 1200)\n })\n }, [formatEntryForCopy])\n\n const handleSelectAllCaps = useCallback(() => {\n setActiveCaps(new Set(visibleCaps))\n }, [visibleCaps])\n\n const handleSelectNoCaps = useCallback(() => {\n setActiveCaps(new Set())\n }, [])\n\n const filteredPopoverCaps = useMemo(() => {\n const needle = filterSearch.trim().toLowerCase()\n if (!needle) return visibleCaps\n return visibleCaps.filter((c) => c.toLowerCase().includes(needle))\n }, [filterSearch, visibleCaps])\n\n const totalAvailable = visibleCaps.length\n const totalActive = activeCaps.size\n // Symmetric with EventStream: empty active set means \"all visible\n // pass through\" (the `if (activeCaps.size > 0) filter` guard above\n // treats empty as \"no filter applied\"), so we surface that state\n // with a single \"All\" pill instead of \"0/Y\".\n const allSelected = totalActive === 0 || totalActive === totalAvailable\n const filterLabel = allSelected ? 'All' : `${totalActive}/${totalAvailable}`\n\n // Close on outside click — mirrors EventStream's filterRootRef pattern.\n useEffect(() => {\n if (!filterOpen) return\n const onDocClick = (e: MouseEvent) => {\n const root = filterRootRef.current\n if (root && !root.contains(e.target as Node)) setFilterOpen(false)\n }\n document.addEventListener('mousedown', onDocClick)\n return () => document.removeEventListener('mousedown', onDocClick)\n }, [filterOpen])\n\n return (\n <div className={cn('h-full min-h-0 flex flex-col', className)} onClick={(e) => e.stopPropagation()}>\n {/* Toolbar */}\n <div className=\"flex items-center justify-between px-3 py-1.5 bg-surface-hover/30 gap-2 shrink-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] uppercase tracking-wide text-foreground-subtle font-medium\">State</span>\n <ScopeBadge label=\"device\" value={`#${deviceId}`} />\n\n <button\n type=\"button\"\n onClick={() => {\n setAutoScroll((a) => !a)\n if (!autoScroll && scrollRef.current) scrollRef.current.scrollTo({ top: 0, behavior: 'smooth' })\n }}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n autoScroll\n ? 'border-border text-foreground-subtle hover:text-foreground'\n : 'border-amber-500/30 bg-amber-500/10 text-amber-400',\n )}\n >\n <ArrowUpToLine className=\"h-2.5 w-2.5\" />\n {autoScroll ? 'Auto' : 'Paused'}\n </button>\n\n <div className=\"relative\" ref={filterRootRef}>\n <button\n type=\"button\"\n onClick={() => setFilterOpen((v) => !v)}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n !allSelected\n ? 'border-violet-500/30 bg-violet-500/10 text-violet-400'\n : 'border-border text-foreground-subtle hover:text-foreground',\n )}\n title=\"Pick caps to track\"\n >\n <Filter className=\"h-2.5 w-2.5\" />\n Filter ({filterLabel})\n </button>\n {filterOpen && (\n <CapFilterPopover\n search={filterSearch}\n onSearchChange={setFilterSearch}\n caps={filteredPopoverCaps}\n active={activeCaps}\n onToggle={toggleCap}\n onSelectAll={handleSelectAllCaps}\n onSelectNone={handleSelectNoCaps}\n onResetDefaults={handleReset}\n />\n )}\n </div>\n\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground transition-colors\"\n title=\"Reset filters\"\n >\n <RotateCcw className=\"h-2.5 w-2.5\" />\n Reset\n </button>\n\n <button\n type=\"button\"\n onClick={handleClear}\n className=\"inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground transition-colors\"\n title=\"Clear visible entries\"\n >\n <Trash2 className=\"h-2.5 w-2.5\" />\n Clear\n </button>\n\n <button\n type=\"button\"\n onClick={handleCopyAll}\n disabled={allEntries.length === 0}\n className={cn(\n 'inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded border transition-colors',\n copiedAll\n ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-400'\n : 'border-border text-foreground-subtle hover:text-foreground',\n allEntries.length === 0 && 'opacity-40 cursor-not-allowed',\n )}\n title=\"Copy all visible state changes\"\n >\n <Copy className=\"h-2.5 w-2.5\" />\n {copiedAll ? 'Copied!' : 'Copy'}\n </button>\n\n <div className=\"relative\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search…\"\n className=\"w-32 pl-1.5 pr-5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50\"\n />\n {searchText && (\n <button\n type=\"button\"\n onClick={() => setSearchText('')}\n className=\"absolute right-1 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground\"\n title=\"Clear search\"\n >\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </div>\n\n {liveEvents.length > 0 && (\n <span className=\"text-[9px] text-emerald-400 font-medium\">+{liveEvents.length} live</span>\n )}\n </div>\n\n {onClose && (\n <button type=\"button\" onClick={onClose} className=\"text-foreground-subtle hover:text-foreground\">\n <X className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n\n {/* Content — flex-1 lets the scroll body fill the remaining\n space inside the panel; max-h-* on the panel root, not here,\n drives the scroll bound. */}\n <div ref={scrollRef} className={cn('flex-1 min-h-0 overflow-auto text-[10px]', maxHeight)}>\n {isLoading && (\n <div className=\"flex items-center justify-center gap-2 py-6 text-foreground-subtle\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n Loading state changes...\n </div>\n )}\n {!isLoading && allEntries.length === 0 && (\n <div className=\"py-4 text-center text-foreground-subtle\">No state changes</div>\n )}\n {allEntries.length > 0 && (\n <div className=\"divide-y divide-border/30\">\n {allEntries.map((entry) => {\n const expanded = expandedRows.has(entry.id)\n const fields = Object.entries(entry.slice)\n const summary = fields\n .slice(0, 3)\n .map(([k, v]) => `${k}=${formatValue(v)}`)\n .join(' · ')\n return (\n <div\n key={entry.id}\n className=\"flex items-start gap-2 px-3 py-1.5 hover:bg-surface-hover/30 cursor-pointer\"\n onClick={() => toggleRow(entry.id)}\n >\n <span className=\"text-foreground-subtle whitespace-nowrap w-[70px] shrink-0 pt-0.5\">\n {new Date(entry.timestamp).toLocaleTimeString()}\n </span>\n <RowCopyButton\n copied={copiedRowId === entry.id}\n onCopy={() => copyOne(entry)}\n />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n {expanded\n ? <ChevronDown className=\"h-3 w-3 text-foreground-subtle shrink-0\" />\n : <ChevronRight className=\"h-3 w-3 text-foreground-subtle shrink-0\" />}\n <span className=\"inline-flex items-center gap-1 rounded-full border border-violet-500/30 bg-violet-500/15 text-violet-400 px-2 py-0.5 text-[9px] font-medium\">\n {entry.capName}\n </span>\n {fields.length > 3 && (\n <span className=\"text-[9px] text-foreground-subtle\">+{fields.length - 3} more</span>\n )}\n </div>\n {summary && (\n <p className=\"text-foreground-subtle text-[10px] mt-0.5 ml-5 truncate\">{summary}</p>\n )}\n {expanded && (\n <div className=\"mt-1 ml-5 text-[9px] bg-surface rounded px-2 py-1.5 space-y-0.5 font-mono overflow-x-auto\">\n {fields.length === 0\n ? <div className=\"text-foreground-subtle italic\">empty slice</div>\n : fields.map(([k, v]) => (\n <div key={k}>\n <span className=\"text-primary/70\">{k}</span>\n <span className=\"text-foreground-subtle\">: </span>\n <span className=\"text-foreground break-all\">{formatValue(v)}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n )}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatValue(v: unknown): string {\n if (v === null) return 'null'\n if (v === undefined) return 'undefined'\n if (typeof v === 'string') return v\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\n try { return JSON.stringify(v) } catch { return String(v) }\n}\n\nfunction ScopeBadge({ label, value }: { readonly label: string; readonly value: string }) {\n return (\n <span className=\"text-[9px] px-1.5 py-0.5 rounded-full bg-primary/10 text-primary font-medium\">\n {label}: {value}\n </span>\n )\n}\n\ninterface CapFilterPopoverProps {\n readonly search: string\n readonly onSearchChange: (s: string) => void\n readonly caps: readonly string[]\n readonly active: ReadonlySet<string>\n readonly onToggle: (cap: string) => void\n readonly onSelectAll: () => void\n readonly onSelectNone: () => void\n readonly onResetDefaults: () => void\n}\n\n/**\n * Cap-name multiselect popover — same shape as\n * `CategoryFilterPopover` in event-stream.tsx (search box at top,\n * Select All / None / Defaults buttons, scrollable checkbox list).\n * Caps don't have icons / styled badges like events do — we render\n * a flat name + violet-pill bracket so the look stays consistent\n * with the rest of the StateValuesStream rows.\n */\nfunction CapFilterPopover({\n search, onSearchChange, caps, active,\n onToggle, onSelectAll, onSelectNone, onResetDefaults,\n}: CapFilterPopoverProps) {\n return (\n <div\n className=\"absolute z-20 top-full mt-1 left-0 w-72 max-h-80 rounded-md border border-border bg-surface shadow-lg flex flex-col\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-border/50\">\n <Search className=\"h-3 w-3 text-foreground-subtle\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => onSearchChange(e.target.value)}\n placeholder=\"Filter caps…\"\n className=\"flex-1 bg-transparent text-[10px] focus:outline-none text-foreground placeholder:text-foreground-subtle\"\n autoFocus\n />\n {search && (\n <button type=\"button\" onClick={() => onSearchChange('')}\n className=\"text-foreground-subtle hover:text-foreground\">\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </div>\n <div className=\"flex items-center gap-1 px-2 py-1 border-b border-border/50 text-[9px]\">\n <button\n type=\"button\"\n onClick={onSelectAll}\n className=\"px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground\"\n >\n All\n </button>\n <button\n type=\"button\"\n onClick={onSelectNone}\n className=\"px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground\"\n >\n None\n </button>\n <button\n type=\"button\"\n onClick={onResetDefaults}\n className=\"px-1.5 py-0.5 rounded border border-border text-foreground-subtle hover:text-foreground\"\n >\n Defaults\n </button>\n </div>\n <div className=\"overflow-y-auto flex-1\">\n {caps.length === 0 && (\n <div className=\"text-[10px] text-foreground-subtle italic px-2 py-3 text-center\">\n No matches\n </div>\n )}\n {caps.map((cap) => {\n const checked = active.has(cap)\n return (\n <button\n key={cap}\n type=\"button\"\n onClick={() => onToggle(cap)}\n className=\"w-full flex items-center gap-2 px-2 py-1 text-left hover:bg-surface-hover/40 text-[10px]\"\n >\n <input\n type=\"checkbox\"\n readOnly\n checked={checked}\n className=\"accent-violet-500\"\n />\n <span className=\"inline-flex items-center gap-1 rounded-full border border-violet-500/30 bg-violet-500/15 text-violet-400 px-1.5 py-0.5 text-[9px] font-medium shrink-0\">\n {cap}\n </span>\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\n/**\n * Per-row Copy icon — same shape used in log-stream / event-stream\n * so the three live-streams' rows are visually symmetric. Stops\n * propagation so the click doesn't toggle the row's expand state.\n * Flashes a Check for ~1s on success.\n */\nfunction RowCopyButton({\n copied,\n onCopy,\n}: {\n readonly copied: boolean\n readonly onCopy: () => void\n}) {\n return (\n <button\n type=\"button\"\n title=\"Copy this state change\"\n onClick={(e) => {\n e.stopPropagation()\n onCopy()\n }}\n className={cn(\n 'rounded p-0.5 transition-colors mt-0.5',\n copied\n ? 'text-emerald-400'\n : 'text-foreground-subtle/60 hover:text-foreground hover:bg-surface-hover',\n )}\n >\n {copied\n ? <Check className=\"h-3 w-3\" />\n : <Copy className=\"h-3 w-3\" />}\n </button>\n )\n}\n","/**\n * DeviceActivityPanel — unified Logs / Events / State Values viewer.\n *\n * Three internal tabs:\n * - Logs → LogStream (scoped to deviceId)\n * - Events → EventStream (multiselect of EventCategory + free text)\n * - State Values → StateValuesStream (DeviceStateChanged subscription)\n *\n * Only the active tab is rendered. tRPC subscriptions in the inactive\n * tabs are torn down because the components are unmounted — keeps the\n * websocket lean even when many devices have a panel open.\n *\n * The panel hosts three live buffers (`logs` / `events` / `state`) and\n * passes them to the streams. Subscriptions still only fire while\n * their stream is mounted, but the entries already received persist\n * across tab switches — so reopening the State tab doesn't reset\n * the visible list to empty just because the global event ring\n * buffer evicted the older state-changed entries.\n */\nimport { useEffect, useState } from 'react'\nimport { ScrollText, Bell, Database } from 'lucide-react'\nimport { LogStream } from './log-stream'\nimport { EventStream } from './event-stream'\nimport { StateValuesStream } from './state-values-stream'\nimport { useLiveBuffer } from '../hooks/use-live-buffer'\nimport { cn } from '../lib/cn'\n\n// Buffer size mirror — keep in sync with the per-stream MAX_LIVE_ENTRIES\n// constants. They've all converged on a few hundred entries; 500 covers\n// the most-verbose Logs path without bloating the panel.\nconst PANEL_BUFFER_SIZE = 500\n\nexport interface DeviceActivityPanelProps {\n readonly deviceId: number\n /** Initial event categories the user wants tracked. Defaults to \"all\". */\n readonly defaultEventCategories?: readonly string[]\n /** Initial state-cap whitelist. Empty = show every cap that fires. */\n readonly defaultStateCaps?: readonly string[]\n /** Tab to show first. */\n readonly initialTab?: ActivityTabId\n /** CSS class for the panel root. */\n readonly className?: string\n /** Max content height (passed to the active stream). */\n readonly maxHeight?: string\n}\n\nconst TABS = [\n { id: 'logs', label: 'Logs', icon: ScrollText },\n { id: 'events', label: 'Events', icon: Bell },\n { id: 'state', label: 'State', icon: Database },\n] as const\n\nexport type ActivityTabId = (typeof TABS)[number]['id']\n\nexport function DeviceActivityPanel({\n deviceId,\n defaultEventCategories,\n defaultStateCaps,\n initialTab = 'events',\n className,\n maxHeight = 'max-h-96',\n}: DeviceActivityPanelProps) {\n const [tab, setTab] = useState<ActivityTabId>(initialTab)\n\n // Three buffers that survive tab switches. Each stream component\n // appends to its respective buffer when its subscription pushes a\n // new entry; switching to another tab unmounts the stream (closing\n // the subscription) but the entries already collected stay in\n // memory and are shown again the next time the tab is opened.\n const logsBuffer = useLiveBuffer<Parameters<typeof LogStream>[0]['liveBuffer'] extends infer B ? B extends { entries: readonly (infer E)[] } ? E : never : never>(PANEL_BUFFER_SIZE)\n const eventsBuffer = useLiveBuffer<Parameters<typeof EventStream>[0]['liveBuffer'] extends infer B ? B extends { entries: readonly (infer E)[] } ? E : never : never>(PANEL_BUFFER_SIZE)\n const stateBuffer = useLiveBuffer<Parameters<typeof StateValuesStream>[0]['liveBuffer'] extends infer B ? B extends { entries: readonly (infer E)[] } ? E : never : never>(PANEL_BUFFER_SIZE)\n\n // Reset every buffer when the panel switches to a different device —\n // a stale buffer from device #5 must not bleed into the panel for\n // device #6.\n // Reset every buffer when the panel switches device. The reset\n // closures themselves are stable (memoized inside `useLiveBuffer`\n // via `useCallback`), so recapturing them per render is fine — the\n // effect fires only when `deviceId` actually changes thanks to the\n // closure equality React-Query relies on.\n const logsReset = logsBuffer.reset\n const eventsReset = eventsBuffer.reset\n const stateReset = stateBuffer.reset\n useEffect(() => {\n logsReset()\n eventsReset()\n stateReset()\n }, [deviceId, logsReset, eventsReset, stateReset])\n\n return (\n <div className={cn('flex flex-col h-full min-h-0', className)}>\n {/* Tab strip */}\n <div className=\"flex items-center gap-1 mb-2 shrink-0\">\n {TABS.map(({ id, label, icon: Icon }) => {\n const active = tab === id\n return (\n <button\n key={id}\n type=\"button\"\n onClick={() => setTab(id)}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-[11px] font-medium transition-colors',\n active\n ? 'bg-primary/15 text-primary border border-primary/30'\n : 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover border border-transparent',\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n </button>\n )\n })}\n </div>\n\n {/* Active tab content. Only ONE stream is mounted at a time so\n the tRPC subscriptions of the others are released, but each\n stream operates on a parent-owned buffer so the list survives\n tab switches. */}\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {tab === 'logs' && (\n <LogStream\n deviceId={deviceId}\n maxHeight={maxHeight}\n showFilters={false}\n liveBuffer={logsBuffer}\n />\n )}\n {tab === 'events' && (\n <EventStream\n deviceId={deviceId}\n defaultCategories={defaultEventCategories}\n maxHeight={maxHeight}\n showCategoryFilter\n liveBuffer={eventsBuffer}\n />\n )}\n {tab === 'state' && (\n <StateValuesStream\n deviceId={deviceId}\n defaultCaps={defaultStateCaps}\n maxHeight={maxHeight}\n liveBuffer={stateBuffer}\n />\n )}\n </div>\n </div>\n )\n}\n","/**\n * ConfirmActionButton — destructive-action button with a modal confirm.\n *\n * Two-step UX for any operation operators shouldn't trigger by accident:\n * reboot device, restart addon, regenerate token, etc. The trigger is a\n * normal Button that opens a Dialog; confirming runs the async action,\n * the trigger spinner-disables itself for the duration, and the dialog\n * closes on success. Errors surface inline at the dialog's bottom.\n *\n * Generic on `TResult` so callers don't have to discard the return\n * value. Pass an `icon` to render it inside the trigger (e.g. RotateCw\n * for reboot, RefreshCw for restart).\n */\nimport { type ReactNode, useState, type ComponentType } from 'react'\nimport { AlertTriangle, Loader2 } from 'lucide-react'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '../primitives/dialog'\nimport { Button, type ButtonProps } from '../primitives/button'\nimport { cn } from '../lib/cn'\n\nexport interface ConfirmActionButtonProps<TResult> {\n /** Visible label on the trigger button. */\n readonly label: string\n /** Icon component (lucide-react) rendered inside the trigger. */\n readonly icon?: ComponentType<{ className?: string }>\n /** Dialog title. Defaults to \"Confirm action\". */\n readonly title?: string\n /**\n * Dialog body — accepts either a string (rendered as DialogDescription)\n * or arbitrary ReactNode for callers that need lists, code blocks, etc.\n */\n readonly description?: ReactNode\n /** Label on the confirm button inside the dialog. Defaults to `label`. */\n readonly confirmLabel?: string\n /** Visual variant for the trigger button (defaults to `outline`). */\n readonly triggerVariant?: ButtonProps['variant']\n /**\n * Visual variant for the confirm button inside the dialog. Defaults to\n * `danger` since this component is meant for destructive actions.\n */\n readonly confirmVariant?: ButtonProps['variant']\n /** Trigger button size — propagated to the underlying Button. */\n readonly size?: ButtonProps['size']\n /** Disable the trigger entirely (gates rendering instead of UX state). */\n readonly disabled?: boolean\n /** Optional extra class name on the trigger. */\n readonly className?: string\n /**\n * The async action to run on confirm. Must throw on failure so this\n * component can surface the error inline. The result is returned to\n * `onSuccess` for callers that need it (e.g. to invalidate queries).\n */\n readonly action: () => Promise<TResult>\n /** Called after `action` resolves, with the result. */\n readonly onSuccess?: (result: TResult) => void\n}\n\nexport function ConfirmActionButton<TResult>({\n label,\n icon: Icon,\n title = 'Confirm action',\n description,\n confirmLabel,\n triggerVariant = 'outline',\n confirmVariant = 'danger',\n size = 'sm',\n disabled,\n className,\n action,\n onSuccess,\n}: ConfirmActionButtonProps<TResult>) {\n const [open, setOpen] = useState(false)\n const [running, setRunning] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const handleConfirm = async () => {\n setError(null)\n setRunning(true)\n try {\n const result = await action()\n onSuccess?.(result)\n setOpen(false)\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setRunning(false)\n }\n }\n\n return (\n <>\n <Button\n type=\"button\"\n variant={triggerVariant}\n size={size}\n disabled={disabled}\n onClick={() => {\n setError(null)\n setOpen(true)\n }}\n className={className}\n >\n {Icon && <Icon className=\"h-3.5 w-3.5\" />}\n {label}\n </Button>\n\n <Dialog open={open} onOpenChange={(next) => !running && setOpen(next)}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <AlertTriangle className=\"h-4 w-4 text-amber-400\" />\n {title}\n </DialogTitle>\n {typeof description === 'string'\n ? <DialogDescription>{description}</DialogDescription>\n : description}\n </DialogHeader>\n\n {error && (\n <div className={cn(\n 'mt-2 px-3 py-2 rounded border border-danger/40 bg-danger/10',\n 'text-xs text-danger',\n )}>\n {error}\n </div>\n )}\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size={size}\n disabled={running}\n onClick={() => setOpen(false)}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant={confirmVariant}\n size={size}\n disabled={running}\n onClick={() => { void handleConfirm() }}\n >\n {running && <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />}\n {confirmLabel ?? label}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n )\n}\n","/**\n * PTZOverlay — pan / tilt / zoom controls.\n *\n * Two visual variants driven by `mode`:\n * - `'overlay'` (default): translucent dark pill positioned bottom-\n * right of the camera viewport. Used as `extraOverlay` on the\n * `CameraStreamPlayer` so operators can drive PTZ without leaving\n * the live view. Opaque background + subtle ring keeps the d-pad\n * legible against any frame.\n * - `'panel'`: full-bleed inside a host container (e.g. the floating\n * PTZ panel in DeviceDetail). No absolute positioning, no inner\n * wrapper card — the host's chrome is the only frame. Inherits the\n * surrounding `bg-surface` so the dark theme reads consistently\n * instead of the previous always-dark-bubble look.\n *\n * Interaction model is identical across modes: short tap fires a\n * discrete pulse (`move`); long press starts continuous motion until\n * release (`startContinuous` + `stopContinuous` on pointer up).\n */\nimport { type PointerEvent, useCallback, useState } from 'react'\nimport {\n ArrowUp, ArrowDown, ArrowLeft, ArrowRight,\n Home, ZoomIn, ZoomOut, ChevronDown,\n type LucideIcon,\n} from 'lucide-react'\nimport type { PTZDirection, UsePTZResult } from '../hooks/use-ptz'\nimport { cn } from '../lib/cn'\n\ninterface DPadButtonProps {\n readonly direction: PTZDirection\n readonly icon: LucideIcon\n readonly disabled?: boolean\n readonly className?: string\n readonly variant: 'overlay' | 'panel'\n readonly onMove: (d: PTZDirection) => void\n readonly onStart: (d: PTZDirection) => void\n readonly onStop: () => void\n}\n\nfunction DPadButton({ direction, icon: Icon, disabled, className, variant, onMove, onStart, onStop }: DPadButtonProps) {\n const [pressedAt, setPressedAt] = useState<number | null>(null)\n const [continuous, setContinuous] = useState(false)\n\n const handlePointerDown = useCallback((e: PointerEvent<HTMLButtonElement>) => {\n if (disabled) return\n e.currentTarget.setPointerCapture(e.pointerId)\n setPressedAt(Date.now())\n setContinuous(false)\n const timer = setTimeout(() => {\n setContinuous(true)\n onStart(direction)\n }, 250)\n e.currentTarget.dataset.timer = String(timer)\n }, [direction, disabled, onStart])\n\n const handlePointerUp = useCallback((e: PointerEvent<HTMLButtonElement>) => {\n const timerId = Number(e.currentTarget.dataset.timer)\n if (timerId) clearTimeout(timerId)\n e.currentTarget.dataset.timer = ''\n if (continuous) {\n onStop()\n } else if (pressedAt !== null) {\n onMove(direction)\n }\n setPressedAt(null)\n setContinuous(false)\n }, [continuous, direction, onMove, onStop, pressedAt])\n\n const handlePointerCancel = useCallback((e: PointerEvent<HTMLButtonElement>) => {\n const timerId = Number(e.currentTarget.dataset.timer)\n if (timerId) clearTimeout(timerId)\n e.currentTarget.dataset.timer = ''\n if (continuous) onStop()\n setPressedAt(null)\n setContinuous(false)\n }, [continuous, onStop])\n\n // Larger hit area in panel mode where layout space is generous;\n // overlay stays compact to keep the viewport readable.\n const sizeClass = variant === 'panel' ? 'h-9 w-9' : 'h-7 w-7'\n const iconSizeClass = variant === 'panel' ? 'h-4 w-4' : 'h-3.5 w-3.5'\n\n // Overlay mode pill is forced-dark (zinc-900/90) regardless of the\n // app theme, so icons must be light-on-dark explicitly — using\n // `text-foreground` would render them invisible under a light theme.\n const baseClass = variant === 'panel'\n ? 'text-foreground hover:bg-surface-hover active:bg-surface-hover/80'\n : 'text-white hover:bg-white/15 active:bg-white/25'\n\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onPointerDown={handlePointerDown}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerCancel}\n className={cn(\n 'flex items-center justify-center rounded transition-colors disabled:opacity-40',\n baseClass,\n sizeClass,\n className,\n )}\n title={direction}\n >\n <Icon className={iconSizeClass} />\n </button>\n )\n}\n\nexport interface PTZOverlayProps {\n /** Result of `usePTZ(trpc, deviceId)`. */\n readonly controls: UsePTZResult\n /**\n * Visual variant. `'overlay'` floats over the camera viewport with\n * a translucent dark pill; `'panel'` lays out flat inside its\n * container with no inner chrome — use that when hosting inside a\n * floating panel that already provides the dark surface.\n */\n readonly mode?: 'overlay' | 'panel'\n /** Show the presets dropdown (default: true when presets > 0). */\n readonly showPresets?: boolean\n /** Show the zoom buttons (default: true). */\n readonly showZoom?: boolean\n /** Show the home button (default: true). */\n readonly showHome?: boolean\n readonly className?: string\n}\n\nexport function PTZOverlay({\n controls,\n mode = 'overlay',\n showPresets,\n showZoom = true,\n showHome = true,\n className,\n}: PTZOverlayProps) {\n const { move, startContinuous, stopContinuous, zoom, goHome, goToPreset, presets, busy, error } = controls\n const [presetsOpen, setPresetsOpen] = useState(false)\n\n const presetsVisible = (showPresets ?? presets.length > 0) && presets.length > 0\n const isPanel = mode === 'panel'\n\n // Outer container — overlay floats with absolute positioning,\n // panel mode flows naturally inside its host (no fixed offsets).\n // Top-right corner keeps the d-pad clear of the bottom area where\n // detection bounding boxes / motion zones / status badges land.\n const containerClass = isPanel\n ? 'flex flex-col items-stretch gap-2 w-full h-full p-3'\n : 'pointer-events-auto absolute top-3 right-3 z-10 flex flex-col items-end gap-2'\n\n // Inner row chrome — overlay needs its own pill (background, border)\n // because the camera viewport is BEHIND it. We need enough opacity\n // for the controls to read against ANY frame (a black-scene camera\n // would swallow a translucent pill, \"dark on dark\"). zinc-900/90\n // + a brighter border + a soft shadow gives strong contrast on\n // both bright and dark frames; backdrop-blur smooths the boundary.\n // Panel mode inherits the host's surface and just adds spacing.\n const rowClass = isPanel\n ? cn(\n 'flex items-center gap-3 rounded-lg p-2',\n busy && 'ring-1 ring-primary/40',\n )\n : cn(\n 'flex items-center gap-2 rounded-lg border border-white/30 bg-zinc-900/90 backdrop-blur-md p-2 shadow-lg shadow-black/40',\n busy && 'ring-1 ring-primary/40',\n )\n\n // Side column buttons (zoom, home) match the d-pad's button styling.\n const sideButtonSize = isPanel ? 'h-9 w-9' : 'h-7 w-7'\n const sideIconSize = isPanel ? 'h-4 w-4' : 'h-3.5 w-3.5'\n const sideButtonHover = isPanel\n ? 'text-foreground hover:bg-surface-hover'\n : 'text-white hover:bg-white/15'\n\n // Vertical separator between d-pad and side controls — uses a darker\n // divider in panel mode to read against the host surface, white-tint\n // in overlay mode against the video background.\n const sepClass = isPanel ? 'h-12 w-px bg-border mx-1' : 'h-12 w-px bg-white/15 mx-1'\n\n return (\n <div className={cn(containerClass, className)}>\n {error && (\n <div className=\"rounded bg-danger/90 px-2 py-1 text-[10px] font-medium text-white shadow-lg max-w-[200px] self-center\">\n PTZ: {error}\n </div>\n )}\n\n <div className={cn(rowClass, isPanel && 'justify-center')}>\n {/* 4-direction cross — Reolink Baichuan PTZ only accepts\n discrete `Left`/`Right`/`Up`/`Down` commands. Diagonal\n inputs translated to two sequential commands which the\n camera serialised, producing horizontal-only or\n vertical-only motion (not real diagonal). The corner\n slots are kept blank for layout symmetry; if the lib\n ever exposes a true diagonal pulse we can wire them. */}\n <div className=\"grid grid-cols-3 gap-0.5\">\n <span aria-hidden className={isPanel ? 'h-9 w-9' : 'h-7 w-7'} />\n <DPadButton direction=\"up\" icon={ArrowUp} variant={mode}\n onMove={move} onStart={startContinuous} onStop={stopContinuous} />\n <span aria-hidden className={isPanel ? 'h-9 w-9' : 'h-7 w-7'} />\n <DPadButton direction=\"left\" icon={ArrowLeft} variant={mode}\n onMove={move} onStart={startContinuous} onStop={stopContinuous} />\n <span aria-hidden className={isPanel ? 'h-9 w-9' : 'h-7 w-7'} />\n <DPadButton direction=\"right\" icon={ArrowRight} variant={mode}\n onMove={move} onStart={startContinuous} onStop={stopContinuous} />\n <span aria-hidden className={isPanel ? 'h-9 w-9' : 'h-7 w-7'} />\n <DPadButton direction=\"down\" icon={ArrowDown} variant={mode}\n onMove={move} onStart={startContinuous} onStop={stopContinuous} />\n <span aria-hidden className={isPanel ? 'h-9 w-9' : 'h-7 w-7'} />\n </div>\n\n {(showZoom || showHome) && <div className={sepClass} />}\n\n <div className=\"flex flex-col gap-0.5\">\n {showZoom && (\n <>\n <button\n type=\"button\"\n onClick={() => zoom('in')}\n disabled={busy}\n title=\"Zoom in\"\n className={cn('flex items-center justify-center rounded disabled:opacity-40', sideButtonSize, sideButtonHover)}\n >\n <ZoomIn className={sideIconSize} />\n </button>\n <button\n type=\"button\"\n onClick={() => zoom('out')}\n disabled={busy}\n title=\"Zoom out\"\n className={cn('flex items-center justify-center rounded disabled:opacity-40', sideButtonSize, sideButtonHover)}\n >\n <ZoomOut className={sideIconSize} />\n </button>\n </>\n )}\n {showHome && (\n <button\n type=\"button\"\n onClick={() => goHome()}\n disabled={busy}\n title=\"Go home\"\n className={cn('flex items-center justify-center rounded disabled:opacity-40', sideButtonSize, sideButtonHover)}\n >\n <Home className={sideIconSize} />\n </button>\n )}\n </div>\n\n {presetsVisible && (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setPresetsOpen((v) => !v)}\n disabled={busy}\n className={cn(\n 'flex items-center gap-1 rounded px-2 text-[10px] disabled:opacity-40',\n isPanel ? 'h-9 text-foreground hover:bg-surface-hover' : 'h-7 text-white hover:bg-white/15',\n )}\n title=\"Presets\"\n >\n Presets\n <ChevronDown className={cn('h-3 w-3 transition-transform', presetsOpen && 'rotate-180')} />\n </button>\n {presetsOpen && (\n <div\n className={cn(\n 'absolute right-0 min-w-[140px] rounded-lg shadow-xl py-1 z-20',\n // Panel mode opens upward (host's floating panel sits\n // anywhere); overlay mode opens DOWNWARD because the\n // pill is anchored to the top of the viewport — no\n // room to grow upward without escaping the frame.\n isPanel\n ? 'bottom-full mb-1 bg-surface border border-border'\n : 'top-full mt-1 border border-white/30 bg-zinc-900/95 backdrop-blur-md',\n )}\n >\n {presets.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => {\n void goToPreset(p.id)\n setPresetsOpen(false)\n }}\n disabled={busy}\n className={cn(\n 'block w-full px-3 py-1.5 text-left text-[10px] disabled:opacity-40',\n isPanel\n ? 'text-foreground hover:bg-surface-hover'\n : 'text-white hover:bg-white/15',\n )}\n >\n {p.name || p.id}\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * SnapshotButton — operator-facing manual snapshot trigger.\n *\n * Two actions in one button:\n * - Single click → invalidate the wrapper's cache, refetch a fresh\n * snapshot, and open a download dialog with the resulting JPEG.\n * - Hold (long-press, 600ms+) → same fetch but copy the data URL to\n * the clipboard instead of downloading. Useful for quick paste\n * into chat / docs.\n *\n * The component owns no React-Query state — it accepts a tRPC mutation\n * + query proxy and lets the caller decide invalidation / refetch\n * cadence. Returns null if the device id is invalid so call-sites can\n * drop it in unconditionally.\n */\nimport { Camera, Loader2, Check } from 'lucide-react'\nimport { useState, useCallback } from 'react'\nimport { cn } from '../lib/cn'\n\ninterface QueryFn<I, O> {\n query(input: I): Promise<O>\n}\n\nexport interface SnapshotButtonTrpc {\n readonly snapshot: {\n readonly getSnapshot: QueryFn<\n { deviceId: number; streamId?: string; force?: boolean },\n { base64: string; contentType: string } | null\n >\n }\n}\n\nexport interface SnapshotButtonProps {\n readonly trpc: SnapshotButtonTrpc\n readonly deviceId: number\n readonly deviceName: string\n /** Visual size — `'sm'` for header / tile, `'md'` for prominent CTA. */\n readonly size?: 'sm' | 'md'\n readonly className?: string\n}\n\nfunction downloadDataUrl(filename: string, dataUrl: string): void {\n const link = document.createElement('a')\n link.href = dataUrl\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n}\n\nexport function SnapshotButton({\n trpc,\n deviceId,\n deviceName,\n size = 'sm',\n className,\n}: SnapshotButtonProps) {\n const [busy, setBusy] = useState(false)\n const [done, setDone] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const safeName = deviceName.replace(/[^a-zA-Z0-9_.-]+/g, '_')\n\n const fetchSnapshot = useCallback(async (action: 'download' | 'copy') => {\n setBusy(true)\n setError(null)\n setDone(false)\n try {\n // Manual user action — pass `force: true` to bypass the wrapper's\n // freshness gate and capture a brand-new frame. On battery cams\n // this WILL wake the camera; that's the explicit operator intent\n // when the snapshot button is clicked.\n const result = await trpc.snapshot.getSnapshot.query({ deviceId, force: true })\n if (!result) throw new Error('No snapshot available')\n const url = `data:${result.contentType};base64,${result.base64}`\n if (action === 'copy') {\n try {\n await navigator.clipboard.writeText(url)\n } catch {\n throw new Error('Clipboard unavailable')\n }\n } else {\n const ext = result.contentType.includes('png') ? 'png' : 'jpg'\n const ts = new Date().toISOString().replace(/[:.]/g, '-')\n downloadDataUrl(`${safeName}-${ts}.${ext}`, url)\n }\n setDone(true)\n // Auto-clear the success indicator after 1.5s.\n setTimeout(() => setDone(false), 1500)\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setBusy(false)\n }\n }, [trpc, deviceId, safeName])\n\n const sizeClasses = size === 'md'\n ? 'h-9 px-3 text-sm gap-2'\n : 'h-7 px-2.5 text-[11px] gap-1.5'\n\n // Long-press detection: if the button is held > 600ms, the action\n // becomes \"copy data URL\" instead of \"download\".\n const [pressTimer, setPressTimer] = useState<ReturnType<typeof setTimeout> | null>(null)\n const [longPressed, setLongPressed] = useState(false)\n\n const handlePointerDown = () => {\n setLongPressed(false)\n const t = setTimeout(() => {\n setLongPressed(true)\n void fetchSnapshot('copy')\n }, 600)\n setPressTimer(t)\n }\n\n const handlePointerUp = () => {\n if (pressTimer) {\n clearTimeout(pressTimer)\n setPressTimer(null)\n }\n if (!longPressed) void fetchSnapshot('download')\n }\n\n const handlePointerCancel = () => {\n if (pressTimer) {\n clearTimeout(pressTimer)\n setPressTimer(null)\n }\n }\n\n return (\n <button\n type=\"button\"\n title=\"Click to download · long-press to copy\"\n disabled={busy}\n onPointerDown={handlePointerDown}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerCancel}\n onPointerCancel={handlePointerCancel}\n className={cn(\n 'inline-flex items-center justify-center rounded-lg font-medium border border-border',\n 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n 'disabled:opacity-50 transition-colors',\n sizeClasses,\n error && 'border-danger/40 text-danger',\n className,\n )}\n >\n {busy\n ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n : done\n ? <Check className=\"h-3.5 w-3.5 text-success\" />\n : <Camera className=\"h-3.5 w-3.5\" />}\n Snapshot\n </button>\n )\n}\n","/**\n * DoorbellRecentPanel — compact list of recent doorbell presses.\n *\n * Renders the result of `useDoorbellEvents({deviceId})` as a small\n * card: header with the bell icon + counter, body with one row per\n * press (relative time + absolute timestamp on hover). Returns null\n * when no presses have been observed yet so the parent layout\n * collapses cleanly.\n */\nimport { Bell, BellRing } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport type { DoorbellPressEvent } from '../hooks/use-doorbell-events'\n\nexport interface DoorbellRecentPanelProps {\n readonly history: readonly DoorbellPressEvent[]\n /** Max rows to show (defaults to 5). */\n readonly limit?: number\n /** Visual hint that the latest press is fresh (< 30s) — pulses the icon. */\n readonly latestIsFresh?: boolean\n readonly className?: string\n}\n\nfunction formatRelative(ms: number): string {\n const diff = Date.now() - ms\n if (diff < 60_000) return 'just now'\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`\n return `${Math.floor(diff / 86_400_000)}d ago`\n}\n\nexport function DoorbellRecentPanel({\n history,\n limit = 5,\n latestIsFresh,\n className,\n}: DoorbellRecentPanelProps) {\n if (history.length === 0) return null\n\n const Icon = latestIsFresh ? BellRing : Bell\n const visible = history.slice(0, limit)\n\n return (\n <div\n className={cn(\n 'rounded-lg border border-border bg-surface px-3 py-2',\n className,\n )}\n >\n <div className=\"flex items-center gap-2 mb-2\">\n <Icon className={cn('h-4 w-4 text-amber-400', latestIsFresh && 'animate-pulse')} />\n <span className=\"text-[11px] font-semibold uppercase tracking-wider text-foreground-subtle\">\n Recent presses\n </span>\n <span className=\"ml-auto rounded-full bg-foreground-subtle/10 px-1.5 py-0.5 text-[10px] font-medium text-foreground-subtle border border-border\">\n {history.length}\n </span>\n </div>\n <ul className=\"space-y-1\">\n {visible.map((p) => (\n <li\n key={`${p.deviceId}-${p.timestamp}`}\n className=\"flex items-center justify-between text-[11px]\"\n title={new Date(p.timestamp).toLocaleString()}\n >\n <span className=\"text-foreground\">{formatRelative(p.timestamp)}</span>\n <span className=\"text-foreground-subtle font-mono text-[10px]\">\n {new Date(p.timestamp).toLocaleTimeString()}\n </span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n","/**\n * KebabMenu — vertical-dots dropdown for secondary device actions.\n *\n * Wraps `Popover` with a curated MenuItem API so call sites read like:\n *\n * <KebabMenu items={[\n * { id: 'snapshot', label: 'Take snapshot', icon: Camera, onClick: ... },\n * { id: 'reboot', label: 'Reboot device', icon: RotateCw, hidden: !canReboot },\n * { id: 'delete', label: 'Delete', icon: Trash2, danger: true, onClick: ... },\n * ]} />\n *\n * Each item handles its own click; the menu auto-closes after invoking\n * the handler. Disabled / hidden items are skipped without rendering\n * a row, so the menu height matches the visible action set.\n *\n * Mobile fallback inherits from Popover: a bottom-sheet drops in for\n * touch devices, no extra wiring needed.\n */\nimport { type ComponentType, type ReactNode, useState } from 'react'\nimport { MoreVertical } from 'lucide-react'\nimport { Popover, PopoverTrigger, PopoverContent } from '../primitives/popover'\nimport { cn } from '../lib/cn'\n\nexport interface KebabMenuItem {\n /** Stable id for React keys + analytics. */\n readonly id: string\n /** Visible label. */\n readonly label: string\n /** Icon component (lucide-react etc.). */\n readonly icon?: ComponentType<{ className?: string }>\n /** Render an inline subtitle / hint under the label. */\n readonly description?: string\n /** Click handler — menu auto-closes after invocation. */\n readonly onClick: () => void\n /** When true, the item is hidden entirely (gated by feature etc.). */\n readonly hidden?: boolean\n /** When true, the item is rendered greyed out and non-clickable. */\n readonly disabled?: boolean\n /** Renders the item with the destructive accent (red text + hover). */\n readonly danger?: boolean\n /**\n * Optional separator BEFORE this item — useful to group destructive\n * actions visually at the bottom of the menu.\n */\n readonly separatorBefore?: boolean\n}\n\nexport interface KebabMenuProps {\n readonly items: readonly KebabMenuItem[]\n /**\n * Optional content rendered ABOVE the items (e.g. an explanatory\n * label or a status line). Hidden when no header is provided.\n */\n readonly header?: ReactNode\n /** Optional class on the trigger button (sizing, alignment). */\n readonly triggerClassName?: string\n /** Tooltip text on the trigger (defaults to \"More actions\"). */\n readonly title?: string\n}\n\nexport function KebabMenu({ items, header, triggerClassName, title = 'More actions' }: KebabMenuProps) {\n const [open, setOpen] = useState(false)\n const visible = items.filter((i) => !i.hidden)\n if (visible.length === 0) return null\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n title={title}\n className={cn(\n 'inline-flex items-center justify-center rounded-lg p-2',\n 'text-foreground-subtle hover:text-foreground hover:bg-surface-hover',\n 'border border-transparent transition-colors',\n triggerClassName,\n )}\n >\n <MoreVertical className=\"h-4 w-4\" />\n </PopoverTrigger>\n <PopoverContent className=\"left-auto right-0 mt-1 min-w-[200px] p-1\">\n {header && (\n <div className=\"px-2 py-1 text-[10px] uppercase tracking-wider text-foreground-subtle\">\n {header}\n </div>\n )}\n <ul className=\"space-y-0.5\">\n {visible.map((item, idx) => (\n <li key={item.id}>\n {item.separatorBefore && idx > 0 && (\n <div className=\"my-1 h-px bg-border\" />\n )}\n <button\n type=\"button\"\n disabled={item.disabled}\n onClick={() => {\n if (item.disabled) return\n item.onClick()\n setOpen(false)\n }}\n className={cn(\n 'flex w-full items-start gap-2 rounded-md px-2 py-1.5 text-left text-[12px]',\n 'transition-colors disabled:opacity-40 disabled:cursor-not-allowed',\n item.danger\n ? 'text-foreground hover:bg-danger/10 hover:text-danger'\n : 'text-foreground hover:bg-surface-hover',\n )}\n >\n {item.icon && (\n <item.icon className={cn(\n 'h-3.5 w-3.5 shrink-0 mt-0.5',\n item.danger && 'text-danger/80',\n )} />\n )}\n <span className=\"flex-1 min-w-0\">\n <span className=\"block leading-tight\">{item.label}</span>\n {item.description && (\n <span className=\"block mt-0.5 text-[10px] text-foreground-subtle leading-tight\">\n {item.description}\n </span>\n )}\n </span>\n </button>\n </li>\n ))}\n </ul>\n </PopoverContent>\n </Popover>\n )\n}\n","/**\n * Per-device zone-editing state shared between the player overlay\n * (drawing surface) and any sibling that needs to drive it\n * (Detection tab \"Add zone\" button, player toolbar Zones toggle, …).\n *\n * Implemented as a React context — kept on its own provider so\n * pages that don't render zones don't pay the extra Render. Wrapped\n * by `PlayerOverlaysProvider` in admin-ui's DeviceDetail.\n *\n * Holds two distinct pieces of state:\n * - `selectedZoneId` — pure selection, fast CRUD path. Operator\n * clicks a zone on the canvas or in the list, the row + polygon\n * light up. No mutation flows from selection alone.\n * - `editingDraft` — non-null while the operator is in unified\n * edit mode (entered via the pencil button on the Detection tab\n * row, exited via Save or Discard). All edits — name, colour,\n * vertex drags — flow into the draft instead of triggering live\n * `updateZone` RPC calls. The Detection tab commits on Save with\n * a single round-trip; Discard throws the draft away. Without\n * this, every keystroke + vertex drop wrote the zones config and\n * the pipeline runner detached + re-attached the camera per\n * write — operators saw 8-character zone renames cycle the\n * pipeline 8 times.\n */\nimport { useCallback, useContext, useMemo, useState, type ReactNode } from 'react'\nimport { createSharedContext } from '../lib/shared-context'\n\nexport type ZoneDrawingKind = 'polygon' | 'tripwire'\n\nexport interface ZoneDraftPoint {\n readonly x: number\n readonly y: number\n}\n\nexport interface ZoneDraft {\n readonly id: string\n readonly kind: ZoneDrawingKind\n readonly name: string\n readonly color: string\n readonly points: ReadonlyArray<ZoneDraftPoint>\n}\n\nexport interface ZoneEditingState {\n /** Whether the zone editor overlay is active. When `true` the\n * Konva Stage intercepts clicks; when `false` clicks pass\n * through to the underlying player. */\n readonly editing: boolean\n /** Active drawing kind. `null` means \"select / drag existing\n * zones\". Setting a non-null value triggers a fresh polygon /\n * tripwire creation on the next click. */\n readonly drawingKind: ZoneDrawingKind | null\n /** Currently-selected zone id (for highlight + ZoneForm). */\n readonly selectedZoneId: string | null\n /** In-flight draft snapshot of the zone being edited. `null` while\n * no edit session is active — read-only browse mode. */\n readonly editingDraft: ZoneDraft | null\n}\n\nexport interface ZoneEditingActions {\n setEditing(editing: boolean): void\n setDrawingKind(kind: ZoneDrawingKind | null): void\n setSelectedZoneId(id: string | null): void\n /** Start a new polygon/tripwire — convenience for \"Add zone\"\n * buttons that should both unlock the overlay AND select the\n * shape kind in one click. */\n startDrawing(kind: ZoneDrawingKind): void\n /** Exit edit mode — clears the drawing kind + selection + any\n * in-flight draft. Called when the Detection tab is torn down. */\n exitEditing(): void\n /** Snapshot a zone into the draft and enter unified edit mode.\n * If a different draft is already active it is discarded. */\n enterDraft(draft: ZoneDraft): void\n /** Patch the active draft. No-op when no draft is active. */\n updateDraft(patch: Partial<Omit<ZoneDraft, 'id' | 'kind'>>): void\n /** Throw the draft away. Caller is expected to refresh from\n * upstream zone state (operator chose Discard or navigated away). */\n discardDraft(): void\n}\n\ninterface ZoneEditingContextValue extends ZoneEditingState, ZoneEditingActions {}\n\nconst ZoneEditingContext = createSharedContext<ZoneEditingContextValue | null>(\n 'camstack:zone-editing',\n null,\n)\n\nexport interface ZoneEditingProviderProps {\n readonly children: ReactNode\n}\n\nexport function ZoneEditingProvider({ children }: ZoneEditingProviderProps) {\n const [editing, setEditingRaw] = useState(false)\n const [drawingKind, setDrawingKindRaw] = useState<ZoneDrawingKind | null>(null)\n const [selectedZoneId, setSelectedZoneIdRaw] = useState<string | null>(null)\n const [editingDraft, setEditingDraftRaw] = useState<ZoneDraft | null>(null)\n\n const setEditing = useCallback((next: boolean) => {\n setEditingRaw(next)\n if (!next) {\n // Leaving edit mode resets transient sub-states so the next\n // entry starts clean.\n setDrawingKindRaw(null)\n setSelectedZoneIdRaw(null)\n setEditingDraftRaw(null)\n }\n }, [])\n const setDrawingKind = useCallback((kind: ZoneDrawingKind | null) => {\n setDrawingKindRaw(kind)\n }, [])\n const setSelectedZoneId = useCallback((id: string | null) => {\n setSelectedZoneIdRaw(id)\n }, [])\n const startDrawing = useCallback((kind: ZoneDrawingKind) => {\n setEditingRaw(true)\n setSelectedZoneIdRaw(null)\n setDrawingKindRaw(kind)\n setEditingDraftRaw(null)\n }, [])\n const exitEditing = useCallback(() => {\n setEditingRaw(false)\n setDrawingKindRaw(null)\n setSelectedZoneIdRaw(null)\n setEditingDraftRaw(null)\n }, [])\n const enterDraft = useCallback((draft: ZoneDraft) => {\n // Selecting + drafting are coupled — the form/canvas highlight\n // the same zone the operator is editing.\n setSelectedZoneIdRaw(draft.id)\n setEditingDraftRaw(draft)\n }, [])\n const updateDraft = useCallback((patch: Partial<Omit<ZoneDraft, 'id' | 'kind'>>) => {\n setEditingDraftRaw((prev) => prev === null ? prev : { ...prev, ...patch })\n }, [])\n const discardDraft = useCallback(() => {\n setEditingDraftRaw(null)\n }, [])\n\n const value = useMemo<ZoneEditingContextValue>(\n () => ({\n editing,\n drawingKind,\n selectedZoneId,\n editingDraft,\n setEditing,\n setDrawingKind,\n setSelectedZoneId,\n startDrawing,\n exitEditing,\n enterDraft,\n updateDraft,\n discardDraft,\n }),\n [\n editing, drawingKind, selectedZoneId, editingDraft,\n setEditing, setDrawingKind, setSelectedZoneId, startDrawing, exitEditing,\n enterDraft, updateDraft, discardDraft,\n ],\n )\n\n return <ZoneEditingContext.Provider value={value}>{children}</ZoneEditingContext.Provider>\n}\n\n/** Read + drive the zone-editing state. Returns `null` outside a\n * provider so callers that mount in pages without zones (e.g. a\n * shared hero on a non-camera device) can no-op gracefully. */\nexport function useZoneEditing(): ZoneEditingContextValue | null {\n return useContext(ZoneEditingContext)\n}\n","/**\n * useDeviceDetections — subscribes to motion, raw motion, and detection events for a device.\n *\n * Parametrized: accepts a tRPC-like proxy object so it works in both\n * admin-ui (BackendClient.trpc) and addon pages (AddonPageProps.trpc).\n */\nimport { useState, useEffect, useRef } from 'react'\nimport type {\n DetectionResultPayload,\n MotionAnalysisPayload,\n MotionZonesRawPayload,\n PhaseTransitionPayload,\n ObjectDetection,\n} from '@camstack/types'\n\n// ---------------------------------------------------------------------------\n// Exported types\n// ---------------------------------------------------------------------------\n\nexport interface MotionZone {\n readonly x: number\n readonly y: number\n readonly w: number\n readonly h: number\n readonly intensity: number\n}\n\nexport interface MotionState {\n readonly zones: readonly MotionZone[]\n readonly frameWidth: number\n readonly frameHeight: number\n}\n\nexport interface DetectionState {\n readonly detections: readonly ObjectDetection[]\n readonly frameWidth: number\n readonly frameHeight: number\n}\n\nexport interface MotionRawBox {\n readonly bbox: readonly [number, number, number, number]\n readonly changeScore: number\n}\n\nexport interface MotionRawState {\n readonly boxes: readonly MotionRawBox[]\n readonly frameWidth: number\n readonly frameHeight: number\n readonly motionScore: number\n}\n\nexport interface DeviceDetections {\n readonly motion: MotionState | null\n readonly motionRaw: MotionRawState | null\n readonly detection: DetectionState | null\n readonly phase: string\n}\n\nconst MOTION_FADE_MS = 500\nconst DETECTION_FADE_MS = 800\n\n// ---------------------------------------------------------------------------\n// tRPC subscription shape — typed to the procedures we actually call.\n// We cannot import the full generated AppRouter into ui-library (circular dep),\n// so we declare the minimal structural subset we need here.\n// ---------------------------------------------------------------------------\n\ninterface LiveOnEvent {\n subscribe: (\n input: { category: string },\n opts: { onData: (event: unknown) => void },\n ) => { unsubscribe: () => void }\n}\n\ninterface UseDetectionsTrpc {\n live?: { onEvent?: LiveOnEvent }\n}\n\n// ---------------------------------------------------------------------------\n// tRPC proxy — must NOT use optional chaining on .subscribe() because\n// Vite/esbuild compiles `a?.b?.method?.()` into `method.call(b, ...)` which\n// breaks tRPC Proxy's internal `this` binding, causing \"Cannot read 'context'\".\n// Instead, use direct property access inside try/catch.\n// ---------------------------------------------------------------------------\n\n/** Helper: subscribe to live.onEvent without optional chaining on subscribe() */\nfunction safeSubscribe(\n trpc: UseDetectionsTrpc,\n category: string,\n onData: (event: unknown) => void,\n): { unsubscribe: () => void } | null {\n try {\n const live = trpc.live\n if (!live) return null\n const proc = live.onEvent\n if (!proc || typeof proc.subscribe !== 'function') return null\n return proc.subscribe({ category }, { onData })\n } catch {\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Event narrowing helper — device events now carry a numeric `source.id`\n// uniformly across the backend (pipeline-orchestrator / detection-pipeline /\n// provider addons), so we compare numbers directly.\n// ---------------------------------------------------------------------------\n\nfunction matchesDevice(source: { readonly id?: string | number } | undefined, deviceId: number): boolean {\n return source?.id === deviceId\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useDeviceDetections(trpc: UseDetectionsTrpc, deviceId: number | null): DeviceDetections {\n const [motion, setMotion] = useState<MotionState | null>(null)\n const [motionRaw, setMotionRaw] = useState<MotionRawState | null>(null)\n const [detection, setDetection] = useState<DetectionState | null>(null)\n const [phase, setPhase] = useState<string>('watching')\n\n const motionTimer = useRef<ReturnType<typeof setTimeout>>(undefined)\n const motionRawTimer = useRef<ReturnType<typeof setTimeout>>(undefined)\n const detectionTimer = useRef<ReturnType<typeof setTimeout>>(undefined)\n\n // Subscribe to motion analysis events\n useEffect(() => {\n if (deviceId === null) return\n\n const sub = safeSubscribe(trpc, 'detection.motion-analysis', (event: unknown) => {\n const e = event as { source?: { id: string | number }; data?: MotionAnalysisPayload }\n if (!matchesDevice(e?.source, deviceId)) return\n const data = e.data\n if (!data?.regions || data.regions.length === 0) return\n\n setMotion({\n zones: data.regions.map((r) => ({ ...r.bbox, intensity: r.intensity })),\n frameWidth: data.frameWidth,\n frameHeight: data.frameHeight,\n })\n\n if (motionTimer.current) clearTimeout(motionTimer.current)\n motionTimer.current = setTimeout(() => setMotion(null), MOTION_FADE_MS)\n })\n\n return () => {\n sub?.unsubscribe()\n if (motionTimer.current) clearTimeout(motionTimer.current)\n }\n }, [trpc, deviceId])\n\n // Subscribe to raw motion zone events (all CCL regions before minArea filter)\n useEffect(() => {\n if (deviceId === null) return\n\n const sub = safeSubscribe(trpc, 'detection.motion-zones-raw', (event: unknown) => {\n const e = event as { source?: { id: string | number }; data?: MotionZonesRawPayload }\n if (!matchesDevice(e?.source, deviceId)) return\n const data = e.data\n if (!data?.zones) return\n\n setMotionRaw({\n boxes: data.zones.map(z => ({ bbox: z.bbox, changeScore: z.changeScore })),\n frameWidth: data.frameSize?.width ?? 0,\n frameHeight: data.frameSize?.height ?? 0,\n motionScore: data.zones.length > 0\n ? data.zones.reduce((sum, z) => sum + z.changeScore, 0) / data.zones.length\n : 0,\n })\n\n if (motionRawTimer.current) clearTimeout(motionRawTimer.current)\n motionRawTimer.current = setTimeout(() => setMotionRaw(null), MOTION_FADE_MS)\n })\n\n return () => {\n sub?.unsubscribe()\n if (motionRawTimer.current) clearTimeout(motionRawTimer.current)\n }\n }, [trpc, deviceId])\n\n // Subscribe to detection result events\n useEffect(() => {\n if (deviceId === null) return\n\n const sub = safeSubscribe(trpc, 'detection.result', (event: unknown) => {\n const e = event as { source?: { id: string | number }; data?: DetectionResultPayload }\n if (!matchesDevice(e?.source, deviceId)) return\n const frame = e.data?.frame\n if (!frame?.detections?.length) return\n\n setDetection({\n detections: frame.detections,\n frameWidth: frame.width,\n frameHeight: frame.height,\n })\n\n if (detectionTimer.current) clearTimeout(detectionTimer.current)\n detectionTimer.current = setTimeout(() => setDetection(null), DETECTION_FADE_MS)\n })\n\n return () => {\n sub?.unsubscribe()\n if (detectionTimer.current) clearTimeout(detectionTimer.current)\n }\n }, [trpc, deviceId])\n\n // Subscribe to detection phase transitions (real-time, not polling)\n useEffect(() => {\n if (deviceId === null) return\n\n // Initial phase stays at the default 'watching' — live\n // `detection.phase-transition` events drive updates. The legacy\n // `detection.cameraDetectionStatus` shim was removed; callers that\n // need a deterministic snapshot read `pipelineRunner.getCameraMetrics`\n // with an explicit nodeId directly.\n const sub = safeSubscribe(trpc, 'detection.phase-transition', (event: unknown) => {\n const e = event as { source?: { id: string | number }; data?: PhaseTransitionPayload }\n if (!matchesDevice(e?.source, deviceId)) return\n if (e.data?.to) setPhase(e.data.to)\n })\n\n return () => { sub?.unsubscribe() }\n }, [trpc, deviceId])\n\n return { motion, motionRaw, detection, phase }\n}\n","/**\n * useDeviceWebrtc — WebRTC signaling hook for device-scoped streaming.\n *\n * Provides `createSession`, `sendAnswer`, `closeSession` callbacks and\n * a `streams` list (Adaptive + High/Mid/Low) for a given device.\n *\n * Works in both admin-ui (BackendClient.trpc) and addon pages\n * (AddonPageProps.trpc) — parametrized by a minimal tRPC proxy shape.\n */\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport type { StreamChoice } from '../composites/stream-panel'\nimport type { ClientStreamHints, SignalingResult } from '../composites/camera-stream-player'\nimport { useLiveEvent } from './use-live-event'\n\n/**\n * Discriminated WebRTC target — same shape as `WebrtcStreamTarget` on\n * the backend cap. Repeated locally to keep the hook self-contained\n * (no cross-package import from `@camstack/types`).\n */\nexport type WebrtcTarget =\n | { readonly kind: 'adaptive' }\n | { readonly kind: 'profile'; readonly profile: 'high' | 'mid' | 'low' }\n | { readonly kind: 'cam-stream'; readonly camStreamId: string }\n\n// ---------------------------------------------------------------------------\n// Minimal tRPC proxy shape — both admin-ui and addon pages satisfy this.\n// ---------------------------------------------------------------------------\n\n/** Mutation call shape: `.mutate(input)` → Promise. */\ninterface MutateFn<I, O> {\n mutate(input: I): Promise<O>\n}\n\n/** Query call shape: `.query(input?)` → Promise. */\ninterface QueryFn<I, O> {\n query(input: I): Promise<O>\n}\n\ninterface StreamChoiceRow {\n readonly id: string\n readonly label: string\n readonly target: WebrtcTarget\n readonly codec: string | null\n readonly resolution: { width: number; height: number } | null\n readonly status: string | null\n readonly inputFps: number | null\n readonly decodeFps: number | null\n readonly bitrateKbps: number | null\n}\n\n/**\n * Minimal subset of the tRPC proxy needed for WebRTC signaling.\n * Both `BackendClient.trpc` and `AddonPageProps['trpc']` satisfy this\n * at runtime.\n */\nexport interface UseDeviceWebrtcTrpc {\n webrtcSession: {\n listStreams: QueryFn<\n { deviceId: number },\n readonly StreamChoiceRow[]\n >\n createSession: MutateFn<\n { deviceId: number; target: WebrtcTarget; hints?: ClientStreamHints },\n { sessionId: string; sdpOffer: string }\n >\n handleAnswer: MutateFn<\n { deviceId: number; sessionId: string; sdpAnswer: string },\n void\n >\n closeSession: MutateFn<\n { deviceId: number; sessionId: string },\n void\n >\n }\n pipelineOrchestrator?: {\n getCameraMetrics: QueryFn<\n { deviceId: number },\n { phase: string; actualFps: number; avgInferenceTimeMs: number; droppedFrames: number; configuredFps: number } | null\n >\n }\n}\n\ninterface CameraMetricsSnapshotPayload {\n readonly deviceId?: number\n readonly metrics?: {\n readonly phase: string\n readonly actualFps: number\n readonly avgInferenceTimeMs: number\n readonly droppedFrames: number\n }\n}\n\n// ---------------------------------------------------------------------------\n// Return type\n// ---------------------------------------------------------------------------\n\n/** Pipeline detection metrics for a device. */\nexport interface DevicePipelineMetrics {\n readonly phase: string\n readonly detectionFps: number\n readonly avgInferenceMs: number\n readonly droppedFrames: number\n}\n\nexport interface DeviceWebrtcResult {\n /** Available stream choices for the dropdown (Adaptive + assigned profiles). */\n readonly streams: readonly StreamChoice[]\n /** Whether the device has at least one assigned profile (can stream). */\n readonly hasWebrtc: boolean\n /** Live pipeline metrics (phase, detection fps, inference time). */\n readonly pipelineMetrics: DevicePipelineMetrics | null\n /** Server-offer signaling: create a WebRTC session. */\n readonly createSession: (target: WebrtcTarget, hints?: ClientStreamHints) => Promise<SignalingResult>\n /** Server-offer signaling: send the client's SDP answer. */\n readonly sendAnswer: (sessionId: string, sdpAnswer: string) => Promise<void>\n /** Close a WebRTC session on the server. */\n readonly closeSession: (sessionId: string) => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * Hook that provides WebRTC signaling callbacks and stream choices for a device.\n *\n * @param trpc - tRPC proxy (admin-ui BackendClient.trpc or addon page trpc)\n * @param deviceId - numeric device ID (null = disabled)\n * @param pollIntervalMs - how often to refresh profile slots (default: 5000)\n */\nexport function useDeviceWebrtc(\n trpc: UseDeviceWebrtcTrpc,\n deviceId: number | null,\n pollIntervalMs = 5000,\n): DeviceWebrtcResult {\n const [remoteStreams, setRemoteStreams] = useState<readonly StreamChoiceRow[]>([])\n\n // Fetch available streams from the webrtc-session cap\n useEffect(() => {\n if (deviceId === null) return\n let cancelled = false\n const fetch = () => {\n trpc.webrtcSession.listStreams\n .query({ deviceId })\n .then((rows) => { if (!cancelled) setRemoteStreams(rows) })\n .catch(() => {})\n }\n fetch()\n const iv = setInterval(fetch, pollIntervalMs)\n return () => { cancelled = true; clearInterval(iv) }\n }, [trpc, deviceId, pollIntervalMs])\n\n // Pipeline metrics (phase, detection fps, inference time).\n //\n // Primary signal: `pipeline.camera-metrics-snapshot` event emitted\n // ~1 Hz by the runner that holds this camera. Subscribe via the\n // live-events router and update local state in place — no polling.\n //\n // Bootstrap fallback: when the subscription isn't available yet\n // (initial WS reconnect, runner just spawned), seed once via the\n // orchestrator query so the overlay shows the last-known phase\n // until the first event arrives. The orchestrator routes to the\n // runner that owns the camera (via the assignment map), so this\n // covers multi-agent setups too.\n const [pipelineMetrics, setPipelineMetrics] = useState<DevicePipelineMetrics | null>(null)\n useEffect(() => {\n if (deviceId === null) return\n let cancelled = false\n if (trpc.pipelineOrchestrator) {\n trpc.pipelineOrchestrator.getCameraMetrics\n .query({ deviceId })\n .then((m) => {\n if (cancelled || !m) return\n setPipelineMetrics({\n phase: m.phase,\n detectionFps: m.actualFps,\n avgInferenceMs: m.avgInferenceTimeMs,\n droppedFrames: m.droppedFrames,\n })\n })\n .catch(() => {})\n }\n return () => {\n cancelled = true\n }\n }, [trpc, deviceId])\n\n // Live updates: same `pipeline.camera-metrics-snapshot` event the\n // bootstrap query seeds. Filter to the current `deviceId` inside the\n // callback — `useLiveEvent` re-binds on connection-version bumps.\n useLiveEvent<CameraMetricsSnapshotPayload>('pipeline.camera-metrics-snapshot', (evt) => {\n if (deviceId === null) return\n const payload = evt.data\n if (payload.deviceId !== deviceId || !payload.metrics) return\n setPipelineMetrics({\n phase: payload.metrics.phase,\n detectionFps: payload.metrics.actualFps,\n avgInferenceMs: payload.metrics.avgInferenceTimeMs,\n droppedFrames: payload.metrics.droppedFrames,\n })\n })\n\n // Map remote stream choices to StreamPanel's StreamChoice format —\n // each row carries the structured `target` so the player can hand\n // it back to `createSession` verbatim. No streamId string parsing\n // anywhere in the pipeline.\n const { streams, hasWebrtc } = useMemo(() => {\n if (deviceId === null || remoteStreams.length === 0) {\n return { streams: [] as StreamChoice[], hasWebrtc: false }\n }\n const choices: StreamChoice[] = remoteStreams.map((r) => ({\n id: r.id,\n label: r.label,\n target: r.target,\n status: r.status,\n inputFps: r.inputFps,\n decodeFps: r.decodeFps,\n bitrateKbps: r.bitrateKbps,\n }))\n return { streams: choices, hasWebrtc: true }\n }, [deviceId, remoteStreams])\n\n // Signaling callbacks — device-scoped webrtc-session cap\n const createSession = useCallback(async (target: WebrtcTarget, hints?: ClientStreamHints): Promise<SignalingResult> => {\n if (deviceId === null) throw new Error('No device selected')\n const res = await trpc.webrtcSession.createSession.mutate({ deviceId, target, hints })\n return { sessionId: res.sessionId, sdpOffer: res.sdpOffer }\n }, [trpc, deviceId])\n\n const sendAnswer = useCallback(async (sessionId: string, sdpAnswer: string) => {\n if (deviceId === null) throw new Error('No device selected')\n await trpc.webrtcSession.handleAnswer.mutate({ deviceId, sessionId, sdpAnswer })\n }, [trpc, deviceId])\n\n const closeSession = useCallback(async (sessionId: string) => {\n if (deviceId === null) return\n await trpc.webrtcSession.closeSession.mutate({ deviceId, sessionId }).catch(() => {})\n }, [trpc, deviceId])\n\n return { streams, hasWebrtc, pipelineMetrics, createSession, sendAnswer, closeSession }\n}\n","/**\n * usePTZ — PTZ control hook for device-scoped pan / tilt / zoom.\n *\n * Wraps the `ptz` capability methods through the canonical\n * `useDeviceProxy` surface — every call goes through\n * `dev.ptz?.<method>(...)` with deviceId/nodeId auto-injected. The\n * hook stays bare-bones around state (`busy`, `error`, `presets`)\n * so the operator-facing component (PTZOverlay) stays trivial.\n *\n * Returns:\n * - `move(direction)`: discrete one-shot move (cap.move + cap.stop).\n * Use for short pulse moves triggered by tapping a d-pad button.\n * - `startContinuous(direction)` / `stopContinuous()`: gesture-driven\n * continuous motion (`cap.continuousMove` + `cap.stop`). Use for\n * long-press handlers on touch / mouse-down handlers on desktop.\n * - `zoom('in' | 'out')`: discrete zoom step.\n * - `goHome()`: jump to preset 0.\n * - `presets` + `goToPreset(presetId)`: list and jump to named presets.\n *\n * Parametrised by the same `UseDeviceProxyTrpc` shape every other\n * device hook uses — works under admin-ui (BackendClient.trpc) and\n * addon pages (AddonPageProps.trpc) alike.\n */\nimport { useCallback, useEffect, useState } from 'react'\nimport { useDeviceProxy, type UseDeviceProxyTrpc } from './use-device-proxy'\n\n// ── Direction encoding ──────────────────────────────────────────────\n\n/**\n * Cardinal + intercardinal direction tokens. The hook translates them\n * into normalised `(pan, tilt)` vectors before calling the underlying\n * cap so the cap surface stays speed-vector-shaped.\n */\nexport type PTZDirection =\n | 'up' | 'down' | 'left' | 'right'\n | 'up-left' | 'up-right' | 'down-left' | 'down-right'\n\nconst DIRECTION_VECTORS: Record<PTZDirection, { pan: number; tilt: number }> = {\n 'up': { pan: 0, tilt: 1 },\n 'down': { pan: 0, tilt: -1 },\n 'left': { pan: -1, tilt: 0 },\n 'right': { pan: 1, tilt: 0 },\n 'up-left': { pan: -1, tilt: 1 },\n 'up-right': { pan: 1, tilt: 1 },\n 'down-left': { pan: -1, tilt: -1 },\n 'down-right': { pan: 1, tilt: -1 },\n}\n\ninterface PTZPreset {\n readonly id: string\n readonly name: string\n}\n\n/**\n * Backwards-compatible alias for the trpc shape — historically the\n * hook took its own narrow contract; the proxy generalisation\n * supersedes that.\n */\nexport type PTZTrpcProxy = UseDeviceProxyTrpc\n\n// ── Hook ────────────────────────────────────────────────────────────\n\nexport interface UsePTZOptions {\n /** Default speed (0..1) for moves when the caller omits one. */\n readonly defaultSpeed?: number\n /** Pulse duration (ms) for one-shot `move` calls. */\n readonly pulseMs?: number\n /**\n * Gate the hook's network calls. When `false`, the initial preset\n * refresh is skipped and every method becomes a no-op. Use to avoid\n * \"provider not available\" errors on devices that don't advertise\n * the `ptz` capability.\n */\n readonly enabled?: boolean\n}\n\nexport interface UsePTZResult {\n /** One-shot directional pulse. Stops itself after `pulseMs`. */\n readonly move: (direction: PTZDirection, speed?: number) => Promise<void>\n /** Begin continuous motion in `direction` until `stopContinuous` is called. */\n readonly startContinuous: (direction: PTZDirection, speed?: number) => Promise<void>\n /** Stop any ongoing continuous motion. Idempotent. */\n readonly stopContinuous: () => Promise<void>\n /** Discrete zoom step (in or out). */\n readonly zoom: (direction: 'in' | 'out', speed?: number) => Promise<void>\n /** Jump to the home preset (0 on most cameras). */\n readonly goHome: () => Promise<void>\n /** Jump to a named preset. */\n readonly goToPreset: (presetId: string) => Promise<void>\n /** List of presets reported by the camera. Empty until first refresh. */\n readonly presets: readonly PTZPreset[]\n /** Force a refresh of the presets list. */\n readonly refreshPresets: () => Promise<void>\n /** True while a control call is in flight (any path). */\n readonly busy: boolean\n /** Last error message from any cap call, or null. */\n readonly error: string | null\n}\n\nexport function usePTZ(\n trpc: UseDeviceProxyTrpc,\n deviceId: number,\n options?: UsePTZOptions,\n): UsePTZResult {\n const defaultSpeed = options?.defaultSpeed ?? 0.5\n const pulseMs = options?.pulseMs ?? 250\n const enabled = options?.enabled ?? true\n\n const dev = useDeviceProxy(trpc, enabled ? deviceId : null)\n const ptz = dev?.ptz\n\n const [presets, setPresets] = useState<readonly PTZPreset[]>([])\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refreshPresets = useCallback(async () => {\n if (!enabled || !ptz) return\n try {\n const list = await ptz.getPresets({})\n setPresets(list)\n } catch (err) {\n // Drop \"provider not available\" errors silently — they happen on\n // devices that legitimately don't expose PTZ. Real errors (auth,\n // network, malformed response) still surface in the UI.\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('provider not available') || msg.includes('no \\'ptz\\' binding')) return\n setError(msg)\n }\n }, [ptz, enabled])\n\n useEffect(() => {\n void refreshPresets()\n }, [refreshPresets])\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | undefined> => {\n if (!enabled || !ptz) return undefined\n setError(null)\n setBusy(true)\n try {\n return await fn()\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n return undefined\n } finally {\n setBusy(false)\n }\n }, [enabled, ptz])\n\n const move = useCallback(async (direction: PTZDirection, speed?: number) => {\n if (!ptz) return\n const v = DIRECTION_VECTORS[direction]\n const s = speed ?? defaultSpeed\n await wrap(async () => {\n await ptz.move({ pan: v.pan, tilt: v.tilt, speed: s })\n // Pulse: stop after `pulseMs` so the camera doesn't keep gliding.\n await new Promise((r) => setTimeout(r, pulseMs))\n await ptz.stop({})\n })\n }, [ptz, defaultSpeed, pulseMs, wrap])\n\n const startContinuous = useCallback(async (direction: PTZDirection, speed?: number) => {\n if (!ptz) return\n const v = DIRECTION_VECTORS[direction]\n const s = speed ?? defaultSpeed\n await wrap(() => ptz.continuousMove({ pan: v.pan, tilt: v.tilt, speed: s }))\n }, [ptz, defaultSpeed, wrap])\n\n const stopContinuous = useCallback(async () => {\n if (!ptz) return\n await wrap(() => ptz.stop({}))\n }, [ptz, wrap])\n\n const zoom = useCallback(async (direction: 'in' | 'out', speed?: number) => {\n if (!ptz) return\n const z = direction === 'in' ? 1 : -1\n const s = speed ?? defaultSpeed\n await wrap(async () => {\n await ptz.move({ zoom: z, speed: s })\n await new Promise((r) => setTimeout(r, pulseMs))\n await ptz.stop({})\n })\n }, [ptz, defaultSpeed, pulseMs, wrap])\n\n const goHome = useCallback(async () => {\n if (!ptz) return\n await wrap(() => ptz.goHome({}))\n }, [ptz, wrap])\n\n const goToPreset = useCallback(async (presetId: string) => {\n if (!ptz) return\n await wrap(() => ptz.goToPreset({ presetId }))\n }, [ptz, wrap])\n\n return {\n move, startContinuous, stopContinuous, zoom,\n goHome, goToPreset,\n presets, refreshPresets,\n busy, error,\n }\n}\n","/**\n * useDoorbellEvents — subscribe to doorbell.onPressed across the cluster.\n *\n * Returns the most recent press (latest event) and a list of recent\n * presses (ring-buffer, capped). The hook is event-driven (no polling),\n * relying on the typed `EventCategory.DoorbellOnPressed` stream that\n * every device with the `doorbell` cap emits.\n *\n * Filter by `deviceId` to scope to one camera; pass `null` to listen\n * cluster-wide (used by the global toast/notifier).\n */\nimport { useEffect, useState } from 'react'\nimport { useEventStreamLatest } from './use-event-stream'\n\nexport interface DoorbellPressEvent {\n readonly deviceId: number\n readonly timestamp: number\n}\n\nexport interface UseDoorbellEventsResult {\n /** Most recent press, or null if none observed since mount. */\n readonly latest: DoorbellPressEvent | null\n /** Recent presses, newest-first. Capped at `historyLimit`. */\n readonly history: readonly DoorbellPressEvent[]\n}\n\nexport interface UseDoorbellEventsOptions {\n /**\n * Scope the subscription to a specific deviceId. Pass `null` (or\n * omit) to receive every press across the cluster.\n */\n readonly deviceId?: number | null\n /** Max history entries kept in memory. Defaults to 20. */\n readonly historyLimit?: number\n}\n\nexport function useDoorbellEvents(options?: UseDoorbellEventsOptions): UseDoorbellEventsResult {\n const deviceId = options?.deviceId ?? null\n const historyLimit = options?.historyLimit ?? 20\n\n // Filter applied at the source so cluster-wide listeners can scope\n // to a device without re-rendering on every cam's press.\n const event = useEventStreamLatest<DoorbellPressEvent>(\n 'doorbell.onPressed',\n deviceId !== null ? (data) => data.deviceId === deviceId : undefined,\n )\n\n const [history, setHistory] = useState<readonly DoorbellPressEvent[]>([])\n\n useEffect(() => {\n if (!event) return\n setHistory((prev) => {\n // De-dup on (deviceId, timestamp): the typed event stream may\n // replay the latest payload on subscribe, which would otherwise\n // double-insert the same press.\n if (prev.length > 0 && prev[0]!.deviceId === event.deviceId && prev[0]!.timestamp === event.timestamp) {\n return prev\n }\n const next = [event, ...prev]\n return next.length > historyLimit ? next.slice(0, historyLimit) : next\n })\n }, [event, historyLimit])\n\n return {\n latest: event ?? null,\n history,\n }\n}\n","/**\n * useDevices / useDevice — reactive sync-mirror reads.\n *\n * Both hooks hand out `DeviceProxy` references straight out of the\n * `System` mirror. The mirror keeps device + binding caches warm via\n * the `device.registered/unregistered/bindings-changed` event stream,\n * so re-renders are driven by lifecycle pushes — no React Query\n * round-trip and no `refetch` plumbing needed at the caller side.\n *\n * The hooks defensively read once on mount and assume the System has\n * been `init()`ed by the host app — calls before the warm-boot\n * completes simply return an empty array / null and re-render once\n * the registered listeners fire.\n */\nimport { useEffect, useMemo, useState } from 'react'\nimport type { DeviceProxy, DeviceQueryFilters } from '@camstack/types'\nimport { useSystem } from '../contexts/system-context.js'\n\n/**\n * Reactive list of devices matching the optional filter set. Returns a\n * stable array reference between updates so consumers passing it as a\n * prop don't tear down memoized children.\n */\nexport function useDevices(filters?: DeviceQueryFilters): readonly DeviceProxy[] {\n const system = useSystem()\n\n // Stabilise the filters reference: callers usually inline a literal.\n // We hash it to JSON so the effect only re-subscribes when the\n // semantic filter changes — not on every render.\n const filtersKey = useMemo(() => (filters ? JSON.stringify(filters) : ''), [filters])\n\n const [devices, setDevices] = useState<readonly DeviceProxy[]>(() =>\n system.listDevices(filters),\n )\n\n useEffect(() => {\n // Refresh once the System (re)connects + on every lifecycle event.\n const refresh = (): void => {\n setDevices(system.listDevices(filters))\n }\n refresh()\n let unsubAdded: (() => void) | null = null\n let unsubRemoved: (() => void) | null = null\n try {\n unsubAdded = system.onDeviceAdded(refresh)\n unsubRemoved = system.onDeviceRemoved(refresh)\n } catch {\n // Mirror not initialised yet — refresh once the connection\n // bumps; the system invalidates RQ on reconnect.\n }\n const unsubConn = system.subscribeConnectionEvents((state) => {\n if (state === 'connected') refresh()\n })\n return () => {\n unsubAdded?.()\n unsubRemoved?.()\n unsubConn()\n }\n // `filters` is included for closure capture (the refresh thunk\n // calls `listDevices(filters)`) but `filtersKey` is the actual\n // gating signal — callers inline literal filters, so the JSON\n // hash stops the effect from re-running on every render.\n }, [system, filters, filtersKey])\n\n return devices\n}\n\n/**\n * Single-device variant. Returns `null` until the device is in the\n * mirror; re-renders when the device is removed (back to `null`) or\n * added.\n */\nexport function useDevice(deviceId: number | null): DeviceProxy | null {\n const system = useSystem()\n const [device, setDevice] = useState<DeviceProxy | null>(() =>\n deviceId === null ? null : system.getDevice(deviceId),\n )\n\n useEffect(() => {\n if (deviceId === null) {\n setDevice(null)\n return undefined\n }\n const refresh = (): void => {\n setDevice(system.getDevice(deviceId))\n }\n refresh()\n let unsubAdded: (() => void) | null = null\n let unsubRemoved: (() => void) | null = null\n try {\n unsubAdded = system.onDeviceAdded(refresh)\n unsubRemoved = system.onDeviceRemoved(refresh)\n } catch {\n /* mirror not ready */\n }\n const unsubConn = system.subscribeConnectionEvents((state) => {\n if (state === 'connected') refresh()\n })\n return () => {\n unsubAdded?.()\n unsubRemoved?.()\n unsubConn()\n }\n }, [system, deviceId])\n\n return device\n}\n","/**\n * useSystemQuery / useSystemMutation — generic escape hatches over the\n * unified `System` SDK class for tRPC calls that don't (yet) have a\n * codegen'd named hook.\n *\n * Codegen'd hooks (see `../generated/system-hooks.ts`) cover every\n * `scope: 'system'` capability method automatically; reach for these\n * helpers when:\n * 1. The call goes through a core (non-cap) router, or\n * 2. You want to compose multiple cap calls into a single React\n * Query bookkeeping unit (single staleTime, single retry policy).\n *\n * The query helper takes a `select(system) → () => Promise<T>` factory\n * so the caller picks any tRPC procedure off the System namespaces.\n * Inputs are passed via the closure — keeps deps explicit and avoids\n * the React Query input-as-cache-key magic that surprises new readers.\n */\nimport {\n useMutation,\n useQuery,\n type QueryKey,\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n} from '@tanstack/react-query'\nimport type { System } from '@camstack/sdk'\nimport { useSystem } from '../contexts/system-context.js'\n\n/**\n * `select` MUST return a thunk that, when invoked, performs the\n * request. Two-step factory keeps the query-key + thunk identities\n * stable between renders: the hook re-creates the thunk on every\n * render (cheap), but React Query keys off `[queryKey]` only.\n */\nexport type SystemQuerySelector<TData> = (system: System) => () => Promise<TData>\n\nexport type SystemMutationSelector<TInput, TData> = (\n system: System,\n) => (input: TInput) => Promise<TData>\n\nexport function useSystemQuery<TData>(\n queryKey: QueryKey,\n select: SystemQuerySelector<TData>,\n opts?: Omit<UseQueryOptions<TData, Error, TData>, 'queryKey' | 'queryFn'>,\n): UseQueryResult<TData, Error> {\n const system = useSystem()\n return useQuery<TData, Error, TData>({\n queryKey,\n queryFn: () => select(system)(),\n ...opts,\n })\n}\n\nexport function useSystemMutation<TInput, TData>(\n select: SystemMutationSelector<TInput, TData>,\n opts?: Omit<UseMutationOptions<TData, Error, TInput>, 'mutationFn'>,\n): UseMutationResult<TData, Error, TInput> {\n const system = useSystem()\n return useMutation<TData, Error, TInput>({\n mutationFn: (input: TInput) => select(system)(input),\n ...opts,\n })\n}\n","/**\n * useEventInvalidation — subscribe to one or more EventBus categories\n * over the unified `System.subscribeEvent` push channel and invalidate\n * a React Query cache prefix when any of them fires.\n *\n * Lets callers drop their `refetchInterval` polling: the cache is kept\n * fresh by server-pushed events instead of timer-driven refetches. The\n * hook is a no-op when the WebSocket isn't available (e.g. during\n * initial reconnection) — the caller is free to keep a long\n * `staleTime` so React Query still serves the last good snapshot.\n *\n * Input shape — pass the tRPC procedure path directly:\n * ✔ `['integrations']` → invalidates every `integrations.*`\n * ✔ `['deviceManager', 'listAll']` → invalidates that one query\n *\n * The hook wraps the path into the `[[...path], ...]` form that\n * @tanstack/react-query + @trpc/react-query use under the hood —\n * passing a flat `['integrations']` to `invalidateQueries` directly\n * would never match the actual tRPC key\n * `[['integrations', 'list'], { input, type }]`. Caller doesn't have\n * to know about the wrap.\n *\n * Reconnect resilience: when `System.reconnect()` rebuilds the\n * underlying wsClient + tRPC client, the System reference doesn't\n * change — but `connectionVersion` bumps. We listen via\n * `subscribeConnectionEvents` so the subscription effect re-runs\n * against the freshly-rebuilt tRPC client.\n *\n * Lives in `@camstack/ui-library` (not in admin-ui's hooks folder)\n * because addon widget bundles reach for it through the shared library\n * — the original admin-ui copy stayed put for backward compatibility\n * but new consumers should import from here.\n */\nimport { useEffect, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useSystem } from '../contexts/system-context.js'\n\nexport function useEventInvalidation(\n queryKey: readonly unknown[],\n categories: readonly string[],\n): void {\n const system = useSystem()\n const queryClient = useQueryClient()\n // Mirrors the SDK's `connectionVersion` — bump on every new\n // `'connected'` transition so the subscription effect below re-runs\n // and re-binds to the freshly-rebuilt tRPC client.\n const [tick, setTick] = useState<number>(system.connectionVersion)\n\n useEffect(() => {\n return system.subscribeConnectionEvents((state, version) => {\n if (state === 'connected') setTick(version)\n })\n }, [system])\n\n // Stable joined key so the effect only re-subscribes when the category\n // set actually changes — passing a new array literal each render\n // (common in callers) shouldn't tear down + rebuild the subscription.\n const key = categories.join('|')\n // Stable JSON of queryKey for the same reason.\n const keyJson = JSON.stringify(queryKey)\n useEffect(() => {\n const subs: Array<() => void> = []\n const refresh = (): void => {\n // Wrap once: tRPC keys queries as `[[<router>, <proc>], {input, type}]`\n // so the React-Query prefix we need is `[[<router>, ...]]`. Idempotent —\n // a caller that already wrapped (`[['x']]`) would end up with\n // `[[['x']]]` which still prefix-matches nothing, so we detect that\n // shape and pass-through.\n const raw = JSON.parse(keyJson) as unknown[]\n const alreadyWrapped = raw.length === 1 && Array.isArray(raw[0])\n const queryKeyToInvalidate = alreadyWrapped ? raw : [raw]\n void queryClient.invalidateQueries({ queryKey: queryKeyToInvalidate })\n }\n\n // Trigger an initial invalidation so the cache refetches the\n // moment the subscription is established. Without this, server\n // events fired between the page mount and the WS subscribe (or\n // during a post-login client recreation) leave the cache stale —\n // the operator sees old data until a fresh event eventually fires.\n refresh()\n\n for (const category of key.split('|')) {\n if (!category) continue\n try {\n subs.push(system.subscribeEvent(category, refresh))\n } catch {\n // WS not available or transient subscription failure — skip.\n }\n }\n return () => { for (const unsub of subs) unsub() }\n // `tick` in deps: a System internal reconnect bumps the version,\n // the connection-events listener flips `tick`, this effect re-runs\n // and subscribes against the fresh trpc client.\n }, [system, queryClient, key, keyJson, tick])\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["FormField","import_react","import_react","existing","existing","import_lucide_react","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_class_variance_authority","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","React","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","table","_","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_lucide_react","import_react","trpc","getSnapshot","import_lucide_react","CameraIcon","ImageIcon","import_jsx_runtime","trpc","import_react","import_react_dom","import_lucide_react","import_jsx_runtime","trpc","import_react","import_react_dom","import_react","trpc","import_jsx_runtime","trpc","import_lucide_react","import_jsx_runtime","import_react","import_react_dom","import_lucide_react","trpc","import_react","import_react_query","trpc","import_lucide_react","import_jsx_runtime","import_jsx_runtime","trpc","POPOVER_WIDTH","import_jsx_runtime","import_jsx_runtime","trpc","import_react","import_react_query","import_lucide_react","import_react","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","trpc","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_client","import_react","import_react_query","import_react","import_jsx_runtime","import_jsx_runtime","superjson","trpc","trpc","import_react","import_react","import_lucide_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_react_query","import_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","FormField","import_jsx_runtime","FormField","import_react","import_jsx_runtime","trpc","patch","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_react","import_jsx_runtime","rowKey","ToolbarButton","import_react","import_lucide_react","import_types","import_jsx_runtime","MAX_LIVE_ENTRIES","ScopeBadge","RowCopyButton","import_react","import_lucide_react","import_jsx_runtime","ChildRow","StatusBadge","import_react","import_lucide_react","import_types","import_jsx_runtime","MAX_LIVE_ENTRIES","ScopeBadge","RowCopyButton","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_lucide_react","import_react","import_jsx_runtime","trpc","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","trpc","import_react","trpc","fetch","import_react","trpc","import_react","import_react","import_react_query","import_react","import_react_query"]}