@devalok/shilp-sutra 0.56.0 → 0.57.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.
- package/MIGRATION.md +107 -0
- package/dist/_chunks/badge-group.js +48 -34
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/chat.js +91 -75
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/document-preview.js +1 -1
- package/dist/_chunks/document-preview.js.map +1 -1
- package/dist/_chunks/emoji-suggestion.js +1 -1
- package/dist/_chunks/emoji-suggestion.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js +2 -2
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/oauth-button.js +1 -1
- package/dist/_chunks/oauth-button.js.map +1 -1
- package/dist/_chunks/success.js +2 -2
- package/dist/_chunks/success.js.map +1 -1
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/_chunks/use-calendar.js +4 -4
- package/dist/_chunks/use-calendar.js.map +1 -1
- package/dist/ai/blocks/text.js +1 -1
- package/dist/ai/blocks/text.js.map +1 -1
- package/dist/ai/command-bar.js +9 -9
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js +2 -2
- package/dist/ai/conversation.js.map +1 -1
- package/dist/composed/activity-feed.js +1 -1
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/avatar-group.d.ts +7 -2
- package/dist/composed/avatar-group.d.ts.map +1 -1
- package/dist/composed/avatar-group.js +3 -3
- package/dist/composed/avatar-group.js.map +1 -1
- package/dist/composed/command-palette.js +7 -7
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.js +2 -2
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/date-picker/index.js +4 -4
- package/dist/composed/date-picker/index.js.map +1 -1
- package/dist/composed/diff.d.ts +23 -2
- package/dist/composed/diff.d.ts.map +1 -1
- package/dist/composed/diff.js +341 -260
- package/dist/composed/diff.js.map +1 -1
- package/dist/composed/emoji-picker.js +3 -3
- package/dist/composed/emoji-picker.js.map +1 -1
- package/dist/composed/error-boundary.js +2 -2
- package/dist/composed/error-boundary.js.map +1 -1
- package/dist/composed/file-preview.js +1 -1
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.js +1 -1
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/inline-edit.js +1 -1
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/composed/loading-skeleton.js +3 -3
- package/dist/composed/loading-skeleton.js.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/member-picker.js +1 -1
- package/dist/composed/member-picker.js.map +1 -1
- package/dist/composed/multi-select-popover.js +1 -1
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/page-skeletons.js +4 -4
- package/dist/composed/page-skeletons.js.map +1 -1
- package/dist/composed/responsive-modal.js +1 -1
- package/dist/composed/responsive-modal.js.map +1 -1
- package/dist/composed/rich-chat-input.js +17 -17
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.js +5 -5
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/schedule-view.js +5 -5
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +4 -3
- package/dist/hooks/use-container-size.d.ts +18 -0
- package/dist/hooks/use-container-size.d.ts.map +1 -0
- package/dist/hooks/use-container-size.js +28 -0
- package/dist/hooks/use-container-size.js.map +1 -0
- package/dist/shell/app-shell.d.ts +101 -0
- package/dist/shell/app-shell.d.ts.map +1 -0
- package/dist/shell/app-shell.js +76 -0
- package/dist/shell/app-shell.js.map +1 -0
- package/dist/shell/bottom-navbar.js +2 -2
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/index.d.ts +1 -0
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +6 -5
- package/dist/shell/notification-center.js +4 -4
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/notification-preferences.js +1 -1
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/shell/top-bar.js +7 -7
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/generate-scale.d.ts +49 -0
- package/dist/tokens/generate-scale.d.ts.map +1 -1
- package/dist/tokens/primitives.css +29 -26
- package/dist/tokens/semantic.css +98 -39
- package/dist/tokens/variants.css +1 -1
- package/dist/ui/accordion.js +1 -1
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +7 -7
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/avatar.js +3 -3
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-indicator.js +1 -1
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/badge.d.ts +47 -33
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/banner.js +1 -1
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/button.js +4 -4
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.js +4 -4
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/chat/date-separator.d.ts +8 -1
- package/dist/ui/chat/date-separator.d.ts.map +1 -1
- package/dist/ui/checkbox.js +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/code.js +2 -2
- package/dist/ui/code.js.map +1 -1
- package/dist/ui/color-input.js +3 -3
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/combobox.js +4 -4
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/context-menu.js +4 -4
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-body.d.ts +3 -1
- package/dist/ui/data-table-body.d.ts.map +1 -1
- package/dist/ui/data-table-body.js +93 -92
- package/dist/ui/data-table-body.js.map +1 -1
- package/dist/ui/data-table-bulk-actions.d.ts +7 -1
- package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
- package/dist/ui/data-table-bulk-actions.js +14 -8
- package/dist/ui/data-table-bulk-actions.js.map +1 -1
- package/dist/ui/data-table-card.d.ts.map +1 -1
- package/dist/ui/data-table-card.js +66 -47
- package/dist/ui/data-table-card.js.map +1 -1
- package/dist/ui/data-table-context.d.ts +4 -0
- package/dist/ui/data-table-context.d.ts.map +1 -1
- package/dist/ui/data-table-context.js.map +1 -1
- package/dist/ui/data-table-header.d.ts.map +1 -1
- package/dist/ui/data-table-header.js +18 -15
- package/dist/ui/data-table-header.js.map +1 -1
- package/dist/ui/data-table-pagination.js +3 -3
- package/dist/ui/data-table-pagination.js.map +1 -1
- package/dist/ui/data-table-toolbar.d.ts +11 -1
- package/dist/ui/data-table-toolbar.d.ts.map +1 -1
- package/dist/ui/data-table-toolbar.js +7 -7
- package/dist/ui/data-table-toolbar.js.map +1 -1
- package/dist/ui/data-table.d.ts +52 -5
- package/dist/ui/data-table.d.ts.map +1 -1
- package/dist/ui/data-table.js +181 -169
- package/dist/ui/data-table.js.map +1 -1
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dot.js +1 -1
- package/dist/ui/dot.js.map +1 -1
- package/dist/ui/dropdown-menu.js +4 -4
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/file-upload.js +3 -3
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/input-otp.js +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/input.js +8 -8
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/menubar.js +5 -5
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.js +1 -1
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/number-input.js +3 -3
- package/dist/ui/number-input.js.map +1 -1
- package/dist/ui/pagination.js +1 -1
- package/dist/ui/pagination.js.map +1 -1
- package/dist/ui/progress-ring.js +2 -2
- package/dist/ui/progress-ring.js.map +1 -1
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +16 -12
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/radio.js +1 -1
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/select.js +5 -5
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sheet.js +1 -1
- package/dist/ui/sheet.js.map +1 -1
- package/dist/ui/sidebar.js +12 -12
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/slider.js +1 -1
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/split-button.js +3 -3
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stat-card.js +1 -1
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stepper.js +2 -2
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/surface.d.ts.map +1 -1
- package/dist/ui/surface.js +2 -2
- package/dist/ui/surface.js.map +1 -1
- package/dist/ui/switch.js +1 -1
- package/dist/ui/switch.js.map +1 -1
- package/dist/ui/table.js +1 -1
- package/dist/ui/table.js.map +1 -1
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +1 -1
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/textarea.js +5 -5
- package/dist/ui/textarea.js.map +1 -1
- package/dist/ui/toast.js +1 -1
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/toggle.js +3 -3
- package/dist/ui/toggle.js.map +1 -1
- package/docs/components/composed/avatar-group.md +4 -4
- package/docs/components/composed/diff.md +10 -2
- package/docs/components/composed/schedule-view.md +1 -1
- package/docs/components/shell/app-shell.md +132 -0
- package/docs/components/ui/avatar.md +1 -1
- package/docs/components/ui/button.md +1 -1
- package/docs/components/ui/chat.md +7 -1
- package/docs/components/ui/color-swatch.md +1 -1
- package/docs/components/ui/data-table-toolbar.md +6 -2
- package/docs/components/ui/data-table.md +41 -7
- package/docs/components/ui/dot.md +1 -1
- package/docs/components/ui/progress.md +1 -0
- package/docs/components/ui/surface.md +3 -3
- package/docs/components/ui/table.md +2 -2
- package/docs/recipes/install-astro.md +1 -0
- package/docs/recipes/install-next-app-router.md +1 -0
- package/docs/recipes/install-remix.md +1 -0
- package/docs/recipes/install-tanstack-start.md +1 -0
- package/docs/recipes/install-vite.md +1 -0
- package/llms.txt +2 -1
- package/make-kit/Guidelines.md +2 -2
- package/make-kit/components/button.md +1 -1
- package/make-kit/components/card.md +6 -6
- package/make-kit/components/surface.md +4 -4
- package/make-kit/foundations/color.md +4 -4
- package/make-kit/foundations/dark-mode.md +1 -1
- package/make-kit/foundations/radius.md +1 -1
- package/make-kit/foundations/surfaces.md +9 -9
- package/mcp-manifest.json +350 -32
- package/package.json +6 -3
- package/skill/SKILL.md +12 -6
- package/skill/references/components.md +2 -1
- package/skill/references/setup-astro.md +1 -0
- package/skill/references/setup-next-app-router.md +1 -0
- package/skill/references/setup-remix.md +1 -0
- package/skill/references/setup-tanstack-start.md +1 -0
- package/skill/references/setup-vite.md +1 -0
- package/dist/primitives/react-toast.d.ts +0 -120
- package/dist/ui/charts/_internal/scales.d.ts +0 -5
- package/dist/ui/charts/_internal/scales.d.ts.map +0 -1
- package/dist/ui/lib/slot.d.ts +0 -8
- package/dist/ui/lib/slot.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-view.js","names":[],"sources":["../../src/ui/tree-view/use-tree.ts","../../src/ui/tree-view/tree-view.tsx","../../src/ui/tree-view/tree-item.tsx"],"sourcesContent":["import { useCallback,useState } from 'react'\n\nimport type { IconInput } from '../lib/icon-input'\n\nexport interface TreeNode {\n id: string\n label: string\n icon?: IconInput\n children?: TreeNode[]\n disabled?: boolean\n}\n\ninterface UseTreeOptions {\n defaultExpanded?: string[]\n defaultSelected?: string[]\n multiSelect?: boolean\n onSelect?: (selectedIds: string[]) => void\n onExpand?: (expandedIds: string[]) => void\n}\n\nexport function useTree(options: UseTreeOptions = {}) {\n const { defaultExpanded, defaultSelected, multiSelect, onSelect, onExpand } = options\n\n const [expanded, setExpanded] = useState<Set<string>>(\n new Set(defaultExpanded ?? []),\n )\n const [selected, setSelected] = useState<Set<string>>(\n new Set(defaultSelected ?? []),\n )\n\n const toggle = useCallback(\n (id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n onExpand?.(Array.from(next))\n return next\n })\n },\n [onExpand],\n )\n\n const select = useCallback(\n (id: string, event?: React.MouseEvent) => {\n setSelected((prev) => {\n let next: Set<string>\n if (multiSelect && event?.ctrlKey) {\n next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n } else {\n next = new Set([id])\n }\n onSelect?.(Array.from(next))\n return next\n })\n },\n [multiSelect, onSelect],\n )\n\n return {\n expanded,\n selected,\n toggle,\n select,\n isExpanded: (id: string) => expanded.has(id),\n isSelected: (id: string) => selected.has(id),\n expandAll: (ids: string[]) => setExpanded(new Set(ids)),\n collapseAll: () => setExpanded(new Set()),\n }\n}\n","'use client'\n\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\nimport { TreeItem } from './tree-item'\nimport { type TreeNode,useTree } from './use-tree'\n\n// ─── Context ────────────────────────────────────────────────────────\ninterface TreeContextValue {\n tree: ReturnType<typeof useTree>\n checkboxes: boolean\n}\n\nconst TreeContext = React.createContext<TreeContextValue | null>(null)\n\nexport function useTreeContext() {\n const ctx = React.useContext(TreeContext)\n if (!ctx) {\n throw new Error('TreeItem must be used within a <TreeView>')\n }\n return ctx\n}\n\n// ─── Props ──────────────────────────────────────────────────────────\nexport interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onSelect'> {\n /** Data-driven mode: pass items array */\n items?: TreeNode[]\n /** Initially expanded node IDs */\n defaultExpanded?: string[]\n /** Initially selected node IDs */\n defaultSelected?: string[]\n /** Enable multi-select */\n multiSelect?: boolean\n /** Show checkboxes before each item */\n checkboxes?: boolean\n /** Called when selection changes */\n onSelect?: (ids: string[]) => void\n /** Called when expansion changes */\n onExpand?: (ids: string[]) => void\n className?: string\n /** Declarative mode: render TreeItem children directly */\n children?: React.ReactNode\n}\n\n// ─── Render nodes recursively (data-driven mode) ───────────────────\nfunction renderNodes(nodes: TreeNode[], depth: number = 0): React.ReactNode {\n return nodes.map((node) => (\n <TreeItem\n key={node.id}\n itemId={node.id}\n label={node.label}\n icon={node.icon}\n disabled={node.disabled}\n depth={depth}\n >\n {node.children && node.children.length > 0\n ? renderNodes(node.children, depth + 1)\n : undefined}\n </TreeItem>\n ))\n}\n\n// ─── Helper: collect all visible item IDs ───────────────────────────\nfunction getVisibleItemElements(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>('[data-tree-item]'),\n ).filter((el) => {\n // Items inside collapsed groups should not be focusable\n let parent = el.parentElement\n while (parent && parent !== container) {\n if (parent.getAttribute('role') === 'group') {\n const grid = parent.parentElement\n if (grid && grid.classList.contains('grid-rows-[0fr]')) {\n return false\n }\n }\n parent = parent.parentElement\n }\n return true\n })\n}\n\n// ─── Component ──────────────────────────────────────────────────────\nconst TreeView = React.forwardRef<HTMLUListElement, TreeViewProps>(\n (\n {\n items,\n defaultExpanded,\n defaultSelected,\n multiSelect = false,\n checkboxes = false,\n onSelect,\n onExpand,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const tree = useTree({\n defaultExpanded,\n defaultSelected,\n multiSelect,\n onSelect,\n onExpand,\n })\n\n const innerRef = React.useRef<HTMLUListElement>(null)\n const containerRef = (ref as React.RefObject<HTMLUListElement>) ?? innerRef\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => {\n const container = containerRef.current\n if (!container) return\n\n const visibleItems = getVisibleItemElements(container)\n const currentIndex = visibleItems.findIndex(\n (el) => el === document.activeElement,\n )\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = visibleItems[currentIndex + 1]\n next?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = visibleItems[currentIndex - 1]\n prev?.focus()\n break\n }\n case 'ArrowRight': {\n // Handled in TreeItem for expand; if already expanded, move to first child\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n if (itemId && tree.isExpanded(itemId)) {\n e.preventDefault()\n const nextItem = visibleItems[currentIndex + 1]\n nextItem?.focus()\n }\n }\n break\n }\n case 'ArrowLeft': {\n // Handled in TreeItem for collapse; if already collapsed or leaf, move to parent\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n const treeItem = current.closest('[role=\"treeitem\"]')\n const parentGroup = treeItem?.parentElement?.closest(\n '[role=\"treeitem\"]',\n )\n if (itemId && !tree.isExpanded(itemId) && parentGroup) {\n e.preventDefault()\n const parentRow = parentGroup.querySelector<HTMLElement>(\n '[data-tree-item]',\n )\n parentRow?.focus()\n }\n }\n break\n }\n case 'Home': {\n e.preventDefault()\n visibleItems[0]?.focus()\n break\n }\n case 'End': {\n e.preventDefault()\n visibleItems[visibleItems.length - 1]?.focus()\n break\n }\n }\n }\n\n const ctxValue = React.useMemo<TreeContextValue>(\n () => ({ tree, checkboxes }),\n [tree, checkboxes],\n )\n\n const content = items ? renderNodes(items) : children\n\n return (\n <TreeContext.Provider value={ctxValue}>\n <ul\n ref={containerRef}\n role=\"tree\"\n aria-multiselectable={multiSelect || undefined}\n onKeyDown={handleKeyDown}\n className={cn('m-0 list-none p-0', className)}\n {...props}\n >\n {content}\n </ul>\n </TreeContext.Provider>\n )\n },\n)\nTreeView.displayName = 'TreeView'\n\nexport { TreeView }\n","'use client'\n\nimport { IconChevronRight } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Checkbox } from '../checkbox'\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\nimport { useTreeContext } from './tree-view'\n\nexport interface TreeItemProps {\n /** Unique identifier for this tree item */\n itemId: string\n /** Primary label content */\n label: React.ReactNode\n /** Optional icon rendered before the label. Accepts any `IconInput`. */\n icon?: IconInput\n /** Secondary label rendered after the primary label */\n secondaryLabel?: React.ReactNode\n /** Action buttons rendered at the end of the row */\n actions?: React.ReactNode\n /** Whether this item is disabled */\n disabled?: boolean\n /** Nested tree items */\n children?: React.ReactNode\n /** Depth level (used internally) */\n depth?: number\n /** Additional CSS class names */\n className?: string\n}\n\nconst TreeItem = React.forwardRef<HTMLLIElement, TreeItemProps>(\n (\n {\n itemId,\n label,\n icon,\n secondaryLabel,\n actions,\n disabled = false,\n children,\n depth = 0,\n className,\n },\n ref,\n ) => {\n const ctx = useTreeContext()\n const hasChildren = React.Children.count(children) > 0\n const isExpanded = ctx.tree.isExpanded(itemId)\n const isSelected = ctx.tree.isSelected(itemId)\n\n const handleRowClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n ctx.tree.select(itemId, e)\n }\n\n const handleChevronClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n if (disabled) return\n ctx.tree.toggle(itemId)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n ctx.tree.select(itemId)\n }\n if (e.key === 'ArrowRight' && hasChildren && !isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n if (e.key === 'ArrowLeft' && hasChildren && isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n }\n\n // Compute indeterminate state for checkbox mode\n const checkboxState = React.useMemo(() => {\n if (!ctx.checkboxes || !hasChildren) {\n return { checked: isSelected, indeterminate: false }\n }\n // Collect all descendant IDs\n const descendants: string[] = []\n const collectIds = (nodes: React.ReactNode) => {\n React.Children.forEach(nodes, (child) => {\n if (React.isValidElement<TreeItemProps>(child) && child.props.itemId) {\n descendants.push(child.props.itemId)\n if (child.props.children) {\n collectIds(child.props.children)\n }\n }\n })\n }\n collectIds(children)\n const selectedCount = descendants.filter((id) =>\n ctx.tree.isSelected(id),\n ).length\n if (selectedCount === 0 && !isSelected) {\n return { checked: false, indeterminate: false }\n }\n if (selectedCount === descendants.length) {\n return { checked: true, indeterminate: false }\n }\n return { checked: false, indeterminate: true }\n }, [ctx.checkboxes, hasChildren, children, isSelected, ctx.tree])\n\n return (\n <li\n ref={ref}\n role=\"treeitem\"\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={isSelected}\n aria-level={depth + 1}\n aria-disabled={disabled || undefined}\n className=\"list-none\"\n >\n {/* Row */}\n <div\n role=\"presentation\"\n data-tree-item={itemId}\n tabIndex={disabled ? -1 : 0}\n onClick={handleRowClick}\n onKeyDown={handleKeyDown}\n style={{ paddingLeft: `calc(${depth} * var(--spacing-ds-05b) + var(--spacing-ds-03))` }}\n className={cn(\n 'flex items-center gap-ds-02 py-ds-02 px-ds-02 rounded-control cursor-pointer transition-colors duration-fast-01',\n 'hover:bg-surface-raised',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n isSelected &&\n 'bg-accent-3 text-accent-11',\n disabled && 'opacity-action-disabled cursor-not-allowed pointer-events-none',\n className,\n )}\n >\n {/* Expand chevron */}\n {hasChildren ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onClick={handleChevronClick}\n className=\"flex shrink-0 items-center justify-center p-0 border-0 bg-transparent cursor-pointer\"\n >\n <Icon\n icon={IconChevronRight}\n size=\"sm\"\n className={cn(\n 'transition-transform duration-moderate-02',\n isExpanded && 'rotate-90',\n )}\n />\n </button>\n ) : (\n <span className=\"inline-block w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n\n {/* Checkbox (optional) */}\n {ctx.checkboxes && (\n <Checkbox\n checked={checkboxState.checked}\n indeterminate={checkboxState.indeterminate}\n disabled={disabled}\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n onCheckedChange={() => {\n if (!disabled) ctx.tree.select(itemId)\n }}\n className=\"shrink-0\"\n />\n )}\n\n {/* Icon */}\n {icon && (\n <span className=\"flex shrink-0 items-center text-surface-fg-subtle\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n )}\n\n {/* Label */}\n <span className=\"min-w-0 truncate text-body-sm\">{label}</span>\n\n {/* Secondary label */}\n {secondaryLabel && (\n <span className=\"ml-auto truncate text-caption text-surface-fg-muted\">\n {secondaryLabel}\n </span>\n )}\n\n {/* Actions */}\n {actions && (\n <span\n className=\"ml-auto flex shrink-0 items-center gap-ds-01\"\n onClick={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n {actions}\n </span>\n )}\n </div>\n\n {/* Children (collapsible) */}\n {hasChildren && (\n <div\n role=\"group\"\n className={cn(\n 'grid transition-[grid-template-rows] duration-moderate-02 ease-productive-standard',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <ul role=\"group\" className=\"overflow-hidden m-0 p-0\">\n {React.Children.map(children, (child) => {\n if (React.isValidElement<TreeItemProps>(child)) {\n return React.cloneElement(child, {\n depth: depth + 1,\n })\n }\n return child\n })}\n </ul>\n </div>\n )}\n </li>\n )\n },\n)\nTreeItem.displayName = 'TreeItem'\n\nexport { TreeItem }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree-view.js","names":[],"sources":["../../src/ui/tree-view/use-tree.ts","../../src/ui/tree-view/tree-view.tsx","../../src/ui/tree-view/tree-item.tsx"],"sourcesContent":["import { useCallback,useState } from 'react'\n\nimport type { IconInput } from '../lib/icon-input'\n\nexport interface TreeNode {\n id: string\n label: string\n icon?: IconInput\n children?: TreeNode[]\n disabled?: boolean\n}\n\ninterface UseTreeOptions {\n defaultExpanded?: string[]\n defaultSelected?: string[]\n multiSelect?: boolean\n onSelect?: (selectedIds: string[]) => void\n onExpand?: (expandedIds: string[]) => void\n}\n\nexport function useTree(options: UseTreeOptions = {}) {\n const { defaultExpanded, defaultSelected, multiSelect, onSelect, onExpand } = options\n\n const [expanded, setExpanded] = useState<Set<string>>(\n new Set(defaultExpanded ?? []),\n )\n const [selected, setSelected] = useState<Set<string>>(\n new Set(defaultSelected ?? []),\n )\n\n const toggle = useCallback(\n (id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n onExpand?.(Array.from(next))\n return next\n })\n },\n [onExpand],\n )\n\n const select = useCallback(\n (id: string, event?: React.MouseEvent) => {\n setSelected((prev) => {\n let next: Set<string>\n if (multiSelect && event?.ctrlKey) {\n next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n } else {\n next = new Set([id])\n }\n onSelect?.(Array.from(next))\n return next\n })\n },\n [multiSelect, onSelect],\n )\n\n return {\n expanded,\n selected,\n toggle,\n select,\n isExpanded: (id: string) => expanded.has(id),\n isSelected: (id: string) => selected.has(id),\n expandAll: (ids: string[]) => setExpanded(new Set(ids)),\n collapseAll: () => setExpanded(new Set()),\n }\n}\n","'use client'\n\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\nimport { TreeItem } from './tree-item'\nimport { type TreeNode,useTree } from './use-tree'\n\n// ─── Context ────────────────────────────────────────────────────────\ninterface TreeContextValue {\n tree: ReturnType<typeof useTree>\n checkboxes: boolean\n}\n\nconst TreeContext = React.createContext<TreeContextValue | null>(null)\n\nexport function useTreeContext() {\n const ctx = React.useContext(TreeContext)\n if (!ctx) {\n throw new Error('TreeItem must be used within a <TreeView>')\n }\n return ctx\n}\n\n// ─── Props ──────────────────────────────────────────────────────────\nexport interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onSelect'> {\n /** Data-driven mode: pass items array */\n items?: TreeNode[]\n /** Initially expanded node IDs */\n defaultExpanded?: string[]\n /** Initially selected node IDs */\n defaultSelected?: string[]\n /** Enable multi-select */\n multiSelect?: boolean\n /** Show checkboxes before each item */\n checkboxes?: boolean\n /** Called when selection changes */\n onSelect?: (ids: string[]) => void\n /** Called when expansion changes */\n onExpand?: (ids: string[]) => void\n className?: string\n /** Declarative mode: render TreeItem children directly */\n children?: React.ReactNode\n}\n\n// ─── Render nodes recursively (data-driven mode) ───────────────────\nfunction renderNodes(nodes: TreeNode[], depth: number = 0): React.ReactNode {\n return nodes.map((node) => (\n <TreeItem\n key={node.id}\n itemId={node.id}\n label={node.label}\n icon={node.icon}\n disabled={node.disabled}\n depth={depth}\n >\n {node.children && node.children.length > 0\n ? renderNodes(node.children, depth + 1)\n : undefined}\n </TreeItem>\n ))\n}\n\n// ─── Helper: collect all visible item IDs ───────────────────────────\nfunction getVisibleItemElements(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>('[data-tree-item]'),\n ).filter((el) => {\n // Items inside collapsed groups should not be focusable\n let parent = el.parentElement\n while (parent && parent !== container) {\n if (parent.getAttribute('role') === 'group') {\n const grid = parent.parentElement\n if (grid && grid.classList.contains('grid-rows-[0fr]')) {\n return false\n }\n }\n parent = parent.parentElement\n }\n return true\n })\n}\n\n// ─── Component ──────────────────────────────────────────────────────\nconst TreeView = React.forwardRef<HTMLUListElement, TreeViewProps>(\n (\n {\n items,\n defaultExpanded,\n defaultSelected,\n multiSelect = false,\n checkboxes = false,\n onSelect,\n onExpand,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const tree = useTree({\n defaultExpanded,\n defaultSelected,\n multiSelect,\n onSelect,\n onExpand,\n })\n\n const innerRef = React.useRef<HTMLUListElement>(null)\n const containerRef = (ref as React.RefObject<HTMLUListElement>) ?? innerRef\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => {\n const container = containerRef.current\n if (!container) return\n\n const visibleItems = getVisibleItemElements(container)\n const currentIndex = visibleItems.findIndex(\n (el) => el === document.activeElement,\n )\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = visibleItems[currentIndex + 1]\n next?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = visibleItems[currentIndex - 1]\n prev?.focus()\n break\n }\n case 'ArrowRight': {\n // Handled in TreeItem for expand; if already expanded, move to first child\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n if (itemId && tree.isExpanded(itemId)) {\n e.preventDefault()\n const nextItem = visibleItems[currentIndex + 1]\n nextItem?.focus()\n }\n }\n break\n }\n case 'ArrowLeft': {\n // Handled in TreeItem for collapse; if already collapsed or leaf, move to parent\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n const treeItem = current.closest('[role=\"treeitem\"]')\n const parentGroup = treeItem?.parentElement?.closest(\n '[role=\"treeitem\"]',\n )\n if (itemId && !tree.isExpanded(itemId) && parentGroup) {\n e.preventDefault()\n const parentRow = parentGroup.querySelector<HTMLElement>(\n '[data-tree-item]',\n )\n parentRow?.focus()\n }\n }\n break\n }\n case 'Home': {\n e.preventDefault()\n visibleItems[0]?.focus()\n break\n }\n case 'End': {\n e.preventDefault()\n visibleItems[visibleItems.length - 1]?.focus()\n break\n }\n }\n }\n\n const ctxValue = React.useMemo<TreeContextValue>(\n () => ({ tree, checkboxes }),\n [tree, checkboxes],\n )\n\n const content = items ? renderNodes(items) : children\n\n return (\n <TreeContext.Provider value={ctxValue}>\n <ul\n ref={containerRef}\n role=\"tree\"\n aria-multiselectable={multiSelect || undefined}\n onKeyDown={handleKeyDown}\n className={cn('m-0 list-none p-0', className)}\n {...props}\n >\n {content}\n </ul>\n </TreeContext.Provider>\n )\n },\n)\nTreeView.displayName = 'TreeView'\n\nexport { TreeView }\n","'use client'\n\nimport { IconChevronRight } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Checkbox } from '../checkbox'\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\nimport { useTreeContext } from './tree-view'\n\nexport interface TreeItemProps {\n /** Unique identifier for this tree item */\n itemId: string\n /** Primary label content */\n label: React.ReactNode\n /** Optional icon rendered before the label. Accepts any `IconInput`. */\n icon?: IconInput\n /** Secondary label rendered after the primary label */\n secondaryLabel?: React.ReactNode\n /** Action buttons rendered at the end of the row */\n actions?: React.ReactNode\n /** Whether this item is disabled */\n disabled?: boolean\n /** Nested tree items */\n children?: React.ReactNode\n /** Depth level (used internally) */\n depth?: number\n /** Additional CSS class names */\n className?: string\n}\n\nconst TreeItem = React.forwardRef<HTMLLIElement, TreeItemProps>(\n (\n {\n itemId,\n label,\n icon,\n secondaryLabel,\n actions,\n disabled = false,\n children,\n depth = 0,\n className,\n },\n ref,\n ) => {\n const ctx = useTreeContext()\n const hasChildren = React.Children.count(children) > 0\n const isExpanded = ctx.tree.isExpanded(itemId)\n const isSelected = ctx.tree.isSelected(itemId)\n\n const handleRowClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n ctx.tree.select(itemId, e)\n }\n\n const handleChevronClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n if (disabled) return\n ctx.tree.toggle(itemId)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n ctx.tree.select(itemId)\n }\n if (e.key === 'ArrowRight' && hasChildren && !isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n if (e.key === 'ArrowLeft' && hasChildren && isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n }\n\n // Compute indeterminate state for checkbox mode\n const checkboxState = React.useMemo(() => {\n if (!ctx.checkboxes || !hasChildren) {\n return { checked: isSelected, indeterminate: false }\n }\n // Collect all descendant IDs\n const descendants: string[] = []\n const collectIds = (nodes: React.ReactNode) => {\n React.Children.forEach(nodes, (child) => {\n if (React.isValidElement<TreeItemProps>(child) && child.props.itemId) {\n descendants.push(child.props.itemId)\n if (child.props.children) {\n collectIds(child.props.children)\n }\n }\n })\n }\n collectIds(children)\n const selectedCount = descendants.filter((id) =>\n ctx.tree.isSelected(id),\n ).length\n if (selectedCount === 0 && !isSelected) {\n return { checked: false, indeterminate: false }\n }\n if (selectedCount === descendants.length) {\n return { checked: true, indeterminate: false }\n }\n return { checked: false, indeterminate: true }\n }, [ctx.checkboxes, hasChildren, children, isSelected, ctx.tree])\n\n return (\n <li\n ref={ref}\n role=\"treeitem\"\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={isSelected}\n aria-level={depth + 1}\n aria-disabled={disabled || undefined}\n className=\"list-none\"\n >\n {/* Row */}\n <div\n role=\"presentation\"\n data-tree-item={itemId}\n tabIndex={disabled ? -1 : 0}\n onClick={handleRowClick}\n onKeyDown={handleKeyDown}\n style={{ paddingLeft: `calc(${depth} * var(--spacing-ds-05b) + var(--spacing-ds-03))` }}\n className={cn(\n 'flex items-center gap-ds-02 py-ds-02 px-ds-02 rounded-control cursor-pointer transition-colors duration-fast-01',\n 'hover:bg-surface-panel-hover',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n isSelected &&\n 'bg-accent-3 text-accent-11',\n disabled && 'opacity-action-disabled cursor-not-allowed pointer-events-none',\n className,\n )}\n >\n {/* Expand chevron */}\n {hasChildren ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onClick={handleChevronClick}\n className=\"flex shrink-0 items-center justify-center p-0 border-0 bg-transparent cursor-pointer\"\n >\n <Icon\n icon={IconChevronRight}\n size=\"sm\"\n className={cn(\n 'transition-transform duration-moderate-02',\n isExpanded && 'rotate-90',\n )}\n />\n </button>\n ) : (\n <span className=\"inline-block w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n\n {/* Checkbox (optional) */}\n {ctx.checkboxes && (\n <Checkbox\n checked={checkboxState.checked}\n indeterminate={checkboxState.indeterminate}\n disabled={disabled}\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n onCheckedChange={() => {\n if (!disabled) ctx.tree.select(itemId)\n }}\n className=\"shrink-0\"\n />\n )}\n\n {/* Icon */}\n {icon && (\n <span className=\"flex shrink-0 items-center text-surface-fg-subtle\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n )}\n\n {/* Label */}\n <span className=\"min-w-0 truncate text-body-sm\">{label}</span>\n\n {/* Secondary label */}\n {secondaryLabel && (\n <span className=\"ml-auto truncate text-caption text-surface-fg-muted\">\n {secondaryLabel}\n </span>\n )}\n\n {/* Actions */}\n {actions && (\n <span\n className=\"ml-auto flex shrink-0 items-center gap-ds-01\"\n onClick={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n {actions}\n </span>\n )}\n </div>\n\n {/* Children (collapsible) */}\n {hasChildren && (\n <div\n role=\"group\"\n className={cn(\n 'grid transition-[grid-template-rows] duration-moderate-02 ease-productive-standard',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <ul role=\"group\" className=\"overflow-hidden m-0 p-0\">\n {React.Children.map(children, (child) => {\n if (React.isValidElement<TreeItemProps>(child)) {\n return React.cloneElement(child, {\n depth: depth + 1,\n })\n }\n return child\n })}\n </ul>\n </div>\n )}\n </li>\n )\n },\n)\nTreeItem.displayName = 'TreeItem'\n\nexport { TreeItem }\n"],"mappings":"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"}
|
|
@@ -77,7 +77,7 @@ var T = [
|
|
|
77
77
|
F ? /* @__PURE__ */ i("span", { className: "h-ds-xs-plus w-ds-xs-plus" }) : /* @__PURE__ */ i("button", {
|
|
78
78
|
type: "button",
|
|
79
79
|
onClick: () => A(w(r, 1)),
|
|
80
|
-
className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-
|
|
80
|
+
className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
|
|
81
81
|
"aria-label": "Previous month",
|
|
82
82
|
children: /* @__PURE__ */ i(t, {
|
|
83
83
|
icon: o,
|
|
@@ -88,14 +88,14 @@ var T = [
|
|
|
88
88
|
/* @__PURE__ */ i("button", {
|
|
89
89
|
type: "button",
|
|
90
90
|
onClick: j,
|
|
91
|
-
className: e("text-body-md font-semibold text-surface-fg", j && "cursor-pointer rounded-control px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-
|
|
91
|
+
className: e("text-body-md font-semibold text-surface-fg", j && "cursor-pointer rounded-control px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover"),
|
|
92
92
|
"aria-label": "Switch to month/year view",
|
|
93
93
|
children: f(r, "MMMM yyyy")
|
|
94
94
|
}),
|
|
95
95
|
I ? /* @__PURE__ */ i("span", { className: "h-ds-xs-plus w-ds-xs-plus" }) : /* @__PURE__ */ i("button", {
|
|
96
96
|
type: "button",
|
|
97
97
|
onClick: () => A(l(r, 1)),
|
|
98
|
-
className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-
|
|
98
|
+
className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
|
|
99
99
|
"aria-label": "Next month",
|
|
100
100
|
children: /* @__PURE__ */ i(t, {
|
|
101
101
|
icon: s,
|
|
@@ -131,7 +131,7 @@ var T = [
|
|
|
131
131
|
"aria-label": f(t, "EEEE, MMMM d, yyyy"),
|
|
132
132
|
"aria-selected": c || u || void 0,
|
|
133
133
|
"aria-disabled": !o || s || void 0,
|
|
134
|
-
className: e("relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-control text-body-md font-body transition-colors duration-fast-01 ease-productive-standard", !o && "pointer-events-none opacity-0", o && s && "opacity-action-disabled pointer-events-none cursor-not-allowed", o && !s && !c && !u && !l && "text-surface-fg hover:bg-surface-
|
|
134
|
+
className: e("relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-control text-body-md font-body transition-colors duration-fast-01 ease-productive-standard", !o && "pointer-events-none opacity-0", o && s && "opacity-action-disabled pointer-events-none cursor-not-allowed", o && !s && !c && !u && !l && "text-surface-fg hover:bg-surface-panel-hover", l && !u && "rounded-none bg-surface-panel-hover text-surface-fg", (c || u) && "bg-accent-9 text-accent-fg hover:bg-accent-10", d && !c && !u && !s && "font-semibold text-accent-11"),
|
|
135
135
|
children: [f(t, "d"), m.length > 0 && /* @__PURE__ */ i("span", {
|
|
136
136
|
className: "flex gap-px justify-center absolute bottom-[2px] left-0 right-0",
|
|
137
137
|
children: m.slice(0, 3).map((e, t) => /* @__PURE__ */ i("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-calendar.js","names":[],"sources":["../../src/composed/date-picker/calendar-grid.tsx","../../src/composed/date-picker/use-calendar.ts"],"sourcesContent":["'use client'\n\nimport { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'\nimport {\n addDays,\n addMonths,\n endOfMonth,\n endOfWeek,\n format,\n isAfter,\n isBefore,\n isSameDay,\n isSameMonth,\n isWithinInterval,\n lastDayOfMonth,\n startOfDay,\n startOfMonth,\n startOfWeek,\n subMonths,\n} from 'date-fns'\nimport * as React from 'react'\n\nimport { Icon } from '../../ui/icon'\nimport { cn } from '../../ui/lib/utils'\n\nconst WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n\nexport interface CalendarEvent {\n date: Date\n color?: string\n label?: string\n}\n\nexport interface CalendarGridProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onSelect'> {\n currentMonth: Date\n selected?: Date | null\n rangeStart?: Date | null\n rangeEnd?: Date | null\n hoverDate?: Date | null\n onSelect: (date: Date) => void\n onHover?: (date: Date | null) => void\n onMonthChange: (date: Date) => void\n onHeaderClick?: () => void\n disabledDates?: (date: Date) => boolean\n minDate?: Date\n maxDate?: Date\n /** Hide the previous-month navigation arrow */\n hidePrevNav?: boolean\n /** Hide the next-month navigation arrow */\n hideNextNav?: boolean\n /** Events to display as dot indicators on dates */\n events?: CalendarEvent[]\n}\n\nexport const CalendarGrid = React.forwardRef<HTMLDivElement, CalendarGridProps>(\n function CalendarGrid({\n currentMonth,\n selected,\n rangeStart,\n rangeEnd,\n hoverDate,\n onSelect,\n onHover,\n onMonthChange,\n onHeaderClick,\n disabledDates,\n minDate,\n maxDate,\n hidePrevNav,\n hideNextNav,\n events,\n className,\n ...props\n}, forwardedRef) {\n const gridRef = React.useRef<HTMLDivElement>(null)\n\n const eventsByDate = React.useMemo(() => {\n const map = new Map<string, CalendarEvent[]>()\n if (!events) return map\n for (const evt of events) {\n const key = format(evt.date, 'yyyy-MM-dd')\n const arr = map.get(key) ?? []\n arr.push(evt)\n map.set(key, arr)\n }\n return map\n }, [events])\n\n const monthStart = startOfMonth(currentMonth)\n const monthEnd = endOfMonth(currentMonth)\n const calendarStart = startOfWeek(monthStart)\n const calendarEnd = endOfWeek(monthEnd)\n\n const days: Date[] = []\n let day = calendarStart\n while (day <= calendarEnd) {\n days.push(day)\n day = addDays(day, 1)\n }\n\n const isDateDisabled = (date: Date): boolean => {\n if (disabledDates?.(date)) return true\n if (minDate && isBefore(date, startOfDay(minDate))) return true\n if (maxDate && isAfter(date, startOfDay(maxDate))) return true\n return false\n }\n\n const isInRange = (date: Date) => {\n if (rangeStart && rangeEnd) {\n const start = isBefore(rangeStart, rangeEnd) ? rangeStart : rangeEnd\n const end = isAfter(rangeEnd, rangeStart) ? rangeEnd : rangeStart\n return isWithinInterval(date, { start, end })\n }\n if (rangeStart && hoverDate) {\n const start = isBefore(rangeStart, hoverDate) ? rangeStart : hoverDate\n const end = isAfter(hoverDate, rangeStart) ? hoverDate : rangeStart\n return isWithinInterval(date, { start, end })\n }\n return false\n }\n\n const isRangeEdge = (date: Date) => {\n if (rangeStart && isSameDay(date, rangeStart)) return true\n if (rangeEnd && isSameDay(date, rangeEnd)) return true\n return false\n }\n\n const focusDate = (target: Date) => {\n if (!gridRef.current) return\n const dateStr = format(target, 'yyyy-MM-dd')\n const btn = gridRef.current.querySelector<HTMLButtonElement>(\n `[data-date=\"${dateStr}\"]`,\n )\n if (btn) {\n btn.focus()\n } else {\n // Date is in a different month — navigate there and focus after render\n onMonthChange(startOfMonth(target))\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement\n const dateStr = target.getAttribute('data-date')\n if (!dateStr) return\n\n const current = new Date(dateStr + 'T00:00:00')\n let next: Date | null = null\n\n switch (e.key) {\n case 'ArrowLeft':\n next = addDays(current, -1)\n break\n case 'ArrowRight':\n next = addDays(current, 1)\n break\n case 'ArrowUp':\n next = addDays(current, -7)\n break\n case 'ArrowDown':\n next = addDays(current, 7)\n break\n case 'Home':\n next = startOfMonth(current)\n break\n case 'End':\n next = lastDayOfMonth(current)\n break\n case 'Enter':\n case ' ': {\n e.preventDefault()\n if (!isDateDisabled(current) && isSameMonth(current, currentMonth)) {\n onSelect(current)\n }\n return\n }\n default:\n return\n }\n\n if (next) {\n e.preventDefault()\n focusDate(next)\n }\n }\n\n return (\n <div ref={forwardedRef} {...props} className={cn(\"w-[252px]\", className)}>\n <div className=\"flex items-center justify-between px-ds-02 pb-ds-04\">\n {hidePrevNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(subMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard 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=\"Previous month\"\n >\n <Icon icon={IconChevronLeft} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onHeaderClick}\n className={cn(\n 'text-body-md font-semibold text-surface-fg',\n onHeaderClick &&\n 'cursor-pointer rounded-control px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover',\n )}\n aria-label=\"Switch to month/year view\"\n >\n {format(currentMonth, 'MMMM yyyy')}\n </button>\n {hideNextNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(addMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard 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=\"Next month\"\n >\n <Icon icon={IconChevronRight} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n </div>\n\n <div\n ref={gridRef}\n className=\"grid grid-cols-7 gap-0\"\n role=\"grid\"\n tabIndex={0}\n aria-label=\"Calendar\"\n onKeyDown={handleKeyDown}\n >\n {WEEKDAYS.map((wd) => (\n <div\n key={wd}\n role=\"columnheader\"\n className=\"flex h-ds-sm items-center justify-center text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\"\n >\n {wd}\n </div>\n ))}\n\n {days.map((d, i) => {\n const inMonth = isSameMonth(d, currentMonth)\n const disabled = isDateDisabled(d)\n const isSelected = selected && isSameDay(d, selected)\n const inRange = isInRange(d)\n const edge = isRangeEdge(d)\n const isToday = isSameDay(d, new Date())\n const dateKey = format(d, 'yyyy-MM-dd')\n const dayEvents = eventsByDate.get(dateKey) ?? []\n\n return (\n <button\n key={i}\n type=\"button\"\n role=\"gridcell\"\n data-date={dateKey}\n tabIndex={inMonth && !disabled ? 0 : -1}\n disabled={!inMonth || disabled}\n onClick={() => {\n if (inMonth && !disabled) onSelect(d)\n }}\n onMouseEnter={() => onHover?.(d)}\n onMouseLeave={() => onHover?.(null)}\n aria-label={format(d, 'EEEE, MMMM d, yyyy')}\n aria-selected={isSelected || edge || undefined}\n aria-disabled={!inMonth || disabled || undefined}\n className={cn(\n 'relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-control text-body-md font-body transition-colors duration-fast-01 ease-productive-standard',\n !inMonth && 'pointer-events-none opacity-0',\n inMonth && disabled && 'opacity-action-disabled pointer-events-none cursor-not-allowed',\n inMonth && !disabled && !isSelected && !edge && !inRange &&\n 'text-surface-fg hover:bg-surface-raised-hover',\n inRange && !edge &&\n 'rounded-none bg-surface-raised-hover text-surface-fg',\n (isSelected || edge) &&\n 'bg-accent-9 text-accent-fg hover:bg-accent-10',\n isToday && !isSelected && !edge && !disabled &&\n 'font-semibold text-accent-11',\n )}\n >\n {format(d, 'd')}\n {dayEvents.length > 0 && (\n <span className=\"flex gap-px justify-center absolute bottom-[2px] left-0 right-0\">\n {dayEvents.slice(0, 3).map((evt, idx) => (\n <span\n key={idx}\n data-event-dot\n className=\"h-ds-02 w-ds-02 rounded-pill\"\n style={{ backgroundColor: evt.color ?? 'var(--color-accent-9)' }}\n />\n ))}\n </span>\n )}\n </button>\n )\n })}\n </div>\n </div>\n )\n},\n)\n\nCalendarGrid.displayName = 'CalendarGrid'\n","'use client'\n\nimport { addMonths, setMonth, setYear,subMonths } from 'date-fns'\nimport { useState } from 'react'\n\nexport function useCalendar(initialMonth?: Date) {\n const [currentMonth, setCurrentMonth] = useState(initialMonth ?? new Date())\n\n const goToPreviousMonth = () => setCurrentMonth((prev) => subMonths(prev, 1))\n const goToNextMonth = () => setCurrentMonth((prev) => addMonths(prev, 1))\n const goToMonth = (month: number) =>\n setCurrentMonth((prev) => setMonth(prev, month))\n const goToYear = (year: number) =>\n setCurrentMonth((prev) => setYear(prev, year))\n\n return {\n currentMonth,\n setCurrentMonth,\n goToPreviousMonth,\n goToNextMonth,\n goToMonth,\n goToYear,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-calendar.js","names":[],"sources":["../../src/composed/date-picker/calendar-grid.tsx","../../src/composed/date-picker/use-calendar.ts"],"sourcesContent":["'use client'\n\nimport { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'\nimport {\n addDays,\n addMonths,\n endOfMonth,\n endOfWeek,\n format,\n isAfter,\n isBefore,\n isSameDay,\n isSameMonth,\n isWithinInterval,\n lastDayOfMonth,\n startOfDay,\n startOfMonth,\n startOfWeek,\n subMonths,\n} from 'date-fns'\nimport * as React from 'react'\n\nimport { Icon } from '../../ui/icon'\nimport { cn } from '../../ui/lib/utils'\n\nconst WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n\nexport interface CalendarEvent {\n date: Date\n color?: string\n label?: string\n}\n\nexport interface CalendarGridProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onSelect'> {\n currentMonth: Date\n selected?: Date | null\n rangeStart?: Date | null\n rangeEnd?: Date | null\n hoverDate?: Date | null\n onSelect: (date: Date) => void\n onHover?: (date: Date | null) => void\n onMonthChange: (date: Date) => void\n onHeaderClick?: () => void\n disabledDates?: (date: Date) => boolean\n minDate?: Date\n maxDate?: Date\n /** Hide the previous-month navigation arrow */\n hidePrevNav?: boolean\n /** Hide the next-month navigation arrow */\n hideNextNav?: boolean\n /** Events to display as dot indicators on dates */\n events?: CalendarEvent[]\n}\n\nexport const CalendarGrid = React.forwardRef<HTMLDivElement, CalendarGridProps>(\n function CalendarGrid({\n currentMonth,\n selected,\n rangeStart,\n rangeEnd,\n hoverDate,\n onSelect,\n onHover,\n onMonthChange,\n onHeaderClick,\n disabledDates,\n minDate,\n maxDate,\n hidePrevNav,\n hideNextNav,\n events,\n className,\n ...props\n}, forwardedRef) {\n const gridRef = React.useRef<HTMLDivElement>(null)\n\n const eventsByDate = React.useMemo(() => {\n const map = new Map<string, CalendarEvent[]>()\n if (!events) return map\n for (const evt of events) {\n const key = format(evt.date, 'yyyy-MM-dd')\n const arr = map.get(key) ?? []\n arr.push(evt)\n map.set(key, arr)\n }\n return map\n }, [events])\n\n const monthStart = startOfMonth(currentMonth)\n const monthEnd = endOfMonth(currentMonth)\n const calendarStart = startOfWeek(monthStart)\n const calendarEnd = endOfWeek(monthEnd)\n\n const days: Date[] = []\n let day = calendarStart\n while (day <= calendarEnd) {\n days.push(day)\n day = addDays(day, 1)\n }\n\n const isDateDisabled = (date: Date): boolean => {\n if (disabledDates?.(date)) return true\n if (minDate && isBefore(date, startOfDay(minDate))) return true\n if (maxDate && isAfter(date, startOfDay(maxDate))) return true\n return false\n }\n\n const isInRange = (date: Date) => {\n if (rangeStart && rangeEnd) {\n const start = isBefore(rangeStart, rangeEnd) ? rangeStart : rangeEnd\n const end = isAfter(rangeEnd, rangeStart) ? rangeEnd : rangeStart\n return isWithinInterval(date, { start, end })\n }\n if (rangeStart && hoverDate) {\n const start = isBefore(rangeStart, hoverDate) ? rangeStart : hoverDate\n const end = isAfter(hoverDate, rangeStart) ? hoverDate : rangeStart\n return isWithinInterval(date, { start, end })\n }\n return false\n }\n\n const isRangeEdge = (date: Date) => {\n if (rangeStart && isSameDay(date, rangeStart)) return true\n if (rangeEnd && isSameDay(date, rangeEnd)) return true\n return false\n }\n\n const focusDate = (target: Date) => {\n if (!gridRef.current) return\n const dateStr = format(target, 'yyyy-MM-dd')\n const btn = gridRef.current.querySelector<HTMLButtonElement>(\n `[data-date=\"${dateStr}\"]`,\n )\n if (btn) {\n btn.focus()\n } else {\n // Date is in a different month — navigate there and focus after render\n onMonthChange(startOfMonth(target))\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement\n const dateStr = target.getAttribute('data-date')\n if (!dateStr) return\n\n const current = new Date(dateStr + 'T00:00:00')\n let next: Date | null = null\n\n switch (e.key) {\n case 'ArrowLeft':\n next = addDays(current, -1)\n break\n case 'ArrowRight':\n next = addDays(current, 1)\n break\n case 'ArrowUp':\n next = addDays(current, -7)\n break\n case 'ArrowDown':\n next = addDays(current, 7)\n break\n case 'Home':\n next = startOfMonth(current)\n break\n case 'End':\n next = lastDayOfMonth(current)\n break\n case 'Enter':\n case ' ': {\n e.preventDefault()\n if (!isDateDisabled(current) && isSameMonth(current, currentMonth)) {\n onSelect(current)\n }\n return\n }\n default:\n return\n }\n\n if (next) {\n e.preventDefault()\n focusDate(next)\n }\n }\n\n return (\n <div ref={forwardedRef} {...props} className={cn(\"w-[252px]\", className)}>\n <div className=\"flex items-center justify-between px-ds-02 pb-ds-04\">\n {hidePrevNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(subMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Previous month\"\n >\n <Icon icon={IconChevronLeft} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onHeaderClick}\n className={cn(\n 'text-body-md font-semibold text-surface-fg',\n onHeaderClick &&\n 'cursor-pointer rounded-control px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover',\n )}\n aria-label=\"Switch to month/year view\"\n >\n {format(currentMonth, 'MMMM yyyy')}\n </button>\n {hideNextNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(addMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Next month\"\n >\n <Icon icon={IconChevronRight} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n </div>\n\n <div\n ref={gridRef}\n className=\"grid grid-cols-7 gap-0\"\n role=\"grid\"\n tabIndex={0}\n aria-label=\"Calendar\"\n onKeyDown={handleKeyDown}\n >\n {WEEKDAYS.map((wd) => (\n <div\n key={wd}\n role=\"columnheader\"\n className=\"flex h-ds-sm items-center justify-center text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\"\n >\n {wd}\n </div>\n ))}\n\n {days.map((d, i) => {\n const inMonth = isSameMonth(d, currentMonth)\n const disabled = isDateDisabled(d)\n const isSelected = selected && isSameDay(d, selected)\n const inRange = isInRange(d)\n const edge = isRangeEdge(d)\n const isToday = isSameDay(d, new Date())\n const dateKey = format(d, 'yyyy-MM-dd')\n const dayEvents = eventsByDate.get(dateKey) ?? []\n\n return (\n <button\n key={i}\n type=\"button\"\n role=\"gridcell\"\n data-date={dateKey}\n tabIndex={inMonth && !disabled ? 0 : -1}\n disabled={!inMonth || disabled}\n onClick={() => {\n if (inMonth && !disabled) onSelect(d)\n }}\n onMouseEnter={() => onHover?.(d)}\n onMouseLeave={() => onHover?.(null)}\n aria-label={format(d, 'EEEE, MMMM d, yyyy')}\n aria-selected={isSelected || edge || undefined}\n aria-disabled={!inMonth || disabled || undefined}\n className={cn(\n 'relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-control text-body-md font-body transition-colors duration-fast-01 ease-productive-standard',\n !inMonth && 'pointer-events-none opacity-0',\n inMonth && disabled && 'opacity-action-disabled pointer-events-none cursor-not-allowed',\n inMonth && !disabled && !isSelected && !edge && !inRange &&\n 'text-surface-fg hover:bg-surface-panel-hover',\n inRange && !edge &&\n 'rounded-none bg-surface-panel-hover text-surface-fg',\n (isSelected || edge) &&\n 'bg-accent-9 text-accent-fg hover:bg-accent-10',\n isToday && !isSelected && !edge && !disabled &&\n 'font-semibold text-accent-11',\n )}\n >\n {format(d, 'd')}\n {dayEvents.length > 0 && (\n <span className=\"flex gap-px justify-center absolute bottom-[2px] left-0 right-0\">\n {dayEvents.slice(0, 3).map((evt, idx) => (\n <span\n key={idx}\n data-event-dot\n className=\"h-ds-02 w-ds-02 rounded-pill\"\n style={{ backgroundColor: evt.color ?? 'var(--color-accent-9)' }}\n />\n ))}\n </span>\n )}\n </button>\n )\n })}\n </div>\n </div>\n )\n},\n)\n\nCalendarGrid.displayName = 'CalendarGrid'\n","'use client'\n\nimport { addMonths, setMonth, setYear,subMonths } from 'date-fns'\nimport { useState } from 'react'\n\nexport function useCalendar(initialMonth?: Date) {\n const [currentMonth, setCurrentMonth] = useState(initialMonth ?? new Date())\n\n const goToPreviousMonth = () => setCurrentMonth((prev) => subMonths(prev, 1))\n const goToNextMonth = () => setCurrentMonth((prev) => addMonths(prev, 1))\n const goToMonth = (month: number) =>\n setCurrentMonth((prev) => setMonth(prev, month))\n const goToYear = (year: number) =>\n setCurrentMonth((prev) => setYear(prev, year))\n\n return {\n currentMonth,\n setCurrentMonth,\n goToPreviousMonth,\n goToNextMonth,\n goToMonth,\n goToYear,\n }\n}\n"],"mappings":"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"}
|
package/dist/ai/blocks/text.js
CHANGED
|
@@ -8,7 +8,7 @@ import i from "remark-gfm";
|
|
|
8
8
|
var a = t.memo(function({ data: t, confidence: a }) {
|
|
9
9
|
return /* @__PURE__ */ n(e, {
|
|
10
10
|
confidence: a,
|
|
11
|
-
className: "prose prose-sm text-surface-fg prose-headings:text-surface-fg prose-a:text-accent-11 prose-a:underline prose-code:text-accent-11 prose-code:bg-surface-
|
|
11
|
+
className: "prose prose-sm text-surface-fg prose-headings:text-surface-fg prose-a:text-accent-11 prose-a:underline prose-code:text-accent-11 prose-code:bg-surface-panel prose-code:rounded prose-code:px-1 prose-strong:text-surface-fg",
|
|
12
12
|
children: /* @__PURE__ */ n(r, {
|
|
13
13
|
remarkPlugins: [i],
|
|
14
14
|
children: t.content
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","names":[],"sources":["../../../src/ai/blocks/text.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nimport type { BlockComponentProps } from '../types'\nimport { BlockShell } from './block-shell'\n\nconst TextBlock = React.memo(function TextBlock({\n data,\n confidence,\n}: BlockComponentProps<{ content: string }>) {\n return (\n <BlockShell\n confidence={confidence}\n className=\"prose prose-sm text-surface-fg prose-headings:text-surface-fg prose-a:text-accent-11 prose-a:underline prose-code:text-accent-11 prose-code:bg-surface-
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../../src/ai/blocks/text.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport Markdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nimport type { BlockComponentProps } from '../types'\nimport { BlockShell } from './block-shell'\n\nconst TextBlock = React.memo(function TextBlock({\n data,\n confidence,\n}: BlockComponentProps<{ content: string }>) {\n return (\n <BlockShell\n confidence={confidence}\n className=\"prose prose-sm text-surface-fg prose-headings:text-surface-fg prose-a:text-accent-11 prose-a:underline prose-code:text-accent-11 prose-code:bg-surface-panel prose-code:rounded prose-code:px-1 prose-strong:text-surface-fg\"\n >\n <Markdown remarkPlugins={[remarkGfm]}>{data.content}</Markdown>\n </BlockShell>\n )\n})\n\nTextBlock.displayName = 'TextBlock'\n\nexport { TextBlock }\n"],"mappings":";;;;;;;AASA,IAAM,IAAY,EAAM,KAAK,SAAmB,EAC9C,SACA,iBAC2C;CAC3C,OACE,kBAAC,GAAD;EACc;EACZ,WAAU;YAEV,kBAAC,GAAD;GAAU,eAAe,CAAC,CAAS;aAAI,EAAK;EAAkB,CAAA;CACpD,CAAA;AAEhB,CAAC;AAED,EAAU,cAAc"}
|
package/dist/ai/command-bar.js
CHANGED
|
@@ -213,7 +213,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
213
213
|
}) : Be ? /* @__PURE__ */ u("button", {
|
|
214
214
|
type: "button",
|
|
215
215
|
onClick: ze,
|
|
216
|
-
className: "shrink-0 rounded-control-inner p-ds-01 text-surface-fg-subtle transition-colors duration-fast-01 hover:bg-surface-
|
|
216
|
+
className: "shrink-0 rounded-control-inner p-ds-01 text-surface-fg-subtle transition-colors duration-fast-01 hover:bg-surface-panel-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
|
|
217
217
|
"aria-label": "Clear",
|
|
218
218
|
title: "Clear",
|
|
219
219
|
children: /* @__PURE__ */ u(i, {
|
|
@@ -226,7 +226,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
226
226
|
animate: { opacity: 1 },
|
|
227
227
|
exit: H ? void 0 : { opacity: 0 },
|
|
228
228
|
transition: J,
|
|
229
|
-
className: "hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-
|
|
229
|
+
className: "hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-panel px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex",
|
|
230
230
|
children: [se(Ne), "J"]
|
|
231
231
|
}) }) : null
|
|
232
232
|
]
|
|
@@ -285,7 +285,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
285
285
|
n.onSelect(), g === "floating" && N(!1);
|
|
286
286
|
},
|
|
287
287
|
onMouseEnter: () => L(a),
|
|
288
|
-
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-
|
|
288
|
+
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-panel-hover text-surface-fg" : "text-surface-fg-muted hover:bg-surface-panel-hover"),
|
|
289
289
|
children: [
|
|
290
290
|
n.icon && /* @__PURE__ */ u("span", {
|
|
291
291
|
className: r("[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard", s ? "text-accent-11" : "text-surface-fg-subtle"),
|
|
@@ -326,7 +326,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
326
326
|
return g === "hero" ? /* @__PURE__ */ d("div", {
|
|
327
327
|
ref: k,
|
|
328
328
|
role: "search",
|
|
329
|
-
className: r("bg-surface-
|
|
329
|
+
className: r("bg-surface-panel rounded-overlay-lg shadow-raised p-ds-07", D),
|
|
330
330
|
...O,
|
|
331
331
|
children: [
|
|
332
332
|
v && /* @__PURE__ */ u("p", {
|
|
@@ -342,7 +342,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
342
342
|
onClick: () => {
|
|
343
343
|
F(e), ye?.(e), B.current?.focus();
|
|
344
344
|
},
|
|
345
|
-
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-
|
|
345
|
+
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-panel-hover hover:text-surface-fg-muted",
|
|
346
346
|
children: e
|
|
347
347
|
}, e))
|
|
348
348
|
}),
|
|
@@ -395,14 +395,14 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
395
395
|
children: [/* @__PURE__ */ d("div", {
|
|
396
396
|
className: "flex items-center gap-ds-01",
|
|
397
397
|
children: [/* @__PURE__ */ u("kbd", {
|
|
398
|
-
className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-
|
|
398
|
+
className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-panel shadow-kbd",
|
|
399
399
|
children: /* @__PURE__ */ u(i, {
|
|
400
400
|
icon: ue,
|
|
401
401
|
size: "xs",
|
|
402
402
|
className: "text-surface-fg-subtle"
|
|
403
403
|
})
|
|
404
404
|
}), /* @__PURE__ */ u("kbd", {
|
|
405
|
-
className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-
|
|
405
|
+
className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-panel shadow-kbd",
|
|
406
406
|
children: /* @__PURE__ */ u(i, {
|
|
407
407
|
icon: le,
|
|
408
408
|
size: "xs",
|
|
@@ -417,7 +417,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
417
417
|
/* @__PURE__ */ d("div", {
|
|
418
418
|
className: "flex items-center gap-ds-02b",
|
|
419
419
|
children: [/* @__PURE__ */ u("kbd", {
|
|
420
|
-
className: "inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-
|
|
420
|
+
className: "inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-panel px-ds-02b shadow-kbd",
|
|
421
421
|
children: /* @__PURE__ */ u(i, {
|
|
422
422
|
icon: de,
|
|
423
423
|
size: "xs",
|
|
@@ -431,7 +431,7 @@ var m = c.forwardRef(function({ onSubmit: l, state: m = "idle", groups: h = [],
|
|
|
431
431
|
/* @__PURE__ */ d("div", {
|
|
432
432
|
className: "flex items-center gap-ds-02b",
|
|
433
433
|
children: [/* @__PURE__ */ u("kbd", {
|
|
434
|
-
className: "inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-
|
|
434
|
+
className: "inline-flex h-[20px] items-center justify-center rounded-control border border-card-strong bg-surface-panel px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd",
|
|
435
435
|
children: "Esc"
|
|
436
436
|
}), /* @__PURE__ */ u("span", {
|
|
437
437
|
className: "text-caption text-surface-fg-subtle",
|
|
@@ -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":"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"}
|
|
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-panel-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-panel 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-panel-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-panel-hover',\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-panel 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-panel-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-panel 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-panel 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-panel 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-panel 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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"}
|
package/dist/ai/conversation.js
CHANGED
|
@@ -62,13 +62,13 @@ function y({ name: t, icon: n }) {
|
|
|
62
62
|
}
|
|
63
63
|
function b({ message: e, reducedMotion: t }) {
|
|
64
64
|
return t ? /* @__PURE__ */ u("div", {
|
|
65
|
-
className: "bg-surface-
|
|
65
|
+
className: "bg-surface-panel rounded-surface px-ds-05 py-ds-04",
|
|
66
66
|
children: /* @__PURE__ */ u("p", {
|
|
67
67
|
className: "text-body-sm text-surface-fg",
|
|
68
68
|
children: e.content
|
|
69
69
|
})
|
|
70
70
|
}) : /* @__PURE__ */ u(_.div, {
|
|
71
|
-
className: "bg-surface-
|
|
71
|
+
className: "bg-surface-panel rounded-surface px-ds-05 py-ds-04",
|
|
72
72
|
initial: { y: 8 },
|
|
73
73
|
animate: {
|
|
74
74
|
opacity: 1,
|