@tomny-dev/uzi 0.1.0 → 0.1.3
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/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/cx.ts","../src/components/button/button.module.css","../src/components/button/Button.tsx","../src/components/card/card.module.css","../src/components/card/Card.tsx","../src/components/pill/pill.module.css","../src/components/pill/Pill.tsx","../src/components/modal/Modal.tsx","../src/components/modal/modal.module.css","../src/components/toast/ToastContext.tsx","../src/components/toast/toast.module.css","../src/components/dropdown/Dropdown.tsx","../src/components/dropdown/dropdown.module.css","../src/components/app-shell/AppShell.tsx","../src/components/app-shell/app-shell.module.css","../src/components/sidebar-nav/sidebar-nav.module.css","../src/components/sidebar-nav/SidebarNav.tsx"],"sourcesContent":["// Primitives\nexport type { ButtonProps, ButtonVariant, ButtonSize } from \"./components/button/Button\";\nexport { Button } from \"./components/button/Button\";\n\nexport type { CardProps, CardPadding, CardTone } from \"./components/card/Card\";\nexport { Card } from \"./components/card/Card\";\n\nexport type { PillProps, PillSize, PillTone } from \"./components/pill/Pill\";\nexport { Pill } from \"./components/pill/Pill\";\n\n// Overlays\nexport type { ModalProps, ModalSize } from \"./components/modal/Modal\";\nexport { Modal } from \"./components/modal/Modal\";\n\nexport { ToastProvider, useToast } from \"./components/toast/ToastContext\";\nexport type {\n Toast,\n ToastConfig,\n ToastContextValue,\n ToastOptions,\n ToastPosition,\n ToastType,\n} from \"./components/toast/types\";\n\n// Inputs\nexport type { DropdownProps, DropdownOption } from \"./components/dropdown/Dropdown\";\nexport { Dropdown } from \"./components/dropdown/Dropdown\";\n\n// Layout\nexport type { AppShellProps } from \"./components/app-shell/AppShell\";\nexport { AppShell } from \"./components/app-shell/AppShell\";\n\nexport type { SidebarNavItem, SidebarNavProps } from \"./components/sidebar-nav/SidebarNav\";\nexport { SidebarNav } from \"./components/sidebar-nav/SidebarNav\";\n\n// Utils\nexport { cx } from \"./utils/cx\";\n","export function cx(...values: Array<string | false | null | undefined>): string {\r\n return values.filter(Boolean).join(\" \");\r\n}\r\n",".button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n font-family: inherit;\r\n font-weight: 600;\r\n border-radius: 8px;\r\n border: none;\r\n cursor: pointer;\r\n text-decoration: none;\r\n transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s;\r\n white-space: nowrap;\r\n}\r\n\r\n.button:disabled {\r\n opacity: 0.45;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* Sizes */\r\n.size-sm {\r\n font-size: 0.82rem;\r\n padding: 6px 14px;\r\n}\r\n\r\n.size-md {\r\n font-size: 0.95rem;\r\n padding: 10px 22px;\r\n}\r\n\r\n.size-lg {\r\n font-size: 1rem;\r\n padding: 12px 28px;\r\n}\r\n\r\n/* Variants */\r\n.variant-primary {\r\n background: var(--ts-btn-primary-bg, var(--accent, #22d3ee));\r\n color: var(--ts-btn-primary-text, #0f172a);\r\n border: 1px solid transparent;\r\n}\r\n\r\n.variant-primary:hover:not(:disabled) {\r\n opacity: 0.88;\r\n}\r\n\r\n.variant-secondary {\r\n background: var(--ts-btn-secondary-bg, rgba(255, 255, 255, 0.06));\r\n color: var(--ts-btn-secondary-text, var(--text, #e2e8f0));\r\n border: 1px solid var(--ts-btn-secondary-border, var(--border, #1f2937));\r\n}\r\n\r\n.variant-secondary:hover:not(:disabled) {\r\n background: var(--ts-btn-secondary-hover-bg, rgba(255, 255, 255, 0.1));\r\n}\r\n\r\n.variant-outline {\r\n background: transparent;\r\n color: var(--ts-btn-outline-text, var(--text, #e2e8f0));\r\n border: 1px solid var(--ts-btn-outline-border, var(--border, #1f2937));\r\n}\r\n\r\n.variant-outline:hover:not(:disabled) {\r\n border-color: var(--ts-btn-outline-hover-border, var(--accent, #22d3ee));\r\n color: var(--ts-btn-outline-hover-text, var(--accent, #22d3ee));\r\n}\r\n\r\n.variant-ghost {\r\n background: transparent;\r\n color: var(--ts-btn-ghost-text, var(--muted, #94a3b8));\r\n border: 1px solid transparent;\r\n padding-left: 8px;\r\n padding-right: 8px;\r\n}\r\n\r\n.variant-ghost:hover:not(:disabled) {\r\n background: rgba(255, 255, 255, 0.05);\r\n color: var(--text, #e2e8f0);\r\n}\r\n","import type { ButtonHTMLAttributes, AnchorHTMLAttributes } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./button.module.css\";\r\n\r\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\r\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\r\n\r\ntype BaseProps = {\r\n variant?: ButtonVariant;\r\n size?: ButtonSize;\r\n className?: string;\r\n children?: React.ReactNode;\r\n};\r\n\r\ntype AsButton = BaseProps &\r\n ButtonHTMLAttributes<HTMLButtonElement> & { as?: \"button\" };\r\n\r\ntype AsAnchor = BaseProps &\r\n AnchorHTMLAttributes<HTMLAnchorElement> & { as: \"a\" };\r\n\r\nexport type ButtonProps = AsButton | AsAnchor;\r\n\r\nexport function Button({\r\n as,\r\n variant = \"primary\",\r\n size = \"md\",\r\n className,\r\n children,\r\n ...rest\r\n}: ButtonProps) {\r\n const classes = cx(\r\n styles.button,\r\n styles[`variant-${variant}`],\r\n styles[`size-${size}`],\r\n className,\r\n );\r\n\r\n if (as === \"a\") {\r\n return (\r\n <a className={classes} {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}>\r\n {children}\r\n </a>\r\n );\r\n }\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={classes}\r\n {...(rest as ButtonHTMLAttributes<HTMLButtonElement>)}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n",".card {\r\n position: relative;\r\n overflow: visible;\r\n border-radius: var(--ts-card-radius, 12px);\r\n border: 1px solid var(--ts-card-border, var(--border, #1f2937));\r\n background: var(--ts-card-bg, var(--panel, #111827));\r\n color: var(--ts-card-fg, var(--text, #e2e8f0));\r\n box-shadow: var(--ts-card-shadow, 0 16px 36px rgba(0, 0, 0, 0.28));\r\n padding: var(--ts-card-padding, 16px);\r\n transition:\r\n transform 140ms ease,\r\n box-shadow 140ms ease,\r\n border-color 140ms ease,\r\n background-color 140ms ease;\r\n}\r\n\r\n.tone-default {\r\n --ts-card-bg: var(--panel, #111827);\r\n --ts-card-border: var(--border, #1f2937);\r\n --ts-card-shadow: 0 16px 36px rgba(0, 0, 0, 0.28);\r\n}\r\n\r\n.tone-muted {\r\n --ts-card-bg: var(--ts-card-muted-bg, rgba(255, 255, 255, 0.02));\r\n --ts-card-border: var(--ts-card-muted-border, rgba(255, 255, 255, 0.06));\r\n --ts-card-shadow: 0 10px 26px rgba(0, 0, 0, 0.22);\r\n}\r\n\r\n.tone-contrast {\r\n --ts-card-bg: var(--ts-card-contrast-bg, #0b1224);\r\n --ts-card-border: var(--ts-card-contrast-border, rgba(255, 255, 255, 0.1));\r\n --ts-card-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);\r\n}\r\n\r\n.interactive {\r\n cursor: default;\r\n}\r\n\r\n.interactive:hover {\r\n transform: translateY(-1px);\r\n box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);\r\n border-color: var(--ts-card-hover-border, rgba(34, 211, 238, 0.4));\r\n}\r\n\r\n.interactive:focus-within {\r\n outline: 2px solid var(--ts-card-hover-border, rgba(34, 211, 238, 0.45));\r\n outline-offset: 2px;\r\n}\r\n\r\n.padding-none {\r\n --ts-card-padding: 0;\r\n}\r\n\r\n.padding-sm {\r\n --ts-card-padding: 10px;\r\n}\r\n\r\n.padding-md {\r\n --ts-card-padding: 16px;\r\n}\r\n\r\n.padding-lg {\r\n --ts-card-padding: 20px;\r\n}\r\n","/**\r\n * Lightweight container component used for panels across the app.\r\n *\r\n * @remarks\r\n * Supports tone variants, padding presets, and an optional interactive affordance.\r\n *\r\n * @param props.as - Semantic element to render (defaults to `div`).\r\n * @param props.tone - Visual tone variant.\r\n * @param props.padding - Padding preset.\r\n * @param props.interactive - Enables hover/focus affordance.\r\n */\r\nimport type { HTMLAttributes } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./card.module.css\";\r\n\r\nexport type CardTone = \"default\" | \"muted\" | \"contrast\";\r\nexport type CardPadding = \"none\" | \"sm\" | \"md\" | \"lg\";\r\n\r\ntype CardElement = \"div\" | \"section\" | \"article\";\r\n\r\nexport type CardProps = HTMLAttributes<HTMLElement> & {\r\n /** Optional semantic element type. Defaults to `div`. */\r\n as?: CardElement;\r\n /** Visual tone; drives background/border CSS vars. */\r\n tone?: CardTone;\r\n /** Padding preset; maps to CSS variables so consumers can override globally. */\r\n padding?: CardPadding;\r\n /** Adds hover/focus affordance (lift + outline). */\r\n interactive?: boolean;\r\n};\r\n\r\nexport function Card({\r\n as,\r\n tone = \"default\",\r\n padding = \"md\",\r\n interactive = false,\r\n className,\r\n children,\r\n ...rest\r\n}: CardProps) {\r\n const Component: CardElement = as ?? \"div\";\r\n const toneClass = tone !== \"default\" ? styles[`tone-${tone}`] : null;\r\n const classes = cx(\r\n styles.card,\r\n toneClass,\r\n styles[`padding-${padding}`],\r\n interactive && styles.interactive,\r\n className,\r\n );\r\n\r\n return (\r\n <Component className={classes} {...rest}>\r\n {children}\r\n </Component>\r\n );\r\n}\r\n",".pill {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 4px 10px;\r\n border-radius: 999px;\r\n border: 1px solid var(--ts-pill-border, var(--border, #1f2937));\r\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\r\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\r\n font-size: 12px;\r\n font-weight: 700;\r\n letter-spacing: 0.05em;\r\n text-transform: uppercase;\r\n line-height: 1.2;\r\n white-space: nowrap;\r\n}\r\n\r\n.size-sm {\r\n padding: 3px 8px;\r\n font-size: 11px;\r\n}\r\n\r\n.size-md {\r\n padding: 4px 10px;\r\n}\r\n\r\n.tone-neutral {\r\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\r\n border-color: var(--ts-pill-border, var(--border, #1f2937));\r\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\r\n}\r\n\r\n.tone-success {\r\n color: #22c55e;\r\n border-color: rgba(34, 197, 94, 0.45);\r\n background: rgba(34, 197, 94, 0.12);\r\n}\r\n\r\n.tone-warning {\r\n color: #f59e0b;\r\n border-color: rgba(245, 158, 11, 0.45);\r\n background: rgba(245, 158, 11, 0.12);\r\n}\r\n\r\n.tone-info {\r\n color: #22d3ee;\r\n border-color: rgba(34, 211, 238, 0.5);\r\n background: rgba(34, 211, 238, 0.12);\r\n}\r\n\r\n.tone-danger {\r\n color: #f87171;\r\n border-color: rgba(248, 113, 113, 0.45);\r\n background: rgba(248, 113, 113, 0.12);\r\n}\r\n\r\n.icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 12px;\r\n height: 12px;\r\n}\r\n\r\n.content {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n}\r\n","/**\r\n * Compact label component for status chips and tags.\r\n *\r\n * @remarks\r\n * Supports tone and size presets, and can render any inline element.\r\n *\r\n * @param props.as - Element to render (defaults to `span`).\r\n * @param props.tone - Visual tone variant.\r\n * @param props.size - Size preset.\r\n * @param props.icon - Optional leading icon.\r\n */\r\nimport type { HTMLAttributes, ReactNode } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./pill.module.css\";\r\n\r\nexport type PillTone = \"neutral\" | \"success\" | \"warning\" | \"info\" | \"danger\";\r\nexport type PillSize = \"sm\" | \"md\";\r\n\r\ntype PillElement = \"span\" | \"div\" | \"button\";\r\n\r\nexport type PillProps = HTMLAttributes<HTMLElement> & {\r\n /** Optional rendered element; defaults to `span`. */\r\n as?: PillElement;\r\n /** Visual tone; adjusts color and border. */\r\n tone?: PillTone;\r\n /** Size preset. */\r\n size?: PillSize;\r\n /** Leading icon node (not focusable). */\r\n icon?: ReactNode;\r\n};\r\n\r\nexport function Pill({\r\n as,\r\n tone = \"neutral\",\r\n size = \"md\",\r\n icon,\r\n className,\r\n children,\r\n ...rest\r\n}: PillProps) {\r\n const Component: PillElement = as ?? \"span\";\r\n const classes = cx(styles.pill, styles[`tone-${tone}`], styles[`size-${size}`], className);\r\n\r\n return (\r\n <Component className={classes} {...rest}>\r\n {icon ? (\r\n <span className={styles.icon} aria-hidden=\"true\">\r\n {icon}\r\n </span>\r\n ) : null}\r\n <span className={styles.content}>{children}</span>\r\n </Component>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useRef, type ReactNode } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./modal.module.css\";\r\n\r\nexport type ModalSize = \"sm\" | \"md\" | \"lg\";\r\n\r\nexport type ModalProps = {\r\n open: boolean;\r\n onClose: () => void;\r\n title: string;\r\n subtitle?: string;\r\n size?: ModalSize;\r\n /** Content between the header and footer */\r\n children: ReactNode;\r\n /** Rendered inside the footer row — typically action buttons */\r\n footer?: ReactNode;\r\n};\r\n\r\nexport function Modal({ open, onClose, title, subtitle, size = \"md\", children, footer }: ModalProps) {\r\n const mouseDownOnBackdrop = useRef(false);\r\n\r\n if (!open) return null;\r\n\r\n return (\r\n <div\r\n className={styles.backdrop}\r\n onMouseDown={(e) => { mouseDownOnBackdrop.current = e.target === e.currentTarget; }}\r\n onMouseUp={(e) => {\r\n if (mouseDownOnBackdrop.current && e.target === e.currentTarget) onClose();\r\n mouseDownOnBackdrop.current = false;\r\n }}\r\n >\r\n <div className={cx(styles.modal, styles[`size-${size}`])}>\r\n <div className={styles.header}>\r\n <div className={styles.titles}>\r\n <div className={styles.title}>{title}</div>\r\n {subtitle && <div className={styles.subtitle}>{subtitle}</div>}\r\n </div>\r\n <button className={styles.closeButton} onClick={onClose} aria-label=\"Close\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div className={styles.body}>{children}</div>\r\n\r\n {footer && <div className={styles.footer}>{footer}</div>}\r\n </div>\r\n </div>\r\n );\r\n}\r\n",".backdrop {\r\n position: fixed;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.55);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 16px;\r\n z-index: 100;\r\n}\r\n\r\n.modal {\r\n background: #0f172a;\r\n border: 1px solid var(--border, #1f2937);\r\n border-radius: 14px;\r\n padding: 24px;\r\n width: min(500px, 100%);\r\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0;\r\n}\r\n\r\n/* Size variants */\r\n.size-sm { width: min(380px, 100%); }\r\n.size-md { width: min(500px, 100%); }\r\n.size-lg { width: min(640px, 100%); }\r\n\r\n.header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 12px;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.titles {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 3px;\r\n}\r\n\r\n.title {\r\n font-weight: 700;\r\n font-size: 16px;\r\n color: var(--text, #e2e8f0);\r\n line-height: 1.3;\r\n}\r\n\r\n.subtitle {\r\n font-size: 13px;\r\n color: var(--muted, #94a3b8);\r\n line-height: 1.4;\r\n}\r\n\r\n.closeButton {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n flex-shrink: 0;\r\n background: transparent;\r\n border: 1px solid transparent;\r\n border-radius: 6px;\r\n color: var(--muted, #94a3b8);\r\n cursor: pointer;\r\n transition: background 0.12s, color 0.12s;\r\n padding: 0;\r\n}\r\n\r\n.closeButton:hover {\r\n background: rgba(255, 255, 255, 0.07);\r\n color: var(--text, #e2e8f0);\r\n}\r\n\r\n.body {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n}\r\n\r\n.footer {\r\n display: flex;\r\n gap: 8px;\r\n margin-top: 20px;\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n type CSSProperties,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport type {\r\n Toast,\r\n ToastConfig,\r\n ToastContextValue,\r\n ToastOptions,\r\n ToastPosition,\r\n ToastType,\r\n} from \"./types\";\r\nimport styles from \"./toast.module.css\";\r\n\r\n/** Default provider configuration. */\r\nconst DEFAULT_CONFIG: Required<ToastConfig> = {\r\n position: \"top-right\",\r\n maxToasts: 5,\r\n defaultDuration: 4000,\r\n pauseOnHover: true,\r\n pauseOnFocusLoss: true,\r\n};\r\n\r\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\r\n\r\nlet toastIdCounter = 0;\r\nconst generateToastId = () => `toast-${++toastIdCounter}-${Date.now()}`;\r\n\r\n/**\r\n * Toast notification context provider.\r\n *\r\n * @remarks\r\n * Wrap your app (or a section) to enable `useToast` calls. Supports configurable placement,\r\n * maximum visible toasts, and pause behavior on hover or window blur.\r\n *\r\n * @param props.children - React subtree that can consume the toast context.\r\n * @param props.config - Optional provider configuration overrides.\r\n */\r\nexport function ToastProvider({\r\n children,\r\n config,\r\n}: {\r\n children: ReactNode;\r\n config?: ToastConfig;\r\n}) {\r\n const [toasts, setToasts] = useState<Toast[]>([]);\r\n const [isPaused, setIsPaused] = useState(false);\r\n const merged = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);\r\n\r\n const push = useCallback(\r\n (message: string, options: ToastOptions = {}) => {\r\n const id = generateToastId();\r\n setToasts((prev) => {\r\n const next: Toast[] = [\r\n ...prev,\r\n {\r\n id,\r\n message,\r\n type: options.type ?? \"info\",\r\n duration: options.duration ?? (options.type === \"error\" ? 6000 : merged.defaultDuration),\r\n dismissible: options.dismissible ?? true,\r\n action: options.action,\r\n },\r\n ];\r\n if (next.length > merged.maxToasts) next.shift();\r\n return next;\r\n });\r\n return id;\r\n },\r\n [merged.defaultDuration, merged.maxToasts],\r\n );\r\n\r\n const success = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"success\" }),\r\n [push],\r\n );\r\n const error = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) =>\r\n push(message, { ...options, type: \"error\", duration: options?.duration ?? 6000 }),\r\n [push],\r\n );\r\n const warning = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"warning\" }),\r\n [push],\r\n );\r\n const info = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"info\" }),\r\n [push],\r\n );\r\n\r\n const dismiss = useCallback((id: string) => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n }, []);\r\n\r\n const dismissAll = useCallback(() => setToasts([]), []);\r\n\r\n useEffect(() => {\r\n if (!merged.pauseOnFocusLoss) return;\r\n const handleVisibility = () => setIsPaused(document.visibilityState !== \"visible\");\r\n document.addEventListener(\"visibilitychange\", handleVisibility);\r\n return () => document.removeEventListener(\"visibilitychange\", handleVisibility);\r\n }, [merged.pauseOnFocusLoss]);\r\n\r\n const value = useMemo<ToastContextValue>(\r\n () => ({ toasts, push, success, error, warning, info, dismiss, dismissAll }),\r\n [toasts, push, success, error, warning, info, dismiss, dismissAll],\r\n );\r\n\r\n return (\r\n <ToastContext.Provider value={value}>\r\n {children}\r\n <ToastContainer\r\n toasts={toasts}\r\n position={merged.position}\r\n pauseOnHover={merged.pauseOnHover}\r\n isPaused={isPaused}\r\n onDismiss={dismiss}\r\n onPauseChange={setIsPaused}\r\n />\r\n </ToastContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * Hook to access the toast API.\r\n *\r\n * @remarks\r\n * Exposes `push`, intent helpers (`success`, `error`, `warning`, `info`), and dismissal helpers.\r\n * Must be called within a `ToastProvider`.\r\n *\r\n * @throws Error if used outside of a `ToastProvider`.\r\n */\r\nexport function useToast(): ToastContextValue {\r\n const ctx = useContext(ToastContext);\r\n if (!ctx) throw new Error(\"useToast must be used within a ToastProvider\");\r\n return ctx;\r\n}\r\n\r\n/** Renders the positioned toast stack. */\r\nfunction ToastContainer({\r\n toasts,\r\n position,\r\n pauseOnHover,\r\n isPaused,\r\n onDismiss,\r\n onPauseChange,\r\n}: {\r\n toasts: Toast[];\r\n position: ToastPosition;\r\n pauseOnHover: boolean;\r\n isPaused: boolean;\r\n onDismiss: (id: string) => void;\r\n onPauseChange: (paused: boolean) => void;\r\n}) {\r\n const posClass = (() => {\r\n switch (position) {\r\n case \"top-left\":\r\n return styles.topLeft;\r\n case \"top-center\":\r\n return styles.topCenter;\r\n case \"bottom-right\":\r\n return styles.bottomRight;\r\n case \"bottom-left\":\r\n return styles.bottomLeft;\r\n case \"bottom-center\":\r\n return styles.bottomCenter;\r\n case \"top-right\":\r\n default:\r\n return styles.topRight;\r\n }\r\n })();\r\n\r\n return (\r\n <div\r\n className={cx(styles.stack, posClass)}\r\n role=\"presentation\"\r\n onMouseEnter={() => pauseOnHover && onPauseChange(true)}\r\n onMouseLeave={() => pauseOnHover && onPauseChange(false)}\r\n >\r\n {toasts.map((toast) => (\r\n <ToastItem key={toast.id} toast={toast} isPaused={isPaused} onDismiss={onDismiss} />\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\n/** Individual toast item with timers and actions. */\r\nfunction ToastItem({\r\n toast,\r\n isPaused,\r\n onDismiss,\r\n}: {\r\n toast: Toast;\r\n isPaused: boolean;\r\n onDismiss: (id: string) => void;\r\n}) {\r\n const [exiting, setExiting] = useState(false);\r\n const timerRef = useRef<number | null>(null);\r\n const startRef = useRef<number>(0);\r\n const remainingRef = useRef<number>(toast.duration ?? 0);\r\n\r\n const palette = getPalette(toast.type);\r\n const styleVars: CSSProperties = {\r\n [\"--toast-bg\" as any]: palette.background,\r\n [\"--toast-border\" as any]: palette.border,\r\n [\"--toast-text\" as any]: palette.text,\r\n [\"--toast-button-bg\" as any]: palette.buttonBg,\r\n [\"--toast-button-border\" as any]: palette.buttonBorder,\r\n [\"--toast-action-bg\" as any]: palette.actionBg,\r\n [\"--toast-action-border\" as any]: palette.actionBorder,\r\n };\r\n\r\n const stopTimer = () => {\r\n if (timerRef.current) {\r\n window.clearTimeout(timerRef.current);\r\n timerRef.current = null;\r\n }\r\n };\r\n\r\n const triggerDismiss = useCallback(() => {\r\n setExiting(true);\r\n stopTimer();\r\n window.setTimeout(() => onDismiss(toast.id), 160);\r\n }, [onDismiss, toast.id]);\r\n\r\n const schedule = useCallback(\r\n (delay: number) => {\r\n if (!delay || delay <= 0) {\r\n triggerDismiss();\r\n return;\r\n }\r\n startRef.current = performance.now();\r\n stopTimer();\r\n timerRef.current = window.setTimeout(() => triggerDismiss(), delay);\r\n },\r\n [triggerDismiss],\r\n );\r\n\r\n useEffect(() => {\r\n if (!toast.duration || toast.duration <= 0) return undefined;\r\n schedule(toast.duration);\r\n return stopTimer;\r\n }, [schedule, toast.duration]);\r\n\r\n useEffect(() => {\r\n if (!toast.duration || toast.duration <= 0) return;\r\n if (isPaused) {\r\n const elapsed = performance.now() - startRef.current;\r\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\r\n stopTimer();\r\n } else {\r\n schedule(remainingRef.current);\r\n }\r\n }, [isPaused, schedule, toast.duration]);\r\n\r\n const icon = getIcon(toast.type);\r\n\r\n return (\r\n <div className={cx(styles.toast, exiting && styles.exit)} style={styleVars} role=\"status\" aria-live=\"polite\">\r\n <span className={styles.icon} aria-hidden>\r\n {icon}\r\n </span>\r\n <div className={styles.body}>\r\n <div className={styles.message}>{toast.message}</div>\r\n {toast.action && (\r\n <div className={styles.actions}>\r\n <button\r\n type=\"button\"\r\n className={styles.actionButton}\r\n onClick={() => {\r\n toast.action?.onClick();\r\n triggerDismiss();\r\n }}\r\n >\r\n {toast.action.label}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n {toast.dismissible !== false && (\r\n <button\r\n type=\"button\"\r\n className={styles.closeButton}\r\n onClick={triggerDismiss}\r\n aria-label=\"Dismiss notification\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden>\r\n <path\r\n d=\"M11 3L3 11M3 3l8 8\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n strokeLinecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction getPalette(type: ToastType) {\r\n switch (type) {\r\n case \"success\":\r\n return {\r\n background: \"#22c55e\",\r\n border: \"#16a34a\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n case \"error\":\r\n return {\r\n background: \"#f87171\",\r\n border: \"#ef4444\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n case \"warning\":\r\n return {\r\n background: \"#fbbf24\",\r\n border: \"#f59e0b\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n case \"info\":\r\n default:\r\n return {\r\n background: \"#38bdf8\",\r\n border: \"#0ea5e9\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n }\r\n}\r\n\r\nfunction getIcon(type: ToastType) {\r\n switch (type) {\r\n case \"success\":\r\n return \"OK\";\r\n case \"error\":\r\n return \"X\";\r\n case \"warning\":\r\n return \"!\";\r\n case \"info\":\r\n default:\r\n return \"i\";\r\n }\r\n}\r\n",".stack {\r\n position: fixed;\r\n z-index: 2147483000;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n pointer-events: none;\r\n}\r\n\r\n.topRight {\r\n top: 16px;\r\n right: 16px;\r\n align-items: flex-end;\r\n}\r\n\r\n.topLeft {\r\n top: 16px;\r\n left: 16px;\r\n align-items: flex-start;\r\n}\r\n\r\n.topCenter {\r\n top: 16px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n align-items: center;\r\n}\r\n\r\n.bottomRight {\r\n bottom: 16px;\r\n right: 16px;\r\n align-items: flex-end;\r\n}\r\n\r\n.bottomLeft {\r\n bottom: 16px;\r\n left: 16px;\r\n align-items: flex-start;\r\n}\r\n\r\n.bottomCenter {\r\n bottom: 16px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n align-items: center;\r\n}\r\n\r\n.toast {\r\n pointer-events: auto;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 10px;\r\n min-width: 280px;\r\n max-width: min(420px, calc(100vw - 32px));\r\n padding: 12px 14px;\r\n border-radius: 10px;\r\n border: 1px solid var(--toast-border, #1f2937);\r\n background: var(--toast-bg, #111827);\r\n color: var(--toast-text, #e2e8f0);\r\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\r\n animation: toastSlideIn 180ms ease-out;\r\n}\r\n\r\n.toast.exit {\r\n animation: toastSlideOut 160ms ease-in forwards;\r\n}\r\n\r\n.icon {\r\n width: 18px;\r\n height: 18px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.body {\r\n flex: 1;\r\n min-width: 0;\r\n display: grid;\r\n gap: 6px;\r\n}\r\n\r\n.message {\r\n word-break: break-word;\r\n font-size: 14px;\r\n line-height: 1.4;\r\n}\r\n\r\n.actions {\r\n display: flex;\r\n gap: 6px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.actionButton {\r\n padding: 5px 10px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n border-radius: 6px;\r\n border: 1px solid var(--toast-action-border, rgba(0, 0, 0, 0.2));\r\n background: var(--toast-action-bg, rgba(0, 0, 0, 0.1));\r\n color: var(--toast-text, #e2e8f0);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.actionButton:hover {\r\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.15));\r\n}\r\n\r\n.closeButton {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 20px;\r\n height: 20px;\r\n padding: 0;\r\n margin: -2px -4px -2px 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: var(--toast-text, #e2e8f0);\r\n opacity: 0.6;\r\n cursor: pointer;\r\n transition: opacity 120ms ease, background 120ms ease;\r\n}\r\n\r\n.closeButton:hover {\r\n opacity: 1;\r\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.1));\r\n}\r\n\r\n@keyframes toastSlideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-8px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n@keyframes toastSlideOut {\r\n from {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n to {\r\n opacity: 0;\r\n transform: translateY(-6px);\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./dropdown.module.css\";\r\n\r\nexport interface DropdownOption {\r\n label: string;\r\n value: string;\r\n}\r\n\r\nexport interface DropdownProps {\r\n /** List of options to display in the menu. */\r\n options: DropdownOption[];\r\n /** Currently selected value. Use empty string for \"no selection\". */\r\n value: string;\r\n /** Called when the user selects an option. */\r\n onChange: (value: string) => void;\r\n /** Label shown when no option is selected. Defaults to \"All\". */\r\n placeholder?: string;\r\n /** Additional class name for the wrapper element. */\r\n className?: string;\r\n /** Whether to show the placeholder as a clearable option. Defaults to true. */\r\n allowClear?: boolean;\r\n /** Associates the trigger button with an external label element via its id. */\r\n \"aria-labelledby\"?: string;\r\n /** Provides an accessible label directly on the trigger button. */\r\n \"aria-label\"?: string;\r\n}\r\n\r\nexport function Dropdown({\r\n options,\r\n value,\r\n onChange,\r\n placeholder = \"All\",\r\n className,\r\n allowClear = true,\r\n \"aria-labelledby\": ariaLabelledBy,\r\n \"aria-label\": ariaLabel,\r\n}: DropdownProps) {\r\n const [open, setOpen] = useState(false);\r\n const ref = useRef<HTMLDivElement>(null);\r\n\r\n const selected = options.find((o) => o.value === value);\r\n const isActive = allowClear && value !== \"\";\r\n\r\n useEffect(() => {\r\n function handleClickOutside(e: MouseEvent) {\r\n if (ref.current && !ref.current.contains(e.target as Node)) {\r\n setOpen(false);\r\n }\r\n }\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, []);\r\n\r\n return (\r\n <div className={cx(styles.wrapper, className)} ref={ref}>\r\n <button\r\n type=\"button\"\r\n className={cx(styles.trigger, isActive && styles[\"trigger-active\"])}\r\n onClick={() => setOpen((o) => !o)}\r\n aria-labelledby={ariaLabelledBy}\r\n aria-label={ariaLabel}\r\n >\r\n {selected ? selected.label : placeholder}\r\n <span className={cx(styles.chevron, open && styles[\"chevron-open\"])}>\r\n <svg viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\">\r\n <path d=\"M2 3.5L5 6.5L8 3.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n </span>\r\n </button>\r\n\r\n {open && (\r\n <div className={styles.menu}>\r\n {allowClear && (\r\n <button\r\n type=\"button\"\r\n className={cx(styles.option, value === \"\" && styles[\"option-selected\"])}\r\n onClick={() => { onChange(\"\"); setOpen(false); }}\r\n >\r\n {placeholder}\r\n </button>\r\n )}\r\n {options.map((opt) => (\r\n <button\r\n key={opt.value}\r\n type=\"button\"\r\n className={cx(styles.option, value === opt.value && styles[\"option-selected\"])}\r\n onClick={() => { onChange(opt.value); setOpen(false); }}\r\n >\r\n {opt.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n",".wrapper {\r\n position: relative;\r\n display: inline-block;\r\n}\r\n\r\n.trigger {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 6px 10px 6px 14px;\r\n background: var(--ts-dropdown-bg, var(--panel, #111827));\r\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\r\n border-radius: 8px;\r\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\r\n font-size: 0.85rem;\r\n font-weight: 500;\r\n cursor: pointer;\r\n white-space: nowrap;\r\n transition: border-color 0.15s;\r\n user-select: none;\r\n}\r\n\r\n.trigger:hover {\r\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n}\r\n\r\n.trigger-active {\r\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n}\r\n\r\n.chevron {\r\n width: 10px;\r\n height: 10px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: transform 0.15s;\r\n color: var(--muted, #94a3b8);\r\n flex-shrink: 0;\r\n}\r\n\r\n.chevron-open {\r\n transform: rotate(180deg);\r\n}\r\n\r\n.menu {\r\n position: absolute;\r\n top: calc(100% + 6px);\r\n left: 0;\r\n min-width: 100%;\r\n background: var(--ts-dropdown-bg, var(--panel, #111827));\r\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\r\n border-radius: 10px;\r\n padding: 4px;\r\n z-index: 50;\r\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\r\n animation: dropdownFadeIn 0.1s ease;\r\n}\r\n\r\n@keyframes dropdownFadeIn {\r\n from { opacity: 0; transform: translateY(-4px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n.option {\r\n display: block;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n font-size: 0.85rem;\r\n font-weight: 500;\r\n color: var(--muted, #94a3b8);\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n text-align: left;\r\n white-space: nowrap;\r\n transition: background 0.1s, color 0.1s;\r\n}\r\n\r\n.option:hover {\r\n background: rgba(255, 255, 255, 0.05);\r\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\r\n}\r\n\r\n.option-selected {\r\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n background: rgba(34, 211, 238, 0.08);\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n useEffect,\r\n useId,\r\n useRef,\r\n useState,\r\n type CSSProperties,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./app-shell.module.css\";\r\n\r\nconst DESKTOP_BREAKPOINT = 960;\r\n\r\nfunction getIsDesktop() {\r\n if (typeof window === \"undefined\") return false;\r\n return window.innerWidth >= DESKTOP_BREAKPOINT;\r\n}\r\n\r\nexport type AppShellProps = {\r\n /** Primary page content rendered in the main area. */\r\n children: ReactNode;\r\n /** Sidebar navigation or custom content. */\r\n sidebar: ReactNode;\r\n /** Brand element rendered next to the hamburger (text or JSX). */\r\n brand?: ReactNode;\r\n /** Optional brand href; when provided the brand renders as an anchor. */\r\n brandHref?: string;\r\n /** Optional content after the brand on the left side of the top bar. */\r\n topbarStart?: ReactNode;\r\n /** Optional content aligned to the right side of the top bar. */\r\n topbarEnd?: ReactNode;\r\n /** Custom class names for styling overrides. */\r\n className?: string;\r\n sidebarClassName?: string;\r\n topbarClassName?: string;\r\n mainClassName?: string;\r\n /** Sets the sidebar width (e.g., `260`, `\"18rem\"`). */\r\n sidebarWidth?: number | string;\r\n /**\r\n * Closes the sidebar on mobile whenever this value changes.\r\n * Useful for reacting to route/pathname changes.\r\n */\r\n closeSidebarOnChangeKey?: unknown;\r\n /** Label for the hamburger button (aria-label). */\r\n hamburgerLabel?: string;\r\n /** Optional callback fired whenever the sidebar open state changes. */\r\n onSidebarToggle?: (open: boolean) => void;\r\n};\r\n\r\n/**\r\n * Responsive application shell with a collapsible sidebar and sticky top bar.\r\n *\r\n * - Sidebar opens by default on desktop, collapses on mobile.\r\n * - Closes on outside click/scroll/touch when in mobile mode.\r\n * - Provides optional hook to close the sidebar when a prop value changes\r\n * (e.g., route transitions).\r\n */\r\nexport function AppShell({\r\n children,\r\n sidebar,\r\n brand,\r\n brandHref,\r\n topbarStart,\r\n topbarEnd,\r\n className,\r\n sidebarClassName,\r\n topbarClassName,\r\n mainClassName,\r\n sidebarWidth,\r\n closeSidebarOnChangeKey,\r\n hamburgerLabel = \"Toggle navigation\",\r\n onSidebarToggle,\r\n}: AppShellProps) {\r\n const [isDesktop, setIsDesktop] = useState(false);\r\n const [sidebarOpen, setSidebarOpen] = useState(false);\r\n const prevIsDesktopRef = useRef(false);\r\n const closeKeyRef = useRef(closeSidebarOnChangeKey);\r\n\r\n const sidebarRef = useRef<HTMLElement | null>(null);\r\n const hamburgerRef = useRef<HTMLButtonElement | null>(null);\r\n const mainRef = useRef<HTMLElement | null>(null);\r\n const sidebarId = useId();\r\n\r\n useEffect(() => {\r\n const desktop = getIsDesktop();\r\n setIsDesktop(desktop);\r\n setSidebarOpen(desktop);\r\n prevIsDesktopRef.current = desktop;\r\n\r\n const handleResize = () => {\r\n const nowDesktop = getIsDesktop();\r\n setIsDesktop(nowDesktop);\r\n if (nowDesktop !== prevIsDesktopRef.current) {\r\n setSidebarOpen(nowDesktop);\r\n prevIsDesktopRef.current = nowDesktop;\r\n }\r\n };\r\n\r\n window.addEventListener(\"resize\", handleResize);\r\n return () => window.removeEventListener(\"resize\", handleResize);\r\n }, []);\r\n\r\n // Close the sidebar when clicking outside or scrolling on mobile.\r\n useEffect(() => {\r\n if (isDesktop || !sidebarOpen) return;\r\n\r\n const mainElement = mainRef.current;\r\n const closeSidebar = () => setSidebarOpen(false);\r\n\r\n const onPointerDown = (e: PointerEvent) => {\r\n const target = e.target as Node | null;\r\n if (!target) return;\r\n if (sidebarRef.current?.contains(target)) return;\r\n if (hamburgerRef.current?.contains(target)) return;\r\n closeSidebar();\r\n };\r\n\r\n const timeoutId = window.setTimeout(() => {\r\n document.addEventListener(\"pointerdown\", onPointerDown);\r\n window.addEventListener(\"scroll\", closeSidebar, { passive: true });\r\n mainElement?.addEventListener(\"scroll\", closeSidebar, { passive: true });\r\n document.addEventListener(\"touchmove\", closeSidebar, { passive: true });\r\n }, 10);\r\n\r\n return () => {\r\n window.clearTimeout(timeoutId);\r\n document.removeEventListener(\"pointerdown\", onPointerDown);\r\n window.removeEventListener(\"scroll\", closeSidebar);\r\n mainElement?.removeEventListener(\"scroll\", closeSidebar);\r\n document.removeEventListener(\"touchmove\", closeSidebar);\r\n };\r\n }, [sidebarOpen, isDesktop]);\r\n\r\n // Allow consumers to request a mobile sidebar close when a value changes (e.g., pathname).\r\n useEffect(() => {\r\n if (!isDesktop && closeKeyRef.current !== closeSidebarOnChangeKey) {\r\n setSidebarOpen(false);\r\n }\r\n closeKeyRef.current = closeSidebarOnChangeKey;\r\n }, [closeSidebarOnChangeKey, isDesktop]);\r\n\r\n useEffect(() => {\r\n onSidebarToggle?.(sidebarOpen);\r\n }, [sidebarOpen, onSidebarToggle]);\r\n\r\n const toggleSidebar = () => setSidebarOpen((open) => !open);\r\n\r\n const sidebarWidthValue =\r\n sidebarWidth === undefined\r\n ? undefined\r\n : typeof sidebarWidth === \"number\"\r\n ? `${sidebarWidth}px`\r\n : sidebarWidth;\r\n\r\n const shellStyle: CSSProperties | undefined = sidebarWidthValue\r\n ? { [\"--app-shell-sidebar-width\" as string]: sidebarWidthValue }\r\n : undefined;\r\n\r\n const shellClasses = cx(\r\n styles.shell,\r\n sidebarOpen ? styles.sidebarOpen : styles.sidebarCollapsed,\r\n className,\r\n );\r\n\r\n const sidebarClasses = cx(styles.sidebar, sidebarOpen && styles.open, sidebarClassName);\r\n\r\n return (\r\n <div\r\n className={shellClasses}\r\n style={shellStyle}\r\n data-app-shell\r\n data-desktop={isDesktop ? \"true\" : \"false\"}\r\n data-sidebar-open={sidebarOpen ? \"true\" : \"false\"}\r\n >\r\n <header className={cx(styles.topbar, topbarClassName)}>\r\n <div className={styles.topbarLeft}>\r\n <button\r\n ref={hamburgerRef}\r\n type=\"button\"\r\n className={styles.hamburger}\r\n onClick={toggleSidebar}\r\n aria-label={hamburgerLabel}\r\n aria-expanded={sidebarOpen}\r\n aria-controls={sidebarId}\r\n >\r\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\r\n </svg>\r\n </button>\r\n {brand &&\r\n (brandHref ? (\r\n <a className={styles.brand} href={brandHref}>\r\n {brand}\r\n </a>\r\n ) : (\r\n <div className={styles.brand}>{brand}</div>\r\n ))}\r\n {topbarStart && <div className={styles.topbarStart}>{topbarStart}</div>}\r\n </div>\r\n <div className={styles.topbarRight}>{topbarEnd}</div>\r\n </header>\r\n {!isDesktop && sidebarOpen && (\r\n <div className={styles.backdrop} onClick={() => setSidebarOpen(false)} onTouchStart={() => setSidebarOpen(false)} aria-hidden=\"true\" />\r\n )}\r\n <aside ref={sidebarRef} id={sidebarId} className={sidebarClasses} aria-label=\"Sidebar navigation\">\r\n {sidebar}\r\n </aside>\r\n <main ref={mainRef} className={cx(styles.main, mainClassName)}>\r\n {children}\r\n </main>\r\n </div>\r\n );\r\n}\r\n",".shell {\r\n display: grid;\r\n grid-template-rows: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top)) 1fr;\r\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\r\n min-height: 100vh;\r\n min-height: 100dvh;\r\n transition: grid-template-columns 200ms ease;\r\n}\r\n\r\n.shell.sidebarOpen {\r\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\r\n}\r\n\r\n.shell.sidebarCollapsed {\r\n grid-template-columns: 0 1fr;\r\n}\r\n\r\n.topbar {\r\n grid-column: 1 / -1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top));\r\n padding: env(safe-area-inset-top) 16px 0 16px;\r\n border-bottom: 1px solid var(--border);\r\n background: rgba(17, 24, 39, 0.8);\r\n backdrop-filter: blur(8px);\r\n position: sticky;\r\n top: 0;\r\n z-index: 20;\r\n gap: 12px;\r\n}\r\n\r\n.topbarLeft {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.topbarStart {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.topbarRight {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n min-width: 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.topbarRight > * {\r\n min-width: 0;\r\n}\r\n\r\n.brand {\r\n font-size: 26px;\r\n color: var(--text);\r\n text-decoration: none;\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.hamburger {\r\n background: transparent;\r\n border: none;\r\n padding: 0;\r\n width: 40px;\r\n height: 40px;\r\n border-radius: 8px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--text);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.hamburger:hover {\r\n background: rgba(255, 255, 255, 0.06);\r\n}\r\n\r\n.hamburger:focus,\r\n.hamburger:focus-visible {\r\n outline: none;\r\n box-shadow: none;\r\n}\r\n\r\n.hamburger svg {\r\n width: 28px;\r\n height: 28px;\r\n}\r\n\r\n.sidebar {\r\n border-right: 1px solid var(--border);\r\n background: #152036;\r\n padding: 24px;\r\n transition: transform 200ms ease, opacity 200ms ease;\r\n}\r\n\r\n.shell.sidebarCollapsed .sidebar {\r\n transform: translateX(-110%);\r\n opacity: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.main {\r\n overflow-y: auto;\r\n padding: 24px;\r\n padding-bottom: 96px;\r\n min-height: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n align-items: center;\r\n}\r\n\r\n.main > * {\r\n width: 100%;\r\n max-width: 1200px;\r\n min-width: 0;\r\n}\r\n\r\n.backdrop {\r\n display: none;\r\n}\r\n\r\n@media (max-width: 960px) {\r\n .backdrop {\r\n display: block;\r\n position: fixed;\r\n inset: 0;\r\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\r\n background: rgba(0, 0, 0, 0.5);\r\n z-index: 14;\r\n }\r\n\r\n .shell {\r\n --app-shell-topbar-height: 56px;\r\n grid-template-columns: 1fr;\r\n grid-template-rows: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top)) 1fr;\r\n }\r\n\r\n .shell.sidebarOpen,\r\n .shell.sidebarCollapsed {\r\n grid-template-columns: 1fr;\r\n }\r\n\r\n .sidebar {\r\n display: block;\r\n position: fixed;\r\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\r\n left: 0;\r\n bottom: 0;\r\n width: var(--app-shell-sidebar-width, 240px);\r\n max-width: 80vw;\r\n background: #152036;\r\n padding: 16px 12px;\r\n transform: translateX(-105%);\r\n z-index: 15;\r\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);\r\n }\r\n\r\n .sidebar.open {\r\n transform: translateX(0);\r\n }\r\n\r\n .topbar {\r\n padding-left: max(12px, env(safe-area-inset-left));\r\n padding-right: max(12px, env(safe-area-inset-right));\r\n gap: 10px;\r\n }\r\n\r\n .topbarLeft {\r\n gap: 10px;\r\n flex: 1;\r\n }\r\n\r\n .topbarStart {\r\n min-width: 0;\r\n }\r\n\r\n .topbarRight {\r\n gap: 6px;\r\n }\r\n\r\n .brand {\r\n font-size: 24px;\r\n max-width: 50vw;\r\n }\r\n\r\n .hamburger {\r\n width: 40px;\r\n height: 40px;\r\n border-radius: 8px;\r\n }\r\n\r\n .hamburger svg {\r\n width: 24px;\r\n height: 24px;\r\n }\r\n\r\n .main {\r\n padding: 16px;\r\n padding-bottom: 96px;\r\n }\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .topbar {\r\n gap: 8px;\r\n }\r\n\r\n .brand {\r\n font-size: 22px;\r\n max-width: 34vw;\r\n }\r\n\r\n .topbarRight {\r\n max-width: 44vw;\r\n }\r\n\r\n .main {\r\n padding: 12px 10px;\r\n padding-bottom: 88px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .brand {\r\n font-size: 20px;\r\n max-width: 30vw;\r\n }\r\n}\r\n",".nav {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n align-items: stretch;\r\n}\r\n\r\n.item {\r\n color: var(--text, #e2e8f0);\r\n background: transparent;\r\n border: none;\r\n box-shadow: none;\r\n padding: 10px 12px 10px 10px;\r\n border-radius: 10px;\r\n text-decoration: none;\r\n font-size: 14px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n width: 100%;\r\n justify-content: flex-start;\r\n text-align: left;\r\n box-sizing: border-box;\r\n white-space: nowrap;\r\n line-height: 1.2;\r\n transition: background 120ms ease, color 120ms ease;\r\n}\r\n\r\n.item:focus,\r\n.item:focus-visible {\r\n outline: none;\r\n box-shadow: none;\r\n}\r\n\r\n.item:hover {\r\n background: rgba(29, 43, 70, 0.55);\r\n}\r\n\r\n.item.active {\r\n background: rgba(29, 43, 70, 0.85);\r\n color: var(--text, #e2e8f0);\r\n font-weight: 700;\r\n}\r\n\r\n.icon {\r\n width: 18px;\r\n height: 18px;\r\n color: var(--muted, #94a3b8);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: 0 0 18px;\r\n vertical-align: middle;\r\n}\r\n\r\n.icon svg {\r\n width: 18px;\r\n height: 18px;\r\n display: block;\r\n stroke: currentColor;\r\n}\r\n\r\n.item.active .icon {\r\n color: var(--accent, #22d3ee);\r\n}\r\n\r\n.label {\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.badge {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n padding: 4px 8px;\r\n border-radius: 999px;\r\n border: 1px solid var(--border, #1f2937);\r\n background: rgba(255, 255, 255, 0.04);\r\n color: var(--muted, #94a3b8);\r\n font-size: 11px;\r\n letter-spacing: 0.04em;\r\n text-transform: uppercase;\r\n}\r\n\r\n@media (max-width: 960px) {\r\n .nav {\r\n gap: 6px;\r\n }\r\n\r\n .item {\r\n padding: 9px 10px 9px 8px;\r\n border-radius: 9px;\r\n font-size: 14px;\r\n gap: 6px;\r\n }\r\n\r\n .icon {\r\n width: 16px;\r\n height: 16px;\r\n flex: 0 0 16px;\r\n }\r\n\r\n .icon svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .item {\r\n padding: 8px 9px 8px 7px;\r\n font-size: 13px;\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport { type AnchorHTMLAttributes, type ReactNode } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./sidebar-nav.module.css\";\r\n\r\nexport type SidebarNavItem = {\r\n label: string;\r\n href: string;\r\n icon?: ReactNode;\r\n badge?: ReactNode;\r\n active?: boolean;\r\n target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\r\n rel?: AnchorHTMLAttributes<HTMLAnchorElement>[\"rel\"];\r\n onClick?: () => void;\r\n};\r\n\r\nexport type SidebarNavProps = {\r\n items: SidebarNavItem[];\r\n /** Optional path-like value used for default active matching. */\r\n currentPath?: string;\r\n /**\r\n * Custom active matcher. Defaults to prefix matching (with a special case for `/`).\r\n * If `item.active` is provided, it wins over this function.\r\n */\r\n getIsActive?: (item: SidebarNavItem, currentPath?: string) => boolean;\r\n /** Called after the item click handler (if provided). */\r\n onItemClick?: (item: SidebarNavItem) => void;\r\n className?: string;\r\n itemClassName?: string;\r\n};\r\n\r\nconst defaultIsActive = (item: SidebarNavItem, path?: string) => {\r\n if (item.active !== undefined) return item.active;\r\n if (!path) return false;\r\n if (item.href === \"/\") return path === \"/\";\r\n return path.startsWith(item.href);\r\n};\r\n\r\nexport function SidebarNav({\r\n items,\r\n currentPath,\r\n getIsActive = defaultIsActive,\r\n onItemClick,\r\n className,\r\n itemClassName,\r\n}: SidebarNavProps) {\r\n return (\r\n <nav className={cx(styles.nav, className)} aria-label=\"Sidebar navigation\">\r\n {items.map((item) => {\r\n const active = getIsActive(item, currentPath);\r\n const rel = item.rel ?? (item.target === \"_blank\" ? \"noreferrer\" : undefined);\r\n\r\n return (\r\n <a\r\n key={item.href}\r\n className={cx(styles.item, active && styles.active, itemClassName)}\r\n href={item.href}\r\n target={item.target}\r\n rel={rel}\r\n aria-current={active ? \"page\" : undefined}\r\n onClick={() => {\r\n item.onClick?.();\r\n onItemClick?.(item);\r\n }}\r\n >\r\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\r\n <span className={styles.label}>{item.label}</span>\r\n {item.badge && <span className={styles.badge}>{item.badge}</span>}\r\n </a>\r\n );\r\n })}\r\n </nav>\r\n );\r\n}\r\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/cx.ts","../src/components/button/button.module.css","../src/components/button/Button.tsx","../src/components/card/card.module.css","../src/components/card/Card.tsx","../src/components/pill/pill.module.css","../src/components/pill/Pill.tsx","../src/components/modal/Modal.tsx","../src/components/modal/modal.module.css","../src/components/toast/ToastContext.tsx","../src/components/toast/toast.module.css","../src/components/dropdown/Dropdown.tsx","../src/components/dropdown/dropdown.module.css","../src/components/app-shell/AppShell.tsx","../src/components/app-shell/app-shell.module.css","../src/components/sidebar-nav/sidebar-nav.module.css","../src/components/sidebar-nav/SidebarNav.tsx"],"sourcesContent":["// Primitives\nexport type { ButtonProps, ButtonVariant, ButtonSize } from \"./components/button/Button\";\nexport { Button } from \"./components/button/Button\";\n\nexport type { CardProps, CardPadding, CardTone } from \"./components/card/Card\";\nexport { Card } from \"./components/card/Card\";\n\nexport type { PillProps, PillSize, PillTone } from \"./components/pill/Pill\";\nexport { Pill } from \"./components/pill/Pill\";\n\n// Overlays\nexport type { ModalProps, ModalSize } from \"./components/modal/Modal\";\nexport { Modal } from \"./components/modal/Modal\";\n\nexport { ToastProvider, useToast } from \"./components/toast/ToastContext\";\nexport type {\n Toast,\n ToastConfig,\n ToastContextValue,\n ToastOptions,\n ToastPosition,\n ToastType,\n} from \"./components/toast/types\";\n\n// Inputs\nexport type { DropdownProps, DropdownOption } from \"./components/dropdown/Dropdown\";\nexport { Dropdown } from \"./components/dropdown/Dropdown\";\n\n// Layout\nexport type { AppShellProps } from \"./components/app-shell/AppShell\";\nexport { AppShell } from \"./components/app-shell/AppShell\";\n\nexport type { SidebarNavItem, SidebarNavProps } from \"./components/sidebar-nav/SidebarNav\";\nexport { SidebarNav } from \"./components/sidebar-nav/SidebarNav\";\n\n// Utils\nexport { cx } from \"./utils/cx\";\n","export function cx(...values: Array<string | false | null | undefined>): string {\n return values.filter(Boolean).join(\" \");\n}\n",".button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font-family: inherit;\n font-weight: 600;\n border-radius: 8px;\n border: none;\n cursor: pointer;\n text-decoration: none;\n transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s;\n white-space: nowrap;\n}\n\n.button:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Sizes */\n.size-sm {\n font-size: 0.82rem;\n padding: 6px 14px;\n}\n\n.size-md {\n font-size: 0.95rem;\n padding: 10px 22px;\n}\n\n.size-lg {\n font-size: 1rem;\n padding: 12px 28px;\n}\n\n/* Variants */\n.variant-primary {\n background: var(--ts-btn-primary-bg, var(--accent, #22d3ee));\n color: var(--ts-btn-primary-text, #0f172a);\n border: 1px solid transparent;\n}\n\n.variant-primary:hover:not(:disabled) {\n opacity: 0.88;\n}\n\n.variant-secondary {\n background: var(--ts-btn-secondary-bg, rgba(255, 255, 255, 0.06));\n color: var(--ts-btn-secondary-text, var(--text, #e2e8f0));\n border: 1px solid var(--ts-btn-secondary-border, var(--border, #1f2937));\n}\n\n.variant-secondary:hover:not(:disabled) {\n background: var(--ts-btn-secondary-hover-bg, rgba(255, 255, 255, 0.1));\n}\n\n.variant-outline {\n background: transparent;\n color: var(--ts-btn-outline-text, var(--text, #e2e8f0));\n border: 1px solid var(--ts-btn-outline-border, var(--border, #1f2937));\n}\n\n.variant-outline:hover:not(:disabled) {\n border-color: var(--ts-btn-outline-hover-border, var(--accent, #22d3ee));\n color: var(--ts-btn-outline-hover-text, var(--accent, #22d3ee));\n}\n\n.variant-ghost {\n background: transparent;\n color: var(--ts-btn-ghost-text, var(--muted, #94a3b8));\n border: 1px solid transparent;\n padding-left: 8px;\n padding-right: 8px;\n}\n\n.variant-ghost:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.05);\n color: var(--text, #e2e8f0);\n}\n","import type { ButtonHTMLAttributes, AnchorHTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./button.module.css\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\ntype BaseProps = {\n variant?: ButtonVariant;\n size?: ButtonSize;\n className?: string;\n children?: React.ReactNode;\n};\n\ntype AsButton = BaseProps &\n ButtonHTMLAttributes<HTMLButtonElement> & { as?: \"button\" };\n\ntype AsAnchor = BaseProps &\n AnchorHTMLAttributes<HTMLAnchorElement> & { as: \"a\" };\n\nexport type ButtonProps = AsButton | AsAnchor;\n\nexport function Button({\n as,\n variant = \"primary\",\n size = \"md\",\n className,\n children,\n ...rest\n}: ButtonProps) {\n const classes = cx(\n styles.button,\n styles[`variant-${variant}`],\n styles[`size-${size}`],\n className,\n );\n\n if (as === \"a\") {\n return (\n <a className={classes} {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}>\n {children}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n className={classes}\n {...(rest as ButtonHTMLAttributes<HTMLButtonElement>)}\n >\n {children}\n </button>\n );\n}\n",".card {\n position: relative;\n overflow: visible;\n border-radius: var(--ts-card-radius, 12px);\n border: 1px solid var(--ts-card-border, var(--border, #1f2937));\n background: var(--ts-card-bg, var(--panel, #111827));\n color: var(--ts-card-fg, var(--text, #e2e8f0));\n box-shadow: var(--ts-card-shadow, 0 16px 36px rgba(0, 0, 0, 0.28));\n padding: var(--ts-card-padding, 16px);\n transition:\n transform 140ms ease,\n box-shadow 140ms ease,\n border-color 140ms ease,\n background-color 140ms ease;\n}\n\n.tone-default {\n --ts-card-bg: var(--panel, #111827);\n --ts-card-border: var(--border, #1f2937);\n --ts-card-shadow: 0 16px 36px rgba(0, 0, 0, 0.28);\n}\n\n.tone-muted {\n --ts-card-bg: var(--ts-card-muted-bg, rgba(255, 255, 255, 0.02));\n --ts-card-border: var(--ts-card-muted-border, rgba(255, 255, 255, 0.06));\n --ts-card-shadow: 0 10px 26px rgba(0, 0, 0, 0.22);\n}\n\n.tone-contrast {\n --ts-card-bg: var(--ts-card-contrast-bg, #0b1224);\n --ts-card-border: var(--ts-card-contrast-border, rgba(255, 255, 255, 0.1));\n --ts-card-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);\n}\n\n.interactive {\n cursor: default;\n}\n\n.interactive:hover {\n transform: translateY(-1px);\n box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);\n border-color: var(--ts-card-hover-border, rgba(34, 211, 238, 0.4));\n}\n\n.interactive:focus-within {\n outline: 2px solid var(--ts-card-hover-border, rgba(34, 211, 238, 0.45));\n outline-offset: 2px;\n}\n\n.padding-none {\n --ts-card-padding: 0;\n}\n\n.padding-sm {\n --ts-card-padding: 10px;\n}\n\n.padding-md {\n --ts-card-padding: 16px;\n}\n\n.padding-lg {\n --ts-card-padding: 20px;\n}\n","/**\n * Lightweight container component used for panels across the app.\n *\n * @remarks\n * Supports tone variants, padding presets, and an optional interactive affordance.\n *\n * @param props.as - Semantic element to render (defaults to `div`).\n * @param props.tone - Visual tone variant.\n * @param props.padding - Padding preset.\n * @param props.interactive - Enables hover/focus affordance.\n */\nimport type { HTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./card.module.css\";\n\nexport type CardTone = \"default\" | \"muted\" | \"contrast\";\nexport type CardPadding = \"none\" | \"sm\" | \"md\" | \"lg\";\n\ntype CardElement = \"div\" | \"section\" | \"article\";\n\nexport type CardProps = HTMLAttributes<HTMLElement> & {\n /** Optional semantic element type. Defaults to `div`. */\n as?: CardElement;\n /** Visual tone; drives background/border CSS vars. */\n tone?: CardTone;\n /** Padding preset; maps to CSS variables so consumers can override globally. */\n padding?: CardPadding;\n /** Adds hover/focus affordance (lift + outline). */\n interactive?: boolean;\n};\n\nexport function Card({\n as,\n tone = \"default\",\n padding = \"md\",\n interactive = false,\n className,\n children,\n ...rest\n}: CardProps) {\n const Component: CardElement = as ?? \"div\";\n const toneClass = tone !== \"default\" ? styles[`tone-${tone}`] : null;\n const classes = cx(\n styles.card,\n toneClass,\n styles[`padding-${padding}`],\n interactive && styles.interactive,\n className,\n );\n\n return (\n <Component className={classes} {...rest}>\n {children}\n </Component>\n );\n}\n",".pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n border: 1px solid var(--ts-pill-border, var(--border, #1f2937));\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n line-height: 1.2;\n white-space: nowrap;\n}\n\n.size-sm {\n padding: 3px 8px;\n font-size: 11px;\n}\n\n.size-md {\n padding: 4px 10px;\n}\n\n.tone-neutral {\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\n border-color: var(--ts-pill-border, var(--border, #1f2937));\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\n}\n\n.tone-success {\n color: #22c55e;\n border-color: rgba(34, 197, 94, 0.45);\n background: rgba(34, 197, 94, 0.12);\n}\n\n.tone-warning {\n color: #f59e0b;\n border-color: rgba(245, 158, 11, 0.45);\n background: rgba(245, 158, 11, 0.12);\n}\n\n.tone-info {\n color: #22d3ee;\n border-color: rgba(34, 211, 238, 0.5);\n background: rgba(34, 211, 238, 0.12);\n}\n\n.tone-danger {\n color: #f87171;\n border-color: rgba(248, 113, 113, 0.45);\n background: rgba(248, 113, 113, 0.12);\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n}\n\n.content {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n","/**\n * Compact label component for status chips and tags.\n *\n * @remarks\n * Supports tone and size presets, and can render any inline element.\n *\n * @param props.as - Element to render (defaults to `span`).\n * @param props.tone - Visual tone variant.\n * @param props.size - Size preset.\n * @param props.icon - Optional leading icon.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./pill.module.css\";\n\nexport type PillTone = \"neutral\" | \"success\" | \"warning\" | \"info\" | \"danger\";\nexport type PillSize = \"sm\" | \"md\";\n\ntype PillElement = \"span\" | \"div\" | \"button\";\n\nexport type PillProps = HTMLAttributes<HTMLElement> & {\n /** Optional rendered element; defaults to `span`. */\n as?: PillElement;\n /** Visual tone; adjusts color and border. */\n tone?: PillTone;\n /** Size preset. */\n size?: PillSize;\n /** Leading icon node (not focusable). */\n icon?: ReactNode;\n};\n\nexport function Pill({\n as,\n tone = \"neutral\",\n size = \"md\",\n icon,\n className,\n children,\n ...rest\n}: PillProps) {\n const Component: PillElement = as ?? \"span\";\n const classes = cx(styles.pill, styles[`tone-${tone}`], styles[`size-${size}`], className);\n\n return (\n <Component className={classes} {...rest}>\n {icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span className={styles.content}>{children}</span>\n </Component>\n );\n}\n","\"use client\";\n\nimport { useRef, type ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./modal.module.css\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\";\n\nexport type ModalProps = {\n open: boolean;\n onClose: () => void;\n title: string;\n subtitle?: string;\n size?: ModalSize;\n /** Content between the header and footer */\n children: ReactNode;\n /** Rendered inside the footer row — typically action buttons */\n footer?: ReactNode;\n};\n\nexport function Modal({ open, onClose, title, subtitle, size = \"md\", children, footer }: ModalProps) {\n const mouseDownOnBackdrop = useRef(false);\n\n if (!open) return null;\n\n return (\n <div\n className={styles.backdrop}\n onMouseDown={(e) => { mouseDownOnBackdrop.current = e.target === e.currentTarget; }}\n onMouseUp={(e) => {\n if (mouseDownOnBackdrop.current && e.target === e.currentTarget) onClose();\n mouseDownOnBackdrop.current = false;\n }}\n >\n <div className={cx(styles.modal, styles[`size-${size}`])}>\n <div className={styles.header}>\n <div className={styles.titles}>\n <div className={styles.title}>{title}</div>\n {subtitle && <div className={styles.subtitle}>{subtitle}</div>}\n </div>\n <button className={styles.closeButton} onClick={onClose} aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n <div className={styles.body}>{children}</div>\n\n {footer && <div className={styles.footer}>{footer}</div>}\n </div>\n </div>\n );\n}\n",".backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.55);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n z-index: 100;\n}\n\n.modal {\n background: #0f172a;\n border: 1px solid var(--border, #1f2937);\n border-radius: 14px;\n padding: 24px;\n width: min(500px, 100%);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n\n/* Size variants */\n.size-sm { width: min(380px, 100%); }\n.size-md { width: min(500px, 100%); }\n.size-lg { width: min(640px, 100%); }\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.titles {\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.title {\n font-weight: 700;\n font-size: 16px;\n color: var(--text, #e2e8f0);\n line-height: 1.3;\n}\n\n.subtitle {\n font-size: 13px;\n color: var(--muted, #94a3b8);\n line-height: 1.4;\n}\n\n.closeButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex-shrink: 0;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: var(--muted, #94a3b8);\n cursor: pointer;\n transition: background 0.12s, color 0.12s;\n padding: 0;\n}\n\n.closeButton:hover {\n background: rgba(255, 255, 255, 0.07);\n color: var(--text, #e2e8f0);\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.footer {\n display: flex;\n gap: 8px;\n margin-top: 20px;\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport type {\n Toast,\n ToastConfig,\n ToastContextValue,\n ToastOptions,\n ToastPosition,\n ToastType,\n} from \"./types\";\nimport styles from \"./toast.module.css\";\n\n/** Default provider configuration. */\nconst DEFAULT_CONFIG: Required<ToastConfig> = {\n position: \"top-right\",\n maxToasts: 5,\n defaultDuration: 4000,\n pauseOnHover: true,\n pauseOnFocusLoss: true,\n};\n\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\n\nlet toastIdCounter = 0;\nconst generateToastId = () => `toast-${++toastIdCounter}-${Date.now()}`;\n\n/**\n * Toast notification context provider.\n *\n * @remarks\n * Wrap your app (or a section) to enable `useToast` calls. Supports configurable placement,\n * maximum visible toasts, and pause behavior on hover or window blur.\n *\n * @param props.children - React subtree that can consume the toast context.\n * @param props.config - Optional provider configuration overrides.\n */\nexport function ToastProvider({\n children,\n config,\n}: {\n children: ReactNode;\n config?: ToastConfig;\n}) {\n const [toasts, setToasts] = useState<Toast[]>([]);\n const [isPaused, setIsPaused] = useState(false);\n const merged = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);\n\n const push = useCallback(\n (message: string, options: ToastOptions = {}) => {\n const id = generateToastId();\n setToasts((prev) => {\n const next: Toast[] = [\n ...prev,\n {\n id,\n message,\n type: options.type ?? \"info\",\n duration: options.duration ?? (options.type === \"error\" ? 6000 : merged.defaultDuration),\n dismissible: options.dismissible ?? true,\n action: options.action,\n },\n ];\n if (next.length > merged.maxToasts) next.shift();\n return next;\n });\n return id;\n },\n [merged.defaultDuration, merged.maxToasts],\n );\n\n const success = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"success\" }),\n [push],\n );\n const error = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) =>\n push(message, { ...options, type: \"error\", duration: options?.duration ?? 6000 }),\n [push],\n );\n const warning = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"warning\" }),\n [push],\n );\n const info = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"info\" }),\n [push],\n );\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, []);\n\n const dismissAll = useCallback(() => setToasts([]), []);\n\n useEffect(() => {\n if (!merged.pauseOnFocusLoss) return;\n const handleVisibility = () => setIsPaused(document.visibilityState !== \"visible\");\n document.addEventListener(\"visibilitychange\", handleVisibility);\n return () => document.removeEventListener(\"visibilitychange\", handleVisibility);\n }, [merged.pauseOnFocusLoss]);\n\n const value = useMemo<ToastContextValue>(\n () => ({ toasts, push, success, error, warning, info, dismiss, dismissAll }),\n [toasts, push, success, error, warning, info, dismiss, dismissAll],\n );\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n <ToastContainer\n toasts={toasts}\n position={merged.position}\n pauseOnHover={merged.pauseOnHover}\n isPaused={isPaused}\n onDismiss={dismiss}\n onPauseChange={setIsPaused}\n />\n </ToastContext.Provider>\n );\n}\n\n/**\n * Hook to access the toast API.\n *\n * @remarks\n * Exposes `push`, intent helpers (`success`, `error`, `warning`, `info`), and dismissal helpers.\n * Must be called within a `ToastProvider`.\n *\n * @throws Error if used outside of a `ToastProvider`.\n */\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used within a ToastProvider\");\n return ctx;\n}\n\n/** Renders the positioned toast stack. */\nfunction ToastContainer({\n toasts,\n position,\n pauseOnHover,\n isPaused,\n onDismiss,\n onPauseChange,\n}: {\n toasts: Toast[];\n position: ToastPosition;\n pauseOnHover: boolean;\n isPaused: boolean;\n onDismiss: (id: string) => void;\n onPauseChange: (paused: boolean) => void;\n}) {\n const posClass = (() => {\n switch (position) {\n case \"top-left\":\n return styles.topLeft;\n case \"top-center\":\n return styles.topCenter;\n case \"bottom-right\":\n return styles.bottomRight;\n case \"bottom-left\":\n return styles.bottomLeft;\n case \"bottom-center\":\n return styles.bottomCenter;\n case \"top-right\":\n default:\n return styles.topRight;\n }\n })();\n\n return (\n <div\n className={cx(styles.stack, posClass)}\n role=\"presentation\"\n onMouseEnter={() => pauseOnHover && onPauseChange(true)}\n onMouseLeave={() => pauseOnHover && onPauseChange(false)}\n >\n {toasts.map((toast) => (\n <ToastItem key={toast.id} toast={toast} isPaused={isPaused} onDismiss={onDismiss} />\n ))}\n </div>\n );\n}\n\n/** Individual toast item with timers and actions. */\nfunction ToastItem({\n toast,\n isPaused,\n onDismiss,\n}: {\n toast: Toast;\n isPaused: boolean;\n onDismiss: (id: string) => void;\n}) {\n const [exiting, setExiting] = useState(false);\n const timerRef = useRef<number | null>(null);\n const startRef = useRef<number>(0);\n const remainingRef = useRef<number>(toast.duration ?? 0);\n\n const palette = getPalette(toast.type);\n const styleVars: CSSProperties = {\n [\"--toast-bg\" as any]: palette.background,\n [\"--toast-border\" as any]: palette.border,\n [\"--toast-text\" as any]: palette.text,\n [\"--toast-button-bg\" as any]: palette.buttonBg,\n [\"--toast-button-border\" as any]: palette.buttonBorder,\n [\"--toast-action-bg\" as any]: palette.actionBg,\n [\"--toast-action-border\" as any]: palette.actionBorder,\n };\n\n const stopTimer = () => {\n if (timerRef.current) {\n window.clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const triggerDismiss = useCallback(() => {\n setExiting(true);\n stopTimer();\n window.setTimeout(() => onDismiss(toast.id), 160);\n }, [onDismiss, toast.id]);\n\n const schedule = useCallback(\n (delay: number) => {\n if (!delay || delay <= 0) {\n triggerDismiss();\n return;\n }\n startRef.current = performance.now();\n stopTimer();\n timerRef.current = window.setTimeout(() => triggerDismiss(), delay);\n },\n [triggerDismiss],\n );\n\n useEffect(() => {\n if (!toast.duration || toast.duration <= 0) return undefined;\n schedule(toast.duration);\n return stopTimer;\n }, [schedule, toast.duration]);\n\n useEffect(() => {\n if (!toast.duration || toast.duration <= 0) return;\n if (isPaused) {\n const elapsed = performance.now() - startRef.current;\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\n stopTimer();\n } else {\n schedule(remainingRef.current);\n }\n }, [isPaused, schedule, toast.duration]);\n\n const icon = getIcon(toast.type);\n\n return (\n <div className={cx(styles.toast, exiting && styles.exit)} style={styleVars} role=\"status\" aria-live=\"polite\">\n <span className={styles.icon} aria-hidden>\n {icon}\n </span>\n <div className={styles.body}>\n <div className={styles.message}>{toast.message}</div>\n {toast.action && (\n <div className={styles.actions}>\n <button\n type=\"button\"\n className={styles.actionButton}\n onClick={() => {\n toast.action?.onClick();\n triggerDismiss();\n }}\n >\n {toast.action.label}\n </button>\n </div>\n )}\n </div>\n {toast.dismissible !== false && (\n <button\n type=\"button\"\n className={styles.closeButton}\n onClick={triggerDismiss}\n aria-label=\"Dismiss notification\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden>\n <path\n d=\"M11 3L3 11M3 3l8 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n}\n\nfunction getPalette(type: ToastType) {\n switch (type) {\n case \"success\":\n return {\n background: \"#22c55e\",\n border: \"#16a34a\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n case \"error\":\n return {\n background: \"#f87171\",\n border: \"#ef4444\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n case \"warning\":\n return {\n background: \"#fbbf24\",\n border: \"#f59e0b\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n case \"info\":\n default:\n return {\n background: \"#38bdf8\",\n border: \"#0ea5e9\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n }\n}\n\nfunction getIcon(type: ToastType) {\n switch (type) {\n case \"success\":\n return \"OK\";\n case \"error\":\n return \"X\";\n case \"warning\":\n return \"!\";\n case \"info\":\n default:\n return \"i\";\n }\n}\n",".stack {\n position: fixed;\n z-index: 2147483000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n}\n\n.topRight {\n top: 16px;\n right: 16px;\n align-items: flex-end;\n}\n\n.topLeft {\n top: 16px;\n left: 16px;\n align-items: flex-start;\n}\n\n.topCenter {\n top: 16px;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.bottomRight {\n bottom: 16px;\n right: 16px;\n align-items: flex-end;\n}\n\n.bottomLeft {\n bottom: 16px;\n left: 16px;\n align-items: flex-start;\n}\n\n.bottomCenter {\n bottom: 16px;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.toast {\n pointer-events: auto;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 280px;\n max-width: min(420px, calc(100vw - 32px));\n padding: 12px 14px;\n border-radius: 10px;\n border: 1px solid var(--toast-border, #1f2937);\n background: var(--toast-bg, #111827);\n color: var(--toast-text, #e2e8f0);\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\n animation: toastSlideIn 180ms ease-out;\n}\n\n.toast.exit {\n animation: toastSlideOut 160ms ease-in forwards;\n}\n\n.icon {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n}\n\n.body {\n flex: 1;\n min-width: 0;\n display: grid;\n gap: 6px;\n}\n\n.message {\n word-break: break-word;\n font-size: 14px;\n line-height: 1.4;\n}\n\n.actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.actionButton {\n padding: 5px 10px;\n font-size: 12px;\n font-weight: 600;\n border-radius: 6px;\n border: 1px solid var(--toast-action-border, rgba(0, 0, 0, 0.2));\n background: var(--toast-action-bg, rgba(0, 0, 0, 0.1));\n color: var(--toast-text, #e2e8f0);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.actionButton:hover {\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.15));\n}\n\n.closeButton {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n margin: -2px -4px -2px 0;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--toast-text, #e2e8f0);\n opacity: 0.6;\n cursor: pointer;\n transition: opacity 120ms ease, background 120ms ease;\n}\n\n.closeButton:hover {\n opacity: 1;\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.1));\n}\n\n@keyframes toastSlideIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideOut {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(-6px);\n }\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./dropdown.module.css\";\n\nexport interface DropdownOption {\n label: string;\n value: string;\n}\n\nexport interface DropdownProps {\n /** List of options to display in the menu. */\n options: DropdownOption[];\n /** Currently selected value. Use empty string for \"no selection\". */\n value: string;\n /** Called when the user selects an option. */\n onChange: (value: string) => void;\n /** Label shown when no option is selected. Defaults to \"All\". */\n placeholder?: string;\n /** Additional class name for the wrapper element. */\n className?: string;\n /** Whether to show the placeholder as a clearable option. Defaults to true. */\n allowClear?: boolean;\n /** Associates the trigger button with an external label element via its id. */\n \"aria-labelledby\"?: string;\n /** Provides an accessible label directly on the trigger button. */\n \"aria-label\"?: string;\n}\n\nexport function Dropdown({\n options,\n value,\n onChange,\n placeholder = \"All\",\n className,\n allowClear = true,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-label\": ariaLabel,\n}: DropdownProps) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n const selected = options.find((o) => o.value === value);\n const isActive = allowClear && value !== \"\";\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n return (\n <div className={cx(styles.wrapper, className)} ref={ref}>\n <button\n type=\"button\"\n className={cx(styles.trigger, isActive && styles[\"trigger-active\"])}\n onClick={() => setOpen((o) => !o)}\n aria-labelledby={ariaLabelledBy}\n aria-label={ariaLabel}\n >\n {selected ? selected.label : placeholder}\n <span className={cx(styles.chevron, open && styles[\"chevron-open\"])}>\n <svg viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\">\n <path d=\"M2 3.5L5 6.5L8 3.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n </button>\n\n {open && (\n <div className={styles.menu}>\n {allowClear && (\n <button\n type=\"button\"\n className={cx(styles.option, value === \"\" && styles[\"option-selected\"])}\n onClick={() => { onChange(\"\"); setOpen(false); }}\n >\n {placeholder}\n </button>\n )}\n {options.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className={cx(styles.option, value === opt.value && styles[\"option-selected\"])}\n onClick={() => { onChange(opt.value); setOpen(false); }}\n >\n {opt.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n",".wrapper {\n position: relative;\n display: inline-block;\n}\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px 6px 14px;\n background: var(--ts-dropdown-bg, var(--panel, #111827));\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\n border-radius: 8px;\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: border-color 0.15s;\n user-select: none;\n}\n\n.trigger:hover {\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n}\n\n.trigger-active {\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n}\n\n.chevron {\n width: 10px;\n height: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.15s;\n color: var(--muted, #94a3b8);\n flex-shrink: 0;\n}\n\n.chevron-open {\n transform: rotate(180deg);\n}\n\n.menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n min-width: 100%;\n background: var(--ts-dropdown-bg, var(--panel, #111827));\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\n border-radius: 10px;\n padding: 4px;\n z-index: 50;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n animation: dropdownFadeIn 0.1s ease;\n}\n\n@keyframes dropdownFadeIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.option {\n display: block;\n width: 100%;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 0.85rem;\n font-weight: 500;\n color: var(--muted, #94a3b8);\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n white-space: nowrap;\n transition: background 0.1s, color 0.1s;\n}\n\n.option:hover {\n background: rgba(255, 255, 255, 0.05);\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\n}\n\n.option-selected {\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n background: rgba(34, 211, 238, 0.08);\n}\n","\"use client\";\n\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./app-shell.module.css\";\n\nconst DESKTOP_BREAKPOINT = 960;\n\nfunction getIsDesktop() {\n if (typeof window === \"undefined\") return false;\n return window.innerWidth >= DESKTOP_BREAKPOINT;\n}\n\nexport type AppShellProps = {\n /** Primary page content rendered in the main area. */\n children: ReactNode;\n /** Sidebar navigation or custom content. */\n sidebar: ReactNode;\n /** Brand element rendered next to the hamburger (text or JSX). */\n brand?: ReactNode;\n /** Optional brand href; when provided the brand renders as an anchor. */\n brandHref?: string;\n /** Optional content after the brand on the left side of the top bar. */\n topbarStart?: ReactNode;\n /** Optional content aligned to the right side of the top bar. */\n topbarEnd?: ReactNode;\n /** Custom class names for styling overrides. */\n className?: string;\n sidebarClassName?: string;\n topbarClassName?: string;\n mainClassName?: string;\n /** Sets the sidebar width (e.g., `260`, `\"18rem\"`). */\n sidebarWidth?: number | string;\n /**\n * Closes the sidebar on mobile whenever this value changes.\n * Useful for reacting to route/pathname changes.\n */\n closeSidebarOnChangeKey?: unknown;\n /** Label for the hamburger button (aria-label). */\n hamburgerLabel?: string;\n /** Optional callback fired whenever the sidebar open state changes. */\n onSidebarToggle?: (open: boolean) => void;\n};\n\n/**\n * Responsive application shell with a collapsible sidebar and sticky top bar.\n *\n * - Sidebar opens by default on desktop, collapses on mobile.\n * - Closes on outside click/scroll/touch when in mobile mode.\n * - Provides optional hook to close the sidebar when a prop value changes\n * (e.g., route transitions).\n */\nexport function AppShell({\n children,\n sidebar,\n brand,\n brandHref,\n topbarStart,\n topbarEnd,\n className,\n sidebarClassName,\n topbarClassName,\n mainClassName,\n sidebarWidth,\n closeSidebarOnChangeKey,\n hamburgerLabel = \"Toggle navigation\",\n onSidebarToggle,\n}: AppShellProps) {\n const [isDesktop, setIsDesktop] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const prevIsDesktopRef = useRef(false);\n const closeKeyRef = useRef(closeSidebarOnChangeKey);\n\n const sidebarRef = useRef<HTMLElement | null>(null);\n const hamburgerRef = useRef<HTMLButtonElement | null>(null);\n const mainRef = useRef<HTMLElement | null>(null);\n const sidebarId = useId();\n\n useEffect(() => {\n const desktop = getIsDesktop();\n setIsDesktop(desktop);\n setSidebarOpen(desktop);\n prevIsDesktopRef.current = desktop;\n\n const handleResize = () => {\n const nowDesktop = getIsDesktop();\n setIsDesktop(nowDesktop);\n if (nowDesktop !== prevIsDesktopRef.current) {\n setSidebarOpen(nowDesktop);\n prevIsDesktopRef.current = nowDesktop;\n }\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n // Close the sidebar when clicking outside or scrolling on mobile.\n useEffect(() => {\n if (isDesktop || !sidebarOpen) return;\n\n const mainElement = mainRef.current;\n const closeSidebar = () => setSidebarOpen(false);\n\n const onPointerDown = (e: PointerEvent) => {\n const target = e.target as Node | null;\n if (!target) return;\n if (sidebarRef.current?.contains(target)) return;\n if (hamburgerRef.current?.contains(target)) return;\n closeSidebar();\n };\n\n const timeoutId = window.setTimeout(() => {\n document.addEventListener(\"pointerdown\", onPointerDown);\n window.addEventListener(\"scroll\", closeSidebar, { passive: true });\n mainElement?.addEventListener(\"scroll\", closeSidebar, { passive: true });\n document.addEventListener(\"touchmove\", closeSidebar, { passive: true });\n }, 10);\n\n return () => {\n window.clearTimeout(timeoutId);\n document.removeEventListener(\"pointerdown\", onPointerDown);\n window.removeEventListener(\"scroll\", closeSidebar);\n mainElement?.removeEventListener(\"scroll\", closeSidebar);\n document.removeEventListener(\"touchmove\", closeSidebar);\n };\n }, [sidebarOpen, isDesktop]);\n\n // Allow consumers to request a mobile sidebar close when a value changes (e.g., pathname).\n useEffect(() => {\n if (!isDesktop && closeKeyRef.current !== closeSidebarOnChangeKey) {\n setSidebarOpen(false);\n }\n closeKeyRef.current = closeSidebarOnChangeKey;\n }, [closeSidebarOnChangeKey, isDesktop]);\n\n useEffect(() => {\n onSidebarToggle?.(sidebarOpen);\n }, [sidebarOpen, onSidebarToggle]);\n\n const toggleSidebar = () => setSidebarOpen((open) => !open);\n\n const sidebarWidthValue =\n sidebarWidth === undefined\n ? undefined\n : typeof sidebarWidth === \"number\"\n ? `${sidebarWidth}px`\n : sidebarWidth;\n\n const shellStyle: CSSProperties | undefined = sidebarWidthValue\n ? { [\"--app-shell-sidebar-width\" as string]: sidebarWidthValue }\n : undefined;\n\n const shellClasses = cx(\n styles.shell,\n sidebarOpen ? styles.sidebarOpen : styles.sidebarCollapsed,\n className,\n );\n\n const sidebarClasses = cx(styles.sidebar, sidebarOpen && styles.open, sidebarClassName);\n\n return (\n <div\n className={shellClasses}\n style={shellStyle}\n data-app-shell\n data-desktop={isDesktop ? \"true\" : \"false\"}\n data-sidebar-open={sidebarOpen ? \"true\" : \"false\"}\n >\n <header className={cx(styles.topbar, topbarClassName)}>\n <div className={styles.topbarLeft}>\n <button\n ref={hamburgerRef}\n type=\"button\"\n className={styles.hamburger}\n onClick={toggleSidebar}\n aria-label={hamburgerLabel}\n aria-expanded={sidebarOpen}\n aria-controls={sidebarId}\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n </button>\n {brand &&\n (brandHref ? (\n <a className={styles.brand} href={brandHref}>\n {brand}\n </a>\n ) : (\n <div className={styles.brand}>{brand}</div>\n ))}\n {topbarStart && <div className={styles.topbarStart}>{topbarStart}</div>}\n </div>\n <div className={styles.topbarRight}>{topbarEnd}</div>\n </header>\n {!isDesktop && sidebarOpen && (\n <div className={styles.backdrop} onClick={() => setSidebarOpen(false)} onTouchStart={() => setSidebarOpen(false)} aria-hidden=\"true\" />\n )}\n <aside ref={sidebarRef} id={sidebarId} className={sidebarClasses} aria-label=\"Sidebar navigation\">\n {sidebar}\n </aside>\n <main ref={mainRef} className={cx(styles.main, mainClassName)}>\n {children}\n </main>\n </div>\n );\n}\n",".shell {\n display: grid;\n grid-template-rows: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top)) 1fr;\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\n min-height: 100vh;\n min-height: 100dvh;\n transition: grid-template-columns 200ms ease;\n}\n\n.shell.sidebarOpen {\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\n}\n\n.shell.sidebarCollapsed {\n grid-template-columns: 0 1fr;\n}\n\n.topbar {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top));\n padding: env(safe-area-inset-top) 16px 0 16px;\n border-bottom: 1px solid var(--border);\n background: rgba(17, 24, 39, 0.8);\n backdrop-filter: blur(8px);\n position: sticky;\n top: 0;\n z-index: 20;\n gap: 12px;\n}\n\n.topbarLeft {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.topbarStart {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n\n.topbarRight {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 0;\n}\n\n.topbarRight > * {\n min-width: 0;\n}\n\n.brand {\n font-size: 26px;\n color: var(--text);\n text-decoration: none;\n display: flex;\n align-items: center;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.hamburger {\n background: transparent;\n border: none;\n padding: 0;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.hamburger:hover {\n background: rgba(255, 255, 255, 0.06);\n}\n\n.hamburger:focus,\n.hamburger:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.hamburger svg {\n width: 28px;\n height: 28px;\n}\n\n.sidebar {\n border-right: 1px solid var(--border);\n background: #152036;\n padding: 24px;\n transition: transform 200ms ease, opacity 200ms ease;\n}\n\n.shell.sidebarCollapsed .sidebar {\n transform: translateX(-110%);\n opacity: 0;\n pointer-events: none;\n}\n\n.main {\n overflow-y: auto;\n padding: 24px;\n padding-bottom: 96px;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 16px;\n align-items: center;\n}\n\n.main > * {\n width: 100%;\n max-width: 1200px;\n min-width: 0;\n}\n\n.backdrop {\n display: none;\n}\n\n@media (max-width: 960px) {\n .backdrop {\n display: block;\n position: fixed;\n inset: 0;\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\n background: rgba(0, 0, 0, 0.5);\n z-index: 14;\n }\n\n .shell {\n --app-shell-topbar-height: 56px;\n grid-template-columns: 1fr;\n grid-template-rows: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top)) 1fr;\n }\n\n .shell.sidebarOpen,\n .shell.sidebarCollapsed {\n grid-template-columns: 1fr;\n }\n\n .sidebar {\n display: block;\n position: fixed;\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\n left: 0;\n bottom: 0;\n width: var(--app-shell-sidebar-width, 240px);\n max-width: 80vw;\n background: #152036;\n padding: 16px 12px;\n transform: translateX(-105%);\n z-index: 15;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);\n }\n\n .sidebar.open {\n transform: translateX(0);\n }\n\n .topbar {\n padding-left: max(12px, env(safe-area-inset-left));\n padding-right: max(12px, env(safe-area-inset-right));\n gap: 10px;\n }\n\n .topbarLeft {\n gap: 10px;\n flex: 1;\n }\n\n .topbarStart {\n min-width: 0;\n }\n\n .topbarRight {\n gap: 6px;\n }\n\n .brand {\n font-size: 24px;\n max-width: 50vw;\n }\n\n .hamburger {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n }\n\n .hamburger svg {\n width: 24px;\n height: 24px;\n }\n\n .main {\n padding: 16px;\n padding-bottom: 96px;\n }\n}\n\n@media (max-width: 640px) {\n .topbar {\n gap: 8px;\n }\n\n .brand {\n font-size: 22px;\n max-width: 34vw;\n }\n\n .topbarRight {\n max-width: 44vw;\n }\n\n .main {\n padding: 12px 10px;\n padding-bottom: 88px;\n }\n}\n\n@media (max-width: 480px) {\n .brand {\n font-size: 20px;\n max-width: 30vw;\n }\n}\n",".nav {\n display: flex;\n flex-direction: column;\n gap: 8px;\n align-items: stretch;\n}\n\n.item {\n color: var(--text, #e2e8f0);\n background: transparent;\n border: none;\n box-shadow: none;\n padding: 10px 12px 10px 10px;\n border-radius: 10px;\n text-decoration: none;\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n justify-content: flex-start;\n text-align: left;\n box-sizing: border-box;\n white-space: nowrap;\n line-height: 1.2;\n transition: background 120ms ease, color 120ms ease;\n}\n\n.item:focus,\n.item:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.item:hover {\n background: rgba(29, 43, 70, 0.55);\n}\n\n.item.active {\n background: rgba(29, 43, 70, 0.85);\n color: var(--text, #e2e8f0);\n font-weight: 700;\n}\n\n.icon {\n width: 18px;\n height: 18px;\n color: var(--muted, #94a3b8);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 18px;\n vertical-align: middle;\n}\n\n.icon svg {\n width: 18px;\n height: 18px;\n display: block;\n stroke: currentColor;\n}\n\n.item.active .icon {\n color: var(--accent, #22d3ee);\n}\n\n.label {\n flex: 1;\n min-width: 0;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 999px;\n border: 1px solid var(--border, #1f2937);\n background: rgba(255, 255, 255, 0.04);\n color: var(--muted, #94a3b8);\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n@media (max-width: 960px) {\n .nav {\n gap: 6px;\n }\n\n .item {\n padding: 9px 10px 9px 8px;\n border-radius: 9px;\n font-size: 14px;\n gap: 6px;\n }\n\n .icon {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n }\n\n .icon svg {\n width: 16px;\n height: 16px;\n }\n}\n\n@media (max-width: 480px) {\n .item {\n padding: 8px 9px 8px 7px;\n font-size: 13px;\n }\n}\n","\"use client\";\n\nimport { type AnchorHTMLAttributes, type ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./sidebar-nav.module.css\";\n\nexport type SidebarNavItem = {\n label: string;\n href: string;\n icon?: ReactNode;\n badge?: ReactNode;\n active?: boolean;\n target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\n rel?: AnchorHTMLAttributes<HTMLAnchorElement>[\"rel\"];\n onClick?: () => void;\n};\n\nexport type SidebarNavProps = {\n items: SidebarNavItem[];\n /** Optional path-like value used for default active matching. */\n currentPath?: string;\n /**\n * Custom active matcher. Defaults to prefix matching (with a special case for `/`).\n * If `item.active` is provided, it wins over this function.\n */\n getIsActive?: (item: SidebarNavItem, currentPath?: string) => boolean;\n /** Called after the item click handler (if provided). */\n onItemClick?: (item: SidebarNavItem) => void;\n className?: string;\n itemClassName?: string;\n};\n\nconst defaultIsActive = (item: SidebarNavItem, path?: string) => {\n if (item.active !== undefined) return item.active;\n if (!path) return false;\n if (item.href === \"/\") return path === \"/\";\n return path.startsWith(item.href);\n};\n\nexport function SidebarNav({\n items,\n currentPath,\n getIsActive = defaultIsActive,\n onItemClick,\n className,\n itemClassName,\n}: SidebarNavProps) {\n return (\n <nav className={cx(styles.nav, className)} aria-label=\"Sidebar navigation\">\n {items.map((item) => {\n const active = getIsActive(item, currentPath);\n const rel = item.rel ?? (item.target === \"_blank\" ? \"noreferrer\" : undefined);\n\n return (\n <a\n key={item.href}\n className={cx(styles.item, active && styles.active, itemClassName)}\n href={item.href}\n target={item.target}\n rel={rel}\n aria-current={active ? \"page\" : undefined}\n onClick={() => {\n item.onClick?.();\n onItemClick?.(item);\n }}\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n <span className={styles.label}>{item.label}</span>\n {item.badge && <span className={styles.badge}>{item.badge}</span>}\n </a>\n );\n })}\n </nav>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime"]}
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/button/button.module.css","../src/components/card/card.module.css","../src/components/pill/pill.module.css","../src/components/modal/modal.module.css","../src/components/toast/toast.module.css","../src/components/dropdown/dropdown.module.css","../src/components/app-shell/app-shell.module.css","../src/components/sidebar-nav/sidebar-nav.module.css"],"sourcesContent":[".button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n font-family: inherit;\r\n font-weight: 600;\r\n border-radius: 8px;\r\n border: none;\r\n cursor: pointer;\r\n text-decoration: none;\r\n transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s;\r\n white-space: nowrap;\r\n}\r\n\r\n.button:disabled {\r\n opacity: 0.45;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* Sizes */\r\n.size-sm {\r\n font-size: 0.82rem;\r\n padding: 6px 14px;\r\n}\r\n\r\n.size-md {\r\n font-size: 0.95rem;\r\n padding: 10px 22px;\r\n}\r\n\r\n.size-lg {\r\n font-size: 1rem;\r\n padding: 12px 28px;\r\n}\r\n\r\n/* Variants */\r\n.variant-primary {\r\n background: var(--ts-btn-primary-bg, var(--accent, #22d3ee));\r\n color: var(--ts-btn-primary-text, #0f172a);\r\n border: 1px solid transparent;\r\n}\r\n\r\n.variant-primary:hover:not(:disabled) {\r\n opacity: 0.88;\r\n}\r\n\r\n.variant-secondary {\r\n background: var(--ts-btn-secondary-bg, rgba(255, 255, 255, 0.06));\r\n color: var(--ts-btn-secondary-text, var(--text, #e2e8f0));\r\n border: 1px solid var(--ts-btn-secondary-border, var(--border, #1f2937));\r\n}\r\n\r\n.variant-secondary:hover:not(:disabled) {\r\n background: var(--ts-btn-secondary-hover-bg, rgba(255, 255, 255, 0.1));\r\n}\r\n\r\n.variant-outline {\r\n background: transparent;\r\n color: var(--ts-btn-outline-text, var(--text, #e2e8f0));\r\n border: 1px solid var(--ts-btn-outline-border, var(--border, #1f2937));\r\n}\r\n\r\n.variant-outline:hover:not(:disabled) {\r\n border-color: var(--ts-btn-outline-hover-border, var(--accent, #22d3ee));\r\n color: var(--ts-btn-outline-hover-text, var(--accent, #22d3ee));\r\n}\r\n\r\n.variant-ghost {\r\n background: transparent;\r\n color: var(--ts-btn-ghost-text, var(--muted, #94a3b8));\r\n border: 1px solid transparent;\r\n padding-left: 8px;\r\n padding-right: 8px;\r\n}\r\n\r\n.variant-ghost:hover:not(:disabled) {\r\n background: rgba(255, 255, 255, 0.05);\r\n color: var(--text, #e2e8f0);\r\n}\r\n",".card {\r\n position: relative;\r\n overflow: visible;\r\n border-radius: var(--ts-card-radius, 12px);\r\n border: 1px solid var(--ts-card-border, var(--border, #1f2937));\r\n background: var(--ts-card-bg, var(--panel, #111827));\r\n color: var(--ts-card-fg, var(--text, #e2e8f0));\r\n box-shadow: var(--ts-card-shadow, 0 16px 36px rgba(0, 0, 0, 0.28));\r\n padding: var(--ts-card-padding, 16px);\r\n transition:\r\n transform 140ms ease,\r\n box-shadow 140ms ease,\r\n border-color 140ms ease,\r\n background-color 140ms ease;\r\n}\r\n\r\n.tone-default {\r\n --ts-card-bg: var(--panel, #111827);\r\n --ts-card-border: var(--border, #1f2937);\r\n --ts-card-shadow: 0 16px 36px rgba(0, 0, 0, 0.28);\r\n}\r\n\r\n.tone-muted {\r\n --ts-card-bg: var(--ts-card-muted-bg, rgba(255, 255, 255, 0.02));\r\n --ts-card-border: var(--ts-card-muted-border, rgba(255, 255, 255, 0.06));\r\n --ts-card-shadow: 0 10px 26px rgba(0, 0, 0, 0.22);\r\n}\r\n\r\n.tone-contrast {\r\n --ts-card-bg: var(--ts-card-contrast-bg, #0b1224);\r\n --ts-card-border: var(--ts-card-contrast-border, rgba(255, 255, 255, 0.1));\r\n --ts-card-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);\r\n}\r\n\r\n.interactive {\r\n cursor: default;\r\n}\r\n\r\n.interactive:hover {\r\n transform: translateY(-1px);\r\n box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);\r\n border-color: var(--ts-card-hover-border, rgba(34, 211, 238, 0.4));\r\n}\r\n\r\n.interactive:focus-within {\r\n outline: 2px solid var(--ts-card-hover-border, rgba(34, 211, 238, 0.45));\r\n outline-offset: 2px;\r\n}\r\n\r\n.padding-none {\r\n --ts-card-padding: 0;\r\n}\r\n\r\n.padding-sm {\r\n --ts-card-padding: 10px;\r\n}\r\n\r\n.padding-md {\r\n --ts-card-padding: 16px;\r\n}\r\n\r\n.padding-lg {\r\n --ts-card-padding: 20px;\r\n}\r\n",".pill {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 4px 10px;\r\n border-radius: 999px;\r\n border: 1px solid var(--ts-pill-border, var(--border, #1f2937));\r\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\r\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\r\n font-size: 12px;\r\n font-weight: 700;\r\n letter-spacing: 0.05em;\r\n text-transform: uppercase;\r\n line-height: 1.2;\r\n white-space: nowrap;\r\n}\r\n\r\n.size-sm {\r\n padding: 3px 8px;\r\n font-size: 11px;\r\n}\r\n\r\n.size-md {\r\n padding: 4px 10px;\r\n}\r\n\r\n.tone-neutral {\r\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\r\n border-color: var(--ts-pill-border, var(--border, #1f2937));\r\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\r\n}\r\n\r\n.tone-success {\r\n color: #22c55e;\r\n border-color: rgba(34, 197, 94, 0.45);\r\n background: rgba(34, 197, 94, 0.12);\r\n}\r\n\r\n.tone-warning {\r\n color: #f59e0b;\r\n border-color: rgba(245, 158, 11, 0.45);\r\n background: rgba(245, 158, 11, 0.12);\r\n}\r\n\r\n.tone-info {\r\n color: #22d3ee;\r\n border-color: rgba(34, 211, 238, 0.5);\r\n background: rgba(34, 211, 238, 0.12);\r\n}\r\n\r\n.tone-danger {\r\n color: #f87171;\r\n border-color: rgba(248, 113, 113, 0.45);\r\n background: rgba(248, 113, 113, 0.12);\r\n}\r\n\r\n.icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 12px;\r\n height: 12px;\r\n}\r\n\r\n.content {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n}\r\n",".backdrop {\r\n position: fixed;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.55);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 16px;\r\n z-index: 100;\r\n}\r\n\r\n.modal {\r\n background: #0f172a;\r\n border: 1px solid var(--border, #1f2937);\r\n border-radius: 14px;\r\n padding: 24px;\r\n width: min(500px, 100%);\r\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0;\r\n}\r\n\r\n/* Size variants */\r\n.size-sm { width: min(380px, 100%); }\r\n.size-md { width: min(500px, 100%); }\r\n.size-lg { width: min(640px, 100%); }\r\n\r\n.header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 12px;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.titles {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 3px;\r\n}\r\n\r\n.title {\r\n font-weight: 700;\r\n font-size: 16px;\r\n color: var(--text, #e2e8f0);\r\n line-height: 1.3;\r\n}\r\n\r\n.subtitle {\r\n font-size: 13px;\r\n color: var(--muted, #94a3b8);\r\n line-height: 1.4;\r\n}\r\n\r\n.closeButton {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n flex-shrink: 0;\r\n background: transparent;\r\n border: 1px solid transparent;\r\n border-radius: 6px;\r\n color: var(--muted, #94a3b8);\r\n cursor: pointer;\r\n transition: background 0.12s, color 0.12s;\r\n padding: 0;\r\n}\r\n\r\n.closeButton:hover {\r\n background: rgba(255, 255, 255, 0.07);\r\n color: var(--text, #e2e8f0);\r\n}\r\n\r\n.body {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n}\r\n\r\n.footer {\r\n display: flex;\r\n gap: 8px;\r\n margin-top: 20px;\r\n}\r\n",".stack {\r\n position: fixed;\r\n z-index: 2147483000;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n pointer-events: none;\r\n}\r\n\r\n.topRight {\r\n top: 16px;\r\n right: 16px;\r\n align-items: flex-end;\r\n}\r\n\r\n.topLeft {\r\n top: 16px;\r\n left: 16px;\r\n align-items: flex-start;\r\n}\r\n\r\n.topCenter {\r\n top: 16px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n align-items: center;\r\n}\r\n\r\n.bottomRight {\r\n bottom: 16px;\r\n right: 16px;\r\n align-items: flex-end;\r\n}\r\n\r\n.bottomLeft {\r\n bottom: 16px;\r\n left: 16px;\r\n align-items: flex-start;\r\n}\r\n\r\n.bottomCenter {\r\n bottom: 16px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n align-items: center;\r\n}\r\n\r\n.toast {\r\n pointer-events: auto;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 10px;\r\n min-width: 280px;\r\n max-width: min(420px, calc(100vw - 32px));\r\n padding: 12px 14px;\r\n border-radius: 10px;\r\n border: 1px solid var(--toast-border, #1f2937);\r\n background: var(--toast-bg, #111827);\r\n color: var(--toast-text, #e2e8f0);\r\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\r\n animation: toastSlideIn 180ms ease-out;\r\n}\r\n\r\n.toast.exit {\r\n animation: toastSlideOut 160ms ease-in forwards;\r\n}\r\n\r\n.icon {\r\n width: 18px;\r\n height: 18px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.body {\r\n flex: 1;\r\n min-width: 0;\r\n display: grid;\r\n gap: 6px;\r\n}\r\n\r\n.message {\r\n word-break: break-word;\r\n font-size: 14px;\r\n line-height: 1.4;\r\n}\r\n\r\n.actions {\r\n display: flex;\r\n gap: 6px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.actionButton {\r\n padding: 5px 10px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n border-radius: 6px;\r\n border: 1px solid var(--toast-action-border, rgba(0, 0, 0, 0.2));\r\n background: var(--toast-action-bg, rgba(0, 0, 0, 0.1));\r\n color: var(--toast-text, #e2e8f0);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.actionButton:hover {\r\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.15));\r\n}\r\n\r\n.closeButton {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 20px;\r\n height: 20px;\r\n padding: 0;\r\n margin: -2px -4px -2px 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: var(--toast-text, #e2e8f0);\r\n opacity: 0.6;\r\n cursor: pointer;\r\n transition: opacity 120ms ease, background 120ms ease;\r\n}\r\n\r\n.closeButton:hover {\r\n opacity: 1;\r\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.1));\r\n}\r\n\r\n@keyframes toastSlideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-8px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n@keyframes toastSlideOut {\r\n from {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n to {\r\n opacity: 0;\r\n transform: translateY(-6px);\r\n }\r\n}\r\n",".wrapper {\r\n position: relative;\r\n display: inline-block;\r\n}\r\n\r\n.trigger {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 6px 10px 6px 14px;\r\n background: var(--ts-dropdown-bg, var(--panel, #111827));\r\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\r\n border-radius: 8px;\r\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\r\n font-size: 0.85rem;\r\n font-weight: 500;\r\n cursor: pointer;\r\n white-space: nowrap;\r\n transition: border-color 0.15s;\r\n user-select: none;\r\n}\r\n\r\n.trigger:hover {\r\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n}\r\n\r\n.trigger-active {\r\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n}\r\n\r\n.chevron {\r\n width: 10px;\r\n height: 10px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: transform 0.15s;\r\n color: var(--muted, #94a3b8);\r\n flex-shrink: 0;\r\n}\r\n\r\n.chevron-open {\r\n transform: rotate(180deg);\r\n}\r\n\r\n.menu {\r\n position: absolute;\r\n top: calc(100% + 6px);\r\n left: 0;\r\n min-width: 100%;\r\n background: var(--ts-dropdown-bg, var(--panel, #111827));\r\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\r\n border-radius: 10px;\r\n padding: 4px;\r\n z-index: 50;\r\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\r\n animation: dropdownFadeIn 0.1s ease;\r\n}\r\n\r\n@keyframes dropdownFadeIn {\r\n from { opacity: 0; transform: translateY(-4px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n.option {\r\n display: block;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n font-size: 0.85rem;\r\n font-weight: 500;\r\n color: var(--muted, #94a3b8);\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n text-align: left;\r\n white-space: nowrap;\r\n transition: background 0.1s, color 0.1s;\r\n}\r\n\r\n.option:hover {\r\n background: rgba(255, 255, 255, 0.05);\r\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\r\n}\r\n\r\n.option-selected {\r\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n background: rgba(34, 211, 238, 0.08);\r\n}\r\n",".shell {\r\n display: grid;\r\n grid-template-rows: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top)) 1fr;\r\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\r\n min-height: 100vh;\r\n min-height: 100dvh;\r\n transition: grid-template-columns 200ms ease;\r\n}\r\n\r\n.shell.sidebarOpen {\r\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\r\n}\r\n\r\n.shell.sidebarCollapsed {\r\n grid-template-columns: 0 1fr;\r\n}\r\n\r\n.topbar {\r\n grid-column: 1 / -1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top));\r\n padding: env(safe-area-inset-top) 16px 0 16px;\r\n border-bottom: 1px solid var(--border);\r\n background: rgba(17, 24, 39, 0.8);\r\n backdrop-filter: blur(8px);\r\n position: sticky;\r\n top: 0;\r\n z-index: 20;\r\n gap: 12px;\r\n}\r\n\r\n.topbarLeft {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.topbarStart {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.topbarRight {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n min-width: 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.topbarRight > * {\r\n min-width: 0;\r\n}\r\n\r\n.brand {\r\n font-size: 26px;\r\n color: var(--text);\r\n text-decoration: none;\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.hamburger {\r\n background: transparent;\r\n border: none;\r\n padding: 0;\r\n width: 40px;\r\n height: 40px;\r\n border-radius: 8px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--text);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.hamburger:hover {\r\n background: rgba(255, 255, 255, 0.06);\r\n}\r\n\r\n.hamburger:focus,\r\n.hamburger:focus-visible {\r\n outline: none;\r\n box-shadow: none;\r\n}\r\n\r\n.hamburger svg {\r\n width: 28px;\r\n height: 28px;\r\n}\r\n\r\n.sidebar {\r\n border-right: 1px solid var(--border);\r\n background: #152036;\r\n padding: 24px;\r\n transition: transform 200ms ease, opacity 200ms ease;\r\n}\r\n\r\n.shell.sidebarCollapsed .sidebar {\r\n transform: translateX(-110%);\r\n opacity: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.main {\r\n overflow-y: auto;\r\n padding: 24px;\r\n padding-bottom: 96px;\r\n min-height: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n align-items: center;\r\n}\r\n\r\n.main > * {\r\n width: 100%;\r\n max-width: 1200px;\r\n min-width: 0;\r\n}\r\n\r\n.backdrop {\r\n display: none;\r\n}\r\n\r\n@media (max-width: 960px) {\r\n .backdrop {\r\n display: block;\r\n position: fixed;\r\n inset: 0;\r\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\r\n background: rgba(0, 0, 0, 0.5);\r\n z-index: 14;\r\n }\r\n\r\n .shell {\r\n --app-shell-topbar-height: 56px;\r\n grid-template-columns: 1fr;\r\n grid-template-rows: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top)) 1fr;\r\n }\r\n\r\n .shell.sidebarOpen,\r\n .shell.sidebarCollapsed {\r\n grid-template-columns: 1fr;\r\n }\r\n\r\n .sidebar {\r\n display: block;\r\n position: fixed;\r\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\r\n left: 0;\r\n bottom: 0;\r\n width: var(--app-shell-sidebar-width, 240px);\r\n max-width: 80vw;\r\n background: #152036;\r\n padding: 16px 12px;\r\n transform: translateX(-105%);\r\n z-index: 15;\r\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);\r\n }\r\n\r\n .sidebar.open {\r\n transform: translateX(0);\r\n }\r\n\r\n .topbar {\r\n padding-left: max(12px, env(safe-area-inset-left));\r\n padding-right: max(12px, env(safe-area-inset-right));\r\n gap: 10px;\r\n }\r\n\r\n .topbarLeft {\r\n gap: 10px;\r\n flex: 1;\r\n }\r\n\r\n .topbarStart {\r\n min-width: 0;\r\n }\r\n\r\n .topbarRight {\r\n gap: 6px;\r\n }\r\n\r\n .brand {\r\n font-size: 24px;\r\n max-width: 50vw;\r\n }\r\n\r\n .hamburger {\r\n width: 40px;\r\n height: 40px;\r\n border-radius: 8px;\r\n }\r\n\r\n .hamburger svg {\r\n width: 24px;\r\n height: 24px;\r\n }\r\n\r\n .main {\r\n padding: 16px;\r\n padding-bottom: 96px;\r\n }\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .topbar {\r\n gap: 8px;\r\n }\r\n\r\n .brand {\r\n font-size: 22px;\r\n max-width: 34vw;\r\n }\r\n\r\n .topbarRight {\r\n max-width: 44vw;\r\n }\r\n\r\n .main {\r\n padding: 12px 10px;\r\n padding-bottom: 88px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .brand {\r\n font-size: 20px;\r\n max-width: 30vw;\r\n }\r\n}\r\n",".nav {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n align-items: stretch;\r\n}\r\n\r\n.item {\r\n color: var(--text, #e2e8f0);\r\n background: transparent;\r\n border: none;\r\n box-shadow: none;\r\n padding: 10px 12px 10px 10px;\r\n border-radius: 10px;\r\n text-decoration: none;\r\n font-size: 14px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n width: 100%;\r\n justify-content: flex-start;\r\n text-align: left;\r\n box-sizing: border-box;\r\n white-space: nowrap;\r\n line-height: 1.2;\r\n transition: background 120ms ease, color 120ms ease;\r\n}\r\n\r\n.item:focus,\r\n.item:focus-visible {\r\n outline: none;\r\n box-shadow: none;\r\n}\r\n\r\n.item:hover {\r\n background: rgba(29, 43, 70, 0.55);\r\n}\r\n\r\n.item.active {\r\n background: rgba(29, 43, 70, 0.85);\r\n color: var(--text, #e2e8f0);\r\n font-weight: 700;\r\n}\r\n\r\n.icon {\r\n width: 18px;\r\n height: 18px;\r\n color: var(--muted, #94a3b8);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: 0 0 18px;\r\n vertical-align: middle;\r\n}\r\n\r\n.icon svg {\r\n width: 18px;\r\n height: 18px;\r\n display: block;\r\n stroke: currentColor;\r\n}\r\n\r\n.item.active .icon {\r\n color: var(--accent, #22d3ee);\r\n}\r\n\r\n.label {\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.badge {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n padding: 4px 8px;\r\n border-radius: 999px;\r\n border: 1px solid var(--border, #1f2937);\r\n background: rgba(255, 255, 255, 0.04);\r\n color: var(--muted, #94a3b8);\r\n font-size: 11px;\r\n letter-spacing: 0.04em;\r\n text-transform: uppercase;\r\n}\r\n\r\n@media (max-width: 960px) {\r\n .nav {\r\n gap: 6px;\r\n }\r\n\r\n .item {\r\n padding: 9px 10px 9px 8px;\r\n border-radius: 9px;\r\n font-size: 14px;\r\n gap: 6px;\r\n }\r\n\r\n .icon {\r\n width: 16px;\r\n height: 16px;\r\n flex: 0 0 16px;\r\n }\r\n\r\n .icon svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .item {\r\n padding: 8px 9px 8px 7px;\r\n font-size: 13px;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/components/button/button.module.css","../src/components/card/card.module.css","../src/components/pill/pill.module.css","../src/components/modal/modal.module.css","../src/components/toast/toast.module.css","../src/components/dropdown/dropdown.module.css","../src/components/app-shell/app-shell.module.css","../src/components/sidebar-nav/sidebar-nav.module.css"],"sourcesContent":[".button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font-family: inherit;\n font-weight: 600;\n border-radius: 8px;\n border: none;\n cursor: pointer;\n text-decoration: none;\n transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s;\n white-space: nowrap;\n}\n\n.button:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Sizes */\n.size-sm {\n font-size: 0.82rem;\n padding: 6px 14px;\n}\n\n.size-md {\n font-size: 0.95rem;\n padding: 10px 22px;\n}\n\n.size-lg {\n font-size: 1rem;\n padding: 12px 28px;\n}\n\n/* Variants */\n.variant-primary {\n background: var(--ts-btn-primary-bg, var(--accent, #22d3ee));\n color: var(--ts-btn-primary-text, #0f172a);\n border: 1px solid transparent;\n}\n\n.variant-primary:hover:not(:disabled) {\n opacity: 0.88;\n}\n\n.variant-secondary {\n background: var(--ts-btn-secondary-bg, rgba(255, 255, 255, 0.06));\n color: var(--ts-btn-secondary-text, var(--text, #e2e8f0));\n border: 1px solid var(--ts-btn-secondary-border, var(--border, #1f2937));\n}\n\n.variant-secondary:hover:not(:disabled) {\n background: var(--ts-btn-secondary-hover-bg, rgba(255, 255, 255, 0.1));\n}\n\n.variant-outline {\n background: transparent;\n color: var(--ts-btn-outline-text, var(--text, #e2e8f0));\n border: 1px solid var(--ts-btn-outline-border, var(--border, #1f2937));\n}\n\n.variant-outline:hover:not(:disabled) {\n border-color: var(--ts-btn-outline-hover-border, var(--accent, #22d3ee));\n color: var(--ts-btn-outline-hover-text, var(--accent, #22d3ee));\n}\n\n.variant-ghost {\n background: transparent;\n color: var(--ts-btn-ghost-text, var(--muted, #94a3b8));\n border: 1px solid transparent;\n padding-left: 8px;\n padding-right: 8px;\n}\n\n.variant-ghost:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.05);\n color: var(--text, #e2e8f0);\n}\n",".card {\n position: relative;\n overflow: visible;\n border-radius: var(--ts-card-radius, 12px);\n border: 1px solid var(--ts-card-border, var(--border, #1f2937));\n background: var(--ts-card-bg, var(--panel, #111827));\n color: var(--ts-card-fg, var(--text, #e2e8f0));\n box-shadow: var(--ts-card-shadow, 0 16px 36px rgba(0, 0, 0, 0.28));\n padding: var(--ts-card-padding, 16px);\n transition:\n transform 140ms ease,\n box-shadow 140ms ease,\n border-color 140ms ease,\n background-color 140ms ease;\n}\n\n.tone-default {\n --ts-card-bg: var(--panel, #111827);\n --ts-card-border: var(--border, #1f2937);\n --ts-card-shadow: 0 16px 36px rgba(0, 0, 0, 0.28);\n}\n\n.tone-muted {\n --ts-card-bg: var(--ts-card-muted-bg, rgba(255, 255, 255, 0.02));\n --ts-card-border: var(--ts-card-muted-border, rgba(255, 255, 255, 0.06));\n --ts-card-shadow: 0 10px 26px rgba(0, 0, 0, 0.22);\n}\n\n.tone-contrast {\n --ts-card-bg: var(--ts-card-contrast-bg, #0b1224);\n --ts-card-border: var(--ts-card-contrast-border, rgba(255, 255, 255, 0.1));\n --ts-card-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);\n}\n\n.interactive {\n cursor: default;\n}\n\n.interactive:hover {\n transform: translateY(-1px);\n box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);\n border-color: var(--ts-card-hover-border, rgba(34, 211, 238, 0.4));\n}\n\n.interactive:focus-within {\n outline: 2px solid var(--ts-card-hover-border, rgba(34, 211, 238, 0.45));\n outline-offset: 2px;\n}\n\n.padding-none {\n --ts-card-padding: 0;\n}\n\n.padding-sm {\n --ts-card-padding: 10px;\n}\n\n.padding-md {\n --ts-card-padding: 16px;\n}\n\n.padding-lg {\n --ts-card-padding: 20px;\n}\n",".pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n border: 1px solid var(--ts-pill-border, var(--border, #1f2937));\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n line-height: 1.2;\n white-space: nowrap;\n}\n\n.size-sm {\n padding: 3px 8px;\n font-size: 11px;\n}\n\n.size-md {\n padding: 4px 10px;\n}\n\n.tone-neutral {\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\n border-color: var(--ts-pill-border, var(--border, #1f2937));\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\n}\n\n.tone-success {\n color: #22c55e;\n border-color: rgba(34, 197, 94, 0.45);\n background: rgba(34, 197, 94, 0.12);\n}\n\n.tone-warning {\n color: #f59e0b;\n border-color: rgba(245, 158, 11, 0.45);\n background: rgba(245, 158, 11, 0.12);\n}\n\n.tone-info {\n color: #22d3ee;\n border-color: rgba(34, 211, 238, 0.5);\n background: rgba(34, 211, 238, 0.12);\n}\n\n.tone-danger {\n color: #f87171;\n border-color: rgba(248, 113, 113, 0.45);\n background: rgba(248, 113, 113, 0.12);\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n}\n\n.content {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n",".backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.55);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n z-index: 100;\n}\n\n.modal {\n background: #0f172a;\n border: 1px solid var(--border, #1f2937);\n border-radius: 14px;\n padding: 24px;\n width: min(500px, 100%);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n\n/* Size variants */\n.size-sm { width: min(380px, 100%); }\n.size-md { width: min(500px, 100%); }\n.size-lg { width: min(640px, 100%); }\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.titles {\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.title {\n font-weight: 700;\n font-size: 16px;\n color: var(--text, #e2e8f0);\n line-height: 1.3;\n}\n\n.subtitle {\n font-size: 13px;\n color: var(--muted, #94a3b8);\n line-height: 1.4;\n}\n\n.closeButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex-shrink: 0;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: var(--muted, #94a3b8);\n cursor: pointer;\n transition: background 0.12s, color 0.12s;\n padding: 0;\n}\n\n.closeButton:hover {\n background: rgba(255, 255, 255, 0.07);\n color: var(--text, #e2e8f0);\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.footer {\n display: flex;\n gap: 8px;\n margin-top: 20px;\n}\n",".stack {\n position: fixed;\n z-index: 2147483000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n}\n\n.topRight {\n top: 16px;\n right: 16px;\n align-items: flex-end;\n}\n\n.topLeft {\n top: 16px;\n left: 16px;\n align-items: flex-start;\n}\n\n.topCenter {\n top: 16px;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.bottomRight {\n bottom: 16px;\n right: 16px;\n align-items: flex-end;\n}\n\n.bottomLeft {\n bottom: 16px;\n left: 16px;\n align-items: flex-start;\n}\n\n.bottomCenter {\n bottom: 16px;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.toast {\n pointer-events: auto;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 280px;\n max-width: min(420px, calc(100vw - 32px));\n padding: 12px 14px;\n border-radius: 10px;\n border: 1px solid var(--toast-border, #1f2937);\n background: var(--toast-bg, #111827);\n color: var(--toast-text, #e2e8f0);\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\n animation: toastSlideIn 180ms ease-out;\n}\n\n.toast.exit {\n animation: toastSlideOut 160ms ease-in forwards;\n}\n\n.icon {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n}\n\n.body {\n flex: 1;\n min-width: 0;\n display: grid;\n gap: 6px;\n}\n\n.message {\n word-break: break-word;\n font-size: 14px;\n line-height: 1.4;\n}\n\n.actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.actionButton {\n padding: 5px 10px;\n font-size: 12px;\n font-weight: 600;\n border-radius: 6px;\n border: 1px solid var(--toast-action-border, rgba(0, 0, 0, 0.2));\n background: var(--toast-action-bg, rgba(0, 0, 0, 0.1));\n color: var(--toast-text, #e2e8f0);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.actionButton:hover {\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.15));\n}\n\n.closeButton {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n margin: -2px -4px -2px 0;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--toast-text, #e2e8f0);\n opacity: 0.6;\n cursor: pointer;\n transition: opacity 120ms ease, background 120ms ease;\n}\n\n.closeButton:hover {\n opacity: 1;\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.1));\n}\n\n@keyframes toastSlideIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideOut {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(-6px);\n }\n}\n",".wrapper {\n position: relative;\n display: inline-block;\n}\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px 6px 14px;\n background: var(--ts-dropdown-bg, var(--panel, #111827));\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\n border-radius: 8px;\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: border-color 0.15s;\n user-select: none;\n}\n\n.trigger:hover {\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n}\n\n.trigger-active {\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n}\n\n.chevron {\n width: 10px;\n height: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.15s;\n color: var(--muted, #94a3b8);\n flex-shrink: 0;\n}\n\n.chevron-open {\n transform: rotate(180deg);\n}\n\n.menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n min-width: 100%;\n background: var(--ts-dropdown-bg, var(--panel, #111827));\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\n border-radius: 10px;\n padding: 4px;\n z-index: 50;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n animation: dropdownFadeIn 0.1s ease;\n}\n\n@keyframes dropdownFadeIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.option {\n display: block;\n width: 100%;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 0.85rem;\n font-weight: 500;\n color: var(--muted, #94a3b8);\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n white-space: nowrap;\n transition: background 0.1s, color 0.1s;\n}\n\n.option:hover {\n background: rgba(255, 255, 255, 0.05);\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\n}\n\n.option-selected {\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n background: rgba(34, 211, 238, 0.08);\n}\n",".shell {\n display: grid;\n grid-template-rows: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top)) 1fr;\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\n min-height: 100vh;\n min-height: 100dvh;\n transition: grid-template-columns 200ms ease;\n}\n\n.shell.sidebarOpen {\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\n}\n\n.shell.sidebarCollapsed {\n grid-template-columns: 0 1fr;\n}\n\n.topbar {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top));\n padding: env(safe-area-inset-top) 16px 0 16px;\n border-bottom: 1px solid var(--border);\n background: rgba(17, 24, 39, 0.8);\n backdrop-filter: blur(8px);\n position: sticky;\n top: 0;\n z-index: 20;\n gap: 12px;\n}\n\n.topbarLeft {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.topbarStart {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n\n.topbarRight {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 0;\n}\n\n.topbarRight > * {\n min-width: 0;\n}\n\n.brand {\n font-size: 26px;\n color: var(--text);\n text-decoration: none;\n display: flex;\n align-items: center;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.hamburger {\n background: transparent;\n border: none;\n padding: 0;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.hamburger:hover {\n background: rgba(255, 255, 255, 0.06);\n}\n\n.hamburger:focus,\n.hamburger:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.hamburger svg {\n width: 28px;\n height: 28px;\n}\n\n.sidebar {\n border-right: 1px solid var(--border);\n background: #152036;\n padding: 24px;\n transition: transform 200ms ease, opacity 200ms ease;\n}\n\n.shell.sidebarCollapsed .sidebar {\n transform: translateX(-110%);\n opacity: 0;\n pointer-events: none;\n}\n\n.main {\n overflow-y: auto;\n padding: 24px;\n padding-bottom: 96px;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 16px;\n align-items: center;\n}\n\n.main > * {\n width: 100%;\n max-width: 1200px;\n min-width: 0;\n}\n\n.backdrop {\n display: none;\n}\n\n@media (max-width: 960px) {\n .backdrop {\n display: block;\n position: fixed;\n inset: 0;\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\n background: rgba(0, 0, 0, 0.5);\n z-index: 14;\n }\n\n .shell {\n --app-shell-topbar-height: 56px;\n grid-template-columns: 1fr;\n grid-template-rows: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top)) 1fr;\n }\n\n .shell.sidebarOpen,\n .shell.sidebarCollapsed {\n grid-template-columns: 1fr;\n }\n\n .sidebar {\n display: block;\n position: fixed;\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\n left: 0;\n bottom: 0;\n width: var(--app-shell-sidebar-width, 240px);\n max-width: 80vw;\n background: #152036;\n padding: 16px 12px;\n transform: translateX(-105%);\n z-index: 15;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);\n }\n\n .sidebar.open {\n transform: translateX(0);\n }\n\n .topbar {\n padding-left: max(12px, env(safe-area-inset-left));\n padding-right: max(12px, env(safe-area-inset-right));\n gap: 10px;\n }\n\n .topbarLeft {\n gap: 10px;\n flex: 1;\n }\n\n .topbarStart {\n min-width: 0;\n }\n\n .topbarRight {\n gap: 6px;\n }\n\n .brand {\n font-size: 24px;\n max-width: 50vw;\n }\n\n .hamburger {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n }\n\n .hamburger svg {\n width: 24px;\n height: 24px;\n }\n\n .main {\n padding: 16px;\n padding-bottom: 96px;\n }\n}\n\n@media (max-width: 640px) {\n .topbar {\n gap: 8px;\n }\n\n .brand {\n font-size: 22px;\n max-width: 34vw;\n }\n\n .topbarRight {\n max-width: 44vw;\n }\n\n .main {\n padding: 12px 10px;\n padding-bottom: 88px;\n }\n}\n\n@media (max-width: 480px) {\n .brand {\n font-size: 20px;\n max-width: 30vw;\n }\n}\n",".nav {\n display: flex;\n flex-direction: column;\n gap: 8px;\n align-items: stretch;\n}\n\n.item {\n color: var(--text, #e2e8f0);\n background: transparent;\n border: none;\n box-shadow: none;\n padding: 10px 12px 10px 10px;\n border-radius: 10px;\n text-decoration: none;\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n justify-content: flex-start;\n text-align: left;\n box-sizing: border-box;\n white-space: nowrap;\n line-height: 1.2;\n transition: background 120ms ease, color 120ms ease;\n}\n\n.item:focus,\n.item:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.item:hover {\n background: rgba(29, 43, 70, 0.55);\n}\n\n.item.active {\n background: rgba(29, 43, 70, 0.85);\n color: var(--text, #e2e8f0);\n font-weight: 700;\n}\n\n.icon {\n width: 18px;\n height: 18px;\n color: var(--muted, #94a3b8);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 18px;\n vertical-align: middle;\n}\n\n.icon svg {\n width: 18px;\n height: 18px;\n display: block;\n stroke: currentColor;\n}\n\n.item.active .icon {\n color: var(--accent, #22d3ee);\n}\n\n.label {\n flex: 1;\n min-width: 0;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 999px;\n border: 1px solid var(--border, #1f2937);\n background: rgba(255, 255, 255, 0.04);\n color: var(--muted, #94a3b8);\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n@media (max-width: 960px) {\n .nav {\n gap: 6px;\n }\n\n .item {\n padding: 9px 10px 9px 8px;\n border-radius: 9px;\n font-size: 14px;\n gap: 6px;\n }\n\n .icon {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n }\n\n .icon svg {\n width: 16px;\n height: 16px;\n }\n}\n\n@media (max-width: 480px) {\n .item {\n padding: 8px 9px 8px 7px;\n font-size: 13px;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/cx.ts","../src/components/button/button.module.css","../src/components/button/Button.tsx","../src/components/card/card.module.css","../src/components/card/Card.tsx","../src/components/pill/pill.module.css","../src/components/pill/Pill.tsx","../src/components/modal/Modal.tsx","../src/components/modal/modal.module.css","../src/components/toast/ToastContext.tsx","../src/components/toast/toast.module.css","../src/components/dropdown/Dropdown.tsx","../src/components/dropdown/dropdown.module.css","../src/components/app-shell/AppShell.tsx","../src/components/app-shell/app-shell.module.css","../src/components/sidebar-nav/sidebar-nav.module.css","../src/components/sidebar-nav/SidebarNav.tsx"],"sourcesContent":["export function cx(...values: Array<string | false | null | undefined>): string {\r\n return values.filter(Boolean).join(\" \");\r\n}\r\n",".button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n font-family: inherit;\r\n font-weight: 600;\r\n border-radius: 8px;\r\n border: none;\r\n cursor: pointer;\r\n text-decoration: none;\r\n transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s;\r\n white-space: nowrap;\r\n}\r\n\r\n.button:disabled {\r\n opacity: 0.45;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* Sizes */\r\n.size-sm {\r\n font-size: 0.82rem;\r\n padding: 6px 14px;\r\n}\r\n\r\n.size-md {\r\n font-size: 0.95rem;\r\n padding: 10px 22px;\r\n}\r\n\r\n.size-lg {\r\n font-size: 1rem;\r\n padding: 12px 28px;\r\n}\r\n\r\n/* Variants */\r\n.variant-primary {\r\n background: var(--ts-btn-primary-bg, var(--accent, #22d3ee));\r\n color: var(--ts-btn-primary-text, #0f172a);\r\n border: 1px solid transparent;\r\n}\r\n\r\n.variant-primary:hover:not(:disabled) {\r\n opacity: 0.88;\r\n}\r\n\r\n.variant-secondary {\r\n background: var(--ts-btn-secondary-bg, rgba(255, 255, 255, 0.06));\r\n color: var(--ts-btn-secondary-text, var(--text, #e2e8f0));\r\n border: 1px solid var(--ts-btn-secondary-border, var(--border, #1f2937));\r\n}\r\n\r\n.variant-secondary:hover:not(:disabled) {\r\n background: var(--ts-btn-secondary-hover-bg, rgba(255, 255, 255, 0.1));\r\n}\r\n\r\n.variant-outline {\r\n background: transparent;\r\n color: var(--ts-btn-outline-text, var(--text, #e2e8f0));\r\n border: 1px solid var(--ts-btn-outline-border, var(--border, #1f2937));\r\n}\r\n\r\n.variant-outline:hover:not(:disabled) {\r\n border-color: var(--ts-btn-outline-hover-border, var(--accent, #22d3ee));\r\n color: var(--ts-btn-outline-hover-text, var(--accent, #22d3ee));\r\n}\r\n\r\n.variant-ghost {\r\n background: transparent;\r\n color: var(--ts-btn-ghost-text, var(--muted, #94a3b8));\r\n border: 1px solid transparent;\r\n padding-left: 8px;\r\n padding-right: 8px;\r\n}\r\n\r\n.variant-ghost:hover:not(:disabled) {\r\n background: rgba(255, 255, 255, 0.05);\r\n color: var(--text, #e2e8f0);\r\n}\r\n","import type { ButtonHTMLAttributes, AnchorHTMLAttributes } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./button.module.css\";\r\n\r\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\r\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\r\n\r\ntype BaseProps = {\r\n variant?: ButtonVariant;\r\n size?: ButtonSize;\r\n className?: string;\r\n children?: React.ReactNode;\r\n};\r\n\r\ntype AsButton = BaseProps &\r\n ButtonHTMLAttributes<HTMLButtonElement> & { as?: \"button\" };\r\n\r\ntype AsAnchor = BaseProps &\r\n AnchorHTMLAttributes<HTMLAnchorElement> & { as: \"a\" };\r\n\r\nexport type ButtonProps = AsButton | AsAnchor;\r\n\r\nexport function Button({\r\n as,\r\n variant = \"primary\",\r\n size = \"md\",\r\n className,\r\n children,\r\n ...rest\r\n}: ButtonProps) {\r\n const classes = cx(\r\n styles.button,\r\n styles[`variant-${variant}`],\r\n styles[`size-${size}`],\r\n className,\r\n );\r\n\r\n if (as === \"a\") {\r\n return (\r\n <a className={classes} {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}>\r\n {children}\r\n </a>\r\n );\r\n }\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={classes}\r\n {...(rest as ButtonHTMLAttributes<HTMLButtonElement>)}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n",".card {\r\n position: relative;\r\n overflow: visible;\r\n border-radius: var(--ts-card-radius, 12px);\r\n border: 1px solid var(--ts-card-border, var(--border, #1f2937));\r\n background: var(--ts-card-bg, var(--panel, #111827));\r\n color: var(--ts-card-fg, var(--text, #e2e8f0));\r\n box-shadow: var(--ts-card-shadow, 0 16px 36px rgba(0, 0, 0, 0.28));\r\n padding: var(--ts-card-padding, 16px);\r\n transition:\r\n transform 140ms ease,\r\n box-shadow 140ms ease,\r\n border-color 140ms ease,\r\n background-color 140ms ease;\r\n}\r\n\r\n.tone-default {\r\n --ts-card-bg: var(--panel, #111827);\r\n --ts-card-border: var(--border, #1f2937);\r\n --ts-card-shadow: 0 16px 36px rgba(0, 0, 0, 0.28);\r\n}\r\n\r\n.tone-muted {\r\n --ts-card-bg: var(--ts-card-muted-bg, rgba(255, 255, 255, 0.02));\r\n --ts-card-border: var(--ts-card-muted-border, rgba(255, 255, 255, 0.06));\r\n --ts-card-shadow: 0 10px 26px rgba(0, 0, 0, 0.22);\r\n}\r\n\r\n.tone-contrast {\r\n --ts-card-bg: var(--ts-card-contrast-bg, #0b1224);\r\n --ts-card-border: var(--ts-card-contrast-border, rgba(255, 255, 255, 0.1));\r\n --ts-card-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);\r\n}\r\n\r\n.interactive {\r\n cursor: default;\r\n}\r\n\r\n.interactive:hover {\r\n transform: translateY(-1px);\r\n box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);\r\n border-color: var(--ts-card-hover-border, rgba(34, 211, 238, 0.4));\r\n}\r\n\r\n.interactive:focus-within {\r\n outline: 2px solid var(--ts-card-hover-border, rgba(34, 211, 238, 0.45));\r\n outline-offset: 2px;\r\n}\r\n\r\n.padding-none {\r\n --ts-card-padding: 0;\r\n}\r\n\r\n.padding-sm {\r\n --ts-card-padding: 10px;\r\n}\r\n\r\n.padding-md {\r\n --ts-card-padding: 16px;\r\n}\r\n\r\n.padding-lg {\r\n --ts-card-padding: 20px;\r\n}\r\n","/**\r\n * Lightweight container component used for panels across the app.\r\n *\r\n * @remarks\r\n * Supports tone variants, padding presets, and an optional interactive affordance.\r\n *\r\n * @param props.as - Semantic element to render (defaults to `div`).\r\n * @param props.tone - Visual tone variant.\r\n * @param props.padding - Padding preset.\r\n * @param props.interactive - Enables hover/focus affordance.\r\n */\r\nimport type { HTMLAttributes } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./card.module.css\";\r\n\r\nexport type CardTone = \"default\" | \"muted\" | \"contrast\";\r\nexport type CardPadding = \"none\" | \"sm\" | \"md\" | \"lg\";\r\n\r\ntype CardElement = \"div\" | \"section\" | \"article\";\r\n\r\nexport type CardProps = HTMLAttributes<HTMLElement> & {\r\n /** Optional semantic element type. Defaults to `div`. */\r\n as?: CardElement;\r\n /** Visual tone; drives background/border CSS vars. */\r\n tone?: CardTone;\r\n /** Padding preset; maps to CSS variables so consumers can override globally. */\r\n padding?: CardPadding;\r\n /** Adds hover/focus affordance (lift + outline). */\r\n interactive?: boolean;\r\n};\r\n\r\nexport function Card({\r\n as,\r\n tone = \"default\",\r\n padding = \"md\",\r\n interactive = false,\r\n className,\r\n children,\r\n ...rest\r\n}: CardProps) {\r\n const Component: CardElement = as ?? \"div\";\r\n const toneClass = tone !== \"default\" ? styles[`tone-${tone}`] : null;\r\n const classes = cx(\r\n styles.card,\r\n toneClass,\r\n styles[`padding-${padding}`],\r\n interactive && styles.interactive,\r\n className,\r\n );\r\n\r\n return (\r\n <Component className={classes} {...rest}>\r\n {children}\r\n </Component>\r\n );\r\n}\r\n",".pill {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 4px 10px;\r\n border-radius: 999px;\r\n border: 1px solid var(--ts-pill-border, var(--border, #1f2937));\r\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\r\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\r\n font-size: 12px;\r\n font-weight: 700;\r\n letter-spacing: 0.05em;\r\n text-transform: uppercase;\r\n line-height: 1.2;\r\n white-space: nowrap;\r\n}\r\n\r\n.size-sm {\r\n padding: 3px 8px;\r\n font-size: 11px;\r\n}\r\n\r\n.size-md {\r\n padding: 4px 10px;\r\n}\r\n\r\n.tone-neutral {\r\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\r\n border-color: var(--ts-pill-border, var(--border, #1f2937));\r\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\r\n}\r\n\r\n.tone-success {\r\n color: #22c55e;\r\n border-color: rgba(34, 197, 94, 0.45);\r\n background: rgba(34, 197, 94, 0.12);\r\n}\r\n\r\n.tone-warning {\r\n color: #f59e0b;\r\n border-color: rgba(245, 158, 11, 0.45);\r\n background: rgba(245, 158, 11, 0.12);\r\n}\r\n\r\n.tone-info {\r\n color: #22d3ee;\r\n border-color: rgba(34, 211, 238, 0.5);\r\n background: rgba(34, 211, 238, 0.12);\r\n}\r\n\r\n.tone-danger {\r\n color: #f87171;\r\n border-color: rgba(248, 113, 113, 0.45);\r\n background: rgba(248, 113, 113, 0.12);\r\n}\r\n\r\n.icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 12px;\r\n height: 12px;\r\n}\r\n\r\n.content {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n}\r\n","/**\r\n * Compact label component for status chips and tags.\r\n *\r\n * @remarks\r\n * Supports tone and size presets, and can render any inline element.\r\n *\r\n * @param props.as - Element to render (defaults to `span`).\r\n * @param props.tone - Visual tone variant.\r\n * @param props.size - Size preset.\r\n * @param props.icon - Optional leading icon.\r\n */\r\nimport type { HTMLAttributes, ReactNode } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./pill.module.css\";\r\n\r\nexport type PillTone = \"neutral\" | \"success\" | \"warning\" | \"info\" | \"danger\";\r\nexport type PillSize = \"sm\" | \"md\";\r\n\r\ntype PillElement = \"span\" | \"div\" | \"button\";\r\n\r\nexport type PillProps = HTMLAttributes<HTMLElement> & {\r\n /** Optional rendered element; defaults to `span`. */\r\n as?: PillElement;\r\n /** Visual tone; adjusts color and border. */\r\n tone?: PillTone;\r\n /** Size preset. */\r\n size?: PillSize;\r\n /** Leading icon node (not focusable). */\r\n icon?: ReactNode;\r\n};\r\n\r\nexport function Pill({\r\n as,\r\n tone = \"neutral\",\r\n size = \"md\",\r\n icon,\r\n className,\r\n children,\r\n ...rest\r\n}: PillProps) {\r\n const Component: PillElement = as ?? \"span\";\r\n const classes = cx(styles.pill, styles[`tone-${tone}`], styles[`size-${size}`], className);\r\n\r\n return (\r\n <Component className={classes} {...rest}>\r\n {icon ? (\r\n <span className={styles.icon} aria-hidden=\"true\">\r\n {icon}\r\n </span>\r\n ) : null}\r\n <span className={styles.content}>{children}</span>\r\n </Component>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useRef, type ReactNode } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./modal.module.css\";\r\n\r\nexport type ModalSize = \"sm\" | \"md\" | \"lg\";\r\n\r\nexport type ModalProps = {\r\n open: boolean;\r\n onClose: () => void;\r\n title: string;\r\n subtitle?: string;\r\n size?: ModalSize;\r\n /** Content between the header and footer */\r\n children: ReactNode;\r\n /** Rendered inside the footer row — typically action buttons */\r\n footer?: ReactNode;\r\n};\r\n\r\nexport function Modal({ open, onClose, title, subtitle, size = \"md\", children, footer }: ModalProps) {\r\n const mouseDownOnBackdrop = useRef(false);\r\n\r\n if (!open) return null;\r\n\r\n return (\r\n <div\r\n className={styles.backdrop}\r\n onMouseDown={(e) => { mouseDownOnBackdrop.current = e.target === e.currentTarget; }}\r\n onMouseUp={(e) => {\r\n if (mouseDownOnBackdrop.current && e.target === e.currentTarget) onClose();\r\n mouseDownOnBackdrop.current = false;\r\n }}\r\n >\r\n <div className={cx(styles.modal, styles[`size-${size}`])}>\r\n <div className={styles.header}>\r\n <div className={styles.titles}>\r\n <div className={styles.title}>{title}</div>\r\n {subtitle && <div className={styles.subtitle}>{subtitle}</div>}\r\n </div>\r\n <button className={styles.closeButton} onClick={onClose} aria-label=\"Close\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div className={styles.body}>{children}</div>\r\n\r\n {footer && <div className={styles.footer}>{footer}</div>}\r\n </div>\r\n </div>\r\n );\r\n}\r\n",".backdrop {\r\n position: fixed;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.55);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 16px;\r\n z-index: 100;\r\n}\r\n\r\n.modal {\r\n background: #0f172a;\r\n border: 1px solid var(--border, #1f2937);\r\n border-radius: 14px;\r\n padding: 24px;\r\n width: min(500px, 100%);\r\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0;\r\n}\r\n\r\n/* Size variants */\r\n.size-sm { width: min(380px, 100%); }\r\n.size-md { width: min(500px, 100%); }\r\n.size-lg { width: min(640px, 100%); }\r\n\r\n.header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 12px;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.titles {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 3px;\r\n}\r\n\r\n.title {\r\n font-weight: 700;\r\n font-size: 16px;\r\n color: var(--text, #e2e8f0);\r\n line-height: 1.3;\r\n}\r\n\r\n.subtitle {\r\n font-size: 13px;\r\n color: var(--muted, #94a3b8);\r\n line-height: 1.4;\r\n}\r\n\r\n.closeButton {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n flex-shrink: 0;\r\n background: transparent;\r\n border: 1px solid transparent;\r\n border-radius: 6px;\r\n color: var(--muted, #94a3b8);\r\n cursor: pointer;\r\n transition: background 0.12s, color 0.12s;\r\n padding: 0;\r\n}\r\n\r\n.closeButton:hover {\r\n background: rgba(255, 255, 255, 0.07);\r\n color: var(--text, #e2e8f0);\r\n}\r\n\r\n.body {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n}\r\n\r\n.footer {\r\n display: flex;\r\n gap: 8px;\r\n margin-top: 20px;\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n type CSSProperties,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport type {\r\n Toast,\r\n ToastConfig,\r\n ToastContextValue,\r\n ToastOptions,\r\n ToastPosition,\r\n ToastType,\r\n} from \"./types\";\r\nimport styles from \"./toast.module.css\";\r\n\r\n/** Default provider configuration. */\r\nconst DEFAULT_CONFIG: Required<ToastConfig> = {\r\n position: \"top-right\",\r\n maxToasts: 5,\r\n defaultDuration: 4000,\r\n pauseOnHover: true,\r\n pauseOnFocusLoss: true,\r\n};\r\n\r\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\r\n\r\nlet toastIdCounter = 0;\r\nconst generateToastId = () => `toast-${++toastIdCounter}-${Date.now()}`;\r\n\r\n/**\r\n * Toast notification context provider.\r\n *\r\n * @remarks\r\n * Wrap your app (or a section) to enable `useToast` calls. Supports configurable placement,\r\n * maximum visible toasts, and pause behavior on hover or window blur.\r\n *\r\n * @param props.children - React subtree that can consume the toast context.\r\n * @param props.config - Optional provider configuration overrides.\r\n */\r\nexport function ToastProvider({\r\n children,\r\n config,\r\n}: {\r\n children: ReactNode;\r\n config?: ToastConfig;\r\n}) {\r\n const [toasts, setToasts] = useState<Toast[]>([]);\r\n const [isPaused, setIsPaused] = useState(false);\r\n const merged = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);\r\n\r\n const push = useCallback(\r\n (message: string, options: ToastOptions = {}) => {\r\n const id = generateToastId();\r\n setToasts((prev) => {\r\n const next: Toast[] = [\r\n ...prev,\r\n {\r\n id,\r\n message,\r\n type: options.type ?? \"info\",\r\n duration: options.duration ?? (options.type === \"error\" ? 6000 : merged.defaultDuration),\r\n dismissible: options.dismissible ?? true,\r\n action: options.action,\r\n },\r\n ];\r\n if (next.length > merged.maxToasts) next.shift();\r\n return next;\r\n });\r\n return id;\r\n },\r\n [merged.defaultDuration, merged.maxToasts],\r\n );\r\n\r\n const success = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"success\" }),\r\n [push],\r\n );\r\n const error = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) =>\r\n push(message, { ...options, type: \"error\", duration: options?.duration ?? 6000 }),\r\n [push],\r\n );\r\n const warning = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"warning\" }),\r\n [push],\r\n );\r\n const info = useCallback(\r\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"info\" }),\r\n [push],\r\n );\r\n\r\n const dismiss = useCallback((id: string) => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n }, []);\r\n\r\n const dismissAll = useCallback(() => setToasts([]), []);\r\n\r\n useEffect(() => {\r\n if (!merged.pauseOnFocusLoss) return;\r\n const handleVisibility = () => setIsPaused(document.visibilityState !== \"visible\");\r\n document.addEventListener(\"visibilitychange\", handleVisibility);\r\n return () => document.removeEventListener(\"visibilitychange\", handleVisibility);\r\n }, [merged.pauseOnFocusLoss]);\r\n\r\n const value = useMemo<ToastContextValue>(\r\n () => ({ toasts, push, success, error, warning, info, dismiss, dismissAll }),\r\n [toasts, push, success, error, warning, info, dismiss, dismissAll],\r\n );\r\n\r\n return (\r\n <ToastContext.Provider value={value}>\r\n {children}\r\n <ToastContainer\r\n toasts={toasts}\r\n position={merged.position}\r\n pauseOnHover={merged.pauseOnHover}\r\n isPaused={isPaused}\r\n onDismiss={dismiss}\r\n onPauseChange={setIsPaused}\r\n />\r\n </ToastContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * Hook to access the toast API.\r\n *\r\n * @remarks\r\n * Exposes `push`, intent helpers (`success`, `error`, `warning`, `info`), and dismissal helpers.\r\n * Must be called within a `ToastProvider`.\r\n *\r\n * @throws Error if used outside of a `ToastProvider`.\r\n */\r\nexport function useToast(): ToastContextValue {\r\n const ctx = useContext(ToastContext);\r\n if (!ctx) throw new Error(\"useToast must be used within a ToastProvider\");\r\n return ctx;\r\n}\r\n\r\n/** Renders the positioned toast stack. */\r\nfunction ToastContainer({\r\n toasts,\r\n position,\r\n pauseOnHover,\r\n isPaused,\r\n onDismiss,\r\n onPauseChange,\r\n}: {\r\n toasts: Toast[];\r\n position: ToastPosition;\r\n pauseOnHover: boolean;\r\n isPaused: boolean;\r\n onDismiss: (id: string) => void;\r\n onPauseChange: (paused: boolean) => void;\r\n}) {\r\n const posClass = (() => {\r\n switch (position) {\r\n case \"top-left\":\r\n return styles.topLeft;\r\n case \"top-center\":\r\n return styles.topCenter;\r\n case \"bottom-right\":\r\n return styles.bottomRight;\r\n case \"bottom-left\":\r\n return styles.bottomLeft;\r\n case \"bottom-center\":\r\n return styles.bottomCenter;\r\n case \"top-right\":\r\n default:\r\n return styles.topRight;\r\n }\r\n })();\r\n\r\n return (\r\n <div\r\n className={cx(styles.stack, posClass)}\r\n role=\"presentation\"\r\n onMouseEnter={() => pauseOnHover && onPauseChange(true)}\r\n onMouseLeave={() => pauseOnHover && onPauseChange(false)}\r\n >\r\n {toasts.map((toast) => (\r\n <ToastItem key={toast.id} toast={toast} isPaused={isPaused} onDismiss={onDismiss} />\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\n/** Individual toast item with timers and actions. */\r\nfunction ToastItem({\r\n toast,\r\n isPaused,\r\n onDismiss,\r\n}: {\r\n toast: Toast;\r\n isPaused: boolean;\r\n onDismiss: (id: string) => void;\r\n}) {\r\n const [exiting, setExiting] = useState(false);\r\n const timerRef = useRef<number | null>(null);\r\n const startRef = useRef<number>(0);\r\n const remainingRef = useRef<number>(toast.duration ?? 0);\r\n\r\n const palette = getPalette(toast.type);\r\n const styleVars: CSSProperties = {\r\n [\"--toast-bg\" as any]: palette.background,\r\n [\"--toast-border\" as any]: palette.border,\r\n [\"--toast-text\" as any]: palette.text,\r\n [\"--toast-button-bg\" as any]: palette.buttonBg,\r\n [\"--toast-button-border\" as any]: palette.buttonBorder,\r\n [\"--toast-action-bg\" as any]: palette.actionBg,\r\n [\"--toast-action-border\" as any]: palette.actionBorder,\r\n };\r\n\r\n const stopTimer = () => {\r\n if (timerRef.current) {\r\n window.clearTimeout(timerRef.current);\r\n timerRef.current = null;\r\n }\r\n };\r\n\r\n const triggerDismiss = useCallback(() => {\r\n setExiting(true);\r\n stopTimer();\r\n window.setTimeout(() => onDismiss(toast.id), 160);\r\n }, [onDismiss, toast.id]);\r\n\r\n const schedule = useCallback(\r\n (delay: number) => {\r\n if (!delay || delay <= 0) {\r\n triggerDismiss();\r\n return;\r\n }\r\n startRef.current = performance.now();\r\n stopTimer();\r\n timerRef.current = window.setTimeout(() => triggerDismiss(), delay);\r\n },\r\n [triggerDismiss],\r\n );\r\n\r\n useEffect(() => {\r\n if (!toast.duration || toast.duration <= 0) return undefined;\r\n schedule(toast.duration);\r\n return stopTimer;\r\n }, [schedule, toast.duration]);\r\n\r\n useEffect(() => {\r\n if (!toast.duration || toast.duration <= 0) return;\r\n if (isPaused) {\r\n const elapsed = performance.now() - startRef.current;\r\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\r\n stopTimer();\r\n } else {\r\n schedule(remainingRef.current);\r\n }\r\n }, [isPaused, schedule, toast.duration]);\r\n\r\n const icon = getIcon(toast.type);\r\n\r\n return (\r\n <div className={cx(styles.toast, exiting && styles.exit)} style={styleVars} role=\"status\" aria-live=\"polite\">\r\n <span className={styles.icon} aria-hidden>\r\n {icon}\r\n </span>\r\n <div className={styles.body}>\r\n <div className={styles.message}>{toast.message}</div>\r\n {toast.action && (\r\n <div className={styles.actions}>\r\n <button\r\n type=\"button\"\r\n className={styles.actionButton}\r\n onClick={() => {\r\n toast.action?.onClick();\r\n triggerDismiss();\r\n }}\r\n >\r\n {toast.action.label}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n {toast.dismissible !== false && (\r\n <button\r\n type=\"button\"\r\n className={styles.closeButton}\r\n onClick={triggerDismiss}\r\n aria-label=\"Dismiss notification\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden>\r\n <path\r\n d=\"M11 3L3 11M3 3l8 8\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n strokeLinecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction getPalette(type: ToastType) {\r\n switch (type) {\r\n case \"success\":\r\n return {\r\n background: \"#22c55e\",\r\n border: \"#16a34a\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n case \"error\":\r\n return {\r\n background: \"#f87171\",\r\n border: \"#ef4444\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n case \"warning\":\r\n return {\r\n background: \"#fbbf24\",\r\n border: \"#f59e0b\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n case \"info\":\r\n default:\r\n return {\r\n background: \"#38bdf8\",\r\n border: \"#0ea5e9\",\r\n text: \"#0b1224\",\r\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\r\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\r\n actionBg: \"rgba(0, 0, 0, 0.1)\",\r\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\r\n };\r\n }\r\n}\r\n\r\nfunction getIcon(type: ToastType) {\r\n switch (type) {\r\n case \"success\":\r\n return \"OK\";\r\n case \"error\":\r\n return \"X\";\r\n case \"warning\":\r\n return \"!\";\r\n case \"info\":\r\n default:\r\n return \"i\";\r\n }\r\n}\r\n",".stack {\r\n position: fixed;\r\n z-index: 2147483000;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n pointer-events: none;\r\n}\r\n\r\n.topRight {\r\n top: 16px;\r\n right: 16px;\r\n align-items: flex-end;\r\n}\r\n\r\n.topLeft {\r\n top: 16px;\r\n left: 16px;\r\n align-items: flex-start;\r\n}\r\n\r\n.topCenter {\r\n top: 16px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n align-items: center;\r\n}\r\n\r\n.bottomRight {\r\n bottom: 16px;\r\n right: 16px;\r\n align-items: flex-end;\r\n}\r\n\r\n.bottomLeft {\r\n bottom: 16px;\r\n left: 16px;\r\n align-items: flex-start;\r\n}\r\n\r\n.bottomCenter {\r\n bottom: 16px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n align-items: center;\r\n}\r\n\r\n.toast {\r\n pointer-events: auto;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 10px;\r\n min-width: 280px;\r\n max-width: min(420px, calc(100vw - 32px));\r\n padding: 12px 14px;\r\n border-radius: 10px;\r\n border: 1px solid var(--toast-border, #1f2937);\r\n background: var(--toast-bg, #111827);\r\n color: var(--toast-text, #e2e8f0);\r\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\r\n animation: toastSlideIn 180ms ease-out;\r\n}\r\n\r\n.toast.exit {\r\n animation: toastSlideOut 160ms ease-in forwards;\r\n}\r\n\r\n.icon {\r\n width: 18px;\r\n height: 18px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.body {\r\n flex: 1;\r\n min-width: 0;\r\n display: grid;\r\n gap: 6px;\r\n}\r\n\r\n.message {\r\n word-break: break-word;\r\n font-size: 14px;\r\n line-height: 1.4;\r\n}\r\n\r\n.actions {\r\n display: flex;\r\n gap: 6px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.actionButton {\r\n padding: 5px 10px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n border-radius: 6px;\r\n border: 1px solid var(--toast-action-border, rgba(0, 0, 0, 0.2));\r\n background: var(--toast-action-bg, rgba(0, 0, 0, 0.1));\r\n color: var(--toast-text, #e2e8f0);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.actionButton:hover {\r\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.15));\r\n}\r\n\r\n.closeButton {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 20px;\r\n height: 20px;\r\n padding: 0;\r\n margin: -2px -4px -2px 0;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: var(--toast-text, #e2e8f0);\r\n opacity: 0.6;\r\n cursor: pointer;\r\n transition: opacity 120ms ease, background 120ms ease;\r\n}\r\n\r\n.closeButton:hover {\r\n opacity: 1;\r\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.1));\r\n}\r\n\r\n@keyframes toastSlideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-8px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n@keyframes toastSlideOut {\r\n from {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n to {\r\n opacity: 0;\r\n transform: translateY(-6px);\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./dropdown.module.css\";\r\n\r\nexport interface DropdownOption {\r\n label: string;\r\n value: string;\r\n}\r\n\r\nexport interface DropdownProps {\r\n /** List of options to display in the menu. */\r\n options: DropdownOption[];\r\n /** Currently selected value. Use empty string for \"no selection\". */\r\n value: string;\r\n /** Called when the user selects an option. */\r\n onChange: (value: string) => void;\r\n /** Label shown when no option is selected. Defaults to \"All\". */\r\n placeholder?: string;\r\n /** Additional class name for the wrapper element. */\r\n className?: string;\r\n /** Whether to show the placeholder as a clearable option. Defaults to true. */\r\n allowClear?: boolean;\r\n /** Associates the trigger button with an external label element via its id. */\r\n \"aria-labelledby\"?: string;\r\n /** Provides an accessible label directly on the trigger button. */\r\n \"aria-label\"?: string;\r\n}\r\n\r\nexport function Dropdown({\r\n options,\r\n value,\r\n onChange,\r\n placeholder = \"All\",\r\n className,\r\n allowClear = true,\r\n \"aria-labelledby\": ariaLabelledBy,\r\n \"aria-label\": ariaLabel,\r\n}: DropdownProps) {\r\n const [open, setOpen] = useState(false);\r\n const ref = useRef<HTMLDivElement>(null);\r\n\r\n const selected = options.find((o) => o.value === value);\r\n const isActive = allowClear && value !== \"\";\r\n\r\n useEffect(() => {\r\n function handleClickOutside(e: MouseEvent) {\r\n if (ref.current && !ref.current.contains(e.target as Node)) {\r\n setOpen(false);\r\n }\r\n }\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, []);\r\n\r\n return (\r\n <div className={cx(styles.wrapper, className)} ref={ref}>\r\n <button\r\n type=\"button\"\r\n className={cx(styles.trigger, isActive && styles[\"trigger-active\"])}\r\n onClick={() => setOpen((o) => !o)}\r\n aria-labelledby={ariaLabelledBy}\r\n aria-label={ariaLabel}\r\n >\r\n {selected ? selected.label : placeholder}\r\n <span className={cx(styles.chevron, open && styles[\"chevron-open\"])}>\r\n <svg viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\">\r\n <path d=\"M2 3.5L5 6.5L8 3.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n </span>\r\n </button>\r\n\r\n {open && (\r\n <div className={styles.menu}>\r\n {allowClear && (\r\n <button\r\n type=\"button\"\r\n className={cx(styles.option, value === \"\" && styles[\"option-selected\"])}\r\n onClick={() => { onChange(\"\"); setOpen(false); }}\r\n >\r\n {placeholder}\r\n </button>\r\n )}\r\n {options.map((opt) => (\r\n <button\r\n key={opt.value}\r\n type=\"button\"\r\n className={cx(styles.option, value === opt.value && styles[\"option-selected\"])}\r\n onClick={() => { onChange(opt.value); setOpen(false); }}\r\n >\r\n {opt.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n",".wrapper {\r\n position: relative;\r\n display: inline-block;\r\n}\r\n\r\n.trigger {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 6px 10px 6px 14px;\r\n background: var(--ts-dropdown-bg, var(--panel, #111827));\r\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\r\n border-radius: 8px;\r\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\r\n font-size: 0.85rem;\r\n font-weight: 500;\r\n cursor: pointer;\r\n white-space: nowrap;\r\n transition: border-color 0.15s;\r\n user-select: none;\r\n}\r\n\r\n.trigger:hover {\r\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n}\r\n\r\n.trigger-active {\r\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n}\r\n\r\n.chevron {\r\n width: 10px;\r\n height: 10px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: transform 0.15s;\r\n color: var(--muted, #94a3b8);\r\n flex-shrink: 0;\r\n}\r\n\r\n.chevron-open {\r\n transform: rotate(180deg);\r\n}\r\n\r\n.menu {\r\n position: absolute;\r\n top: calc(100% + 6px);\r\n left: 0;\r\n min-width: 100%;\r\n background: var(--ts-dropdown-bg, var(--panel, #111827));\r\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\r\n border-radius: 10px;\r\n padding: 4px;\r\n z-index: 50;\r\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\r\n animation: dropdownFadeIn 0.1s ease;\r\n}\r\n\r\n@keyframes dropdownFadeIn {\r\n from { opacity: 0; transform: translateY(-4px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n.option {\r\n display: block;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n font-size: 0.85rem;\r\n font-weight: 500;\r\n color: var(--muted, #94a3b8);\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n text-align: left;\r\n white-space: nowrap;\r\n transition: background 0.1s, color 0.1s;\r\n}\r\n\r\n.option:hover {\r\n background: rgba(255, 255, 255, 0.05);\r\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\r\n}\r\n\r\n.option-selected {\r\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\r\n background: rgba(34, 211, 238, 0.08);\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n useEffect,\r\n useId,\r\n useRef,\r\n useState,\r\n type CSSProperties,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./app-shell.module.css\";\r\n\r\nconst DESKTOP_BREAKPOINT = 960;\r\n\r\nfunction getIsDesktop() {\r\n if (typeof window === \"undefined\") return false;\r\n return window.innerWidth >= DESKTOP_BREAKPOINT;\r\n}\r\n\r\nexport type AppShellProps = {\r\n /** Primary page content rendered in the main area. */\r\n children: ReactNode;\r\n /** Sidebar navigation or custom content. */\r\n sidebar: ReactNode;\r\n /** Brand element rendered next to the hamburger (text or JSX). */\r\n brand?: ReactNode;\r\n /** Optional brand href; when provided the brand renders as an anchor. */\r\n brandHref?: string;\r\n /** Optional content after the brand on the left side of the top bar. */\r\n topbarStart?: ReactNode;\r\n /** Optional content aligned to the right side of the top bar. */\r\n topbarEnd?: ReactNode;\r\n /** Custom class names for styling overrides. */\r\n className?: string;\r\n sidebarClassName?: string;\r\n topbarClassName?: string;\r\n mainClassName?: string;\r\n /** Sets the sidebar width (e.g., `260`, `\"18rem\"`). */\r\n sidebarWidth?: number | string;\r\n /**\r\n * Closes the sidebar on mobile whenever this value changes.\r\n * Useful for reacting to route/pathname changes.\r\n */\r\n closeSidebarOnChangeKey?: unknown;\r\n /** Label for the hamburger button (aria-label). */\r\n hamburgerLabel?: string;\r\n /** Optional callback fired whenever the sidebar open state changes. */\r\n onSidebarToggle?: (open: boolean) => void;\r\n};\r\n\r\n/**\r\n * Responsive application shell with a collapsible sidebar and sticky top bar.\r\n *\r\n * - Sidebar opens by default on desktop, collapses on mobile.\r\n * - Closes on outside click/scroll/touch when in mobile mode.\r\n * - Provides optional hook to close the sidebar when a prop value changes\r\n * (e.g., route transitions).\r\n */\r\nexport function AppShell({\r\n children,\r\n sidebar,\r\n brand,\r\n brandHref,\r\n topbarStart,\r\n topbarEnd,\r\n className,\r\n sidebarClassName,\r\n topbarClassName,\r\n mainClassName,\r\n sidebarWidth,\r\n closeSidebarOnChangeKey,\r\n hamburgerLabel = \"Toggle navigation\",\r\n onSidebarToggle,\r\n}: AppShellProps) {\r\n const [isDesktop, setIsDesktop] = useState(false);\r\n const [sidebarOpen, setSidebarOpen] = useState(false);\r\n const prevIsDesktopRef = useRef(false);\r\n const closeKeyRef = useRef(closeSidebarOnChangeKey);\r\n\r\n const sidebarRef = useRef<HTMLElement | null>(null);\r\n const hamburgerRef = useRef<HTMLButtonElement | null>(null);\r\n const mainRef = useRef<HTMLElement | null>(null);\r\n const sidebarId = useId();\r\n\r\n useEffect(() => {\r\n const desktop = getIsDesktop();\r\n setIsDesktop(desktop);\r\n setSidebarOpen(desktop);\r\n prevIsDesktopRef.current = desktop;\r\n\r\n const handleResize = () => {\r\n const nowDesktop = getIsDesktop();\r\n setIsDesktop(nowDesktop);\r\n if (nowDesktop !== prevIsDesktopRef.current) {\r\n setSidebarOpen(nowDesktop);\r\n prevIsDesktopRef.current = nowDesktop;\r\n }\r\n };\r\n\r\n window.addEventListener(\"resize\", handleResize);\r\n return () => window.removeEventListener(\"resize\", handleResize);\r\n }, []);\r\n\r\n // Close the sidebar when clicking outside or scrolling on mobile.\r\n useEffect(() => {\r\n if (isDesktop || !sidebarOpen) return;\r\n\r\n const mainElement = mainRef.current;\r\n const closeSidebar = () => setSidebarOpen(false);\r\n\r\n const onPointerDown = (e: PointerEvent) => {\r\n const target = e.target as Node | null;\r\n if (!target) return;\r\n if (sidebarRef.current?.contains(target)) return;\r\n if (hamburgerRef.current?.contains(target)) return;\r\n closeSidebar();\r\n };\r\n\r\n const timeoutId = window.setTimeout(() => {\r\n document.addEventListener(\"pointerdown\", onPointerDown);\r\n window.addEventListener(\"scroll\", closeSidebar, { passive: true });\r\n mainElement?.addEventListener(\"scroll\", closeSidebar, { passive: true });\r\n document.addEventListener(\"touchmove\", closeSidebar, { passive: true });\r\n }, 10);\r\n\r\n return () => {\r\n window.clearTimeout(timeoutId);\r\n document.removeEventListener(\"pointerdown\", onPointerDown);\r\n window.removeEventListener(\"scroll\", closeSidebar);\r\n mainElement?.removeEventListener(\"scroll\", closeSidebar);\r\n document.removeEventListener(\"touchmove\", closeSidebar);\r\n };\r\n }, [sidebarOpen, isDesktop]);\r\n\r\n // Allow consumers to request a mobile sidebar close when a value changes (e.g., pathname).\r\n useEffect(() => {\r\n if (!isDesktop && closeKeyRef.current !== closeSidebarOnChangeKey) {\r\n setSidebarOpen(false);\r\n }\r\n closeKeyRef.current = closeSidebarOnChangeKey;\r\n }, [closeSidebarOnChangeKey, isDesktop]);\r\n\r\n useEffect(() => {\r\n onSidebarToggle?.(sidebarOpen);\r\n }, [sidebarOpen, onSidebarToggle]);\r\n\r\n const toggleSidebar = () => setSidebarOpen((open) => !open);\r\n\r\n const sidebarWidthValue =\r\n sidebarWidth === undefined\r\n ? undefined\r\n : typeof sidebarWidth === \"number\"\r\n ? `${sidebarWidth}px`\r\n : sidebarWidth;\r\n\r\n const shellStyle: CSSProperties | undefined = sidebarWidthValue\r\n ? { [\"--app-shell-sidebar-width\" as string]: sidebarWidthValue }\r\n : undefined;\r\n\r\n const shellClasses = cx(\r\n styles.shell,\r\n sidebarOpen ? styles.sidebarOpen : styles.sidebarCollapsed,\r\n className,\r\n );\r\n\r\n const sidebarClasses = cx(styles.sidebar, sidebarOpen && styles.open, sidebarClassName);\r\n\r\n return (\r\n <div\r\n className={shellClasses}\r\n style={shellStyle}\r\n data-app-shell\r\n data-desktop={isDesktop ? \"true\" : \"false\"}\r\n data-sidebar-open={sidebarOpen ? \"true\" : \"false\"}\r\n >\r\n <header className={cx(styles.topbar, topbarClassName)}>\r\n <div className={styles.topbarLeft}>\r\n <button\r\n ref={hamburgerRef}\r\n type=\"button\"\r\n className={styles.hamburger}\r\n onClick={toggleSidebar}\r\n aria-label={hamburgerLabel}\r\n aria-expanded={sidebarOpen}\r\n aria-controls={sidebarId}\r\n >\r\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\r\n </svg>\r\n </button>\r\n {brand &&\r\n (brandHref ? (\r\n <a className={styles.brand} href={brandHref}>\r\n {brand}\r\n </a>\r\n ) : (\r\n <div className={styles.brand}>{brand}</div>\r\n ))}\r\n {topbarStart && <div className={styles.topbarStart}>{topbarStart}</div>}\r\n </div>\r\n <div className={styles.topbarRight}>{topbarEnd}</div>\r\n </header>\r\n {!isDesktop && sidebarOpen && (\r\n <div className={styles.backdrop} onClick={() => setSidebarOpen(false)} onTouchStart={() => setSidebarOpen(false)} aria-hidden=\"true\" />\r\n )}\r\n <aside ref={sidebarRef} id={sidebarId} className={sidebarClasses} aria-label=\"Sidebar navigation\">\r\n {sidebar}\r\n </aside>\r\n <main ref={mainRef} className={cx(styles.main, mainClassName)}>\r\n {children}\r\n </main>\r\n </div>\r\n );\r\n}\r\n",".shell {\r\n display: grid;\r\n grid-template-rows: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top)) 1fr;\r\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\r\n min-height: 100vh;\r\n min-height: 100dvh;\r\n transition: grid-template-columns 200ms ease;\r\n}\r\n\r\n.shell.sidebarOpen {\r\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\r\n}\r\n\r\n.shell.sidebarCollapsed {\r\n grid-template-columns: 0 1fr;\r\n}\r\n\r\n.topbar {\r\n grid-column: 1 / -1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top));\r\n padding: env(safe-area-inset-top) 16px 0 16px;\r\n border-bottom: 1px solid var(--border);\r\n background: rgba(17, 24, 39, 0.8);\r\n backdrop-filter: blur(8px);\r\n position: sticky;\r\n top: 0;\r\n z-index: 20;\r\n gap: 12px;\r\n}\r\n\r\n.topbarLeft {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.topbarStart {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.topbarRight {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n min-width: 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.topbarRight > * {\r\n min-width: 0;\r\n}\r\n\r\n.brand {\r\n font-size: 26px;\r\n color: var(--text);\r\n text-decoration: none;\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.hamburger {\r\n background: transparent;\r\n border: none;\r\n padding: 0;\r\n width: 40px;\r\n height: 40px;\r\n border-radius: 8px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--text);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.hamburger:hover {\r\n background: rgba(255, 255, 255, 0.06);\r\n}\r\n\r\n.hamburger:focus,\r\n.hamburger:focus-visible {\r\n outline: none;\r\n box-shadow: none;\r\n}\r\n\r\n.hamburger svg {\r\n width: 28px;\r\n height: 28px;\r\n}\r\n\r\n.sidebar {\r\n border-right: 1px solid var(--border);\r\n background: #152036;\r\n padding: 24px;\r\n transition: transform 200ms ease, opacity 200ms ease;\r\n}\r\n\r\n.shell.sidebarCollapsed .sidebar {\r\n transform: translateX(-110%);\r\n opacity: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.main {\r\n overflow-y: auto;\r\n padding: 24px;\r\n padding-bottom: 96px;\r\n min-height: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n align-items: center;\r\n}\r\n\r\n.main > * {\r\n width: 100%;\r\n max-width: 1200px;\r\n min-width: 0;\r\n}\r\n\r\n.backdrop {\r\n display: none;\r\n}\r\n\r\n@media (max-width: 960px) {\r\n .backdrop {\r\n display: block;\r\n position: fixed;\r\n inset: 0;\r\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\r\n background: rgba(0, 0, 0, 0.5);\r\n z-index: 14;\r\n }\r\n\r\n .shell {\r\n --app-shell-topbar-height: 56px;\r\n grid-template-columns: 1fr;\r\n grid-template-rows: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top)) 1fr;\r\n }\r\n\r\n .shell.sidebarOpen,\r\n .shell.sidebarCollapsed {\r\n grid-template-columns: 1fr;\r\n }\r\n\r\n .sidebar {\r\n display: block;\r\n position: fixed;\r\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\r\n left: 0;\r\n bottom: 0;\r\n width: var(--app-shell-sidebar-width, 240px);\r\n max-width: 80vw;\r\n background: #152036;\r\n padding: 16px 12px;\r\n transform: translateX(-105%);\r\n z-index: 15;\r\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);\r\n }\r\n\r\n .sidebar.open {\r\n transform: translateX(0);\r\n }\r\n\r\n .topbar {\r\n padding-left: max(12px, env(safe-area-inset-left));\r\n padding-right: max(12px, env(safe-area-inset-right));\r\n gap: 10px;\r\n }\r\n\r\n .topbarLeft {\r\n gap: 10px;\r\n flex: 1;\r\n }\r\n\r\n .topbarStart {\r\n min-width: 0;\r\n }\r\n\r\n .topbarRight {\r\n gap: 6px;\r\n }\r\n\r\n .brand {\r\n font-size: 24px;\r\n max-width: 50vw;\r\n }\r\n\r\n .hamburger {\r\n width: 40px;\r\n height: 40px;\r\n border-radius: 8px;\r\n }\r\n\r\n .hamburger svg {\r\n width: 24px;\r\n height: 24px;\r\n }\r\n\r\n .main {\r\n padding: 16px;\r\n padding-bottom: 96px;\r\n }\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .topbar {\r\n gap: 8px;\r\n }\r\n\r\n .brand {\r\n font-size: 22px;\r\n max-width: 34vw;\r\n }\r\n\r\n .topbarRight {\r\n max-width: 44vw;\r\n }\r\n\r\n .main {\r\n padding: 12px 10px;\r\n padding-bottom: 88px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .brand {\r\n font-size: 20px;\r\n max-width: 30vw;\r\n }\r\n}\r\n",".nav {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n align-items: stretch;\r\n}\r\n\r\n.item {\r\n color: var(--text, #e2e8f0);\r\n background: transparent;\r\n border: none;\r\n box-shadow: none;\r\n padding: 10px 12px 10px 10px;\r\n border-radius: 10px;\r\n text-decoration: none;\r\n font-size: 14px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n width: 100%;\r\n justify-content: flex-start;\r\n text-align: left;\r\n box-sizing: border-box;\r\n white-space: nowrap;\r\n line-height: 1.2;\r\n transition: background 120ms ease, color 120ms ease;\r\n}\r\n\r\n.item:focus,\r\n.item:focus-visible {\r\n outline: none;\r\n box-shadow: none;\r\n}\r\n\r\n.item:hover {\r\n background: rgba(29, 43, 70, 0.55);\r\n}\r\n\r\n.item.active {\r\n background: rgba(29, 43, 70, 0.85);\r\n color: var(--text, #e2e8f0);\r\n font-weight: 700;\r\n}\r\n\r\n.icon {\r\n width: 18px;\r\n height: 18px;\r\n color: var(--muted, #94a3b8);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: 0 0 18px;\r\n vertical-align: middle;\r\n}\r\n\r\n.icon svg {\r\n width: 18px;\r\n height: 18px;\r\n display: block;\r\n stroke: currentColor;\r\n}\r\n\r\n.item.active .icon {\r\n color: var(--accent, #22d3ee);\r\n}\r\n\r\n.label {\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.badge {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n padding: 4px 8px;\r\n border-radius: 999px;\r\n border: 1px solid var(--border, #1f2937);\r\n background: rgba(255, 255, 255, 0.04);\r\n color: var(--muted, #94a3b8);\r\n font-size: 11px;\r\n letter-spacing: 0.04em;\r\n text-transform: uppercase;\r\n}\r\n\r\n@media (max-width: 960px) {\r\n .nav {\r\n gap: 6px;\r\n }\r\n\r\n .item {\r\n padding: 9px 10px 9px 8px;\r\n border-radius: 9px;\r\n font-size: 14px;\r\n gap: 6px;\r\n }\r\n\r\n .icon {\r\n width: 16px;\r\n height: 16px;\r\n flex: 0 0 16px;\r\n }\r\n\r\n .icon svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .item {\r\n padding: 8px 9px 8px 7px;\r\n font-size: 13px;\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport { type AnchorHTMLAttributes, type ReactNode } from \"react\";\r\nimport { cx } from \"../../utils/cx\";\r\nimport styles from \"./sidebar-nav.module.css\";\r\n\r\nexport type SidebarNavItem = {\r\n label: string;\r\n href: string;\r\n icon?: ReactNode;\r\n badge?: ReactNode;\r\n active?: boolean;\r\n target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\r\n rel?: AnchorHTMLAttributes<HTMLAnchorElement>[\"rel\"];\r\n onClick?: () => void;\r\n};\r\n\r\nexport type SidebarNavProps = {\r\n items: SidebarNavItem[];\r\n /** Optional path-like value used for default active matching. */\r\n currentPath?: string;\r\n /**\r\n * Custom active matcher. Defaults to prefix matching (with a special case for `/`).\r\n * If `item.active` is provided, it wins over this function.\r\n */\r\n getIsActive?: (item: SidebarNavItem, currentPath?: string) => boolean;\r\n /** Called after the item click handler (if provided). */\r\n onItemClick?: (item: SidebarNavItem) => void;\r\n className?: string;\r\n itemClassName?: string;\r\n};\r\n\r\nconst defaultIsActive = (item: SidebarNavItem, path?: string) => {\r\n if (item.active !== undefined) return item.active;\r\n if (!path) return false;\r\n if (item.href === \"/\") return path === \"/\";\r\n return path.startsWith(item.href);\r\n};\r\n\r\nexport function SidebarNav({\r\n items,\r\n currentPath,\r\n getIsActive = defaultIsActive,\r\n onItemClick,\r\n className,\r\n itemClassName,\r\n}: SidebarNavProps) {\r\n return (\r\n <nav className={cx(styles.nav, className)} aria-label=\"Sidebar navigation\">\r\n {items.map((item) => {\r\n const active = getIsActive(item, currentPath);\r\n const rel = item.rel ?? (item.target === \"_blank\" ? \"noreferrer\" : undefined);\r\n\r\n return (\r\n <a\r\n key={item.href}\r\n className={cx(styles.item, active && styles.active, itemClassName)}\r\n href={item.href}\r\n target={item.target}\r\n rel={rel}\r\n aria-current={active ? \"page\" : undefined}\r\n onClick={() => {\r\n item.onClick?.();\r\n onItemClick?.(item);\r\n }}\r\n >\r\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\r\n <span className={styles.label}>{item.label}</span>\r\n {item.badge && <span className={styles.badge}>{item.badge}</span>}\r\n </a>\r\n );\r\n })}\r\n </nav>\r\n );\r\n}\r\n"],"mappings":"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","names":["jsx","jsx","jsx","jsxs","useRef","jsx","jsxs","useRef","useState","useRef","useEffect","jsx","jsxs","useState","useRef","useEffect","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/cx.ts","../src/components/button/button.module.css","../src/components/button/Button.tsx","../src/components/card/card.module.css","../src/components/card/Card.tsx","../src/components/pill/pill.module.css","../src/components/pill/Pill.tsx","../src/components/modal/Modal.tsx","../src/components/modal/modal.module.css","../src/components/toast/ToastContext.tsx","../src/components/toast/toast.module.css","../src/components/dropdown/Dropdown.tsx","../src/components/dropdown/dropdown.module.css","../src/components/app-shell/AppShell.tsx","../src/components/app-shell/app-shell.module.css","../src/components/sidebar-nav/sidebar-nav.module.css","../src/components/sidebar-nav/SidebarNav.tsx"],"sourcesContent":["export function cx(...values: Array<string | false | null | undefined>): string {\n return values.filter(Boolean).join(\" \");\n}\n",".button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font-family: inherit;\n font-weight: 600;\n border-radius: 8px;\n border: none;\n cursor: pointer;\n text-decoration: none;\n transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s;\n white-space: nowrap;\n}\n\n.button:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Sizes */\n.size-sm {\n font-size: 0.82rem;\n padding: 6px 14px;\n}\n\n.size-md {\n font-size: 0.95rem;\n padding: 10px 22px;\n}\n\n.size-lg {\n font-size: 1rem;\n padding: 12px 28px;\n}\n\n/* Variants */\n.variant-primary {\n background: var(--ts-btn-primary-bg, var(--accent, #22d3ee));\n color: var(--ts-btn-primary-text, #0f172a);\n border: 1px solid transparent;\n}\n\n.variant-primary:hover:not(:disabled) {\n opacity: 0.88;\n}\n\n.variant-secondary {\n background: var(--ts-btn-secondary-bg, rgba(255, 255, 255, 0.06));\n color: var(--ts-btn-secondary-text, var(--text, #e2e8f0));\n border: 1px solid var(--ts-btn-secondary-border, var(--border, #1f2937));\n}\n\n.variant-secondary:hover:not(:disabled) {\n background: var(--ts-btn-secondary-hover-bg, rgba(255, 255, 255, 0.1));\n}\n\n.variant-outline {\n background: transparent;\n color: var(--ts-btn-outline-text, var(--text, #e2e8f0));\n border: 1px solid var(--ts-btn-outline-border, var(--border, #1f2937));\n}\n\n.variant-outline:hover:not(:disabled) {\n border-color: var(--ts-btn-outline-hover-border, var(--accent, #22d3ee));\n color: var(--ts-btn-outline-hover-text, var(--accent, #22d3ee));\n}\n\n.variant-ghost {\n background: transparent;\n color: var(--ts-btn-ghost-text, var(--muted, #94a3b8));\n border: 1px solid transparent;\n padding-left: 8px;\n padding-right: 8px;\n}\n\n.variant-ghost:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.05);\n color: var(--text, #e2e8f0);\n}\n","import type { ButtonHTMLAttributes, AnchorHTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./button.module.css\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\ntype BaseProps = {\n variant?: ButtonVariant;\n size?: ButtonSize;\n className?: string;\n children?: React.ReactNode;\n};\n\ntype AsButton = BaseProps &\n ButtonHTMLAttributes<HTMLButtonElement> & { as?: \"button\" };\n\ntype AsAnchor = BaseProps &\n AnchorHTMLAttributes<HTMLAnchorElement> & { as: \"a\" };\n\nexport type ButtonProps = AsButton | AsAnchor;\n\nexport function Button({\n as,\n variant = \"primary\",\n size = \"md\",\n className,\n children,\n ...rest\n}: ButtonProps) {\n const classes = cx(\n styles.button,\n styles[`variant-${variant}`],\n styles[`size-${size}`],\n className,\n );\n\n if (as === \"a\") {\n return (\n <a className={classes} {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}>\n {children}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n className={classes}\n {...(rest as ButtonHTMLAttributes<HTMLButtonElement>)}\n >\n {children}\n </button>\n );\n}\n",".card {\n position: relative;\n overflow: visible;\n border-radius: var(--ts-card-radius, 12px);\n border: 1px solid var(--ts-card-border, var(--border, #1f2937));\n background: var(--ts-card-bg, var(--panel, #111827));\n color: var(--ts-card-fg, var(--text, #e2e8f0));\n box-shadow: var(--ts-card-shadow, 0 16px 36px rgba(0, 0, 0, 0.28));\n padding: var(--ts-card-padding, 16px);\n transition:\n transform 140ms ease,\n box-shadow 140ms ease,\n border-color 140ms ease,\n background-color 140ms ease;\n}\n\n.tone-default {\n --ts-card-bg: var(--panel, #111827);\n --ts-card-border: var(--border, #1f2937);\n --ts-card-shadow: 0 16px 36px rgba(0, 0, 0, 0.28);\n}\n\n.tone-muted {\n --ts-card-bg: var(--ts-card-muted-bg, rgba(255, 255, 255, 0.02));\n --ts-card-border: var(--ts-card-muted-border, rgba(255, 255, 255, 0.06));\n --ts-card-shadow: 0 10px 26px rgba(0, 0, 0, 0.22);\n}\n\n.tone-contrast {\n --ts-card-bg: var(--ts-card-contrast-bg, #0b1224);\n --ts-card-border: var(--ts-card-contrast-border, rgba(255, 255, 255, 0.1));\n --ts-card-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);\n}\n\n.interactive {\n cursor: default;\n}\n\n.interactive:hover {\n transform: translateY(-1px);\n box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);\n border-color: var(--ts-card-hover-border, rgba(34, 211, 238, 0.4));\n}\n\n.interactive:focus-within {\n outline: 2px solid var(--ts-card-hover-border, rgba(34, 211, 238, 0.45));\n outline-offset: 2px;\n}\n\n.padding-none {\n --ts-card-padding: 0;\n}\n\n.padding-sm {\n --ts-card-padding: 10px;\n}\n\n.padding-md {\n --ts-card-padding: 16px;\n}\n\n.padding-lg {\n --ts-card-padding: 20px;\n}\n","/**\n * Lightweight container component used for panels across the app.\n *\n * @remarks\n * Supports tone variants, padding presets, and an optional interactive affordance.\n *\n * @param props.as - Semantic element to render (defaults to `div`).\n * @param props.tone - Visual tone variant.\n * @param props.padding - Padding preset.\n * @param props.interactive - Enables hover/focus affordance.\n */\nimport type { HTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./card.module.css\";\n\nexport type CardTone = \"default\" | \"muted\" | \"contrast\";\nexport type CardPadding = \"none\" | \"sm\" | \"md\" | \"lg\";\n\ntype CardElement = \"div\" | \"section\" | \"article\";\n\nexport type CardProps = HTMLAttributes<HTMLElement> & {\n /** Optional semantic element type. Defaults to `div`. */\n as?: CardElement;\n /** Visual tone; drives background/border CSS vars. */\n tone?: CardTone;\n /** Padding preset; maps to CSS variables so consumers can override globally. */\n padding?: CardPadding;\n /** Adds hover/focus affordance (lift + outline). */\n interactive?: boolean;\n};\n\nexport function Card({\n as,\n tone = \"default\",\n padding = \"md\",\n interactive = false,\n className,\n children,\n ...rest\n}: CardProps) {\n const Component: CardElement = as ?? \"div\";\n const toneClass = tone !== \"default\" ? styles[`tone-${tone}`] : null;\n const classes = cx(\n styles.card,\n toneClass,\n styles[`padding-${padding}`],\n interactive && styles.interactive,\n className,\n );\n\n return (\n <Component className={classes} {...rest}>\n {children}\n </Component>\n );\n}\n",".pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n border: 1px solid var(--ts-pill-border, var(--border, #1f2937));\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n line-height: 1.2;\n white-space: nowrap;\n}\n\n.size-sm {\n padding: 3px 8px;\n font-size: 11px;\n}\n\n.size-md {\n padding: 4px 10px;\n}\n\n.tone-neutral {\n background: var(--ts-pill-bg, rgba(255, 255, 255, 0.04));\n border-color: var(--ts-pill-border, var(--border, #1f2937));\n color: var(--ts-pill-fg, var(--muted, #94a3b8));\n}\n\n.tone-success {\n color: #22c55e;\n border-color: rgba(34, 197, 94, 0.45);\n background: rgba(34, 197, 94, 0.12);\n}\n\n.tone-warning {\n color: #f59e0b;\n border-color: rgba(245, 158, 11, 0.45);\n background: rgba(245, 158, 11, 0.12);\n}\n\n.tone-info {\n color: #22d3ee;\n border-color: rgba(34, 211, 238, 0.5);\n background: rgba(34, 211, 238, 0.12);\n}\n\n.tone-danger {\n color: #f87171;\n border-color: rgba(248, 113, 113, 0.45);\n background: rgba(248, 113, 113, 0.12);\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n}\n\n.content {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n","/**\n * Compact label component for status chips and tags.\n *\n * @remarks\n * Supports tone and size presets, and can render any inline element.\n *\n * @param props.as - Element to render (defaults to `span`).\n * @param props.tone - Visual tone variant.\n * @param props.size - Size preset.\n * @param props.icon - Optional leading icon.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./pill.module.css\";\n\nexport type PillTone = \"neutral\" | \"success\" | \"warning\" | \"info\" | \"danger\";\nexport type PillSize = \"sm\" | \"md\";\n\ntype PillElement = \"span\" | \"div\" | \"button\";\n\nexport type PillProps = HTMLAttributes<HTMLElement> & {\n /** Optional rendered element; defaults to `span`. */\n as?: PillElement;\n /** Visual tone; adjusts color and border. */\n tone?: PillTone;\n /** Size preset. */\n size?: PillSize;\n /** Leading icon node (not focusable). */\n icon?: ReactNode;\n};\n\nexport function Pill({\n as,\n tone = \"neutral\",\n size = \"md\",\n icon,\n className,\n children,\n ...rest\n}: PillProps) {\n const Component: PillElement = as ?? \"span\";\n const classes = cx(styles.pill, styles[`tone-${tone}`], styles[`size-${size}`], className);\n\n return (\n <Component className={classes} {...rest}>\n {icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span className={styles.content}>{children}</span>\n </Component>\n );\n}\n","\"use client\";\n\nimport { useRef, type ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./modal.module.css\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\";\n\nexport type ModalProps = {\n open: boolean;\n onClose: () => void;\n title: string;\n subtitle?: string;\n size?: ModalSize;\n /** Content between the header and footer */\n children: ReactNode;\n /** Rendered inside the footer row — typically action buttons */\n footer?: ReactNode;\n};\n\nexport function Modal({ open, onClose, title, subtitle, size = \"md\", children, footer }: ModalProps) {\n const mouseDownOnBackdrop = useRef(false);\n\n if (!open) return null;\n\n return (\n <div\n className={styles.backdrop}\n onMouseDown={(e) => { mouseDownOnBackdrop.current = e.target === e.currentTarget; }}\n onMouseUp={(e) => {\n if (mouseDownOnBackdrop.current && e.target === e.currentTarget) onClose();\n mouseDownOnBackdrop.current = false;\n }}\n >\n <div className={cx(styles.modal, styles[`size-${size}`])}>\n <div className={styles.header}>\n <div className={styles.titles}>\n <div className={styles.title}>{title}</div>\n {subtitle && <div className={styles.subtitle}>{subtitle}</div>}\n </div>\n <button className={styles.closeButton} onClick={onClose} aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n <div className={styles.body}>{children}</div>\n\n {footer && <div className={styles.footer}>{footer}</div>}\n </div>\n </div>\n );\n}\n",".backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.55);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n z-index: 100;\n}\n\n.modal {\n background: #0f172a;\n border: 1px solid var(--border, #1f2937);\n border-radius: 14px;\n padding: 24px;\n width: min(500px, 100%);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n\n/* Size variants */\n.size-sm { width: min(380px, 100%); }\n.size-md { width: min(500px, 100%); }\n.size-lg { width: min(640px, 100%); }\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.titles {\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.title {\n font-weight: 700;\n font-size: 16px;\n color: var(--text, #e2e8f0);\n line-height: 1.3;\n}\n\n.subtitle {\n font-size: 13px;\n color: var(--muted, #94a3b8);\n line-height: 1.4;\n}\n\n.closeButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex-shrink: 0;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: var(--muted, #94a3b8);\n cursor: pointer;\n transition: background 0.12s, color 0.12s;\n padding: 0;\n}\n\n.closeButton:hover {\n background: rgba(255, 255, 255, 0.07);\n color: var(--text, #e2e8f0);\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.footer {\n display: flex;\n gap: 8px;\n margin-top: 20px;\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport type {\n Toast,\n ToastConfig,\n ToastContextValue,\n ToastOptions,\n ToastPosition,\n ToastType,\n} from \"./types\";\nimport styles from \"./toast.module.css\";\n\n/** Default provider configuration. */\nconst DEFAULT_CONFIG: Required<ToastConfig> = {\n position: \"top-right\",\n maxToasts: 5,\n defaultDuration: 4000,\n pauseOnHover: true,\n pauseOnFocusLoss: true,\n};\n\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\n\nlet toastIdCounter = 0;\nconst generateToastId = () => `toast-${++toastIdCounter}-${Date.now()}`;\n\n/**\n * Toast notification context provider.\n *\n * @remarks\n * Wrap your app (or a section) to enable `useToast` calls. Supports configurable placement,\n * maximum visible toasts, and pause behavior on hover or window blur.\n *\n * @param props.children - React subtree that can consume the toast context.\n * @param props.config - Optional provider configuration overrides.\n */\nexport function ToastProvider({\n children,\n config,\n}: {\n children: ReactNode;\n config?: ToastConfig;\n}) {\n const [toasts, setToasts] = useState<Toast[]>([]);\n const [isPaused, setIsPaused] = useState(false);\n const merged = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);\n\n const push = useCallback(\n (message: string, options: ToastOptions = {}) => {\n const id = generateToastId();\n setToasts((prev) => {\n const next: Toast[] = [\n ...prev,\n {\n id,\n message,\n type: options.type ?? \"info\",\n duration: options.duration ?? (options.type === \"error\" ? 6000 : merged.defaultDuration),\n dismissible: options.dismissible ?? true,\n action: options.action,\n },\n ];\n if (next.length > merged.maxToasts) next.shift();\n return next;\n });\n return id;\n },\n [merged.defaultDuration, merged.maxToasts],\n );\n\n const success = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"success\" }),\n [push],\n );\n const error = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) =>\n push(message, { ...options, type: \"error\", duration: options?.duration ?? 6000 }),\n [push],\n );\n const warning = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"warning\" }),\n [push],\n );\n const info = useCallback(\n (message: string, options?: Omit<ToastOptions, \"type\">) => push(message, { ...options, type: \"info\" }),\n [push],\n );\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, []);\n\n const dismissAll = useCallback(() => setToasts([]), []);\n\n useEffect(() => {\n if (!merged.pauseOnFocusLoss) return;\n const handleVisibility = () => setIsPaused(document.visibilityState !== \"visible\");\n document.addEventListener(\"visibilitychange\", handleVisibility);\n return () => document.removeEventListener(\"visibilitychange\", handleVisibility);\n }, [merged.pauseOnFocusLoss]);\n\n const value = useMemo<ToastContextValue>(\n () => ({ toasts, push, success, error, warning, info, dismiss, dismissAll }),\n [toasts, push, success, error, warning, info, dismiss, dismissAll],\n );\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n <ToastContainer\n toasts={toasts}\n position={merged.position}\n pauseOnHover={merged.pauseOnHover}\n isPaused={isPaused}\n onDismiss={dismiss}\n onPauseChange={setIsPaused}\n />\n </ToastContext.Provider>\n );\n}\n\n/**\n * Hook to access the toast API.\n *\n * @remarks\n * Exposes `push`, intent helpers (`success`, `error`, `warning`, `info`), and dismissal helpers.\n * Must be called within a `ToastProvider`.\n *\n * @throws Error if used outside of a `ToastProvider`.\n */\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used within a ToastProvider\");\n return ctx;\n}\n\n/** Renders the positioned toast stack. */\nfunction ToastContainer({\n toasts,\n position,\n pauseOnHover,\n isPaused,\n onDismiss,\n onPauseChange,\n}: {\n toasts: Toast[];\n position: ToastPosition;\n pauseOnHover: boolean;\n isPaused: boolean;\n onDismiss: (id: string) => void;\n onPauseChange: (paused: boolean) => void;\n}) {\n const posClass = (() => {\n switch (position) {\n case \"top-left\":\n return styles.topLeft;\n case \"top-center\":\n return styles.topCenter;\n case \"bottom-right\":\n return styles.bottomRight;\n case \"bottom-left\":\n return styles.bottomLeft;\n case \"bottom-center\":\n return styles.bottomCenter;\n case \"top-right\":\n default:\n return styles.topRight;\n }\n })();\n\n return (\n <div\n className={cx(styles.stack, posClass)}\n role=\"presentation\"\n onMouseEnter={() => pauseOnHover && onPauseChange(true)}\n onMouseLeave={() => pauseOnHover && onPauseChange(false)}\n >\n {toasts.map((toast) => (\n <ToastItem key={toast.id} toast={toast} isPaused={isPaused} onDismiss={onDismiss} />\n ))}\n </div>\n );\n}\n\n/** Individual toast item with timers and actions. */\nfunction ToastItem({\n toast,\n isPaused,\n onDismiss,\n}: {\n toast: Toast;\n isPaused: boolean;\n onDismiss: (id: string) => void;\n}) {\n const [exiting, setExiting] = useState(false);\n const timerRef = useRef<number | null>(null);\n const startRef = useRef<number>(0);\n const remainingRef = useRef<number>(toast.duration ?? 0);\n\n const palette = getPalette(toast.type);\n const styleVars: CSSProperties = {\n [\"--toast-bg\" as any]: palette.background,\n [\"--toast-border\" as any]: palette.border,\n [\"--toast-text\" as any]: palette.text,\n [\"--toast-button-bg\" as any]: palette.buttonBg,\n [\"--toast-button-border\" as any]: palette.buttonBorder,\n [\"--toast-action-bg\" as any]: palette.actionBg,\n [\"--toast-action-border\" as any]: palette.actionBorder,\n };\n\n const stopTimer = () => {\n if (timerRef.current) {\n window.clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const triggerDismiss = useCallback(() => {\n setExiting(true);\n stopTimer();\n window.setTimeout(() => onDismiss(toast.id), 160);\n }, [onDismiss, toast.id]);\n\n const schedule = useCallback(\n (delay: number) => {\n if (!delay || delay <= 0) {\n triggerDismiss();\n return;\n }\n startRef.current = performance.now();\n stopTimer();\n timerRef.current = window.setTimeout(() => triggerDismiss(), delay);\n },\n [triggerDismiss],\n );\n\n useEffect(() => {\n if (!toast.duration || toast.duration <= 0) return undefined;\n schedule(toast.duration);\n return stopTimer;\n }, [schedule, toast.duration]);\n\n useEffect(() => {\n if (!toast.duration || toast.duration <= 0) return;\n if (isPaused) {\n const elapsed = performance.now() - startRef.current;\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\n stopTimer();\n } else {\n schedule(remainingRef.current);\n }\n }, [isPaused, schedule, toast.duration]);\n\n const icon = getIcon(toast.type);\n\n return (\n <div className={cx(styles.toast, exiting && styles.exit)} style={styleVars} role=\"status\" aria-live=\"polite\">\n <span className={styles.icon} aria-hidden>\n {icon}\n </span>\n <div className={styles.body}>\n <div className={styles.message}>{toast.message}</div>\n {toast.action && (\n <div className={styles.actions}>\n <button\n type=\"button\"\n className={styles.actionButton}\n onClick={() => {\n toast.action?.onClick();\n triggerDismiss();\n }}\n >\n {toast.action.label}\n </button>\n </div>\n )}\n </div>\n {toast.dismissible !== false && (\n <button\n type=\"button\"\n className={styles.closeButton}\n onClick={triggerDismiss}\n aria-label=\"Dismiss notification\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden>\n <path\n d=\"M11 3L3 11M3 3l8 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n}\n\nfunction getPalette(type: ToastType) {\n switch (type) {\n case \"success\":\n return {\n background: \"#22c55e\",\n border: \"#16a34a\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n case \"error\":\n return {\n background: \"#f87171\",\n border: \"#ef4444\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n case \"warning\":\n return {\n background: \"#fbbf24\",\n border: \"#f59e0b\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n case \"info\":\n default:\n return {\n background: \"#38bdf8\",\n border: \"#0ea5e9\",\n text: \"#0b1224\",\n buttonBg: \"rgba(0, 0, 0, 0.08)\",\n buttonBorder: \"rgba(0, 0, 0, 0.2)\",\n actionBg: \"rgba(0, 0, 0, 0.1)\",\n actionBorder: \"rgba(0, 0, 0, 0.2)\",\n };\n }\n}\n\nfunction getIcon(type: ToastType) {\n switch (type) {\n case \"success\":\n return \"OK\";\n case \"error\":\n return \"X\";\n case \"warning\":\n return \"!\";\n case \"info\":\n default:\n return \"i\";\n }\n}\n",".stack {\n position: fixed;\n z-index: 2147483000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n}\n\n.topRight {\n top: 16px;\n right: 16px;\n align-items: flex-end;\n}\n\n.topLeft {\n top: 16px;\n left: 16px;\n align-items: flex-start;\n}\n\n.topCenter {\n top: 16px;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.bottomRight {\n bottom: 16px;\n right: 16px;\n align-items: flex-end;\n}\n\n.bottomLeft {\n bottom: 16px;\n left: 16px;\n align-items: flex-start;\n}\n\n.bottomCenter {\n bottom: 16px;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.toast {\n pointer-events: auto;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 280px;\n max-width: min(420px, calc(100vw - 32px));\n padding: 12px 14px;\n border-radius: 10px;\n border: 1px solid var(--toast-border, #1f2937);\n background: var(--toast-bg, #111827);\n color: var(--toast-text, #e2e8f0);\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\n animation: toastSlideIn 180ms ease-out;\n}\n\n.toast.exit {\n animation: toastSlideOut 160ms ease-in forwards;\n}\n\n.icon {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n}\n\n.body {\n flex: 1;\n min-width: 0;\n display: grid;\n gap: 6px;\n}\n\n.message {\n word-break: break-word;\n font-size: 14px;\n line-height: 1.4;\n}\n\n.actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.actionButton {\n padding: 5px 10px;\n font-size: 12px;\n font-weight: 600;\n border-radius: 6px;\n border: 1px solid var(--toast-action-border, rgba(0, 0, 0, 0.2));\n background: var(--toast-action-bg, rgba(0, 0, 0, 0.1));\n color: var(--toast-text, #e2e8f0);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.actionButton:hover {\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.15));\n}\n\n.closeButton {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n margin: -2px -4px -2px 0;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--toast-text, #e2e8f0);\n opacity: 0.6;\n cursor: pointer;\n transition: opacity 120ms ease, background 120ms ease;\n}\n\n.closeButton:hover {\n opacity: 1;\n background: var(--toast-button-bg, rgba(0, 0, 0, 0.1));\n}\n\n@keyframes toastSlideIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideOut {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(-6px);\n }\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./dropdown.module.css\";\n\nexport interface DropdownOption {\n label: string;\n value: string;\n}\n\nexport interface DropdownProps {\n /** List of options to display in the menu. */\n options: DropdownOption[];\n /** Currently selected value. Use empty string for \"no selection\". */\n value: string;\n /** Called when the user selects an option. */\n onChange: (value: string) => void;\n /** Label shown when no option is selected. Defaults to \"All\". */\n placeholder?: string;\n /** Additional class name for the wrapper element. */\n className?: string;\n /** Whether to show the placeholder as a clearable option. Defaults to true. */\n allowClear?: boolean;\n /** Associates the trigger button with an external label element via its id. */\n \"aria-labelledby\"?: string;\n /** Provides an accessible label directly on the trigger button. */\n \"aria-label\"?: string;\n}\n\nexport function Dropdown({\n options,\n value,\n onChange,\n placeholder = \"All\",\n className,\n allowClear = true,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-label\": ariaLabel,\n}: DropdownProps) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n const selected = options.find((o) => o.value === value);\n const isActive = allowClear && value !== \"\";\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n return (\n <div className={cx(styles.wrapper, className)} ref={ref}>\n <button\n type=\"button\"\n className={cx(styles.trigger, isActive && styles[\"trigger-active\"])}\n onClick={() => setOpen((o) => !o)}\n aria-labelledby={ariaLabelledBy}\n aria-label={ariaLabel}\n >\n {selected ? selected.label : placeholder}\n <span className={cx(styles.chevron, open && styles[\"chevron-open\"])}>\n <svg viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\">\n <path d=\"M2 3.5L5 6.5L8 3.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n </button>\n\n {open && (\n <div className={styles.menu}>\n {allowClear && (\n <button\n type=\"button\"\n className={cx(styles.option, value === \"\" && styles[\"option-selected\"])}\n onClick={() => { onChange(\"\"); setOpen(false); }}\n >\n {placeholder}\n </button>\n )}\n {options.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className={cx(styles.option, value === opt.value && styles[\"option-selected\"])}\n onClick={() => { onChange(opt.value); setOpen(false); }}\n >\n {opt.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n",".wrapper {\n position: relative;\n display: inline-block;\n}\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px 6px 14px;\n background: var(--ts-dropdown-bg, var(--panel, #111827));\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\n border-radius: 8px;\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: border-color 0.15s;\n user-select: none;\n}\n\n.trigger:hover {\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n}\n\n.trigger-active {\n border-color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n}\n\n.chevron {\n width: 10px;\n height: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.15s;\n color: var(--muted, #94a3b8);\n flex-shrink: 0;\n}\n\n.chevron-open {\n transform: rotate(180deg);\n}\n\n.menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n min-width: 100%;\n background: var(--ts-dropdown-bg, var(--panel, #111827));\n border: 1px solid var(--ts-dropdown-border, var(--border, #1f2937));\n border-radius: 10px;\n padding: 4px;\n z-index: 50;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n animation: dropdownFadeIn 0.1s ease;\n}\n\n@keyframes dropdownFadeIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.option {\n display: block;\n width: 100%;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 0.85rem;\n font-weight: 500;\n color: var(--muted, #94a3b8);\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n white-space: nowrap;\n transition: background 0.1s, color 0.1s;\n}\n\n.option:hover {\n background: rgba(255, 255, 255, 0.05);\n color: var(--ts-dropdown-text, var(--text, #e2e8f0));\n}\n\n.option-selected {\n color: var(--ts-dropdown-accent, var(--accent, #22d3ee));\n background: rgba(34, 211, 238, 0.08);\n}\n","\"use client\";\n\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./app-shell.module.css\";\n\nconst DESKTOP_BREAKPOINT = 960;\n\nfunction getIsDesktop() {\n if (typeof window === \"undefined\") return false;\n return window.innerWidth >= DESKTOP_BREAKPOINT;\n}\n\nexport type AppShellProps = {\n /** Primary page content rendered in the main area. */\n children: ReactNode;\n /** Sidebar navigation or custom content. */\n sidebar: ReactNode;\n /** Brand element rendered next to the hamburger (text or JSX). */\n brand?: ReactNode;\n /** Optional brand href; when provided the brand renders as an anchor. */\n brandHref?: string;\n /** Optional content after the brand on the left side of the top bar. */\n topbarStart?: ReactNode;\n /** Optional content aligned to the right side of the top bar. */\n topbarEnd?: ReactNode;\n /** Custom class names for styling overrides. */\n className?: string;\n sidebarClassName?: string;\n topbarClassName?: string;\n mainClassName?: string;\n /** Sets the sidebar width (e.g., `260`, `\"18rem\"`). */\n sidebarWidth?: number | string;\n /**\n * Closes the sidebar on mobile whenever this value changes.\n * Useful for reacting to route/pathname changes.\n */\n closeSidebarOnChangeKey?: unknown;\n /** Label for the hamburger button (aria-label). */\n hamburgerLabel?: string;\n /** Optional callback fired whenever the sidebar open state changes. */\n onSidebarToggle?: (open: boolean) => void;\n};\n\n/**\n * Responsive application shell with a collapsible sidebar and sticky top bar.\n *\n * - Sidebar opens by default on desktop, collapses on mobile.\n * - Closes on outside click/scroll/touch when in mobile mode.\n * - Provides optional hook to close the sidebar when a prop value changes\n * (e.g., route transitions).\n */\nexport function AppShell({\n children,\n sidebar,\n brand,\n brandHref,\n topbarStart,\n topbarEnd,\n className,\n sidebarClassName,\n topbarClassName,\n mainClassName,\n sidebarWidth,\n closeSidebarOnChangeKey,\n hamburgerLabel = \"Toggle navigation\",\n onSidebarToggle,\n}: AppShellProps) {\n const [isDesktop, setIsDesktop] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const prevIsDesktopRef = useRef(false);\n const closeKeyRef = useRef(closeSidebarOnChangeKey);\n\n const sidebarRef = useRef<HTMLElement | null>(null);\n const hamburgerRef = useRef<HTMLButtonElement | null>(null);\n const mainRef = useRef<HTMLElement | null>(null);\n const sidebarId = useId();\n\n useEffect(() => {\n const desktop = getIsDesktop();\n setIsDesktop(desktop);\n setSidebarOpen(desktop);\n prevIsDesktopRef.current = desktop;\n\n const handleResize = () => {\n const nowDesktop = getIsDesktop();\n setIsDesktop(nowDesktop);\n if (nowDesktop !== prevIsDesktopRef.current) {\n setSidebarOpen(nowDesktop);\n prevIsDesktopRef.current = nowDesktop;\n }\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n // Close the sidebar when clicking outside or scrolling on mobile.\n useEffect(() => {\n if (isDesktop || !sidebarOpen) return;\n\n const mainElement = mainRef.current;\n const closeSidebar = () => setSidebarOpen(false);\n\n const onPointerDown = (e: PointerEvent) => {\n const target = e.target as Node | null;\n if (!target) return;\n if (sidebarRef.current?.contains(target)) return;\n if (hamburgerRef.current?.contains(target)) return;\n closeSidebar();\n };\n\n const timeoutId = window.setTimeout(() => {\n document.addEventListener(\"pointerdown\", onPointerDown);\n window.addEventListener(\"scroll\", closeSidebar, { passive: true });\n mainElement?.addEventListener(\"scroll\", closeSidebar, { passive: true });\n document.addEventListener(\"touchmove\", closeSidebar, { passive: true });\n }, 10);\n\n return () => {\n window.clearTimeout(timeoutId);\n document.removeEventListener(\"pointerdown\", onPointerDown);\n window.removeEventListener(\"scroll\", closeSidebar);\n mainElement?.removeEventListener(\"scroll\", closeSidebar);\n document.removeEventListener(\"touchmove\", closeSidebar);\n };\n }, [sidebarOpen, isDesktop]);\n\n // Allow consumers to request a mobile sidebar close when a value changes (e.g., pathname).\n useEffect(() => {\n if (!isDesktop && closeKeyRef.current !== closeSidebarOnChangeKey) {\n setSidebarOpen(false);\n }\n closeKeyRef.current = closeSidebarOnChangeKey;\n }, [closeSidebarOnChangeKey, isDesktop]);\n\n useEffect(() => {\n onSidebarToggle?.(sidebarOpen);\n }, [sidebarOpen, onSidebarToggle]);\n\n const toggleSidebar = () => setSidebarOpen((open) => !open);\n\n const sidebarWidthValue =\n sidebarWidth === undefined\n ? undefined\n : typeof sidebarWidth === \"number\"\n ? `${sidebarWidth}px`\n : sidebarWidth;\n\n const shellStyle: CSSProperties | undefined = sidebarWidthValue\n ? { [\"--app-shell-sidebar-width\" as string]: sidebarWidthValue }\n : undefined;\n\n const shellClasses = cx(\n styles.shell,\n sidebarOpen ? styles.sidebarOpen : styles.sidebarCollapsed,\n className,\n );\n\n const sidebarClasses = cx(styles.sidebar, sidebarOpen && styles.open, sidebarClassName);\n\n return (\n <div\n className={shellClasses}\n style={shellStyle}\n data-app-shell\n data-desktop={isDesktop ? \"true\" : \"false\"}\n data-sidebar-open={sidebarOpen ? \"true\" : \"false\"}\n >\n <header className={cx(styles.topbar, topbarClassName)}>\n <div className={styles.topbarLeft}>\n <button\n ref={hamburgerRef}\n type=\"button\"\n className={styles.hamburger}\n onClick={toggleSidebar}\n aria-label={hamburgerLabel}\n aria-expanded={sidebarOpen}\n aria-controls={sidebarId}\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n </button>\n {brand &&\n (brandHref ? (\n <a className={styles.brand} href={brandHref}>\n {brand}\n </a>\n ) : (\n <div className={styles.brand}>{brand}</div>\n ))}\n {topbarStart && <div className={styles.topbarStart}>{topbarStart}</div>}\n </div>\n <div className={styles.topbarRight}>{topbarEnd}</div>\n </header>\n {!isDesktop && sidebarOpen && (\n <div className={styles.backdrop} onClick={() => setSidebarOpen(false)} onTouchStart={() => setSidebarOpen(false)} aria-hidden=\"true\" />\n )}\n <aside ref={sidebarRef} id={sidebarId} className={sidebarClasses} aria-label=\"Sidebar navigation\">\n {sidebar}\n </aside>\n <main ref={mainRef} className={cx(styles.main, mainClassName)}>\n {children}\n </main>\n </div>\n );\n}\n",".shell {\n display: grid;\n grid-template-rows: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top)) 1fr;\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\n min-height: 100vh;\n min-height: 100dvh;\n transition: grid-template-columns 200ms ease;\n}\n\n.shell.sidebarOpen {\n grid-template-columns: var(--app-shell-sidebar-width, 240px) 1fr;\n}\n\n.shell.sidebarCollapsed {\n grid-template-columns: 0 1fr;\n}\n\n.topbar {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: calc(var(--app-shell-topbar-height, 64px) + env(safe-area-inset-top));\n padding: env(safe-area-inset-top) 16px 0 16px;\n border-bottom: 1px solid var(--border);\n background: rgba(17, 24, 39, 0.8);\n backdrop-filter: blur(8px);\n position: sticky;\n top: 0;\n z-index: 20;\n gap: 12px;\n}\n\n.topbarLeft {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.topbarStart {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n\n.topbarRight {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 0;\n}\n\n.topbarRight > * {\n min-width: 0;\n}\n\n.brand {\n font-size: 26px;\n color: var(--text);\n text-decoration: none;\n display: flex;\n align-items: center;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.hamburger {\n background: transparent;\n border: none;\n padding: 0;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.hamburger:hover {\n background: rgba(255, 255, 255, 0.06);\n}\n\n.hamburger:focus,\n.hamburger:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.hamburger svg {\n width: 28px;\n height: 28px;\n}\n\n.sidebar {\n border-right: 1px solid var(--border);\n background: #152036;\n padding: 24px;\n transition: transform 200ms ease, opacity 200ms ease;\n}\n\n.shell.sidebarCollapsed .sidebar {\n transform: translateX(-110%);\n opacity: 0;\n pointer-events: none;\n}\n\n.main {\n overflow-y: auto;\n padding: 24px;\n padding-bottom: 96px;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 16px;\n align-items: center;\n}\n\n.main > * {\n width: 100%;\n max-width: 1200px;\n min-width: 0;\n}\n\n.backdrop {\n display: none;\n}\n\n@media (max-width: 960px) {\n .backdrop {\n display: block;\n position: fixed;\n inset: 0;\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\n background: rgba(0, 0, 0, 0.5);\n z-index: 14;\n }\n\n .shell {\n --app-shell-topbar-height: 56px;\n grid-template-columns: 1fr;\n grid-template-rows: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top)) 1fr;\n }\n\n .shell.sidebarOpen,\n .shell.sidebarCollapsed {\n grid-template-columns: 1fr;\n }\n\n .sidebar {\n display: block;\n position: fixed;\n top: calc(var(--app-shell-topbar-height, 56px) + env(safe-area-inset-top));\n left: 0;\n bottom: 0;\n width: var(--app-shell-sidebar-width, 240px);\n max-width: 80vw;\n background: #152036;\n padding: 16px 12px;\n transform: translateX(-105%);\n z-index: 15;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);\n }\n\n .sidebar.open {\n transform: translateX(0);\n }\n\n .topbar {\n padding-left: max(12px, env(safe-area-inset-left));\n padding-right: max(12px, env(safe-area-inset-right));\n gap: 10px;\n }\n\n .topbarLeft {\n gap: 10px;\n flex: 1;\n }\n\n .topbarStart {\n min-width: 0;\n }\n\n .topbarRight {\n gap: 6px;\n }\n\n .brand {\n font-size: 24px;\n max-width: 50vw;\n }\n\n .hamburger {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n }\n\n .hamburger svg {\n width: 24px;\n height: 24px;\n }\n\n .main {\n padding: 16px;\n padding-bottom: 96px;\n }\n}\n\n@media (max-width: 640px) {\n .topbar {\n gap: 8px;\n }\n\n .brand {\n font-size: 22px;\n max-width: 34vw;\n }\n\n .topbarRight {\n max-width: 44vw;\n }\n\n .main {\n padding: 12px 10px;\n padding-bottom: 88px;\n }\n}\n\n@media (max-width: 480px) {\n .brand {\n font-size: 20px;\n max-width: 30vw;\n }\n}\n",".nav {\n display: flex;\n flex-direction: column;\n gap: 8px;\n align-items: stretch;\n}\n\n.item {\n color: var(--text, #e2e8f0);\n background: transparent;\n border: none;\n box-shadow: none;\n padding: 10px 12px 10px 10px;\n border-radius: 10px;\n text-decoration: none;\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n justify-content: flex-start;\n text-align: left;\n box-sizing: border-box;\n white-space: nowrap;\n line-height: 1.2;\n transition: background 120ms ease, color 120ms ease;\n}\n\n.item:focus,\n.item:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.item:hover {\n background: rgba(29, 43, 70, 0.55);\n}\n\n.item.active {\n background: rgba(29, 43, 70, 0.85);\n color: var(--text, #e2e8f0);\n font-weight: 700;\n}\n\n.icon {\n width: 18px;\n height: 18px;\n color: var(--muted, #94a3b8);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 18px;\n vertical-align: middle;\n}\n\n.icon svg {\n width: 18px;\n height: 18px;\n display: block;\n stroke: currentColor;\n}\n\n.item.active .icon {\n color: var(--accent, #22d3ee);\n}\n\n.label {\n flex: 1;\n min-width: 0;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 999px;\n border: 1px solid var(--border, #1f2937);\n background: rgba(255, 255, 255, 0.04);\n color: var(--muted, #94a3b8);\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n@media (max-width: 960px) {\n .nav {\n gap: 6px;\n }\n\n .item {\n padding: 9px 10px 9px 8px;\n border-radius: 9px;\n font-size: 14px;\n gap: 6px;\n }\n\n .icon {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n }\n\n .icon svg {\n width: 16px;\n height: 16px;\n }\n}\n\n@media (max-width: 480px) {\n .item {\n padding: 8px 9px 8px 7px;\n font-size: 13px;\n }\n}\n","\"use client\";\n\nimport { type AnchorHTMLAttributes, type ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx\";\nimport styles from \"./sidebar-nav.module.css\";\n\nexport type SidebarNavItem = {\n label: string;\n href: string;\n icon?: ReactNode;\n badge?: ReactNode;\n active?: boolean;\n target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\n rel?: AnchorHTMLAttributes<HTMLAnchorElement>[\"rel\"];\n onClick?: () => void;\n};\n\nexport type SidebarNavProps = {\n items: SidebarNavItem[];\n /** Optional path-like value used for default active matching. */\n currentPath?: string;\n /**\n * Custom active matcher. Defaults to prefix matching (with a special case for `/`).\n * If `item.active` is provided, it wins over this function.\n */\n getIsActive?: (item: SidebarNavItem, currentPath?: string) => boolean;\n /** Called after the item click handler (if provided). */\n onItemClick?: (item: SidebarNavItem) => void;\n className?: string;\n itemClassName?: string;\n};\n\nconst defaultIsActive = (item: SidebarNavItem, path?: string) => {\n if (item.active !== undefined) return item.active;\n if (!path) return false;\n if (item.href === \"/\") return path === \"/\";\n return path.startsWith(item.href);\n};\n\nexport function SidebarNav({\n items,\n currentPath,\n getIsActive = defaultIsActive,\n onItemClick,\n className,\n itemClassName,\n}: SidebarNavProps) {\n return (\n <nav className={cx(styles.nav, className)} aria-label=\"Sidebar navigation\">\n {items.map((item) => {\n const active = getIsActive(item, currentPath);\n const rel = item.rel ?? (item.target === \"_blank\" ? \"noreferrer\" : undefined);\n\n return (\n <a\n key={item.href}\n className={cx(styles.item, active && styles.active, itemClassName)}\n href={item.href}\n target={item.target}\n rel={rel}\n aria-current={active ? \"page\" : undefined}\n onClick={() => {\n item.onClick?.();\n onItemClick?.(item);\n }}\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n <span className={styles.label}>{item.label}</span>\n {item.badge && <span className={styles.badge}>{item.badge}</span>}\n </a>\n );\n })}\n </nav>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","jsxs","useRef","jsx","jsxs","useRef","useState","useRef","useEffect","jsx","jsxs","useState","useRef","useEffect","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomny-dev/uzi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Rapid-fire React UI components. Ship faster, build more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -24,11 +24,6 @@
|
|
|
24
24
|
"node": ">=18",
|
|
25
25
|
"pnpm": ">=8"
|
|
26
26
|
},
|
|
27
|
-
"scripts": {
|
|
28
|
-
"build": "tsup",
|
|
29
|
-
"dev": "tsup --watch",
|
|
30
|
-
"lint": "tsc --noEmit"
|
|
31
|
-
},
|
|
32
27
|
"peerDependencies": {
|
|
33
28
|
"react": "^18.0.0 || ^19.0.0",
|
|
34
29
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
@@ -38,5 +33,10 @@
|
|
|
38
33
|
"@types/react-dom": "^18.2.0",
|
|
39
34
|
"tsup": "^8.0.0",
|
|
40
35
|
"typescript": "^5.4.3"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"dev": "tsup --watch",
|
|
40
|
+
"lint": "tsc --noEmit"
|
|
41
41
|
}
|
|
42
|
-
}
|
|
42
|
+
}
|