@devalok/shilp-sutra 0.52.0 → 0.53.0

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.
Files changed (41) hide show
  1. package/MIGRATION.md +6 -0
  2. package/dist/_chunks/motion-provider.js +7 -6
  3. package/dist/_chunks/motion-provider.js.map +1 -1
  4. package/dist/_chunks/success.js +53 -53
  5. package/dist/ai/command-bar.js +158 -158
  6. package/dist/ai/command-bar.js.map +1 -1
  7. package/dist/ai/conversation.js +5 -5
  8. package/dist/composed/command-palette.js +17 -17
  9. package/dist/composed/command-palette.js.map +1 -1
  10. package/dist/composed/priority-indicator.d.ts +15 -6
  11. package/dist/composed/priority-indicator.d.ts.map +1 -1
  12. package/dist/composed/priority-indicator.js +37 -88
  13. package/dist/composed/priority-indicator.js.map +1 -1
  14. package/dist/composed/schedule-view.d.ts +17 -2
  15. package/dist/composed/schedule-view.d.ts.map +1 -1
  16. package/dist/composed/schedule-view.js +163 -64
  17. package/dist/composed/schedule-view.js.map +1 -1
  18. package/dist/motion/motion-provider.d.ts.map +1 -1
  19. package/dist/shell/bottom-navbar.d.ts +32 -6
  20. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  21. package/dist/shell/bottom-navbar.js +156 -129
  22. package/dist/shell/bottom-navbar.js.map +1 -1
  23. package/dist/tokens/primitives.css +6 -2
  24. package/dist/tokens/utilities.css +6 -0
  25. package/dist/ui/autocomplete.d.ts +34 -32
  26. package/dist/ui/autocomplete.d.ts.map +1 -1
  27. package/dist/ui/autocomplete.js +115 -110
  28. package/dist/ui/autocomplete.js.map +1 -1
  29. package/dist/ui/combobox.js +4 -4
  30. package/dist/ui/index.js +30 -30
  31. package/dist/ui/search-input.js +4 -4
  32. package/dist/ui/sidebar.js +7 -7
  33. package/docs/components/composed/priority-indicator.md +22 -11
  34. package/docs/components/composed/schedule-view.md +20 -5
  35. package/docs/components/shell/bottom-navbar.md +24 -5
  36. package/docs/components/ui/autocomplete.md +26 -10
  37. package/llms.txt +1 -1
  38. package/mcp-manifest.json +179 -26
  39. package/package.json +1 -1
  40. package/skill/SKILL.md +1 -1
  41. package/skill/references/components.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"command-bar.js","names":[],"sources":["../../src/ai/command-bar.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandBar -- Unified AI command interface.\n *\n * Three variants:\n * - hero: Full-featured inline bar with greeting, hints, placeholder rotation\n * - inline: Compact inline bar for embedding in panels/toolbars\n * - floating: Modal overlay (same pattern as CommandPalette) with global keybinding\n *\n * Supports both command-palette filtering (when `groups` provided) and\n * AI natural-language submission via `onSubmit`.\n */\nimport {\n IconArrowDown,\n IconArrowUp,\n IconCornerDownLeft,\n IconLoader2,\n IconSearch,\n IconX,\n} from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport type { CommandGroup, CommandItem } from '../composed/command-palette'\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// GradientBorderWrap — animated gradient border during processing\n// -----------------------------------------------------------------------\n\n/**\n * Wraps the input row with an animated gradient border during processing.\n * Uses the Devalok brand palette (pink → purple → magenta) flowing around\n * the border. When inactive, renders children directly with no wrapper overhead.\n *\n * Technique: outer div with gradient background + padding-[1.5px] creates\n * a visible gradient border. The inner content covers the center, leaving\n * only the edge visible as a \"border\".\n */\nfunction GradientBorderWrap({\n active,\n rounded,\n reducedMotion,\n children,\n}: {\n active: boolean\n rounded: string\n reducedMotion: boolean\n children: React.ReactNode\n}) {\n if (!active) return <>{children}</>\n\n if (reducedMotion) {\n return (\n <div className={cn('p-[1.5px] bg-accent-9', rounded)}>\n {children}\n </div>\n )\n }\n\n return (\n <motion.div\n className={cn('relative p-[1.5px]', rounded)}\n style={{\n background: 'linear-gradient(var(--gradient-angle, 0deg), #D33163, #9B5DE5, #C850C0, #D33163)',\n backgroundSize: '300% 300%',\n }}\n animate={{\n // Rotate the gradient angle — creates the flowing border effect\n // Using CSS custom property animation via backgroundPosition as proxy\n backgroundPosition: ['0% 0%', '100% 100%', '0% 0%'],\n }}\n transition={{\n backgroundPosition: {\n duration: 4,\n repeat: Infinity,\n ease: 'linear',\n },\n }}\n >\n {children}\n </motion.div>\n )\n}\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\n/**\n * Unified AI command interface with three visual variants:\n * - `hero`: full-featured inline bar with greeting, animated placeholder rotation, and hints\n * - `inline`: compact bar for embedding in panels or toolbars\n * - `floating`: modal overlay with global keybinding (same pattern as CommandPalette)\n *\n * Supports both command-palette filtering (when `groups` provided) and\n * natural-language AI submission via `onSubmit`.\n */\nexport interface CommandBarProps\n extends Omit<React.ComponentPropsWithRef<'div'>, 'onSubmit'> {\n // -- AI submission --\n /** Called when the user submits a query (Enter key). */\n onSubmit?: (query: string) => void\n /** Current interaction state. Controls visual feedback (gradient border, placeholder). */\n state?: 'idle' | 'typing' | 'processing' | 'responded'\n\n // -- Command palette mode (optional) --\n /** When provided, enables command-palette filtering alongside AI submission. */\n groups?: CommandGroup[]\n onSearch?: (query: string) => void\n emptyMessage?: string\n emptyState?: React.ReactNode\n\n // -- Visual --\n /** Layout variant. @default 'hero' */\n variant?: 'hero' | 'inline' | 'floating'\n /** Placeholder text, or an array of strings that rotate on an interval. */\n placeholder?: string | string[]\n /** Rotation interval in ms when `placeholder` is an array. @default 4000 */\n placeholderInterval?: number\n /** Greeting text shown above the input in `hero` variant. */\n greeting?: string\n /** Hint strings shown below the input in `hero` variant. */\n hints?: string[]\n agentName?: string\n agentIcon?: React.ReactNode\n\n // -- Floating variant (modal) --\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Keybinding to toggle the floating bar. @default 'mod+k' */\n keybinding?: string | string[] | false\n\n // -- Interaction --\n disabled?: boolean\n maxHeight?: string | number\n\n // -- Composition --\n children?: React.ReactNode\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n// -----------------------------------------------------------------------\n// Rotating Placeholder\n// -----------------------------------------------------------------------\n\nfunction RotatingPlaceholder({\n placeholders,\n interval,\n paused,\n}: {\n placeholders: string[]\n interval: number\n paused: boolean\n}) {\n const [currentIndex, setCurrentIndex] = React.useState(0)\n const { reducedMotion } = useMotion()\n\n React.useEffect(() => {\n if (paused || placeholders.length <= 1) return\n const timer = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % placeholders.length)\n }, interval)\n return () => clearInterval(timer)\n }, [paused, placeholders.length, interval])\n\n if (reducedMotion) {\n return (\n <span className=\"pointer-events-none absolute text-surface-fg-subtle\">\n {placeholders[currentIndex]}\n </span>\n )\n }\n\n return (\n <AnimatePresence mode=\"wait\">\n <motion.span\n key={placeholders[currentIndex]}\n initial={{ opacity: 0, y: -4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 4 }}\n transition={tweens.fade}\n className=\"pointer-events-none absolute text-surface-fg-subtle\"\n >\n {placeholders[currentIndex]}\n </motion.span>\n </AnimatePresence>\n )\n}\n\n// -----------------------------------------------------------------------\n// CommandBar\n// -----------------------------------------------------------------------\n\nconst CommandBar = React.forwardRef<HTMLDivElement, CommandBarProps>(\n function CommandBar(\n {\n onSubmit,\n state = 'idle',\n groups = [],\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n variant = 'hero',\n placeholder = 'Ask anything...',\n placeholderInterval = 5000,\n greeting,\n hints,\n agentName,\n agentIcon,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+j',\n disabled = false,\n maxHeight = '320px',\n children,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state (floating) --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved =\n typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n // -- Core state --\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(-1)\n const [lastQuery, setLastQuery] = React.useState('')\n const [isFocused, setIsFocused] = React.useState(false)\n const [shake, setShake] = React.useState(false)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-bar-listbox-${instanceId}`\n\n // -- Motion --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // -- Placeholders --\n const placeholders = React.useMemo(\n () => (Array.isArray(placeholder) ? placeholder : [placeholder]),\n [placeholder],\n )\n\n // -- Has groups --\n const hasGroups = groups.length > 0\n\n // -- Filter groups --\n const filteredGroups = React.useMemo(() => {\n if (!hasGroups) return []\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query, hasGroups])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Build item index map for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Max height CSS --\n const maxHeightValue =\n typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Global keybinding (floating variant) --\n React.useEffect(() => {\n if (variant !== 'floating' || keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [variant, keybinding, setOpen])\n\n // -- Reset on floating open --\n React.useEffect(() => {\n if (variant === 'floating' && open) {\n setQuery('')\n setActiveIndex(-1)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [variant, open])\n\n // -- Scroll active item into view --\n React.useEffect(() => {\n if (activeIndex < 0) return\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n // -- Query change handler --\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(hasGroups && value.trim() ? 0 : -1)\n onSearch?.(value)\n }\n\n // -- Submit handler --\n const handleSubmit = React.useCallback(() => {\n if (!query.trim() || disabled) return\n setLastQuery(query)\n onSubmit?.(query)\n }, [query, disabled, onSubmit])\n\n // -- Keyboard handler --\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n if (!hasGroups || filteredItems.length === 0) return\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n if (hasGroups && filteredItems.length > 0) {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n } else if (!hasGroups && !query && lastQuery) {\n // Recall last query\n e.preventDefault()\n setQuery(lastQuery)\n }\n break\n }\n case 'Enter': {\n e.preventDefault()\n const isCmdEnter = e.metaKey || e.ctrlKey\n\n if (isCmdEnter) {\n // Cmd+Enter always submits\n handleSubmit()\n } else if (\n hasGroups &&\n activeIndex >= 0 &&\n filteredItems[activeIndex]\n ) {\n // Enter selects active command item\n filteredItems[activeIndex].onSelect()\n if (variant === 'floating') setOpen(false)\n } else {\n // Enter submits query\n handleSubmit()\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n if (state === 'responded') {\n setQuery('')\n } else if (variant === 'floating') {\n setOpen(false)\n } else {\n inputRef.current?.blur()\n }\n break\n }\n }\n }\n\n // -- Clear handler --\n const handleClear = () => {\n setQuery('')\n setActiveIndex(-1)\n inputRef.current?.focus()\n }\n\n // -- Shake animation reset --\n React.useEffect(() => {\n if (shake) {\n const timer = setTimeout(() => setShake(false), 500)\n return () => clearTimeout(timer)\n }\n }, [shake])\n\n // -- Shared spring/tween for reduced motion --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // =====================================================================\n // Shared Input Row\n // =====================================================================\n const isCompact = variant === 'inline'\n const isProcessing = state === 'processing'\n const isResponded = state === 'responded'\n\n const renderInputRow = () => (\n <GradientBorderWrap\n active={isProcessing}\n rounded={isCompact ? 'rounded-control' : 'rounded-surface'}\n reducedMotion={isReduced}\n >\n <div\n className={cn(\n 'flex items-center gap-ds-04 border bg-surface-overlay transition-colors transition-shadow duration-fast-02 ease-productive-standard',\n isCompact\n ? 'rounded-control px-ds-04'\n : 'rounded-surface px-ds-05',\n isProcessing\n ? 'border-transparent'\n : 'border-surface-border-strong',\n isFocused && !isProcessing && 'border-accent-7 shadow-ring',\n shake && 'animate-shake',\n )}\n >\n {/* Search icon */}\n <Icon\n icon={IconSearch}\n size={isCompact ? 'xs' : 'sm'}\n stroke=\"light\"\n className={cn(\n 'shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isFocused ? 'text-accent-9' : 'text-surface-fg-subtle',\n )}\n />\n\n {/* Input wrapper */}\n <div className=\"relative flex flex-1 items-center\">\n {!query && !isFocused && placeholders.length > 1 && (\n <RotatingPlaceholder\n placeholders={placeholders}\n interval={placeholderInterval}\n paused={isFocused || !!query}\n />\n )}\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n placeholder={\n placeholders.length === 1 || isFocused ? placeholders[0] : ''\n }\n readOnly={isProcessing}\n disabled={disabled}\n role=\"combobox\"\n aria-expanded={hasGroups && filteredItems.length > 0}\n aria-controls={hasGroups ? listboxId : undefined}\n aria-activedescendant={\n hasGroups && activeIndex >= 0 && filteredItems[activeIndex]\n ? `command-bar-item-${instanceId}-${filteredItems[activeIndex].id}`\n : undefined\n }\n aria-autocomplete={hasGroups ? 'list' : undefined}\n aria-label={agentName ? `Ask ${agentName}` : 'AI Command Bar'}\n className={cn(\n 'flex-1 bg-transparent text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n isCompact ? 'h-9 text-body-sm' : 'h-12 text-body-lg',\n isProcessing && 'cursor-wait',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n </div>\n\n {/* Right side: spinner / clear / shortcut badge */}\n {isProcessing ? (\n <span data-testid=\"command-bar-spinner\" className=\"shrink-0\">\n <Icon\n icon={IconLoader2}\n size={isCompact ? 'xs' : 'sm'}\n stroke=\"light\"\n animate=\"spin\"\n className=\"text-accent-9\"\n />\n </span>\n ) : isResponded ? (\n <button\n type=\"button\"\n onClick={handleClear}\n className=\"shrink-0 rounded-control-inner p-ds-01 text-surface-fg-subtle transition-colors duration-fast-01 hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Clear\"\n title=\"Clear\"\n >\n <Icon\n icon={IconX}\n size={isCompact ? 'xs' : 'sm'}\n stroke=\"light\"\n />\n </button>\n ) : variant === 'hero' ? (\n <AnimatePresence>\n {!isFocused && (\n <motion.kbd\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\"\n >\n {getModifierDisplay(isMac)}J\n </motion.kbd>\n )}\n </AnimatePresence>\n ) : null}\n </div>\n </GradientBorderWrap>\n )\n\n // =====================================================================\n // Command Results (shared between variants)\n // =====================================================================\n const renderCommandResults = () => {\n if (!hasGroups) return null\n\n const showResults =\n filteredItems.length > 0 || (query.trim() && filteredGroups.length === 0)\n\n if (!showResults && !query.trim()) return null\n\n return (\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && query.trim() && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={\n isReduced\n ? noMotionTransition\n : { ...tweens.fade, delay: groupIdx * 0.06 }\n }\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-bar-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={\n isReduced\n ? noMotionTransition\n : { ...springs.snappy, delay: itemIndex * 0.03 }\n }\n onClick={() => {\n item.onSelect()\n if (variant === 'floating') setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'text-accent-11'\n : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex flex-1 flex-col\">\n <span className=\"text-body-md\">\n {item.renderLabel\n ? item.renderLabel(query)\n : item.label}\n </span>\n {item.description && (\n <span className=\"text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon\n icon={IconCornerDownLeft}\n size=\"sm\"\n stroke=\"light\"\n className=\"text-surface-fg-subtle\"\n />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n )\n }\n\n // =====================================================================\n // Hero Variant\n // =====================================================================\n if (variant === 'hero') {\n return (\n <div\n ref={ref}\n role=\"search\"\n className={cn(\n 'bg-surface-raised rounded-overlay-lg shadow-raised p-ds-07',\n className,\n )}\n {...props}\n >\n {greeting && (\n <p className=\"text-heading-xs text-surface-fg-muted mb-ds-04\">\n {greeting}\n </p>\n )}\n\n {renderInputRow()}\n {renderCommandResults()}\n\n {/* Hints */}\n {hints && hints.length > 0 && (\n <div className=\"mt-ds-04 flex flex-wrap gap-ds-02b\">\n {hints.map((hint) => (\n <button\n key={hint}\n type=\"button\"\n onClick={() => {\n setQuery(hint)\n onSearch?.(hint)\n inputRef.current?.focus()\n }}\n className=\"rounded-control border border-card-strong bg-surface-overlay px-ds-03 py-ds-01 text-body-sm text-surface-fg-subtle transition-colors duration-fast-02 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted\"\n >\n {hint}\n </button>\n ))}\n </div>\n )}\n\n {/* Response area (children) */}\n {children && <div className=\"mt-ds-05\">{children}</div>}\n </div>\n )\n }\n\n // =====================================================================\n // Inline Variant\n // =====================================================================\n if (variant === 'inline') {\n return (\n <div\n ref={ref}\n role=\"search\"\n className={cn('w-full', className)}\n {...props}\n >\n {renderInputRow()}\n {renderCommandResults()}\n {children && <div className=\"mt-ds-03\">{children}</div>}\n </div>\n )\n }\n\n // =====================================================================\n // Floating Variant\n // =====================================================================\n const handleDialogOpenChange = (nextOpen: boolean) => {\n setOpen(nextOpen)\n }\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n >\n <VisuallyHidden>\n <DialogTitle>AI Command Bar</DialogTitle>\n <DialogDescription>\n Search commands or ask a question\n </DialogDescription>\n </VisuallyHidden>\n\n <div className=\"p-ds-04\">{renderInputRow()}</div>\n\n {renderCommandResults()}\n\n {children && (\n <div className=\"border-t border-surface-border-strong p-ds-04\">\n {children}\n </div>\n )}\n\n {/* Footer hints */}\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {hasGroups && (\n <div className=\"flex items-center gap-ds-02b\">\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n <span className=\"text-caption text-surface-fg-subtle\">\n Navigate\n </span>\n </div>\n )}\n <div className=\"flex items-center gap-ds-02b\">\n <kbd className=\"inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <span className=\"text-caption text-surface-fg-subtle\">\n Submit\n </span>\n </div>\n <div className=\"flex items-center gap-ds-02b\">\n <kbd className=\"inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n Esc\n </kbd>\n <span className=\"text-caption text-surface-fg-subtle\">\n Close\n </span>\n </div>\n </motion.div>\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandBar.displayName = 'CommandBar'\n\nexport { CommandBar }\nexport type { CommandGroup, CommandItem }\n"],"mappings":";;;;;;;;;;;;;;;AAuDA,SAAS,GAAmB,EAC1B,WACA,YACA,kBACA,eAMC;CAWD,OAVK,IAED,IAEA,kBAAC,OAAD;EAAK,WAAW,EAAG,yBAAyB,CAAO;EAChD;CACE,CAAA,IAKP,kBAAC,EAAO,KAAR;EACE,WAAW,EAAG,sBAAsB,CAAO;EAC3C,OAAO;GACL,YAAY;GACZ,gBAAgB;EAClB;EACA,SAAS,EAGP,oBAAoB;GAAC;GAAS;GAAa;EAAO,EACpD;EACA,YAAY,EACV,oBAAoB;GAClB,UAAU;GACV,QAAQ;GACR,MAAM;EACR,EACF;EAEC;CACS,CAAA,IA/BM,kBAAA,GAAA,EAAG,YAAW,CAAA;AAiCpC;AA+DA,SAAS,GAAe,GAA2B;CAGjD,OAFI,EAAK,cAAoB,EAAK,cAC9B,OAAO,EAAK,SAAU,WAAiB,EAAK,QACzC;AACT;AAEA,SAAS,GAAqB,GAA2B;CAEvD,OADI,OAAO,EAAK,eAAgB,WAAiB,EAAK,cAC/C;AACT;AAMA,SAAS,GAAoB,EAC3B,iBACA,aACA,aAKC;CACD,IAAM,CAAC,GAAc,KAAmB,EAAM,SAAS,CAAC,GAClD,EAAE,qBAAkB,EAAU;CAkBpC,OAhBA,EAAM,gBAAgB;EACpB,IAAI,KAAU,EAAa,UAAU,GAAG;EACxC,IAAM,IAAQ,kBAAkB;GAC9B,GAAiB,OAAU,IAAO,KAAK,EAAa,MAAM;EAC5D,GAAG,CAAQ;EACX,aAAa,cAAc,CAAK;CAClC,GAAG;EAAC;EAAQ,EAAa;EAAQ;CAAQ,CAAC,GAEtC,IAEA,kBAAC,QAAD;EAAM,WAAU;YACb,EAAa;CACV,CAAA,IAKR,kBAAC,GAAD;EAAiB,MAAK;YACpB,kBAAC,EAAO,MAAR;GAEE,SAAS;IAAE,SAAS;IAAG,GAAG;GAAG;GAC7B,SAAS;IAAE,SAAS;IAAG,GAAG;GAAE;GAC5B,MAAM;IAAE,SAAS;IAAG,GAAG;GAAE;GACzB,YAAY,EAAO;GACnB,WAAU;aAET,EAAa;EACH,GARN,EAAa,EAQP;CACE,CAAA;AAErB;AAMA,IAAM,IAAa,EAAM,WACvB,SACE,EACE,aACA,WAAQ,QACR,YAAS,CAAC,GACV,aACA,mBAAe,qBACf,gBACA,aAAU,QACV,iBAAc,mBACd,0BAAsB,KACtB,aACA,UACA,eACA,eACA,MAAM,IACN,iBACA,kBACA,gBAAa,SACb,cAAW,IACX,eAAY,SACZ,aACA,cACA,GAAG,KAEL,GACA;CAEA,IAAM,IAAe,OAAa,KAAA,GAC5B,CAAC,IAAc,MAAmB,EAAM,SAAS,MAAe,EAAK,GACrE,IAAO,IAAe,KAAW,IAEjC,IAAU,EAAM,OAAO,CAAI;CACjC,EAAQ,UAAU;CAElB,IAAM,IAAU,EAAM,aACnB,MAAqD;EACpD,IAAM,IACJ,OAAO,KAAa,aAAa,EAAS,EAAQ,OAAO,IAAI;EAI/D,AAHK,KACH,GAAgB,CAAQ,GAE1B,KAAe,CAAQ;CACzB,GACA,CAAC,GAAc,EAAY,CAC7B,GAGM,CAAC,GAAO,KAAY,EAAM,SAAS,EAAE,GACrC,CAAC,GAAa,KAAkB,EAAM,SAAS,EAAE,GACjD,CAAC,GAAW,MAAgB,EAAM,SAAS,EAAE,GAC7C,CAAC,GAAW,MAAgB,EAAM,SAAS,EAAK,GAChD,CAAC,GAAO,MAAY,EAAM,SAAS,EAAK,GACxC,IAAW,EAAM,OAAyB,IAAI,GAC9C,KAAU,EAAM,OAAuB,IAAI,GAC3C,IAAa,EAAM,MAAM,GACzB,KAAY,uBAAuB,KAGnC,EAAE,eAAe,MAAc,EAAU,GACzC,IAAqB,EAAE,UAAU,EAAE,GAGnC,KAAQ,EAAM,cAAc,GAAS,GAAG,CAAC,CAAC,GAG1C,IAAe,EAAM,cAClB,MAAM,QAAQ,CAAW,IAAI,IAAc,CAAC,CAAW,GAC9D,CAAC,CAAW,CACd,GAGM,IAAY,EAAO,SAAS,GAG5B,IAAiB,EAAM,cAAc;EACzC,IAAI,CAAC,GAAW,OAAO,CAAC;EACxB,IAAI,CAAC,EAAM,KAAK,GAAG,OAAO;EAC1B,IAAM,IAAI,EAAM,YAAY;EAC5B,OAAO,EACJ,KAAK,OAAW;GACf,GAAG;GACH,OAAO,EAAM,MAAM,QAChB,MACC,GAAe,CAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,KAC7C,GAAqB,CAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,CACvD;EACF,EAAE,CAAC,CACF,QAAQ,MAAU,EAAM,MAAM,SAAS,CAAC;CAC7C,GAAG;EAAC;EAAQ;EAAO;CAAS,CAAC,GAEvB,IAAgB,EAAM,cACpB,EAAe,SAAS,MAAM,EAAE,KAAK,GAC3C,CAAC,CAAc,CACjB,GAGM,KAAe,EAAM,cAAc;EACvC,IAAM,oBAAM,IAAI,IAAoB,GAChC,IAAM;EACV,KAAK,IAAM,KAAS,GAClB,KAAK,IAAM,KAAQ,EAAM,OACvB,EAAI,IAAI,EAAK,IAAI,GAAK;EAG1B,OAAO;CACT,GAAG,CAAC,CAAc,CAAC,GAGb,KACJ,OAAO,KAAc,WAAW,GAAG,EAAU,MAAM;CAiCrD,AA9BA,EAAM,gBAAgB;EACpB,IAAI,MAAY,cAAc,MAAe,IAAO;EAEpD,IAAM,IAAW,MAAM,QAAQ,CAAU,IAAI,IAAa,CAAC,CAAU;EAErE,SAAS,EAAc,GAAkB;GACvC,KAAK,IAAM,KAAW,GACpB,IAAI,GAAkB,GAAG,CAAO,GAAG;IAEjC,AADA,EAAE,eAAe,GACjB,GAAS,MAAS,CAAC,CAAI;IACvB;GACF;EAEJ;EAEA,OADA,SAAS,iBAAiB,WAAW,CAAa,SACrC,SAAS,oBAAoB,WAAW,CAAa;CACpE,GAAG;EAAC;EAAS;EAAY;CAAO,CAAC,GAGjC,EAAM,gBAAgB;EACpB,AAAI,MAAY,cAAc,MAC5B,EAAS,EAAE,GACX,EAAe,EAAE,GACjB,4BAA4B;GAC1B,EAAS,SAAS,MAAM;EAC1B,CAAC;CAEL,GAAG,CAAC,GAAS,CAAI,CAAC,GAGlB,EAAM,gBAAgB;EAChB,IAAc,MACD,GAAQ,SAAS,cAChC,wBAAwB,EAAY,GACtC,EAAA,EACU,eAAe,EAAE,OAAO,UAAU,CAAC;CAC/C,GAAG,CAAC,CAAW,CAAC;CAGhB,IAAM,MAAqB,MAAkB;EAG3C,AAFA,EAAS,CAAK,GACd,EAAe,KAAa,EAAM,KAAK,IAAI,IAAI,EAAE,GACjD,IAAW,CAAK;CAClB,GAGM,KAAe,EAAM,kBAAkB;EACvC,CAAC,EAAM,KAAK,KAAK,MACrB,GAAa,CAAK,GAClB,IAAW,CAAK;CAClB,GAAG;EAAC;EAAO;EAAU;CAAQ,CAAC,GAGxB,MAAiB,MAA2B;EAChD,QAAQ,EAAE,KAAV;GACE,KAAK;IACH,IAAI,CAAC,KAAa,EAAc,WAAW,GAAG;IAE9C,AADA,EAAE,eAAe,GACjB,GAAgB,MACd,IAAO,EAAc,SAAS,IAAI,IAAO,IAAI,CAC/C;IACA;GAEF,KAAK;IACH,AAAI,KAAa,EAAc,SAAS,KACtC,EAAE,eAAe,GACjB,GAAgB,MACd,IAAO,IAAI,IAAO,IAAI,EAAc,SAAS,CAC/C,KACS,CAAC,KAAa,CAAC,KAAS,MAEjC,EAAE,eAAe,GACjB,EAAS,CAAS;IAEpB;GAEF,KAAK;IAIH,AAHA,EAAE,eAAe,GACE,EAAE,WAAW,EAAE,UAIhC,GAAa,IAEb,KACA,KAAe,KACf,EAAc,MAGd,EAAc,EAAY,CAAC,SAAS,GAChC,MAAY,cAAY,EAAQ,EAAK,KAGzC,GAAa;IAEf;GAEF,KAAK;IAEH,AADA,EAAE,eAAe,GACb,MAAU,cACZ,EAAS,EAAE,IACF,MAAY,aACrB,EAAQ,EAAK,IAEb,EAAS,SAAS,KAAK;IAEzB;EAEJ;CACF,GAGM,WAAoB;EAGxB,AAFA,EAAS,EAAE,GACX,EAAe,EAAE,GACjB,EAAS,SAAS,MAAM;CAC1B;CAWqB,AARrB,EAAM,gBAAgB;EACpB,IAAI,GAAO;GACT,IAAM,IAAQ,iBAAiB,GAAS,EAAK,GAAG,GAAG;GACnD,aAAa,aAAa,CAAK;EACjC;CACF,GAAG,CAAC,CAAK,CAAC,GAGW,KAAiC,EAAQ;CAC9D,IAAM,IAAY,IAAY,IAAqB,EAAO,MACpD,IAAS,IAAY;EAAE,SAAS;EAAG,OAAO;EAAG,GAAG;CAAE,IAAI,KAAA,GAKtD,IAAY,MAAY,UACxB,IAAe,MAAU,cACzB,KAAc,MAAU,aAExB,UACJ,kBAAC,IAAD;EACE,QAAQ;EACR,SAAS,IAAY,oBAAoB;EACzC,eAAe;YAEf,kBAAC,OAAD;GACE,WAAW,EACT,uIACA,IACI,6BACA,4BACJ,IACI,uBACA,gCACJ,KAAa,CAAC,KAAgB,+BAC9B,KAAS,eACX;aAXF;IAcA,kBAAC,GAAD;KACE,MAAM;KACN,MAAM,IAAY,OAAO;KACzB,QAAO;KACP,WAAW,EACT,wEACA,IAAY,kBAAkB,wBAChC;IACD,CAAA;IAGD,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,CAAC,KAAS,CAAC,KAAa,EAAa,SAAS,KAC7C,kBAAC,IAAD;MACgB;MACd,UAAU;MACV,QAAQ,KAAa,CAAC,CAAC;KACxB,CAAA,GAEH,kBAAC,SAAD;MACE,KAAK;MACL,OAAO;MACP,WAAW,MAAM,GAAkB,EAAE,OAAO,KAAK;MACjD,eAAe,GAAa,EAAI;MAChC,cAAc,GAAa,EAAK;MAChC,WAAW;MACX,aACE,EAAa,WAAW,KAAK,IAAY,EAAa,KAAK;MAE7D,UAAU;MACA;MACV,MAAK;MACL,iBAAe,KAAa,EAAc,SAAS;MACnD,iBAAe,IAAY,KAAY,KAAA;MACvC,yBACE,KAAa,KAAe,KAAK,EAAc,KAC3C,oBAAoB,EAAW,GAAG,EAAc,EAAY,CAAC,OAC7D,KAAA;MAEN,qBAAmB,IAAY,SAAS,KAAA;MACxC,cAAY,KAAY,OAAO,OAAc;MAC7C,WAAW,EACT,wDACA,sCACA,IAAY,qBAAqB,qBACjC,KAAgB,eAChB,KAAY,+BACd;MACA,cAAa;MACb,aAAY;MACZ,YAAY;KACb,CAAA,CACE;;IAGJ,IACC,kBAAC,QAAD;KAAM,eAAY;KAAsB,WAAU;eAChD,kBAAC,GAAD;MACE,MAAM;MACN,MAAM,IAAY,OAAO;MACzB,QAAO;MACP,SAAQ;MACR,WAAU;KACX,CAAA;IACG,CAAA,IACJ,KACF,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;KACV,cAAW;KACX,OAAM;eAEN,kBAAC,GAAD;MACE,MAAM;MACN,MAAM,IAAY,OAAO;MACzB,QAAO;KACR,CAAA;IACK,CAAA,IACN,MAAY,SACd,kBAAC,GAAD,EAAA,UACG,CAAC,KACA,kBAAC,EAAO,KAAR;KACE,SAAS,KAAU,EAAE,SAAS,EAAE;KAChC,SAAS,EAAE,SAAS,EAAE;KACtB,MAAM,IAAY,KAAA,IAAY,EAAE,SAAS,EAAE;KAC3C,YAAY;KACZ,WAAU;eALZ,CAOG,GAAmB,EAAK,GAAE,GACjB;OAEC,CAAA,IACf;GACC;;CACa,CAAA,GAMhB,UACA,CAAC,KAKD,EAFF,EAAc,SAAS,KAAM,EAAM,KAAK,KAAK,EAAe,WAAW,MAErD,CAAC,EAAM,KAAK,IAAU,OAGxC,kBAAC,OAAD;EACE,KAAK;EACL,IAAI;EACJ,MAAK;EACL,cAAW;EACX,WAAU;EACV,OAAO,EAAE,WAAW,GAAe;YANrC,CAQG,EAAe,WAAW,KAAK,EAAM,KAAK,KACzC,kBAAC,EAAO,KAAR;GACE,SAAS,KAAU,EAAE,SAAS,EAAE;GAChC,SAAS,EAAE,SAAS,EAAE;GACtB,YAAY;GACZ,WAAU;aAET,MACC,kBAAC,KAAD;IAAG,WAAU;cACV;GACA,CAAA;EAEK,CAAA,GAGb,EAAe,KAAK,GAAO,MAC1B,kBAAC,EAAO,KAAR;GAEE,SAAS,KAAU,EAAE,SAAS,EAAE;GAChC,SAAS,EAAE,SAAS,EAAE;GACtB,YACE,IACI,IACA;IAAE,GAAG,EAAO;IAAM,OAAO,IAAW;GAAK;GAE/C,WAAU;aATZ,CAWE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,QAAD;KAAM,WAAU;eACb,EAAM;IACH,CAAA;GACH,CAAA,GAEJ,EAAM,MAAM,KAAK,MAAS;IACzB,IAAM,IAAY,GAAa,IAAI,EAAK,EAAE,KAAK,GACzC,IAAW,MAAc;IAC/B,OACE,kBAAC,EAAO,QAAR;KAEE,IAAI,oBAAoB,EAAW,GAAG,EAAK;KAC3C,MAAK;KACL,MAAK;KACL,iBAAe;KACf,sBAAoB;KACpB,SAAS,KAAU;MAAE,SAAS;MAAG,GAAG;KAAE;KACtC,SAAS;MAAE,SAAS;MAAG,GAAG;KAAE;KAC5B,YACE,IACI,IACA;MAAE,GAAG,EAAQ;MAAQ,OAAO,IAAY;KAAK;KAEnD,eAAe;MAEb,AADA,EAAK,SAAS,GACV,MAAY,cAAY,EAAQ,EAAK;KAC3C;KACA,oBAAoB,EAAe,CAAS;KAC5C,WAAW,EACT,gKACA,IACI,4CACA,+CACN;eAxBF;MA0BG,EAAK,QACJ,kBAAC,QAAD;OACE,WAAW,EACT,0GACA,IACI,mBACA,wBACN;OACA,eAAY;iBAEZ,kBAAC,GAAD;QAAc,MAAK;kBAAM,EAAc,EAAK,IAAI;OAAgB,CAAA;MAC5D,CAAA;MAER,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAK,cACF,EAAK,YAAY,CAAK,IACtB,EAAK;OACL,CAAA,GACL,EAAK,eACJ,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAK;OACF,CAAA,CAEL;;MACL,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,EAAO,MAAR;OACE,SAAS,IAAY,KAAA,IAAY,EAAE,SAAS,EAAE;OAC9C,SAAS,EAAE,SAAS,EAAE;OACtB,MAAM,IAAY,KAAA,IAAY,EAAE,SAAS,EAAE;OAC3C,YAAY;OACZ,WAAU;iBAEV,kBAAC,GAAD;QACE,MAAM;QACN,MAAK;QACL,QAAO;QACP,WAAU;OACX,CAAA;MACU,CAAA,EAEA,CAAA;KACJ;OApER,EAAK,EAoEG;GAEnB,CAAC,CACS;KA5FL,EAAM,KA4FD,CACb,CACE;;CA8ET,OAvEI,MAAY,SAEZ,kBAAC,OAAD;EACO;EACL,MAAK;EACL,WAAW,EACT,8DACA,CACF;EACA,GAAI;YAPN;GASG,KACC,kBAAC,KAAD;IAAG,WAAU;cACV;GACA,CAAA;GAGJ,EAAe;GACf,EAAqB;GAGrB,KAAS,EAAM,SAAS,KACvB,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAM,KAAK,MACV,kBAAC,UAAD;KAEE,MAAK;KACL,eAAe;MAGb,AAFA,EAAS,CAAI,GACb,IAAW,CAAI,GACf,EAAS,SAAS,MAAM;KAC1B;KACA,WAAU;eAET;IACK,GAVD,CAUC,CACT;GACE,CAAA;GAIN,KAAY,kBAAC,OAAD;IAAK,WAAU;IAAY;GAAc,CAAA;EACnD;MAOL,MAAY,WAEZ,kBAAC,OAAD;EACO;EACL,MAAK;EACL,WAAW,EAAG,UAAU,CAAS;EACjC,GAAI;YAJN;GAMG,EAAe;GACf,EAAqB;GACrB,KAAY,kBAAC,OAAD;IAAK,WAAU;IAAY;GAAc,CAAA;EACnD;MAYP,kBAAC,GAAD;EAAc;EAAM,eALU,MAAsB;GACpD,EAAQ,CAAQ;EAClB;YAII,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAe,WAAU,6JAA8J,CAAA,GACvL,kBAAC,GAAD;GACO;GACL,GAAI;GACJ,WAAW,EACT,0EACA,wEACA,qFACA,8DACA,gEACA,sFACA,gFACA,CACF;aAZF;IAcE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAa,iBAA2B,CAAA,GACxC,kBAAC,IAAD,EAAA,UAAmB,oCAEA,CAAA,CACL,EAAA,CAAA;IAEhB,kBAAC,OAAD;KAAK,WAAU;eAAW,EAAe;IAAO,CAAA;IAE/C,EAAqB;IAErB,KACC,kBAAC,OAAD;KAAK,WAAU;KACZ;IACE,CAAA;IAIP,kBAAC,EAAO,KAAR;KACE,SAAS,KAAU,EAAE,SAAS,EAAE;KAChC,SAAS,EAAE,SAAS,EAAE;KACtB,YAAY;KACZ,WAAU;eAJZ;MAMG,KACC,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,GAAD;UAAM,MAAM;UAAa,MAAK;UAAK,WAAU;SAA0B,CAAA;QACpE,CAAA,GACL,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,GAAD;UAAM,MAAM;UAAe,MAAK;UAAK,WAAU;SAA0B,CAAA;QACtE,CAAA,CACF;WACL,kBAAC,QAAD;QAAM,WAAU;kBAAsC;OAEhD,CAAA,CACH;;MAEP,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD;SAAM,MAAM;SAAoB,MAAK;SAAK,WAAU;QAA0B,CAAA;OAC3E,CAAA,GACL,kBAAC,QAAD;QAAM,WAAU;kBAAsC;OAEhD,CAAA,CACH;;MACL,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAoL;OAE9L,CAAA,GACL,kBAAC,QAAD;QAAM,WAAU;kBAAsC;OAEhD,CAAA,CACH;;KACK;;GACI;IACN,EAAA,CAAA;CACR,CAAA;AAEZ,CACF;AAEA,EAAW,cAAc"}
1
+ {"version":3,"file":"command-bar.js","names":[],"sources":["../../src/ai/command-bar.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandBar -- Unified AI command interface.\n *\n * Three variants:\n * - hero: Full-featured inline bar with greeting, hints, placeholder rotation\n * - inline: Compact inline bar for embedding in panels/toolbars\n * - floating: Modal overlay (same pattern as CommandPalette) with global keybinding\n *\n * Supports both command-palette filtering (when `groups` provided) and\n * AI natural-language submission via `onSubmit`.\n */\nimport {\n IconArrowDown,\n IconArrowUp,\n IconCornerDownLeft,\n IconLoader2,\n IconSearch,\n IconX,\n} from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport type { CommandGroup, CommandItem } from '../composed/command-palette'\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// GradientBorderWrap — animated gradient border during processing\n// -----------------------------------------------------------------------\n\n/**\n * Wraps the input row with an animated gradient border during processing.\n * Uses the Devalok brand palette (pink → purple → magenta) flowing around\n * the border. When inactive, renders children directly with no wrapper overhead.\n *\n * Technique: outer div with gradient background + padding-[1.5px] creates\n * a visible gradient border. The inner content covers the center, leaving\n * only the edge visible as a \"border\".\n */\nfunction GradientBorderWrap({\n active,\n rounded,\n reducedMotion,\n children,\n}: {\n active: boolean\n rounded: string\n reducedMotion: boolean\n children: React.ReactNode\n}) {\n if (!active) return <>{children}</>\n\n if (reducedMotion) {\n return (\n <div className={cn('p-[1.5px] bg-accent-9', rounded)}>\n {children}\n </div>\n )\n }\n\n return (\n <motion.div\n className={cn('relative p-[1.5px]', rounded)}\n style={{\n background: 'linear-gradient(var(--gradient-angle, 0deg), #D33163, #9B5DE5, #C850C0, #D33163)',\n backgroundSize: '300% 300%',\n }}\n animate={{\n // Rotate the gradient angle — creates the flowing border effect\n // Using CSS custom property animation via backgroundPosition as proxy\n backgroundPosition: ['0% 0%', '100% 100%', '0% 0%'],\n }}\n transition={{\n backgroundPosition: {\n duration: 4,\n repeat: Infinity,\n ease: 'linear',\n },\n }}\n >\n {children}\n </motion.div>\n )\n}\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\n/**\n * Unified AI command interface with three visual variants:\n * - `hero`: full-featured inline bar with greeting, animated placeholder rotation, and hints\n * - `inline`: compact bar for embedding in panels or toolbars\n * - `floating`: modal overlay with global keybinding (same pattern as CommandPalette)\n *\n * Supports both command-palette filtering (when `groups` provided) and\n * natural-language AI submission via `onSubmit`.\n */\nexport interface CommandBarProps\n extends Omit<React.ComponentPropsWithRef<'div'>, 'onSubmit'> {\n // -- AI submission --\n /** Called when the user submits a query (Enter key). */\n onSubmit?: (query: string) => void\n /** Current interaction state. Controls visual feedback (gradient border, placeholder). */\n state?: 'idle' | 'typing' | 'processing' | 'responded'\n\n // -- Command palette mode (optional) --\n /** When provided, enables command-palette filtering alongside AI submission. */\n groups?: CommandGroup[]\n onSearch?: (query: string) => void\n emptyMessage?: string\n emptyState?: React.ReactNode\n\n // -- Visual --\n /** Layout variant. @default 'hero' */\n variant?: 'hero' | 'inline' | 'floating'\n /** Placeholder text, or an array of strings that rotate on an interval. */\n placeholder?: string | string[]\n /** Rotation interval in ms when `placeholder` is an array. @default 4000 */\n placeholderInterval?: number\n /** Greeting text shown above the input in `hero` variant. */\n greeting?: string\n /** Hint strings shown below the input in `hero` variant. */\n hints?: string[]\n agentName?: string\n agentIcon?: React.ReactNode\n\n // -- Floating variant (modal) --\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Keybinding to toggle the floating bar. @default 'mod+k' */\n keybinding?: string | string[] | false\n\n // -- Interaction --\n disabled?: boolean\n maxHeight?: string | number\n\n // -- Composition --\n children?: React.ReactNode\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n// -----------------------------------------------------------------------\n// Rotating Placeholder\n// -----------------------------------------------------------------------\n\nfunction RotatingPlaceholder({\n placeholders,\n interval,\n paused,\n}: {\n placeholders: string[]\n interval: number\n paused: boolean\n}) {\n const [currentIndex, setCurrentIndex] = React.useState(0)\n const { reducedMotion } = useMotion()\n\n React.useEffect(() => {\n if (paused || placeholders.length <= 1) return\n const timer = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % placeholders.length)\n }, interval)\n return () => clearInterval(timer)\n }, [paused, placeholders.length, interval])\n\n if (reducedMotion) {\n return (\n <span className=\"pointer-events-none absolute text-surface-fg-subtle\">\n {placeholders[currentIndex]}\n </span>\n )\n }\n\n return (\n <AnimatePresence mode=\"wait\">\n <motion.span\n key={placeholders[currentIndex]}\n initial={{ opacity: 0, y: -4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 4 }}\n transition={tweens.fade}\n className=\"pointer-events-none absolute text-surface-fg-subtle\"\n >\n {placeholders[currentIndex]}\n </motion.span>\n </AnimatePresence>\n )\n}\n\n// -----------------------------------------------------------------------\n// CommandBar\n// -----------------------------------------------------------------------\n\nconst CommandBar = React.forwardRef<HTMLDivElement, CommandBarProps>(\n function CommandBar(\n {\n onSubmit,\n state = 'idle',\n groups = [],\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n variant = 'hero',\n placeholder = 'Ask anything...',\n placeholderInterval = 5000,\n greeting,\n hints,\n agentName,\n agentIcon,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+j',\n disabled = false,\n maxHeight = '320px',\n children,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state (floating) --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved =\n typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n // -- Core state --\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(-1)\n const [lastQuery, setLastQuery] = React.useState('')\n const [isFocused, setIsFocused] = React.useState(false)\n const [shake, setShake] = React.useState(false)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-bar-listbox-${instanceId}`\n\n // -- Motion --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // -- Placeholders --\n const placeholders = React.useMemo(\n () => (Array.isArray(placeholder) ? placeholder : [placeholder]),\n [placeholder],\n )\n\n // -- Has groups --\n const hasGroups = groups.length > 0\n\n // -- Filter groups --\n const filteredGroups = React.useMemo(() => {\n if (!hasGroups) return []\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query, hasGroups])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Build item index map for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Max height CSS --\n const maxHeightValue =\n typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Global keybinding (floating variant) --\n React.useEffect(() => {\n if (variant !== 'floating' || keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [variant, keybinding, setOpen])\n\n // -- Reset on floating open --\n React.useEffect(() => {\n if (variant === 'floating' && open) {\n setQuery('')\n setActiveIndex(-1)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [variant, open])\n\n // -- Scroll active item into view --\n React.useEffect(() => {\n if (activeIndex < 0) return\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n // -- Query change handler --\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(hasGroups && value.trim() ? 0 : -1)\n onSearch?.(value)\n }\n\n // -- Submit handler --\n const handleSubmit = React.useCallback(() => {\n if (!query.trim() || disabled) return\n setLastQuery(query)\n onSubmit?.(query)\n }, [query, disabled, onSubmit])\n\n // -- Keyboard handler --\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n if (!hasGroups || filteredItems.length === 0) return\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n if (hasGroups && filteredItems.length > 0) {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n } else if (!hasGroups && !query && lastQuery) {\n // Recall last query\n e.preventDefault()\n setQuery(lastQuery)\n }\n break\n }\n case 'Enter': {\n e.preventDefault()\n const isCmdEnter = e.metaKey || e.ctrlKey\n\n if (isCmdEnter) {\n // Cmd+Enter always submits\n handleSubmit()\n } else if (\n hasGroups &&\n activeIndex >= 0 &&\n filteredItems[activeIndex]\n ) {\n // Enter selects active command item\n filteredItems[activeIndex].onSelect()\n if (variant === 'floating') setOpen(false)\n } else {\n // Enter submits query\n handleSubmit()\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n if (state === 'responded') {\n setQuery('')\n } else if (variant === 'floating') {\n setOpen(false)\n } else {\n inputRef.current?.blur()\n }\n break\n }\n }\n }\n\n // -- Clear handler --\n const handleClear = () => {\n setQuery('')\n setActiveIndex(-1)\n inputRef.current?.focus()\n }\n\n // -- Shake animation reset --\n React.useEffect(() => {\n if (shake) {\n const timer = setTimeout(() => setShake(false), 500)\n return () => clearTimeout(timer)\n }\n }, [shake])\n\n // -- Shared spring/tween for reduced motion --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // =====================================================================\n // Shared Input Row\n // =====================================================================\n const isCompact = variant === 'inline'\n const isProcessing = state === 'processing'\n const isResponded = state === 'responded'\n\n const renderInputRow = () => (\n <GradientBorderWrap\n active={isProcessing}\n rounded={isCompact ? 'rounded-control' : 'rounded-surface'}\n reducedMotion={isReduced}\n >\n <div\n className={cn(\n 'flex items-center gap-ds-04 border bg-surface-overlay transition-colors transition-shadow duration-fast-02 ease-productive-standard',\n isCompact\n ? 'rounded-control px-ds-04'\n : 'rounded-surface px-ds-05',\n isProcessing\n ? 'border-transparent'\n : 'border-surface-border-strong',\n isFocused && !isProcessing && 'border-accent-7 shadow-ring',\n shake && 'animate-shake',\n )}\n >\n {/* Search icon */}\n <Icon\n icon={IconSearch}\n size={isCompact ? 'xs' : 'sm'}\n stroke=\"light\"\n className={cn(\n 'shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isFocused ? 'text-accent-9' : 'text-surface-fg-subtle',\n )}\n />\n\n {/* Input wrapper */}\n <div className=\"relative flex flex-1 items-center\">\n {!query && !isFocused && placeholders.length > 1 && (\n <RotatingPlaceholder\n placeholders={placeholders}\n interval={placeholderInterval}\n paused={isFocused || !!query}\n />\n )}\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n placeholder={\n placeholders.length === 1 || isFocused ? placeholders[0] : ''\n }\n readOnly={isProcessing}\n disabled={disabled}\n role=\"combobox\"\n aria-expanded={hasGroups && filteredItems.length > 0}\n aria-controls={hasGroups ? listboxId : undefined}\n aria-activedescendant={\n hasGroups && activeIndex >= 0 && filteredItems[activeIndex]\n ? `command-bar-item-${instanceId}-${filteredItems[activeIndex].id}`\n : undefined\n }\n aria-autocomplete={hasGroups ? 'list' : undefined}\n aria-label={agentName ? `Ask ${agentName}` : 'AI Command Bar'}\n className={cn(\n 'flex-1 bg-transparent text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n isCompact ? 'h-9 text-body-sm' : 'h-12 text-body-lg',\n isProcessing && 'cursor-wait',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n </div>\n\n {/* Right side: spinner / clear / shortcut badge */}\n {isProcessing ? (\n <span data-testid=\"command-bar-spinner\" className=\"shrink-0\">\n <Icon\n icon={IconLoader2}\n size={isCompact ? 'xs' : 'sm'}\n stroke=\"light\"\n animate=\"spin\"\n className=\"text-accent-9\"\n />\n </span>\n ) : isResponded ? (\n <button\n type=\"button\"\n onClick={handleClear}\n className=\"shrink-0 rounded-control-inner p-ds-01 text-surface-fg-subtle transition-colors duration-fast-01 hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Clear\"\n title=\"Clear\"\n >\n <Icon\n icon={IconX}\n size={isCompact ? 'xs' : 'sm'}\n stroke=\"light\"\n />\n </button>\n ) : variant === 'hero' ? (\n <AnimatePresence>\n {!isFocused && (\n <motion.kbd\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\"\n >\n {getModifierDisplay(isMac)}J\n </motion.kbd>\n )}\n </AnimatePresence>\n ) : null}\n </div>\n </GradientBorderWrap>\n )\n\n // =====================================================================\n // Command Results (shared between variants)\n // =====================================================================\n const renderCommandResults = () => {\n if (!hasGroups) return null\n\n const showResults =\n filteredItems.length > 0 || (query.trim() && filteredGroups.length === 0)\n\n if (!showResults && !query.trim()) return null\n\n return (\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && query.trim() && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={\n isReduced\n ? noMotionTransition\n : { ...tweens.fade, delay: groupIdx * 0.06 }\n }\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-bar-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={\n isReduced\n ? noMotionTransition\n : { ...springs.snappy, delay: itemIndex * 0.03 }\n }\n onClick={() => {\n item.onSelect()\n if (variant === 'floating') setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'text-accent-11'\n : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex flex-1 flex-col\">\n <span className=\"text-body-md\">\n {item.renderLabel\n ? item.renderLabel(query)\n : item.label}\n </span>\n {item.description && (\n <span className=\"text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon\n icon={IconCornerDownLeft}\n size=\"sm\"\n stroke=\"light\"\n className=\"text-surface-fg-subtle\"\n />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n )\n }\n\n // =====================================================================\n // Hero Variant\n // =====================================================================\n if (variant === 'hero') {\n return (\n <div\n ref={ref}\n role=\"search\"\n className={cn(\n 'bg-surface-raised rounded-overlay-lg shadow-raised p-ds-07',\n className,\n )}\n {...props}\n >\n {greeting && (\n <p className=\"text-heading-xs text-surface-fg-muted mb-ds-04\">\n {greeting}\n </p>\n )}\n\n {renderInputRow()}\n {renderCommandResults()}\n\n {/* Hints */}\n {hints && hints.length > 0 && (\n <div className=\"mt-ds-04 flex flex-wrap gap-ds-02b\">\n {hints.map((hint) => (\n <button\n key={hint}\n type=\"button\"\n onClick={() => {\n setQuery(hint)\n onSearch?.(hint)\n inputRef.current?.focus()\n }}\n className=\"rounded-control border border-card-strong bg-surface-overlay px-ds-03 py-ds-01 text-body-sm text-surface-fg-subtle transition-colors duration-fast-02 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted\"\n >\n {hint}\n </button>\n ))}\n </div>\n )}\n\n {/* Response area (children) */}\n {children && <div className=\"mt-ds-05\">{children}</div>}\n </div>\n )\n }\n\n // =====================================================================\n // Inline Variant\n // =====================================================================\n if (variant === 'inline') {\n return (\n <div\n ref={ref}\n role=\"search\"\n className={cn('w-full', className)}\n {...props}\n >\n {renderInputRow()}\n {renderCommandResults()}\n {children && <div className=\"mt-ds-03\">{children}</div>}\n </div>\n )\n }\n\n // =====================================================================\n // Floating Variant\n // =====================================================================\n const handleDialogOpenChange = (nextOpen: boolean) => {\n setOpen(nextOpen)\n }\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n >\n <VisuallyHidden>\n <DialogTitle>AI Command Bar</DialogTitle>\n <DialogDescription>\n Search commands or ask a question\n </DialogDescription>\n </VisuallyHidden>\n\n <div className=\"p-ds-04\">{renderInputRow()}</div>\n\n {renderCommandResults()}\n\n {children && (\n <div className=\"border-t border-surface-border-strong p-ds-04\">\n {children}\n </div>\n )}\n\n {/* Footer hints */}\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {hasGroups && (\n <div className=\"flex items-center gap-ds-02b\">\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n <span className=\"text-caption text-surface-fg-subtle\">\n Navigate\n </span>\n </div>\n )}\n <div className=\"flex items-center gap-ds-02b\">\n <kbd className=\"inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <span className=\"text-caption text-surface-fg-subtle\">\n Submit\n </span>\n </div>\n <div className=\"flex items-center gap-ds-02b\">\n <kbd className=\"inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n Esc\n </kbd>\n <span className=\"text-caption text-surface-fg-subtle\">\n Close\n </span>\n </div>\n </motion.div>\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandBar.displayName = 'CommandBar'\n\nexport { CommandBar }\nexport type { CommandGroup, CommandItem }\n"],"mappings":"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"}
@@ -3,8 +3,8 @@ import { IconProvider as e } from "../ui/icon-context.js";
3
3
  import { durations as t, springs as n } from "../ui/lib/motion.js";
4
4
  import { cn as r } from "../ui/lib/utils.js";
5
5
  import { Icon as i } from "../ui/icon.js";
6
- import { normalizeIcon as a } from "../_chunks/normalize-icon.js";
7
- import { useMotion as o } from "../_chunks/motion-provider.js";
6
+ import { useMotion as a } from "../_chunks/motion-provider.js";
7
+ import { normalizeIcon as o } from "../_chunks/normalize-icon.js";
8
8
  import { useAICommand as s } from "./ai-command-provider.js";
9
9
  import { BlockRenderer as c } from "./block-renderer.js";
10
10
  import * as l from "react";
@@ -52,7 +52,7 @@ function y({ name: t, icon: n }) {
52
52
  className: "h-4 w-4 flex items-center justify-center",
53
53
  children: /* @__PURE__ */ u(e, {
54
54
  size: "sm",
55
- children: a(n)
55
+ children: o(n)
56
56
  })
57
57
  }), /* @__PURE__ */ u("span", {
58
58
  className: "text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
@@ -180,8 +180,8 @@ function C({ onClick: e }) {
180
180
  children: ["↓", " New response"]
181
181
  });
182
182
  }
183
- var w = { name: "Assistant" }, T = l.forwardRef(({ messages: e, isProcessing: t = !1, processingSteps: n, agent: i, onAction: a, customBlocks: c, maxHeight: f, autoScroll: p = !0, className: m }, h) => {
184
- let _ = s(), { reducedMotion: v } = o(), y = i ?? _?.agent ?? w, T = a ?? _?.onAction, E = l.useMemo(() => ({
183
+ var w = { name: "Assistant" }, T = l.forwardRef(({ messages: e, isProcessing: t = !1, processingSteps: n, agent: i, onAction: o, customBlocks: c, maxHeight: f, autoScroll: p = !0, className: m }, h) => {
184
+ let _ = s(), { reducedMotion: v } = a(), y = i ?? _?.agent ?? w, T = o ?? _?.onAction, E = l.useMemo(() => ({
185
185
  ..._?.customBlocks ?? {},
186
186
  ...c
187
187
  }), [_?.customBlocks, c]), D = l.useRef(null), O = l.useRef(null), [k, A] = l.useState(!0), [j, M] = l.useState(!1), N = l.useRef(e.length), P = l.useRef(t);
@@ -3,10 +3,10 @@ import { IconProvider as e } from "../ui/icon-context.js";
3
3
  import { springs as t, tweens as n } from "../ui/lib/motion.js";
4
4
  import { cn as r } from "../ui/lib/utils.js";
5
5
  import { Icon as i } from "../ui/icon.js";
6
- import { normalizeIcon as a } from "../_chunks/normalize-icon.js";
7
- import { Dialog as o, DialogContentRaw as s, DialogDescription as c, DialogOverlay as l, DialogPortal as ee, DialogTitle as u } from "../ui/dialog.js";
8
- import { VisuallyHidden as te } from "../ui/visually-hidden.js";
9
- import { useMotion as ne } from "../_chunks/motion-provider.js";
6
+ import { useMotion as a } from "../_chunks/motion-provider.js";
7
+ import { normalizeIcon as o } from "../_chunks/normalize-icon.js";
8
+ import { Dialog as s, DialogContentRaw as c, DialogDescription as l, DialogOverlay as ee, DialogPortal as u, DialogTitle as te } from "../ui/dialog.js";
9
+ import { VisuallyHidden as ne } from "../ui/visually-hidden.js";
10
10
  import { getIsMac as d, getModifierDisplay as f, matchesKeybinding as p } from "../_chunks/keybinding.js";
11
11
  import * as m from "react";
12
12
  import { jsx as h, jsxs as g } from "react/jsx-runtime";
@@ -28,7 +28,7 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
28
28
  let R = m.useCallback((e) => {
29
29
  let t = typeof e == "function" ? e(L.current) : e;
30
30
  N || F(t), E?.(t);
31
- }, [N, E]), [z, B] = m.useState(""), [V, H] = m.useState(0), U = m.useRef(null), W = m.useRef(null), G = m.useId(), K = `command-palette-listbox-${G}`, { reducedMotion: q } = ne(), J = { duration: 0 }, ue = m.useMemo(() => d(), []), Y = m.useMemo(() => {
31
+ }, [N, E]), [z, B] = m.useState(""), [V, H] = m.useState(0), U = m.useRef(null), W = m.useRef(null), G = m.useId(), K = `command-palette-listbox-${G}`, { reducedMotion: q } = a(), J = { duration: 0 }, ue = m.useMemo(() => d(), []), Y = m.useMemo(() => {
32
32
  if (!z.trim()) return b;
33
33
  let e = z.toLowerCase();
34
34
  return b.map((t) => ({
@@ -97,18 +97,18 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
97
97
  label: "Close"
98
98
  }
99
99
  ];
100
- return /* @__PURE__ */ h(o, {
100
+ return /* @__PURE__ */ h(s, {
101
101
  open: I,
102
102
  onOpenChange: m.useCallback((e) => {
103
103
  R(e);
104
104
  }, [R]),
105
- children: /* @__PURE__ */ g(ee, { children: [/* @__PURE__ */ h(l, { className: "fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }), /* @__PURE__ */ g(s, {
105
+ children: /* @__PURE__ */ g(u, { children: [/* @__PURE__ */ h(ee, { className: "fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }), /* @__PURE__ */ g(c, {
106
106
  ref: M,
107
107
  ...j,
108
108
  className: r("fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2", "overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay", "duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2", "data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2", A),
109
109
  onKeyDown: de,
110
110
  children: [
111
- /* @__PURE__ */ g(te, { children: [/* @__PURE__ */ h(u, { children: "Command Palette" }), /* @__PURE__ */ h(c, { children: "Search or jump to pages, projects, tasks, and actions" })] }),
111
+ /* @__PURE__ */ g(ne, { children: [/* @__PURE__ */ h(te, { children: "Command Palette" }), /* @__PURE__ */ h(l, { children: "Search or jump to pages, projects, tasks, and actions" })] }),
112
112
  /* @__PURE__ */ g("div", {
113
113
  className: "flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04",
114
114
  children: [
@@ -167,7 +167,7 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
167
167
  className: "text-body-md text-surface-fg-subtle",
168
168
  children: S
169
169
  })
170
- }), Y.map((o, s) => /* @__PURE__ */ g(v.div, {
170
+ }), Y.map((a, s) => /* @__PURE__ */ g(v.div, {
171
171
  initial: Q ?? { opacity: 0 },
172
172
  animate: { opacity: 1 },
173
173
  transition: q ? J : {
@@ -179,16 +179,16 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
179
179
  className: "px-ds-03 pb-ds-02 pt-ds-03",
180
180
  children: /* @__PURE__ */ h("span", {
181
181
  className: "text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
182
- children: o.label
182
+ children: a.label
183
183
  })
184
- }), o.items.map((n) => {
185
- let o = pe.get(n.id) ?? 0, s = o === V;
184
+ }), a.items.map((n) => {
185
+ let a = pe.get(n.id) ?? 0, s = a === V;
186
186
  return /* @__PURE__ */ g(v.button, {
187
187
  id: `command-item-${G}-${n.id}`,
188
188
  type: "button",
189
189
  role: "option",
190
190
  "aria-selected": s,
191
- "data-command-index": o,
191
+ "data-command-index": a,
192
192
  initial: Q ?? {
193
193
  opacity: 0,
194
194
  y: 4
@@ -199,12 +199,12 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
199
199
  },
200
200
  transition: q ? J : {
201
201
  ...t.snappy,
202
- delay: o * .03
202
+ delay: a * .03
203
203
  },
204
204
  onClick: () => {
205
205
  n.onSelect(), R(!1);
206
206
  },
207
- onMouseEnter: () => H(o),
207
+ onMouseEnter: () => H(a),
208
208
  className: r("flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard", s ? "bg-surface-raised-hover text-surface-fg" : "text-surface-fg-muted hover:bg-surface-raised"),
209
209
  children: [
210
210
  n.icon && /* @__PURE__ */ h("span", {
@@ -212,7 +212,7 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
212
212
  "aria-hidden": "true",
213
213
  children: /* @__PURE__ */ h(e, {
214
214
  size: "sm",
215
- children: a(n.icon)
215
+ children: o(n.icon)
216
216
  })
217
217
  }),
218
218
  /* @__PURE__ */ g("div", {
@@ -248,7 +248,7 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
248
248
  ]
249
249
  }, n.id);
250
250
  })]
251
- }, o.label))]
251
+ }, a.label))]
252
252
  }),
253
253
  $ !== !1 && /* @__PURE__ */ h(v.div, {
254
254
  initial: Q ?? { opacity: 0 },
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.js","names":[],"sources":["../../src/composed/command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandPalette -- Keyboard-driven command palette (Ctrl+K / Cmd+K).\n *\n * Adapted from Karm V2. Uses ui/Dialog as the overlay.\n * All V1 color tokens replaced with semantic design-system tokens.\n */\nimport { IconArrowDown,IconArrowUp, IconCornerDownLeft, IconSearch } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface CommandItem {\n id: string\n /** Display label — string or ReactNode. When ReactNode, provide `filterValue` for search filtering. */\n label: string | React.ReactNode\n /** Optional description — string or ReactNode. */\n description?: string | React.ReactNode\n icon?: IconInput\n /** Keyboard shortcut hint displayed as keycap badges (e.g., \"G D\", \"Ctrl+N\"). */\n shortcut?: string\n /** Custom render override for the label. Receives the current search query for match highlighting. */\n renderLabel?: (query: string) => React.ReactNode\n /** Plain-text value used for search filtering when `label` is a ReactNode. Falls back to `label` if string. */\n filterValue?: string\n onSelect: () => void\n}\n\nexport interface CommandGroup {\n label: string\n items: CommandItem[]\n}\n\n/** A single keyboard hint shown in the footer. */\nexport interface FooterHint {\n /** Key(s) to display — rendered as text inside `<kbd>` or as an icon. */\n keys: string\n /** Human-readable label for the hint (e.g., \"Navigate\", \"Select\"). */\n label: string\n}\n\n/**\n * A searchable command palette with keyboard navigation (Ctrl+K / Cmd+K).\n * Supports grouped items, custom keybindings, controlled/uncontrolled open state,\n * and custom empty states.\n */\nexport interface CommandPaletteProps extends React.ComponentPropsWithoutRef<'div'> {\n /** Item groups displayed in the palette. Each group has a label and an array of CommandItems. */\n groups?: CommandGroup[]\n /** Placeholder text for the search input. */\n placeholder?: string\n /** Called on every search input change with the current query string. */\n onSearch?: (query: string) => void\n /** Simple text shown when no results match. Overridden by `emptyState` if provided. */\n emptyMessage?: string\n /** Full custom empty state ReactNode — overrides `emptyMessage` when provided. */\n emptyState?: React.ReactNode\n // -- Controlled/uncontrolled open state (P1 #4) --\n /** Controlled open state. */\n open?: boolean\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n // -- Keyboard shortcut customization (P1 #6) --\n /** Keybinding(s) to toggle the palette. Pass `false` to disable.\n * String format: modifier+key, e.g., 'mod+k', 'ctrl+shift+p'.\n * 'mod' maps to Meta on macOS, Ctrl otherwise. */\n keybinding?: string | string[] | false\n // -- Configurable max-height (P2 #8) --\n /** Max height of the results container. CSS value. Default '320px'. */\n maxHeight?: string | number\n // -- Custom footer hints (P2 #11) --\n /** Custom footer keyboard hints. Pass `false` to hide the footer entirely. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\n\n/** Get the text-searchable value from a CommandItem. */\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\n/** Get the text-searchable description from a CommandItem. */\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n/** Parse a shortcut string like \"G D\" or \"Ctrl+N\" into individual keycap segments. */\nfunction parseShortcutKeys(shortcut: string): string[] {\n // If it has \"+\" separator (Ctrl+Shift+N style), split on +\n if (shortcut.includes('+')) {\n return shortcut.split('+').map(s => s.trim()).filter(Boolean)\n }\n // Otherwise split on spaces (G D style)\n return shortcut.split(/\\s+/).filter(Boolean)\n}\n\n// -----------------------------------------------------------------------\n// CommandPalette\n// -----------------------------------------------------------------------\n\nconst CommandPalette = React.forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n groups = [],\n placeholder = 'Search or jump to...',\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+k',\n maxHeight = '320px',\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n // Use a ref for the current open value to avoid stale closures in setOpen\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved = typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(0)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-palette-listbox-${instanceId}`\n\n // -- Reduced motion (P2 #12) --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection (P2 #13) --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // Filter groups based on query\n const filteredGroups = React.useMemo(() => {\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Global keyboard shortcut\n React.useEffect(() => {\n if (keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [keybinding, setOpen])\n\n // Reset state when opening\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActiveIndex(0)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [open])\n\n // Keyboard navigation inside the palette\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n break\n }\n case 'Enter': {\n e.preventDefault()\n const item = filteredItems[activeIndex]\n if (item) {\n item.onSelect()\n setOpen(false)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n break\n }\n }\n }\n\n // Scroll active item into view\n React.useEffect(() => {\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(0)\n onSearch?.(value)\n }\n\n // Build a map of item id -> flat index for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Resolve motion transitions --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // -- Resolve max height CSS value --\n const maxHeightValue = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Resolve footer hints --\n const resolvedFooterHints: FooterHint[] | false =\n footerHints === false\n ? false\n : footerHints ?? [\n { keys: '↑↓', label: 'Navigate' },\n { keys: '↵', label: 'Select' },\n { keys: 'Esc', label: 'Close' },\n ]\n\n // Handle dialog open change (from Dialog's own close mechanisms)\n const handleDialogOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n setOpen(nextOpen)\n },\n [setOpen],\n )\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay\n className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\"\n />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n onKeyDown={handleKeyDown}\n >\n <VisuallyHidden>\n <DialogTitle>Command Palette</DialogTitle>\n <DialogDescription>\n Search or jump to pages, projects, tasks, and actions\n </DialogDescription>\n </VisuallyHidden>\n\n {/* Search input */}\n <div className=\"flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <motion.span\n initial={noInit ?? { opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springSnappy}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconSearch} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls={listboxId}\n aria-activedescendant={filteredItems[activeIndex] ? `command-item-${instanceId}-${filteredItems[activeIndex].id}` : undefined}\n aria-autocomplete=\"list\"\n className={cn(\n 'flex-1 bg-transparent text-body-lg text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n <kbd className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\">\n Esc\n </kbd>\n </div>\n\n {/* Results */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={isReduced ? noMotionTransition : { ...tweens.fade, delay: groupIdx * 0.06 }}\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={isReduced ? noMotionTransition : { ...springs.snappy, delay: itemIndex * 0.03 }}\n onClick={() => {\n item.onSelect()\n setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive ? 'text-accent-11' : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-body-md\">\n {item.renderLabel ? item.renderLabel(query) : item.label}\n </span>\n {item.description && (\n <span className=\"line-clamp-1 text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && (\n <span className=\"flex shrink-0 items-center gap-ds-01\">\n {parseShortcutKeys(item.shortcut).map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-body-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-accent-2 text-accent-11 border-accent-6'\n : 'bg-surface-raised text-surface-fg-subtle border-surface-border-strong',\n )}\n >\n {key === 'Ctrl' || key === 'ctrl' ? getModifierDisplay(isMac) : key}\n </kbd>\n ))}\n </span>\n )}\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconCornerDownLeft} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n\n {/* Footer with keyboard hints */}\n {resolvedFooterHints !== false && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {resolvedFooterHints.map((hint, i) => (\n <div key={i} className=\"flex items-center gap-ds-02b\">\n {hint.keys === '↑↓' ? (\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n ) : hint.keys === '↵' ? (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n ) : (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n {hint.keys}\n </kbd>\n )}\n <span className=\"text-caption text-surface-fg-subtle\">\n {hint.label}\n </span>\n </div>\n ))}\n </motion.div>\n )}\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandPalette.displayName = 'CommandPalette'\n\nexport { CommandPalette }\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-palette.js","names":[],"sources":["../../src/composed/command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandPalette -- Keyboard-driven command palette (Ctrl+K / Cmd+K).\n *\n * Adapted from Karm V2. Uses ui/Dialog as the overlay.\n * All V1 color tokens replaced with semantic design-system tokens.\n */\nimport { IconArrowDown,IconArrowUp, IconCornerDownLeft, IconSearch } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface CommandItem {\n id: string\n /** Display label — string or ReactNode. When ReactNode, provide `filterValue` for search filtering. */\n label: string | React.ReactNode\n /** Optional description — string or ReactNode. */\n description?: string | React.ReactNode\n icon?: IconInput\n /** Keyboard shortcut hint displayed as keycap badges (e.g., \"G D\", \"Ctrl+N\"). */\n shortcut?: string\n /** Custom render override for the label. Receives the current search query for match highlighting. */\n renderLabel?: (query: string) => React.ReactNode\n /** Plain-text value used for search filtering when `label` is a ReactNode. Falls back to `label` if string. */\n filterValue?: string\n onSelect: () => void\n}\n\nexport interface CommandGroup {\n label: string\n items: CommandItem[]\n}\n\n/** A single keyboard hint shown in the footer. */\nexport interface FooterHint {\n /** Key(s) to display — rendered as text inside `<kbd>` or as an icon. */\n keys: string\n /** Human-readable label for the hint (e.g., \"Navigate\", \"Select\"). */\n label: string\n}\n\n/**\n * A searchable command palette with keyboard navigation (Ctrl+K / Cmd+K).\n * Supports grouped items, custom keybindings, controlled/uncontrolled open state,\n * and custom empty states.\n */\nexport interface CommandPaletteProps extends React.ComponentPropsWithoutRef<'div'> {\n /** Item groups displayed in the palette. Each group has a label and an array of CommandItems. */\n groups?: CommandGroup[]\n /** Placeholder text for the search input. */\n placeholder?: string\n /** Called on every search input change with the current query string. */\n onSearch?: (query: string) => void\n /** Simple text shown when no results match. Overridden by `emptyState` if provided. */\n emptyMessage?: string\n /** Full custom empty state ReactNode — overrides `emptyMessage` when provided. */\n emptyState?: React.ReactNode\n // -- Controlled/uncontrolled open state (P1 #4) --\n /** Controlled open state. */\n open?: boolean\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n // -- Keyboard shortcut customization (P1 #6) --\n /** Keybinding(s) to toggle the palette. Pass `false` to disable.\n * String format: modifier+key, e.g., 'mod+k', 'ctrl+shift+p'.\n * 'mod' maps to Meta on macOS, Ctrl otherwise. */\n keybinding?: string | string[] | false\n // -- Configurable max-height (P2 #8) --\n /** Max height of the results container. CSS value. Default '320px'. */\n maxHeight?: string | number\n // -- Custom footer hints (P2 #11) --\n /** Custom footer keyboard hints. Pass `false` to hide the footer entirely. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\n\n/** Get the text-searchable value from a CommandItem. */\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\n/** Get the text-searchable description from a CommandItem. */\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n/** Parse a shortcut string like \"G D\" or \"Ctrl+N\" into individual keycap segments. */\nfunction parseShortcutKeys(shortcut: string): string[] {\n // If it has \"+\" separator (Ctrl+Shift+N style), split on +\n if (shortcut.includes('+')) {\n return shortcut.split('+').map(s => s.trim()).filter(Boolean)\n }\n // Otherwise split on spaces (G D style)\n return shortcut.split(/\\s+/).filter(Boolean)\n}\n\n// -----------------------------------------------------------------------\n// CommandPalette\n// -----------------------------------------------------------------------\n\nconst CommandPalette = React.forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n groups = [],\n placeholder = 'Search or jump to...',\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+k',\n maxHeight = '320px',\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n // Use a ref for the current open value to avoid stale closures in setOpen\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved = typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(0)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-palette-listbox-${instanceId}`\n\n // -- Reduced motion (P2 #12) --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection (P2 #13) --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // Filter groups based on query\n const filteredGroups = React.useMemo(() => {\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Global keyboard shortcut\n React.useEffect(() => {\n if (keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [keybinding, setOpen])\n\n // Reset state when opening\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActiveIndex(0)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [open])\n\n // Keyboard navigation inside the palette\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n break\n }\n case 'Enter': {\n e.preventDefault()\n const item = filteredItems[activeIndex]\n if (item) {\n item.onSelect()\n setOpen(false)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n break\n }\n }\n }\n\n // Scroll active item into view\n React.useEffect(() => {\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(0)\n onSearch?.(value)\n }\n\n // Build a map of item id -> flat index for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Resolve motion transitions --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // -- Resolve max height CSS value --\n const maxHeightValue = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Resolve footer hints --\n const resolvedFooterHints: FooterHint[] | false =\n footerHints === false\n ? false\n : footerHints ?? [\n { keys: '↑↓', label: 'Navigate' },\n { keys: '↵', label: 'Select' },\n { keys: 'Esc', label: 'Close' },\n ]\n\n // Handle dialog open change (from Dialog's own close mechanisms)\n const handleDialogOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n setOpen(nextOpen)\n },\n [setOpen],\n )\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay\n className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\"\n />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n onKeyDown={handleKeyDown}\n >\n <VisuallyHidden>\n <DialogTitle>Command Palette</DialogTitle>\n <DialogDescription>\n Search or jump to pages, projects, tasks, and actions\n </DialogDescription>\n </VisuallyHidden>\n\n {/* Search input */}\n <div className=\"flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <motion.span\n initial={noInit ?? { opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springSnappy}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconSearch} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls={listboxId}\n aria-activedescendant={filteredItems[activeIndex] ? `command-item-${instanceId}-${filteredItems[activeIndex].id}` : undefined}\n aria-autocomplete=\"list\"\n className={cn(\n 'flex-1 bg-transparent text-body-lg text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n <kbd className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\">\n Esc\n </kbd>\n </div>\n\n {/* Results */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={isReduced ? noMotionTransition : { ...tweens.fade, delay: groupIdx * 0.06 }}\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={isReduced ? noMotionTransition : { ...springs.snappy, delay: itemIndex * 0.03 }}\n onClick={() => {\n item.onSelect()\n setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive ? 'text-accent-11' : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-body-md\">\n {item.renderLabel ? item.renderLabel(query) : item.label}\n </span>\n {item.description && (\n <span className=\"line-clamp-1 text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && (\n <span className=\"flex shrink-0 items-center gap-ds-01\">\n {parseShortcutKeys(item.shortcut).map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-body-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-accent-2 text-accent-11 border-accent-6'\n : 'bg-surface-raised text-surface-fg-subtle border-surface-border-strong',\n )}\n >\n {key === 'Ctrl' || key === 'ctrl' ? getModifierDisplay(isMac) : key}\n </kbd>\n ))}\n </span>\n )}\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconCornerDownLeft} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n\n {/* Footer with keyboard hints */}\n {resolvedFooterHints !== false && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {resolvedFooterHints.map((hint, i) => (\n <div key={i} className=\"flex items-center gap-ds-02b\">\n {hint.keys === '↑↓' ? (\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n ) : hint.keys === '↵' ? (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n ) : (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n {hint.keys}\n </kbd>\n )}\n <span className=\"text-caption text-surface-fg-subtle\">\n {hint.label}\n </span>\n </div>\n ))}\n </motion.div>\n )}\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandPalette.displayName = 'CommandPalette'\n\nexport { CommandPalette }\n"],"mappings":";;;;;;;;;;;;;;;AAyGA,SAAS,GAAe,GAA2B;CAGjD,OAFI,EAAK,cAAoB,EAAK,cAC9B,OAAO,EAAK,SAAU,WAAiB,EAAK,QACzC;AACT;AAGA,SAAS,GAAqB,GAA2B;CAEvD,OADI,OAAO,EAAK,eAAgB,WAAiB,EAAK,cAC/C;AACT;AAGA,SAAS,EAAkB,GAA4B;CAMrD,OAJI,EAAS,SAAS,GAAG,IAChB,EAAS,MAAM,GAAG,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,IAGvD,EAAS,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;AAC7C;AAMA,IAAM,IAAiB,EAAM,WAC3B,SACE,EACE,YAAS,CAAC,GACV,iBAAc,wBACd,cACA,kBAAe,qBACf,eACA,MAAM,GACN,gBACA,iBACA,gBAAa,SACb,eAAY,SACZ,gBACA,cACA,GAAG,KAEL,GACA;CAEF,IAAM,IAAe,MAAa,KAAA,GAC5B,CAAC,GAAc,KAAmB,EAAM,SAAS,KAAe,EAAK,GACrE,IAAO,IAAe,IAAW,GAGjC,IAAU,EAAM,OAAO,CAAI;CACjC,EAAQ,UAAU;CAElB,IAAM,IAAU,EAAM,aACnB,MAAqD;EACpD,IAAM,IAAW,OAAO,KAAa,aAAa,EAAS,EAAQ,OAAO,IAAI;EAI9E,AAHK,KACH,EAAgB,CAAQ,GAE1B,IAAe,CAAQ;CACzB,GACA,CAAC,GAAc,CAAY,CAC7B,GAEM,CAAC,GAAO,KAAY,EAAM,SAAS,EAAE,GACrC,CAAC,GAAa,KAAkB,EAAM,SAAS,CAAC,GAChD,IAAW,EAAM,OAAyB,IAAI,GAC9C,IAAU,EAAM,OAAuB,IAAI,GAC3C,IAAa,EAAM,MAAM,GACzB,IAAY,2BAA2B,KAGvC,EAAE,eAAe,MAAc,EAAU,GACzC,IAAqB,EAAE,UAAU,EAAE,GAGnC,KAAQ,EAAM,cAAc,EAAS,GAAG,CAAC,CAAC,GAG1C,IAAiB,EAAM,cAAc;EACzC,IAAI,CAAC,EAAM,KAAK,GAAG,OAAO;EAC1B,IAAM,IAAI,EAAM,YAAY;EAC5B,OAAO,EACJ,KAAK,OAAW;GACf,GAAG;GACH,OAAO,EAAM,MAAM,QAChB,MACC,GAAe,CAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,KAC7C,GAAqB,CAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,CACvD;EACF,EAAE,CAAC,CACF,QAAQ,MAAU,EAAM,MAAM,SAAS,CAAC;CAC7C,GAAG,CAAC,GAAQ,CAAK,CAAC,GAEZ,IAAgB,EAAM,cACpB,EAAe,SAAS,MAAM,EAAE,KAAK,GAC3C,CAAC,CAAc,CACjB;CAsBA,AAnBA,EAAM,gBAAgB;EACpB,IAAI,MAAe,IAAO;EAE1B,IAAM,IAAW,MAAM,QAAQ,CAAU,IAAI,IAAa,CAAC,CAAU;EAErE,SAAS,EAAc,GAAkB;GACvC,KAAK,IAAM,KAAW,GACpB,IAAI,EAAkB,GAAG,CAAO,GAAG;IAEjC,AADA,EAAE,eAAe,GACjB,GAAS,MAAS,CAAC,CAAI;IACvB;GACF;EAEJ;EAEA,OADA,SAAS,iBAAiB,WAAW,CAAa,SACrC,SAAS,oBAAoB,WAAW,CAAa;CACpE,GAAG,CAAC,GAAY,CAAO,CAAC,GAGxB,EAAM,gBAAgB;EACpB,AAAI,MACF,EAAS,EAAE,GACX,EAAe,CAAC,GAChB,4BAA4B;GAC1B,EAAS,SAAS,MAAM;EAC1B,CAAC;CAEL,GAAG,CAAC,CAAI,CAAC;CAGT,IAAM,MAAiB,MAA2B;EAChD,QAAQ,EAAE,KAAV;GACE,KAAK;IAEH,AADA,EAAE,eAAe,GACjB,GAAgB,MACd,IAAO,EAAc,SAAS,IAAI,IAAO,IAAI,CAC/C;IACA;GAEF,KAAK;IAEH,AADA,EAAE,eAAe,GACjB,GAAgB,MACd,IAAO,IAAI,IAAO,IAAI,EAAc,SAAS,CAC/C;IACA;GAEF,KAAK,SAAS;IACZ,EAAE,eAAe;IACjB,IAAM,IAAO,EAAc;IAC3B,AAAI,MACF,EAAK,SAAS,GACd,EAAQ,EAAK;IAEf;GACF;GACA,KAAK;IAEH,AADA,EAAE,eAAe,GACjB,EAAQ,EAAK;IACb;EAEJ;CACF;CAGA,EAAM,gBAAgB;EAIpB,CAHiB,EAAQ,SAAS,cAChC,wBAAwB,EAAY,GACtC,EAAA,EACU,eAAe,EAAE,OAAO,UAAU,CAAC;CAC/C,GAAG,CAAC,CAAW,CAAC;CAEhB,IAAM,MAAqB,MAAkB;EAG3C,AAFA,EAAS,CAAK,GACd,EAAe,CAAC,GAChB,KAAW,CAAK;CAClB,GAGM,KAAe,EAAM,cAAc;EACvC,IAAM,oBAAM,IAAI,IAAoB,GAChC,IAAM;EACV,KAAK,IAAM,KAAS,GAClB,KAAK,IAAM,KAAQ,EAAM,OACvB,EAAI,IAAI,EAAK,IAAI,GAAK;EAG1B,OAAO;CACT,GAAG,CAAC,CAAc,CAAC,GAGb,KAAe,IAAY,IAAqB,EAAQ,QACxD,IAAY,IAAY,IAAqB,EAAO,MACpD,IAAS,IAAY;EAAE,SAAS;EAAG,OAAO;EAAG,GAAG;CAAE,IAAI,KAAA,GAGtD,KAAiB,OAAO,KAAc,WAAW,GAAG,EAAU,MAAM,GAGpE,IACJ,MAAgB,KACZ,KACA,KAAe;EACb;GAAE,MAAM;GAAM,OAAO;EAAW;EAChC;GAAE,MAAM;GAAK,OAAO;EAAS;EAC7B;GAAE,MAAM;GAAO,OAAO;EAAQ;CAChC;CAUN,OACE,kBAAC,GAAD;EAAc;EAAM,cARS,EAAM,aAClC,MAAsB;GACrB,EAAQ,CAAQ;EAClB,GACA,CAAC,CAAO,CAI0B;YAChC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EACE,WAAU,6JACX,CAAA,GACD,kBAAC,GAAD;GACO;GACL,GAAI;GACJ,WAAW,EACT,0EACA,wEACA,qFACA,8DACA,gEACA,sFACA,gFACA,CACF;GACA,WAAW;aAbb;IAeE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAa,kBAA4B,CAAA,GACzC,kBAAC,GAAD,EAAA,UAAmB,wDAEA,CAAA,CACL,EAAA,CAAA;IAGhB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,EAAO,MAAR;OACE,SAAS,KAAU;QAAE,SAAS;QAAG,OAAO;OAAK;OAC7C,SAAS;QAAE,SAAS;QAAG,OAAO;OAAE;OAChC,YAAY;OACZ,WAAU;iBAEV,kBAAC,GAAD;QAAM,MAAM;QAAY,MAAK;QAAK,QAAO;QAAQ,WAAU;OAA0B,CAAA;MAC1E,CAAA;MACb,kBAAC,SAAD;OACE,KAAK;OACL,OAAO;OACP,WAAW,MAAM,GAAkB,EAAE,OAAO,KAAK;OACpC;OACb,MAAK;OACL,iBAAe;OACf,iBAAe;OACf,yBAAuB,EAAc,KAAe,gBAAgB,EAAW,GAAG,EAAc,EAAY,CAAC,OAAO,KAAA;OACpH,qBAAkB;OAClB,WAAW,EACT,qEACA,oCACF;OACA,cAAa;OACb,aAAY;OACZ,YAAY;MACb,CAAA;MACD,kBAAC,OAAD;OAAK,WAAU;iBAAuL;MAEjM,CAAA;KACF;;IAGL,kBAAC,OAAD;KACE,KAAK;KACL,IAAI;KACJ,MAAK;KACL,cAAW;KACX,WAAU;KACV,OAAO,EAAE,WAAW,GAAe;eANrC,CAQG,EAAe,WAAW,KACzB,kBAAC,EAAO,KAAR;MACE,SAAS,KAAU,EAAE,SAAS,EAAE;MAChC,SAAS,EAAE,SAAS,EAAE;MACtB,YAAY;MACZ,WAAU;gBAET,KACC,kBAAC,KAAD;OAAG,WAAU;iBACV;MACA,CAAA;KAEK,CAAA,GAGb,EAAe,KAAK,GAAO,MAC1B,kBAAC,EAAO,KAAR;MAEE,SAAS,KAAU,EAAE,SAAS,EAAE;MAChC,SAAS,EAAE,SAAS,EAAE;MACtB,YAAY,IAAY,IAAqB;OAAE,GAAG,EAAO;OAAM,OAAO,IAAW;MAAK;MACtF,WAAU;gBALZ,CAOE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAM;OACH,CAAA;MACH,CAAA,GAEJ,EAAM,MAAM,KAAK,MAAS;OACzB,IAAM,IAAY,GAAa,IAAI,EAAK,EAAE,KAAK,GACzC,IAAW,MAAc;OAC/B,OACE,kBAAC,EAAO,QAAR;QAEE,IAAI,gBAAgB,EAAW,GAAG,EAAK;QACvC,MAAK;QACL,MAAK;QACL,iBAAe;QACf,sBAAoB;QACpB,SAAS,KAAU;SAAE,SAAS;SAAG,GAAG;QAAE;QACtC,SAAS;SAAE,SAAS;SAAG,GAAG;QAAE;QAC5B,YAAY,IAAY,IAAqB;SAAE,GAAG,EAAQ;SAAQ,OAAO,IAAY;QAAK;QAC1F,eAAe;SAEb,AADA,EAAK,SAAS,GACd,EAAQ,EAAK;QACf;QACA,oBAAoB,EAAe,CAAS;QAC5C,WAAW,EACT,gKACA,IACI,4CACA,+CACN;kBApBF;SAsBG,EAAK,QACJ,kBAAC,QAAD;UACE,WAAW,EACT,0GACA,IAAW,mBAAmB,wBAChC;UACA,eAAY;oBAEZ,kBAAC,GAAD;WAAc,MAAK;qBAAM,EAAc,EAAK,IAAI;UAAgB,CAAA;SAC5D,CAAA;SAER,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAK,cAAc,EAAK,YAAY,CAAK,IAAI,EAAK;UAC/C,CAAA,GACL,EAAK,eACJ,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAK;UACF,CAAA,CAEL;;SACJ,EAAK,YACJ,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAkB,EAAK,QAAQ,CAAC,CAAC,KAAK,GAAK,MAC1C,kBAAC,OAAD;WAEE,WAAW,EACT,0LACA,IACI,+CACA,uEACN;qBAEC,MAAQ,UAAU,MAAQ,SAAS,EAAmB,EAAK,IAAI;UAC7D,GATE,CASF,CACN;SACG,CAAA;SAER,kBAAC,IAAD,EAAA,UACG,KACC,kBAAC,EAAO,MAAR;UACE,SAAS,IAAY,KAAA,IAAY,EAAE,SAAS,EAAE;UAC9C,SAAS,EAAE,SAAS,EAAE;UACtB,MAAM,IAAY,KAAA,IAAY,EAAE,SAAS,EAAE;UAC3C,YAAY;UACZ,WAAU;oBAEV,kBAAC,GAAD;WAAM,MAAM;WAAoB,MAAK;WAAK,QAAO;WAAQ,WAAU;UAA0B,CAAA;SAClF,CAAA,EAEA,CAAA;QACJ;UAxER,EAAK,EAwEG;MAEnB,CAAC,CACS;QA5FL,EAAM,KA4FD,CACb,CACE;;IAGJ,MAAwB,MACvB,kBAAC,EAAO,KAAR;KACE,SAAS,KAAU,EAAE,SAAS,EAAE;KAChC,SAAS,EAAE,SAAS,EAAE;KACtB,YAAY;KACZ,WAAU;eAET,EAAoB,KAAK,GAAM,MAC9B,kBAAC,OAAD;MAAa,WAAU;gBAAvB,CACG,EAAK,SAAS,OACb,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD;SAAM,MAAM;SAAa,MAAK;SAAK,WAAU;QAA0B,CAAA;OACpE,CAAA,GACL,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD;SAAM,MAAM;SAAe,MAAK;SAAK,WAAU;QAA0B,CAAA;OACtE,CAAA,CACF;WACH,EAAK,SAAS,MAChB,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAM,MAAM;QAAoB,MAAK;QAAK,WAAU;OAA0B,CAAA;MAC3E,CAAA,IAEL,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAK;MACH,CAAA,GAEP,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAK;MACF,CAAA,CACH;QAtBK,CAsBL,CACN;IACS,CAAA;GAEE;IACN,EAAA,CAAA;CACR,CAAA;AAEV,CACF;AAEA,EAAe,cAAc"}
@@ -1,13 +1,22 @@
1
1
  "use client";
2
- import { VariantProps } from 'class-variance-authority';
3
2
  import * as React from 'react';
4
3
  export type Priority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' | 'low' | 'medium' | 'high' | 'urgent';
5
- declare const priorityVariants: (props?: ({
6
- display?: "compact" | "full" | null | undefined;
7
- } & import('class-variance-authority/types').ClassProp) | undefined) => string;
8
- export interface PriorityIndicatorProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>, VariantProps<typeof priorityVariants> {
4
+ export interface PriorityIndicatorProps extends React.HTMLAttributes<HTMLElement> {
9
5
  priority: Priority;
6
+ /** Render an icon-only chip (no visible text). Set an accessible name is handled automatically. */
7
+ iconOnly?: boolean;
8
+ /**
9
+ * @deprecated Use `iconOnly`. `'compact'` → icon-only, `'full'` → labeled.
10
+ * Accepted for back-compat; maps to `iconOnly`.
11
+ */
12
+ display?: 'compact' | 'full';
13
+ /** Override the label text (i18n / custom copy). Defaults to the priority name. */
14
+ children?: React.ReactNode;
10
15
  }
11
- declare const PriorityIndicator: React.ForwardRefExoticComponent<PriorityIndicatorProps & React.RefAttributes<HTMLDivElement>>;
16
+ /**
17
+ * Presentational priority chip — composes `Badge` so radius, color semantics,
18
+ * a11y labeling, and reduced-motion handling come from one place.
19
+ */
20
+ declare const PriorityIndicator: React.ForwardRefExoticComponent<PriorityIndicatorProps & React.RefAttributes<HTMLElement>>;
12
21
  export { PriorityIndicator };
13
22
  //# sourceMappingURL=priority-indicator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"priority-indicator.d.ts","sourceRoot":"","sources":["../../src/composed/priority-indicator.tsx"],"names":[],"mappings":"AASA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAgClG,QAAA,MAAM,gBAAgB;;8EAarB,CAAA;AAED,MAAM,WAAW,sBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,EAC5D,YAAY,CAAC,OAAO,gBAAgB,CAAC;IACvC,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED,QAAA,MAAM,iBAAiB,+FAwEtB,CAAA;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
1
+ {"version":3,"file":"priority-indicator.d.ts","sourceRoot":"","sources":["../../src/composed/priority-indicator.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,MAAM,QAAQ,GAChB,KAAK,GACL,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,KAAK,GACL,QAAQ,GACR,MAAM,GACN,QAAQ,CAAA;AAiBZ,MAAM,WAAW,sBAAuB,SAAQ,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC;IAC/E,QAAQ,EAAE,QAAQ,CAAA;IAClB,mGAAmG;IACnG,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B;AAED;;;GAGG;AACH,QAAA,MAAM,iBAAiB,4FAqCtB,CAAA;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAA"}