cattle-care-ui 0.1.21 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Button.d.ts +27 -12
- package/dist/components/Calendar.d.ts +23 -0
- package/dist/components/Checkbox.d.ts +8 -0
- package/dist/components/DatePicker.d.ts +33 -0
- package/dist/components/Dropdown.d.ts +40 -4
- package/dist/components/MenuItem.d.ts +3 -1
- package/dist/components/Spinner.d.ts +5 -1
- package/dist/components/Tag.d.ts +35 -6
- package/dist/components/TextArea.d.ts +22 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1129 -491
- package/dist/index.js.map +1 -1
- package/dist/utils/date.d.ts +25 -0
- package/package.json +3 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["__iconData","__iconData","__iconData","__iconData"],"sources":["../src/components/Button.module.css","../src/components/Button.tsx","../src/components/Card.module.css","../src/components/Card.tsx","../src/components/Tag.module.css","../src/components/Tag.tsx","../src/components/TagGroup.module.css","../src/components/OptionGroup.module.css","../src/components/FieldLabel.module.css","../src/components/FieldLabel.tsx","../src/components/TagGroup.tsx","../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toLucideIconData.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/defaultAttributes.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconNode.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconForReact.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs","../node_modules/lucide-react/dist/esm/context.mjs","../node_modules/lucide-react/dist/esm/Icon.mjs","../node_modules/lucide-react/dist/esm/createLucideIcon.mjs","../node_modules/lucide-react/dist/esm/icons/check.mjs","../node_modules/lucide-react/dist/esm/icons/chevron-down.mjs","../node_modules/lucide-react/dist/esm/icons/eye-off.mjs","../node_modules/lucide-react/dist/esm/icons/eye.mjs","../node_modules/lucide-react/dist/esm/icons/search.mjs","../src/components/Toolbar.module.css","../src/components/Toolbar.tsx","../src/components/Checkbox.module.css","../src/components/Checkbox.tsx","../src/components/RadioButton.module.css","../src/components/RadioButton.tsx","../src/components/Switch.module.css","../src/components/Switch.tsx","../src/components/TextField.module.css","../src/components/TextField.tsx","../src/components/PasswordField.tsx","../src/components/DateField.tsx","../src/components/NumberField.module.css","../src/components/NumberField.tsx","../src/components/Menu.module.css","../src/components/Menu.tsx","../src/components/MenuItem.module.css","../src/components/MenuItem.tsx","../src/components/Dropdown.module.css","../src/components/Dropdown.tsx","../src/components/HighlightText.module.css","../src/components/HighlightText.tsx","../src/components/FilterSection.module.css","../src/components/FilterSection.tsx","../src/components/Tabs.module.css","../src/components/Tabs.tsx","../src/components/Toggle.module.css","../src/components/Toggle.tsx","../src/components/Spinner.module.css","../src/components/Spinner.tsx","../src/utils/format.ts"],"sourcesContent":[".primary,\n.secondary,\n.tertiary,\n.dangerous {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: none;\n font-family: inherit;\n font-weight: var(--font-weight-regular);\n letter-spacing: 0.01em;\n cursor: pointer;\n transition:\n color 0.2s ease,\n transform 0.2s ease-out;\n}\n.primary:focus-visible,\n.secondary:focus-visible,\n.tertiary:focus-visible,\n.dangerous:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.primary:active:not(:disabled),\n.secondary:active:not(:disabled),\n.tertiary:active:not(:disabled),\n.dangerous:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n padding: 0 12px;\n font-size: 0.9rem;\n}\n.base {\n height: var(--control-height-base);\n border-radius: var(--radius-base);\n padding: 0 16px;\n font-size: 0.9rem;\n}\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.leadingIcon {\n margin-left: -4px;\n}\n.trailingIcon {\n margin-right: -4px;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n\n.iconOnly {\n box-sizing: border-box;\n padding: 0;\n}\n.iconOnly.sm {\n width: var(--control-height-sm);\n}\n.iconOnly.base {\n width: var(--control-height-base);\n}\n.fullWidth {\n width: 100%;\n}\n.primary::before,\n.secondary::before,\n.tertiary::before,\n.dangerous::before {\n content: '';\n position: absolute;\n left: 50%;\n bottom: 0;\n width: 24%;\n aspect-ratio: 1;\n border-radius: 50%;\n transform: translate(-50%, 100%) scale(1);\n transition: transform 0.3s cubic-bezier(0.39, 0.575, 0.565, 1);\n z-index: -1;\n pointer-events: none;\n}\n.primary:hover::before,\n.secondary:hover::before,\n.tertiary:hover::before,\n.dangerous:hover::before {\n transform: translate(-50%, 15%) scale(8);\n}\n\n.primary {\n background: var(--brand-dark);\n color: #fff;\n font-weight: var(--font-weight-regular);\n letter-spacing: 0.02em;\n}\n.primary::before {\n background: rgba(255, 255, 255, 0.08);\n}\n.primary:active:not(:disabled)::before {\n background: rgba(0, 0, 0, 0.08);\n}\n\n.secondary {\n background: var(--depth-5);\n color: var(--text-primary);\n}\n.secondary .icon {\n color: var(--text-secondary);\n}\n.secondary::before {\n background: rgba(var(--brand-main-rgb), 0.08);\n}\n.secondary:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n.secondary:hover .icon {\n color: var(--brand-main);\n}\n.secondary:hover {\n color: var(--brand-main);\n}\n\n.tertiary {\n background: transparent;\n color: var(--text-secondary);\n}\n.tertiary::before {\n background: rgba(var(--brand-main-rgb), 0.16);\n}\n.tertiary:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n.tertiary:hover,\n.tertiary:active:not(:disabled) {\n background: var(--bg);\n}\n.tertiary:hover {\n color: var(--brand-main);\n}\n\n.dangerous {\n background: var(--danger-bg);\n color: var(--danger-text-dark);\n}\n.dangerous::before {\n background: rgba(var(--danger-rgb), 0.16);\n}\n.dangerous:active:not(:disabled)::before {\n background: rgba(var(--danger-rgb), 0.28);\n}\n\n.primary:disabled,\n.secondary:disabled,\n.tertiary:disabled,\n.dangerous:disabled {\n background: var(--disabled-bg);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.primary:disabled:hover,\n.secondary:disabled:hover,\n.tertiary:disabled:hover,\n.dangerous:disabled:hover {\n color: var(--disabled-text);\n}\n.primary:disabled::before,\n.secondary:disabled::before,\n.tertiary:disabled::before,\n.dangerous:disabled::before {\n display: none;\n}\n","import type { ButtonHTMLAttributes, ReactNode, Ref } from 'react';\nimport styles from './Button.module.css';\n\ntype ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'dangerous';\ntype ButtonSize = 'sm' | 'base';\n\ninterface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Icon shown before the label. Omit `children` to render an icon-only square button — pass `aria-label` in that case. */\n leadingIcon?: ReactNode;\n /** Icon shown after the label. */\n trailingIcon?: ReactNode;\n /** Stretch to the width of the container. */\n fullWidth?: boolean;\n children?: ReactNode;\n /**\n * Extra classes for layout around the button — responsive visibility,\n * positioning, spacing. Appended after the variant classes.\n */\n className?: string;\n ref?: Ref<HTMLButtonElement>;\n}\n\nexport function Button({\n variant = 'primary',\n size = 'base',\n leadingIcon,\n trailingIcon,\n fullWidth,\n children,\n className,\n ref,\n ...rest\n}: ButtonProps) {\n const iconOnly = !children && Boolean(leadingIcon);\n const classes = [\n styles[variant],\n styles[size],\n iconOnly && styles.iconOnly,\n fullWidth && styles.fullWidth,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button ref={ref} type=\"button\" className={classes} {...rest}>\n {leadingIcon && <span className={`${styles.icon} ${iconOnly ? '' : styles.leadingIcon}`.trim()}>{leadingIcon}</span>}\n {children}\n {trailingIcon && <span className={`${styles.icon} ${styles.trailingIcon}`}>{trailingIcon}</span>}\n </button>\n );\n}\n",".wrap {\n position: relative;\n width: 220px;\n flex: 0 0 220px;\n}\n.wrap:hover {\n z-index: 10;\n}\n.fluid {\n width: 100%;\n flex: none;\n}\n\n.backing {\n position: absolute;\n left: 6px;\n right: 6px;\n bottom: -4px;\n height: 10px;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border);\n border-radius: 0 0 14px 14px;\n z-index: 0;\n}\n.backing.completed {\n background: var(--success-bg);\n box-shadow: inset 0 0 0 1px #bfe3cc;\n}\n\n.card {\n position: relative;\n z-index: 1;\n width: 100%;\n box-sizing: border-box;\n background: var(--card-surface);\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 1px 2px rgba(16, 24, 32, 0.04);\n border-radius: 16px;\n padding: 12px 14px;\n cursor: default;\n transition:\n box-shadow 0.2s,\n transform 0.1s;\n}\n.card.interactive {\n cursor: pointer;\n}\n.card.interactive:active {\n transform: scale(0.98, 0.95);\n}\n.card.grabbable {\n cursor: grab;\n}\n.card.grabbable:active {\n cursor: grabbing;\n}\n.card.dragging,\n.card.dragging:hover {\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 1px 2px rgba(16, 24, 32, 0.04);\n}\n.card.interactive:hover {\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 0 0 2px var(--brand-main);\n}\n.card.completed {\n background: var(--success-bg);\n box-shadow:\n inset 0 0 0 1px #bfe3cc,\n 0 1px 2px rgba(16, 24, 32, 0.04),\n 0 2px 8px rgba(16, 24, 32, 0.06);\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Card.module.css';\n\ninterface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {\n /** Shows a second sheet behind the card, for representing a stack/batch. */\n stacked?: boolean;\n /** Success-tinted surface, e.g. a completed task. */\n completed?: boolean;\n /** Adds pointer cursor + accent hover ring. */\n interactive?: boolean;\n /** Grab cursor, for drag sources — pair with `interactive`. */\n draggable?: boolean;\n /** Suppresses the hover ring while a drag is in progress. */\n dragging?: boolean;\n /** Card fills its container width instead of a fixed width. */\n fluid?: boolean;\n children: ReactNode;\n}\n\nexport function Card({\n stacked,\n completed,\n interactive,\n draggable,\n dragging,\n fluid,\n children,\n ...rest\n}: CardProps) {\n return (\n <div className={`${styles.wrap} ${fluid ? styles.fluid : ''}`}>\n {stacked && <div className={`${styles.backing} ${completed ? styles.completed : ''}`} />}\n <div\n className={[\n styles.card,\n completed ? styles.completed : '',\n interactive ? styles.interactive : '',\n draggable ? styles.grabbable : '',\n dragging ? styles.dragging : '',\n ]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n {children}\n </div>\n </div>\n );\n}\n",".neutral,\n.pill,\n.accent,\n.success,\n.danger,\n.count {\n display: inline-flex;\n align-items: center;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n}\n\n/* Square tags — e.g. day badges, worker names, video panel tags */\n.neutral {\n color: var(--text-tertiary);\n font-size: 0.75rem;\n background: var(--depth-5);\n border-radius: 6px;\n padding: 2px 7px;\n}\n\n/* Pill tags — e.g. BPO group labels, total-duration tags */\n.pill {\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border);\n color: var(--text-tertiary);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Accent pill — e.g. \"current\" stat, read-only banner badge */\n.accent {\n background: var(--brand-bg);\n color: var(--brand-dark);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Success pill — e.g. \"time spent\" stat */\n.success {\n background: var(--success-bg);\n color: var(--success-text);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Danger — square (e.g. ASAP tag) reuses the same token pair as the\n pill-shaped status variant; only the shape differs by context. */\n.danger {\n color: var(--danger-text);\n font-size: 0.75rem;\n background: var(--danger-bg);\n border-radius: 6px;\n padding: 2px 7px;\n}\n\n/* Count badge — small solid circle, e.g. active-filter count */\n.count {\n justify-content: center;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--brand-main);\n color: #fff;\n font-size: 0.65rem;\n line-height: 16px;\n text-align: center;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Tag.module.css';\n\ntype TagVariant = 'neutral' | 'pill' | 'accent' | 'success' | 'danger' | 'count';\n\ninterface TagProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'className'> {\n variant?: TagVariant;\n children: ReactNode;\n}\n\nexport function Tag({ variant = 'neutral', children, ...rest }: TagProps) {\n return (\n <span className={styles[variant]} {...rest}>\n {children}\n </span>\n );\n}\n",".group {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n}\n\n.group.sm {\n gap: 6px;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n border: none;\n outline: none;\n font-family: inherit;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n border-radius: 999px;\n cursor: pointer;\n transition:\n background-color 0.15s ease-out,\n color 0.15s ease-out,\n transform 0.1s ease-out;\n background: var(--depth-5);\n color: var(--text-primary);\n}\n\n.group.base .chip {\n height: 36px;\n padding: 0 14px;\n font-size: 0.85rem;\n}\n\n.group.sm .chip {\n height: 24px;\n padding: 0 9px;\n font-size: 0.75rem;\n}\n\n.chip:hover:not(:disabled) {\n background: var(--surface-muted);\n}\n\n.chip:active:not(:disabled) {\n transform: scale(0.95);\n background: var(--surface-muted);\n}\n\n.chip:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n\n.chip.selected {\n background: var(--brand-bg);\n color: var(--brand-main);\n}\n\n.chip.selected:hover:not(:disabled) {\n background: var(--brand-main-20);\n}\n\n.chip.selected:active:not(:disabled) {\n background: var(--brand-main-30);\n}\n\n.chip:disabled {\n background: var(--disabled-bg);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n",".group {\n display: inline-flex;\n flex-direction: column;\n gap: 0;\n}\n\n.groupLabel {\n margin-bottom: 6px;\n}\n",".label {\n font-size: 0.85rem;\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n padding-left: 4px;\n}\n","import type { ReactNode } from 'react';\nimport styles from './FieldLabel.module.css';\n\ninterface FieldLabelProps {\n children: ReactNode;\n /** Pass the id of the control this labels to render a real `<label htmlFor>`. */\n htmlFor?: string;\n className?: string;\n}\n\nexport function FieldLabel({ children, htmlFor, className }: FieldLabelProps) {\n const classes = `${styles.label} ${className ?? ''}`.trim();\n if (htmlFor) {\n return (\n <label className={classes} htmlFor={htmlFor}>\n {children}\n </label>\n );\n }\n return <span className={classes}>{children}</span>;\n}\n","import type { ReactNode } from 'react';\nimport styles from './TagGroup.module.css';\nimport groupStyles from './OptionGroup.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype TagGroupSize = 'sm' | 'base';\n\ninterface TagGroupItem {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\ninterface TagGroupProps {\n items: TagGroupItem[];\n value: string[];\n onChange: (value: string[]) => void;\n size?: TagGroupSize;\n disabled?: boolean;\n label?: ReactNode;\n 'aria-label'?: string;\n}\n\nexport function TagGroup({\n items,\n value,\n onChange,\n size = 'base',\n disabled = false,\n label,\n ...rest\n}: TagGroupProps) {\n function toggle(itemValue: string) {\n const next = value.includes(itemValue)\n ? value.filter((v) => v !== itemValue)\n : [...value, itemValue];\n onChange(next);\n }\n\n const tags = (\n <div\n role=\"group\"\n aria-label={label ? undefined : rest['aria-label']}\n className={`${styles.group} ${styles[size]}`}\n >\n {items.map((item) => {\n const selected = value.includes(item.value);\n const isDisabled = disabled || item.disabled;\n return (\n <button\n key={item.value}\n type=\"button\"\n aria-pressed={selected}\n disabled={isDisabled}\n className={[styles.chip, selected && styles.selected].filter(Boolean).join(' ')}\n onClick={() => !isDisabled && toggle(item.value)}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n\n if (!label) return tags;\n\n return (\n <div className={groupStyles.group} {...rest}>\n <FieldLabel className={groupStyles.groupLabel}>{label}</FieldLabel>\n {tags}\n </div>\n );\n}\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string?.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toKebabCase } from './toKebabCase.mjs';\n\nfunction toLucideIconData(iconName, iconNode, aliases = []) {\n if (iconNode == null) {\n throw new Error(\"[lucide]: iconNode is required when icon name is used\");\n }\n return {\n name: toKebabCase(iconName),\n size: 24,\n node: iconNode,\n ...aliases.length > 0 ? { aliases } : {}\n };\n}\n\nexport { toLucideIconData };\n//# sourceMappingURL=toLucideIconData.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => {\n let out = \"\";\n let upperNext = false;\n for (const ch of string) {\n if (ch === \"-\" || ch === \"_\" || ch <= \" \") {\n upperNext = out.length > 0;\n continue;\n }\n if (out.length === 0) {\n out += ch.toLowerCase();\n } else {\n out += upperNext ? ch.toUpperCase() : ch;\n }\n upperNext = false;\n }\n return out;\n};\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.mjs';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport defaultAttributes from './defaultAttributes.mjs';\nimport { mergeClasses } from '../utils/mergeClasses.mjs';\n\nfunction isDefined(value) {\n return value !== null && value !== void 0;\n}\nfunction buildLucideIconNode(icon, params = {}) {\n const attributeNames = params.attributeNames ?? {};\n const getAttributeName = (attributeName) => attributeNames[attributeName] ?? attributeName;\n const viewBoxWidth = icon.size ?? icon.width ?? defaultAttributes[\"width\"];\n const viewBoxHeight = icon.size ?? icon.height ?? defaultAttributes[\"height\"];\n const aliasClassNames = icon.aliases?.filter((alias) => typeof alias === \"string\" && alias.trim() !== \"\").map((alias) => `lucide-${alias}`) ?? [];\n const iconClassNames = [...icon.name ? [`lucide-${icon.name}`] : [], ...aliasClassNames];\n const classNamesFromClassName = params.className?.split(\" \").filter(Boolean) ?? [];\n const className = params.includeDefaultClasses === false ? mergeClasses(...classNamesFromClassName) : mergeClasses(\"lucide\", ...iconClassNames, ...classNamesFromClassName);\n const calculatedStrokeWidth = params.absoluteStrokeWidth ? Number(params.strokeWidth ?? defaultAttributes[\"stroke-width\"]) * Number(icon.size ?? icon.width ?? defaultAttributes[\"width\"]) / Number(params.size ?? params.width ?? defaultAttributes[\"width\"]) : params.strokeWidth ?? defaultAttributes[\"stroke-width\"];\n const attributes = {\n ...Object.entries(defaultAttributes).reduce((attrs, [attrName, value]) => {\n attrs[getAttributeName(attrName)] = value;\n return attrs;\n }, {}),\n ...\"color\" in params && params.color && {\n [getAttributeName(\"stroke\")]: params.color\n },\n ...\"size\" in params && isDefined(params.size) && {\n [getAttributeName(\"width\")]: params.size,\n [getAttributeName(\"height\")]: params.size\n },\n ...\"width\" in params && isDefined(params.width) && {\n [getAttributeName(\"width\")]: params.width\n },\n ...\"height\" in params && isDefined(params.height) && {\n [getAttributeName(\"height\")]: params.height\n },\n [getAttributeName(\"stroke-width\")]: calculatedStrokeWidth,\n ...className && {\n [getAttributeName(\"class\")]: className\n },\n [getAttributeName(\"viewBox\")]: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,\n ...params.hasA11yProp === false ? {\n [getAttributeName(\"aria-hidden\")]: \"true\"\n } : {},\n ...\"attributes\" in params && params.attributes\n };\n return [\n \"svg\",\n attributes,\n icon.node.map((child) => {\n const [name, attrs, children] = child;\n const nextAttrs = params.nonScalingStroke ? { [getAttributeName(\"vector-effect\")]: \"non-scaling-stroke\", ...attrs } : attrs;\n return children ? [name, nextAttrs, children] : [name, nextAttrs];\n })\n ];\n}\n\nexport { buildLucideIconNode as default };\n//# sourceMappingURL=buildLucideIconNode.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport buildLucideIconNode from './buildLucideIconNode.mjs';\n\nfunction buildLucideIconForReact(icon, params = {}) {\n return buildLucideIconNode(icon, {\n ...params,\n attributeNames: {\n ...params.attributeNames,\n class: \"className\",\n \"stroke-width\": \"strokeWidth\",\n \"stroke-linecap\": \"strokeLinecap\",\n \"stroke-linejoin\": \"strokeLinejoin\",\n \"vector-effect\": \"vectorEffect\"\n }\n });\n}\n\nexport { buildLucideIconForReact as default };\n//# sourceMappingURL=buildLucideIconForReact.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { createContext, useContext, useMemo, createElement } from 'react';\n\nconst LucideContext = createContext({});\nfunction LucideProvider({\n children,\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className\n}) {\n const value = useMemo(\n () => ({\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className\n }),\n [size, color, strokeWidth, absoluteStrokeWidth, nonScalingStroke, className]\n );\n return createElement(LucideContext.Provider, { value }, children);\n}\nconst useLucideContext = () => useContext(LucideContext);\n\nexport { LucideProvider, useLucideContext };\n//# sourceMappingURL=context.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.mjs';\nimport buildLucideIconForReact from './shared/src/build/buildLucideIconForReact.mjs';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.mjs';\nimport { useLucideContext } from './context.mjs';\n\nconst Icon = forwardRef(\n ({\n color,\n size,\n width,\n height,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className = \"\",\n children,\n iconNode = [],\n icon = {\n node: iconNode,\n aliases: [],\n size: 24\n },\n ...rest\n }, ref) => {\n const {\n size: contextSize = 24,\n strokeWidth: contextStrokeWidth = 2,\n absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,\n nonScalingStroke: contextNonScalingStroke = false,\n color: contextColor = \"currentColor\",\n className: contextClass = \"\"\n } = useLucideContext() ?? {};\n const hasAccessibleProp = Boolean(children) || hasA11yProp(rest);\n const [name, svgAttributes, builtIconNode = []] = buildLucideIconForReact(icon, {\n color: color ?? contextColor,\n width: width ?? size ?? contextSize,\n height: height ?? size ?? contextSize,\n strokeWidth: strokeWidth ?? contextStrokeWidth,\n absoluteStrokeWidth: absoluteStrokeWidth ?? contextAbsoluteStrokeWidth,\n nonScalingStroke: nonScalingStroke ?? contextNonScalingStroke,\n className: mergeClasses(contextClass, className),\n hasA11yProp: hasAccessibleProp,\n attributes: rest\n });\n return createElement(\n name,\n {\n ref,\n ...svgAttributes\n },\n [\n ...builtIconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n );\n }\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { toLucideIconData } from './shared/src/utils/toLucideIconData.mjs';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.mjs';\nimport Icon from './Icon.mjs';\n\nfunction createLucideIcon(iconDataOrName, iconNode = [], aliases = []) {\n const iconData = typeof iconDataOrName === \"string\" ? toLucideIconData(iconDataOrName, iconNode, aliases) : iconDataOrName;\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n icon: iconData,\n className,\n ...props\n })\n );\n if (iconData.name) {\n Component.displayName = toPascalCase(iconData.name);\n }\n return Component;\n}\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"check\",\n size: 24,\n node: [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]\n};\n__iconData.node;\nconst Check = createLucideIcon(__iconData);\n\nexport { __iconData, Check as default };\n//# sourceMappingURL=check.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevron-down\",\n size: 24,\n node: [[\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]]\n};\n__iconData.node;\nconst ChevronDown = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronDown as default };\n//# sourceMappingURL=chevron-down.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"eye-off\",\n size: 24,\n node: [\n [\n \"path\",\n {\n 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 key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n 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 key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n ]\n};\n__iconData.node;\nconst EyeOff = createLucideIcon(__iconData);\n\nexport { __iconData, EyeOff as default };\n//# sourceMappingURL=eye-off.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"eye\",\n size: 24,\n node: [\n [\n \"path\",\n {\n 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 key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n ]\n};\n__iconData.node;\nconst Eye = createLucideIcon(__iconData);\n\nexport { __iconData, Eye as default };\n//# sourceMappingURL=eye.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"search\",\n size: 24,\n node: [\n [\"path\", { d: \"m21 21-4.34-4.34\", key: \"14j7rj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }]\n ]\n};\n__iconData.node;\nconst Search = createLucideIcon(__iconData);\n\nexport { __iconData, Search as default };\n//# sourceMappingURL=search.mjs.map\n",".toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 0 8px;\n background: var(--card-surface);\n border-radius: 16px;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 1px 2px rgba(16, 24, 32, 0.04),\n 0 2px 8px rgba(16, 24, 32, 0.06);\n}\n.searchWrap {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n.searchWrap::after {\n content: '';\n position: absolute;\n left: 36px;\n right: 0;\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n opacity: 0;\n pointer-events: none;\n}\n.searchWrap:focus-within::after {\n opacity: 1;\n}\n.searchIcon {\n position: absolute;\n top: 50%;\n left: 12px;\n width: 16px;\n height: 16px;\n transform: translateY(-53%);\n color: var(--text-tertiary);\n pointer-events: none;\n}\n.searchIcon svg {\n width: 100%;\n height: 100%;\n}\n.search {\n width: 100%;\n box-sizing: border-box;\n border: none;\n padding: 16px 52px 16px 36px;\n font-family: inherit;\n font-size: 1rem;\n color: var(--text-primary);\n background: none;\n box-shadow: inset -1px 0 0 var(--border);\n}\n.search:focus {\n outline: none;\n}\n.searchShortcut {\n position: absolute;\n top: 50%;\n right: 8px;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 6px;\n background: var(--bg);\n color: var(--text-tertiary);\n font-size: 0.75rem;\n font-weight: var(--font-weight-semibold);\n letter-spacing: 0.02em;\n pointer-events: none;\n}\n.controls {\n display: flex;\n align-items: center;\n flex: none;\n}\n","import { useEffect, useRef, type ChangeEvent, type ReactNode } from 'react';\nimport { Search } from 'lucide-react';\nimport styles from './Toolbar.module.css';\n\ninterface ToolbarProps {\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n placeholder?: string;\n /** Text shown in the keyboard-shortcut badge, e.g. \"⌘K\". Omit to hide the badge. */\n shortcutLabel?: string;\n /** Focuses the search input when Cmd/Ctrl + the shortcut key is pressed. */\n shortcutKey?: string;\n /** Right-side content — filter/sort controls, actions, etc. */\n children?: ReactNode;\n}\n\nexport function Toolbar({\n searchValue,\n onSearchChange,\n placeholder = 'Search…',\n shortcutLabel = '⌘K',\n shortcutKey = 'k',\n children,\n}: ToolbarProps) {\n const searchRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === shortcutKey.toLowerCase()) {\n e.preventDefault();\n searchRef.current?.focus();\n }\n }\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [shortcutKey]);\n\n return (\n <div className={styles.toolbar}>\n <div className={styles.searchWrap}>\n <span className={styles.searchIcon}>\n <Search />\n </span>\n <input\n ref={searchRef}\n type=\"text\"\n className={styles.search}\n placeholder={placeholder}\n autoComplete=\"off\"\n value={searchValue}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onSearchChange?.(e.target.value)}\n />\n {shortcutLabel && (\n <span className={styles.searchShortcut} aria-hidden=\"true\">\n {shortcutLabel}\n </span>\n )}\n </div>\n {children && <div className={styles.controls}>{children}</div>}\n </div>\n );\n}\n",".checkbox {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n padding: 8px 4px;\n}\n.control {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.labelText {\n font-size: 0.85rem;\n color: var(--text-primary);\n transition: color 0.2s ease-out;\n}\n.checkbox:hover .labelText {\n color: var(--brand-main);\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.box {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 6px;\n background: var(--depth-5);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1),\n transform 0.1s cubic-bezier(0, 0, 0.2, 1);\n}\n.checkbox:hover .box {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .box {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:active + .box {\n transform: scale(0.88);\n}\n.input:checked + .box {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.checkbox:hover .input:checked + .box {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.icon {\n width: 10px;\n height: 10px;\n overflow: visible;\n}\n.icon polyline {\n fill: none;\n stroke: #fff;\n stroke-width: 2.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-dasharray: 22px;\n stroke-dashoffset: 22px;\n transition: stroke-dashoffset 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .box .icon polyline {\n stroke-dashoffset: 0px;\n}\n.checkbox:has(.input:disabled),\n.input:disabled {\n cursor: not-allowed;\n}\n.checkbox:has(.input:disabled) .labelText {\n color: var(--disabled-text);\n}\n.checkbox:has(.input:disabled) .box {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n transform: none;\n}\n.checkbox:has(.input:disabled) .input:checked + .box {\n background: var(--disabled-bg);\n box-shadow: inset 0 0 0 1px var(--disabled-bg);\n}\n","import type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport styles from './Checkbox.module.css';\nimport groupStyles from './OptionGroup.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ninterface CheckboxProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur?: (e: FocusEvent<HTMLInputElement>) => void;\n name?: string;\n label?: ReactNode;\n ariaLabel?: string;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\nexport function Checkbox({\n checked,\n onChange,\n onBlur,\n name,\n label,\n ariaLabel,\n disabled,\n className,\n ref,\n}: CheckboxProps) {\n return (\n <label className={`${styles.checkbox} ${className ?? ''}`}>\n <span className={styles.control}>\n <input\n ref={ref}\n type=\"checkbox\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n onBlur={onBlur}\n name={name}\n aria-label={ariaLabel}\n disabled={disabled}\n />\n <span className={styles.box}>\n <svg className={styles.icon} viewBox=\"0 0 17 18\" aria-hidden=\"true\">\n <polyline points=\"1 9 7 14 15 4\" />\n </svg>\n </span>\n </span>\n {label && <span className={styles.labelText}>{label}</span>}\n </label>\n );\n}\n\ninterface CheckboxGroupItem {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\ninterface CheckboxGroupProps {\n label?: ReactNode;\n items: CheckboxGroupItem[];\n value: string[];\n onChange: (value: string[]) => void;\n disabled?: boolean;\n 'aria-label'?: string;\n}\n\nexport function CheckboxGroup({ label, items, value, onChange, disabled, ...rest }: CheckboxGroupProps) {\n function toggle(itemValue: string) {\n const next = value.includes(itemValue)\n ? value.filter((v) => v !== itemValue)\n : [...value, itemValue];\n onChange(next);\n }\n\n return (\n <div role=\"group\" aria-label={label ? undefined : rest['aria-label']} className={groupStyles.group}>\n {label && <FieldLabel className={groupStyles.groupLabel}>{label}</FieldLabel>}\n {items.map((item) => (\n <Checkbox\n key={item.value}\n checked={value.includes(item.value)}\n onChange={() => toggle(item.value)}\n label={item.label}\n disabled={disabled || item.disabled}\n />\n ))}\n </div>\n );\n}\n",".radio {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n padding: 8px 4px;\n}\n.control {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.labelText {\n font-size: 0.85rem;\n color: var(--text-primary);\n transition: color 0.2s ease-out;\n}\n.radio:hover .labelText {\n color: var(--brand-main);\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.circle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--depth-5);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1),\n transform 0.1s cubic-bezier(0, 0, 0.2, 1);\n}\n.radio:hover .circle {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .circle {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:active + .circle {\n transform: scale(0.88);\n}\n.input:checked + .circle {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.radio:hover .input:checked + .circle {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #fff;\n transform: scale(0);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .circle .dot {\n transform: scale(1);\n}\n.radio:has(.input:disabled),\n.input:disabled {\n cursor: not-allowed;\n}\n.radio:has(.input:disabled) .labelText {\n color: var(--disabled-text);\n}\n.radio:has(.input:disabled) .circle {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n transform: none;\n}\n.radio:has(.input:disabled) .input:checked + .circle {\n background: var(--disabled-bg);\n box-shadow: inset 0 0 0 1px var(--disabled-bg);\n}\n","import type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport styles from './RadioButton.module.css';\nimport groupStyles from './OptionGroup.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ninterface RadioButtonProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur?: (e: FocusEvent<HTMLInputElement>) => void;\n name?: string;\n value?: string;\n label?: ReactNode;\n ariaLabel?: string;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\nexport function RadioButton({\n checked,\n onChange,\n onBlur,\n name,\n value,\n label,\n ariaLabel,\n disabled,\n className,\n ref,\n}: RadioButtonProps) {\n return (\n <label className={`${styles.radio} ${className ?? ''}`}>\n <span className={styles.control}>\n <input\n ref={ref}\n type=\"radio\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n onBlur={onBlur}\n name={name}\n value={value}\n aria-label={ariaLabel}\n disabled={disabled}\n />\n <span className={styles.circle}>\n <span className={styles.dot} />\n </span>\n </span>\n {label && <span className={styles.labelText}>{label}</span>}\n </label>\n );\n}\n\ninterface RadioGroupItem {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\ninterface RadioGroupProps {\n label?: ReactNode;\n name: string;\n items: RadioGroupItem[];\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n 'aria-label'?: string;\n}\n\nexport function RadioGroup({ label, name, items, value, onChange, disabled, ...rest }: RadioGroupProps) {\n return (\n <div\n role=\"radiogroup\"\n aria-label={label ? undefined : rest['aria-label']}\n className={groupStyles.group}\n >\n {label && <FieldLabel className={groupStyles.groupLabel}>{label}</FieldLabel>}\n {items.map((item) => (\n <RadioButton\n key={item.value}\n name={name}\n value={item.value}\n checked={value === item.value}\n onChange={() => onChange(item.value)}\n label={item.label}\n disabled={disabled || item.disabled}\n />\n ))}\n </div>\n );\n}\n",".switch {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n}\n.switch:has(.input:disabled) {\n cursor: not-allowed;\n}\n.control {\n position: relative;\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.input:disabled {\n cursor: not-allowed;\n}\n.track {\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 999px;\n background: var(--depth-5);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1);\n}\n.switch:hover .track {\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .track {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:checked + .track {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.input:disabled + .track {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n}\n.thumb {\n position: absolute;\n top: 50%;\n left: 2px;\n border-radius: 50%;\n background: #fff;\n transform: translateY(-50%);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .track .thumb {\n transform: translateY(-50%) translateX(var(--switch-thumb-travel));\n}\n\n.sm {\n width: 32px;\n height: 18px;\n --switch-thumb-travel: 14px;\n}\n.sm .thumb {\n width: 14px;\n height: 14px;\n}\n.base {\n width: 40px;\n height: 22px;\n --switch-thumb-travel: 18px;\n}\n.base .thumb {\n width: 18px;\n height: 18px;\n}\n\n.labelText {\n font-size: 0.85rem;\n color: var(--text-primary);\n transition: color 0.2s ease-out;\n}\n.switch:hover .labelText {\n color: var(--brand-main);\n}\n.switch:has(.input:disabled) .labelText {\n color: var(--disabled-text);\n}\n","import type { ChangeEvent, ReactNode } from 'react';\nimport styles from './Switch.module.css';\n\ntype SwitchSize = 'sm' | 'base';\n\ninterface SwitchProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n size?: SwitchSize;\n label?: ReactNode;\n ariaLabel?: string;\n disabled?: boolean;\n className?: string;\n}\n\nexport function Switch({\n checked,\n onChange,\n size = 'base',\n label,\n ariaLabel,\n disabled,\n className,\n}: SwitchProps) {\n return (\n <label className={`${styles.switch} ${className ?? ''}`}>\n <span className={`${styles.control} ${styles[size]}`}>\n <input\n type=\"checkbox\"\n role=\"switch\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n aria-label={ariaLabel}\n disabled={disabled}\n />\n <span className={styles.track}>\n <span className={styles.thumb} />\n </span>\n </span>\n {label && <span className={styles.labelText}>{label}</span>}\n </label>\n );\n}\n",".field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.inputWrap {\n position: relative;\n display: flex;\n align-items: center;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n transition: box-shadow 0.2s ease-out;\n}\n.inputWrap:focus-within {\n box-shadow:\n inset 0 0 0 0 var(--border-input),\n 0 0 0 2px var(--brand-main);\n}\n.errorWrap,\n.errorWrap:focus-within {\n box-shadow: inset 0 0 0 1px var(--danger-text);\n}\n.inputWrap:has(.input:disabled) {\n background: var(--surface-muted);\n}\n\n.toolbar {\n background: none;\n box-shadow: none;\n}\n.toolbar::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n opacity: 0;\n transition: opacity 0.2s ease-out;\n}\n.toolbar:focus-within {\n box-shadow: none;\n}\n.toolbar:focus-within::after {\n opacity: 1;\n}\n.toolbar.errorWrap,\n.toolbar.errorWrap:focus-within {\n box-shadow: none;\n}\n.toolbar.errorWrap::after {\n background: var(--danger-text);\n opacity: 1;\n}\n\n.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n}\n.sm .input {\n padding: 0 12px;\n font-size: 0.9rem;\n}\n.base {\n height: var(--control-height-base);\n border-radius: var(--radius-base);\n}\n.base .input {\n padding: 0 14px;\n font-size: 0.9rem;\n}\n.inputWrap:has(.icon) .input {\n padding-left: 8px;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 12px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n background: none;\n font-family: inherit;\n color: var(--text-primary);\n font-weight: var(--font-weight-regular);\n}\n.input:focus {\n outline: none;\n}\n.input::placeholder {\n color: var(--text-tertiary);\n}\n.input:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n.trailing {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n margin-right: 6px;\n padding: 0;\n border: none;\n border-radius: 8px;\n background: none;\n color: var(--text-tertiary);\n cursor: pointer;\n flex-shrink: 0;\n transition: color 0.15s ease-out, background 0.15s ease-out;\n}\n.trailing svg {\n width: 16px;\n height: 16px;\n}\n.trailing:hover:not(:disabled) {\n color: var(--brand-main);\n background: var(--brand-main-5);\n}\n.trailing:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: -2px;\n}\n.trailing:disabled {\n cursor: not-allowed;\n}\n.pickerInput {\n cursor: pointer;\n caret-color: transparent;\n}\n.pickerInput:disabled {\n cursor: not-allowed;\n}\n","import { useId, type InputHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport styles from './TextField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype TextFieldSize = 'sm' | 'base';\ntype TextFieldVariant = 'default' | 'toolbar';\n\ninterface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: TextFieldSize;\n variant?: TextFieldVariant;\n leadingIcon?: ReactNode;\n /** Extra classes for layout around the field — width, flex growth. Appended after its own class. */\n className?: string;\n /** Reaches the <input>, e.g. for a form library to focus a field that failed validation. */\n ref?: Ref<HTMLInputElement>;\n}\n\nexport function TextField({\n label,\n helperText,\n error,\n size = 'base',\n variant = 'default',\n leadingIcon,\n id,\n className,\n ref,\n ...rest\n}: TextFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div\n className={`${styles.inputWrap} ${styles[variant]} ${styles[size]} ${error ? styles.errorWrap : ''}`}\n >\n {leadingIcon && <span className={styles.icon}>{leadingIcon}</span>}\n <input ref={ref} id={inputId} className={styles.input} {...rest} />\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n","import { useId, useState, type InputHTMLAttributes, type Ref } from 'react';\nimport { Eye, EyeOff } from 'lucide-react';\nimport styles from './TextField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype PasswordFieldSize = 'sm' | 'base';\n\ninterface PasswordFieldProps\n extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size' | 'type'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: PasswordFieldSize;\n /** Accessible name of the toggle while the value is hidden. */\n showLabel?: string;\n /** Accessible name of the toggle while the value is shown. */\n hideLabel?: string;\n /** Start with the value shown. */\n defaultVisible?: boolean;\n /** Extra classes for layout around the field. */\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/** A text field for passwords and PINs, with a button that shows or hides what was typed. */\nexport function PasswordField({\n label,\n helperText,\n error,\n size = 'base',\n showLabel = 'Show password',\n hideLabel = 'Hide password',\n defaultVisible = false,\n id,\n className,\n ref,\n disabled,\n ...rest\n}: PasswordFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const [visible, setVisible] = useState(defaultVisible);\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div className={`${styles.inputWrap} ${styles.default} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n <input\n ref={ref}\n id={inputId}\n className={styles.input}\n type={visible ? 'text' : 'password'}\n autoComplete=\"off\"\n disabled={disabled}\n {...rest}\n />\n <button\n type=\"button\"\n className={styles.trailing}\n aria-label={visible ? hideLabel : showLabel}\n aria-pressed={visible}\n aria-controls={inputId}\n disabled={disabled}\n onClick={() => setVisible((v) => !v)}\n >\n {visible ? <EyeOff /> : <Eye />}\n </button>\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n","import { useId, useRef, type InputHTMLAttributes, type Ref } from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport styles from './TextField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype DateFieldSize = 'sm' | 'base';\n\ninterface DateFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: DateFieldSize;\n /** Accessible name of the button next to the date. */\n openLabel?: string;\n /** Extra classes for layout around the field. */\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/**\n * Shows a picked date and opens a calendar on click. It renders no calendar\n * itself: pass it as the input of a date picker (e.g. react-datepicker's\n * `customInput`), which supplies `value`, `onClick` and `ref`.\n */\nexport function DateField({\n label,\n helperText,\n error,\n size = 'base',\n openLabel = 'Open calendar',\n id,\n className,\n ref,\n onClick,\n disabled,\n ...rest\n}: DateFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n function setRefs(el: HTMLInputElement | null) {\n inputRef.current = el;\n if (typeof ref === 'function') ref(el);\n else if (ref) ref.current = el;\n }\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div className={`${styles.inputWrap} ${styles.default} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n <input\n {...rest}\n ref={setRefs}\n id={inputId}\n className={`${styles.input} ${styles.pickerInput}`}\n inputMode=\"none\"\n readOnly\n disabled={disabled}\n onClick={onClick}\n />\n <button\n type=\"button\"\n tabIndex={-1}\n className={styles.trailing}\n aria-label={openLabel}\n disabled={disabled}\n onClick={() => inputRef.current?.click()}\n >\n <ChevronDown />\n </button>\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n",".field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.inputWrap {\n position: relative;\n display: flex;\n align-items: center;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n transition: box-shadow 0.2s ease-out;\n}\n.inputWrap:focus-within {\n box-shadow:\n inset 0 0 0 0 var(--border-input),\n 0 0 0 2px var(--brand-main);\n}\n.errorWrap,\n.errorWrap:focus-within {\n box-shadow: inset 0 0 0 1px var(--danger-text);\n}\n.inputWrap:has(.input:disabled) {\n background: var(--surface-muted);\n}\n\n.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n}\n.sm .input {\n padding: 0 8px;\n font-size: 0.85rem;\n}\n.base {\n height: var(--control-height-base);\n border-radius: var(--radius-base);\n}\n.base .input {\n padding: 0 10px;\n font-size: 0.9rem;\n}\n.inputWrap:has(.prefix) .input {\n padding-left: 4px;\n}\n.inputWrap:has(.suffix) .input {\n padding-right: 4px;\n}\n\n.prefix,\n.suffix {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--text-tertiary);\n font-size: 0.78rem;\n white-space: nowrap;\n}\n.prefix {\n margin-left: 10px;\n}\n.suffix {\n margin-right: 10px;\n}\n\n.input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n background: none;\n font-family: inherit;\n color: var(--text-primary);\n font-weight: var(--font-weight-regular);\n font-variant-numeric: tabular-nums;\n appearance: textfield;\n -moz-appearance: textfield;\n}\n.input::-webkit-outer-spin-button,\n.input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n.input:focus {\n outline: none;\n}\n.input::placeholder {\n color: var(--text-tertiary);\n}\n.input:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n","import { useId, type InputHTMLAttributes, type ReactNode } from 'react';\nimport styles from './NumberField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype NumberFieldSize = 'sm' | 'base';\n\ninterface NumberFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size' | 'prefix'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: NumberFieldSize;\n /** Rendered inline before the value, e.g. \"$\". */\n prefix?: ReactNode;\n /** Rendered inline after the value, e.g. \"cows\", \"/cwt\". */\n suffix?: ReactNode;\n}\n\nexport function NumberField({\n label,\n helperText,\n error,\n size = 'base',\n prefix,\n suffix,\n id,\n ...rest\n}: NumberFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <div className={styles.field}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div className={`${styles.inputWrap} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n {prefix && <span className={styles.prefix}>{prefix}</span>}\n <input id={inputId} className={styles.input} {...rest} />\n {suffix && <span className={styles.suffix}>{suffix}</span>}\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n",".menu {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 180px;\n width: fit-content;\n padding: 4px;\n box-sizing: border-box;\n background: var(--card-surface);\n border-radius: 12px;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px rgba(0, 0, 0, 0.12);\n}\n.divider {\n height: 1px;\n background: var(--border);\n margin: 4px 6px;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Menu.module.css';\n\ninterface MenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {\n children: ReactNode;\n}\n\nexport function Menu({ children, ...rest }: MenuProps) {\n return (\n <div role=\"menu\" className={styles.menu} {...rest}>\n {children}\n </div>\n );\n}\n\nexport function MenuDivider() {\n return <div className={styles.divider} role=\"separator\" />;\n}\n",".item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n min-height: var(--control-height-sm);\n box-sizing: border-box;\n border: none;\n background: none;\n border-radius: 8px;\n padding: 8px 12px;\n font-family: inherit;\n font-size: 0.9rem;\n color: var(--text-primary);\n text-align: left;\n cursor: pointer;\n transition:\n background 0.15s ease-out,\n color 0.15s ease-out;\n}\n.item:hover:not(:disabled) {\n background: var(--brand-bg);\n color: var(--brand-dark);\n}\n.item:hover:not(:disabled) .icon,\n.item:hover:not(:disabled) .check {\n color: var(--brand-dark);\n}\n.item:active:not(:disabled) {\n background: var(--brand-main-20);\n}\n.item:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: -2px;\n}\n.item:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: -2px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.trailing {\n color: var(--text-tertiary);\n font-size: 0.8rem;\n margin-right: -2px;\n flex-shrink: 0;\n}\n.selected {\n background: var(--depth-5);\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n.selected .icon {\n color: var(--text-primary);\n}\n.check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 8px;\n color: var(--text-primary);\n flex-shrink: 0;\n}\n.selected .check {\n color: var(--brand-main);\n}\n.check svg {\n width: 100%;\n height: 100%;\n}\n.destructive {\n color: var(--danger-text);\n}\n.destructive .icon {\n color: var(--danger-text);\n}\n.destructive:hover:not(:disabled) {\n background: var(--danger-bg);\n color: var(--danger-text);\n}\n.destructive:hover:not(:disabled) .icon {\n color: var(--danger-text);\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport { Check } from 'lucide-react';\nimport styles from './MenuItem.module.css';\n\ninterface MenuItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n icon?: ReactNode;\n trailing?: ReactNode;\n selected?: boolean;\n destructive?: boolean;\n children: ReactNode;\n}\n\nexport function MenuItem({ icon, trailing, selected, destructive, children, ...rest }: MenuItemProps) {\n const classes = [styles.item, selected && styles.selected, destructive && styles.destructive]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button type=\"button\" role=\"menuitem\" className={classes} {...rest}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{children}</span>\n {trailing && <span className={styles.trailing}>{trailing}</span>}\n {selected && (\n <span className={styles.check}>\n <Check />\n </span>\n )}\n </button>\n );\n}\n",".field {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.trigger {\n display: flex;\n align-items: center;\n width: 100%;\n box-sizing: border-box;\n border: none;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n font-family: inherit;\n color: var(--text-primary);\n cursor: pointer;\n transition: box-shadow 0.2s ease-out;\n}\n.trigger:focus-visible {\n box-shadow:\n inset 0 0 0 0 var(--border-input),\n 0 0 0 2px var(--brand-main);\n}\n.errorWrap {\n box-shadow: inset 0 0 0 1px var(--danger-text);\n}\n.trigger:disabled {\n background: var(--surface-muted);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n\n.sm {\n border-radius: var(--radius-sm);\n}\n.sm.trigger {\n height: var(--control-height-sm);\n padding: 0 12px;\n font-size: 0.9rem;\n}\n.base {\n border-radius: var(--radius-base);\n}\n.base.trigger {\n height: var(--control-height-base);\n padding: 0 14px;\n font-size: 0.9rem;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-right: 8px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.value {\n flex: 1;\n min-width: 0;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.placeholder {\n color: var(--text-tertiary);\n}\n.chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 8px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n transition: transform 0.15s ease-out;\n}\n.chevron svg {\n width: 100%;\n height: 100%;\n}\n.chevronOpen {\n transform: rotate(180deg);\n}\n\n.menuWrap {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n z-index: 10;\n}\n.menuWrapUp {\n top: auto;\n bottom: calc(100% + 4px);\n}\n.list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 320px;\n overflow-y: auto;\n}\n.search {\n width: 100%;\n height: var(--control-height-sm);\n box-sizing: border-box;\n margin-bottom: 4px;\n padding: 0 10px;\n border: none;\n border-radius: 8px;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n font-family: inherit;\n font-size: 0.9rem;\n color: var(--text-primary);\n outline: none;\n}\n.search:focus {\n box-shadow: inset 0 0 0 1.5px var(--brand-main);\n}\n.noResults {\n padding: 8px 12px;\n font-size: 0.9rem;\n color: var(--text-tertiary);\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n","import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ChangeEvent,\n type KeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { Menu } from './Menu';\nimport { MenuItem } from './MenuItem';\nimport { FieldLabel } from './FieldLabel';\nimport styles from './Dropdown.module.css';\n\ntype DropdownSize = 'sm' | 'base';\n\ninterface DropdownOption<T extends string> {\n value: T;\n label: ReactNode;\n icon?: ReactNode;\n disabled?: boolean;\n /** Text matched by search when `label` is not a plain string. */\n searchText?: string;\n}\n\ninterface DropdownProps<T extends string> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: DropdownSize;\n placeholder?: string;\n options: DropdownOption<T>[];\n value?: T;\n onChange: (value: T) => void;\n disabled?: boolean;\n /** Show a search field at the top of the open menu that filters options by their text. */\n searchable?: boolean;\n /** Placeholder for the search field. */\n searchPlaceholder?: string;\n /** Shown in place of the options when a search matches nothing. */\n noResultsText?: ReactNode;\n /** Open the menu on first render. */\n defaultOpen?: boolean;\n /** Focus the trigger on first render. */\n autoFocus?: boolean;\n /**\n * Extra classes for layout around the field — width, responsive sizing.\n * Appended after the field's own class.\n */\n className?: string;\n /** Extra classes for the label, e.g. to hide it below a breakpoint. */\n labelClassName?: string;\n /** Accessible name when there is no visible `label`. */\n 'aria-label'?: string;\n 'data-testid'?: string;\n}\n\nfunction optionText(opt: DropdownOption<string>): string {\n if (opt.searchText !== undefined) return opt.searchText;\n return typeof opt.label === 'string' || typeof opt.label === 'number' ? String(opt.label) : '';\n}\n\nexport function Dropdown<T extends string>({\n label,\n helperText,\n error,\n size = 'base',\n placeholder = 'Select…',\n options,\n value,\n onChange,\n disabled,\n searchable,\n searchPlaceholder = 'Search…',\n noResultsText = 'No matches',\n defaultOpen = false,\n autoFocus,\n className,\n labelClassName,\n 'aria-label': ariaLabel,\n 'data-testid': dataTestId,\n}: DropdownProps<T>) {\n const [open, setOpen] = useState(defaultOpen);\n const [query, setQuery] = useState('');\n const [openUpward, setOpenUpward] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const searchRef = useRef<HTMLInputElement>(null);\n const triggerId = useId();\n const listboxId = useId();\n\n const selected = options.find((opt) => opt.value === value);\n const trimmedQuery = query.trim().toLowerCase();\n const visibleOptions =\n searchable && trimmedQuery\n ? options.filter((opt) => optionText(opt).toLowerCase().includes(trimmedQuery))\n : options;\n const enabledValues = visibleOptions.filter((opt) => !opt.disabled).map((opt) => opt.value);\n\n function close() {\n setOpen(false);\n setQuery('');\n }\n\n // Searchable menus focus the search field; others focus the selected (or first) option.\n useEffect(() => {\n if (!open) return;\n if (searchable) {\n searchRef.current?.focus();\n return;\n }\n const focusValue = value ?? enabledValues[0];\n const el = rootRef.current?.querySelector<HTMLButtonElement>(`[data-value=\"${focusValue}\"]`);\n el?.focus();\n }, [open]);\n\n // Open upward when there is not enough room below and more room above.\n useLayoutEffect(() => {\n if (!open || !menuRef.current || !rootRef.current) {\n setOpenUpward(false);\n return;\n }\n const rootRect = rootRef.current.getBoundingClientRect();\n const menuHeight = menuRef.current.getBoundingClientRect().height;\n const spaceBelow = window.innerHeight - rootRect.bottom;\n const spaceAbove = rootRect.top;\n setOpenUpward(spaceBelow < menuHeight + 8 && spaceAbove > spaceBelow);\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n function onPointerDown(e: PointerEvent) {\n if (!rootRef.current?.contains(e.target as Node)) close();\n }\n function onKeyDown(e: globalThis.KeyboardEvent) {\n if (e.key === 'Escape') {\n close();\n triggerRef.current?.focus();\n }\n }\n window.addEventListener('pointerdown', onPointerDown);\n window.addEventListener('keydown', onKeyDown);\n return () => {\n window.removeEventListener('pointerdown', onPointerDown);\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n function focusOption(optionValue: T | undefined) {\n if (optionValue === undefined) return;\n rootRef.current?.querySelector<HTMLButtonElement>(`[data-value=\"${optionValue}\"]`)?.focus();\n }\n\n function handleTriggerKeyDown(e: KeyboardEvent<HTMLButtonElement>) {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setOpen(true);\n }\n }\n\n function handleSearchKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n focusOption(enabledValues[0]);\n }\n if (e.key === 'Enter' && enabledValues.length === 1) {\n e.preventDefault();\n select(enabledValues[0]);\n }\n }\n\n function handleOptionKeyDown(e: KeyboardEvent<HTMLButtonElement>, currentValue: T) {\n const currentIndex = enabledValues.indexOf(currentValue);\n if (currentIndex === -1) return;\n\n let nextIndex: number | null = null;\n if (e.key === 'ArrowDown') nextIndex = (currentIndex + 1) % enabledValues.length;\n if (e.key === 'ArrowUp') {\n if (searchable && currentIndex === 0) {\n e.preventDefault();\n searchRef.current?.focus();\n return;\n }\n nextIndex = (currentIndex - 1 + enabledValues.length) % enabledValues.length;\n }\n if (e.key === 'Home') nextIndex = 0;\n if (e.key === 'End') nextIndex = enabledValues.length - 1;\n\n if (nextIndex !== null) {\n e.preventDefault();\n focusOption(enabledValues[nextIndex]);\n }\n }\n\n function select(optionValue: T) {\n onChange(optionValue);\n close();\n triggerRef.current?.focus();\n }\n\n return (\n <div\n className={[styles.field, className].filter(Boolean).join(' ')}\n ref={rootRef}\n data-testid={dataTestId}\n >\n {label && (\n <FieldLabel htmlFor={triggerId} className={labelClassName}>\n {label}\n </FieldLabel>\n )}\n <button\n ref={triggerRef}\n id={triggerId}\n type=\"button\"\n role=\"combobox\"\n className={`${styles.trigger} ${styles[size]} ${error ? styles.errorWrap : ''}`}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={open ? listboxId : undefined}\n aria-label={label ? undefined : ariaLabel}\n autoFocus={autoFocus}\n disabled={disabled}\n onClick={() => (open ? close() : setOpen(true))}\n onKeyDown={handleTriggerKeyDown}\n >\n {selected?.icon && <span className={styles.icon}>{selected.icon}</span>}\n <span className={`${styles.value} ${!selected ? styles.placeholder : ''}`}>\n {selected ? selected.label : placeholder}\n </span>\n <span className={`${styles.chevron} ${open ? styles.chevronOpen : ''}`}>\n <ChevronDown />\n </span>\n </button>\n {open && (\n <div ref={menuRef} className={`${styles.menuWrap} ${openUpward ? styles.menuWrapUp : ''}`}>\n <Menu role=\"presentation\" style={{ width: '100%' }}>\n {searchable && (\n <input\n ref={searchRef}\n type=\"text\"\n className={styles.search}\n value={query}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n aria-controls={listboxId}\n autoComplete=\"off\"\n spellCheck={false}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setQuery(e.target.value)}\n onKeyDown={handleSearchKeyDown}\n />\n )}\n <div id={listboxId} role=\"listbox\" aria-label={label ?? ariaLabel} className={styles.list}>\n {visibleOptions.length === 0 ? (\n <div className={styles.noResults} role=\"presentation\">\n {noResultsText}\n </div>\n ) : (\n visibleOptions.map((opt) => (\n <MenuItem\n key={opt.value}\n data-value={opt.value}\n role=\"option\"\n aria-selected={opt.value === value}\n icon={opt.icon}\n selected={opt.value === value}\n disabled={opt.disabled}\n onClick={() => select(opt.value)}\n onKeyDown={(e) => handleOptionKeyDown(e, opt.value)}\n >\n {opt.label}\n </MenuItem>\n ))\n )}\n </div>\n </Menu>\n </div>\n )}\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n",".highlight {\n background: var(--brand-bg);\n color: var(--brand-dark);\n border-radius: 3px;\n padding: 0 1px;\n}\n","import { Fragment } from 'react';\nimport styles from './HighlightText.module.css';\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function HighlightText({ text, query }: { text: string; query: string }) {\n if (!query) return <>{text}</>;\n\n const parts = text.split(new RegExp(`(${escapeRegExp(query)})`, 'ig'));\n return (\n <>\n {parts.map((part, i) =>\n part.toLowerCase() === query.toLowerCase() ? (\n <mark key={i} className={styles.highlight}>\n {part}\n </mark>\n ) : (\n <Fragment key={i}>{part}</Fragment>\n ),\n )}\n </>\n );\n}\n",".group {\n position: relative;\n}\n.btn {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-radius: 12px;\n padding: 12px;\n font-family: inherit;\n font-size: 1rem;\n color: var(--text-primary);\n cursor: pointer;\n transition:\n background 0.2s ease-out,\n box-shadow 0.2s ease-out,\n transform 0.2s ease-out;\n}\n.btn:hover {\n background: rgba(10, 10, 11, 0.04);\n}\n.btn:active {\n background: var(--brand-bg);\n box-shadow: inset 0 2px 1px 0 rgba(0, 140, 216, 0.25);\n transform: scale(0.95);\n}\n.caret {\n color: var(--text-tertiary);\n display: flex;\n align-items: center;\n}\n.caret svg {\n width: 14px;\n height: 14px;\n}\n.label {\n color: var(--text-secondary);\n}\n.badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--brand-main, #0a84d8);\n color: #fff;\n font-size: 0.65rem;\n font-weight: var(--font-weight-semibold);\n line-height: 16px;\n text-align: center;\n}\n.value {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n background: #fff;\n border-radius: 12px;\n min-width: 220px;\n width: fit-content;\n max-height: 280px;\n overflow-y: auto;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px rgba(0, 0, 0, 0.12);\n z-index: 50;\n}\n.panel.open {\n display: block;\n}\n.panelRight {\n left: auto;\n right: 0;\n}\n.panelWide {\n min-width: 260px;\n padding-bottom: 4px;\n}\n.sectionHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 12px 14px 4px;\n}\n.sectionLabel {\n font-size: 0.75rem;\n font-weight: var(--font-weight-semibold);\n color: var(--text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n.allToggle {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.75rem;\n font-weight: var(--font-weight-semibold);\n color: var(--brand-main, #0a84d8);\n cursor: pointer;\n}\n.allToggle:hover {\n text-decoration: underline;\n}\n.allToggle:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n border-radius: 4px;\n}\n.divider {\n height: 1px;\n background: var(--border);\n margin: 4px 0;\n}\n.option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border-radius: 8px;\n font-size: 1rem;\n cursor: pointer;\n}\n.option:hover {\n background: var(--bg);\n}\n.search {\n width: calc(100% - 16px);\n box-sizing: border-box;\n border: none;\n box-shadow: inset 0 0 0 1px var(--border-input);\n border-radius: 8px;\n padding: 8px 12px;\n margin: 8px;\n font-family: inherit;\n font-size: 1rem;\n margin-bottom: 0;\n}\n.search:focus {\n outline: none;\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.optionsList {\n padding: 4px 4px;\n}\n.empty {\n padding: 7px 8px;\n color: var(--text-tertiary);\n font-size: 0.85rem;\n}\n","import { useState } from 'react';\nimport { Checkbox } from './Checkbox';\nimport styles from './FilterSection.module.css';\n\ninterface FilterSectionProps<T extends string> {\n label: string;\n options: T[];\n optionLabel: (opt: T) => string;\n activeSet: Set<T>;\n onToggle: (opt: T) => void;\n onSetAll?: (opts: T[]) => void;\n searchable?: boolean;\n}\n\nexport function FilterSection<T extends string>({\n label,\n options,\n optionLabel,\n activeSet,\n onToggle,\n onSetAll,\n searchable,\n}: FilterSectionProps<T>) {\n const [query, setQuery] = useState('');\n\n const q = query.trim().toLowerCase();\n const matches = q ? options.filter((opt) => optionLabel(opt).toLowerCase().includes(q)) : options;\n const allSelected = options.length > 0 && activeSet.size === options.length;\n\n return (\n <div>\n <div className={styles.sectionHeader}>\n <div className={styles.sectionLabel}>{label}</div>\n {onSetAll && (\n <button\n type=\"button\"\n className={styles.allToggle}\n onClick={() => onSetAll(allSelected ? [] : options)}\n >\n {allSelected ? 'Deselect all' : 'Select all'}\n </button>\n )}\n </div>\n {searchable && (\n <input\n type=\"text\"\n className={styles.search}\n placeholder={`Search ${label.toLowerCase()}…`}\n autoComplete=\"off\"\n value={query}\n onClick={(e) => e.stopPropagation()}\n onChange={(e) => setQuery(e.target.value)}\n />\n )}\n <div className={styles.optionsList}>\n {matches.length === 0 && <div className={styles.empty}>No match</div>}\n {matches.map((opt) => (\n <Checkbox\n key={opt}\n className={styles.option}\n checked={activeSet.has(opt)}\n onChange={() => onToggle(opt)}\n label={optionLabel(opt)}\n />\n ))}\n </div>\n </div>\n );\n}\n",".line,\n.box {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.indicator {\n position: absolute;\n left: 0;\n pointer-events: none;\n transition: translate 0.25s cubic-bezier(0.39, 0.575, 0.565, 1), width 0.25s ease,\n scale 0.125s cubic-bezier(0.39, 0.575, 0.565, 1);\n}\n\n.indicator.settling {\n transition: scale 0.1s linear;\n}\n\n.indicatorLine {\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n}\n\n.indicatorBox {\n top: 4px;\n bottom: 4px;\n border-radius: 8px;\n background: var(--card-surface);\n box-shadow: 0 0 1px 0.5px var(--border);\n}\n\n.tab {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: none;\n border-radius: 8px 8px 0 0;\n font-family: inherit;\n font-weight: var(--font-weight-regular);\n cursor: pointer;\n white-space: nowrap;\n transition: color 0.15s ease-out, background 0.15s ease-out, box-shadow 0.15s ease-out;\n}\n\n.tab::before {\n content: '';\n position: absolute;\n left: 50%;\n bottom: 0;\n width: 40%;\n aspect-ratio: 1;\n border-radius: 50%;\n transform: translate(-50%, 100%) scale(1);\n transition: transform 0.3s cubic-bezier(0.39, 0.575, 0.565, 1);\n z-index: -1;\n pointer-events: none;\n background: rgba(var(--brand-main-rgb), 0.08);\n}\n.tab:hover:not(:disabled)::before {\n transform: translate(-50%, 15%) scale(4);\n}\n.tab:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n\n.tab:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.tab:disabled::before {\n display: none;\n}\n\n.tab.selected:hover::before {\n display: none;\n}\n\n.tab:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: -4px;\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n\n.tab.iconOnly {\n justify-content: center;\n}\n.tab.iconOnly .icon {\n margin-left: 0;\n}\n/* Square button: the default 40% hover circle (x4) doesn't reach the top corners */\n.tab.iconOnly::before {\n width: 60%;\n}\n\n/* Line variant */\n\n.line {\n box-shadow: inset 0 -1px 0 0 var(--border);\n}\n\n.line .tab {\n background: transparent;\n padding: 12px 8px;\n font-size: 1rem;\n color: var(--text-secondary);\n}\n.line .tab:hover:not(:disabled) {\n color: var(--brand-main);\n}\n.line .tab.selected {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n\n/* Box variant */\n\n.box {\n box-sizing: border-box;\n height: var(--control-height-base);\n background: var(--depth-5);\n border-radius: var(--radius-base);\n padding: 4px;\n gap: 4px;\n box-shadow: inset 0 0 0.5px 1px #e3e3e3;\n}\n\n.box .tab {\n height: calc(var(--control-height-base) - 8px);\n border-radius: 8px;\n padding: 0 14px;\n font-size: 0.9rem;\n background: transparent;\n color: var(--text-secondary);\n}\n.box .tab:hover:not(:disabled) {\n color: var(--brand-main);\n /* box-shadow: 0 0 0px 1px var(--brand-main-30); */\n}\n.box .tab.selected {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n\n.box.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n}\n.box.sm .tab {\n height: calc(var(--control-height-sm) - 8px);\n border-radius: 6px;\n padding: 0 14px;\n}\n.box .tab.iconOnly {\n width: calc(var(--control-height-base) - 8px);\n padding: 0;\n}\n.box.sm .tab.iconOnly {\n width: calc(var(--control-height-sm) - 8px);\n padding: 0;\n}\n.box.sm .indicatorBox {\n border-radius: 6px;\n}\n","import {\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n type TransitionEvent,\n} from 'react';\nimport styles from './Tabs.module.css';\n\ntype TabsVariant = 'line' | 'box';\ntype TabsSize = 'base' | 'sm';\n\nexport interface TabItem {\n value: string;\n label?: ReactNode;\n icon?: ReactNode;\n disabled?: boolean;\n 'aria-label'?: string;\n}\n\ninterface TabsProps {\n items: TabItem[];\n value: string;\n onChange: (value: string) => void;\n variant?: TabsVariant;\n size?: TabsSize;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n}\n\nexport function Tabs({ items, value, onChange, variant = 'line', size = 'base', ...rest }: TabsProps) {\n const enabledValues = items.filter((item) => !item.disabled).map((item) => item.value);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const tabRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n const prevValueRef = useRef(value);\n const [indicatorStyle, setIndicatorStyle] = useState<{ left: number; width: number } | null>(\n null,\n );\n const [pillPhase, setPillPhase] = useState<'idle' | 'moving' | 'settling'>('idle');\n\n useLayoutEffect(() => {\n const selectedTab = tabRefs.current.get(value);\n if (!selectedTab) return;\n setIndicatorStyle({ left: selectedTab.offsetLeft, width: selectedTab.offsetWidth });\n\n if (variant === 'box' && prevValueRef.current !== value) {\n setPillPhase('moving');\n }\n prevValueRef.current = value;\n }, [value, items, variant, size]);\n\n function handlePillTransitionEnd(event: TransitionEvent<HTMLSpanElement>) {\n if (event.propertyName !== 'scale') return;\n if (pillPhase === 'moving') setPillPhase('settling');\n else if (pillPhase === 'settling') setPillPhase('idle');\n }\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() => {\n const selectedTab = tabRefs.current.get(value);\n if (!selectedTab) return;\n setIndicatorStyle({ left: selectedTab.offsetLeft, width: selectedTab.offsetWidth });\n });\n observer.observe(container);\n return () => observer.disconnect();\n }, [value]);\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const currentIndex = enabledValues.indexOf(value);\n if (currentIndex === -1) return;\n\n let nextIndex: number | null = null;\n if (event.key === 'ArrowRight') nextIndex = (currentIndex + 1) % enabledValues.length;\n if (event.key === 'ArrowLeft') {\n nextIndex = (currentIndex - 1 + enabledValues.length) % enabledValues.length;\n }\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = enabledValues.length - 1;\n\n if (nextIndex !== null) {\n event.preventDefault();\n onChange(enabledValues[nextIndex]);\n }\n }\n\n return (\n <div\n ref={containerRef}\n role=\"tablist\"\n className={[styles[variant], variant === 'box' && size === 'sm' && styles.sm]\n .filter(Boolean)\n .join(' ')}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {indicatorStyle && (\n <span\n aria-hidden\n className={[\n styles.indicator,\n variant === 'line' ? styles.indicatorLine : styles.indicatorBox,\n pillPhase === 'settling' && styles.settling,\n ]\n .filter(Boolean)\n .join(' ')}\n onTransitionEnd={handlePillTransitionEnd}\n style={{\n translate: `${indicatorStyle.left}px 0`,\n scale: variant === 'box' && pillPhase === 'moving' ? 0.92 : 1,\n width: indicatorStyle.width,\n }}\n />\n )}\n {items.map((item) => {\n const selected = item.value === value;\n const iconOnly = !item.label && !!item.icon;\n return (\n <button\n key={item.value}\n ref={(node) => {\n if (node) tabRefs.current.set(item.value, node);\n else tabRefs.current.delete(item.value);\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n aria-label={item['aria-label']}\n disabled={item.disabled}\n tabIndex={selected ? 0 : -1}\n className={[styles.tab, selected && styles.selected, iconOnly && styles.iconOnly]\n .filter(Boolean)\n .join(' ')}\n onClick={() => !item.disabled && onChange(item.value)}\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n gap: 12px;\n}\n\n.label {\n font-size: 0.9rem;\n color: var(--text-secondary);\n font-weight: var(--font-weight-regular);\n white-space: nowrap;\n}\n","import { useId, type ReactNode } from 'react';\nimport { Tabs, type TabItem } from './Tabs';\nimport styles from './Toggle.module.css';\n\ninterface ToggleProps {\n items: TabItem[];\n value: string;\n onChange: (value: string) => void;\n label?: ReactNode;\n 'aria-label'?: string;\n}\n\nexport function Toggle({ items, value, onChange, label, 'aria-label': ariaLabel }: ToggleProps) {\n const labelId = useId();\n\n return (\n <div className={styles.root}>\n {label && (\n <span id={labelId} className={styles.label}>\n {label}\n </span>\n )}\n <Tabs\n items={items}\n value={value}\n onChange={onChange}\n variant=\"box\"\n size=\"sm\"\n aria-label={ariaLabel}\n aria-labelledby={label && !ariaLabel ? labelId : undefined}\n />\n </div>\n );\n}\n",".spinner {\n position: relative;\n display: block;\n flex-shrink: 0;\n}\n\n.inner,\n.outer {\n position: absolute;\n top: 0;\n left: 0;\n display: block;\n}\n\n.inner {\n animation: spin 1s cubic-bezier(0.5, 0, 0.4, 1) infinite;\n}\n\n.outer {\n animation: spinReverse 1s ease-in-out infinite;\n}\n\n/* Brand logo colors, kept as literals on purpose. */\n.default .inner {\n fill: #008cd8;\n}\n.default .outer {\n fill: #4cd5ff;\n}\n\n.subtle .inner,\n.subtle .outer {\n fill: var(--depth-5);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .inner,\n .outer {\n animation-duration: 3s;\n }\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@keyframes spinReverse {\n to {\n transform: rotate(-360deg);\n }\n}\n","import styles from './Spinner.module.css';\n\ntype SpinnerVariant = 'default' | 'subtle';\n\ninterface SpinnerProps {\n /** `default` uses the brand logo blues; `subtle` uses a faint depth tint for busy surfaces. */\n variant?: SpinnerVariant;\n /** Width and height in px. */\n size?: number;\n /** Accessible name announced by screen readers. */\n label?: string;\n /** Extra classes for layout around the spinner. Appended after the variant classes. */\n className?: string;\n 'data-testid'?: string;\n}\n\nexport function Spinner({\n variant = 'default',\n size = 64,\n label = 'Loading',\n className,\n 'data-testid': dataTestId,\n}: SpinnerProps) {\n const classes = [styles.spinner, styles[variant], className].filter(Boolean).join(' ');\n return (\n <div\n role=\"status\"\n aria-label={label}\n className={classes}\n style={{ width: size, height: size }}\n data-testid={dataTestId}\n >\n <svg className={styles.inner} width={size} height={size} viewBox=\"0 0 64 64\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M45.4273 17.5099C45.5053 17.5796 45.5088 17.6535 45.4377 17.7316L38.8829 24.8071C38.8634 24.828 38.8365 24.8404 38.8079 24.8416C38.7793 24.8428 38.7514 24.8326 38.7303 24.8134C36.6569 22.9045 34.221 22.0275 31.4225 22.1823C29.9153 22.2659 28.5572 22.6333 27.3483 23.2845C25.0295 24.5352 23.4428 26.4155 22.588 28.9253C20.717 34.4308 24.3708 40.1612 29.8184 41.6584C30.8097 41.9302 31.99 41.9735 33.3593 41.788C35.158 41.5433 36.8709 40.5854 38.3412 39.5627C38.4022 39.5203 38.4764 39.5014 38.5502 39.5094C38.6241 39.5175 38.6925 39.552 38.7428 39.6066L45.1742 46.6069C45.1803 46.6137 45.185 46.6217 45.188 46.6303C45.191 46.639 45.1923 46.6482 45.1917 46.6573C45.1911 46.6665 45.1887 46.6754 45.1846 46.6836C45.1805 46.6918 45.1748 46.6992 45.1679 46.7052C44.4401 47.3033 43.6502 47.8855 42.7982 48.4516C39.8799 50.3897 36.6339 51.4633 33.0602 51.6725C29.3847 51.8872 25.9031 51.1106 22.6152 49.3425C19.7917 47.8227 17.4903 45.764 15.7112 43.1663C14.4132 41.2707 13.4349 39.3097 12.8667 37.0717C11.973 33.5775 11.9925 30.1014 12.9253 26.6435C13.1679 25.7483 13.5465 24.8469 13.8414 23.9412C14.6703 21.4035 16.9915 18.887 18.9133 17.1899C26.3467 10.6186 38.1184 10.8908 45.4273 17.5099Z\"\n />\n </svg>\n <svg className={styles.outer} width={size} height={size} viewBox=\"0 0 64 64\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M23.9528 51.6749C24.675 51.9719 25.504 52.2515 26.4396 52.5136C29.5538 53.3858 33.0236 53.4255 36.1044 52.8608C39.7938 52.1832 43.2155 50.3364 46.0955 47.9667C46.1341 47.9349 46.1835 47.9192 46.2336 47.9227C46.2837 47.9262 46.3308 47.9487 46.3653 47.9855C48.5489 50.321 50.6076 52.5617 52.5415 54.7076C52.7465 54.9349 52.9626 55.1914 53.1899 55.4773C53.2568 55.5623 53.2492 55.6404 53.1669 55.7115C45.9875 61.8759 37.7414 64.4924 28.4286 63.5609C27.0036 63.4173 25.635 63.1761 24.323 62.8373C18.1489 61.2422 12.9382 58.1328 8.69108 53.5092C4.73535 49.2049 2.16559 44.2111 0.981796 38.5277C0.170292 34.6236 0.131251 30.548 0.864671 26.3008C1.10171 24.933 1.44681 23.5867 1.89997 22.2621C3.86319 16.5286 7.08689 11.7802 11.5711 8.01689C16.4638 3.90918 22.0697 1.47885 28.3889 0.725907C29.9073 0.546038 31.6858 0.498631 33.7243 0.583685C39.227 0.815842 44.6001 2.60826 49.1575 5.58447C50.8335 6.67902 52.2222 7.73732 53.3238 8.75937C53.5301 8.9504 53.5427 9.1463 53.3614 9.34708C51.1054 11.836 48.8612 14.2391 46.6289 16.5565C46.534 16.6569 46.435 16.6611 46.3319 16.569C42.8516 13.5029 38.8624 11.7049 34.3643 11.1751C33.642 11.09 32.7831 11.0531 31.7875 11.0642C30.8199 11.074 29.9868 11.1263 29.2882 11.2211C23.3065 12.0305 18.3747 15.0653 14.7397 19.9196C14.2266 20.6043 13.7943 21.2986 13.443 22.0028C12.3944 24.1012 11.7028 25.9683 11.3682 27.6038C10.2792 32.9385 11.0824 38.0216 13.7776 42.853C14.0481 43.3368 14.3402 43.7872 14.654 44.2041C14.9691 44.6252 15.294 45.0372 15.6286 45.4402C17.9767 48.2748 20.7514 50.3531 23.9528 51.6749Z\"\n />\n </svg>\n </div>\n );\n}\n","export function formatDuration(mins: number): string {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n return `${h}h:${String(m).padStart(2, '0')}m`;\n}\n\n/** HH:MM:SS — seconds are a stable per-video display detail, not tracked in the data model. */\nexport function formatDurationHMS(mins: number, seconds: number): string {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${pad(h)}:${pad(m)}:${pad(seconds)}`;\n}\n"],"x_google_ignoreList":[11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["__iconData","__iconData","__iconData","__iconData","__iconData","__iconData","__iconData"],"sources":["../src/components/Button.module.css","../src/components/Button.tsx","../src/components/Card.module.css","../src/components/Card.tsx","../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toLucideIconData.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/defaultAttributes.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconNode.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconForReact.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs","../node_modules/lucide-react/dist/esm/context.mjs","../node_modules/lucide-react/dist/esm/Icon.mjs","../node_modules/lucide-react/dist/esm/createLucideIcon.mjs","../node_modules/lucide-react/dist/esm/icons/check.mjs","../node_modules/lucide-react/dist/esm/icons/chevron-down.mjs","../node_modules/lucide-react/dist/esm/icons/chevron-left.mjs","../node_modules/lucide-react/dist/esm/icons/chevron-right.mjs","../node_modules/lucide-react/dist/esm/icons/eye-off.mjs","../node_modules/lucide-react/dist/esm/icons/eye.mjs","../node_modules/lucide-react/dist/esm/icons/search.mjs","../node_modules/lucide-react/dist/esm/icons/x.mjs","../src/components/Tag.module.css","../src/components/ChipBase.module.css","../src/components/Tag.tsx","../src/components/TagGroup.module.css","../src/components/OptionGroup.module.css","../src/components/FieldLabel.module.css","../src/components/FieldLabel.tsx","../src/components/TagGroup.tsx","../src/components/Toolbar.module.css","../src/components/Toolbar.tsx","../src/components/Checkbox.module.css","../src/components/Checkbox.tsx","../src/components/RadioButton.module.css","../src/components/RadioButton.tsx","../src/components/Switch.module.css","../src/components/Switch.tsx","../src/components/TextField.module.css","../src/components/TextField.tsx","../src/components/TextArea.module.css","../src/components/TextArea.tsx","../src/components/PasswordField.tsx","../src/components/DateField.tsx","../src/utils/date.ts","../src/components/Calendar.module.css","../src/components/Calendar.tsx","../src/components/DatePicker.module.css","../src/components/DatePicker.tsx","../src/components/NumberField.module.css","../src/components/NumberField.tsx","../src/components/Menu.module.css","../src/components/Menu.tsx","../src/components/MenuItem.module.css","../src/components/MenuItem.tsx","../src/components/Dropdown.module.css","../src/components/Dropdown.tsx","../src/components/HighlightText.module.css","../src/components/HighlightText.tsx","../src/components/FilterSection.module.css","../src/components/FilterSection.tsx","../src/components/Tabs.module.css","../src/components/Tabs.tsx","../src/components/Toggle.module.css","../src/components/Toggle.tsx","../src/components/Spinner.module.css","../src/components/Spinner.tsx","../src/utils/format.ts"],"sourcesContent":[".primary,\n.secondary,\n.tertiary,\n.onDark,\n.dangerous {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: none;\n font-family: inherit;\n font-weight: var(--font-weight-regular);\n letter-spacing: -0.01em;\n cursor: pointer;\n box-shadow: 0 0 0 0 var(--btn-glow, transparent);\n transition:\n background 0.15s ease-out,\n color 0.15s ease-out,\n box-shadow 0.15s ease-out;\n}\n.primary:focus-visible,\n.secondary:focus-visible,\n.tertiary:focus-visible,\n.onDark:focus-visible,\n.dangerous:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.primary:hover:not(:disabled),\n.secondary:hover:not(:disabled),\n.tertiary:hover:not(:disabled),\n.onDark:hover:not(:disabled),\n.dangerous:hover:not(:disabled) {\n box-shadow: 0 0 0 2px var(--btn-glow, transparent);\n}\n.primary:active:not(:disabled),\n.secondary:active:not(:disabled),\n.tertiary:active:not(:disabled),\n.onDark:active:not(:disabled),\n.dangerous:active:not(:disabled) {\n box-shadow: 0 0 0 0 var(--btn-glow, transparent);\n}\n\n.xs {\n height: var(--control-height-xs);\n border-radius: var(--radius-xs);\n padding: 0 16px;\n font-size: var(--control-font-size);\n}\n.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n padding: 0 16px;\n font-size: var(--control-font-size);\n}\n.base {\n height: var(--control-height-base);\n border-radius: var(--radius-base);\n padding: 0 20px;\n font-size: var(--control-font-size);\n}\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.leadingIcon {\n margin-left: -4px;\n}\n.trailingIcon {\n margin-right: -4px;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n\n.iconOnly {\n box-sizing: border-box;\n padding: 0;\n}\n.iconOnly.xs {\n width: var(--control-height-xs);\n}\n.iconOnly.sm {\n width: var(--control-height-sm);\n}\n.iconOnly.base {\n width: var(--control-height-base);\n}\n.fullWidth {\n width: 100%;\n}\n.primary::after,\n.secondary::after,\n.tertiary::after,\n.onDark::after,\n.dangerous::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n box-shadow: inset 0 0 0 var(--btn-ring-width, 1px) var(--btn-ring, transparent);\n pointer-events: none;\n}\n\n.primary {\n --btn-ring: rgba(0, 0, 0, 0.1);\n --btn-glow: var(--brand-main-30);\n background: var(--brand-dark);\n color: #fff;\n}\n.primary:hover:not(:disabled) {\n background: var(--brand-main);\n}\n.primary:active:not(:disabled) {\n background: var(--brand-dark);\n}\n\n.tertiary {\n --btn-glow: var(--brand-main-10);\n background: transparent;\n color: var(--text-secondary);\n}\n.tertiary:hover:not(:disabled) {\n background: var(--brand-main-10);\n color: var(--brand-main);\n}\n.tertiary:active:not(:disabled) {\n background: var(--brand-main-15);\n}\n\n.secondary {\n --btn-ring: rgba(0, 0, 0, 0.08);\n --btn-ring-width: 1.5px;\n --btn-glow: var(--brand-main-30);\n background: transparent;\n color: var(--text-primary);\n}\n.secondary .icon {\n color: var(--text-secondary);\n}\n.secondary:hover:not(:disabled) {\n background: var(--brand-main-5);\n color: var(--brand-main);\n}\n.secondary:hover:not(:disabled) .icon {\n color: var(--brand-main);\n}\n.secondary:active:not(:disabled) {\n background: var(--brand-main-15);\n}\n\n.onDark {\n --btn-ring: rgba(255, 255, 255, 0.05);\n --btn-glow: rgba(255, 255, 255, 0.3);\n background: rgba(255, 255, 255, 0.12);\n color: #fff;\n}\n.onDark:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.2);\n}\n.onDark:active:not(:disabled) {\n background: rgba(255, 255, 255, 0.16);\n}\n\n.dangerous {\n --btn-ring: rgba(var(--danger-rgb), 0.2);\n --btn-ring-width: 1.5px;\n --btn-glow: rgba(var(--danger-rgb), 0.3);\n background: transparent;\n color: var(--danger-text-dark);\n}\n.dangerous:hover:not(:disabled) {\n background: rgba(var(--danger-rgb), 0.05);\n}\n.dangerous:active:not(:disabled) {\n background: rgba(var(--danger-rgb), 0.15);\n}\n\n.primary:disabled,\n.secondary:disabled,\n.tertiary:disabled,\n.onDark:disabled,\n.dangerous:disabled {\n --btn-ring: transparent;\n background: var(--disabled-bg);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n\n/* link: inline text in a flow of copy — none of the block-button rules above apply */\n.link {\n display: inline;\n margin: 0;\n padding: 0;\n border: none;\n border-radius: 0;\n background: transparent;\n color: var(--brand-main);\n font: inherit;\n letter-spacing: inherit;\n text-align: inherit;\n white-space: normal;\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n}\n.link:hover:not(:disabled) {\n color: var(--brand-dark);\n}\n.link:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n border-radius: 2px;\n}\n.link.underlineHover {\n text-decoration: none;\n}\n.link.underlineHover:hover:not(:disabled),\n.link.underlineHover:focus-visible {\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.link:disabled {\n color: var(--disabled-text);\n text-decoration: none;\n cursor: not-allowed;\n}\n","import type { ButtonHTMLAttributes, ReactNode, Ref } from 'react';\nimport styles from './Button.module.css';\n\n/** `onDark` is for buttons placed on dark surfaces. `link` is inline text in a flow of copy, not a block button. */\ntype BlockButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'onDark' | 'dangerous';\ntype ButtonSize = 'xs' | 'sm' | 'base';\n\ninterface ButtonBaseProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children'> {\n children?: ReactNode;\n /**\n * Extra classes for layout around the button — responsive visibility,\n * positioning, spacing. Appended after the variant classes.\n */\n className?: string;\n ref?: Ref<HTMLButtonElement>;\n}\n\ninterface BlockButtonProps extends ButtonBaseProps {\n variant?: BlockButtonVariant;\n size?: ButtonSize;\n /** Icon shown before the label. Omit `children` to render an icon-only square button — pass `aria-label` in that case. */\n leadingIcon?: ReactNode;\n /** Icon shown after the label. */\n trailingIcon?: ReactNode;\n /** Stretch to the width of the container. */\n fullWidth?: boolean;\n underline?: never;\n}\n\ninterface LinkButtonProps extends ButtonBaseProps {\n /** Inline text that inherits font size and line height from its parent and wraps with the surrounding copy. */\n variant: 'link';\n /** When to underline the text. */\n underline?: 'always' | 'hover';\n size?: never;\n leadingIcon?: never;\n trailingIcon?: never;\n fullWidth?: never;\n}\n\ntype ButtonProps = BlockButtonProps | LinkButtonProps;\n\nexport function Button({\n variant = 'primary',\n size = 'base',\n leadingIcon,\n trailingIcon,\n fullWidth,\n underline = 'always',\n children,\n className,\n ref,\n ...rest\n}: ButtonProps) {\n if (variant === 'link') {\n const linkClasses = [styles.link, underline === 'hover' && styles.underlineHover, className].filter(Boolean).join(' ');\n return (\n <button ref={ref} type=\"button\" className={linkClasses} {...rest}>\n {children}\n </button>\n );\n }\n const iconOnly = !children && Boolean(leadingIcon);\n const classes = [\n styles[variant],\n styles[size],\n iconOnly && styles.iconOnly,\n fullWidth && styles.fullWidth,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button ref={ref} type=\"button\" className={classes} {...rest}>\n {leadingIcon && <span className={`${styles.icon} ${iconOnly ? '' : styles.leadingIcon}`.trim()}>{leadingIcon}</span>}\n {children}\n {trailingIcon && <span className={`${styles.icon} ${styles.trailingIcon}`}>{trailingIcon}</span>}\n </button>\n );\n}\n",".wrap {\n position: relative;\n width: 220px;\n flex: 0 0 220px;\n}\n.wrap:hover {\n z-index: 10;\n}\n.fluid {\n width: 100%;\n flex: none;\n}\n\n.backing {\n position: absolute;\n left: 6px;\n right: 6px;\n bottom: -4px;\n height: 10px;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border);\n border-radius: 0 0 14px 14px;\n z-index: 0;\n}\n.backing.completed {\n background: var(--success-bg);\n box-shadow: inset 0 0 0 1px #bfe3cc;\n}\n\n.card {\n position: relative;\n z-index: 1;\n width: 100%;\n box-sizing: border-box;\n background: var(--card-surface);\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 1px 2px rgba(16, 24, 32, 0.04);\n border-radius: 16px;\n padding: 12px 14px;\n cursor: default;\n transition:\n box-shadow 0.2s,\n transform 0.1s;\n}\n.card.interactive {\n cursor: pointer;\n}\n.card.interactive:active {\n transform: scale(0.98, 0.95);\n}\n.card.grabbable {\n cursor: grab;\n}\n.card.grabbable:active {\n cursor: grabbing;\n}\n.card.dragging,\n.card.dragging:hover {\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 1px 2px rgba(16, 24, 32, 0.04);\n}\n.card.interactive:hover {\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 0 0 2px var(--brand-main);\n}\n.card.completed {\n background: var(--success-bg);\n box-shadow:\n inset 0 0 0 1px #bfe3cc,\n 0 1px 2px rgba(16, 24, 32, 0.04),\n 0 2px 8px rgba(16, 24, 32, 0.06);\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Card.module.css';\n\ninterface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {\n /** Shows a second sheet behind the card, for representing a stack/batch. */\n stacked?: boolean;\n /** Success-tinted surface, e.g. a completed task. */\n completed?: boolean;\n /** Adds pointer cursor + accent hover ring. */\n interactive?: boolean;\n /** Grab cursor, for drag sources — pair with `interactive`. */\n draggable?: boolean;\n /** Suppresses the hover ring while a drag is in progress. */\n dragging?: boolean;\n /** Card fills its container width instead of a fixed width. */\n fluid?: boolean;\n children: ReactNode;\n}\n\nexport function Card({\n stacked,\n completed,\n interactive,\n draggable,\n dragging,\n fluid,\n children,\n ...rest\n}: CardProps) {\n return (\n <div className={`${styles.wrap} ${fluid ? styles.fluid : ''}`}>\n {stacked && <div className={`${styles.backing} ${completed ? styles.completed : ''}`} />}\n <div\n className={[\n styles.card,\n completed ? styles.completed : '',\n interactive ? styles.interactive : '',\n draggable ? styles.grabbable : '',\n dragging ? styles.dragging : '',\n ]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n {children}\n </div>\n </div>\n );\n}\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string?.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toKebabCase } from './toKebabCase.mjs';\n\nfunction toLucideIconData(iconName, iconNode, aliases = []) {\n if (iconNode == null) {\n throw new Error(\"[lucide]: iconNode is required when icon name is used\");\n }\n return {\n name: toKebabCase(iconName),\n size: 24,\n node: iconNode,\n ...aliases.length > 0 ? { aliases } : {}\n };\n}\n\nexport { toLucideIconData };\n//# sourceMappingURL=toLucideIconData.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => {\n let out = \"\";\n let upperNext = false;\n for (const ch of string) {\n if (ch === \"-\" || ch === \"_\" || ch <= \" \") {\n upperNext = out.length > 0;\n continue;\n }\n if (out.length === 0) {\n out += ch.toLowerCase();\n } else {\n out += upperNext ? ch.toUpperCase() : ch;\n }\n upperNext = false;\n }\n return out;\n};\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.mjs';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport defaultAttributes from './defaultAttributes.mjs';\nimport { mergeClasses } from '../utils/mergeClasses.mjs';\n\nfunction isDefined(value) {\n return value !== null && value !== void 0;\n}\nfunction buildLucideIconNode(icon, params = {}) {\n const attributeNames = params.attributeNames ?? {};\n const getAttributeName = (attributeName) => attributeNames[attributeName] ?? attributeName;\n const viewBoxWidth = icon.size ?? icon.width ?? defaultAttributes[\"width\"];\n const viewBoxHeight = icon.size ?? icon.height ?? defaultAttributes[\"height\"];\n const aliasClassNames = icon.aliases?.filter((alias) => typeof alias === \"string\" && alias.trim() !== \"\").map((alias) => `lucide-${alias}`) ?? [];\n const iconClassNames = [...icon.name ? [`lucide-${icon.name}`] : [], ...aliasClassNames];\n const classNamesFromClassName = params.className?.split(\" \").filter(Boolean) ?? [];\n const className = params.includeDefaultClasses === false ? mergeClasses(...classNamesFromClassName) : mergeClasses(\"lucide\", ...iconClassNames, ...classNamesFromClassName);\n const calculatedStrokeWidth = params.absoluteStrokeWidth ? Number(params.strokeWidth ?? defaultAttributes[\"stroke-width\"]) * Number(icon.size ?? icon.width ?? defaultAttributes[\"width\"]) / Number(params.size ?? params.width ?? defaultAttributes[\"width\"]) : params.strokeWidth ?? defaultAttributes[\"stroke-width\"];\n const attributes = {\n ...Object.entries(defaultAttributes).reduce((attrs, [attrName, value]) => {\n attrs[getAttributeName(attrName)] = value;\n return attrs;\n }, {}),\n ...\"color\" in params && params.color && {\n [getAttributeName(\"stroke\")]: params.color\n },\n ...\"size\" in params && isDefined(params.size) && {\n [getAttributeName(\"width\")]: params.size,\n [getAttributeName(\"height\")]: params.size\n },\n ...\"width\" in params && isDefined(params.width) && {\n [getAttributeName(\"width\")]: params.width\n },\n ...\"height\" in params && isDefined(params.height) && {\n [getAttributeName(\"height\")]: params.height\n },\n [getAttributeName(\"stroke-width\")]: calculatedStrokeWidth,\n ...className && {\n [getAttributeName(\"class\")]: className\n },\n [getAttributeName(\"viewBox\")]: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,\n ...params.hasA11yProp === false ? {\n [getAttributeName(\"aria-hidden\")]: \"true\"\n } : {},\n ...\"attributes\" in params && params.attributes\n };\n return [\n \"svg\",\n attributes,\n icon.node.map((child) => {\n const [name, attrs, children] = child;\n const nextAttrs = params.nonScalingStroke ? { [getAttributeName(\"vector-effect\")]: \"non-scaling-stroke\", ...attrs } : attrs;\n return children ? [name, nextAttrs, children] : [name, nextAttrs];\n })\n ];\n}\n\nexport { buildLucideIconNode as default };\n//# sourceMappingURL=buildLucideIconNode.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport buildLucideIconNode from './buildLucideIconNode.mjs';\n\nfunction buildLucideIconForReact(icon, params = {}) {\n return buildLucideIconNode(icon, {\n ...params,\n attributeNames: {\n ...params.attributeNames,\n class: \"className\",\n \"stroke-width\": \"strokeWidth\",\n \"stroke-linecap\": \"strokeLinecap\",\n \"stroke-linejoin\": \"strokeLinejoin\",\n \"vector-effect\": \"vectorEffect\"\n }\n });\n}\n\nexport { buildLucideIconForReact as default };\n//# sourceMappingURL=buildLucideIconForReact.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { createContext, useContext, useMemo, createElement } from 'react';\n\nconst LucideContext = createContext({});\nfunction LucideProvider({\n children,\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className\n}) {\n const value = useMemo(\n () => ({\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className\n }),\n [size, color, strokeWidth, absoluteStrokeWidth, nonScalingStroke, className]\n );\n return createElement(LucideContext.Provider, { value }, children);\n}\nconst useLucideContext = () => useContext(LucideContext);\n\nexport { LucideProvider, useLucideContext };\n//# sourceMappingURL=context.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.mjs';\nimport buildLucideIconForReact from './shared/src/build/buildLucideIconForReact.mjs';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.mjs';\nimport { useLucideContext } from './context.mjs';\n\nconst Icon = forwardRef(\n ({\n color,\n size,\n width,\n height,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className = \"\",\n children,\n iconNode = [],\n icon = {\n node: iconNode,\n aliases: [],\n size: 24\n },\n ...rest\n }, ref) => {\n const {\n size: contextSize = 24,\n strokeWidth: contextStrokeWidth = 2,\n absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,\n nonScalingStroke: contextNonScalingStroke = false,\n color: contextColor = \"currentColor\",\n className: contextClass = \"\"\n } = useLucideContext() ?? {};\n const hasAccessibleProp = Boolean(children) || hasA11yProp(rest);\n const [name, svgAttributes, builtIconNode = []] = buildLucideIconForReact(icon, {\n color: color ?? contextColor,\n width: width ?? size ?? contextSize,\n height: height ?? size ?? contextSize,\n strokeWidth: strokeWidth ?? contextStrokeWidth,\n absoluteStrokeWidth: absoluteStrokeWidth ?? contextAbsoluteStrokeWidth,\n nonScalingStroke: nonScalingStroke ?? contextNonScalingStroke,\n className: mergeClasses(contextClass, className),\n hasA11yProp: hasAccessibleProp,\n attributes: rest\n });\n return createElement(\n name,\n {\n ref,\n ...svgAttributes\n },\n [\n ...builtIconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n );\n }\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { toLucideIconData } from './shared/src/utils/toLucideIconData.mjs';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.mjs';\nimport Icon from './Icon.mjs';\n\nfunction createLucideIcon(iconDataOrName, iconNode = [], aliases = []) {\n const iconData = typeof iconDataOrName === \"string\" ? toLucideIconData(iconDataOrName, iconNode, aliases) : iconDataOrName;\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n icon: iconData,\n className,\n ...props\n })\n );\n if (iconData.name) {\n Component.displayName = toPascalCase(iconData.name);\n }\n return Component;\n}\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"check\",\n size: 24,\n node: [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]\n};\n__iconData.node;\nconst Check = createLucideIcon(__iconData);\n\nexport { __iconData, Check as default };\n//# sourceMappingURL=check.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevron-down\",\n size: 24,\n node: [[\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]]\n};\n__iconData.node;\nconst ChevronDown = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronDown as default };\n//# sourceMappingURL=chevron-down.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevron-left\",\n size: 24,\n node: [[\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]]\n};\n__iconData.node;\nconst ChevronLeft = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronLeft as default };\n//# sourceMappingURL=chevron-left.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevron-right\",\n size: 24,\n node: [[\"path\", { d: \"m9 18 6-6-6-6\", key: \"mthhwq\" }]]\n};\n__iconData.node;\nconst ChevronRight = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronRight as default };\n//# sourceMappingURL=chevron-right.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"eye-off\",\n size: 24,\n node: [\n [\n \"path\",\n {\n 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 key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n 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 key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n ]\n};\n__iconData.node;\nconst EyeOff = createLucideIcon(__iconData);\n\nexport { __iconData, EyeOff as default };\n//# sourceMappingURL=eye-off.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"eye\",\n size: 24,\n node: [\n [\n \"path\",\n {\n 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 key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n ]\n};\n__iconData.node;\nconst Eye = createLucideIcon(__iconData);\n\nexport { __iconData, Eye as default };\n//# sourceMappingURL=eye.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"search\",\n size: 24,\n node: [\n [\"path\", { d: \"m21 21-4.34-4.34\", key: \"14j7rj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }]\n ]\n};\n__iconData.node;\nconst Search = createLucideIcon(__iconData);\n\nexport { __iconData, Search as default };\n//# sourceMappingURL=search.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"x\",\n size: 24,\n node: [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n ]\n};\n__iconData.node;\nconst X = createLucideIcon(__iconData);\n\nexport { __iconData, X as default };\n//# sourceMappingURL=x.mjs.map\n",".neutral,\n.pill,\n.accent,\n.success,\n.warning,\n.danger,\n.count,\n.chip {\n display: inline-flex;\n align-items: center;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n}\n\n/* Square tags — e.g. day badges, worker names, video panel tags */\n.neutral {\n color: var(--text-tertiary);\n font-size: 0.75rem;\n background: var(--depth-5);\n border-radius: 6px;\n padding: 2px 7px;\n}\n\n/* Pill tags — unfilled outline, e.g. BPO group labels, chart-axis pills */\n.pill {\n background: none;\n box-shadow: inset 0 0 0 1px var(--border);\n color: var(--text-tertiary);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n.pill.pressed {\n box-shadow: inset 0 0 0 1px var(--brand-main);\n color: var(--brand-main);\n}\n\n/* Accent pill — e.g. \"current\" stat, read-only banner badge */\n.accent {\n background: var(--brand-bg);\n color: var(--brand-dark);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Success pill — e.g. \"time spent\" stat */\n.success {\n background: var(--success-bg);\n color: var(--success-text);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Warning pill — same shape as success */\n.warning {\n background: var(--warning-bg);\n color: var(--warning-text);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Chip — filled toggle pill; colours/states come from ChipBase.module.css */\n.chip {\n justify-content: center;\n height: 36px;\n padding: 0 14px;\n font-size: 0.85rem;\n border-radius: 999px;\n}\n\n/* Danger — square (e.g. ASAP tag) reuses the same token pair as the\n pill-shaped status variant; only the shape differs by context. */\n.danger {\n color: var(--danger-text);\n font-size: 0.75rem;\n background: var(--danger-bg);\n border-radius: 6px;\n padding: 2px 7px;\n}\n\n/* Count badge — small solid circle, e.g. active-filter count */\n.count {\n justify-content: center;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--brand-main);\n color: #fff;\n font-size: 0.65rem;\n line-height: 16px;\n text-align: center;\n}\n\n/* Slots (leading / remove) */\n.slots {\n gap: 6px;\n}\n\n.leading {\n display: inline-flex;\n align-items: center;\n}\n\n/* Interactive behaviour (pressable and/or removable) */\n.interactive {\n font-family: inherit;\n transition:\n background-color 0.15s ease-out,\n box-shadow 0.15s ease-out,\n color 0.15s ease-out,\n transform 0.1s ease-out;\n}\n\n/* Root <button>: reset native chrome. Inherit font-size from the variant, not the UA. */\n.button {\n appearance: none;\n border: none;\n margin: 0;\n line-height: inherit;\n cursor: pointer;\n}\n\n.interactive:not(.chip) {\n cursor: pointer;\n}\n\n.interactive:not(.disabled):hover.neutral {\n background: var(--depth-10);\n}\n\n.interactive:not(.disabled):hover.accent {\n background: color-mix(in srgb, var(--brand-main) 12%, var(--brand-bg));\n}\n\n.interactive:not(.disabled):hover.success {\n background: color-mix(in srgb, var(--success-text) 12%, var(--success-bg));\n}\n\n.interactive:not(.disabled):hover.warning {\n background: color-mix(in srgb, var(--warning-text) 12%, var(--warning-bg));\n}\n\n.interactive:not(.disabled):hover.danger {\n background: color-mix(in srgb, var(--danger-text) 12%, var(--danger-bg));\n}\n\n.interactive:not(.disabled):hover.pill {\n background: var(--depth-5);\n}\n\n.interactive:not(.disabled):active {\n transform: scale(0.97);\n}\n\n.button:focus-visible,\n.main:focus-visible,\n.remove:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n\n.disabled {\n background: var(--disabled-bg);\n box-shadow: none;\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n\n.disabled.interactive:hover {\n background: var(--disabled-bg);\n}\n\n/* Removable: span root holds the look; two sibling buttons inside */\n.removable {\n align-items: center;\n}\n\n.main {\n display: inline-flex;\n align-items: center;\n appearance: none;\n border: none;\n background: none;\n padding: 0;\n margin: 0;\n font: inherit;\n color: inherit;\n cursor: pointer;\n border-radius: inherit;\n}\n\n.main:disabled,\n.remove:disabled {\n cursor: not-allowed;\n}\n\n.remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n border: none;\n background: none;\n padding: 2px;\n margin: 0 -4px 0 0;\n border-radius: 999px;\n color: inherit;\n cursor: pointer;\n}\n\n.remove:hover:not(:disabled) {\n background: color-mix(in srgb, currentColor 15%, transparent);\n}\n\n.pill.pressed.disabled {\n box-shadow: none;\n color: var(--disabled-text);\n}\n","/* Visual core shared by TagGroup's chips and Tag variant=\"chip\" so the two\n cannot drift apart. Sizing and the :active transform stay with each consumer. */\n.chip {\n background: var(--depth-5);\n color: var(--text-primary);\n transition:\n background-color 0.15s ease-out,\n color 0.15s ease-out,\n transform 0.1s ease-out;\n}\n\n.chip:hover:not(:disabled):not(.disabled) {\n background: var(--surface-muted);\n}\n\n.chip:active:not(:disabled):not(.disabled) {\n background: var(--surface-muted);\n}\n\n.chip:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n\n.chip.selected {\n background: var(--brand-bg);\n color: var(--brand-main);\n}\n\n.chip.selected:hover:not(:disabled):not(.disabled) {\n background: var(--brand-main-20);\n}\n\n.chip.selected:active:not(:disabled):not(.disabled) {\n background: var(--brand-main-30);\n}\n\n.chip:disabled,\n.chip.disabled {\n background: var(--disabled-bg);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n","import { X } from 'lucide-react';\nimport type { HTMLAttributes, MouseEvent, ReactNode } from 'react';\nimport styles from './Tag.module.css';\nimport chipStyles from './ChipBase.module.css';\n\ntype TagVariant =\n | 'neutral'\n | 'pill'\n | 'accent'\n | 'success'\n | 'warning'\n | 'danger'\n | 'count'\n | 'chip';\n\ntype InteractiveVariant = Exclude<TagVariant, 'count'>;\n\ntype NativeProps = Omit<HTMLAttributes<HTMLElement>, 'className' | 'onClick' | 'children'>;\n\ntype RemoveProps =\n | { onRemove?: undefined; removeLabel?: undefined }\n | {\n /** Shows a × button on the right. */\n onRemove: () => void;\n /** Accessible name of the × button. */\n removeLabel: string;\n };\n\ntype CountTagProps = NativeProps & {\n variant: 'count';\n children: ReactNode;\n onClick?: never;\n pressed?: never;\n disabled?: never;\n leading?: never;\n onRemove?: never;\n removeLabel?: never;\n};\n\ntype RegularTagProps = NativeProps &\n RemoveProps & {\n variant?: InteractiveVariant;\n children: ReactNode;\n /** Makes the tag pressable: renders a <button type=\"button\"> instead of a <span>. */\n onClick?: (e: MouseEvent<HTMLButtonElement>) => void;\n /** Toggle state, exposed as aria-pressed. Ignored without onClick. */\n pressed?: boolean;\n disabled?: boolean;\n /** Slot before the text, e.g. a colour dot in a legend. */\n leading?: ReactNode;\n };\n\nexport type TagProps = CountTagProps | RegularTagProps;\n\nfunction cx(...names: Array<string | false | undefined>) {\n return names.filter(Boolean).join(' ');\n}\n\nexport function Tag(props: TagProps) {\n if (props.variant === 'count') {\n const { variant, children, ...rest } = props;\n return (\n <span className={styles[variant]} {...rest}>\n {children}\n </span>\n );\n }\n\n const {\n variant = 'neutral',\n children,\n onClick,\n pressed,\n disabled,\n leading,\n onRemove,\n removeLabel,\n ...rest\n } = props;\n\n const pressable = !!onClick;\n const removable = !!onRemove;\n const isChipLike = variant === 'chip';\n const isPressed = pressable && pressed === true;\n\n const rootClass = cx(\n styles[variant],\n isChipLike && chipStyles.chip,\n isChipLike && isPressed && chipStyles.selected,\n isChipLike && disabled && chipStyles.disabled,\n (pressable || removable) && styles.interactive,\n isPressed && styles.pressed,\n disabled && styles.disabled,\n (leading != null || removable) && styles.slots,\n );\n\n const content = (\n <>\n {leading != null && <span className={styles.leading}>{leading}</span>}\n {children}\n </>\n );\n\n // Removable: the root stays a <span> so the two buttons are siblings, never nested.\n if (removable) {\n return (\n <span className={cx(rootClass, styles.removable)} {...rest}>\n {pressable ? (\n <button\n type=\"button\"\n className={cx(styles.main, styles.slots)}\n aria-pressed={pressed}\n disabled={disabled}\n onClick={onClick}\n >\n {content}\n </button>\n ) : (\n content\n )}\n <button\n type=\"button\"\n className={styles.remove}\n aria-label={removeLabel}\n disabled={disabled}\n onClick={() => onRemove()}\n >\n <X size={12} aria-hidden=\"true\" />\n </button>\n </span>\n );\n }\n\n if (pressable) {\n return (\n <button\n type=\"button\"\n className={cx(rootClass, styles.button)}\n aria-pressed={pressed}\n disabled={disabled}\n onClick={onClick}\n {...rest}\n >\n {content}\n </button>\n );\n }\n\n return (\n <span className={rootClass} {...rest}>\n {content}\n </span>\n );\n}\n",".group {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n}\n\n.group.sm {\n gap: 6px;\n}\n\n.chip {\n composes: chip from './ChipBase.module.css';\n display: inline-flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n border: none;\n outline: none;\n font-family: inherit;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n border-radius: 999px;\n cursor: pointer;\n}\n\n.group.base .chip {\n height: 36px;\n padding: 0 14px;\n font-size: 0.85rem;\n}\n\n.group.sm .chip {\n height: 24px;\n padding: 0 9px;\n font-size: 0.75rem;\n}\n\n.chip:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.selected {\n composes: selected from './ChipBase.module.css';\n}\n",".group {\n display: inline-flex;\n flex-direction: column;\n gap: 0;\n}\n\n.groupLabel {\n margin-bottom: 6px;\n}\n",".label {\n font-size: 0.85rem;\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n padding-left: 4px;\n}\n","import type { ReactNode } from 'react';\nimport styles from './FieldLabel.module.css';\n\ninterface FieldLabelProps {\n children: ReactNode;\n /** Pass the id of the control this labels to render a real `<label htmlFor>`. */\n htmlFor?: string;\n className?: string;\n}\n\nexport function FieldLabel({ children, htmlFor, className }: FieldLabelProps) {\n const classes = `${styles.label} ${className ?? ''}`.trim();\n if (htmlFor) {\n return (\n <label className={classes} htmlFor={htmlFor}>\n {children}\n </label>\n );\n }\n return <span className={classes}>{children}</span>;\n}\n","import type { ReactNode } from 'react';\nimport styles from './TagGroup.module.css';\nimport groupStyles from './OptionGroup.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype TagGroupSize = 'sm' | 'base';\n\ninterface TagGroupItem {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\ninterface TagGroupProps {\n items: TagGroupItem[];\n value: string[];\n onChange: (value: string[]) => void;\n size?: TagGroupSize;\n disabled?: boolean;\n label?: ReactNode;\n 'aria-label'?: string;\n}\n\nexport function TagGroup({\n items,\n value,\n onChange,\n size = 'base',\n disabled = false,\n label,\n ...rest\n}: TagGroupProps) {\n function toggle(itemValue: string) {\n const next = value.includes(itemValue)\n ? value.filter((v) => v !== itemValue)\n : [...value, itemValue];\n onChange(next);\n }\n\n const tags = (\n <div\n role=\"group\"\n aria-label={label ? undefined : rest['aria-label']}\n className={`${styles.group} ${styles[size]}`}\n >\n {items.map((item) => {\n const selected = value.includes(item.value);\n const isDisabled = disabled || item.disabled;\n return (\n <button\n key={item.value}\n type=\"button\"\n aria-pressed={selected}\n disabled={isDisabled}\n className={[styles.chip, selected && styles.selected].filter(Boolean).join(' ')}\n onClick={() => !isDisabled && toggle(item.value)}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n\n if (!label) return tags;\n\n return (\n <div className={groupStyles.group} {...rest}>\n <FieldLabel className={groupStyles.groupLabel}>{label}</FieldLabel>\n {tags}\n </div>\n );\n}\n",".toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 0 8px;\n background: var(--card-surface);\n border-radius: 16px;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 1px 2px rgba(16, 24, 32, 0.04),\n 0 2px 8px rgba(16, 24, 32, 0.06);\n}\n.searchWrap {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n.searchWrap::after {\n content: '';\n position: absolute;\n left: 36px;\n right: 0;\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n opacity: 0;\n pointer-events: none;\n}\n.searchWrap:focus-within::after {\n opacity: 1;\n}\n.searchIcon {\n position: absolute;\n top: 50%;\n left: 12px;\n width: 16px;\n height: 16px;\n transform: translateY(-53%);\n color: var(--text-tertiary);\n pointer-events: none;\n}\n.searchIcon svg {\n width: 100%;\n height: 100%;\n}\n.search {\n width: 100%;\n box-sizing: border-box;\n border: none;\n padding: 16px 52px 16px 36px;\n font-family: inherit;\n font-size: 1rem;\n color: var(--text-primary);\n background: none;\n box-shadow: inset -1px 0 0 var(--border);\n}\n.search:focus {\n outline: none;\n}\n.searchShortcut {\n position: absolute;\n top: 50%;\n right: 8px;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 6px;\n background: var(--bg);\n color: var(--text-tertiary);\n font-size: 0.75rem;\n font-weight: var(--font-weight-semibold);\n letter-spacing: 0.02em;\n pointer-events: none;\n}\n.controls {\n display: flex;\n align-items: center;\n flex: none;\n}\n","import { useEffect, useRef, type ChangeEvent, type ReactNode } from 'react';\nimport { Search } from 'lucide-react';\nimport styles from './Toolbar.module.css';\n\ninterface ToolbarProps {\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n placeholder?: string;\n /** Text shown in the keyboard-shortcut badge, e.g. \"⌘K\". Omit to hide the badge. */\n shortcutLabel?: string;\n /** Focuses the search input when Cmd/Ctrl + the shortcut key is pressed. */\n shortcutKey?: string;\n /** Right-side content — filter/sort controls, actions, etc. */\n children?: ReactNode;\n}\n\nexport function Toolbar({\n searchValue,\n onSearchChange,\n placeholder = 'Search…',\n shortcutLabel = '⌘K',\n shortcutKey = 'k',\n children,\n}: ToolbarProps) {\n const searchRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === shortcutKey.toLowerCase()) {\n e.preventDefault();\n searchRef.current?.focus();\n }\n }\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [shortcutKey]);\n\n return (\n <div className={styles.toolbar}>\n <div className={styles.searchWrap}>\n <span className={styles.searchIcon}>\n <Search />\n </span>\n <input\n ref={searchRef}\n type=\"text\"\n className={styles.search}\n placeholder={placeholder}\n autoComplete=\"off\"\n value={searchValue}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onSearchChange?.(e.target.value)}\n />\n {shortcutLabel && (\n <span className={styles.searchShortcut} aria-hidden=\"true\">\n {shortcutLabel}\n </span>\n )}\n </div>\n {children && <div className={styles.controls}>{children}</div>}\n </div>\n );\n}\n",".checkbox {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n padding: 8px 4px;\n}\n.control {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.labelText {\n font-size: var(--control-font-size);\n color: var(--text-primary);\n transition: color 0.2s ease-out;\n}\n.checkbox:hover .labelText {\n color: var(--brand-main);\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.box {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 6px;\n background: var(--depth-5);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1),\n transform 0.1s cubic-bezier(0, 0, 0.2, 1);\n}\n.checkbox:hover .box {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .box {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:active + .box {\n transform: scale(0.88);\n}\n.input:checked + .box {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.checkbox:hover .input:checked + .box {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.icon {\n width: 10px;\n height: 10px;\n overflow: visible;\n}\n.icon polyline {\n fill: none;\n stroke: #fff;\n stroke-width: 2.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-dasharray: 22px;\n stroke-dashoffset: 22px;\n transition: stroke-dashoffset 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .box .icon polyline {\n stroke-dashoffset: 0px;\n}\n.checkbox:has(.input:disabled),\n.input:disabled {\n cursor: not-allowed;\n}\n.checkbox:has(.input:disabled) .labelText {\n color: var(--disabled-text);\n}\n.checkbox:has(.input:disabled) .box {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n transform: none;\n}\n.checkbox:has(.input:disabled) .input:checked + .box {\n background: var(--disabled-bg);\n box-shadow: inset 0 0 0 1px var(--disabled-bg);\n}\n\n/* CheckboxIndicator — same visuals driven by data attributes instead of an input */\n.indicator[data-checked='true'] {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.indicator[data-checked='true'] .icon polyline {\n stroke-dashoffset: 0px;\n}\nbutton:is(:hover, :focus-visible):not(:disabled) .indicator {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.indicator[data-disabled] {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n}\n.indicator[data-disabled][data-checked='true'] {\n background: var(--disabled-bg);\n box-shadow: inset 0 0 0 1px var(--disabled-bg);\n}\n","import type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport styles from './Checkbox.module.css';\nimport groupStyles from './OptionGroup.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ninterface CheckboxProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur?: (e: FocusEvent<HTMLInputElement>) => void;\n name?: string;\n label?: ReactNode;\n ariaLabel?: string;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\nexport function Checkbox({\n checked,\n onChange,\n onBlur,\n name,\n label,\n ariaLabel,\n disabled,\n className,\n ref,\n}: CheckboxProps) {\n return (\n <label className={`${styles.checkbox} ${className ?? ''}`}>\n <span className={styles.control}>\n <input\n ref={ref}\n type=\"checkbox\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n onBlur={onBlur}\n name={name}\n aria-label={ariaLabel}\n disabled={disabled}\n />\n <span className={styles.box}>\n <svg className={styles.icon} viewBox=\"0 0 17 18\" aria-hidden=\"true\">\n <polyline points=\"1 9 7 14 15 4\" />\n </svg>\n </span>\n </span>\n {label && <span className={styles.labelText}>{label}</span>}\n </label>\n );\n}\n\n/**\n * The checkbox visual without an input, for rows that already carry the state\n * themselves (e.g. multi-select menu options). Purely decorative.\n */\nexport function CheckboxIndicator({ checked, disabled }: { checked: boolean; disabled?: boolean }) {\n return (\n <span\n className={`${styles.box} ${styles.indicator}`}\n data-checked={checked}\n data-disabled={disabled || undefined}\n aria-hidden=\"true\"\n >\n <svg className={styles.icon} viewBox=\"0 0 17 18\" aria-hidden=\"true\">\n <polyline points=\"1 9 7 14 15 4\" />\n </svg>\n </span>\n );\n}\n\ninterface CheckboxGroupItem {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\ninterface CheckboxGroupProps {\n label?: ReactNode;\n items: CheckboxGroupItem[];\n value: string[];\n onChange: (value: string[]) => void;\n disabled?: boolean;\n 'aria-label'?: string;\n}\n\nexport function CheckboxGroup({ label, items, value, onChange, disabled, ...rest }: CheckboxGroupProps) {\n function toggle(itemValue: string) {\n const next = value.includes(itemValue)\n ? value.filter((v) => v !== itemValue)\n : [...value, itemValue];\n onChange(next);\n }\n\n return (\n <div role=\"group\" aria-label={label ? undefined : rest['aria-label']} className={groupStyles.group}>\n {label && <FieldLabel className={groupStyles.groupLabel}>{label}</FieldLabel>}\n {items.map((item) => (\n <Checkbox\n key={item.value}\n checked={value.includes(item.value)}\n onChange={() => toggle(item.value)}\n label={item.label}\n disabled={disabled || item.disabled}\n />\n ))}\n </div>\n );\n}\n",".radio {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n padding: 8px 4px;\n}\n.control {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.labelText {\n font-size: var(--control-font-size);\n color: var(--text-primary);\n transition: color 0.2s ease-out;\n}\n.radio:hover .labelText {\n color: var(--brand-main);\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.circle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--depth-5);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1),\n transform 0.1s cubic-bezier(0, 0, 0.2, 1);\n}\n.radio:hover .circle {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .circle {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:active + .circle {\n transform: scale(0.88);\n}\n.input:checked + .circle {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.radio:hover .input:checked + .circle {\n box-shadow: 0 0 0 1px var(--brand-main);\n}\n.dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #fff;\n transform: scale(0);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .circle .dot {\n transform: scale(1);\n}\n.radio:has(.input:disabled),\n.input:disabled {\n cursor: not-allowed;\n}\n.radio:has(.input:disabled) .labelText {\n color: var(--disabled-text);\n}\n.radio:has(.input:disabled) .circle {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n transform: none;\n}\n.radio:has(.input:disabled) .input:checked + .circle {\n background: var(--disabled-bg);\n box-shadow: inset 0 0 0 1px var(--disabled-bg);\n}\n","import type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport styles from './RadioButton.module.css';\nimport groupStyles from './OptionGroup.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ninterface RadioButtonProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur?: (e: FocusEvent<HTMLInputElement>) => void;\n name?: string;\n value?: string;\n label?: ReactNode;\n ariaLabel?: string;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\nexport function RadioButton({\n checked,\n onChange,\n onBlur,\n name,\n value,\n label,\n ariaLabel,\n disabled,\n className,\n ref,\n}: RadioButtonProps) {\n return (\n <label className={`${styles.radio} ${className ?? ''}`}>\n <span className={styles.control}>\n <input\n ref={ref}\n type=\"radio\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n onBlur={onBlur}\n name={name}\n value={value}\n aria-label={ariaLabel}\n disabled={disabled}\n />\n <span className={styles.circle}>\n <span className={styles.dot} />\n </span>\n </span>\n {label && <span className={styles.labelText}>{label}</span>}\n </label>\n );\n}\n\ninterface RadioGroupItem {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\ninterface RadioGroupProps {\n label?: ReactNode;\n name: string;\n items: RadioGroupItem[];\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n 'aria-label'?: string;\n}\n\nexport function RadioGroup({ label, name, items, value, onChange, disabled, ...rest }: RadioGroupProps) {\n return (\n <div\n role=\"radiogroup\"\n aria-label={label ? undefined : rest['aria-label']}\n className={groupStyles.group}\n >\n {label && <FieldLabel className={groupStyles.groupLabel}>{label}</FieldLabel>}\n {items.map((item) => (\n <RadioButton\n key={item.value}\n name={name}\n value={item.value}\n checked={value === item.value}\n onChange={() => onChange(item.value)}\n label={item.label}\n disabled={disabled || item.disabled}\n />\n ))}\n </div>\n );\n}\n",".switch {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n}\n.switch:has(.input:disabled) {\n cursor: not-allowed;\n}\n.control {\n position: relative;\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.input:disabled {\n cursor: not-allowed;\n}\n.track {\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 999px;\n background: var(--depth-5);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1);\n}\n.switch:hover .track {\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .track {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:checked + .track {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.input:disabled + .track {\n background: var(--surface-muted);\n box-shadow: inset 0 0 0 1px var(--border);\n}\n.thumb {\n position: absolute;\n top: 50%;\n left: 2px;\n border-radius: 50%;\n background: #fff;\n transform: translateY(-50%);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .track .thumb {\n transform: translateY(-50%) translateX(var(--switch-thumb-travel));\n}\n\n.sm {\n width: 32px;\n height: 18px;\n --switch-thumb-travel: 14px;\n}\n.sm .thumb {\n width: 14px;\n height: 14px;\n}\n.base {\n width: 40px;\n height: 22px;\n --switch-thumb-travel: 18px;\n}\n.base .thumb {\n width: 18px;\n height: 18px;\n}\n\n.labelText {\n font-size: var(--control-font-size);\n color: var(--text-primary);\n transition: color 0.2s ease-out;\n}\n.switch:hover .labelText {\n color: var(--brand-main);\n}\n.switch:has(.input:disabled) .labelText {\n color: var(--disabled-text);\n}\n","import type { ChangeEvent, ReactNode } from 'react';\nimport styles from './Switch.module.css';\n\ntype SwitchSize = 'sm' | 'base';\n\ninterface SwitchProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n size?: SwitchSize;\n label?: ReactNode;\n ariaLabel?: string;\n disabled?: boolean;\n className?: string;\n}\n\nexport function Switch({\n checked,\n onChange,\n size = 'base',\n label,\n ariaLabel,\n disabled,\n className,\n}: SwitchProps) {\n return (\n <label className={`${styles.switch} ${className ?? ''}`}>\n <span className={`${styles.control} ${styles[size]}`}>\n <input\n type=\"checkbox\"\n role=\"switch\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n aria-label={ariaLabel}\n disabled={disabled}\n />\n <span className={styles.track}>\n <span className={styles.thumb} />\n </span>\n </span>\n {label && <span className={styles.labelText}>{label}</span>}\n </label>\n );\n}\n",".field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.inputWrap {\n position: relative;\n display: flex;\n align-items: center;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n transition: box-shadow 0.2s ease-out;\n}\n.inputWrap:hover:not(:focus-within, :has(.input:disabled), .toolbar) {\n box-shadow:\n inset 0 0 0 1px var(--border-input),\n 0 0 0 2px var(--brand-main-30);\n}\n.inputWrap:focus-within {\n box-shadow:\n inset 0 0 0 1.5px var(--brand-main),\n 0 0 0 2px var(--border-input);\n}\n.errorWrap {\n box-shadow: inset 0 0 0 1px rgba(var(--danger-rgb), 0.2);\n}\n.errorWrap:focus-within {\n box-shadow:\n inset 0 0 0 1.5px var(--danger-text),\n 0 0 0 2px rgba(var(--danger-rgb), 0.3);\n}\n.inputWrap.errorWrap:hover:not(:focus-within, :has(.input:disabled), .toolbar) {\n box-shadow:\n inset 0 0 0 1px rgba(var(--danger-rgb), 0.2),\n 0 0 0 2px rgba(var(--danger-rgb), 0.3);\n}\n.inputWrap:has(.input:disabled) {\n background: var(--surface-muted);\n}\n\n.toolbar {\n background: none;\n box-shadow: none;\n}\n.toolbar::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n opacity: 0;\n transition: opacity 0.2s ease-out;\n}\n.toolbar:focus-within {\n box-shadow: none;\n}\n.toolbar:focus-within::after {\n opacity: 1;\n}\n.toolbar.errorWrap,\n.toolbar.errorWrap:focus-within {\n box-shadow: none;\n}\n.toolbar.errorWrap::after {\n background: var(--danger-text);\n opacity: 1;\n}\n\n.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n}\n.sm .input {\n padding: 0 12px;\n font-size: var(--control-font-size);\n}\n.base {\n height: var(--control-height-base);\n border-radius: var(--radius-base);\n}\n.base .input {\n padding: 0 14px;\n font-size: var(--control-font-size);\n}\n.inputWrap:has(.icon) .input {\n padding-left: 8px;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 12px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n background: none;\n font-family: inherit;\n color: var(--text-primary);\n font-weight: var(--font-weight-regular);\n}\n.input:focus {\n outline: none;\n}\n.input::placeholder {\n color: var(--text-tertiary);\n}\n.input:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n.trailing {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n margin-right: 6px;\n padding: 0;\n border: none;\n border-radius: 8px;\n background: none;\n color: var(--text-tertiary);\n cursor: pointer;\n flex-shrink: 0;\n transition: color 0.15s ease-out, background 0.15s ease-out;\n}\n.trailing svg {\n width: 16px;\n height: 16px;\n}\n.trailing:hover:not(:disabled) {\n color: var(--brand-main);\n background: var(--brand-main-5);\n}\n.trailing:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: -2px;\n}\n.trailing:disabled {\n cursor: not-allowed;\n}\n.pickerInput {\n cursor: pointer;\n caret-color: transparent;\n}\n.pickerInput:disabled {\n cursor: not-allowed;\n}\n","import { useId, type InputHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport styles from './TextField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype TextFieldSize = 'sm' | 'base';\ntype TextFieldVariant = 'default' | 'toolbar';\n\ninterface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: TextFieldSize;\n variant?: TextFieldVariant;\n leadingIcon?: ReactNode;\n /** Extra classes for layout around the field — width, flex growth. Appended after its own class. */\n className?: string;\n /** Reaches the <input>, e.g. for a form library to focus a field that failed validation. */\n ref?: Ref<HTMLInputElement>;\n}\n\nexport function TextField({\n label,\n helperText,\n error,\n size = 'base',\n variant = 'default',\n leadingIcon,\n id,\n className,\n ref,\n ...rest\n}: TextFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div\n className={`${styles.inputWrap} ${styles[variant]} ${styles[size]} ${error ? styles.errorWrap : ''}`}\n >\n {leadingIcon && <span className={styles.icon}>{leadingIcon}</span>}\n <input ref={ref} id={inputId} className={styles.input} {...rest} />\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n","/* TODO: .wrap / .errorWrap / .disabled / text styles duplicate TextField.module.css.\n Extract into a shared field.module.css once both are touched together. */\n.field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.wrap {\n display: flex;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n transition: box-shadow 0.2s ease-out;\n}\n.wrap:focus-within:not(.readOnly) {\n box-shadow:\n inset 0 0 0 0 var(--border-input),\n 0 0 0 2px var(--brand-main);\n}\n.errorWrap,\n.errorWrap:focus-within:not(.readOnly) {\n box-shadow: inset 0 0 0 1px var(--danger-text);\n}\n.disabled {\n background: var(--surface-muted);\n}\n\n.sm {\n border-radius: var(--radius-sm);\n}\n.sm .textarea {\n padding: 8px 12px;\n}\n.base {\n border-radius: var(--radius-base);\n}\n.base .textarea {\n padding: 12px 14px;\n}\n\n.textarea {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n border-radius: inherit;\n background: none;\n font-family: inherit;\n font-size: var(--control-font-size);\n line-height: 1.4;\n color: var(--text-primary);\n font-weight: var(--font-weight-regular);\n}\n.textarea:focus {\n outline: none;\n}\n.textarea::placeholder {\n color: var(--text-tertiary);\n}\n.textarea:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.textarea:read-only:not(:disabled) {\n cursor: text;\n}\n.resize-none {\n resize: none;\n}\n.resize-vertical {\n resize: vertical;\n}\n\n.footer {\n display: flex;\n justify-content: space-between;\n gap: 8px;\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n.count {\n margin-left: auto;\n font-size: 0.78rem;\n color: var(--text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n.countNear {\n color: var(--warning-text);\n}\n.countLimit {\n color: var(--danger-text);\n}\n","import {\n useCallback,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ChangeEvent,\n type Ref,\n type TextareaHTMLAttributes,\n} from 'react';\nimport styles from './TextArea.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype TextAreaSize = 'sm' | 'base';\n\ninterface TextAreaProps\n extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'className' | 'size'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: TextAreaSize;\n /** Manual resize handle. Ignored (forced to 'none') when `autoResize` is on. */\n resize?: 'none' | 'vertical';\n /** The field grows as the text grows. */\n autoResize?: boolean;\n /** Growth ceiling for `autoResize`, in rows. Past it the field scrolls internally. */\n maxRows?: number;\n /** Shows a character counter under the field, on the right. */\n showCount?: boolean;\n /** Extra classes for layout around the field — width, flex growth. Appended after its own class. */\n className?: string;\n /** Reaches the <textarea>, e.g. for a form library to focus a field that failed validation. */\n ref?: Ref<HTMLTextAreaElement>;\n}\n\nfunction setRef<T>(ref: Ref<T> | undefined, node: T | null) {\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n}\n\nexport function TextArea({\n label,\n helperText,\n error,\n size = 'base',\n resize = 'vertical',\n autoResize = false,\n maxRows = 8,\n showCount = false,\n id,\n className,\n ref,\n rows = 3,\n value,\n defaultValue,\n maxLength,\n disabled,\n readOnly,\n onChange,\n onInput,\n 'aria-describedby': ariaDescribedBy,\n ...rest\n}: TextAreaProps) {\n const generatedId = useId();\n const fieldId = id ?? generatedId;\n const textRef = useRef<HTMLTextAreaElement | null>(null);\n\n const isControlled = value !== undefined;\n const [uncontrolledLength, setUncontrolledLength] = useState(() =>\n String(defaultValue ?? '').length,\n );\n const length = isControlled ? String(value).length : uncontrolledLength;\n\n const fit = useCallback(() => {\n const el = textRef.current;\n if (!el || !autoResize) return;\n const cs = getComputedStyle(el);\n const fontSize = parseFloat(cs.fontSize) || 14;\n const lineHeight = parseFloat(cs.lineHeight) || fontSize * 1.4;\n const padding = (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);\n const maxHeight = lineHeight * maxRows + padding;\n el.style.height = 'auto';\n const next = Math.min(el.scrollHeight, maxHeight);\n el.style.height = `${next}px`;\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }, [autoResize, maxRows]);\n\n // Re-fit on value, rows, size and settings changes (covers mount too).\n useLayoutEffect(() => {\n fit();\n }, [fit, value, rows, size]);\n\n // The wrapped line count depends on width, so re-fit when the width changes.\n useLayoutEffect(() => {\n const el = textRef.current;\n if (!autoResize || !el || typeof ResizeObserver === 'undefined') return;\n let lastWidth = el.clientWidth;\n const observer = new ResizeObserver(() => {\n if (el.clientWidth === lastWidth) return;\n lastWidth = el.clientWidth;\n fit();\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [autoResize, fit]);\n\n // Without autoResize, drop inline styles left over from a previous run.\n useLayoutEffect(() => {\n const el = textRef.current;\n if (autoResize || !el) return;\n el.style.height = '';\n el.style.overflowY = '';\n }, [autoResize]);\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setUncontrolledLength(e.target.value.length);\n onChange?.(e);\n };\n\n const handleInput = (e: Parameters<NonNullable<TextAreaProps['onInput']>>[0]) => {\n if (!isControlled) {\n setUncontrolledLength(e.currentTarget.value.length);\n fit();\n }\n onInput?.(e);\n };\n\n const helperId = `${fieldId}-helper`;\n const errorId = `${fieldId}-error`;\n const countId = `${fieldId}-count`;\n const describedBy =\n [ariaDescribedBy, error ? errorId : helperText ? helperId : null, showCount ? countId : null]\n .filter(Boolean)\n .join(' ') || undefined;\n\n const ratio = maxLength ? length / maxLength : 0;\n const countClass =\n ratio >= 1 ? styles.countLimit : ratio >= 0.9 ? styles.countNear : '';\n\n const wrapClass = [\n styles.wrap,\n styles[size],\n error ? styles.errorWrap : '',\n disabled ? styles.disabled : '',\n readOnly ? styles.readOnly : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n const effectiveResize = autoResize ? 'none' : resize;\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={fieldId}>{label}</FieldLabel>}\n <div className={wrapClass}>\n <textarea\n {...rest}\n ref={(node) => {\n textRef.current = node;\n setRef(ref, node);\n }}\n id={fieldId}\n className={`${styles.textarea} ${styles[`resize-${effectiveResize}`]}`}\n rows={rows}\n value={value}\n defaultValue={defaultValue}\n maxLength={maxLength}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={error ? true : rest['aria-invalid']}\n aria-describedby={describedBy}\n onChange={handleChange}\n onInput={handleInput}\n />\n </div>\n {(error || helperText || showCount) && (\n <div className={styles.footer}>\n {error ? (\n <span id={errorId} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={helperId} className={styles.helperText}>\n {helperText}\n </span>\n ) : null}\n {showCount && (\n <span id={countId} className={`${styles.count} ${countClass}`}>\n {maxLength ? `${length} / ${maxLength}` : length}\n </span>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useId, useState, type InputHTMLAttributes, type Ref } from 'react';\nimport { Eye, EyeOff } from 'lucide-react';\nimport styles from './TextField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype PasswordFieldSize = 'sm' | 'base';\n\ninterface PasswordFieldProps\n extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size' | 'type'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: PasswordFieldSize;\n /** Accessible name of the toggle while the value is hidden. */\n showLabel?: string;\n /** Accessible name of the toggle while the value is shown. */\n hideLabel?: string;\n /** Start with the value shown. */\n defaultVisible?: boolean;\n /** Extra classes for layout around the field. */\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/** A text field for passwords and PINs, with a button that shows or hides what was typed. */\nexport function PasswordField({\n label,\n helperText,\n error,\n size = 'base',\n showLabel = 'Show password',\n hideLabel = 'Hide password',\n defaultVisible = false,\n id,\n className,\n ref,\n disabled,\n ...rest\n}: PasswordFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const [visible, setVisible] = useState(defaultVisible);\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div className={`${styles.inputWrap} ${styles.default} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n <input\n ref={ref}\n id={inputId}\n className={styles.input}\n type={visible ? 'text' : 'password'}\n autoComplete=\"off\"\n disabled={disabled}\n {...rest}\n />\n <button\n type=\"button\"\n className={styles.trailing}\n aria-label={visible ? hideLabel : showLabel}\n aria-pressed={visible}\n aria-controls={inputId}\n disabled={disabled}\n onClick={() => setVisible((v) => !v)}\n >\n {visible ? <EyeOff /> : <Eye />}\n </button>\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n","import { useId, useRef, type InputHTMLAttributes, type Ref } from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport styles from './TextField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype DateFieldSize = 'sm' | 'base';\n\ninterface DateFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: DateFieldSize;\n /** Accessible name of the button next to the date. */\n openLabel?: string;\n /** Extra classes for layout around the field. */\n className?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/**\n * Shows a picked date and opens a calendar on click. It renders no calendar\n * itself: pass it as the input of a date picker (e.g. react-datepicker's\n * `customInput`), which supplies `value`, `onClick` and `ref`.\n */\nexport function DateField({\n label,\n helperText,\n error,\n size = 'base',\n openLabel = 'Open calendar',\n id,\n className,\n ref,\n onClick,\n disabled,\n ...rest\n}: DateFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n function setRefs(el: HTMLInputElement | null) {\n inputRef.current = el;\n if (typeof ref === 'function') ref(el);\n else if (ref) ref.current = el;\n }\n\n return (\n <div className={[styles.field, className].filter(Boolean).join(' ')}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div className={`${styles.inputWrap} ${styles.default} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n <input\n {...rest}\n ref={setRefs}\n id={inputId}\n className={`${styles.input} ${styles.pickerInput}`}\n inputMode=\"none\"\n readOnly\n disabled={disabled}\n onClick={onClick}\n />\n <button\n type=\"button\"\n tabIndex={-1}\n className={styles.trailing}\n aria-label={openLabel}\n disabled={disabled}\n onClick={() => inputRef.current?.click()}\n >\n <ChevronDown />\n </button>\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n","/*\n * Calendar-day arithmetic on local dates. Time of day is ignored everywhere and\n * every returned Date is local midnight. Days are always built with\n * `new Date(y, m, d)` rather than by adding milliseconds, so DST changes and\n * UTC-12…UTC+14 offsets can never move a date to a neighbouring day.\n */\n\nexport type WeekStart = 0 | 1;\n\nexport function startOfDay(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate());\n}\n\nexport function addDays(date: Date, days: number): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);\n}\n\nexport function daysInMonth(year: number, month: number): number {\n return new Date(year, month + 1, 0).getDate();\n}\n\n/** Moves by whole months, keeping the day of month where possible (Jan 31 + 1 → Feb 28/29). */\nexport function addMonths(date: Date, months: number): Date {\n const target = new Date(date.getFullYear(), date.getMonth() + months, 1);\n const day = Math.min(date.getDate(), daysInMonth(target.getFullYear(), target.getMonth()));\n return new Date(target.getFullYear(), target.getMonth(), day);\n}\n\nexport function isSameDay(a: Date, b: Date): boolean {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n}\n\n/** Negative when `a` is an earlier calendar day than `b`, positive when later, 0 when the same day. */\nexport function compareDays(a: Date, b: Date): number {\n return (\n a.getFullYear() - b.getFullYear() || a.getMonth() - b.getMonth() || a.getDate() - b.getDate()\n );\n}\n\nexport function isDayDisabled(date: Date, minDate?: Date, maxDate?: Date): boolean {\n if (minDate && compareDays(date, minDate) < 0) return true;\n if (maxDate && compareDays(date, maxDate) > 0) return true;\n return false;\n}\n\n/** Pulls a day into [minDate, maxDate]. */\nexport function clampDay(date: Date, minDate?: Date, maxDate?: Date): Date {\n if (minDate && compareDays(date, minDate) < 0) return startOfDay(minDate);\n if (maxDate && compareDays(date, maxDate) > 0) return startOfDay(maxDate);\n return startOfDay(date);\n}\n\n/** First day of the week containing `date`. */\nexport function startOfWeek(date: Date, weekStartsOn: WeekStart): Date {\n const offset = (date.getDay() - weekStartsOn + 7) % 7;\n return addDays(date, -offset);\n}\n\nexport function endOfWeek(date: Date, weekStartsOn: WeekStart): Date {\n return addDays(startOfWeek(date, weekStartsOn), 6);\n}\n\nexport interface GridDay {\n date: Date;\n /** False for the leading/trailing days that belong to a neighbouring month. */\n inMonth: boolean;\n}\n\nconst GRID_WEEKS = 6;\n\n/**\n * Month page as six full weeks (a fixed height keeps the popup from jumping\n * between months), padded with days of the neighbouring months.\n */\nexport function getMonthGrid(year: number, month: number, weekStartsOn: WeekStart): GridDay[][] {\n const first = startOfWeek(new Date(year, month, 1), weekStartsOn);\n const weeks: GridDay[][] = [];\n for (let w = 0; w < GRID_WEEKS; w++) {\n const week: GridDay[] = [];\n for (let d = 0; d < 7; d++) {\n const date = addDays(first, w * 7 + d);\n week.push({ date, inMonth: date.getMonth() === month });\n }\n weeks.push(week);\n }\n return weeks;\n}\n",".calendar {\n width: 100%;\n max-width: 100%;\n font-family: inherit;\n color: var(--text-primary);\n}\n.header {\n display: grid;\n grid-template-columns: var(--control-height-sm) 1fr var(--control-height-sm);\n align-items: center;\n margin-bottom: 8px;\n}\n.header .navButton {\n border-radius: 50%;\n}\n/* Disabled tertiary buttons turn into a grey disc; here they should just fade. */\n.header .navButton:disabled {\n background: transparent;\n box-shadow: none;\n}\n.title {\n text-align: center;\n font-size: 0.9rem;\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n.grid {\n display: flex;\n flex-direction: column;\n}\n.row {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n}\n.weekday {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 28px;\n font-size: 0.75rem;\n color: var(--text-tertiary);\n user-select: none;\n}\n.day {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 36px;\n margin: 0;\n padding: 0;\n border: none;\n border-radius: var(--radius-sm);\n background: transparent;\n font-family: inherit;\n font-size: 0.9rem;\n color: var(--text-primary);\n cursor: pointer;\n transition: background 0.15s ease-out;\n}\n.day:hover:not(.selected, .disabled) {\n background: var(--brand-main-5);\n}\n.day:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 1px;\n}\n.outside {\n color: var(--text-tertiary);\n}\n.today {\n color: var(--brand-main);\n}\n.selected,\n.selected.outside,\n.selected.today {\n background: var(--brand-main);\n color: #fff;\n font-weight: var(--font-weight-medium);\n}\n.day.disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n@media (prefers-reduced-motion: reduce) {\n .day {\n transition: none;\n }\n}\n","import { useEffect, useId, useMemo, useRef, useState, type KeyboardEvent } from 'react';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { Button } from './Button';\nimport {\n addDays,\n addMonths,\n clampDay,\n endOfWeek,\n getMonthGrid,\n isDayDisabled,\n isSameDay,\n startOfDay,\n startOfWeek,\n type WeekStart,\n} from '../utils/date';\nimport styles from './Calendar.module.css';\n\ninterface CalendarProps {\n value: Date | null;\n /** Receives the picked day as a Date at local midnight. */\n onChange: (date: Date) => void;\n minDate?: Date;\n maxDate?: Date;\n /** BCP 47 tag, e.g. 'en' or 'es'. Names of months and weekdays follow it. */\n locale?: string;\n /** 0 = Sunday, 1 = Monday. */\n weekStartsOn?: WeekStart;\n /** Move keyboard focus to the selected (or today's) day on mount. */\n autoFocus?: boolean;\n /** Accessible name of the previous-month button. */\n previousMonthLabel?: string;\n /** Accessible name of the next-month button. */\n nextMonthLabel?: string;\n /** Extra classes for layout around the calendar. */\n className?: string;\n}\n\nconst dayKey = (d: Date) => `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;\n\n/** Intl returns lowercase month names in some locales (es); the title reads better capitalised. */\nfunction capitalize(text: string, locale: string): string {\n return text.charAt(0).toLocaleUpperCase(locale) + text.slice(1);\n}\n\n/** Month grid with keyboard navigation. Has no surface of its own; a popup or card supplies it. */\nexport function Calendar({\n value,\n onChange,\n minDate,\n maxDate,\n locale = 'en',\n weekStartsOn = 0,\n autoFocus,\n previousMonthLabel = 'Previous month',\n nextMonthLabel = 'Next month',\n className,\n}: CalendarProps) {\n // The focused day drives the visible month, so keyboard and buttons share one source of truth.\n const [focused, setFocused] = useState(() => clampDay(value ?? new Date(), minDate, maxDate));\n const valueKey = value ? dayKey(value) : null;\n const [prevValueKey, setPrevValueKey] = useState(valueKey);\n if (valueKey !== prevValueKey) {\n setPrevValueKey(valueKey);\n if (value) setFocused(clampDay(value, minDate, maxDate));\n }\n\n const gridRef = useRef<HTMLDivElement>(null);\n const shouldFocusRef = useRef(Boolean(autoFocus));\n const titleId = useId();\n\n useEffect(() => {\n if (!shouldFocusRef.current) return;\n shouldFocusRef.current = false;\n gridRef.current?.querySelector<HTMLElement>(`[data-date=\"${dayKey(focused)}\"]`)?.focus();\n }, [focused]);\n\n const year = focused.getFullYear();\n const month = focused.getMonth();\n const weeks = useMemo(() => getMonthGrid(year, month, weekStartsOn), [year, month, weekStartsOn]);\n const today = startOfDay(new Date());\n\n const format = useMemo(\n () => ({\n title: new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }),\n short: new Intl.DateTimeFormat(locale, { weekday: 'short' }),\n long: new Intl.DateTimeFormat(locale, { weekday: 'long' }),\n full: new Intl.DateTimeFormat(locale, { dateStyle: 'full' }),\n }),\n [locale],\n );\n\n // Row 0 of the grid already holds one of each weekday, in display order.\n const weekdays = weeks[0].map(({ date }) => ({\n short: capitalize(format.short.format(date), locale).slice(0, 2),\n long: format.long.format(date),\n }));\n\n // A page is unreachable when its whole month lies outside [minDate, maxDate].\n const prevBlocked = (d: Date) => Boolean(minDate) && new Date(d.getFullYear(), d.getMonth(), 0) < startOfDay(minDate!);\n const nextBlocked = (d: Date) => Boolean(maxDate) && new Date(d.getFullYear(), d.getMonth() + 1, 1) > startOfDay(maxDate!);\n const prevDisabled = prevBlocked(focused);\n const nextDisabled = nextBlocked(focused);\n\n function moveFocus(next: Date) {\n shouldFocusRef.current = true;\n setFocused(clampDay(next, minDate, maxDate));\n }\n\n function shiftMonth(delta: number) {\n const next = clampDay(addMonths(focused, delta), minDate, maxDate);\n // The button just pressed is about to be disabled; keep focus from falling to <body>.\n shouldFocusRef.current = delta < 0 ? prevBlocked(next) : nextBlocked(next);\n setFocused(next);\n }\n\n function handleKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n let next: Date | null = null;\n switch (e.key) {\n case 'ArrowLeft':\n next = addDays(focused, -1);\n break;\n case 'ArrowRight':\n next = addDays(focused, 1);\n break;\n case 'ArrowUp':\n next = addDays(focused, -7);\n break;\n case 'ArrowDown':\n next = addDays(focused, 7);\n break;\n case 'PageUp':\n next = addMonths(focused, -1);\n break;\n case 'PageDown':\n next = addMonths(focused, 1);\n break;\n case 'Home':\n next = startOfWeek(focused, weekStartsOn);\n break;\n case 'End':\n next = endOfWeek(focused, weekStartsOn);\n break;\n }\n if (!next) return;\n e.preventDefault();\n moveFocus(next);\n }\n\n function pick(date: Date) {\n const day = startOfDay(date);\n setFocused(day);\n onChange(day);\n }\n\n return (\n <div className={[styles.calendar, className].filter(Boolean).join(' ')}>\n <div className={styles.header}>\n <Button\n variant=\"tertiary\"\n size=\"sm\"\n className={styles.navButton}\n leadingIcon={<ChevronLeft />}\n aria-label={previousMonthLabel}\n disabled={prevDisabled}\n onClick={() => shiftMonth(-1)}\n />\n <div id={titleId} className={styles.title} aria-live=\"polite\">\n {capitalize(format.title.format(focused), locale)}\n </div>\n <Button\n variant=\"tertiary\"\n size=\"sm\"\n className={styles.navButton}\n leadingIcon={<ChevronRight />}\n aria-label={nextMonthLabel}\n disabled={nextDisabled}\n onClick={() => shiftMonth(1)}\n />\n </div>\n <div ref={gridRef} role=\"grid\" aria-labelledby={titleId} className={styles.grid} onKeyDown={handleKeyDown}>\n <div role=\"row\" className={styles.row}>\n {weekdays.map((day) => (\n <span key={day.long} role=\"columnheader\" aria-label={day.long} className={styles.weekday}>\n {day.short}\n </span>\n ))}\n </div>\n {weeks.map((week) => (\n <div role=\"row\" className={styles.row} key={dayKey(week[0].date)}>\n {week.map(({ date, inMonth }) => {\n const disabled = isDayDisabled(date, minDate, maxDate);\n const selected = Boolean(value) && isSameDay(date, value!);\n const isToday = isSameDay(date, today);\n return (\n <button\n key={dayKey(date)}\n type=\"button\"\n role=\"gridcell\"\n data-date={dayKey(date)}\n tabIndex={isSameDay(date, focused) ? 0 : -1}\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n aria-current={isToday ? 'date' : undefined}\n aria-label={format.full.format(date)}\n className={[\n styles.day,\n !inMonth && styles.outside,\n isToday && styles.today,\n selected && styles.selected,\n disabled && styles.disabled,\n ]\n .filter(Boolean)\n .join(' ')}\n // Keeps a click on an unavailable day from stealing focus.\n onMouseDown={disabled ? (e) => e.preventDefault() : undefined}\n onClick={disabled ? undefined : () => pick(date)}\n >\n {date.getDate()}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n </div>\n );\n}\n",".popup {\n position: fixed;\n top: 0;\n left: 0;\n z-index: var(--z-popover);\n box-sizing: border-box;\n width: 276px; /* 7 × 36px columns + 12px padding either side */\n max-width: calc(100vw - 16px);\n padding: 12px;\n border-radius: var(--radius-base);\n background: var(--card-surface);\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px var(--depth-10);\n}\n\n/* Phones: a bottom sheet spanning the screen with 8px margins. */\n@media (max-width: 480px) {\n .popup {\n top: auto;\n left: 8px;\n right: 8px;\n bottom: 8px;\n width: auto;\n max-width: none;\n }\n}\n","import {\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { Calendar } from './Calendar';\nimport { DateField } from './DateField';\nimport type { WeekStart } from '../utils/date';\nimport styles from './DatePicker.module.css';\n\ntype DatePickerSize = 'sm' | 'base';\n\ninterface DatePickerProps {\n value: Date | null;\n /** Receives the picked day as a Date at local midnight. */\n onChange: (date: Date | null) => void;\n minDate?: Date;\n maxDate?: Date;\n disabled?: boolean;\n /** BCP 47 tag, e.g. 'en' or 'es'. Names of months and weekdays follow it. */\n locale?: string;\n /** 0 = Sunday, 1 = Monday. */\n weekStartsOn?: WeekStart;\n /** How the picked date reads in the field. Defaults to month + two-digit day, e.g. \"Oct 03\". */\n formatValue?: (date: Date) => string;\n /** Which edge of the field the popup lines up with. It flips above the field when there is no room below. */\n placement?: 'bottom-start' | 'bottom-end';\n label?: string;\n helperText?: string;\n error?: string;\n size?: DatePickerSize;\n /** Accessible name of the chevron button in the field. */\n openLabel?: string;\n placeholder?: string;\n /** Accessible name of the popup. */\n dialogLabel?: string;\n /** Extra classes for layout around the field — width and the like. */\n className?: string;\n id?: string;\n}\n\n/** Keep in sync with the bottom-sheet breakpoint in DatePicker.module.css. */\nconst SHEET_QUERY = '(max-width: 480px)';\nconst GAP = 4;\nconst VIEWPORT_MARGIN = 8;\n\n/** A date field that opens a `Calendar` in a popup. The popup is portalled to <body> so no parent can clip it. */\nexport function DatePicker({\n value,\n onChange,\n minDate,\n maxDate,\n disabled,\n locale = 'en',\n weekStartsOn = 0,\n formatValue,\n placement = 'bottom-start',\n label,\n helperText,\n error,\n size,\n openLabel,\n placeholder,\n dialogLabel = 'Choose date',\n className,\n id,\n}: DatePickerProps) {\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const popupRef = useRef<HTMLDivElement>(null);\n const popupId = useId();\n const isOpen = open && !disabled;\n\n const defaultFormat = useMemo(\n () => new Intl.DateTimeFormat(locale, { month: 'short', day: '2-digit' }),\n [locale],\n );\n const text = value ? (formatValue ? formatValue(value) : defaultFormat.format(value)) : '';\n\n // The visible field box (not the label or helper text) is what the popup attaches to.\n const getAnchor = useCallback(() => inputRef.current?.parentElement ?? inputRef.current, []);\n\n const reposition = useCallback(() => {\n const popup = popupRef.current;\n const anchor = getAnchor();\n if (!popup || !anchor) return;\n if (window.matchMedia(SHEET_QUERY).matches) {\n // CSS docks the popup to the bottom of the screen.\n popup.style.left = '';\n popup.style.top = '';\n return;\n }\n const rect = anchor.getBoundingClientRect();\n const width = popup.offsetWidth;\n const height = popup.offsetHeight;\n const viewportWidth = document.documentElement.clientWidth;\n const viewportHeight = window.innerHeight;\n\n let left = placement === 'bottom-end' ? rect.right - width : rect.left;\n left = Math.max(VIEWPORT_MARGIN, Math.min(left, viewportWidth - width - VIEWPORT_MARGIN));\n\n let top = rect.bottom + GAP;\n const fitsBelow = top + height <= viewportHeight - VIEWPORT_MARGIN;\n const roomAbove = rect.top - GAP - height >= VIEWPORT_MARGIN;\n if (!fitsBelow && roomAbove) top = rect.top - GAP - height;\n\n popup.style.left = `${left}px`;\n popup.style.top = `${top}px`;\n }, [getAnchor, placement]);\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n reposition();\n window.addEventListener('resize', reposition);\n window.addEventListener('scroll', reposition, true);\n return () => {\n window.removeEventListener('resize', reposition);\n window.removeEventListener('scroll', reposition, true);\n };\n }, [isOpen, reposition]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n function close() {\n setOpen(false);\n inputRef.current?.focus();\n }\n\n function onPointerDown(e: PointerEvent) {\n const target = e.target as Node;\n if (popupRef.current?.contains(target) || getAnchor()?.contains(target)) return;\n setOpen(false);\n }\n\n function onKeyDown(e: globalThis.KeyboardEvent) {\n if (e.key === 'Escape') {\n e.preventDefault();\n close();\n return;\n }\n if (e.key !== 'Tab') return;\n // Focus trap: Tab cycles through the popup's own controls.\n const popup = popupRef.current;\n if (!popup) return;\n const stops = Array.from(\n popup.querySelectorAll<HTMLElement>('button:not(:disabled):not([tabindex=\"-1\"])'),\n );\n if (stops.length === 0) {\n e.preventDefault();\n return;\n }\n const first = stops[0];\n const last = stops[stops.length - 1];\n const active = document.activeElement;\n if (!popup.contains(active)) {\n e.preventDefault();\n (e.shiftKey ? last : first).focus();\n } else if (e.shiftKey && active === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n\n window.addEventListener('pointerdown', onPointerDown);\n window.addEventListener('keydown', onKeyDown);\n return () => {\n window.removeEventListener('pointerdown', onPointerDown);\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [isOpen, getAnchor]);\n\n function handleFieldKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {\n e.preventDefault();\n if (!disabled) setOpen(true);\n }\n }\n\n function handleSelect(date: Date) {\n onChange(date);\n setOpen(false);\n inputRef.current?.focus();\n }\n\n return (\n <>\n <DateField\n ref={inputRef}\n id={id}\n className={className}\n label={label}\n helperText={helperText}\n error={error}\n size={size}\n openLabel={openLabel}\n placeholder={placeholder}\n disabled={disabled}\n value={text}\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? popupId : undefined}\n onClick={() => !disabled && setOpen((o) => !o)}\n onKeyDown={handleFieldKeyDown}\n />\n {isOpen &&\n createPortal(\n <div ref={popupRef} id={popupId} role=\"dialog\" aria-label={dialogLabel} className={styles.popup}>\n <Calendar\n autoFocus\n value={value}\n onChange={handleSelect}\n minDate={minDate}\n maxDate={maxDate}\n locale={locale}\n weekStartsOn={weekStartsOn}\n />\n </div>,\n document.body,\n )}\n </>\n );\n}\n",".field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.inputWrap {\n position: relative;\n display: flex;\n align-items: center;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n transition: box-shadow 0.2s ease-out;\n}\n.inputWrap:focus-within {\n box-shadow:\n inset 0 0 0 0 var(--border-input),\n 0 0 0 2px var(--brand-main);\n}\n.errorWrap,\n.errorWrap:focus-within {\n box-shadow: inset 0 0 0 1px var(--danger-text);\n}\n.inputWrap:has(.input:disabled) {\n background: var(--surface-muted);\n}\n\n.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n}\n.sm .input {\n padding: 0 8px;\n font-size: var(--control-font-size);\n}\n.base {\n height: var(--control-height-base);\n border-radius: var(--radius-base);\n}\n.base .input {\n padding: 0 10px;\n font-size: var(--control-font-size);\n}\n.inputWrap:has(.prefix) .input {\n padding-left: 4px;\n}\n.inputWrap:has(.suffix) .input {\n padding-right: 4px;\n}\n\n.prefix,\n.suffix {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--text-tertiary);\n font-size: 0.78rem;\n white-space: nowrap;\n}\n.prefix {\n margin-left: 10px;\n}\n.suffix {\n margin-right: 10px;\n}\n\n.input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n background: none;\n font-family: inherit;\n color: var(--text-primary);\n font-weight: var(--font-weight-regular);\n font-variant-numeric: tabular-nums;\n appearance: textfield;\n -moz-appearance: textfield;\n}\n.input::-webkit-outer-spin-button,\n.input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n.input:focus {\n outline: none;\n}\n.input::placeholder {\n color: var(--text-tertiary);\n}\n.input:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n","import { useId, type InputHTMLAttributes, type ReactNode } from 'react';\nimport styles from './NumberField.module.css';\nimport { FieldLabel } from './FieldLabel';\n\ntype NumberFieldSize = 'sm' | 'base';\n\ninterface NumberFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size' | 'prefix'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: NumberFieldSize;\n /** Rendered inline before the value, e.g. \"$\". */\n prefix?: ReactNode;\n /** Rendered inline after the value, e.g. \"cows\", \"/cwt\". */\n suffix?: ReactNode;\n}\n\nexport function NumberField({\n label,\n helperText,\n error,\n size = 'base',\n prefix,\n suffix,\n id,\n ...rest\n}: NumberFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <div className={styles.field}>\n {label && <FieldLabel htmlFor={inputId}>{label}</FieldLabel>}\n <div className={`${styles.inputWrap} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n {prefix && <span className={styles.prefix}>{prefix}</span>}\n <input id={inputId} className={styles.input} {...rest} />\n {suffix && <span className={styles.suffix}>{suffix}</span>}\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n",".menu {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 180px;\n width: fit-content;\n padding: 4px;\n box-sizing: border-box;\n background: var(--card-surface);\n border-radius: 12px;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px rgba(0, 0, 0, 0.12);\n}\n.divider {\n height: 1px;\n background: var(--border);\n margin: 4px 6px;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Menu.module.css';\n\ninterface MenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {\n children: ReactNode;\n}\n\nexport function Menu({ children, ...rest }: MenuProps) {\n return (\n <div role=\"menu\" className={styles.menu} {...rest}>\n {children}\n </div>\n );\n}\n\nexport function MenuDivider() {\n return <div className={styles.divider} role=\"separator\" />;\n}\n",".item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n min-height: var(--control-height-sm);\n box-sizing: border-box;\n border: none;\n background: none;\n border-radius: 8px;\n padding: 8px 12px;\n font-family: inherit;\n font-size: var(--control-font-size);\n color: var(--text-primary);\n text-align: left;\n cursor: pointer;\n transition:\n background 0.15s ease-out,\n color 0.15s ease-out;\n}\n.item:hover:not(:disabled) {\n background: var(--brand-bg);\n color: var(--brand-dark);\n}\n.item:hover:not(:disabled) .icon,\n.item:hover:not(:disabled) .check {\n color: var(--brand-dark);\n}\n.item:active:not(:disabled) {\n background: var(--brand-main-20);\n}\n.item:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: -2px;\n}\n.item:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.leading {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n margin-left: -2px;\n}\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: -2px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.trailing {\n color: var(--text-tertiary);\n font-size: 0.8rem;\n margin-right: -2px;\n flex-shrink: 0;\n}\n.selected {\n background: var(--depth-5);\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n.selected .icon {\n color: var(--text-primary);\n}\n.check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 8px;\n color: var(--text-primary);\n flex-shrink: 0;\n}\n.selected .check {\n color: var(--brand-main);\n}\n.check svg {\n width: 100%;\n height: 100%;\n}\n.destructive {\n color: var(--danger-text);\n}\n.destructive .icon {\n color: var(--danger-text);\n}\n.destructive:hover:not(:disabled) {\n background: var(--danger-bg);\n color: var(--danger-text);\n}\n.destructive:hover:not(:disabled) .icon {\n color: var(--danger-text);\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport { Check } from 'lucide-react';\nimport styles from './MenuItem.module.css';\n\ninterface MenuItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n /** Raw content before the icon and label, e.g. a checkbox indicator. */\n leading?: ReactNode;\n icon?: ReactNode;\n trailing?: ReactNode;\n selected?: boolean;\n destructive?: boolean;\n children: ReactNode;\n}\n\nexport function MenuItem({ leading, icon, trailing, selected, destructive, children, ...rest }: MenuItemProps) {\n const classes = [styles.item, selected && styles.selected, destructive && styles.destructive]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button type=\"button\" role=\"menuitem\" className={classes} {...rest}>\n {leading && <span className={styles.leading}>{leading}</span>}\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{children}</span>\n {trailing && <span className={styles.trailing}>{trailing}</span>}\n {selected && (\n <span className={styles.check}>\n <Check />\n </span>\n )}\n </button>\n );\n}\n",".field,\n.fieldInline {\n --ease-out: cubic-bezier(0.22, 1, 0.36, 1);\n}\n.field {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.fieldInline {\n position: relative;\n display: inline-flex;\n flex-direction: column;\n vertical-align: top;\n}\n.trigger {\n display: flex;\n align-items: center;\n width: 100%;\n box-sizing: border-box;\n border: none;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n font-family: inherit;\n color: var(--text-primary);\n cursor: pointer;\n transition: box-shadow 0.2s ease-out;\n}\n.trigger:hover:not(:disabled, :focus-visible) {\n box-shadow:\n inset 0 0 0 1px var(--border-input),\n 0 0 0 2px var(--brand-main-30);\n}\n.trigger:focus-visible {\n outline: none;\n box-shadow:\n inset 0 0 0 1.5px var(--brand-main),\n 0 0 0 2px var(--border-input);\n}\n.errorWrap {\n box-shadow: inset 0 0 0 1px rgba(var(--danger-rgb), 0.2);\n}\n.trigger.errorWrap:focus-visible {\n box-shadow:\n inset 0 0 0 1.5px var(--danger-text),\n 0 0 0 2px rgba(var(--danger-rgb), 0.3);\n}\n.trigger.errorWrap:hover:not(:disabled, :focus-visible) {\n box-shadow:\n inset 0 0 0 1px rgba(var(--danger-rgb), 0.2),\n 0 0 0 2px rgba(var(--danger-rgb), 0.3);\n}\n.trigger:disabled {\n background: var(--surface-muted);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n\n.sm {\n border-radius: var(--radius-sm);\n}\n.sm.trigger {\n height: var(--control-height-sm);\n padding: 0 12px;\n font-size: var(--control-font-size);\n}\n.base {\n border-radius: var(--radius-base);\n}\n.base.trigger {\n height: var(--control-height-base);\n padding: 0 14px;\n font-size: var(--control-font-size);\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-right: 8px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.value {\n flex: 1;\n min-width: 0;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.placeholder {\n color: var(--text-tertiary);\n}\n.chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 8px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n transition: transform 0.3s var(--ease-out);\n}\n.chevron svg {\n width: 100%;\n height: 100%;\n}\n.chevronOpen {\n transform: rotate(180deg);\n}\n\n.menuWrap {\n --menu-dy: -6px;\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n z-index: 10;\n transform-origin: top center;\n animation: menuIn 0.28s var(--ease-out) both;\n}\n.menuWrapAuto {\n right: auto;\n min-width: 100%;\n width: max-content;\n transform-origin: top left;\n}\n.menuWrapEnd {\n left: auto;\n right: 0;\n transform-origin: top right;\n}\n.menuWrapUp {\n --menu-dy: 6px;\n top: auto;\n bottom: calc(100% + 4px);\n transform-origin: bottom center;\n}\n.menuWrapUp.menuWrapAuto {\n transform-origin: bottom left;\n}\n.menuWrapUp.menuWrapEnd {\n transform-origin: bottom right;\n}\n.menuWrapClosing {\n pointer-events: none;\n animation: menuOut 0.12s ease-in both;\n}\n@keyframes menuIn {\n from {\n opacity: 0;\n transform: translateY(var(--menu-dy)) scale(0.92);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n@keyframes menuOut {\n from {\n opacity: 1;\n transform: none;\n }\n to {\n opacity: 0;\n transform: translateY(calc(var(--menu-dy) / 2)) scale(0.96);\n }\n}\n.list > button {\n position: relative;\n z-index: 1;\n animation: itemIn 0.3s var(--ease-out) both;\n animation-delay: calc(var(--i, 0) * 18ms + 40ms);\n}\n.menuWrapClosing .list > button {\n animation: none;\n}\n/* Gliding hover highlight — replaces the per-item hover background */\n.list > button:hover:not(:disabled),\n.list > button:focus-visible:not(:disabled) {\n background: transparent;\n}\n.list > button:focus-visible {\n outline: none;\n}\n.highlight {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 0;\n border-radius: 8px;\n background: var(--brand-bg);\n pointer-events: none;\n transition:\n transform 0.28s var(--ease-out),\n height 0.2s ease-out;\n}\n.highlightInstant {\n transition: none;\n}\n@keyframes itemIn {\n from {\n opacity: 0;\n transform: translateY(calc(var(--menu-dy) * 0.75));\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .menuWrap,\n .menuWrapClosing {\n animation-duration: 0.01ms;\n }\n .list > button {\n animation: none;\n }\n .highlight {\n transition: none;\n }\n .chevron,\n .pillChevron,\n .buttonChevron {\n transition: none;\n }\n}\n\n/* Pill trigger — mirrors the pill Tag, but interactive */\n.pillTrigger {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n box-sizing: border-box;\n border: none;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border);\n color: var(--text-tertiary);\n font-family: inherit;\n font-size: 0.8rem;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n padding: 3px 8px 3px 11px;\n border-radius: 999px;\n cursor: pointer;\n transition:\n background 0.15s ease-out,\n color 0.15s ease-out,\n transform 0.15s ease-out;\n}\n.pillTrigger:hover:not(:disabled) {\n background: var(--brand-bg);\n color: var(--brand-dark);\n}\n.pillTrigger:active:not(:disabled) {\n transform: scale(0.96);\n}\n.pillTrigger:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.pillTrigger:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.pillIcon {\n display: flex;\n width: 14px;\n height: 14px;\n margin-left: -4px;\n}\n.pillChevron {\n display: flex;\n width: 14px;\n height: 14px;\n transition: transform 0.3s var(--ease-out);\n}\n.buttonChevron {\n display: flex;\n width: 100%;\n height: 100%;\n transition: transform 0.3s var(--ease-out);\n}\n.pillIcon svg,\n.pillChevron svg,\n.buttonChevron svg {\n width: 100%;\n height: 100%;\n}\n.list {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 320px;\n overflow-y: auto;\n}\n.search {\n width: 100%;\n height: var(--control-height-sm);\n box-sizing: border-box;\n margin-bottom: 4px;\n padding: 0 10px;\n border: none;\n border-radius: 8px;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n font-family: inherit;\n font-size: var(--control-font-size);\n color: var(--text-primary);\n outline: none;\n}\n.search:focus {\n box-shadow: inset 0 0 0 1.5px var(--brand-main);\n}\n.noResults {\n padding: 8px 12px;\n font-size: var(--control-font-size);\n color: var(--text-tertiary);\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n\n.prefix {\n color: var(--text-tertiary);\n}\n/* Multi-select menus need room for names like \"002 Night shift\" */\n.menuWrapMultiple {\n min-width: max(100%, 240px);\n}\n","import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ChangeEvent,\n type CSSProperties,\n type KeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { Button } from './Button';\nimport { Menu } from './Menu';\nimport { MenuItem } from './MenuItem';\nimport { CheckboxIndicator } from './Checkbox';\nimport { FieldLabel } from './FieldLabel';\nimport styles from './Dropdown.module.css';\n\ntype DropdownSize = 'sm' | 'base';\ntype DropdownVariant = 'field' | 'secondary' | 'tertiary' | 'pill';\n\ninterface DropdownOption<T extends string> {\n value: T;\n label: ReactNode;\n icon?: ReactNode;\n disabled?: boolean;\n /** Text matched by search when `label` is not a plain string. */\n searchText?: string;\n}\n\ninterface CommonProps<T extends string> {\n /**\n * What opens the menu: a text-field-style trigger (`field`), a secondary or\n * tertiary `Button`, or a `pill` styled like a pill `Tag`.\n * `label`, `helperText` and `error` only apply to `field`.\n */\n variant?: DropdownVariant;\n /** Fixed trigger text (e.g. \"Actions\"). Defaults to the selected option's label, or the placeholder. */\n triggerLabel?: ReactNode;\n /** Which trigger edge the menu lines up with. Ignored for `field`, where the menu spans the trigger. */\n menuAlign?: 'start' | 'end';\n label?: string;\n helperText?: string;\n error?: string;\n /** Applies to `field`, `secondary` and `tertiary`; `pill` has a single size. */\n size?: DropdownSize;\n placeholder?: string;\n options: DropdownOption<T>[];\n disabled?: boolean;\n /** Show a search field at the top of the open menu that filters options by their text. */\n searchable?: boolean;\n /** Placeholder for the search field. */\n searchPlaceholder?: string;\n /** Shown in place of the options when a search matches nothing. */\n noResultsText?: ReactNode;\n /** Open the menu on first render. */\n defaultOpen?: boolean;\n /** Focus the trigger on first render. */\n autoFocus?: boolean;\n /**\n * Extra classes for layout around the field — width, responsive sizing.\n * Appended after the field's own class.\n */\n className?: string;\n /** Extra classes for the label, e.g. to hide it below a breakpoint. */\n labelClassName?: string;\n /** Accessible name when there is no visible `label`. */\n 'aria-label'?: string;\n 'data-testid'?: string;\n}\n\n/**\n * `multiple` switches the dropdown to multi-select: `value` becomes an array in the\n * order options were picked, and the menu stays open while options are toggled.\n */\ntype DropdownProps<T extends string> = CommonProps<T> &\n (\n | {\n multiple?: false;\n value?: T;\n onChange: (value: T) => void;\n triggerPrefix?: never;\n renderTriggerLabel?: never;\n moreText?: never;\n }\n | {\n multiple: true;\n value?: T[];\n onChange: (value: T[]) => void;\n /** Static, muted text before the value in the trigger, e.g. \"Compare with:\". */\n triggerPrefix?: ReactNode;\n /**\n * Trigger content when at least one option is selected, in selection order.\n * Defaults to the label of a single selection, or \"First and N more\".\n * An empty selection always shows the placeholder.\n */\n renderTriggerLabel?: (selected: DropdownOption<T>[]) => ReactNode;\n /** Builds the \"and N more\" suffix of the default trigger label. */\n moreText?: (count: number) => string;\n }\n );\n\nfunction optionText(opt: DropdownOption<string>): string {\n if (opt.searchText !== undefined) return opt.searchText;\n return typeof opt.label === 'string' || typeof opt.label === 'number' ? String(opt.label) : '';\n}\n\n/** Plain text for a selected option in the trigger: its string label, else `searchText`. */\nfunction labelText(opt: DropdownOption<string>): string | undefined {\n if (typeof opt.label === 'string' || typeof opt.label === 'number') return String(opt.label);\n return opt.searchText;\n}\n\nconst defaultMoreText = (count: number) => `and ${count} more`;\n\nexport function Dropdown<T extends string>(props: DropdownProps<T>) {\n const {\n variant = 'field',\n triggerLabel,\n menuAlign = 'start',\n label,\n helperText,\n error,\n size = 'base',\n placeholder = 'Select…',\n options,\n disabled,\n searchable,\n searchPlaceholder = 'Search…',\n noResultsText = 'No matches',\n defaultOpen = false,\n autoFocus,\n className,\n labelClassName,\n 'aria-label': ariaLabel,\n 'data-testid': dataTestId,\n } = props;\n const multiple = props.multiple === true;\n const [open, setOpen] = useState(defaultOpen);\n // Stays true while the close animation plays so the menu can animate out before unmounting.\n const [present, setPresent] = useState(defaultOpen);\n const [query, setQuery] = useState('');\n const [openUpward, setOpenUpward] = useState(false);\n // Hover highlight that glides between options; `instant` skips the slide on first appearance.\n const [highlight, setHighlight] = useState<{\n top: number;\n height: number;\n instant: boolean;\n } | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const searchRef = useRef<HTMLInputElement>(null);\n const triggerId = useId();\n const listboxId = useId();\n\n const value = props.multiple ? undefined : props.value;\n const selectedValues: T[] = (props.multiple && props.value) || [];\n // Selection order, not option order.\n const selectedOptions = selectedValues\n .map((v) => options.find((opt) => opt.value === v))\n .filter((opt): opt is DropdownOption<T> => opt !== undefined);\n const selected = multiple ? undefined : options.find((opt) => opt.value === value);\n const trimmedQuery = query.trim().toLowerCase();\n const visibleOptions =\n searchable && trimmedQuery\n ? options.filter((opt) => optionText(opt).toLowerCase().includes(trimmedQuery))\n : options;\n const enabledValues = visibleOptions.filter((opt) => !opt.disabled).map((opt) => opt.value);\n\n const isField = variant === 'field';\n\n function openMenu() {\n setPresent(true);\n setOpen(true);\n }\n\n function close() {\n setOpen(false);\n setQuery('');\n }\n\n // Searchable menus focus the search field; others focus the selected (or first) option.\n useEffect(() => {\n if (!open) return;\n if (searchable) {\n searchRef.current?.focus();\n return;\n }\n const focusValue =\n (multiple ? selectedOptions.find((opt) => !opt.disabled)?.value : value) ?? enabledValues[0];\n const el = rootRef.current?.querySelector<HTMLButtonElement>(`[data-value=\"${focusValue}\"]`);\n el?.focus();\n }, [open]);\n\n // Open upward when there is not enough room below and more room above.\n useLayoutEffect(() => {\n if (!open || !menuRef.current || !rootRef.current) return;\n const rootRect = rootRef.current.getBoundingClientRect();\n // offsetHeight ignores the entrance animation's scale transform.\n const menuHeight = menuRef.current.offsetHeight;\n const spaceBelow = window.innerHeight - rootRect.bottom;\n const spaceAbove = rootRect.top;\n setOpenUpward(spaceBelow < menuHeight + 8 && spaceAbove > spaceBelow);\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n function onPointerDown(e: PointerEvent) {\n if (!rootRef.current?.contains(e.target as Node)) close();\n }\n function onKeyDown(e: globalThis.KeyboardEvent) {\n if (e.key === 'Escape') {\n close();\n triggerRef.current?.focus();\n }\n // Multi-select keeps focus in the menu after a pick, so Tab has to dismiss it.\n if (e.key === 'Tab' && multiple) close();\n }\n window.addEventListener('pointerdown', onPointerDown);\n window.addEventListener('keydown', onKeyDown);\n return () => {\n window.removeEventListener('pointerdown', onPointerDown);\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [open, multiple]);\n\n function focusOption(optionValue: T | undefined) {\n if (optionValue === undefined) return;\n rootRef.current?.querySelector<HTMLButtonElement>(`[data-value=\"${optionValue}\"]`)?.focus();\n }\n\n function handleTriggerKeyDown(e: KeyboardEvent<HTMLButtonElement>) {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n openMenu();\n }\n }\n\n function handleSearchKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n focusOption(enabledValues[0]);\n }\n if (e.key === 'Enter' && enabledValues.length === 1) {\n e.preventDefault();\n select(enabledValues[0]);\n }\n }\n\n function handleOptionKeyDown(e: KeyboardEvent<HTMLButtonElement>, currentValue: T) {\n const currentIndex = enabledValues.indexOf(currentValue);\n if (currentIndex === -1) return;\n\n let nextIndex: number | null = null;\n if (e.key === 'ArrowDown') nextIndex = (currentIndex + 1) % enabledValues.length;\n if (e.key === 'ArrowUp') {\n if (searchable && currentIndex === 0) {\n e.preventDefault();\n searchRef.current?.focus();\n return;\n }\n nextIndex = (currentIndex - 1 + enabledValues.length) % enabledValues.length;\n }\n if (e.key === 'Home') nextIndex = 0;\n if (e.key === 'End') nextIndex = enabledValues.length - 1;\n\n if (nextIndex !== null) {\n e.preventDefault();\n focusOption(enabledValues[nextIndex]);\n }\n }\n\n function glideTo(el: HTMLElement) {\n setHighlight((prev) => ({\n top: el.offsetTop,\n height: el.offsetHeight,\n instant: !prev,\n }));\n }\n\n function select(optionValue: T) {\n if (props.multiple) {\n const current = props.value ?? [];\n props.onChange(\n current.includes(optionValue) ? current.filter((v) => v !== optionValue) : [...current, optionValue],\n );\n return;\n }\n props.onChange(optionValue);\n close();\n triggerRef.current?.focus();\n }\n\n function multipleLabel(): ReactNode {\n if (props.multiple && props.renderTriggerLabel) return props.renderTriggerLabel(selectedOptions);\n const first = selectedOptions[0];\n if (selectedOptions.length === 1) return first.label;\n const text = labelText(first);\n if (text === undefined) return `${selectedOptions.length} selected`;\n const more = (props.multiple && props.moreText) || defaultMoreText;\n return `${text} ${more(selectedOptions.length - 1)}`;\n }\n\n const showPlaceholder = triggerLabel === undefined && (multiple ? selectedOptions.length === 0 : !selected);\n const prefix =\n multiple && props.triggerPrefix ? <span className={styles.prefix}>{props.triggerPrefix} </span> : null;\n const valueText =\n triggerLabel ?? (showPlaceholder ? placeholder : multiple ? multipleLabel() : selected?.label);\n const triggerText = (\n <>\n {prefix}\n {valueText}\n </>\n );\n const triggerProps = {\n 'aria-haspopup': 'listbox' as const,\n 'aria-expanded': open,\n 'aria-controls': open ? listboxId : undefined,\n 'aria-label': label ? undefined : ariaLabel,\n autoFocus,\n disabled,\n onClick: () => (open ? close() : openMenu()),\n onKeyDown: handleTriggerKeyDown,\n };\n\n return (\n <div\n className={[isField ? styles.field : styles.fieldInline, className].filter(Boolean).join(' ')}\n ref={rootRef}\n data-testid={dataTestId}\n >\n {isField && label && (\n <FieldLabel htmlFor={triggerId} className={labelClassName}>\n {label}\n </FieldLabel>\n )}\n {isField ? (\n <button\n ref={triggerRef}\n id={triggerId}\n type=\"button\"\n role=\"combobox\"\n className={`${styles.trigger} ${styles[size]} ${error ? styles.errorWrap : ''}`}\n {...triggerProps}\n >\n {selected?.icon && <span className={styles.icon}>{selected.icon}</span>}\n <span className={`${styles.value} ${showPlaceholder ? styles.placeholder : ''}`}>\n {triggerText}\n </span>\n <span className={`${styles.chevron} ${open ? styles.chevronOpen : ''}`}>\n <ChevronDown />\n </span>\n </button>\n ) : variant === 'pill' ? (\n <button\n ref={triggerRef}\n id={triggerId}\n type=\"button\"\n className={styles.pillTrigger}\n {...triggerProps}\n >\n {selected?.icon && <span className={styles.pillIcon}>{selected.icon}</span>}\n {triggerText}\n <span className={`${styles.pillChevron} ${open ? styles.chevronOpen : ''}`}>\n <ChevronDown />\n </span>\n </button>\n ) : (\n <Button\n ref={triggerRef}\n id={triggerId}\n variant={variant}\n size={size}\n leadingIcon={selected?.icon}\n trailingIcon={\n <span className={`${styles.buttonChevron} ${open ? styles.chevronOpen : ''}`}>\n <ChevronDown />\n </span>\n }\n {...triggerProps}\n >\n {triggerText}\n </Button>\n )}\n {present && (\n <div\n ref={menuRef}\n className={[\n styles.menuWrap,\n !isField && styles.menuWrapAuto,\n !isField && multiple && styles.menuWrapMultiple,\n !isField && menuAlign === 'end' && styles.menuWrapEnd,\n openUpward && styles.menuWrapUp,\n !open && styles.menuWrapClosing,\n ]\n .filter(Boolean)\n .join(' ')}\n onAnimationEnd={(e) => {\n if (open || e.target !== e.currentTarget) return;\n setPresent(false);\n setOpenUpward(false);\n }}\n >\n <Menu role=\"presentation\" style={isField ? { width: '100%' } : undefined}>\n {searchable && (\n <input\n ref={searchRef}\n type=\"text\"\n className={styles.search}\n value={query}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n aria-controls={listboxId}\n autoComplete=\"off\"\n spellCheck={false}\n onChange={(e: ChangeEvent<HTMLInputElement>) => {\n setQuery(e.target.value);\n setHighlight(null);\n }}\n onKeyDown={handleSearchKeyDown}\n />\n )}\n <div\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-label={label ?? ariaLabel}\n className={styles.list}\n onMouseLeave={() => setHighlight(null)}\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setHighlight(null);\n }}\n >\n {highlight && visibleOptions.length > 0 && (\n <span\n aria-hidden=\"true\"\n className={`${styles.highlight} ${highlight.instant ? styles.highlightInstant : ''}`}\n style={{\n transform: `translateY(${highlight.top}px)`,\n height: highlight.height,\n }}\n />\n )}\n {visibleOptions.length === 0 ? (\n <div className={styles.noResults} role=\"presentation\">\n {noResultsText}\n </div>\n ) : (\n visibleOptions.map((opt, index) => (\n <MenuItem\n key={opt.value}\n style={{ '--i': Math.min(index, 8) } as CSSProperties}\n data-value={opt.value}\n role=\"option\"\n aria-selected={multiple ? selectedValues.includes(opt.value) : opt.value === value}\n icon={opt.icon}\n leading={\n multiple ? (\n <CheckboxIndicator\n checked={selectedValues.includes(opt.value)}\n disabled={opt.disabled}\n />\n ) : undefined\n }\n selected={!multiple && opt.value === value}\n disabled={opt.disabled}\n onClick={() => select(opt.value)}\n onMouseEnter={(e) => !opt.disabled && glideTo(e.currentTarget)}\n onFocus={(e) => glideTo(e.currentTarget)}\n onKeyDown={(e) => handleOptionKeyDown(e, opt.value)}\n >\n {opt.label}\n </MenuItem>\n ))\n )}\n </div>\n </Menu>\n </div>\n )}\n {isField && error ? (\n <span className={styles.errorText}>{error}</span>\n ) : isField && helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n",".highlight {\n background: var(--brand-bg);\n color: var(--brand-dark);\n border-radius: 3px;\n padding: 0 1px;\n}\n","import { Fragment } from 'react';\nimport styles from './HighlightText.module.css';\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function HighlightText({ text, query }: { text: string; query: string }) {\n if (!query) return <>{text}</>;\n\n const parts = text.split(new RegExp(`(${escapeRegExp(query)})`, 'ig'));\n return (\n <>\n {parts.map((part, i) =>\n part.toLowerCase() === query.toLowerCase() ? (\n <mark key={i} className={styles.highlight}>\n {part}\n </mark>\n ) : (\n <Fragment key={i}>{part}</Fragment>\n ),\n )}\n </>\n );\n}\n",".group {\n position: relative;\n}\n.btn {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-radius: 12px;\n padding: 12px;\n font-family: inherit;\n font-size: 1rem;\n color: var(--text-primary);\n cursor: pointer;\n transition:\n background 0.2s ease-out,\n box-shadow 0.2s ease-out,\n transform 0.2s ease-out;\n}\n.btn:hover {\n background: rgba(10, 10, 11, 0.04);\n}\n.btn:active {\n background: var(--brand-bg);\n box-shadow: inset 0 2px 1px 0 rgba(0, 140, 216, 0.25);\n transform: scale(0.95);\n}\n.caret {\n color: var(--text-tertiary);\n display: flex;\n align-items: center;\n}\n.caret svg {\n width: 14px;\n height: 14px;\n}\n.label {\n color: var(--text-secondary);\n}\n.badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--brand-main, #0a84d8);\n color: #fff;\n font-size: 0.65rem;\n font-weight: var(--font-weight-semibold);\n line-height: 16px;\n text-align: center;\n}\n.value {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n background: #fff;\n border-radius: 12px;\n min-width: 220px;\n width: fit-content;\n max-height: 280px;\n overflow-y: auto;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px rgba(0, 0, 0, 0.12);\n z-index: 50;\n}\n.panel.open {\n display: block;\n}\n.panelRight {\n left: auto;\n right: 0;\n}\n.panelWide {\n min-width: 260px;\n padding-bottom: 4px;\n}\n.sectionHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 12px 14px 4px;\n}\n.sectionLabel {\n font-size: 0.75rem;\n font-weight: var(--font-weight-semibold);\n color: var(--text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n.allToggle {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.75rem;\n font-weight: var(--font-weight-semibold);\n color: var(--brand-main, #0a84d8);\n cursor: pointer;\n}\n.allToggle:hover {\n text-decoration: underline;\n}\n.allToggle:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n border-radius: 4px;\n}\n.divider {\n height: 1px;\n background: var(--border);\n margin: 4px 0;\n}\n.option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border-radius: 8px;\n font-size: 1rem;\n cursor: pointer;\n}\n.option:hover {\n background: var(--bg);\n}\n.search {\n width: calc(100% - 16px);\n box-sizing: border-box;\n border: none;\n box-shadow: inset 0 0 0 1px var(--border-input);\n border-radius: 8px;\n padding: 8px 12px;\n margin: 8px;\n font-family: inherit;\n font-size: 1rem;\n margin-bottom: 0;\n}\n.search:focus {\n outline: none;\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.optionsList {\n padding: 4px 4px;\n}\n.empty {\n padding: 7px 8px;\n color: var(--text-tertiary);\n font-size: 0.85rem;\n}\n","import { useState } from 'react';\nimport { Checkbox } from './Checkbox';\nimport styles from './FilterSection.module.css';\n\ninterface FilterSectionProps<T extends string> {\n label: string;\n options: T[];\n optionLabel: (opt: T) => string;\n activeSet: Set<T>;\n onToggle: (opt: T) => void;\n onSetAll?: (opts: T[]) => void;\n searchable?: boolean;\n}\n\nexport function FilterSection<T extends string>({\n label,\n options,\n optionLabel,\n activeSet,\n onToggle,\n onSetAll,\n searchable,\n}: FilterSectionProps<T>) {\n const [query, setQuery] = useState('');\n\n const q = query.trim().toLowerCase();\n const matches = q ? options.filter((opt) => optionLabel(opt).toLowerCase().includes(q)) : options;\n const allSelected = options.length > 0 && activeSet.size === options.length;\n\n return (\n <div>\n <div className={styles.sectionHeader}>\n <div className={styles.sectionLabel}>{label}</div>\n {onSetAll && (\n <button\n type=\"button\"\n className={styles.allToggle}\n onClick={() => onSetAll(allSelected ? [] : options)}\n >\n {allSelected ? 'Deselect all' : 'Select all'}\n </button>\n )}\n </div>\n {searchable && (\n <input\n type=\"text\"\n className={styles.search}\n placeholder={`Search ${label.toLowerCase()}…`}\n autoComplete=\"off\"\n value={query}\n onClick={(e) => e.stopPropagation()}\n onChange={(e) => setQuery(e.target.value)}\n />\n )}\n <div className={styles.optionsList}>\n {matches.length === 0 && <div className={styles.empty}>No match</div>}\n {matches.map((opt) => (\n <Checkbox\n key={opt}\n className={styles.option}\n checked={activeSet.has(opt)}\n onChange={() => onToggle(opt)}\n label={optionLabel(opt)}\n />\n ))}\n </div>\n </div>\n );\n}\n",".line,\n.box {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.indicator {\n position: absolute;\n left: 0;\n pointer-events: none;\n transition: translate 0.25s cubic-bezier(0.39, 0.575, 0.565, 1), width 0.25s ease,\n scale 0.125s cubic-bezier(0.39, 0.575, 0.565, 1);\n}\n\n.indicator.settling {\n transition: scale 0.1s linear;\n}\n\n.indicatorLine {\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n}\n\n.indicatorBox {\n top: 4px;\n bottom: 4px;\n border-radius: 8px;\n background: var(--card-surface);\n box-shadow: 0 0 1px 0.5px var(--border);\n}\n\n.tab {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: none;\n border-radius: 8px 8px 0 0;\n font-family: inherit;\n font-weight: var(--font-weight-regular);\n cursor: pointer;\n white-space: nowrap;\n transition: color 0.15s ease-out, background 0.15s ease-out, box-shadow 0.15s ease-out;\n}\n\n.tab::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n opacity: 0;\n transition: opacity 0.15s ease-out;\n z-index: -1;\n pointer-events: none;\n background: rgba(var(--brand-main-rgb), 0.08);\n}\n.tab:hover:not(:disabled)::before {\n opacity: 1;\n}\n.tab:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n\n.tab:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.tab:disabled::before {\n display: none;\n}\n\n.tab.selected:hover::before {\n display: none;\n}\n\n.tab:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: -4px;\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n\n.tab.iconOnly {\n justify-content: center;\n}\n.tab.iconOnly .icon {\n margin-left: 0;\n}\n\n/* Line variant */\n\n.line {\n box-shadow: inset 0 -1px 0 0 var(--border);\n}\n\n.line .tab {\n background: transparent;\n padding: 12px 8px;\n font-size: var(--control-font-size);\n color: var(--text-secondary);\n}\n.line .tab:hover:not(:disabled) {\n color: var(--brand-main);\n}\n.line .tab.selected {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n\n/* Box variant */\n\n.box {\n box-sizing: border-box;\n height: var(--control-height-base);\n background: var(--depth-5);\n border-radius: var(--radius-base);\n padding: 4px;\n gap: 4px;\n box-shadow: inset 0 0 0.5px 1px #e3e3e3;\n}\n\n.box .tab {\n height: calc(var(--control-height-base) - 8px);\n border-radius: 8px;\n padding: 0 14px;\n font-size: var(--control-font-size);\n background: transparent;\n color: var(--text-secondary);\n}\n.box .tab:hover:not(:disabled) {\n color: var(--brand-main);\n /* box-shadow: 0 0 0px 1px var(--brand-main-30); */\n}\n.box .tab.selected {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n\n.box.sm {\n height: var(--control-height-sm);\n border-radius: var(--radius-sm);\n}\n.box.sm .tab {\n height: calc(var(--control-height-sm) - 8px);\n border-radius: 6px;\n padding: 0 14px;\n}\n.box .tab.iconOnly {\n width: calc(var(--control-height-base) - 8px);\n padding: 0;\n}\n.box.sm .tab.iconOnly {\n width: calc(var(--control-height-sm) - 8px);\n padding: 0;\n}\n.box.sm .indicatorBox {\n border-radius: 6px;\n}\n","import {\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n type TransitionEvent,\n} from 'react';\nimport styles from './Tabs.module.css';\n\ntype TabsVariant = 'line' | 'box';\ntype TabsSize = 'base' | 'sm';\n\nexport interface TabItem {\n value: string;\n label?: ReactNode;\n icon?: ReactNode;\n disabled?: boolean;\n 'aria-label'?: string;\n}\n\ninterface TabsProps {\n items: TabItem[];\n value: string;\n onChange: (value: string) => void;\n variant?: TabsVariant;\n size?: TabsSize;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n}\n\nexport function Tabs({ items, value, onChange, variant = 'line', size = 'base', ...rest }: TabsProps) {\n const enabledValues = items.filter((item) => !item.disabled).map((item) => item.value);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const tabRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n const prevValueRef = useRef(value);\n const [indicatorStyle, setIndicatorStyle] = useState<{ left: number; width: number } | null>(\n null,\n );\n const [pillPhase, setPillPhase] = useState<'idle' | 'moving' | 'settling'>('idle');\n\n useLayoutEffect(() => {\n const selectedTab = tabRefs.current.get(value);\n if (!selectedTab) return;\n setIndicatorStyle({ left: selectedTab.offsetLeft, width: selectedTab.offsetWidth });\n\n if (variant === 'box' && prevValueRef.current !== value) {\n setPillPhase('moving');\n }\n prevValueRef.current = value;\n }, [value, items, variant, size]);\n\n function handlePillTransitionEnd(event: TransitionEvent<HTMLSpanElement>) {\n if (event.propertyName !== 'scale') return;\n if (pillPhase === 'moving') setPillPhase('settling');\n else if (pillPhase === 'settling') setPillPhase('idle');\n }\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() => {\n const selectedTab = tabRefs.current.get(value);\n if (!selectedTab) return;\n setIndicatorStyle({ left: selectedTab.offsetLeft, width: selectedTab.offsetWidth });\n });\n observer.observe(container);\n return () => observer.disconnect();\n }, [value]);\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const currentIndex = enabledValues.indexOf(value);\n if (currentIndex === -1) return;\n\n let nextIndex: number | null = null;\n if (event.key === 'ArrowRight') nextIndex = (currentIndex + 1) % enabledValues.length;\n if (event.key === 'ArrowLeft') {\n nextIndex = (currentIndex - 1 + enabledValues.length) % enabledValues.length;\n }\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = enabledValues.length - 1;\n\n if (nextIndex !== null) {\n event.preventDefault();\n onChange(enabledValues[nextIndex]);\n }\n }\n\n return (\n <div\n ref={containerRef}\n role=\"tablist\"\n className={[styles[variant], variant === 'box' && size === 'sm' && styles.sm]\n .filter(Boolean)\n .join(' ')}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {indicatorStyle && (\n <span\n aria-hidden\n className={[\n styles.indicator,\n variant === 'line' ? styles.indicatorLine : styles.indicatorBox,\n pillPhase === 'settling' && styles.settling,\n ]\n .filter(Boolean)\n .join(' ')}\n onTransitionEnd={handlePillTransitionEnd}\n style={{\n translate: `${indicatorStyle.left}px 0`,\n scale: variant === 'box' && pillPhase === 'moving' ? 0.92 : 1,\n width: indicatorStyle.width,\n }}\n />\n )}\n {items.map((item) => {\n const selected = item.value === value;\n const iconOnly = !item.label && !!item.icon;\n return (\n <button\n key={item.value}\n ref={(node) => {\n if (node) tabRefs.current.set(item.value, node);\n else tabRefs.current.delete(item.value);\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n aria-label={item['aria-label']}\n disabled={item.disabled}\n tabIndex={selected ? 0 : -1}\n className={[styles.tab, selected && styles.selected, iconOnly && styles.iconOnly]\n .filter(Boolean)\n .join(' ')}\n onClick={() => !item.disabled && onChange(item.value)}\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n gap: 12px;\n}\n\n.label {\n font-size: var(--control-font-size);\n color: var(--text-secondary);\n font-weight: var(--font-weight-regular);\n white-space: nowrap;\n}\n","import { useId, type ReactNode } from 'react';\nimport { Tabs, type TabItem } from './Tabs';\nimport styles from './Toggle.module.css';\n\ninterface ToggleProps {\n items: TabItem[];\n value: string;\n onChange: (value: string) => void;\n label?: ReactNode;\n 'aria-label'?: string;\n}\n\nexport function Toggle({ items, value, onChange, label, 'aria-label': ariaLabel }: ToggleProps) {\n const labelId = useId();\n\n return (\n <div className={styles.root}>\n {label && (\n <span id={labelId} className={styles.label}>\n {label}\n </span>\n )}\n <Tabs\n items={items}\n value={value}\n onChange={onChange}\n variant=\"box\"\n size=\"sm\"\n aria-label={ariaLabel}\n aria-labelledby={label && !ariaLabel ? labelId : undefined}\n />\n </div>\n );\n}\n","/* Always centered in the parent, both axes. The parent must be a positioned\n element (position: relative/absolute/fixed) with a non-zero size. */\n.spinner {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: block;\n}\n\n.inner,\n.outer {\n position: absolute;\n top: 0;\n left: 0;\n display: block;\n}\n\n.inner {\n animation: spin 1s cubic-bezier(0.5, 0, 0.4, 1) infinite;\n}\n\n.outer {\n animation: spinReverse 1s ease-in-out infinite;\n}\n\n/* Brand logo colors, kept as literals on purpose. */\n.default .inner {\n fill: #008cd8;\n}\n.default .outer {\n fill: #4cd5ff;\n}\n\n.subtle .inner,\n.subtle .outer {\n fill: var(--depth-10);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .inner,\n .outer {\n animation-duration: 3s;\n }\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@keyframes spinReverse {\n to {\n transform: rotate(-360deg);\n }\n}\n","import styles from './Spinner.module.css';\n\ntype SpinnerVariant = 'default' | 'subtle';\n\n/**\n * Always centered (vertically and horizontally) in its parent container.\n * The parent must be positioned (`position: relative`, `absolute` or `fixed`) and have a size.\n */\ninterface SpinnerProps {\n /** `default` uses the brand logo blues; `subtle` uses a faint depth tint for busy surfaces. */\n variant?: SpinnerVariant;\n /** Width and height in px. */\n size?: number;\n /** Accessible name announced by screen readers. */\n label?: string;\n /** Extra classes appended after the variant classes. Do not override the centering position. */\n className?: string;\n 'data-testid'?: string;\n}\n\nexport function Spinner({\n variant = 'default',\n size = 64,\n label = 'Loading',\n className,\n 'data-testid': dataTestId,\n}: SpinnerProps) {\n const classes = [styles.spinner, styles[variant], className].filter(Boolean).join(' ');\n return (\n <div\n role=\"status\"\n aria-label={label}\n className={classes}\n style={{ width: size, height: size }}\n data-testid={dataTestId}\n >\n <svg className={styles.inner} width={size} height={size} viewBox=\"0 0 64 64\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M45.4273 17.5099C45.5053 17.5796 45.5088 17.6535 45.4377 17.7316L38.8829 24.8071C38.8634 24.828 38.8365 24.8404 38.8079 24.8416C38.7793 24.8428 38.7514 24.8326 38.7303 24.8134C36.6569 22.9045 34.221 22.0275 31.4225 22.1823C29.9153 22.2659 28.5572 22.6333 27.3483 23.2845C25.0295 24.5352 23.4428 26.4155 22.588 28.9253C20.717 34.4308 24.3708 40.1612 29.8184 41.6584C30.8097 41.9302 31.99 41.9735 33.3593 41.788C35.158 41.5433 36.8709 40.5854 38.3412 39.5627C38.4022 39.5203 38.4764 39.5014 38.5502 39.5094C38.6241 39.5175 38.6925 39.552 38.7428 39.6066L45.1742 46.6069C45.1803 46.6137 45.185 46.6217 45.188 46.6303C45.191 46.639 45.1923 46.6482 45.1917 46.6573C45.1911 46.6665 45.1887 46.6754 45.1846 46.6836C45.1805 46.6918 45.1748 46.6992 45.1679 46.7052C44.4401 47.3033 43.6502 47.8855 42.7982 48.4516C39.8799 50.3897 36.6339 51.4633 33.0602 51.6725C29.3847 51.8872 25.9031 51.1106 22.6152 49.3425C19.7917 47.8227 17.4903 45.764 15.7112 43.1663C14.4132 41.2707 13.4349 39.3097 12.8667 37.0717C11.973 33.5775 11.9925 30.1014 12.9253 26.6435C13.1679 25.7483 13.5465 24.8469 13.8414 23.9412C14.6703 21.4035 16.9915 18.887 18.9133 17.1899C26.3467 10.6186 38.1184 10.8908 45.4273 17.5099Z\"\n />\n </svg>\n <svg className={styles.outer} width={size} height={size} viewBox=\"0 0 64 64\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M23.9528 51.6749C24.675 51.9719 25.504 52.2515 26.4396 52.5136C29.5538 53.3858 33.0236 53.4255 36.1044 52.8608C39.7938 52.1832 43.2155 50.3364 46.0955 47.9667C46.1341 47.9349 46.1835 47.9192 46.2336 47.9227C46.2837 47.9262 46.3308 47.9487 46.3653 47.9855C48.5489 50.321 50.6076 52.5617 52.5415 54.7076C52.7465 54.9349 52.9626 55.1914 53.1899 55.4773C53.2568 55.5623 53.2492 55.6404 53.1669 55.7115C45.9875 61.8759 37.7414 64.4924 28.4286 63.5609C27.0036 63.4173 25.635 63.1761 24.323 62.8373C18.1489 61.2422 12.9382 58.1328 8.69108 53.5092C4.73535 49.2049 2.16559 44.2111 0.981796 38.5277C0.170292 34.6236 0.131251 30.548 0.864671 26.3008C1.10171 24.933 1.44681 23.5867 1.89997 22.2621C3.86319 16.5286 7.08689 11.7802 11.5711 8.01689C16.4638 3.90918 22.0697 1.47885 28.3889 0.725907C29.9073 0.546038 31.6858 0.498631 33.7243 0.583685C39.227 0.815842 44.6001 2.60826 49.1575 5.58447C50.8335 6.67902 52.2222 7.73732 53.3238 8.75937C53.5301 8.9504 53.5427 9.1463 53.3614 9.34708C51.1054 11.836 48.8612 14.2391 46.6289 16.5565C46.534 16.6569 46.435 16.6611 46.3319 16.569C42.8516 13.5029 38.8624 11.7049 34.3643 11.1751C33.642 11.09 32.7831 11.0531 31.7875 11.0642C30.8199 11.074 29.9868 11.1263 29.2882 11.2211C23.3065 12.0305 18.3747 15.0653 14.7397 19.9196C14.2266 20.6043 13.7943 21.2986 13.443 22.0028C12.3944 24.1012 11.7028 25.9683 11.3682 27.6038C10.2792 32.9385 11.0824 38.0216 13.7776 42.853C14.0481 43.3368 14.3402 43.7872 14.654 44.2041C14.9691 44.6252 15.294 45.0372 15.6286 45.4402C17.9767 48.2748 20.7514 50.3531 23.9528 51.6749Z\"\n />\n </svg>\n </div>\n );\n}\n","export function formatDuration(mins: number): string {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n return `${h}h:${String(m).padStart(2, '0')}m`;\n}\n\n/** HH:MM:SS — seconds are a stable per-video display detail, not tracked in the data model. */\nexport function formatDurationHMS(mins: number, seconds: number): string {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${pad(h)}:${pad(m)}:${pad(seconds)}`;\n}\n"],"x_google_ignoreList":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],"mappings":"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"}
|