@braedonsaunders/appkit-ui 0.3.0 → 0.4.1
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/drawer.d.ts.map +1 -1
- package/drawer.js.map +1 -1
- package/index.d.ts +2 -2
- package/index.d.ts.map +1 -1
- package/index.js.map +1 -1
- package/package.json +7 -2
- package/page-header.d.ts.map +1 -1
- package/page-header.js +1 -1
- package/page-header.js.map +1 -1
- package/search-select.d.ts.map +1 -1
- package/search-select.js +6 -3
- package/search-select.js.map +1 -1
- package/settings-layout.d.ts +8 -1
- package/settings-layout.d.ts.map +1 -1
- package/settings-layout.js +17 -5
- package/settings-layout.js.map +1 -1
- package/table.d.ts.map +1 -1
- package/table.js +0 -1
- package/table.js.map +1 -1
- package/theme-options.d.ts +30 -0
- package/theme-options.d.ts.map +1 -0
- package/theme-options.js +20 -0
- package/theme-options.js.map +1 -0
- package/theme-script.d.ts +11 -2
- package/theme-script.d.ts.map +1 -1
- package/theme-script.js +16 -4
- package/theme-script.js.map +1 -1
- package/theme.d.ts +11 -5
- package/theme.d.ts.map +1 -1
- package/theme.js +28 -17
- package/theme.js.map +1 -1
package/drawer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../src/drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../src/drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAA;AACnE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;AAgBzC,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;CACpC,CAAA;AAUD,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,qBAGA;AAcD,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC/B,yEAAyE;IACzE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;CAC5B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,WAAW,EACX,IAAW,EACX,IAAc,EACd,QAAQ,EACR,MAAM,EACN,aAAa,EACb,OAAO,EACP,aAAa,EACb,cAAc,EACd,OAAe,EACf,iBAAyB,EACzB,iBAAyB,EACzB,cAAc,GACf,EAAE,WAAW,4BAiQb;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,wBAA+B,MAAM,KAAK,IAAI,SAAe,CAAA;AAE/F,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC,GAAG;IACtF,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,qBAgB/E"}
|
package/drawer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.js","sourceRoot":"","sources":["../src/drawer.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport { cn } from './utils'\n\n// Z-INDEX SCALE (single source of truth for the ecosystem)\n//\n// sidebar : z-10\n// header : z-20\n// sticky-bars : z-30\n// dropdowns : z-40\n// drawer : z-50 (stacked/nested: z-[55])\n// floating UI : z-[60] — Popover, Select dropdown, confirm dialog\n// toast : z-70\n//\n// The drawer's top edge is `--drawer-top` (default 0). An app shell sets it to\n// its header height so drawers sit beneath the persistent header:\n// :root { --drawer-top: 3.5rem; }\n\nexport type DrawerSize = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\nexport type DrawerSide = 'left' | 'right'\n\nconst SIZE_CLASS: Record<DrawerSize, string> = {\n sm: 'w-full sm:max-w-md',\n md: 'w-full sm:max-w-xl',\n lg: 'w-full sm:max-w-2xl',\n xl: 'w-full sm:max-w-4xl',\n '2xl': 'w-full sm:max-w-6xl',\n full: 'w-full',\n}\n\n// --- Injectable labels ------------------------------------------------------\n// appkit is i18n-agnostic. Apps wrap their tree in <DrawerTextProvider> to map\n// these to next-intl / their own dictionary; standalone use gets English.\n// `translate` supports message-key titles while remaining a pass-through for\n// raw ReactNode titles.\nexport type DrawerText = {\n close: string\n fullscreen: string\n exitFullscreen: string\n translate?: (key: string) => string\n}\n\nconst DEFAULT_DRAWER_TEXT: DrawerText = {\n close: 'Close',\n fullscreen: 'Fullscreen',\n exitFullscreen: 'Exit fullscreen',\n}\n\nconst DrawerTextContext = React.createContext<DrawerText>(DEFAULT_DRAWER_TEXT)\n\nexport function DrawerTextProvider({\n value,\n children,\n}: {\n value: Partial<DrawerText>\n children: React.ReactNode\n}) {\n const merged = React.useMemo(() => ({ ...DEFAULT_DRAWER_TEXT, ...value }), [value])\n return <DrawerTextContext.Provider value={merged}>{children}</DrawerTextContext.Provider>\n}\n\nfunction useDrawerText(): DrawerText {\n return React.useContext(DrawerTextContext)\n}\n\n// Ref-counted scroll lock — nested/stacked drawers share one lock so the body\n// only unlocks when the last drawer closes.\nlet openDrawerCount = 0\nlet originalBodyOverflow: string | null = null\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nexport type DrawerProps = {\n open: boolean\n onClose: () => void\n title?: React.ReactNode\n description?: React.ReactNode\n size?: DrawerSize\n side?: DrawerSide\n children: React.ReactNode\n footer?: React.ReactNode\n /** Primary action buttons pinned into the header, before the close button. */\n headerActions?: React.ReactNode\n /** Record-detail navigation rendered directly below the title header. */\n subtabs?: React.ReactNode\n /** Override the body wrapper classes (default: scroll + px-6 py-5). */\n bodyClassName?: string\n /** Extra classes for the panel (e.g. record-type tinting). */\n panelClassName?: string\n /** Raise above another open drawer in a deliberate nested flow. */\n stacked?: boolean\n /** Open at full viewport width; the user can still collapse it. */\n initialFullscreen?: boolean\n /** Hide the fullscreen expand/collapse affordance. */\n disableFullscreen?: boolean\n /** Fires after the exit animation completes (UrlDrawer defers navigation). */\n onExitComplete?: () => void\n}\n\n/**\n * Slide-in flyout for sub-entity create/edit and detail views. Portals to body;\n * spring slide-in; backdrop fade+blur; Esc + click-out + ref-counted scroll\n * lock; focus trap + restore; a NetSuite-style expand/collapse to full viewport\n * width (animated via max-width). Fully tokenized and reduced-motion aware.\n */\nexport function Drawer({\n open,\n onClose,\n title,\n description,\n size = 'md',\n side = 'right',\n children,\n footer,\n headerActions,\n subtabs,\n bodyClassName,\n panelClassName,\n stacked = false,\n initialFullscreen = false,\n disableFullscreen = false,\n onExitComplete,\n}: DrawerProps) {\n const text = useDrawerText()\n const tr = text.translate ?? ((s: string) => s)\n const reduce = useReducedMotion()\n const [mounted, setMounted] = React.useState(false)\n React.useEffect(() => setMounted(true), [])\n\n const [fullscreen, setFullscreen] = React.useState(initialFullscreen)\n React.useEffect(() => {\n if (!open) setFullscreen(initialFullscreen)\n }, [initialFullscreen, open])\n\n const panelRef = React.useRef<HTMLElement>(null)\n const onCloseRef = React.useRef(onClose)\n React.useEffect(() => {\n onCloseRef.current = onClose\n }, [onClose])\n\n // Esc + scroll lock. Stacked-aware: a base drawer ignores Esc while a nested\n // drawer or a floating overlay is on top.\n React.useEffect(() => {\n if (!open) return\n function onKey(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n if (document.querySelector('[data-ui-overlay]')) return\n if (!stacked && document.querySelector('[data-drawer-layer=\"nested\"]')) return\n onCloseRef.current()\n }\n document.addEventListener('keydown', onKey)\n if (openDrawerCount === 0) originalBodyOverflow = document.body.style.overflow\n openDrawerCount += 1\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', onKey)\n openDrawerCount = Math.max(0, openDrawerCount - 1)\n if (openDrawerCount === 0) {\n document.body.style.overflow = originalBodyOverflow ?? ''\n originalBodyOverflow = null\n }\n }\n }, [open, stacked])\n\n // Focus management: move focus in on open, trap Tab, restore on close.\n React.useEffect(() => {\n if (!open) return\n const previouslyFocused = document.activeElement as HTMLElement | null\n const focusTimer = window.setTimeout(() => {\n if (!stacked && document.querySelector('[data-drawer-layer=\"nested\"]')) return\n const panel = panelRef.current\n if (!panel) return\n if (panel.contains(document.activeElement)) return\n const preferred = panel.querySelector<HTMLElement>('[autofocus]')\n const first = panel.querySelector<HTMLElement>(FOCUSABLE)\n ;(preferred ?? first ?? panel).focus()\n }, 0)\n\n function onKeyDown(e: KeyboardEvent) {\n if (e.key !== 'Tab') return\n if (!stacked && document.querySelector('[data-drawer-layer=\"nested\"]')) return\n const panel = panelRef.current\n if (!panel) return\n const focusables = Array.from(panel.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => el.offsetParent !== null || el === document.activeElement,\n )\n if (focusables.length === 0) {\n e.preventDefault()\n panel.focus()\n return\n }\n const firstEl = focusables[0]!\n const lastEl = focusables[focusables.length - 1]!\n const activeEl = document.activeElement\n if (e.shiftKey) {\n if (activeEl === firstEl || activeEl === panel || !panel.contains(activeEl)) {\n e.preventDefault()\n lastEl.focus()\n }\n } else if (activeEl === lastEl) {\n e.preventDefault()\n firstEl.focus()\n }\n }\n\n document.addEventListener('keydown', onKeyDown)\n return () => {\n window.clearTimeout(focusTimer)\n document.removeEventListener('keydown', onKeyDown)\n if (previouslyFocused && document.contains(previouslyFocused)) previouslyFocused.focus()\n }\n }, [open, stacked])\n\n if (typeof document === 'undefined') return null\n\n const offscreen = side === 'left' ? '-100%' : '100%'\n const panelMotion = reduce\n ? {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0 },\n transition: { duration: 0.12 },\n }\n : {\n initial: { x: offscreen },\n animate: { x: 0 },\n exit: { x: offscreen },\n transition: { type: 'spring' as const, damping: 32, stiffness: 320, mass: 0.8 },\n }\n\n return createPortal(\n <AnimatePresence onExitComplete={onExitComplete}>\n {mounted && open ? (\n <div\n key=\"drawer\"\n data-drawer-layer={stacked ? 'nested' : 'base'}\n className={cn(\n 'fixed inset-x-0 bottom-0 top-[var(--drawer-top,0px)]',\n stacked ? 'z-[55]' : 'z-50',\n )}\n // Under the View Transitions API (PageTransition), a route change\n // paints the page snapshot in the browser's top layer — above any\n // z-index. Naming the drawer gives it its own top-layer group,\n // stacked over the page group, so the page can never flash across\n // an open drawer mid-navigation.\n style={{ viewTransitionName: stacked ? 'appkit-drawer-nested' : 'appkit-drawer' }}\n >\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n className=\"absolute inset-0 bg-overlay/40 backdrop-blur-[2px]\"\n onClick={onClose}\n aria-hidden=\"true\"\n />\n <motion.aside\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n {...panelMotion}\n className={cn(\n 'absolute inset-y-0 flex flex-col overflow-hidden border-t border-border bg-surface shadow-lg transition-[max-width] duration-300 ease-in-out',\n side === 'left' ? 'left-0 border-r' : 'right-0 border-l',\n // Full replacement (not additive): two sm:max-w-* utilities on one\n // element resolve by stylesheet order, so stacking them no-ops.\n fullscreen ? 'w-full sm:max-w-[100vw]' : SIZE_CLASS[size],\n panelClassName,\n )}\n >\n {title || description || headerActions ? (\n <header className=\"flex items-center justify-between gap-4 border-b border-border px-6 py-4\">\n <div className=\"min-w-0 space-y-0.5\">\n {title ? (\n <h2 className=\"truncate text-base font-semibold text-fg\">\n {typeof title === 'string' ? tr(title) : title}\n </h2>\n ) : null}\n {description ? (\n <p className=\"text-sm text-fg-muted\">\n {typeof description === 'string' ? tr(description) : description}\n </p>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {headerActions ? (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {headerActions}\n </div>\n ) : null}\n {!disableFullscreen ? (\n <button\n type=\"button\"\n onClick={() => setFullscreen((f) => !f)}\n className=\"hidden rounded-md p-1.5 text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg sm:block\"\n aria-label={fullscreen ? text.exitFullscreen : text.fullscreen}\n title={fullscreen ? text.exitFullscreen : text.fullscreen}\n >\n {fullscreen ? (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"14\" y1=\"10\" x2=\"21\" y2=\"3\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n ) : (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n )}\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-md p-1.5 text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg\"\n aria-label={text.close}\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\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 </header>\n ) : null}\n {subtabs ? (\n <div className=\"shrink-0 border-b border-border bg-surface px-6\">{subtabs}</div>\n ) : null}\n <div\n className={cn(\n 'app-scroll min-h-0 flex-1 text-fg',\n bodyClassName ?? 'overflow-y-auto px-6 py-5',\n )}\n >\n {children}\n </div>\n {footer ? (\n <footer className=\"flex items-center justify-end gap-2 border-t border-border bg-bg-subtle px-6 py-3\">\n {footer}\n </footer>\n ) : null}\n </motion.aside>\n </div>\n ) : null}\n </AnimatePresence>,\n document.body,\n )\n}\n\n/**\n * Client-side navigate fn supplied by the host app (e.g. Next's `router.push`)\n * so `UrlDrawer` can close by changing the URL — which re-runs the server\n * component that owns the drawer's `open` state. Falls back to a hard nav.\n */\nexport const DrawerNavigateContext = React.createContext<((href: string) => void) | null>(null)\n\nexport type UrlDrawerProps = Omit<DrawerProps, 'open' | 'onClose' | 'onExitComplete'> & {\n open: boolean\n closeHref: string\n}\n\n/**\n * URL-state drawer for server-rendered pages: `open` derives from a search\n * param, so closing needs a real navigation (deferred until the slide-out\n * finishes, so the exit animation always plays).\n */\nexport function UrlDrawer({ open, closeHref, children, ...rest }: UrlDrawerProps) {\n const navigate = React.useContext(DrawerNavigateContext)\n const [show, setShow] = React.useState(open)\n React.useEffect(() => setShow(open), [open])\n\n function afterExit() {\n if (typeof window === 'undefined') return\n if (navigate) navigate(closeHref)\n else window.location.assign(closeHref)\n }\n\n return (\n <Drawer open={show} onClose={() => setShow(false)} onExitComplete={afterExit} {...rest}>\n {children}\n </Drawer>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"drawer.js","sourceRoot":"","sources":["../src/drawer.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport { cn } from './utils'\n\n// Z-INDEX SCALE (single source of truth for the ecosystem)\n//\n// sidebar : z-10\n// header : z-20\n// sticky-bars : z-30\n// dropdowns : z-40\n// drawer : z-50 (stacked/nested: z-[55])\n// floating UI : z-[60] — Popover, confirm dialog\n// dialog : z-[65]\n// select : z-[70] — dropdown and mobile sheet above dialogs\n// toast : z-70\n//\n// The drawer's top edge is `--drawer-top` (default 0). An app shell sets it to\n// its header height so drawers sit beneath the persistent header:\n// :root { --drawer-top: 3.5rem; }\n\nexport type DrawerSize = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\nexport type DrawerSide = 'left' | 'right'\n\nconst SIZE_CLASS: Record<DrawerSize, string> = {\n sm: 'w-full sm:max-w-md',\n md: 'w-full sm:max-w-xl',\n lg: 'w-full sm:max-w-2xl',\n xl: 'w-full sm:max-w-4xl',\n '2xl': 'w-full sm:max-w-6xl',\n full: 'w-full',\n}\n\n// --- Injectable labels ------------------------------------------------------\n// appkit is i18n-agnostic. Apps wrap their tree in <DrawerTextProvider> to map\n// these to next-intl / their own dictionary; standalone use gets English.\n// `translate` supports message-key titles while remaining a pass-through for\n// raw ReactNode titles.\nexport type DrawerText = {\n close: string\n fullscreen: string\n exitFullscreen: string\n translate?: (key: string) => string\n}\n\nconst DEFAULT_DRAWER_TEXT: DrawerText = {\n close: 'Close',\n fullscreen: 'Fullscreen',\n exitFullscreen: 'Exit fullscreen',\n}\n\nconst DrawerTextContext = React.createContext<DrawerText>(DEFAULT_DRAWER_TEXT)\n\nexport function DrawerTextProvider({\n value,\n children,\n}: {\n value: Partial<DrawerText>\n children: React.ReactNode\n}) {\n const merged = React.useMemo(() => ({ ...DEFAULT_DRAWER_TEXT, ...value }), [value])\n return <DrawerTextContext.Provider value={merged}>{children}</DrawerTextContext.Provider>\n}\n\nfunction useDrawerText(): DrawerText {\n return React.useContext(DrawerTextContext)\n}\n\n// Ref-counted scroll lock — nested/stacked drawers share one lock so the body\n// only unlocks when the last drawer closes.\nlet openDrawerCount = 0\nlet originalBodyOverflow: string | null = null\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nexport type DrawerProps = {\n open: boolean\n onClose: () => void\n title?: React.ReactNode\n description?: React.ReactNode\n size?: DrawerSize\n side?: DrawerSide\n children: React.ReactNode\n footer?: React.ReactNode\n /** Primary action buttons pinned into the header, before the close button. */\n headerActions?: React.ReactNode\n /** Record-detail navigation rendered directly below the title header. */\n subtabs?: React.ReactNode\n /** Override the body wrapper classes (default: scroll + px-6 py-5). */\n bodyClassName?: string\n /** Extra classes for the panel (e.g. record-type tinting). */\n panelClassName?: string\n /** Raise above another open drawer in a deliberate nested flow. */\n stacked?: boolean\n /** Open at full viewport width; the user can still collapse it. */\n initialFullscreen?: boolean\n /** Hide the fullscreen expand/collapse affordance. */\n disableFullscreen?: boolean\n /** Fires after the exit animation completes (UrlDrawer defers navigation). */\n onExitComplete?: () => void\n}\n\n/**\n * Slide-in flyout for sub-entity create/edit and detail views. Portals to body;\n * spring slide-in; backdrop fade+blur; Esc + click-out + ref-counted scroll\n * lock; focus trap + restore; a NetSuite-style expand/collapse to full viewport\n * width (animated via max-width). Fully tokenized and reduced-motion aware.\n */\nexport function Drawer({\n open,\n onClose,\n title,\n description,\n size = 'md',\n side = 'right',\n children,\n footer,\n headerActions,\n subtabs,\n bodyClassName,\n panelClassName,\n stacked = false,\n initialFullscreen = false,\n disableFullscreen = false,\n onExitComplete,\n}: DrawerProps) {\n const text = useDrawerText()\n const tr = text.translate ?? ((s: string) => s)\n const reduce = useReducedMotion()\n const [mounted, setMounted] = React.useState(false)\n React.useEffect(() => setMounted(true), [])\n\n const [fullscreen, setFullscreen] = React.useState(initialFullscreen)\n React.useEffect(() => {\n if (!open) setFullscreen(initialFullscreen)\n }, [initialFullscreen, open])\n\n const panelRef = React.useRef<HTMLElement>(null)\n const onCloseRef = React.useRef(onClose)\n React.useEffect(() => {\n onCloseRef.current = onClose\n }, [onClose])\n\n // Esc + scroll lock. Stacked-aware: a base drawer ignores Esc while a nested\n // drawer or a floating overlay is on top.\n React.useEffect(() => {\n if (!open) return\n function onKey(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n if (document.querySelector('[data-ui-overlay]')) return\n if (!stacked && document.querySelector('[data-drawer-layer=\"nested\"]')) return\n onCloseRef.current()\n }\n document.addEventListener('keydown', onKey)\n if (openDrawerCount === 0) originalBodyOverflow = document.body.style.overflow\n openDrawerCount += 1\n document.body.style.overflow = 'hidden'\n return () => {\n document.removeEventListener('keydown', onKey)\n openDrawerCount = Math.max(0, openDrawerCount - 1)\n if (openDrawerCount === 0) {\n document.body.style.overflow = originalBodyOverflow ?? ''\n originalBodyOverflow = null\n }\n }\n }, [open, stacked])\n\n // Focus management: move focus in on open, trap Tab, restore on close.\n React.useEffect(() => {\n if (!open) return\n const previouslyFocused = document.activeElement as HTMLElement | null\n const focusTimer = window.setTimeout(() => {\n if (!stacked && document.querySelector('[data-drawer-layer=\"nested\"]')) return\n const panel = panelRef.current\n if (!panel) return\n if (panel.contains(document.activeElement)) return\n const preferred = panel.querySelector<HTMLElement>('[autofocus]')\n const first = panel.querySelector<HTMLElement>(FOCUSABLE)\n ;(preferred ?? first ?? panel).focus()\n }, 0)\n\n function onKeyDown(e: KeyboardEvent) {\n if (e.key !== 'Tab') return\n if (!stacked && document.querySelector('[data-drawer-layer=\"nested\"]')) return\n const panel = panelRef.current\n if (!panel) return\n const focusables = Array.from(panel.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => el.offsetParent !== null || el === document.activeElement,\n )\n if (focusables.length === 0) {\n e.preventDefault()\n panel.focus()\n return\n }\n const firstEl = focusables[0]!\n const lastEl = focusables[focusables.length - 1]!\n const activeEl = document.activeElement\n if (e.shiftKey) {\n if (activeEl === firstEl || activeEl === panel || !panel.contains(activeEl)) {\n e.preventDefault()\n lastEl.focus()\n }\n } else if (activeEl === lastEl) {\n e.preventDefault()\n firstEl.focus()\n }\n }\n\n document.addEventListener('keydown', onKeyDown)\n return () => {\n window.clearTimeout(focusTimer)\n document.removeEventListener('keydown', onKeyDown)\n if (previouslyFocused && document.contains(previouslyFocused)) previouslyFocused.focus()\n }\n }, [open, stacked])\n\n if (typeof document === 'undefined') return null\n\n const offscreen = side === 'left' ? '-100%' : '100%'\n const panelMotion = reduce\n ? {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0 },\n transition: { duration: 0.12 },\n }\n : {\n initial: { x: offscreen },\n animate: { x: 0 },\n exit: { x: offscreen },\n transition: { type: 'spring' as const, damping: 32, stiffness: 320, mass: 0.8 },\n }\n\n return createPortal(\n <AnimatePresence onExitComplete={onExitComplete}>\n {mounted && open ? (\n <div\n key=\"drawer\"\n data-drawer-layer={stacked ? 'nested' : 'base'}\n className={cn(\n 'fixed inset-x-0 bottom-0 top-[var(--drawer-top,0px)]',\n stacked ? 'z-[55]' : 'z-50',\n )}\n // Under the View Transitions API (PageTransition), a route change\n // paints the page snapshot in the browser's top layer — above any\n // z-index. Naming the drawer gives it its own top-layer group,\n // stacked over the page group, so the page can never flash across\n // an open drawer mid-navigation.\n style={{ viewTransitionName: stacked ? 'appkit-drawer-nested' : 'appkit-drawer' }}\n >\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n className=\"absolute inset-0 bg-overlay/40 backdrop-blur-[2px]\"\n onClick={onClose}\n aria-hidden=\"true\"\n />\n <motion.aside\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n {...panelMotion}\n className={cn(\n 'absolute inset-y-0 flex flex-col overflow-hidden border-t border-border bg-surface shadow-lg transition-[max-width] duration-300 ease-in-out',\n side === 'left' ? 'left-0 border-r' : 'right-0 border-l',\n // Full replacement (not additive): two sm:max-w-* utilities on one\n // element resolve by stylesheet order, so stacking them no-ops.\n fullscreen ? 'w-full sm:max-w-[100vw]' : SIZE_CLASS[size],\n panelClassName,\n )}\n >\n {title || description || headerActions ? (\n <header className=\"flex items-center justify-between gap-4 border-b border-border px-6 py-4\">\n <div className=\"min-w-0 space-y-0.5\">\n {title ? (\n <h2 className=\"truncate text-base font-semibold text-fg\">\n {typeof title === 'string' ? tr(title) : title}\n </h2>\n ) : null}\n {description ? (\n <p className=\"text-sm text-fg-muted\">\n {typeof description === 'string' ? tr(description) : description}\n </p>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {headerActions ? (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {headerActions}\n </div>\n ) : null}\n {!disableFullscreen ? (\n <button\n type=\"button\"\n onClick={() => setFullscreen((f) => !f)}\n className=\"hidden rounded-md p-1.5 text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg sm:block\"\n aria-label={fullscreen ? text.exitFullscreen : text.fullscreen}\n title={fullscreen ? text.exitFullscreen : text.fullscreen}\n >\n {fullscreen ? (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"14\" y1=\"10\" x2=\"21\" y2=\"3\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n ) : (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n )}\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-md p-1.5 text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg\"\n aria-label={text.close}\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\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 </header>\n ) : null}\n {subtabs ? (\n <div className=\"shrink-0 border-b border-border bg-surface px-6\">{subtabs}</div>\n ) : null}\n <div\n className={cn(\n 'app-scroll min-h-0 flex-1 text-fg',\n bodyClassName ?? 'overflow-y-auto px-6 py-5',\n )}\n >\n {children}\n </div>\n {footer ? (\n <footer className=\"flex items-center justify-end gap-2 border-t border-border bg-bg-subtle px-6 py-3\">\n {footer}\n </footer>\n ) : null}\n </motion.aside>\n </div>\n ) : null}\n </AnimatePresence>,\n document.body,\n )\n}\n\n/**\n * Client-side navigate fn supplied by the host app (e.g. Next's `router.push`)\n * so `UrlDrawer` can close by changing the URL — which re-runs the server\n * component that owns the drawer's `open` state. Falls back to a hard nav.\n */\nexport const DrawerNavigateContext = React.createContext<((href: string) => void) | null>(null)\n\nexport type UrlDrawerProps = Omit<DrawerProps, 'open' | 'onClose' | 'onExitComplete'> & {\n open: boolean\n closeHref: string\n}\n\n/**\n * URL-state drawer for server-rendered pages: `open` derives from a search\n * param, so closing needs a real navigation (deferred until the slide-out\n * finishes, so the exit animation always plays).\n */\nexport function UrlDrawer({ open, closeHref, children, ...rest }: UrlDrawerProps) {\n const navigate = React.useContext(DrawerNavigateContext)\n const [show, setShow] = React.useState(open)\n React.useEffect(() => setShow(open), [open])\n\n function afterExit() {\n if (typeof window === 'undefined') return\n if (navigate) navigate(closeHref)\n else window.location.assign(closeHref)\n }\n\n return (\n <Drawer open={show} onClose={() => setShow(false)} onExitComplete={afterExit} {...rest}>\n {children}\n </Drawer>\n )\n}\n"]}
|
package/index.d.ts
CHANGED
|
@@ -23,8 +23,8 @@ export { EmptyState, type EmptyStateProps } from './empty-state.js';
|
|
|
23
23
|
export { PageHeader, DetailHeader, type PageHeaderProps, type DetailHeaderProps, } from './page-header.js';
|
|
24
24
|
export { DocumentTitle } from './document-title.js';
|
|
25
25
|
export { UiLinkProvider, UiLink, UiBackLinkProvider, UiBackLink, type UiLinkComponent, type BackLinkProps, type BackLinkLike, type BackLinkComponent, } from './link-context.js';
|
|
26
|
-
export { ThemeProvider, ThemeToggle, useTheme, type
|
|
27
|
-
export { getThemeScript } from './theme-script.js';
|
|
26
|
+
export { ThemeProvider, ThemeToggle, useTheme, type ThemeProviderProps, type ThemeToggleLabels, } from './theme.js';
|
|
27
|
+
export { getThemeScript, type Theme, type ThemeOptions, type ResolvedTheme } from './theme-script.js';
|
|
28
28
|
export { NavigationModeProvider, useNavigationMode } from './navigation-mode.js';
|
|
29
29
|
export { AccountMenu, type AccountMenuProps, type AccountMenuChoice, type AccountMenuOption, type AccountMenuLabels, } from './account-menu.js';
|
|
30
30
|
export { GlobalSearch, type GlobalSearchHit, type GlobalSearchGroup, type GlobalSearchResult, type GlobalSearchLabels, } from './global-search.js';
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnE,OAAO,EACL,IAAI,EACJ,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,UAAU,EACV,KAAK,SAAS,GACf,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AAC7F,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC1F,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EACL,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,aAAa,EACb,WAAW,EACX,QAAQ,EACR,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { cn } from './utils'\nexport { Button, buttonVariants, type ButtonProps } from './button'\nexport {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardContent,\n CardFooter,\n type CardProps,\n} from './card'\nexport { Input, type InputProps } from './input'\nexport { Textarea, type TextareaProps } from './textarea'\nexport { Label } from './label'\nexport { Badge, badgeVariants, type BadgeProps } from './badge'\nexport { Alert, AlertTitle, AlertDescription, alertVariants, type AlertProps } from './alert'\nexport { Switch, type SwitchProps } from './switch'\nexport { Checkbox, type CheckboxProps } from './checkbox'\nexport { Separator, type SeparatorProps } from './separator'\nexport { Progress, type ProgressProps } from './progress'\nexport { Slider, type SliderProps } from './slider'\nexport { Skeleton, type SkeletonProps } from './skeleton'\nexport { Spinner, type SpinnerProps } from './spinner'\nexport { Avatar, type AvatarProps } from './avatar'\nexport { AnimatedNumber, formatNumber, type AnimatedNumberProps } from './animated-number'\nexport { Sparkline, type SparklineProps, type SparklineTone } from './sparkline'\nexport { Tabs, type TabsProps, type TabItem } from './tabs'\nexport { TabContent } from './tab-content'\nexport { Tooltip, type TooltipProps } from './tooltip'\nexport { EmptyState, type EmptyStateProps } from './empty-state'\nexport {\n PageHeader,\n DetailHeader,\n type PageHeaderProps,\n type DetailHeaderProps,\n} from './page-header'\nexport { DocumentTitle } from './document-title'\nexport {\n UiLinkProvider,\n UiLink,\n UiBackLinkProvider,\n UiBackLink,\n type UiLinkComponent,\n type BackLinkProps,\n type BackLinkLike,\n type BackLinkComponent,\n} from './link-context'\nexport {\n ThemeProvider,\n ThemeToggle,\n useTheme,\n type Theme,\n type ResolvedTheme,\n type ThemeToggleLabels,\n} from './theme'\nexport { getThemeScript } from './theme-script'\nexport { NavigationModeProvider, useNavigationMode } from './navigation-mode'\nexport {\n AccountMenu,\n type AccountMenuProps,\n type AccountMenuChoice,\n type AccountMenuOption,\n type AccountMenuLabels,\n} from './account-menu'\nexport {\n GlobalSearch,\n type GlobalSearchHit,\n type GlobalSearchGroup,\n type GlobalSearchResult,\n type GlobalSearchLabels,\n} from './global-search'\nexport {\n NotificationsBell,\n type NotificationItem,\n type NotificationsBellLabels,\n} from './notifications-bell'\nexport {\n ApiReference,\n ApiEndpoint,\n MethodBadge,\n CodeBlock,\n type ApiEndpointDoc,\n type ApiParamDoc,\n} from './api-reference'\nexport { AppShell, type AppShellNavigationMode } from './app-shell'\nexport { AppSidebar } from './app-sidebar'\nexport { TopNav } from './top-nav'\nexport { MobileTabBar } from './mobile-tab-bar'\nexport {\n SidebarNav,\n findActiveNavHref,\n isFlatNavigation,\n selectMobileTabs,\n toBlocks,\n NavIcon,\n type NavBlock,\n type SidebarNavItem,\n type SidebarNavGroup,\n} from './sidebar-nav'\nexport {\n buildDefaultNavigationConfig,\n reconcileNavigationConfig,\n resolveNavigationItems,\n stampKnownNavigationItems,\n isTenantNavigationConfig,\n type NavigationRegistryItem,\n type NavigationItemConfig,\n type TenantNavigationConfig,\n type ResolvedNavigationItem,\n} from './navigation-config'\nexport {\n NavigationConfigEditor,\n type NavigationConfigEditorProps,\n type NavigationConfigEditorLabels,\n} from './navigation-config-editor'\nexport { PageContainer, ListPageLayout, DetailPageLayout, WizardLayout } from './page-layout'\nexport {\n parseListParams,\n parsePrefixedListParams,\n pickString,\n clamp,\n buildHref,\n mergeHref,\n buildExportHref,\n isUuid,\n type ListParams,\n type ListSearchParams,\n} from './list-params'\nexport { ListNavProvider, useListNav, useListNavClick, type ListNav } from './list-nav'\nexport { SearchInput } from './list-search-input'\nexport { FilterChips, SearchSelectFilter, type FilterOption } from './filter-chips'\nexport { SortableTh, SortTh } from './sortable-th'\nexport { Pagination, type PaginationLabels } from './list-pagination'\nexport {\n PagedTable,\n type PagedColumn,\n type PagedSortValue,\n type PagedTableLabels,\n type PagedTableProps,\n type PagedTableSort,\n} from './paged-table'\nexport { SubtabNav, type SubtabItem, type SubtabNavProps } from './subtab-nav'\nexport {\n OrgChart,\n buildOrgTree,\n canReparent,\n orgChartDescendantIds,\n type OrgChartNode,\n type OrgChartTreeNode,\n type OrgChartLabels,\n type OrgChartProps,\n} from './org-chart'\nexport {\n AdminHub,\n SettingsShell,\n SettingsNav,\n SettingsSection,\n SettingsRow,\n type AdminHubCard,\n type AdminHubGroup,\n type AdminHubAccent,\n type SettingsNavItem,\n type SettingsNavGroup,\n type LinkRender,\n} from './settings-layout'\nexport { Popover } from './popover'\nexport {\n ContextMenu,\n useContextMenu,\n type ContextMenuItem,\n type ContextMenuEntry,\n type ContextMenuController,\n} from './context-menu'\nexport { SearchSelect, type SearchSelectProps, type SelectOption } from './search-select'\nexport {\n MultiSelect,\n type MultiSelectProps,\n type MultiSelectOption,\n} from './multi-select'\nexport { Select, type SelectProps } from './select'\nexport { Dialog, type DialogProps, type DialogSize } from './dialog'\nexport {\n ConfirmRoot,\n cancelConfirmDialog,\n confirmDialog,\n type ConfirmDialogOptions,\n type ConfirmRootProps,\n type ConfirmTone,\n} from './confirm-dialog'\nexport {\n PromptRoot,\n promptDialog,\n cancelPromptDialog,\n type PromptDialogOptions,\n} from './prompt-dialog'\nexport {\n toast,\n Toaster,\n type ToastT,\n type ExternalToast,\n type ToastType,\n type ToasterPosition,\n} from './toast'\nexport {\n Table,\n TableHeader,\n TableBody,\n TableRow,\n TableHead,\n TableCell,\n type TableRowProps,\n} from './table'\nexport {\n LineGrid,\n type LineGridProps,\n type LineGridColumn,\n type LineGridLabels,\n} from './line-grid'\nexport {\n RecordList,\n type RecordListProps,\n type RecordColumn,\n type RecordCellKind,\n type RecordListLink,\n} from './record-list'\nexport {\n WorkspaceLauncher,\n type WorkspaceLauncherProps,\n type WorkspaceLaunchItem,\n type WorkspaceLaunchBreakdown,\n type WorkspaceLaunchSegment,\n type WorkspaceLaunchTone,\n} from './workspace-launcher'\nexport {\n Drawer,\n UrlDrawer,\n DrawerTextProvider,\n DrawerNavigateContext,\n type DrawerProps,\n type UrlDrawerProps,\n type DrawerSize,\n type DrawerSide,\n type DrawerText,\n} from './drawer'\nexport { UiTextProvider, useUiText, type UiTextTranslator } from './text-context'\nexport {\n FileUploader,\n uploadReservedFile,\n type FileUploaderProps,\n type UploadRequestResult,\n type FinalizeUploadInput,\n type RequestUploadAction,\n type FinalizeUploadAction,\n type UploadedFile,\n} from './file-uploader'\nexport {\n defaultMaxUploadBytes,\n formatUploadSizeLimit,\n type AttachmentKind,\n} from './upload-limits'\nexport { SignaturePad, type SignaturePadProps } from './signature-pad'\nexport { useElementSize } from './use-element-size'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { cn } from './utils'\nexport { Button, buttonVariants, type ButtonProps } from './button'\nexport {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardContent,\n CardFooter,\n type CardProps,\n} from './card'\nexport { Input, type InputProps } from './input'\nexport { Textarea, type TextareaProps } from './textarea'\nexport { Label } from './label'\nexport { Badge, badgeVariants, type BadgeProps } from './badge'\nexport { Alert, AlertTitle, AlertDescription, alertVariants, type AlertProps } from './alert'\nexport { Switch, type SwitchProps } from './switch'\nexport { Checkbox, type CheckboxProps } from './checkbox'\nexport { Separator, type SeparatorProps } from './separator'\nexport { Progress, type ProgressProps } from './progress'\nexport { Slider, type SliderProps } from './slider'\nexport { Skeleton, type SkeletonProps } from './skeleton'\nexport { Spinner, type SpinnerProps } from './spinner'\nexport { Avatar, type AvatarProps } from './avatar'\nexport { AnimatedNumber, formatNumber, type AnimatedNumberProps } from './animated-number'\nexport { Sparkline, type SparklineProps, type SparklineTone } from './sparkline'\nexport { Tabs, type TabsProps, type TabItem } from './tabs'\nexport { TabContent } from './tab-content'\nexport { Tooltip, type TooltipProps } from './tooltip'\nexport { EmptyState, type EmptyStateProps } from './empty-state'\nexport {\n PageHeader,\n DetailHeader,\n type PageHeaderProps,\n type DetailHeaderProps,\n} from './page-header'\nexport { DocumentTitle } from './document-title'\nexport {\n UiLinkProvider,\n UiLink,\n UiBackLinkProvider,\n UiBackLink,\n type UiLinkComponent,\n type BackLinkProps,\n type BackLinkLike,\n type BackLinkComponent,\n} from './link-context'\nexport {\n ThemeProvider,\n ThemeToggle,\n useTheme,\n type ThemeProviderProps,\n type ThemeToggleLabels,\n} from './theme'\nexport { getThemeScript, type Theme, type ThemeOptions, type ResolvedTheme } from './theme-script'\nexport { NavigationModeProvider, useNavigationMode } from './navigation-mode'\nexport {\n AccountMenu,\n type AccountMenuProps,\n type AccountMenuChoice,\n type AccountMenuOption,\n type AccountMenuLabels,\n} from './account-menu'\nexport {\n GlobalSearch,\n type GlobalSearchHit,\n type GlobalSearchGroup,\n type GlobalSearchResult,\n type GlobalSearchLabels,\n} from './global-search'\nexport {\n NotificationsBell,\n type NotificationItem,\n type NotificationsBellLabels,\n} from './notifications-bell'\nexport {\n ApiReference,\n ApiEndpoint,\n MethodBadge,\n CodeBlock,\n type ApiEndpointDoc,\n type ApiParamDoc,\n} from './api-reference'\nexport { AppShell, type AppShellNavigationMode } from './app-shell'\nexport { AppSidebar } from './app-sidebar'\nexport { TopNav } from './top-nav'\nexport { MobileTabBar } from './mobile-tab-bar'\nexport {\n SidebarNav,\n findActiveNavHref,\n isFlatNavigation,\n selectMobileTabs,\n toBlocks,\n NavIcon,\n type NavBlock,\n type SidebarNavItem,\n type SidebarNavGroup,\n} from './sidebar-nav'\nexport {\n buildDefaultNavigationConfig,\n reconcileNavigationConfig,\n resolveNavigationItems,\n stampKnownNavigationItems,\n isTenantNavigationConfig,\n type NavigationRegistryItem,\n type NavigationItemConfig,\n type TenantNavigationConfig,\n type ResolvedNavigationItem,\n} from './navigation-config'\nexport {\n NavigationConfigEditor,\n type NavigationConfigEditorProps,\n type NavigationConfigEditorLabels,\n} from './navigation-config-editor'\nexport { PageContainer, ListPageLayout, DetailPageLayout, WizardLayout } from './page-layout'\nexport {\n parseListParams,\n parsePrefixedListParams,\n pickString,\n clamp,\n buildHref,\n mergeHref,\n buildExportHref,\n isUuid,\n type ListParams,\n type ListSearchParams,\n} from './list-params'\nexport { ListNavProvider, useListNav, useListNavClick, type ListNav } from './list-nav'\nexport { SearchInput } from './list-search-input'\nexport { FilterChips, SearchSelectFilter, type FilterOption } from './filter-chips'\nexport { SortableTh, SortTh } from './sortable-th'\nexport { Pagination, type PaginationLabels } from './list-pagination'\nexport {\n PagedTable,\n type PagedColumn,\n type PagedSortValue,\n type PagedTableLabels,\n type PagedTableProps,\n type PagedTableSort,\n} from './paged-table'\nexport { SubtabNav, type SubtabItem, type SubtabNavProps } from './subtab-nav'\nexport {\n OrgChart,\n buildOrgTree,\n canReparent,\n orgChartDescendantIds,\n type OrgChartNode,\n type OrgChartTreeNode,\n type OrgChartLabels,\n type OrgChartProps,\n} from './org-chart'\nexport {\n AdminHub,\n SettingsShell,\n SettingsNav,\n SettingsSection,\n SettingsRow,\n type AdminHubCard,\n type AdminHubGroup,\n type AdminHubAccent,\n type SettingsNavItem,\n type SettingsNavGroup,\n type LinkRender,\n} from './settings-layout'\nexport { Popover } from './popover'\nexport {\n ContextMenu,\n useContextMenu,\n type ContextMenuItem,\n type ContextMenuEntry,\n type ContextMenuController,\n} from './context-menu'\nexport { SearchSelect, type SearchSelectProps, type SelectOption } from './search-select'\nexport {\n MultiSelect,\n type MultiSelectProps,\n type MultiSelectOption,\n} from './multi-select'\nexport { Select, type SelectProps } from './select'\nexport { Dialog, type DialogProps, type DialogSize } from './dialog'\nexport {\n ConfirmRoot,\n cancelConfirmDialog,\n confirmDialog,\n type ConfirmDialogOptions,\n type ConfirmRootProps,\n type ConfirmTone,\n} from './confirm-dialog'\nexport {\n PromptRoot,\n promptDialog,\n cancelPromptDialog,\n type PromptDialogOptions,\n} from './prompt-dialog'\nexport {\n toast,\n Toaster,\n type ToastT,\n type ExternalToast,\n type ToastType,\n type ToasterPosition,\n} from './toast'\nexport {\n Table,\n TableHeader,\n TableBody,\n TableRow,\n TableHead,\n TableCell,\n type TableRowProps,\n} from './table'\nexport {\n LineGrid,\n type LineGridProps,\n type LineGridColumn,\n type LineGridLabels,\n} from './line-grid'\nexport {\n RecordList,\n type RecordListProps,\n type RecordColumn,\n type RecordCellKind,\n type RecordListLink,\n} from './record-list'\nexport {\n WorkspaceLauncher,\n type WorkspaceLauncherProps,\n type WorkspaceLaunchItem,\n type WorkspaceLaunchBreakdown,\n type WorkspaceLaunchSegment,\n type WorkspaceLaunchTone,\n} from './workspace-launcher'\nexport {\n Drawer,\n UrlDrawer,\n DrawerTextProvider,\n DrawerNavigateContext,\n type DrawerProps,\n type UrlDrawerProps,\n type DrawerSize,\n type DrawerSide,\n type DrawerText,\n} from './drawer'\nexport { UiTextProvider, useUiText, type UiTextTranslator } from './text-context'\nexport {\n FileUploader,\n uploadReservedFile,\n type FileUploaderProps,\n type UploadRequestResult,\n type FinalizeUploadInput,\n type RequestUploadAction,\n type FinalizeUploadAction,\n type UploadedFile,\n} from './file-uploader'\nexport {\n defaultMaxUploadBytes,\n formatUploadSizeLimit,\n type AttachmentKind,\n} from './upload-limits'\nexport { SignaturePad, type SignaturePadProps } from './signature-pad'\nexport { useElementSize } from './use-element-size'\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@braedonsaunders/appkit-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Tokenized, animated UI primitives — the feel of the ecosystem.",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"import": "./page-transition.js",
|
|
19
19
|
"default": "./page-transition.js"
|
|
20
20
|
},
|
|
21
|
+
"./theme-script": {
|
|
22
|
+
"types": "./theme-script.d.ts",
|
|
23
|
+
"import": "./theme-script.js",
|
|
24
|
+
"default": "./theme-script.js"
|
|
25
|
+
},
|
|
21
26
|
"./use-element-size": {
|
|
22
27
|
"types": "./use-element-size.d.ts",
|
|
23
28
|
"import": "./use-element-size.js",
|
|
@@ -29,7 +34,7 @@
|
|
|
29
34
|
"main": "./index.js",
|
|
30
35
|
"types": "./index.d.ts",
|
|
31
36
|
"dependencies": {
|
|
32
|
-
"@braedonsaunders/appkit-tokens": "^0.
|
|
37
|
+
"@braedonsaunders/appkit-tokens": "^0.2.0",
|
|
33
38
|
"class-variance-authority": "^0.7.1",
|
|
34
39
|
"clsx": "^2.1.1",
|
|
35
40
|
"framer-motion": "^12.42.2",
|
package/page-header.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../src/page-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,sEAAsE;IACtE,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,KAAK,KAAK,CAAC,SAAS,CAAA;KAAE,CAAA;IAC3I,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../src/page-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,sEAAsE;IACtE,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,KAAK,KAAK,CAAC,SAAS,CAAA;KAAE,CAAA;IAC3I,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,eAAe,qBA0B3F;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,OAAO,EACP,SAAS,GACV,EAAE,iBAAiB,qBAqBnB"}
|
package/page-header.js
CHANGED
|
@@ -5,7 +5,7 @@ import { UiBackLink } from './link-context.js';
|
|
|
5
5
|
import { cn } from './utils.js';
|
|
6
6
|
export function PageHeader({ title, description, actions, back, className }) {
|
|
7
7
|
const backClass = 'inline-flex items-center gap-1 text-xs text-fg-muted transition-colors hover:text-primary';
|
|
8
|
-
return (_jsxs("div", { className: cn('space-y-2', className), children: [_jsx(DocumentTitle, { title: title }), back ? (back.render ? (back.render({ href: back.href, className: backClass, children: _jsxs(_Fragment, { children: ["\u2190 ", back.label] }) })) : _jsx(UiBackLink, { href: back.href, label: back.label, className: backClass })) : null, _jsxs("header", { className: "flex items-center justify-between gap-3 sm:items-end sm:gap-4", children: [_jsxs("div", { className: "min-w-0 space-y-1", children: [_jsx("h1", { className: "truncate text-xl font-semibold text-fg sm:text-2xl", children: title }), description ? (_jsx("p", { className: "hidden text-sm text-fg-muted sm:block", children: description })) : null] }), actions ? (_jsx("div", { className: "flex
|
|
8
|
+
return (_jsxs("div", { className: cn('space-y-2', className), children: [_jsx(DocumentTitle, { title: title }), back ? (back.render ? (back.render({ href: back.href, className: backClass, children: _jsxs(_Fragment, { children: ["\u2190 ", back.label] }) })) : _jsx(UiBackLink, { href: back.href, label: back.label, className: backClass })) : null, _jsxs("header", { className: "flex flex-wrap items-center justify-between gap-x-3 gap-y-2 sm:items-end sm:gap-x-4", children: [_jsxs("div", { className: "min-w-0 flex-[1_1_12rem] space-y-1", children: [_jsx("h1", { className: "truncate text-xl font-semibold text-fg sm:text-2xl", children: title }), description ? (_jsx("p", { className: "hidden text-sm text-fg-muted sm:block", children: description })) : null] }), actions ? (_jsx("div", { className: "flex min-w-0 max-w-full flex-wrap items-center gap-2 sm:ml-auto sm:justify-end", children: actions })) : null] })] }));
|
|
9
9
|
}
|
|
10
10
|
/** Source-compatible record-detail heading. */
|
|
11
11
|
export function DetailHeader({ back, title, subtitle, badge, actions, className, }) {
|
package/page-header.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-header.js","sourceRoot":"","sources":["../src/page-header.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAW5B,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAmB;IAC1F,MAAM,SAAS,GAAG,2FAA2F,CAAA;IAC7G,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,aACxC,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,GAAI,EAC9B,IAAI,CAAC,CAAC,CAAC,CACN,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CACZ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,yCAAK,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CACtF,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,GAAI,CAC7E,CAAC,CAAC,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"page-header.js","sourceRoot":"","sources":["../src/page-header.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAW5B,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAmB;IAC1F,MAAM,SAAS,GAAG,2FAA2F,CAAA;IAC7G,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,aACxC,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,GAAI,EAC9B,IAAI,CAAC,CAAC,CAAC,CACN,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CACZ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,yCAAK,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CACtF,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,GAAI,CAC7E,CAAC,CAAC,CAAC,IAAI,EAIR,kBAAQ,SAAS,EAAC,qFAAqF,aACrG,eAAK,SAAS,EAAC,oCAAoC,aACjD,aAAI,SAAS,EAAC,oDAAoD,YAAE,KAAK,GAAM,EAC9E,WAAW,CAAC,CAAC,CAAC,CACb,YAAG,SAAS,EAAC,uCAAuC,YAAE,WAAW,GAAK,CACvE,CAAC,CAAC,CAAC,IAAI,IACJ,EACL,OAAO,CAAC,CAAC,CAAC,CACT,cAAK,SAAS,EAAC,gFAAgF,YAAE,OAAO,GAAO,CAChH,CAAC,CAAC,CAAC,IAAI,IACD,IACL,CACP,CAAA;AACH,CAAC;AAWD,+CAA+C;AAC/C,MAAM,UAAU,YAAY,CAAC,EAC3B,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,OAAO,EACP,SAAS,GACS;IAClB,OAAO,CACL,kBAAQ,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,aAC3C,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,GAAI,EAC9B,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,UAAU,IACT,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,SAAS,EAAC,sCAAsC,GAChD,CACH,CAAC,CAAC,CAAC,IAAI,EACR,eAAK,SAAS,EAAC,+EAA+E,aAC5F,eAAK,SAAS,EAAC,uDAAuD,aACpE,aAAI,SAAS,EAAC,uDAAuD,YAAE,KAAK,GAAM,EACjF,KAAK,IACF,EACL,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,mCAAmC,YAAE,OAAO,GAAO,CAAC,CAAC,CAAC,IAAI,IAChF,EACL,QAAQ,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,uBAAuB,YAAE,QAAQ,GAAK,CAAC,CAAC,CAAC,IAAI,IAC/D,CACV,CAAA;AACH,CAAC","sourcesContent":["import * as React from 'react'\nimport { DocumentTitle } from './document-title'\nimport { UiBackLink } from './link-context'\nimport { cn } from './utils'\n\nexport type PageHeaderProps = {\n title: string\n description?: string\n actions?: React.ReactNode\n /** Optional back link. `render` lets an app supply its own <Link>. */\n back?: { href: string; label: string; render?: (props: { href: string; children: React.ReactNode; className: string }) => React.ReactNode }\n className?: string\n}\n\nexport function PageHeader({ title, description, actions, back, className }: PageHeaderProps) {\n const backClass = 'inline-flex items-center gap-1 text-xs text-fg-muted transition-colors hover:text-primary'\n return (\n <div className={cn('space-y-2', className)}>\n <DocumentTitle title={title} />\n {back ? (\n back.render ? (\n back.render({ href: back.href, className: backClass, children: <>← {back.label}</> })\n ) : <UiBackLink href={back.href} label={back.label} className={backClass} />\n ) : null}\n {/* The title keeps at least 12rem; when the actions no longer fit beside\n it they wrap onto their own row instead of overflowing, and a crowded\n actions row wraps its own items rather than forcing a scroll. */}\n <header className=\"flex flex-wrap items-center justify-between gap-x-3 gap-y-2 sm:items-end sm:gap-x-4\">\n <div className=\"min-w-0 flex-[1_1_12rem] space-y-1\">\n <h1 className=\"truncate text-xl font-semibold text-fg sm:text-2xl\">{title}</h1>\n {description ? (\n <p className=\"hidden text-sm text-fg-muted sm:block\">{description}</p>\n ) : null}\n </div>\n {actions ? (\n <div className=\"flex min-w-0 max-w-full flex-wrap items-center gap-2 sm:ml-auto sm:justify-end\">{actions}</div>\n ) : null}\n </header>\n </div>\n )\n}\n\nexport type DetailHeaderProps = {\n back?: { href: string; label: string }\n title: string\n subtitle?: string\n badge?: React.ReactNode\n actions?: React.ReactNode\n className?: string\n}\n\n/** Source-compatible record-detail heading. */\nexport function DetailHeader({\n back,\n title,\n subtitle,\n badge,\n actions,\n className,\n}: DetailHeaderProps) {\n return (\n <header className={cn('space-y-2', className)}>\n <DocumentTitle title={title} />\n {back ? (\n <UiBackLink\n href={back.href}\n label={back.label}\n className=\"text-sm text-primary hover:underline\"\n />\n ) : null}\n <div className=\"flex flex-col gap-2.5 sm:flex-row sm:items-center sm:justify-between sm:gap-4\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1.5\">\n <h1 className=\"text-xl font-semibold text-fg sm:truncate sm:text-2xl\">{title}</h1>\n {badge}\n </div>\n {actions ? <div className=\"flex flex-wrap items-center gap-2\">{actions}</div> : null}\n </div>\n {subtitle ? <p className=\"text-sm text-fg-muted\">{subtitle}</p> : null}\n </header>\n )\n}\n"]}
|
package/search-select.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-select.d.ts","sourceRoot":"","sources":["../src/search-select.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC9B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,EAAE,CAAC,EAAE,MAAM,CAAA;IAEX,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAuB,EACvB,iBAA6B,EAC7B,QAAgB,EAChB,SAAiB,EACjB,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,MAAc,EACd,OAAe,EACf,aAAa,EACb,UAAoB,EACpB,cAAc,EACd,OAAe,EACf,EAAE,EACF,SAAkB,EAClB,cAA6B,EAC7B,cAA6B,EAC7B,WAAsB,EACtB,UAAoB,GACrB,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"search-select.d.ts","sourceRoot":"","sources":["../src/search-select.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC9B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,EAAE,CAAC,EAAE,MAAM,CAAA;IAEX,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAuB,EACvB,iBAA6B,EAC7B,QAAgB,EAChB,SAAiB,EACjB,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,MAAc,EACd,OAAe,EACf,aAAa,EACb,UAAoB,EACpB,cAAc,EACd,OAAe,EACf,EAAE,EACF,SAAkB,EAClB,cAA6B,EAC7B,cAA6B,EAC7B,WAAsB,EACtB,UAAoB,GACrB,EAAE,iBAAiB,qBA8VnB"}
|
package/search-select.js
CHANGED
|
@@ -138,8 +138,11 @@ export function SearchSelect({ value, onChange, options, placeholder = 'Select
|
|
|
138
138
|
}
|
|
139
139
|
};
|
|
140
140
|
function onKey(e) {
|
|
141
|
-
if (e.key === 'Escape')
|
|
141
|
+
if (e.key === 'Escape') {
|
|
142
|
+
e.preventDefault();
|
|
142
143
|
setOpen(false);
|
|
144
|
+
triggerRef.current?.focus();
|
|
145
|
+
}
|
|
143
146
|
else if (e.key === 'ArrowDown') {
|
|
144
147
|
e.preventDefault();
|
|
145
148
|
setHighlight((h) => nextEnabled(h, 1));
|
|
@@ -194,9 +197,9 @@ export function SearchSelect({ value, onChange, options, placeholder = 'Select
|
|
|
194
197
|
left: pos.left,
|
|
195
198
|
width: Math.max(pos.width, 208),
|
|
196
199
|
maxHeight: pos.maxHeight,
|
|
197
|
-
}, className: "z-[
|
|
200
|
+
}, className: "z-[70] flex flex-col overflow-hidden rounded-xl border border-border bg-elevated shadow-lg", children: [showSearch ? searchBox(false) : null, _jsx("div", { className: cn('min-h-0 flex-1 overflow-y-auto', showSearch && 'mt-1'), children: optionList })] }), document.body)
|
|
198
201
|
: null, mounted && !isDesktop
|
|
199
|
-
? createPortal(_jsx(AnimatePresence, { children: open ? (_jsxs("div", { "data-ui-overlay": true, className: "fixed inset-0 z-[
|
|
202
|
+
? createPortal(_jsx(AnimatePresence, { children: open ? (_jsxs("div", { "data-ui-overlay": true, className: "fixed inset-0 z-[70]", children: [_jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, className: "absolute inset-0 bg-overlay/40 backdrop-blur-[2px]", onClick: () => setOpen(false) }), _jsxs(motion.div, { initial: { y: '100%' }, animate: { y: 0 }, exit: { y: '100%' }, transition: { type: 'spring', damping: 34, stiffness: 340, mass: 0.8 }, className: "absolute inset-x-0 bottom-0 flex max-h-[82vh] flex-col rounded-t-2xl border-t border-border bg-surface shadow-lg", children: [_jsx("div", { className: "flex items-center justify-center pt-2.5", children: _jsx("span", { className: "h-1.5 w-10 rounded-full bg-border-strong" }) }), _jsxs("div", { className: "flex items-center justify-between px-4 pb-1 pt-2", children: [_jsx("span", { className: "text-base font-semibold text-fg", children: sheetTitle ?? selectLabel }), _jsx("button", { type: "button", onClick: () => setOpen(false), "aria-label": closeLabel, className: "rounded-md p-1.5 text-fg-muted hover:bg-surface-hover", children: _jsx(X, { size: 18 }) })] }), showSearch ? searchBox(true) : null, _jsx("div", { className: "mt-1 min-h-0 flex-1 overflow-y-auto pb-[max(0.75rem,env(safe-area-inset-bottom))]", children: optionList })] })] })) : null }), document.body)
|
|
200
203
|
: null] }));
|
|
201
204
|
}
|
|
202
205
|
//# sourceMappingURL=search-select.js.map
|
package/search-select.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-select.js","sourceRoot":"","sources":["../src/search-select.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n// SearchSelect — a slick, mobile-first searchable select / typeahead.\n// • Desktop: anchored dropdown (portaled to <body>) with a search box + kbd nav.\n// • Mobile (<lg): an iOS/Android-style bottom sheet with large tap targets.\n// Animated, portal'd sheet, Esc + click-out + scroll-lock, disabled options,\n// optgroup-style headers (via SelectOption.group), hints, clearable, remote mode.\n// Fully tokenized; i18n strings are injectable props with English defaults.\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport { Check, ChevronDown, Search, X } from 'lucide-react'\nimport { cn } from './utils'\n\nexport type SelectOption = {\n value: string\n label: string\n hint?: string\n disabled?: boolean\n /** Group header label; options sharing a group are batched under it. */\n group?: string\n}\n\nexport type SearchSelectProps = {\n value: string\n onChange: (value: string) => void\n options: SelectOption[]\n placeholder?: string\n searchPlaceholder?: string\n disabled?: boolean\n /** Adds a leading empty option (e.g. \"None\"). */\n clearable?: boolean\n emptyLabel?: string\n /** Title at the top of the mobile bottom sheet. */\n sheetTitle?: string\n ariaLabel?: string\n className?: string\n triggerClassName?: string\n /** Force the search box on/off. Auto: shown when >7 options or any groups. */\n searchable?: boolean\n /** Preserve server ordering + forward the query instead of local filtering. */\n remote?: boolean\n loading?: boolean\n statusMessage?: string\n statusTone?: 'muted' | 'error'\n onSearchChange?: (query: string) => void\n invalid?: boolean\n id?: string\n // Injectable labels (default English).\n noneLabel?: string\n noMatchesLabel?: string\n searchingLabel?: string\n selectLabel?: string\n closeLabel?: string\n}\n\nexport function SearchSelect({\n value,\n onChange,\n options,\n placeholder = 'Select…',\n searchPlaceholder = 'Search…',\n disabled = false,\n clearable = false,\n emptyLabel,\n sheetTitle,\n ariaLabel,\n className,\n triggerClassName,\n searchable,\n remote = false,\n loading = false,\n statusMessage,\n statusTone = 'muted',\n onSearchChange,\n invalid = false,\n id,\n noneLabel = 'None',\n noMatchesLabel = 'No matches',\n searchingLabel = 'Searching…',\n selectLabel = 'Select',\n closeLabel = 'Close',\n}: SearchSelectProps) {\n const [open, setOpen] = React.useState(false)\n const [query, setQuery] = React.useState('')\n const [highlight, setHighlight] = React.useState(0)\n const [isDesktop, setIsDesktop] = React.useState(true)\n const [mounted, setMounted] = React.useState(false)\n const wrapRef = React.useRef<HTMLDivElement>(null)\n const searchRef = React.useRef<HTMLInputElement>(null)\n const triggerRef = React.useRef<HTMLButtonElement>(null)\n const dropRef = React.useRef<HTMLDivElement>(null)\n // The menu is anchored from the edge that touches the trigger: `top` when it\n // opens downward, `bottom` when it opens upward. Anchoring an upward menu by\n // its top would place it a full maxHeight above the trigger no matter how\n // short the list actually is — a three-option menu would float hundreds of\n // pixels clear of the field it belongs to.\n const [pos, setPos] = React.useState<\n | { edge: 'top'; offset: number; left: number; width: number; maxHeight: number }\n | { edge: 'bottom'; offset: number; left: number; width: number; maxHeight: number }\n | null\n >(null)\n function place() {\n const r = triggerRef.current?.getBoundingClientRect()\n if (r) {\n // Collision-aware: open upward when the space below is tight, and clamp\n // the list to the available viewport space either way.\n const margin = 8\n const below = window.innerHeight - r.bottom - margin\n const above = r.top - margin\n const desired = 320\n const width = Math.min(Math.max(r.width, 208), window.innerWidth - margin * 2)\n const left = Math.min(Math.max(margin, r.left), Math.max(margin, window.innerWidth - width - margin))\n if (below >= Math.min(desired, 180) || below >= above) {\n setPos({\n edge: 'top',\n offset: r.bottom + 6,\n left,\n width,\n maxHeight: Math.max(160, Math.min(desired, Math.max(below, 160))),\n })\n } else {\n setPos({\n edge: 'bottom',\n offset: Math.max(margin, window.innerHeight - r.top + 6),\n left,\n width,\n maxHeight: Math.max(160, Math.min(desired, Math.max(above, 160))),\n })\n }\n }\n }\n\n React.useEffect(() => {\n setMounted(true)\n const mq = window.matchMedia('(min-width: 1024px)')\n const update = () => setIsDesktop(mq.matches)\n update()\n mq.addEventListener('change', update)\n return () => mq.removeEventListener('change', update)\n }, [])\n\n const allOptions = React.useMemo(\n () => (clearable ? [{ value: '', label: emptyLabel ?? noneLabel }, ...options] : options),\n [clearable, emptyLabel, noneLabel, options],\n )\n const selected = options.find((o) => o.value === value)\n const showEmpty = clearable && value === '' && !!emptyLabel\n const display = selected?.label ?? (showEmpty ? emptyLabel : placeholder)\n const isPlaceholder = !selected && !showEmpty\n\n const showSearch = searchable ?? (allOptions.length > 7 || allOptions.some((o) => o.group))\n\n const filtered = React.useMemo(() => {\n if (remote) return allOptions\n const q = query.trim().toLowerCase()\n if (!q) return allOptions\n return allOptions.filter(\n (o) => o.label.toLowerCase().includes(q) || o.group?.toLowerCase().includes(q),\n )\n }, [allOptions, query, remote])\n\n function firstEnabled(items: SelectOption[], start: number) {\n if (start >= 0 && start < items.length && !items[start]?.disabled) return start\n const fwd = items.findIndex((o) => !o.disabled)\n return fwd === -1 ? 0 : fwd\n }\n\n function openMenu() {\n if (disabled) return\n setQuery('')\n onSearchChange?.('')\n setHighlight(firstEnabled(allOptions, allOptions.findIndex((o) => o.value === value)))\n place()\n setOpen(true)\n setTimeout(() => searchRef.current?.focus(), 60)\n }\n function choose(v: string) {\n onChange(v)\n setOpen(false)\n }\n\n React.useEffect(() => {\n if (!open || !isDesktop) return\n function onDoc(e: MouseEvent) {\n const target = e.target as Node\n if (wrapRef.current?.contains(target) || dropRef.current?.contains(target)) return\n setOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n return () => document.removeEventListener('mousedown', onDoc)\n }, [open, isDesktop])\n\n React.useEffect(() => {\n if (!open || !isDesktop) return\n place()\n const onMove = () => place()\n window.addEventListener('scroll', onMove, true)\n window.addEventListener('resize', onMove)\n return () => {\n window.removeEventListener('scroll', onMove, true)\n window.removeEventListener('resize', onMove)\n }\n }, [open, isDesktop])\n\n React.useEffect(() => {\n if (!open) return\n const nextEnabled = (from: number, dir: 1 | -1) => {\n let index = from\n while (true) {\n index += dir\n if (index < 0 || index >= filtered.length) return from\n if (!filtered[index]?.disabled) return index\n }\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false)\n else if (e.key === 'ArrowDown') {\n e.preventDefault()\n setHighlight((h) => nextEnabled(h, 1))\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n setHighlight((h) => nextEnabled(h, -1))\n } else if (e.key === 'Enter') {\n e.preventDefault()\n const o = filtered[highlight]\n if (o && !o.disabled) {\n onChange(o.value)\n setOpen(false)\n }\n }\n }\n document.addEventListener('keydown', onKey)\n let restore: (() => void) | undefined\n if (!isDesktop) {\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n restore = () => {\n document.body.style.overflow = prev\n }\n }\n return () => {\n document.removeEventListener('keydown', onKey)\n restore?.()\n }\n }, [filtered, highlight, isDesktop, onChange, open])\n\n const optionList = (\n <>\n <ul role=\"listbox\" className=\"py-1\">\n {filtered.length === 0 && !loading ? (\n <li role=\"option\" aria-disabled=\"true\" className=\"px-3 py-8 text-center text-sm text-fg-subtle\">\n {noMatchesLabel}\n </li>\n ) : null}\n {filtered.map((o, i) => {\n const active = o.value === value\n const prevGroup = i > 0 ? filtered[i - 1]?.group : undefined\n const header = o.group && o.group !== prevGroup ? o.group : null\n return (\n <li key={o.value || `__opt-${i}`} role=\"presentation\">\n {header ? (\n <div className=\"px-4 pb-1 pt-2.5 text-[11px] font-semibold tracking-wide text-fg-subtle uppercase lg:px-3\">\n {header}\n </div>\n ) : null}\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n disabled={o.disabled}\n onMouseEnter={() => !o.disabled && setHighlight(i)}\n onClick={() => !o.disabled && choose(o.value)}\n className={cn(\n 'flex h-12 w-full items-center gap-2.5 px-4 text-left text-[15px] transition-colors lg:h-9 lg:px-3 lg:text-sm',\n o.disabled\n ? 'cursor-not-allowed text-fg-subtle'\n : i === highlight\n ? 'bg-primary-subtle'\n : 'active:bg-surface-hover',\n !o.disabled && (active ? 'font-medium text-primary' : 'text-fg'),\n )}\n >\n <span className=\"min-w-0 flex-1 truncate\">\n {o.label}\n {o.hint ? <span className=\"ml-1.5 text-xs text-fg-subtle\">{o.hint}</span> : null}\n </span>\n {active ? <Check size={17} className=\"shrink-0 text-primary\" /> : null}\n </button>\n </li>\n )\n })}\n </ul>\n {loading || statusMessage ? (\n <div\n role={statusTone === 'error' ? 'alert' : 'status'}\n className={cn(\n 'border-t border-border px-3 py-2 text-xs',\n statusTone === 'error' ? 'text-danger' : 'text-fg-muted',\n )}\n >\n {loading ? searchingLabel : statusMessage}\n </div>\n ) : null}\n </>\n )\n\n const searchBox = (largeText: boolean) => (\n <div className=\"relative px-3 pt-3\">\n <Search size={16} className=\"absolute left-6 top-1/2 -translate-y-1/2 text-fg-subtle\" />\n <input\n ref={searchRef}\n value={query}\n onChange={(e) => {\n const next = e.target.value\n setQuery(next)\n onSearchChange?.(next)\n setHighlight(0)\n }}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n aria-busy={loading || undefined}\n className={cn(\n 'w-full rounded-lg border border-border bg-bg-subtle pl-9 pr-3 outline-none transition focus:border-primary focus:bg-surface focus:ring-2 focus:ring-ring/20',\n largeText ? 'h-11 text-base' : 'h-9 text-base sm:text-sm',\n )}\n />\n </div>\n )\n\n return (\n <div ref={wrapRef} className={cn('relative', className)}>\n <button\n ref={triggerRef}\n type=\"button\"\n id={id}\n onClick={() => (open ? setOpen(false) : openMenu())}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-invalid={invalid || undefined}\n className={cn(\n 'flex h-10 w-full items-center gap-2 rounded-lg border border-border bg-surface px-3 text-left text-sm shadow-sm transition',\n 'focus:border-primary focus:outline-none focus:ring-2 focus:ring-ring/25',\n disabled && 'cursor-not-allowed bg-bg-subtle opacity-70',\n open && 'border-primary ring-2 ring-ring/25',\n invalid && 'border-danger focus:border-danger focus:ring-danger/30',\n triggerClassName,\n )}\n >\n <span className={cn('min-w-0 flex-1 truncate', isPlaceholder ? 'text-fg-subtle' : 'text-fg')}>\n {display}\n </span>\n <ChevronDown\n size={16}\n className={cn('shrink-0 text-fg-subtle transition-transform', open && 'rotate-180')}\n />\n </button>\n\n {mounted && open && isDesktop && pos\n ? createPortal(\n <div\n ref={dropRef}\n data-ui-overlay\n style={{\n position: 'fixed',\n [pos.edge]: pos.offset,\n left: pos.left,\n width: Math.max(pos.width, 208),\n maxHeight: pos.maxHeight,\n }}\n className=\"z-[60] flex flex-col overflow-hidden rounded-xl border border-border bg-elevated shadow-lg\"\n >\n {showSearch ? searchBox(false) : null}\n <div className={cn('min-h-0 flex-1 overflow-y-auto', showSearch && 'mt-1')}>{optionList}</div>\n </div>,\n document.body,\n )\n : null}\n\n {mounted && !isDesktop\n ? createPortal(\n <AnimatePresence>\n {open ? (\n <div data-ui-overlay className=\"fixed inset-0 z-[60]\">\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n className=\"absolute inset-0 bg-overlay/40 backdrop-blur-[2px]\"\n onClick={() => setOpen(false)}\n />\n <motion.div\n initial={{ y: '100%' }}\n animate={{ y: 0 }}\n exit={{ y: '100%' }}\n transition={{ type: 'spring', damping: 34, stiffness: 340, mass: 0.8 }}\n className=\"absolute inset-x-0 bottom-0 flex max-h-[82vh] flex-col rounded-t-2xl border-t border-border bg-surface shadow-lg\"\n >\n <div className=\"flex items-center justify-center pt-2.5\">\n <span className=\"h-1.5 w-10 rounded-full bg-border-strong\" />\n </div>\n <div className=\"flex items-center justify-between px-4 pb-1 pt-2\">\n <span className=\"text-base font-semibold text-fg\">{sheetTitle ?? selectLabel}</span>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n aria-label={closeLabel}\n className=\"rounded-md p-1.5 text-fg-muted hover:bg-surface-hover\"\n >\n <X size={18} />\n </button>\n </div>\n {showSearch ? searchBox(true) : null}\n <div className=\"mt-1 min-h-0 flex-1 overflow-y-auto pb-[max(0.75rem,env(safe-area-inset-bottom))]\">\n {optionList}\n </div>\n </motion.div>\n </div>\n ) : null}\n </AnimatePresence>,\n document.body,\n )\n : null}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search-select.js","sourceRoot":"","sources":["../src/search-select.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n// SearchSelect — a slick, mobile-first searchable select / typeahead.\n// • Desktop: anchored dropdown (portaled to <body>) with a search box + kbd nav.\n// • Mobile (<lg): an iOS/Android-style bottom sheet with large tap targets.\n// Animated, portal'd sheet, Esc + click-out + scroll-lock, disabled options,\n// optgroup-style headers (via SelectOption.group), hints, clearable, remote mode.\n// Fully tokenized; i18n strings are injectable props with English defaults.\n\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport { Check, ChevronDown, Search, X } from 'lucide-react'\nimport { cn } from './utils'\n\nexport type SelectOption = {\n value: string\n label: string\n hint?: string\n disabled?: boolean\n /** Group header label; options sharing a group are batched under it. */\n group?: string\n}\n\nexport type SearchSelectProps = {\n value: string\n onChange: (value: string) => void\n options: SelectOption[]\n placeholder?: string\n searchPlaceholder?: string\n disabled?: boolean\n /** Adds a leading empty option (e.g. \"None\"). */\n clearable?: boolean\n emptyLabel?: string\n /** Title at the top of the mobile bottom sheet. */\n sheetTitle?: string\n ariaLabel?: string\n className?: string\n triggerClassName?: string\n /** Force the search box on/off. Auto: shown when >7 options or any groups. */\n searchable?: boolean\n /** Preserve server ordering + forward the query instead of local filtering. */\n remote?: boolean\n loading?: boolean\n statusMessage?: string\n statusTone?: 'muted' | 'error'\n onSearchChange?: (query: string) => void\n invalid?: boolean\n id?: string\n // Injectable labels (default English).\n noneLabel?: string\n noMatchesLabel?: string\n searchingLabel?: string\n selectLabel?: string\n closeLabel?: string\n}\n\nexport function SearchSelect({\n value,\n onChange,\n options,\n placeholder = 'Select…',\n searchPlaceholder = 'Search…',\n disabled = false,\n clearable = false,\n emptyLabel,\n sheetTitle,\n ariaLabel,\n className,\n triggerClassName,\n searchable,\n remote = false,\n loading = false,\n statusMessage,\n statusTone = 'muted',\n onSearchChange,\n invalid = false,\n id,\n noneLabel = 'None',\n noMatchesLabel = 'No matches',\n searchingLabel = 'Searching…',\n selectLabel = 'Select',\n closeLabel = 'Close',\n}: SearchSelectProps) {\n const [open, setOpen] = React.useState(false)\n const [query, setQuery] = React.useState('')\n const [highlight, setHighlight] = React.useState(0)\n const [isDesktop, setIsDesktop] = React.useState(true)\n const [mounted, setMounted] = React.useState(false)\n const wrapRef = React.useRef<HTMLDivElement>(null)\n const searchRef = React.useRef<HTMLInputElement>(null)\n const triggerRef = React.useRef<HTMLButtonElement>(null)\n const dropRef = React.useRef<HTMLDivElement>(null)\n // The menu is anchored from the edge that touches the trigger: `top` when it\n // opens downward, `bottom` when it opens upward. Anchoring an upward menu by\n // its top would place it a full maxHeight above the trigger no matter how\n // short the list actually is — a three-option menu would float hundreds of\n // pixels clear of the field it belongs to.\n const [pos, setPos] = React.useState<\n | { edge: 'top'; offset: number; left: number; width: number; maxHeight: number }\n | { edge: 'bottom'; offset: number; left: number; width: number; maxHeight: number }\n | null\n >(null)\n function place() {\n const r = triggerRef.current?.getBoundingClientRect()\n if (r) {\n // Collision-aware: open upward when the space below is tight, and clamp\n // the list to the available viewport space either way.\n const margin = 8\n const below = window.innerHeight - r.bottom - margin\n const above = r.top - margin\n const desired = 320\n const width = Math.min(Math.max(r.width, 208), window.innerWidth - margin * 2)\n const left = Math.min(Math.max(margin, r.left), Math.max(margin, window.innerWidth - width - margin))\n if (below >= Math.min(desired, 180) || below >= above) {\n setPos({\n edge: 'top',\n offset: r.bottom + 6,\n left,\n width,\n maxHeight: Math.max(160, Math.min(desired, Math.max(below, 160))),\n })\n } else {\n setPos({\n edge: 'bottom',\n offset: Math.max(margin, window.innerHeight - r.top + 6),\n left,\n width,\n maxHeight: Math.max(160, Math.min(desired, Math.max(above, 160))),\n })\n }\n }\n }\n\n React.useEffect(() => {\n setMounted(true)\n const mq = window.matchMedia('(min-width: 1024px)')\n const update = () => setIsDesktop(mq.matches)\n update()\n mq.addEventListener('change', update)\n return () => mq.removeEventListener('change', update)\n }, [])\n\n const allOptions = React.useMemo(\n () => (clearable ? [{ value: '', label: emptyLabel ?? noneLabel }, ...options] : options),\n [clearable, emptyLabel, noneLabel, options],\n )\n const selected = options.find((o) => o.value === value)\n const showEmpty = clearable && value === '' && !!emptyLabel\n const display = selected?.label ?? (showEmpty ? emptyLabel : placeholder)\n const isPlaceholder = !selected && !showEmpty\n\n const showSearch = searchable ?? (allOptions.length > 7 || allOptions.some((o) => o.group))\n\n const filtered = React.useMemo(() => {\n if (remote) return allOptions\n const q = query.trim().toLowerCase()\n if (!q) return allOptions\n return allOptions.filter(\n (o) => o.label.toLowerCase().includes(q) || o.group?.toLowerCase().includes(q),\n )\n }, [allOptions, query, remote])\n\n function firstEnabled(items: SelectOption[], start: number) {\n if (start >= 0 && start < items.length && !items[start]?.disabled) return start\n const fwd = items.findIndex((o) => !o.disabled)\n return fwd === -1 ? 0 : fwd\n }\n\n function openMenu() {\n if (disabled) return\n setQuery('')\n onSearchChange?.('')\n setHighlight(firstEnabled(allOptions, allOptions.findIndex((o) => o.value === value)))\n place()\n setOpen(true)\n setTimeout(() => searchRef.current?.focus(), 60)\n }\n function choose(v: string) {\n onChange(v)\n setOpen(false)\n }\n\n React.useEffect(() => {\n if (!open || !isDesktop) return\n function onDoc(e: MouseEvent) {\n const target = e.target as Node\n if (wrapRef.current?.contains(target) || dropRef.current?.contains(target)) return\n setOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n return () => document.removeEventListener('mousedown', onDoc)\n }, [open, isDesktop])\n\n React.useEffect(() => {\n if (!open || !isDesktop) return\n place()\n const onMove = () => place()\n window.addEventListener('scroll', onMove, true)\n window.addEventListener('resize', onMove)\n return () => {\n window.removeEventListener('scroll', onMove, true)\n window.removeEventListener('resize', onMove)\n }\n }, [open, isDesktop])\n\n React.useEffect(() => {\n if (!open) return\n const nextEnabled = (from: number, dir: 1 | -1) => {\n let index = from\n while (true) {\n index += dir\n if (index < 0 || index >= filtered.length) return from\n if (!filtered[index]?.disabled) return index\n }\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n e.preventDefault()\n setOpen(false)\n triggerRef.current?.focus()\n }\n else if (e.key === 'ArrowDown') {\n e.preventDefault()\n setHighlight((h) => nextEnabled(h, 1))\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n setHighlight((h) => nextEnabled(h, -1))\n } else if (e.key === 'Enter') {\n e.preventDefault()\n const o = filtered[highlight]\n if (o && !o.disabled) {\n onChange(o.value)\n setOpen(false)\n }\n }\n }\n document.addEventListener('keydown', onKey)\n let restore: (() => void) | undefined\n if (!isDesktop) {\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n restore = () => {\n document.body.style.overflow = prev\n }\n }\n return () => {\n document.removeEventListener('keydown', onKey)\n restore?.()\n }\n }, [filtered, highlight, isDesktop, onChange, open])\n\n const optionList = (\n <>\n <ul role=\"listbox\" className=\"py-1\">\n {filtered.length === 0 && !loading ? (\n <li role=\"option\" aria-disabled=\"true\" className=\"px-3 py-8 text-center text-sm text-fg-subtle\">\n {noMatchesLabel}\n </li>\n ) : null}\n {filtered.map((o, i) => {\n const active = o.value === value\n const prevGroup = i > 0 ? filtered[i - 1]?.group : undefined\n const header = o.group && o.group !== prevGroup ? o.group : null\n return (\n <li key={o.value || `__opt-${i}`} role=\"presentation\">\n {header ? (\n <div className=\"px-4 pb-1 pt-2.5 text-[11px] font-semibold tracking-wide text-fg-subtle uppercase lg:px-3\">\n {header}\n </div>\n ) : null}\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={active}\n disabled={o.disabled}\n onMouseEnter={() => !o.disabled && setHighlight(i)}\n onClick={() => !o.disabled && choose(o.value)}\n className={cn(\n 'flex h-12 w-full items-center gap-2.5 px-4 text-left text-[15px] transition-colors lg:h-9 lg:px-3 lg:text-sm',\n o.disabled\n ? 'cursor-not-allowed text-fg-subtle'\n : i === highlight\n ? 'bg-primary-subtle'\n : 'active:bg-surface-hover',\n !o.disabled && (active ? 'font-medium text-primary' : 'text-fg'),\n )}\n >\n <span className=\"min-w-0 flex-1 truncate\">\n {o.label}\n {o.hint ? <span className=\"ml-1.5 text-xs text-fg-subtle\">{o.hint}</span> : null}\n </span>\n {active ? <Check size={17} className=\"shrink-0 text-primary\" /> : null}\n </button>\n </li>\n )\n })}\n </ul>\n {loading || statusMessage ? (\n <div\n role={statusTone === 'error' ? 'alert' : 'status'}\n className={cn(\n 'border-t border-border px-3 py-2 text-xs',\n statusTone === 'error' ? 'text-danger' : 'text-fg-muted',\n )}\n >\n {loading ? searchingLabel : statusMessage}\n </div>\n ) : null}\n </>\n )\n\n const searchBox = (largeText: boolean) => (\n <div className=\"relative px-3 pt-3\">\n <Search size={16} className=\"absolute left-6 top-1/2 -translate-y-1/2 text-fg-subtle\" />\n <input\n ref={searchRef}\n value={query}\n onChange={(e) => {\n const next = e.target.value\n setQuery(next)\n onSearchChange?.(next)\n setHighlight(0)\n }}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n aria-busy={loading || undefined}\n className={cn(\n 'w-full rounded-lg border border-border bg-bg-subtle pl-9 pr-3 outline-none transition focus:border-primary focus:bg-surface focus:ring-2 focus:ring-ring/20',\n largeText ? 'h-11 text-base' : 'h-9 text-base sm:text-sm',\n )}\n />\n </div>\n )\n\n return (\n <div ref={wrapRef} className={cn('relative', className)}>\n <button\n ref={triggerRef}\n type=\"button\"\n id={id}\n onClick={() => (open ? setOpen(false) : openMenu())}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-invalid={invalid || undefined}\n className={cn(\n 'flex h-10 w-full items-center gap-2 rounded-lg border border-border bg-surface px-3 text-left text-sm shadow-sm transition',\n 'focus:border-primary focus:outline-none focus:ring-2 focus:ring-ring/25',\n disabled && 'cursor-not-allowed bg-bg-subtle opacity-70',\n open && 'border-primary ring-2 ring-ring/25',\n invalid && 'border-danger focus:border-danger focus:ring-danger/30',\n triggerClassName,\n )}\n >\n <span className={cn('min-w-0 flex-1 truncate', isPlaceholder ? 'text-fg-subtle' : 'text-fg')}>\n {display}\n </span>\n <ChevronDown\n size={16}\n className={cn('shrink-0 text-fg-subtle transition-transform', open && 'rotate-180')}\n />\n </button>\n\n {mounted && open && isDesktop && pos\n ? createPortal(\n <div\n ref={dropRef}\n data-ui-overlay\n style={{\n position: 'fixed',\n [pos.edge]: pos.offset,\n left: pos.left,\n width: Math.max(pos.width, 208),\n maxHeight: pos.maxHeight,\n }}\n className=\"z-[70] flex flex-col overflow-hidden rounded-xl border border-border bg-elevated shadow-lg\"\n >\n {showSearch ? searchBox(false) : null}\n <div className={cn('min-h-0 flex-1 overflow-y-auto', showSearch && 'mt-1')}>{optionList}</div>\n </div>,\n document.body,\n )\n : null}\n\n {mounted && !isDesktop\n ? createPortal(\n <AnimatePresence>\n {open ? (\n <div data-ui-overlay className=\"fixed inset-0 z-[70]\">\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n className=\"absolute inset-0 bg-overlay/40 backdrop-blur-[2px]\"\n onClick={() => setOpen(false)}\n />\n <motion.div\n initial={{ y: '100%' }}\n animate={{ y: 0 }}\n exit={{ y: '100%' }}\n transition={{ type: 'spring', damping: 34, stiffness: 340, mass: 0.8 }}\n className=\"absolute inset-x-0 bottom-0 flex max-h-[82vh] flex-col rounded-t-2xl border-t border-border bg-surface shadow-lg\"\n >\n <div className=\"flex items-center justify-center pt-2.5\">\n <span className=\"h-1.5 w-10 rounded-full bg-border-strong\" />\n </div>\n <div className=\"flex items-center justify-between px-4 pb-1 pt-2\">\n <span className=\"text-base font-semibold text-fg\">{sheetTitle ?? selectLabel}</span>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n aria-label={closeLabel}\n className=\"rounded-md p-1.5 text-fg-muted hover:bg-surface-hover\"\n >\n <X size={18} />\n </button>\n </div>\n {showSearch ? searchBox(true) : null}\n <div className=\"mt-1 min-h-0 flex-1 overflow-y-auto pb-[max(0.75rem,env(safe-area-inset-bottom))]\">\n {optionList}\n </div>\n </motion.div>\n </div>\n ) : null}\n </AnimatePresence>,\n document.body,\n )\n : null}\n </div>\n )\n}\n"]}
|
package/settings-layout.d.ts
CHANGED
|
@@ -35,10 +35,17 @@ export type SettingsNavGroup = {
|
|
|
35
35
|
label?: string;
|
|
36
36
|
items: SettingsNavItem[];
|
|
37
37
|
};
|
|
38
|
-
export declare function SettingsNav({ groups, activeKey, onSelect, className, }: {
|
|
38
|
+
export declare function SettingsNav({ groups, activeKey, onSelect, layout, className, }: {
|
|
39
39
|
groups: SettingsNavGroup[];
|
|
40
40
|
activeKey: string;
|
|
41
41
|
onSelect: (key: string) => void;
|
|
42
|
+
/**
|
|
43
|
+
* `rail` is the grouped vertical sidebar list. `responsive` renders the
|
|
44
|
+
* same list as one horizontally scrolling strip below the `md` breakpoint
|
|
45
|
+
* (group labels become separators, the active section stays scrolled into
|
|
46
|
+
* view) and as the rail from `md` up — one DOM, no duplicate controls.
|
|
47
|
+
*/
|
|
48
|
+
layout?: 'rail' | 'responsive';
|
|
42
49
|
className?: string;
|
|
43
50
|
}): React.JSX.Element;
|
|
44
51
|
export declare function SettingsShell({ title, description, back, actions, nav, activeKey, onSelect, children, contentWidth, linkRender, }: {
|
package/settings-layout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-layout.d.ts","sourceRoot":"","sources":["../src/settings-layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAInE,YAAY,EAAE,UAAU,EAAE,CAAA;AAS1B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAA;AAyBhE,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AACD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,WAAW,EACX,OAAO,EACP,MAAM,EACN,UAA8B,GAC/B,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,qBAqJA;
|
|
1
|
+
{"version":3,"file":"settings-layout.d.ts","sourceRoot":"","sources":["../src/settings-layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAInE,YAAY,EAAE,UAAU,EAAE,CAAA;AAS1B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAA;AAyBhE,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AACD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,WAAW,EACX,OAAO,EACP,MAAM,EACN,UAA8B,GAC/B,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,qBAqJA;AAUD,MAAM,MAAM,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAA;AAC7G,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,CAAA;AAE3E,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,EACT,QAAQ,EACR,MAAe,EACf,SAAS,GACV,EAAE;IACD,MAAM,EAAE,gBAAgB,EAAE,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,qBA2DA;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,GAAG,EACH,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,YAAuB,EACvB,UAA8B,GAC/B,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,GAAG,EAAE,gBAAgB,EAAE,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAA;IACzC,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,qBAiCA;AAMD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,SAAS,GACV,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,qBAiBA;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,WAAW,EACX,OAAO,EACP,OAAe,EACf,QAAQ,EACR,SAAS,GACV,EAAE;IACD,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,qBAgBA"}
|
package/settings-layout.js
CHANGED
|
@@ -43,12 +43,24 @@ export function AdminHub({ title, description, actions, groups, linkRender = def
|
|
|
43
43
|
}) })] }, gi));
|
|
44
44
|
}) }) })] }));
|
|
45
45
|
}
|
|
46
|
-
export function SettingsNav({ groups, activeKey, onSelect, className, }) {
|
|
47
|
-
|
|
46
|
+
export function SettingsNav({ groups, activeKey, onSelect, layout = 'rail', className, }) {
|
|
47
|
+
const responsive = layout === 'responsive';
|
|
48
|
+
const navRef = React.useRef(null);
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
if (!responsive)
|
|
51
|
+
return;
|
|
52
|
+
const strip = navRef.current;
|
|
53
|
+
const active = strip?.querySelector('[aria-current="page"]');
|
|
54
|
+
// A no-op at rail widths, where the nav never overflows horizontally.
|
|
55
|
+
if (strip && active && strip.scrollWidth > strip.clientWidth) {
|
|
56
|
+
strip.scrollLeft = Math.max(0, active.offsetLeft - (strip.clientWidth - active.offsetWidth) / 2);
|
|
57
|
+
}
|
|
58
|
+
}, [activeKey, responsive]);
|
|
59
|
+
return (_jsx("nav", { ref: navRef, className: cn('w-full', responsive && 'app-scroll relative overflow-x-auto md:overflow-x-visible', className), children: _jsx("div", { className: responsive ? 'flex w-max items-center gap-1 px-3 py-2 md:block md:w-auto md:space-y-5 md:p-0' : 'space-y-5', children: groups.map((group, gi) => (_jsxs("div", { className: responsive ? 'flex items-center gap-1 md:block md:space-y-1' : 'space-y-1', children: [responsive && gi > 0 ? _jsx("span", { "aria-hidden": true, className: "mx-1 h-5 w-px shrink-0 bg-border md:hidden" }) : null, group.label ? (_jsx("h3", { className: cn('px-2 text-xs font-semibold tracking-wider text-fg-subtle uppercase', responsive && 'hidden md:block'), children: group.label })) : null, _jsx("ul", { className: responsive ? 'flex items-center gap-1 md:block md:space-y-0.5' : 'space-y-0.5', children: group.items.map((item) => {
|
|
48
60
|
const active = item.key === activeKey;
|
|
49
|
-
return (_jsx("li", { children: _jsxs("button", { type: "button", "aria-current": active ? 'page' : undefined, onClick: () => onSelect(item.key), className: cn('flex
|
|
61
|
+
return (_jsx("li", { children: _jsxs("button", { type: "button", "aria-current": active ? 'page' : undefined, onClick: () => onSelect(item.key), className: cn('flex items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-sm transition-colors', responsive ? 'whitespace-nowrap md:w-full' : 'w-full', active
|
|
50
62
|
? 'bg-primary-subtle font-medium text-primary'
|
|
51
|
-
: 'text-fg-muted hover:bg-surface-hover hover:text-fg'), children: [_jsx("span", { className: cn('shrink-0 [&_svg]:size-[15px]', active ? 'text-primary' : 'text-fg-subtle'), children: item.icon }), _jsx("span", { className:
|
|
63
|
+
: 'text-fg-muted hover:bg-surface-hover hover:text-fg'), children: [_jsx("span", { className: cn('shrink-0 [&_svg]:size-[15px]', active ? 'text-primary' : 'text-fg-subtle'), children: item.icon }), _jsx("span", { className: cn('text-left', responsive ? 'md:flex-1 md:truncate' : 'flex-1 truncate'), children: item.label }), item.badge] }) }, item.key));
|
|
52
64
|
}) })] }, gi))) }) }));
|
|
53
65
|
}
|
|
54
66
|
export function SettingsShell({ title, description, back, actions, nav, activeKey, onSelect, children, contentWidth = 'narrow', linkRender = defaultLinkRender, }) {
|
|
@@ -59,7 +71,7 @@ export function SettingsShell({ title, description, back, actions, nav, activeKe
|
|
|
59
71
|
}[contentWidth];
|
|
60
72
|
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "shrink-0 border-b border-border bg-surface px-3 py-3 sm:px-6", children: _jsx(PageHeader, { title: title, description: description, actions: actions, back: back
|
|
61
73
|
? { ...back, render: (p) => linkRender({ href: p.href, className: p.className, children: p.children }) }
|
|
62
|
-
: undefined }) }), _jsxs("div", { className: "flex min-h-0 flex-1", children: [_jsx("aside", { className: "app-scroll
|
|
74
|
+
: undefined }) }), _jsxs("div", { className: "flex min-h-0 flex-1 flex-col md:flex-row", children: [_jsx("aside", { className: "app-scroll shrink-0 border-b border-border bg-surface md:w-52 md:overflow-y-auto md:border-r md:border-b-0 md:p-3 lg:w-60", children: _jsx(SettingsNav, { groups: nav, activeKey: activeKey, onSelect: onSelect, layout: "responsive" }) }), _jsx("div", { className: "app-scroll min-h-0 flex-1 overflow-y-auto bg-bg-subtle", children: _jsx("div", { className: cn('mx-auto w-full space-y-6 p-4 sm:p-6', contentWidthClass), children: children }) })] })] }));
|
|
63
75
|
}
|
|
64
76
|
// ---------------------------------------------------------------------------
|
|
65
77
|
// Content helpers used inside a SettingsShell.
|
package/settings-layout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-layout.js","sourceRoot":"","sources":["../src/settings-layout.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { ArrowRight, ArrowUpRight, Check } from 'lucide-react'\nimport { defaultLinkRender, type LinkRender } from './link-context'\nimport { PageHeader } from './page-header'\nimport { cn } from './utils'\n\nexport type { LinkRender }\n\n// ---------------------------------------------------------------------------\n// AdminHub — the settings LANDING page: grouped cards, each an accent-colored\n// icon chip + title/description + a hover arrow, linking to a sub-area.\n// Expressed through semantic tokens so a\n// consuming application's brand and dark theme remain authoritative.\n// ---------------------------------------------------------------------------\n\nexport type AdminHubAccent = 'teal' | 'violet' | 'amber' | 'sky'\n\nconst ACCENTS: Record<AdminHubAccent, { chip: string; border: string; link: string }> = {\n teal: {\n chip: 'bg-primary-subtle text-primary ring-primary/15',\n border: 'hover:border-primary/40',\n link: 'group-hover:text-primary',\n },\n violet: {\n chip: 'bg-info-subtle text-info ring-info/15',\n border: 'hover:border-info/40',\n link: 'group-hover:text-info',\n },\n amber: {\n chip: 'bg-warning-subtle text-warning ring-warning/15',\n border: 'hover:border-warning/40',\n link: 'group-hover:text-warning',\n },\n sky: {\n chip: 'bg-success-subtle text-success ring-success/15',\n border: 'hover:border-success/40',\n link: 'group-hover:text-success',\n },\n}\n\nexport type AdminHubCard = {\n href?: string\n title: string\n description?: string\n icon?: React.ReactNode\n badge?: React.ReactNode\n features?: string[]\n linkLabel?: string\n}\nexport type AdminHubGroup = {\n label?: string\n description?: string\n accent?: AdminHubAccent\n layout?: 'compact' | 'detailed'\n cards: AdminHubCard[]\n}\n\nexport function AdminHub({\n title,\n description,\n actions,\n groups,\n linkRender = defaultLinkRender,\n}: {\n title?: string\n description?: string\n actions?: React.ReactNode\n groups: AdminHubGroup[]\n linkRender?: LinkRender\n}) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {title || description ? (\n <div className=\"shrink-0 border-b border-border bg-surface px-3 py-3 sm:px-6\">\n <PageHeader title={title ?? ''} description={description} actions={actions} />\n </div>\n ) : null}\n <div className=\"app-scroll min-h-0 flex-1 overflow-y-auto bg-bg-subtle\">\n <div className=\"mx-auto w-full max-w-(--breakpoint-2xl) space-y-8 p-4 sm:p-6\">\n {groups.map((group, gi) => {\n const accent = ACCENTS[group.accent ?? 'teal']\n return (\n <section key={gi} className=\"space-y-3\">\n {group.label || group.description ? (\n <div className=\"space-y-1 px-0.5\">\n {group.label ? (\n <h2 className=\"text-xs font-semibold tracking-wider text-fg-subtle uppercase\">\n {group.label}\n </h2>\n ) : null}\n {group.description ? (\n <p className=\"max-w-3xl text-sm text-fg-muted\">{group.description}</p>\n ) : null}\n </div>\n ) : null}\n <div\n className={cn(\n 'grid grid-cols-1 gap-3 sm:grid-cols-2',\n group.layout === 'detailed' ? '2xl:grid-cols-3' : 'lg:grid-cols-3 2xl:grid-cols-4',\n )}\n >\n {group.cards.map((card, ci) => {\n const detailed = group.layout === 'detailed'\n const content = detailed ? (\n <>\n <div className=\"flex items-start gap-3\">\n <span\n className={cn(\n 'grid size-10 shrink-0 place-items-center rounded-lg ring-1 [&_svg]:size-[18px]',\n accent.chip,\n )}\n >\n {card.icon}\n </span>\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"font-mono text-sm font-semibold text-fg\">{card.title}</h3>\n {card.badge}\n </div>\n {card.description ? (\n <p className=\"text-sm leading-relaxed text-fg-muted\">\n {card.description}\n </p>\n ) : null}\n </div>\n </div>\n {card.features?.length ? (\n <ul className=\"mt-4 space-y-2 border-t border-border-subtle pt-4\">\n {card.features.map((feature) => (\n <li\n key={feature}\n className=\"flex gap-2 text-xs leading-relaxed text-fg-muted\"\n >\n <Check\n className=\"mt-0.5 size-3.5 shrink-0 text-primary\"\n aria-hidden\n />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n ) : null}\n {card.href && card.linkLabel ? (\n <span\n className={cn(\n 'mt-auto flex items-center gap-1.5 pt-4 text-xs font-semibold text-fg-muted',\n accent.link,\n )}\n >\n {card.linkLabel}\n <ArrowRight\n className=\"size-3.5 transition-transform group-hover:translate-x-0.5\"\n aria-hidden\n />\n </span>\n ) : null}\n </>\n ) : (\n <>\n <span\n className={cn(\n 'grid size-10 shrink-0 place-items-center rounded-lg ring-1',\n accent.chip,\n )}\n >\n {card.icon}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <h3 className=\"truncate text-sm font-semibold text-fg\">{card.title}</h3>\n {card.badge}\n </div>\n {card.description ? (\n <p className=\"truncate text-xs text-fg-muted\">{card.description}</p>\n ) : null}\n </div>\n {card.href ? (\n <ArrowUpRight\n size={15}\n aria-hidden\n className={cn(\n 'shrink-0 text-fg-subtle opacity-0 transition-all duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:opacity-100',\n accent.link,\n )}\n />\n ) : null}\n </>\n )\n const className = cn(\n 'group rounded-xl border border-border bg-surface shadow-sm transition-all',\n detailed ? 'flex h-full flex-col p-4' : 'flex items-center gap-3 p-3.5',\n card.href && 'hover:shadow-md',\n card.href && accent.border,\n )\n\n return card.href ? (\n <React.Fragment key={ci}>\n {linkRender({\n href: card.href,\n title: card.description,\n className,\n children: content,\n })}\n </React.Fragment>\n ) : (\n <article key={ci} className={className}>\n {content}\n </article>\n )\n })}\n </div>\n </section>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// SettingsShell — the SIDEBAR settings area: a fixed header (with a back link\n// to the hub), and a two-pane body — a grouped nav rail beside the active\n// content, each pane scrolling independently. The\n// setup/layout.tsx + SetupNav.tsx.\n// ---------------------------------------------------------------------------\n\nexport type SettingsNavItem = { key: string; label: string; icon?: React.ReactNode; badge?: React.ReactNode }\nexport type SettingsNavGroup = { label?: string; items: SettingsNavItem[] }\n\nexport function SettingsNav({\n groups,\n activeKey,\n onSelect,\n className,\n}: {\n groups: SettingsNavGroup[]\n activeKey: string\n onSelect: (key: string) => void\n className?: string\n}) {\n return (\n <nav className={cn('w-full', className)}>\n <div className=\"space-y-5\">\n {groups.map((group, gi) => (\n <div key={gi} className=\"space-y-1\">\n {group.label ? (\n <h3 className=\"px-2 text-xs font-semibold tracking-wider text-fg-subtle uppercase\">\n {group.label}\n </h3>\n ) : null}\n <ul className=\"space-y-0.5\">\n {group.items.map((item) => {\n const active = item.key === activeKey\n return (\n <li key={item.key}>\n <button\n type=\"button\"\n aria-current={active ? 'page' : undefined}\n onClick={() => onSelect(item.key)}\n className={cn(\n 'flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-sm transition-colors',\n active\n ? 'bg-primary-subtle font-medium text-primary'\n : 'text-fg-muted hover:bg-surface-hover hover:text-fg',\n )}\n >\n <span className={cn('shrink-0 [&_svg]:size-[15px]', active ? 'text-primary' : 'text-fg-subtle')}>\n {item.icon}\n </span>\n <span className=\"flex-1 truncate text-left\">{item.label}</span>\n {item.badge}\n </button>\n </li>\n )\n })}\n </ul>\n </div>\n ))}\n </div>\n </nav>\n )\n}\n\nexport function SettingsShell({\n title,\n description,\n back,\n actions,\n nav,\n activeKey,\n onSelect,\n children,\n contentWidth = 'narrow',\n linkRender = defaultLinkRender,\n}: {\n title: string\n description?: string\n back?: { href: string; label: string }\n actions?: React.ReactNode\n nav: SettingsNavGroup[]\n activeKey: string\n onSelect: (key: string) => void\n children: React.ReactNode\n /**\n * Bounds the active pane without changing the navigation shell.\n * Settings forms stay narrow by default; record-heavy administration\n * workspaces can opt into a wider or edge-to-edge canvas.\n */\n contentWidth?: 'narrow' | 'wide' | 'full'\n linkRender?: LinkRender\n}) {\n const contentWidthClass = {\n narrow: 'max-w-5xl',\n wide: 'max-w-(--breakpoint-2xl)',\n full: 'max-w-none',\n }[contentWidth]\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"shrink-0 border-b border-border bg-surface px-3 py-3 sm:px-6\">\n <PageHeader\n title={title}\n description={description}\n actions={actions}\n back={\n back\n ? { ...back, render: (p) => linkRender({ href: p.href, className: p.className, children: p.children }) }\n : undefined\n }\n />\n </div>\n <div className=\"flex min-h-0 flex-1\">\n <aside className=\"app-scroll w-44 shrink-0 overflow-y-auto border-r border-border bg-surface p-3 sm:w-52 lg:w-60\">\n <SettingsNav groups={nav} activeKey={activeKey} onSelect={onSelect} />\n </aside>\n <div className=\"app-scroll min-h-0 flex-1 overflow-y-auto bg-bg-subtle\">\n <div className={cn('mx-auto w-full space-y-6 p-4 sm:p-6', contentWidthClass)}>\n {children}\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Content helpers used inside a SettingsShell.\n// ---------------------------------------------------------------------------\n\nexport function SettingsSection({\n title,\n description,\n footer,\n children,\n className,\n}: {\n title?: string\n description?: string\n footer?: React.ReactNode\n children: React.ReactNode\n className?: string\n}) {\n return (\n <section className={cn('overflow-hidden rounded-xl border border-border bg-surface', className)}>\n {title || description ? (\n <div className=\"border-b border-border px-5 py-4\">\n {title ? <h2 className=\"text-sm font-semibold text-fg\">{title}</h2> : null}\n {description ? <p className=\"mt-0.5 text-sm text-fg-muted\">{description}</p> : null}\n </div>\n ) : null}\n <div className=\"divide-y divide-border\">{children}</div>\n {footer ? (\n <div className=\"flex items-center justify-end gap-2 border-t border-border bg-bg-subtle px-5 py-3\">\n {footer}\n </div>\n ) : null}\n </section>\n )\n}\n\nexport function SettingsRow({\n title,\n description,\n control,\n stacked = false,\n children,\n className,\n}: {\n title: React.ReactNode\n description?: React.ReactNode\n control?: React.ReactNode\n stacked?: boolean\n children?: React.ReactNode\n className?: string\n}) {\n const right = control ?? children\n return (\n <div\n className={cn(\n stacked ? 'space-y-2 px-5 py-4' : 'flex items-center justify-between gap-4 px-5 py-4',\n className,\n )}\n >\n <div className=\"min-w-0 space-y-0.5\">\n <div className=\"text-sm font-medium text-fg\">{title}</div>\n {description ? <div className=\"text-sm text-fg-muted\">{description}</div> : null}\n </div>\n {right ? <div className={cn(stacked ? 'w-full' : 'shrink-0')}>{right}</div> : null}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"settings-layout.js","sourceRoot":"","sources":["../src/settings-layout.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { ArrowRight, ArrowUpRight, Check } from 'lucide-react'\nimport { defaultLinkRender, type LinkRender } from './link-context'\nimport { PageHeader } from './page-header'\nimport { cn } from './utils'\n\nexport type { LinkRender }\n\n// ---------------------------------------------------------------------------\n// AdminHub — the settings LANDING page: grouped cards, each an accent-colored\n// icon chip + title/description + a hover arrow, linking to a sub-area.\n// Expressed through semantic tokens so a\n// consuming application's brand and dark theme remain authoritative.\n// ---------------------------------------------------------------------------\n\nexport type AdminHubAccent = 'teal' | 'violet' | 'amber' | 'sky'\n\nconst ACCENTS: Record<AdminHubAccent, { chip: string; border: string; link: string }> = {\n teal: {\n chip: 'bg-primary-subtle text-primary ring-primary/15',\n border: 'hover:border-primary/40',\n link: 'group-hover:text-primary',\n },\n violet: {\n chip: 'bg-info-subtle text-info ring-info/15',\n border: 'hover:border-info/40',\n link: 'group-hover:text-info',\n },\n amber: {\n chip: 'bg-warning-subtle text-warning ring-warning/15',\n border: 'hover:border-warning/40',\n link: 'group-hover:text-warning',\n },\n sky: {\n chip: 'bg-success-subtle text-success ring-success/15',\n border: 'hover:border-success/40',\n link: 'group-hover:text-success',\n },\n}\n\nexport type AdminHubCard = {\n href?: string\n title: string\n description?: string\n icon?: React.ReactNode\n badge?: React.ReactNode\n features?: string[]\n linkLabel?: string\n}\nexport type AdminHubGroup = {\n label?: string\n description?: string\n accent?: AdminHubAccent\n layout?: 'compact' | 'detailed'\n cards: AdminHubCard[]\n}\n\nexport function AdminHub({\n title,\n description,\n actions,\n groups,\n linkRender = defaultLinkRender,\n}: {\n title?: string\n description?: string\n actions?: React.ReactNode\n groups: AdminHubGroup[]\n linkRender?: LinkRender\n}) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {title || description ? (\n <div className=\"shrink-0 border-b border-border bg-surface px-3 py-3 sm:px-6\">\n <PageHeader title={title ?? ''} description={description} actions={actions} />\n </div>\n ) : null}\n <div className=\"app-scroll min-h-0 flex-1 overflow-y-auto bg-bg-subtle\">\n <div className=\"mx-auto w-full max-w-(--breakpoint-2xl) space-y-8 p-4 sm:p-6\">\n {groups.map((group, gi) => {\n const accent = ACCENTS[group.accent ?? 'teal']\n return (\n <section key={gi} className=\"space-y-3\">\n {group.label || group.description ? (\n <div className=\"space-y-1 px-0.5\">\n {group.label ? (\n <h2 className=\"text-xs font-semibold tracking-wider text-fg-subtle uppercase\">\n {group.label}\n </h2>\n ) : null}\n {group.description ? (\n <p className=\"max-w-3xl text-sm text-fg-muted\">{group.description}</p>\n ) : null}\n </div>\n ) : null}\n <div\n className={cn(\n 'grid grid-cols-1 gap-3 sm:grid-cols-2',\n group.layout === 'detailed' ? '2xl:grid-cols-3' : 'lg:grid-cols-3 2xl:grid-cols-4',\n )}\n >\n {group.cards.map((card, ci) => {\n const detailed = group.layout === 'detailed'\n const content = detailed ? (\n <>\n <div className=\"flex items-start gap-3\">\n <span\n className={cn(\n 'grid size-10 shrink-0 place-items-center rounded-lg ring-1 [&_svg]:size-[18px]',\n accent.chip,\n )}\n >\n {card.icon}\n </span>\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"font-mono text-sm font-semibold text-fg\">{card.title}</h3>\n {card.badge}\n </div>\n {card.description ? (\n <p className=\"text-sm leading-relaxed text-fg-muted\">\n {card.description}\n </p>\n ) : null}\n </div>\n </div>\n {card.features?.length ? (\n <ul className=\"mt-4 space-y-2 border-t border-border-subtle pt-4\">\n {card.features.map((feature) => (\n <li\n key={feature}\n className=\"flex gap-2 text-xs leading-relaxed text-fg-muted\"\n >\n <Check\n className=\"mt-0.5 size-3.5 shrink-0 text-primary\"\n aria-hidden\n />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n ) : null}\n {card.href && card.linkLabel ? (\n <span\n className={cn(\n 'mt-auto flex items-center gap-1.5 pt-4 text-xs font-semibold text-fg-muted',\n accent.link,\n )}\n >\n {card.linkLabel}\n <ArrowRight\n className=\"size-3.5 transition-transform group-hover:translate-x-0.5\"\n aria-hidden\n />\n </span>\n ) : null}\n </>\n ) : (\n <>\n <span\n className={cn(\n 'grid size-10 shrink-0 place-items-center rounded-lg ring-1',\n accent.chip,\n )}\n >\n {card.icon}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <h3 className=\"truncate text-sm font-semibold text-fg\">{card.title}</h3>\n {card.badge}\n </div>\n {card.description ? (\n <p className=\"truncate text-xs text-fg-muted\">{card.description}</p>\n ) : null}\n </div>\n {card.href ? (\n <ArrowUpRight\n size={15}\n aria-hidden\n className={cn(\n 'shrink-0 text-fg-subtle opacity-0 transition-all duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:opacity-100',\n accent.link,\n )}\n />\n ) : null}\n </>\n )\n const className = cn(\n 'group rounded-xl border border-border bg-surface shadow-sm transition-all',\n detailed ? 'flex h-full flex-col p-4' : 'flex items-center gap-3 p-3.5',\n card.href && 'hover:shadow-md',\n card.href && accent.border,\n )\n\n return card.href ? (\n <React.Fragment key={ci}>\n {linkRender({\n href: card.href,\n title: card.description,\n className,\n children: content,\n })}\n </React.Fragment>\n ) : (\n <article key={ci} className={className}>\n {content}\n </article>\n )\n })}\n </div>\n </section>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// SettingsShell — the SIDEBAR settings area: a fixed header (with a back link\n// to the hub), and a two-pane body — a grouped nav rail beside the active\n// content, each pane scrolling independently. Below the `md` breakpoint the\n// rail collapses into a horizontally scrolling section strip above the\n// content, so phones keep the full content width.\n// ---------------------------------------------------------------------------\n\nexport type SettingsNavItem = { key: string; label: string; icon?: React.ReactNode; badge?: React.ReactNode }\nexport type SettingsNavGroup = { label?: string; items: SettingsNavItem[] }\n\nexport function SettingsNav({\n groups,\n activeKey,\n onSelect,\n layout = 'rail',\n className,\n}: {\n groups: SettingsNavGroup[]\n activeKey: string\n onSelect: (key: string) => void\n /**\n * `rail` is the grouped vertical sidebar list. `responsive` renders the\n * same list as one horizontally scrolling strip below the `md` breakpoint\n * (group labels become separators, the active section stays scrolled into\n * view) and as the rail from `md` up — one DOM, no duplicate controls.\n */\n layout?: 'rail' | 'responsive'\n className?: string\n}) {\n const responsive = layout === 'responsive'\n const navRef = React.useRef<HTMLElement>(null)\n React.useEffect(() => {\n if (!responsive) return\n const strip = navRef.current\n const active = strip?.querySelector<HTMLElement>('[aria-current=\"page\"]')\n // A no-op at rail widths, where the nav never overflows horizontally.\n if (strip && active && strip.scrollWidth > strip.clientWidth) {\n strip.scrollLeft = Math.max(0, active.offsetLeft - (strip.clientWidth - active.offsetWidth) / 2)\n }\n }, [activeKey, responsive])\n\n return (\n <nav\n ref={navRef}\n className={cn('w-full', responsive && 'app-scroll relative overflow-x-auto md:overflow-x-visible', className)}\n >\n <div className={responsive ? 'flex w-max items-center gap-1 px-3 py-2 md:block md:w-auto md:space-y-5 md:p-0' : 'space-y-5'}>\n {groups.map((group, gi) => (\n <div key={gi} className={responsive ? 'flex items-center gap-1 md:block md:space-y-1' : 'space-y-1'}>\n {responsive && gi > 0 ? <span aria-hidden className=\"mx-1 h-5 w-px shrink-0 bg-border md:hidden\" /> : null}\n {group.label ? (\n <h3 className={cn('px-2 text-xs font-semibold tracking-wider text-fg-subtle uppercase', responsive && 'hidden md:block')}>\n {group.label}\n </h3>\n ) : null}\n <ul className={responsive ? 'flex items-center gap-1 md:block md:space-y-0.5' : 'space-y-0.5'}>\n {group.items.map((item) => {\n const active = item.key === activeKey\n return (\n <li key={item.key}>\n <button\n type=\"button\"\n aria-current={active ? 'page' : undefined}\n onClick={() => onSelect(item.key)}\n className={cn(\n 'flex items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-sm transition-colors',\n responsive ? 'whitespace-nowrap md:w-full' : 'w-full',\n active\n ? 'bg-primary-subtle font-medium text-primary'\n : 'text-fg-muted hover:bg-surface-hover hover:text-fg',\n )}\n >\n <span className={cn('shrink-0 [&_svg]:size-[15px]', active ? 'text-primary' : 'text-fg-subtle')}>\n {item.icon}\n </span>\n <span className={cn('text-left', responsive ? 'md:flex-1 md:truncate' : 'flex-1 truncate')}>{item.label}</span>\n {item.badge}\n </button>\n </li>\n )\n })}\n </ul>\n </div>\n ))}\n </div>\n </nav>\n )\n}\n\nexport function SettingsShell({\n title,\n description,\n back,\n actions,\n nav,\n activeKey,\n onSelect,\n children,\n contentWidth = 'narrow',\n linkRender = defaultLinkRender,\n}: {\n title: string\n description?: string\n back?: { href: string; label: string }\n actions?: React.ReactNode\n nav: SettingsNavGroup[]\n activeKey: string\n onSelect: (key: string) => void\n children: React.ReactNode\n /**\n * Bounds the active pane without changing the navigation shell.\n * Settings forms stay narrow by default; record-heavy administration\n * workspaces can opt into a wider or edge-to-edge canvas.\n */\n contentWidth?: 'narrow' | 'wide' | 'full'\n linkRender?: LinkRender\n}) {\n const contentWidthClass = {\n narrow: 'max-w-5xl',\n wide: 'max-w-(--breakpoint-2xl)',\n full: 'max-w-none',\n }[contentWidth]\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"shrink-0 border-b border-border bg-surface px-3 py-3 sm:px-6\">\n <PageHeader\n title={title}\n description={description}\n actions={actions}\n back={\n back\n ? { ...back, render: (p) => linkRender({ href: p.href, className: p.className, children: p.children }) }\n : undefined\n }\n />\n </div>\n <div className=\"flex min-h-0 flex-1 flex-col md:flex-row\">\n <aside className=\"app-scroll shrink-0 border-b border-border bg-surface md:w-52 md:overflow-y-auto md:border-r md:border-b-0 md:p-3 lg:w-60\">\n <SettingsNav groups={nav} activeKey={activeKey} onSelect={onSelect} layout=\"responsive\" />\n </aside>\n <div className=\"app-scroll min-h-0 flex-1 overflow-y-auto bg-bg-subtle\">\n <div className={cn('mx-auto w-full space-y-6 p-4 sm:p-6', contentWidthClass)}>\n {children}\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Content helpers used inside a SettingsShell.\n// ---------------------------------------------------------------------------\n\nexport function SettingsSection({\n title,\n description,\n footer,\n children,\n className,\n}: {\n title?: string\n description?: string\n footer?: React.ReactNode\n children: React.ReactNode\n className?: string\n}) {\n return (\n <section className={cn('overflow-hidden rounded-xl border border-border bg-surface', className)}>\n {title || description ? (\n <div className=\"border-b border-border px-5 py-4\">\n {title ? <h2 className=\"text-sm font-semibold text-fg\">{title}</h2> : null}\n {description ? <p className=\"mt-0.5 text-sm text-fg-muted\">{description}</p> : null}\n </div>\n ) : null}\n <div className=\"divide-y divide-border\">{children}</div>\n {footer ? (\n <div className=\"flex items-center justify-end gap-2 border-t border-border bg-bg-subtle px-5 py-3\">\n {footer}\n </div>\n ) : null}\n </section>\n )\n}\n\nexport function SettingsRow({\n title,\n description,\n control,\n stacked = false,\n children,\n className,\n}: {\n title: React.ReactNode\n description?: React.ReactNode\n control?: React.ReactNode\n stacked?: boolean\n children?: React.ReactNode\n className?: string\n}) {\n const right = control ?? children\n return (\n <div\n className={cn(\n stacked ? 'space-y-2 px-5 py-4' : 'flex items-center justify-between gap-4 px-5 py-4',\n className,\n )}\n >\n <div className=\"min-w-0 space-y-0.5\">\n <div className=\"text-sm font-medium text-fg\">{title}</div>\n {description ? <div className=\"text-sm text-fg-muted\">{description}</div> : null}\n </div>\n {right ? <div className={cn(stacked ? 'w-full' : 'shrink-0')}>{right}</div> : null}\n </div>\n )\n}\n"]}
|
package/table.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../src/table.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../src/table.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,GAAG;IAChE;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED,eAAO,MAAM,KAAK;IAPhB;;;OAGG;yBACkB,MAAM;0CAc5B,CAAA;AAGD,eAAO,MAAM,WAAW,+HAYtB,CAAA;AAGF,eAAO,MAAM,SAAS,+HAKpB,CAAA;AAGF,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,mBAAmB,CAAC,GAAG;IACtE,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,eAAO,MAAM,QAAQ;IAJnB,yDAAyD;gBAC7C,OAAO;6CAkBpB,CAAA;AAGD,eAAO,MAAM,SAAS,2HAYpB,CAAA;AAGF,eAAO,MAAM,SAAS,2HAKpB,CAAA"}
|
package/table.js
CHANGED
package/table.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.tsx"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAU5B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CACnC,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CACpD,cACE,SAAS,EAAE,EAAE,CACX,6EAA6E,EAC7E,kBAAkB,CACnB,YAED,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,GACrF,CACP,CACF,CAAA;AACD,KAAK,CAAC,WAAW,GAAG,OAAO,CAAA;AAE3B,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAGzC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,gBACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CACX,yFAAyF,EACzF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC,CAAA;AACF,WAAW,CAAC,WAAW,GAAG,aAAa,CAAA;AAEvC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CACvF,CAAC,CAAA;AACF,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA;AAOnC,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CACtC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;AAC3C,qEAAqE;AACrE,yEAAyE;AACzE,4EAA4E;AAC5E,aACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CACX,wHAAwH,EACxH,CAAC,SAAS,IAAI,YAAY,EAC1B,SAAS,CACV,KACG,KAAK,GACT,CACH,CACF,CAAA;AACD,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAA;AAEjC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,aACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CACX,4FAA4F,EAC5F,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC,CAAA;AACF,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA;AAEnC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,aAAI,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,wBAAwB,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAChF,CAAC,CAAA;AACF,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA","sourcesContent":["import * as React from 'react'\nimport { cn } from './utils'\n\nexport type TableProps = React.HTMLAttributes<HTMLTableElement> & {\n /**\n * Classes for the table's scrolling surface. Use this to remove the default\n * card treatment when the table already lives inside a bordered workspace.\n */\n containerClassName?: string\n}\n\nexport const Table = React.forwardRef<HTMLTableElement, TableProps>(\n ({ className, containerClassName, ...props }, ref) => (\n <div\n className={cn(\n 'w-full overflow-x-auto rounded-lg border border-border bg-surface shadow-sm',\n containerClassName,\n )}\n >\n <table ref={ref} className={cn('w-full caption-bottom text-sm', className)} {...props} />\n </div>\n ),\n)\nTable.displayName = 'Table'\n\nexport const TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead\n ref={ref}\n className={cn(\n 'sticky top-0 z-10 bg-bg-subtle/95 backdrop-blur-sm [&_tr]:border-b [&_tr]:border-border',\n className,\n )}\n {...props}\n />\n))\nTableHeader.displayName = 'TableHeader'\n\nexport const TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />\n))\nTableBody.displayName = 'TableBody'\n\nexport type TableRowProps = React.HTMLAttributes<HTMLTableRowElement> & {\n /** Disable the staggered entrance (e.g. header rows). */\n noAnimate?: boolean\n}\n\nexport const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(\n ({ className, noAnimate, ...props }, ref) => (\n // Staggered entrance is pure CSS (`.appkit-row` + nth-child delay in\n // tokens.css) — no JS index, so it's StrictMode- and hydration-safe, and\n // visible-by-default (@starting-style) so it never strands in a hidden tab.\n <tr\n ref={ref}\n className={cn(\n 'border-b border-border-subtle transition-colors duration-150 hover:bg-surface-hover data-[state=selected]:bg-bg-subtle',\n !noAnimate && 'appkit-row',\n className,\n )}\n {...props}\n />\n ),\n)\nTableRow.displayName = 'TableRow'\n\nexport const TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n 'h-10 px-3 text-left align-middle text-xs font-medium tracking-wide text-fg-muted uppercase',\n className,\n )}\n {...props}\n />\n))\nTableHead.displayName = 'TableHead'\n\nexport const TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td ref={ref} className={cn('px-3 py-3 align-middle', className)} {...props} />\n))\nTableCell.displayName = 'TableCell'\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type Theme = 'light' | 'dark' | 'system';
|
|
2
|
+
export type ResolvedTheme = 'light' | 'dark';
|
|
3
|
+
/**
|
|
4
|
+
* How an app's theme preference behaves. The provider and the pre-paint script
|
|
5
|
+
* must receive the same options so the first paint matches the hydrated theme.
|
|
6
|
+
*
|
|
7
|
+
* - `storageKey` — the localStorage key holding an explicit choice.
|
|
8
|
+
* - `defaultTheme` — the theme used until the user picks one (`'system'` when
|
|
9
|
+
* omitted). A dark-by-default app passes `'dark'`.
|
|
10
|
+
* - `enableSystem: false` — a light/dark-only app: `'system'` is never offered
|
|
11
|
+
* or honoured, so `defaultTheme` must be `'light'` or `'dark'`.
|
|
12
|
+
*/
|
|
13
|
+
export type ThemeOptions = {
|
|
14
|
+
storageKey?: string;
|
|
15
|
+
} & ({
|
|
16
|
+
enableSystem?: true;
|
|
17
|
+
defaultTheme?: Theme;
|
|
18
|
+
} | {
|
|
19
|
+
enableSystem: false;
|
|
20
|
+
defaultTheme: ResolvedTheme;
|
|
21
|
+
});
|
|
22
|
+
export type ResolvedThemeOptions = {
|
|
23
|
+
storageKey: string;
|
|
24
|
+
defaultTheme: Theme;
|
|
25
|
+
enableSystem: boolean;
|
|
26
|
+
};
|
|
27
|
+
export declare function resolveThemeOptions(options?: ThemeOptions): ResolvedThemeOptions;
|
|
28
|
+
/** The theme a stored value selects under these options (invalid or disallowed values fall back to the default). */
|
|
29
|
+
export declare function themeFromStorage(stored: string | null, options: ResolvedThemeOptions): Theme;
|
|
30
|
+
//# sourceMappingURL=theme-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-options.d.ts","sourceRoot":"","sources":["../src/theme-options.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAC/C,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAA;AAE5C;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,CACjD;IAAE,YAAY,CAAC,EAAE,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,GAC7C;IAAE,YAAY,EAAE,KAAK,CAAC;IAAC,YAAY,EAAE,aAAa,CAAA;CAAE,CACvD,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,KAAK,CAAA;IACnB,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,YAAiB,GAAG,oBAAoB,CAQpF;AAED,oHAAoH;AACpH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,oBAAoB,GAAG,KAAK,CAI5F"}
|
package/theme-options.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Theme preference rules shared by `ThemeProvider` and `getThemeScript`, so the
|
|
2
|
+
// pre-paint class and the hydrated theme can never disagree.
|
|
3
|
+
export function resolveThemeOptions(options = {}) {
|
|
4
|
+
const enableSystem = options.enableSystem !== false;
|
|
5
|
+
const requested = options.defaultTheme ?? 'system';
|
|
6
|
+
return {
|
|
7
|
+
storageKey: options.storageKey ?? 'theme',
|
|
8
|
+
enableSystem,
|
|
9
|
+
defaultTheme: !enableSystem && requested === 'system' ? 'light' : requested,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** The theme a stored value selects under these options (invalid or disallowed values fall back to the default). */
|
|
13
|
+
export function themeFromStorage(stored, options) {
|
|
14
|
+
if (stored === 'light' || stored === 'dark')
|
|
15
|
+
return stored;
|
|
16
|
+
if (stored === 'system' && options.enableSystem)
|
|
17
|
+
return stored;
|
|
18
|
+
return options.defaultTheme;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=theme-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-options.js","sourceRoot":"","sources":["../src/theme-options.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,6DAA6D;AA0B7D,MAAM,UAAU,mBAAmB,CAAC,UAAwB,EAAE;IAC5D,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,KAAK,KAAK,CAAA;IACnD,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,IAAI,QAAQ,CAAA;IAClD,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,OAAO;QACzC,YAAY;QACZ,YAAY,EAAE,CAAC,YAAY,IAAI,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;KAC5E,CAAA;AACH,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,gBAAgB,CAAC,MAAqB,EAAE,OAA6B;IACnF,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAA;IAC1D,IAAI,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,YAAY;QAAE,OAAO,MAAM,CAAA;IAC9D,OAAO,OAAO,CAAC,YAAY,CAAA;AAC7B,CAAC","sourcesContent":["// Theme preference rules shared by `ThemeProvider` and `getThemeScript`, so the\n// pre-paint class and the hydrated theme can never disagree.\n\nexport type Theme = 'light' | 'dark' | 'system'\nexport type ResolvedTheme = 'light' | 'dark'\n\n/**\n * How an app's theme preference behaves. The provider and the pre-paint script\n * must receive the same options so the first paint matches the hydrated theme.\n *\n * - `storageKey` — the localStorage key holding an explicit choice.\n * - `defaultTheme` — the theme used until the user picks one (`'system'` when\n * omitted). A dark-by-default app passes `'dark'`.\n * - `enableSystem: false` — a light/dark-only app: `'system'` is never offered\n * or honoured, so `defaultTheme` must be `'light'` or `'dark'`.\n */\nexport type ThemeOptions = { storageKey?: string } & (\n | { enableSystem?: true; defaultTheme?: Theme }\n | { enableSystem: false; defaultTheme: ResolvedTheme }\n)\n\nexport type ResolvedThemeOptions = {\n storageKey: string\n defaultTheme: Theme\n enableSystem: boolean\n}\n\nexport function resolveThemeOptions(options: ThemeOptions = {}): ResolvedThemeOptions {\n const enableSystem = options.enableSystem !== false\n const requested = options.defaultTheme ?? 'system'\n return {\n storageKey: options.storageKey ?? 'theme',\n enableSystem,\n defaultTheme: !enableSystem && requested === 'system' ? 'light' : requested,\n }\n}\n\n/** The theme a stored value selects under these options (invalid or disallowed values fall back to the default). */\nexport function themeFromStorage(stored: string | null, options: ResolvedThemeOptions): Theme {\n if (stored === 'light' || stored === 'dark') return stored\n if (stored === 'system' && options.enableSystem) return stored\n return options.defaultTheme\n}\n"]}
|
package/theme-script.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { type ThemeOptions } from './theme-options.js';
|
|
2
|
+
export type { ResolvedTheme, Theme, ThemeOptions } from './theme-options.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inline script body that applies the stored (or default) theme class to
|
|
5
|
+
* `<html>` before first paint. Use it with a framework's pre-hydration script
|
|
6
|
+
* facility (for example `next/script` with `strategy="beforeInteractive"`), or
|
|
7
|
+
* inject it into a static `index.html` at build time (for example from a Vite
|
|
8
|
+
* `transformIndexHtml` hook). `'system'` leaves both classes off so the
|
|
9
|
+
* stylesheet's `prefers-color-scheme` defaults apply.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getThemeScript(options?: ThemeOptions): string;
|
|
3
12
|
//# sourceMappingURL=theme-script.d.ts.map
|
package/theme-script.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-script.d.ts","sourceRoot":"","sources":["../src/theme-script.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme-script.d.ts","sourceRoot":"","sources":["../src/theme-script.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAExE,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEzE;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CAIjE"}
|
package/theme-script.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
// The pre-paint theme script. Framework-neutral: no React and no browser
|
|
2
|
+
// globals at import time, so it is safe in Server Components, in
|
|
3
|
+
// `vite.config`/`next.config`, and in build scripts (`@braedonsaunders/appkit-ui/theme-script`).
|
|
4
|
+
import { resolveThemeOptions } from './theme-options.js';
|
|
5
|
+
/**
|
|
6
|
+
* Inline script body that applies the stored (or default) theme class to
|
|
7
|
+
* `<html>` before first paint. Use it with a framework's pre-hydration script
|
|
8
|
+
* facility (for example `next/script` with `strategy="beforeInteractive"`), or
|
|
9
|
+
* inject it into a static `index.html` at build time (for example from a Vite
|
|
10
|
+
* `transformIndexHtml` hook). `'system'` leaves both classes off so the
|
|
11
|
+
* stylesheet's `prefers-color-scheme` defaults apply.
|
|
12
|
+
*/
|
|
13
|
+
export function getThemeScript(options = {}) {
|
|
14
|
+
const resolved = resolveThemeOptions(options);
|
|
15
|
+
const json = (value) => JSON.stringify(value).replaceAll('<', '\\u003c');
|
|
16
|
+
return `(function(){var t=${json(resolved.defaultTheme)};try{var s=localStorage.getItem(${json(resolved.storageKey)});if(s==='light'||s==='dark'||(${resolved.enableSystem}&&s==='system'))t=s}catch(_){}var d=document.documentElement;d.classList.toggle('dark',t==='dark');d.classList.toggle('light',t==='light')})()`;
|
|
5
17
|
}
|
|
6
18
|
//# sourceMappingURL=theme-script.js.map
|
package/theme-script.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-script.js","sourceRoot":"","sources":["../src/theme-script.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"theme-script.js","sourceRoot":"","sources":["../src/theme-script.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,iEAAiE;AACjE,iGAAiG;AAEjG,OAAO,EAAE,mBAAmB,EAAqB,MAAM,iBAAiB,CAAA;AAIxE;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,UAAwB,EAAE;IACvD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC7C,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACjF,OAAO,qBAAqB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,mCAAmC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,kCAAkC,QAAQ,CAAC,YAAY,gJAAgJ,CAAA;AAC5T,CAAC","sourcesContent":["// The pre-paint theme script. Framework-neutral: no React and no browser\n// globals at import time, so it is safe in Server Components, in\n// `vite.config`/`next.config`, and in build scripts (`@braedonsaunders/appkit-ui/theme-script`).\n\nimport { resolveThemeOptions, type ThemeOptions } from './theme-options'\n\nexport type { ResolvedTheme, Theme, ThemeOptions } from './theme-options'\n\n/**\n * Inline script body that applies the stored (or default) theme class to\n * `<html>` before first paint. Use it with a framework's pre-hydration script\n * facility (for example `next/script` with `strategy=\"beforeInteractive\"`), or\n * inject it into a static `index.html` at build time (for example from a Vite\n * `transformIndexHtml` hook). `'system'` leaves both classes off so the\n * stylesheet's `prefers-color-scheme` defaults apply.\n */\nexport function getThemeScript(options: ThemeOptions = {}): string {\n const resolved = resolveThemeOptions(options)\n const json = (value: unknown) => JSON.stringify(value).replaceAll('<', '\\\\u003c')\n return `(function(){var t=${json(resolved.defaultTheme)};try{var s=localStorage.getItem(${json(resolved.storageKey)});if(s==='light'||s==='dark'||(${resolved.enableSystem}&&s==='system'))t=s}catch(_){}var d=document.documentElement;d.classList.toggle('dark',t==='dark');d.classList.toggle('light',t==='light')})()`\n}\n"]}
|
package/theme.d.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
export type ResolvedTheme = 'light' | 'dark';
|
|
2
|
+
import { type ResolvedTheme, type Theme, type ThemeOptions } from './theme-options.js';
|
|
4
3
|
type ThemeContextValue = {
|
|
5
4
|
theme: Theme;
|
|
6
5
|
resolvedTheme: ResolvedTheme;
|
|
7
6
|
setTheme: (theme: Theme) => void;
|
|
7
|
+
/** False for a light/dark-only app; `'system'` is then never offered. */
|
|
8
|
+
enableSystem: boolean;
|
|
8
9
|
mounted: boolean;
|
|
9
10
|
};
|
|
10
|
-
export
|
|
11
|
+
export type ThemeProviderProps = ThemeOptions & {
|
|
11
12
|
children: React.ReactNode;
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Live theme state. Pass the same options to `getThemeScript` so the
|
|
16
|
+
* pre-paint class matches: `<ThemeProvider defaultTheme="dark"
|
|
17
|
+
* enableSystem={false}>` for a dark-by-default, light/dark-only app.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ThemeProvider({ children, ...options }: ThemeProviderProps): React.JSX.Element;
|
|
14
20
|
export declare function useTheme(): ThemeContextValue;
|
|
15
21
|
export type ThemeToggleLabels = {
|
|
16
22
|
label: string;
|
package/theme.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAA;AAExB,KAAK,iBAAiB,GAAG;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,yEAAyE;IACzE,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAKD,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAA;AAE7E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,kBAAkB,qBAoEzE;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C;AASD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CACnC,CAAA;AAUD,wBAAgB,WAAW,CAAC,EAC1B,SAAiB,EACjB,MAAuB,EACvB,SAAS,GACV,EAAE;IACD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,qBAuDA"}
|
package/theme.js
CHANGED
|
@@ -3,22 +3,26 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { Monitor, Moon, Sun } from 'lucide-react';
|
|
5
5
|
import { cn } from './utils.js';
|
|
6
|
+
import { resolveThemeOptions, themeFromStorage, } from './theme-options.js';
|
|
6
7
|
const ThemeContext = React.createContext(null);
|
|
7
8
|
const unavailableThemes = new Map();
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Live theme state. Pass the same options to `getThemeScript` so the
|
|
11
|
+
* pre-paint class matches: `<ThemeProvider defaultTheme="dark"
|
|
12
|
+
* enableSystem={false}>` for a dark-by-default, light/dark-only app.
|
|
13
|
+
*/
|
|
14
|
+
export function ThemeProvider({ children, ...options }) {
|
|
15
|
+
const { storageKey, defaultTheme, enableSystem } = resolveThemeOptions(options);
|
|
16
|
+
const config = React.useMemo(() => ({ storageKey, defaultTheme, enableSystem }), [storageKey, defaultTheme, enableSystem]);
|
|
12
17
|
const eventName = `appkit-theme-change:${storageKey}`;
|
|
13
18
|
const readTheme = React.useCallback(() => {
|
|
14
19
|
try {
|
|
15
|
-
|
|
16
|
-
return isTheme(stored) ? stored : 'system';
|
|
20
|
+
return themeFromStorage(localStorage.getItem(storageKey), config);
|
|
17
21
|
}
|
|
18
22
|
catch {
|
|
19
|
-
return unavailableThemes.get(storageKey) ??
|
|
23
|
+
return themeFromStorage(unavailableThemes.get(storageKey) ?? null, config);
|
|
20
24
|
}
|
|
21
|
-
}, [storageKey]);
|
|
25
|
+
}, [config, storageKey]);
|
|
22
26
|
const subscribeTheme = React.useCallback((onChange) => {
|
|
23
27
|
window.addEventListener('storage', onChange);
|
|
24
28
|
window.addEventListener(eventName, onChange);
|
|
@@ -32,7 +36,7 @@ export function ThemeProvider({ children, storageKey = 'theme', }) {
|
|
|
32
36
|
media.addEventListener('change', onChange);
|
|
33
37
|
return () => media.removeEventListener('change', onChange);
|
|
34
38
|
}, []);
|
|
35
|
-
const theme = React.useSyncExternalStore(subscribeTheme, readTheme, () =>
|
|
39
|
+
const theme = React.useSyncExternalStore(subscribeTheme, readTheme, () => defaultTheme);
|
|
36
40
|
const prefersDark = React.useSyncExternalStore(subscribeSystem, () => matchMedia('(prefers-color-scheme: dark)').matches, () => false);
|
|
37
41
|
const [mounted, setMounted] = React.useState(false);
|
|
38
42
|
const resolvedTheme = theme === 'system' ? (prefersDark ? 'dark' : 'light') : theme;
|
|
@@ -41,9 +45,12 @@ export function ThemeProvider({ children, storageKey = 'theme', }) {
|
|
|
41
45
|
document.documentElement.classList.toggle('dark', resolvedTheme === 'dark');
|
|
42
46
|
document.documentElement.classList.toggle('light', resolvedTheme === 'light');
|
|
43
47
|
}, [resolvedTheme]);
|
|
44
|
-
const setTheme = React.useCallback((
|
|
48
|
+
const setTheme = React.useCallback((requested) => {
|
|
49
|
+
const next = themeFromStorage(requested, config);
|
|
45
50
|
try {
|
|
46
|
-
|
|
51
|
+
// The default is stored as "no explicit choice", so changing the
|
|
52
|
+
// app's default later moves users who never picked one.
|
|
53
|
+
if (next === defaultTheme)
|
|
47
54
|
localStorage.removeItem(storageKey);
|
|
48
55
|
else
|
|
49
56
|
localStorage.setItem(storageKey, next);
|
|
@@ -53,8 +60,8 @@ export function ThemeProvider({ children, storageKey = 'theme', }) {
|
|
|
53
60
|
unavailableThemes.set(storageKey, next);
|
|
54
61
|
}
|
|
55
62
|
window.dispatchEvent(new Event(eventName));
|
|
56
|
-
}, [eventName, storageKey]);
|
|
57
|
-
return (_jsx(ThemeContext.Provider, { value: { theme, resolvedTheme, setTheme, mounted }, children: children }));
|
|
63
|
+
}, [config, defaultTheme, eventName, storageKey]);
|
|
64
|
+
return (_jsx(ThemeContext.Provider, { value: { theme, resolvedTheme, setTheme, enableSystem, mounted }, children: children }));
|
|
58
65
|
}
|
|
59
66
|
export function useTheme() {
|
|
60
67
|
const context = React.useContext(ThemeContext);
|
|
@@ -67,6 +74,7 @@ const THEME_OPTIONS = [
|
|
|
67
74
|
{ value: 'system', icon: Monitor },
|
|
68
75
|
{ value: 'dark', icon: Moon },
|
|
69
76
|
];
|
|
77
|
+
const CYCLE = ['light', 'dark', 'system'];
|
|
70
78
|
const DEFAULT_LABELS = {
|
|
71
79
|
label: 'Theme',
|
|
72
80
|
light: 'Light',
|
|
@@ -75,15 +83,18 @@ const DEFAULT_LABELS = {
|
|
|
75
83
|
current: (theme) => `Theme: ${theme}`,
|
|
76
84
|
};
|
|
77
85
|
export function ThemeToggle({ collapsed = false, labels = DEFAULT_LABELS, className, }) {
|
|
78
|
-
const { theme, setTheme, mounted } = useTheme();
|
|
86
|
+
const { theme, setTheme, enableSystem, mounted } = useTheme();
|
|
87
|
+
const options = enableSystem ? THEME_OPTIONS : THEME_OPTIONS.filter((option) => option.value !== 'system');
|
|
79
88
|
if (collapsed) {
|
|
80
|
-
|
|
89
|
+
// Cycles light → dark (→ system when enabled) → light.
|
|
90
|
+
const cycle = enableSystem ? CYCLE : CYCLE.filter((value) => value !== 'system');
|
|
91
|
+
const active = options.find((option) => option.value === theme) ?? options[0];
|
|
81
92
|
const Icon = active.icon;
|
|
82
93
|
const activeLabel = labels[active.value];
|
|
83
|
-
const next =
|
|
94
|
+
const next = cycle[(cycle.indexOf(active.value) + 1) % cycle.length];
|
|
84
95
|
return (_jsx("button", { type: "button", onClick: () => setTheme(next), title: labels.current(activeLabel), "aria-label": labels.current(activeLabel), className: cn('grid size-9 place-items-center rounded-md text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg', className), children: mounted ? _jsx(Icon, { size: 16 }) : _jsx(Monitor, { size: 16, className: "opacity-0" }) }));
|
|
85
96
|
}
|
|
86
|
-
return (_jsx("div", { role: "radiogroup", "aria-label": labels.label, className: cn('flex items-center gap-0.5 rounded-lg border border-border bg-bg-subtle p-0.5', className), children:
|
|
97
|
+
return (_jsx("div", { role: "radiogroup", "aria-label": labels.label, className: cn('flex items-center gap-0.5 rounded-lg border border-border bg-bg-subtle p-0.5', className), children: options.map((option) => {
|
|
87
98
|
const Icon = option.icon;
|
|
88
99
|
const selected = mounted && theme === option.value;
|
|
89
100
|
return (_jsx("button", { type: "button", role: "radio", "aria-checked": selected, onClick: () => setTheme(option.value), title: labels[option.value], className: cn('inline-flex h-7 flex-1 items-center justify-center rounded-md transition-colors', selected ? 'bg-surface text-primary shadow-sm' : 'text-fg-muted hover:text-fg'), children: _jsx(Icon, { size: 15 }) }, option.value));
|
package/theme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Monitor, Moon, Sun } from 'lucide-react'\nimport { cn } from './utils'\n\nexport type Theme = 'light' | 'dark' | 'system'\nexport type ResolvedTheme = 'light' | 'dark'\n\ntype ThemeContextValue = {\n theme: Theme\n resolvedTheme: ResolvedTheme\n setTheme: (theme: Theme) => void\n mounted: boolean\n}\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null)\nconst unavailableThemes = new Map<string, Theme>()\n\nfunction isTheme(value: string | null): value is Theme {\n return value === 'light' || value === 'dark' || value === 'system'\n}\n\nexport function ThemeProvider({\n children,\n storageKey = 'theme',\n}: {\n children: React.ReactNode\n storageKey?: string\n}) {\n const eventName = `appkit-theme-change:${storageKey}`\n const readTheme = React.useCallback((): Theme => {\n try {\n const stored = localStorage.getItem(storageKey)\n return isTheme(stored) ? stored : 'system'\n } catch {\n return unavailableThemes.get(storageKey) ?? 'system'\n }\n }, [storageKey])\n const subscribeTheme = React.useCallback(\n (onChange: () => void) => {\n window.addEventListener('storage', onChange)\n window.addEventListener(eventName, onChange)\n return () => {\n window.removeEventListener('storage', onChange)\n window.removeEventListener(eventName, onChange)\n }\n },\n [eventName],\n )\n const subscribeSystem = React.useCallback((onChange: () => void) => {\n const media = matchMedia('(prefers-color-scheme: dark)')\n media.addEventListener('change', onChange)\n return () => media.removeEventListener('change', onChange)\n }, [])\n const theme = React.useSyncExternalStore<Theme>(subscribeTheme, readTheme, () => 'system')\n const prefersDark = React.useSyncExternalStore(\n subscribeSystem,\n () => matchMedia('(prefers-color-scheme: dark)').matches,\n () => false,\n )\n const [mounted, setMounted] = React.useState(false)\n const resolvedTheme: ResolvedTheme =\n theme === 'system' ? (prefersDark ? 'dark' : 'light') : theme\n\n React.useEffect(() => setMounted(true), [])\n React.useEffect(() => {\n document.documentElement.classList.toggle('dark', resolvedTheme === 'dark')\n document.documentElement.classList.toggle('light', resolvedTheme === 'light')\n }, [resolvedTheme])\n\n const setTheme = React.useCallback(\n (next: Theme) => {\n try {\n if (next === 'system') localStorage.removeItem(storageKey)\n else localStorage.setItem(storageKey, next)\n unavailableThemes.delete(storageKey)\n } catch {\n unavailableThemes.set(storageKey, next)\n }\n window.dispatchEvent(new Event(eventName))\n },\n [eventName, storageKey],\n )\n\n return (\n <ThemeContext.Provider value={{ theme, resolvedTheme, setTheme, mounted }}>\n {children}\n </ThemeContext.Provider>\n )\n}\n\nexport function useTheme(): ThemeContextValue {\n const context = React.useContext(ThemeContext)\n if (!context) throw new Error('useTheme must be used within ThemeProvider')\n return context\n}\n\nconst THEME_OPTIONS = [\n { value: 'light' as const, icon: Sun },\n { value: 'system' as const, icon: Monitor },\n { value: 'dark' as const, icon: Moon },\n]\n\nexport type ThemeToggleLabels = {\n label: string\n light: string\n system: string\n dark: string\n current: (theme: string) => string\n}\n\nconst DEFAULT_LABELS: ThemeToggleLabels = {\n label: 'Theme',\n light: 'Light',\n system: 'System',\n dark: 'Dark',\n current: (theme) => `Theme: ${theme}`,\n}\n\nexport function ThemeToggle({\n collapsed = false,\n labels = DEFAULT_LABELS,\n className,\n}: {\n collapsed?: boolean\n labels?: ThemeToggleLabels\n className?: string\n}) {\n const { theme, setTheme, mounted } = useTheme()\n\n if (collapsed) {\n const active = THEME_OPTIONS.find((option) => option.value === theme) ?? THEME_OPTIONS[1]!\n const Icon = active.icon\n const activeLabel = labels[active.value]\n const next: Theme = theme === 'light' ? 'dark' : theme === 'dark' ? 'system' : 'light'\n return (\n <button\n type=\"button\"\n onClick={() => setTheme(next)}\n title={labels.current(activeLabel)}\n aria-label={labels.current(activeLabel)}\n className={cn(\n 'grid size-9 place-items-center rounded-md text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg',\n className,\n )}\n >\n {mounted ? <Icon size={16} /> : <Monitor size={16} className=\"opacity-0\" />}\n </button>\n )\n }\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={labels.label}\n className={cn('flex items-center gap-0.5 rounded-lg border border-border bg-bg-subtle p-0.5', className)}\n >\n {THEME_OPTIONS.map((option) => {\n const Icon = option.icon\n const selected = mounted && theme === option.value\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n onClick={() => setTheme(option.value)}\n title={labels[option.value]}\n className={cn(\n 'inline-flex h-7 flex-1 items-center justify-center rounded-md transition-colors',\n selected ? 'bg-surface text-primary shadow-sm' : 'text-fg-muted hover:text-fg',\n )}\n >\n <Icon size={15} />\n </button>\n )\n })}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Monitor, Moon, Sun } from 'lucide-react'\nimport { cn } from './utils'\nimport {\n resolveThemeOptions,\n themeFromStorage,\n type ResolvedTheme,\n type Theme,\n type ThemeOptions,\n} from './theme-options'\n\ntype ThemeContextValue = {\n theme: Theme\n resolvedTheme: ResolvedTheme\n setTheme: (theme: Theme) => void\n /** False for a light/dark-only app; `'system'` is then never offered. */\n enableSystem: boolean\n mounted: boolean\n}\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null)\nconst unavailableThemes = new Map<string, Theme>()\n\nexport type ThemeProviderProps = ThemeOptions & { children: React.ReactNode }\n\n/**\n * Live theme state. Pass the same options to `getThemeScript` so the\n * pre-paint class matches: `<ThemeProvider defaultTheme=\"dark\"\n * enableSystem={false}>` for a dark-by-default, light/dark-only app.\n */\nexport function ThemeProvider({ children, ...options }: ThemeProviderProps) {\n const { storageKey, defaultTheme, enableSystem } = resolveThemeOptions(options)\n const config = React.useMemo(\n () => ({ storageKey, defaultTheme, enableSystem }),\n [storageKey, defaultTheme, enableSystem],\n )\n const eventName = `appkit-theme-change:${storageKey}`\n const readTheme = React.useCallback((): Theme => {\n try {\n return themeFromStorage(localStorage.getItem(storageKey), config)\n } catch {\n return themeFromStorage(unavailableThemes.get(storageKey) ?? null, config)\n }\n }, [config, storageKey])\n const subscribeTheme = React.useCallback(\n (onChange: () => void) => {\n window.addEventListener('storage', onChange)\n window.addEventListener(eventName, onChange)\n return () => {\n window.removeEventListener('storage', onChange)\n window.removeEventListener(eventName, onChange)\n }\n },\n [eventName],\n )\n const subscribeSystem = React.useCallback((onChange: () => void) => {\n const media = matchMedia('(prefers-color-scheme: dark)')\n media.addEventListener('change', onChange)\n return () => media.removeEventListener('change', onChange)\n }, [])\n const theme = React.useSyncExternalStore<Theme>(subscribeTheme, readTheme, () => defaultTheme)\n const prefersDark = React.useSyncExternalStore(\n subscribeSystem,\n () => matchMedia('(prefers-color-scheme: dark)').matches,\n () => false,\n )\n const [mounted, setMounted] = React.useState(false)\n const resolvedTheme: ResolvedTheme =\n theme === 'system' ? (prefersDark ? 'dark' : 'light') : theme\n\n React.useEffect(() => setMounted(true), [])\n React.useEffect(() => {\n document.documentElement.classList.toggle('dark', resolvedTheme === 'dark')\n document.documentElement.classList.toggle('light', resolvedTheme === 'light')\n }, [resolvedTheme])\n\n const setTheme = React.useCallback(\n (requested: Theme) => {\n const next = themeFromStorage(requested, config)\n try {\n // The default is stored as \"no explicit choice\", so changing the\n // app's default later moves users who never picked one.\n if (next === defaultTheme) localStorage.removeItem(storageKey)\n else localStorage.setItem(storageKey, next)\n unavailableThemes.delete(storageKey)\n } catch {\n unavailableThemes.set(storageKey, next)\n }\n window.dispatchEvent(new Event(eventName))\n },\n [config, defaultTheme, eventName, storageKey],\n )\n\n return (\n <ThemeContext.Provider value={{ theme, resolvedTheme, setTheme, enableSystem, mounted }}>\n {children}\n </ThemeContext.Provider>\n )\n}\n\nexport function useTheme(): ThemeContextValue {\n const context = React.useContext(ThemeContext)\n if (!context) throw new Error('useTheme must be used within ThemeProvider')\n return context\n}\n\nconst THEME_OPTIONS = [\n { value: 'light' as const, icon: Sun },\n { value: 'system' as const, icon: Monitor },\n { value: 'dark' as const, icon: Moon },\n]\nconst CYCLE: Theme[] = ['light', 'dark', 'system']\n\nexport type ThemeToggleLabels = {\n label: string\n light: string\n system: string\n dark: string\n current: (theme: string) => string\n}\n\nconst DEFAULT_LABELS: ThemeToggleLabels = {\n label: 'Theme',\n light: 'Light',\n system: 'System',\n dark: 'Dark',\n current: (theme) => `Theme: ${theme}`,\n}\n\nexport function ThemeToggle({\n collapsed = false,\n labels = DEFAULT_LABELS,\n className,\n}: {\n collapsed?: boolean\n labels?: ThemeToggleLabels\n className?: string\n}) {\n const { theme, setTheme, enableSystem, mounted } = useTheme()\n const options = enableSystem ? THEME_OPTIONS : THEME_OPTIONS.filter((option) => option.value !== 'system')\n\n if (collapsed) {\n // Cycles light → dark (→ system when enabled) → light.\n const cycle = enableSystem ? CYCLE : CYCLE.filter((value) => value !== 'system')\n const active = options.find((option) => option.value === theme) ?? options[0]!\n const Icon = active.icon\n const activeLabel = labels[active.value]\n const next = cycle[(cycle.indexOf(active.value) + 1) % cycle.length]!\n return (\n <button\n type=\"button\"\n onClick={() => setTheme(next)}\n title={labels.current(activeLabel)}\n aria-label={labels.current(activeLabel)}\n className={cn(\n 'grid size-9 place-items-center rounded-md text-fg-muted transition-colors hover:bg-surface-hover hover:text-fg',\n className,\n )}\n >\n {mounted ? <Icon size={16} /> : <Monitor size={16} className=\"opacity-0\" />}\n </button>\n )\n }\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={labels.label}\n className={cn('flex items-center gap-0.5 rounded-lg border border-border bg-bg-subtle p-0.5', className)}\n >\n {options.map((option) => {\n const Icon = option.icon\n const selected = mounted && theme === option.value\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n onClick={() => setTheme(option.value)}\n title={labels[option.value]}\n className={cn(\n 'inline-flex h-7 flex-1 items-center justify-center rounded-md transition-colors',\n selected ? 'bg-surface text-primary shadow-sm' : 'text-fg-muted hover:text-fg',\n )}\n >\n <Icon size={15} />\n </button>\n )\n })}\n </div>\n )\n}\n"]}
|