@braedonsaunders/appkit-ui 0.4.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/package.json +1 -1
- package/search-select.d.ts.map +1 -1
- package/search-select.js +6 -3
- package/search-select.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/package.json
CHANGED
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":"AAAA,YAAY,CAAA;;AAEZ,sEAAsE;AACtE,mFAAmF;AACnF,8EAA8E;AAC9E,6EAA6E;AAC7E,kFAAkF;AAClF,4EAA4E;AAE5E,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AA4C5B,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAW,GAAG,SAAS,EACvB,iBAAiB,GAAG,SAAS,EAC7B,QAAQ,GAAG,KAAK,EAChB,SAAS,GAAG,KAAK,EACjB,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,MAAM,GAAG,KAAK,EACd,OAAO,GAAG,KAAK,EACf,aAAa,EACb,UAAU,GAAG,OAAO,EACpB,cAAc,EACd,OAAO,GAAG,KAAK,EACf,EAAE,EACF,SAAS,GAAG,MAAM,EAClB,cAAc,GAAG,YAAY,EAC7B,cAAc,GAAG,YAAY,EAC7B,WAAW,GAAG,QAAQ,EACtB,UAAU,GAAG,OAAO,GACF;IAClB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC5C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IACnD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAA;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAmB,IAAI,CAAC,CAAA;IACtD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAoB,IAAI,CAAC,CAAA;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAA;IAClD,6EAA6E;IAC7E,6EAA6E;IAC7E,0EAA0E;IAC1E,2EAA2E;IAC3E,2CAA2C;IAC3C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAIlC,IAAI,CAAC,CAAA;IACP,SAAS,KAAK;QACZ,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAA;QACrD,IAAI,CAAC,EAAE,CAAC;YACN,wEAAwE;YACxE,uDAAuD;YACvD,MAAM,MAAM,GAAG,CAAC,CAAA;YAChB,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,MAAM,GAAG,MAAM,CAAA;YACpD,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,MAAM,CAAA;YAC5B,MAAM,OAAO,GAAG,GAAG,CAAA;YACnB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,CAAC,CAAC,CAAA;YAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC,CAAA;YACrG,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;gBACtD,MAAM,CAAC;oBACL,IAAI,EAAE,KAAK;oBACX,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;oBACpB,IAAI;oBACJ,KAAK;oBACL,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;iBAClE,CAAC,CAAA;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC;oBACL,IAAI,EAAE,QAAQ;oBACd,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;oBACxD,IAAI;oBACJ,KAAK;oBACL,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;iBAClE,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,UAAU,CAAC,IAAI,CAAC,CAAA;QAChB,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAA;QACnD,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;QAC7C,MAAM,EAAE,CAAA;QACR,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QACrC,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACvD,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAC9B,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,IAAI,SAAS,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EACzF,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAC5C,CAAA;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAA;IACvD,MAAM,SAAS,GAAG,SAAS,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,CAAA;IAC3D,MAAM,OAAO,GAAG,QAAQ,EAAE,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IACzE,MAAM,aAAa,GAAG,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAA;IAE7C,MAAM,UAAU,GAAG,UAAU,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IAE3F,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAClC,IAAI,MAAM;YAAE,OAAO,UAAU,CAAA;QAC7B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QACpC,IAAI,CAAC,CAAC;YAAE,OAAO,UAAU,CAAA;QACzB,OAAO,UAAU,CAAC,MAAM,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC/E,CAAA;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IAE/B,SAAS,YAAY,CAAC,KAAqB,EAAE,KAAa;QACxD,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ;YAAE,OAAO,KAAK,CAAA;QAC/E,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC/C,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;IAC7B,CAAC;IAED,SAAS,QAAQ;QACf,IAAI,QAAQ;YAAE,OAAM;QACpB,QAAQ,CAAC,EAAE,CAAC,CAAA;QACZ,cAAc,EAAE,CAAC,EAAE,CAAC,CAAA;QACpB,YAAY,CAAC,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,CAAA;QACtF,KAAK,EAAE,CAAA;QACP,OAAO,CAAC,IAAI,CAAC,CAAA;QACb,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;IAClD,CAAC;IACD,SAAS,MAAM,CAAC,CAAS;QACvB,QAAQ,CAAC,CAAC,CAAC,CAAA;QACX,OAAO,CAAC,KAAK,CAAC,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAC/B,SAAS,KAAK,CAAC,CAAa;YAC1B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAc,CAAA;YAC/B,IAAI,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC;gBAAE,OAAM;YAClF,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB,CAAC;QACD,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QAC7C,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;IAC/D,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;IAErB,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAC/B,KAAK,EAAE,CAAA;QACP,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,CAAA;QAC5B,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;QAC/C,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QACzC,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;YAClD,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC9C,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;IAErB,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,EAAE;YAChD,IAAI,KAAK,GAAG,IAAI,CAAA;YAChB,OAAO,IAAI,EAAE,CAAC;gBACZ,KAAK,IAAI,GAAG,CAAA;gBACZ,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM;oBAAE,OAAO,IAAI,CAAA;gBACtD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ;oBAAE,OAAO,KAAK,CAAA;YAC9C,CAAC;QACH,CAAC,CAAA;QACD,SAAS,KAAK,CAAC,CAAgB;YAC7B,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACvB,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,OAAO,CAAC,KAAK,CAAC,CAAA;gBACd,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,CAAA;YAC7B,CAAC;iBACI,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBAC/B,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YACxC,CAAC;iBAAM,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC/B,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;YACzC,CAAC;iBAAM,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;gBAC7B,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,MAAM,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;gBAC7B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;oBACrB,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;oBACjB,OAAO,CAAC,KAAK,CAAC,CAAA;gBAChB,CAAC;YACH,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAC3C,IAAI,OAAiC,CAAA;QACrC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAA;YACzC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;YACvC,OAAO,GAAG,GAAG,EAAE;gBACb,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;YACrC,CAAC,CAAA;QACH,CAAC;QACD,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YAC9C,OAAO,EAAE,EAAE,CAAA;QACb,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;IAEpD,MAAM,UAAU,GAAG,CACjB,8BACE,cAAI,IAAI,EAAC,SAAS,EAAC,SAAS,EAAC,MAAM,aAChC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CACnC,aAAI,IAAI,EAAC,QAAQ,mBAAe,MAAM,EAAC,SAAS,EAAC,8CAA8C,YAC5F,cAAc,GACZ,CACN,CAAC,CAAC,CAAC,IAAI,EACP,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;wBACrB,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAA;wBAChC,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;wBAC5D,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;wBAChE,OAAO,CACL,cAAkC,IAAI,EAAC,cAAc,aAClD,MAAM,CAAC,CAAC,CAAC,CACR,cAAK,SAAS,EAAC,2FAA2F,YACvG,MAAM,GACH,CACP,CAAC,CAAC,CAAC,IAAI,EACR,kBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,mBACE,MAAM,EACrB,QAAQ,EAAE,CAAC,CAAC,QAAQ,EACpB,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,EAClD,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAC7C,SAAS,EAAE,EAAE,CACX,8GAA8G,EAC9G,CAAC,CAAC,QAAQ;wCACR,CAAC,CAAC,mCAAmC;wCACrC,CAAC,CAAC,CAAC,KAAK,SAAS;4CACf,CAAC,CAAC,mBAAmB;4CACrB,CAAC,CAAC,yBAAyB,EAC/B,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,SAAS,CAAC,CACjE,aAED,gBAAM,SAAS,EAAC,yBAAyB,aACtC,CAAC,CAAC,KAAK,EACP,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,IAAI,GAAQ,CAAC,CAAC,CAAC,IAAI,IAC3E,EACN,MAAM,CAAC,CAAC,CAAC,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,uBAAuB,GAAG,CAAC,CAAC,CAAC,IAAI,IAC/D,KA5BF,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,EAAE,CA6B3B,CACN,CAAA;oBACH,CAAC,CAAC,IACC,EACJ,OAAO,IAAI,aAAa,CAAC,CAAC,CAAC,CAC1B,cACE,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EACjD,SAAS,EAAE,EAAE,CACX,0CAA0C,EAC1C,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CACzD,YAEA,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,GACrC,CACP,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,CAAA;IAED,MAAM,SAAS,GAAG,CAAC,SAAkB,EAAE,EAAE,CAAC,CACxC,eAAK,SAAS,EAAC,oBAAoB,aACjC,KAAC,MAAM,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,yDAAyD,GAAG,EACxF,gBACE,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;oBAC3B,QAAQ,CAAC,IAAI,CAAC,CAAA;oBACd,cAAc,EAAE,CAAC,IAAI,CAAC,CAAA;oBACtB,YAAY,CAAC,CAAC,CAAC,CAAA;gBACjB,CAAC,EACD,WAAW,EAAE,iBAAiB,gBAClB,iBAAiB,eAClB,OAAO,IAAI,SAAS,EAC/B,SAAS,EAAE,EAAE,CACX,6JAA6J,EAC7J,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,0BAA0B,CAC1D,GACD,IACE,CACP,CAAA;IAED,OAAO,CACL,eAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,aACrD,kBACE,GAAG,EAAE,UAAU,EACf,IAAI,EAAC,QAAQ,EACb,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,EACnD,QAAQ,EAAE,QAAQ,gBACN,SAAS,mBACP,SAAS,mBACR,IAAI,kBACL,OAAO,IAAI,SAAS,EAClC,SAAS,EAAE,EAAE,CACX,4HAA4H,EAC5H,yEAAyE,EACzE,QAAQ,IAAI,4CAA4C,EACxD,IAAI,IAAI,oCAAoC,EAC5C,OAAO,IAAI,wDAAwD,EACnE,gBAAgB,CACjB,aAED,eAAM,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,YACzF,OAAO,GACH,EACP,KAAC,WAAW,IACV,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,EAAE,CAAC,8CAA8C,EAAE,IAAI,IAAI,YAAY,CAAC,GACnF,IACK,EAER,OAAO,IAAI,IAAI,IAAI,SAAS,IAAI,GAAG;gBAClC,CAAC,CAAC,YAAY,CACV,eACE,GAAG,EAAE,OAAO,2BAEZ,KAAK,EAAE;wBACL,QAAQ,EAAE,OAAO;wBACjB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,MAAM;wBACtB,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;wBAC/B,SAAS,EAAE,GAAG,CAAC,SAAS;qBACzB,EACD,SAAS,EAAC,4FAA4F,aAErG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EACrC,cAAK,SAAS,EAAE,EAAE,CAAC,gCAAgC,EAAE,UAAU,IAAI,MAAM,CAAC,YAAG,UAAU,GAAO,IAC1F,EACN,QAAQ,CAAC,IAAI,CACd;gBACH,CAAC,CAAC,IAAI,EAEP,OAAO,IAAI,CAAC,SAAS;gBACpB,CAAC,CAAC,YAAY,CACV,KAAC,eAAe,cACb,IAAI,CAAC,CAAC,CAAC,CACN,wCAAqB,SAAS,EAAC,sBAAsB,aACnD,KAAC,MAAM,CAAC,GAAG,IACT,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EACvB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EACvB,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EACpB,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAC9B,SAAS,EAAC,oDAAoD,EAC9D,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAC7B,EACF,MAAC,MAAM,CAAC,GAAG,IACT,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EACjB,IAAI,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EACnB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EACtE,SAAS,EAAC,kHAAkH,aAE5H,cAAK,SAAS,EAAC,yCAAyC,YACtD,eAAM,SAAS,EAAC,0CAA0C,GAAG,GACzD,EACN,eAAK,SAAS,EAAC,kDAAkD,aAC/D,eAAM,SAAS,EAAC,iCAAiC,YAAE,UAAU,IAAI,WAAW,GAAQ,EACpF,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBACjB,UAAU,EACtB,SAAS,EAAC,uDAAuD,YAEjE,KAAC,CAAC,IAAC,IAAI,EAAE,EAAE,GAAI,GACR,IACL,EACL,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EACpC,cAAK,SAAS,EAAC,mFAAmF,YAC/F,UAAU,GACP,IACK,IACT,CACP,CAAC,CAAC,CAAC,IAAI,GACQ,EAClB,QAAQ,CAAC,IAAI,CACd;gBACH,CAAC,CAAC,IAAI,IACJ,CACP,CAAA;AACH,CAAC","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"]}
|