@devalok/shilp-sutra 0.52.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/AGENTS.md +7 -1
  2. package/BREAKING.json +29 -0
  3. package/MIGRATION.md +61 -0
  4. package/dist/_chunks/motion-provider.js +7 -6
  5. package/dist/_chunks/motion-provider.js.map +1 -1
  6. package/dist/_chunks/success.js +53 -53
  7. package/dist/ai/command-bar.js +158 -158
  8. package/dist/ai/command-bar.js.map +1 -1
  9. package/dist/ai/conversation.js +5 -5
  10. package/dist/composed/avatar-group.d.ts +11 -9
  11. package/dist/composed/avatar-group.d.ts.map +1 -1
  12. package/dist/composed/avatar-group.js +108 -140
  13. package/dist/composed/avatar-group.js.map +1 -1
  14. package/dist/composed/bulk-action-bar.d.ts +19 -11
  15. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  16. package/dist/composed/bulk-action-bar.js +81 -110
  17. package/dist/composed/bulk-action-bar.js.map +1 -1
  18. package/dist/composed/command-palette.js +17 -17
  19. package/dist/composed/command-palette.js.map +1 -1
  20. package/dist/composed/error-boundary.d.ts +15 -3
  21. package/dist/composed/error-boundary.d.ts.map +1 -1
  22. package/dist/composed/error-boundary.js +43 -26
  23. package/dist/composed/error-boundary.js.map +1 -1
  24. package/dist/composed/loading-skeleton.d.ts +2 -0
  25. package/dist/composed/loading-skeleton.d.ts.map +1 -1
  26. package/dist/composed/loading-skeleton.js +79 -56
  27. package/dist/composed/loading-skeleton.js.map +1 -1
  28. package/dist/composed/master-detail.d.ts +21 -8
  29. package/dist/composed/master-detail.d.ts.map +1 -1
  30. package/dist/composed/master-detail.js +91 -77
  31. package/dist/composed/master-detail.js.map +1 -1
  32. package/dist/composed/page-skeletons.d.ts +6 -0
  33. package/dist/composed/page-skeletons.d.ts.map +1 -1
  34. package/dist/composed/page-skeletons.js +93 -71
  35. package/dist/composed/page-skeletons.js.map +1 -1
  36. package/dist/composed/priority-indicator.d.ts +15 -6
  37. package/dist/composed/priority-indicator.d.ts.map +1 -1
  38. package/dist/composed/priority-indicator.js +37 -88
  39. package/dist/composed/priority-indicator.js.map +1 -1
  40. package/dist/composed/schedule-view.d.ts +17 -2
  41. package/dist/composed/schedule-view.d.ts.map +1 -1
  42. package/dist/composed/schedule-view.js +163 -64
  43. package/dist/composed/schedule-view.js.map +1 -1
  44. package/dist/motion/motion-provider.d.ts.map +1 -1
  45. package/dist/shell/bottom-navbar.d.ts +32 -6
  46. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  47. package/dist/shell/bottom-navbar.js +156 -129
  48. package/dist/shell/bottom-navbar.js.map +1 -1
  49. package/dist/shell/index.d.ts +5 -3
  50. package/dist/shell/index.d.ts.map +1 -1
  51. package/dist/shell/index.js +2 -3
  52. package/dist/shell/notification-preferences.d.ts.map +1 -1
  53. package/dist/shell/notification-preferences.js +2 -0
  54. package/dist/shell/notification-preferences.js.map +1 -1
  55. package/dist/tokens/primitives.css +6 -2
  56. package/dist/tokens/utilities.css +6 -0
  57. package/dist/ui/autocomplete.d.ts +34 -32
  58. package/dist/ui/autocomplete.d.ts.map +1 -1
  59. package/dist/ui/autocomplete.js +115 -110
  60. package/dist/ui/autocomplete.js.map +1 -1
  61. package/dist/ui/combobox.d.ts +1 -1
  62. package/dist/ui/combobox.d.ts.map +1 -1
  63. package/dist/ui/combobox.js +133 -128
  64. package/dist/ui/combobox.js.map +1 -1
  65. package/dist/ui/file-upload.d.ts.map +1 -1
  66. package/dist/ui/file-upload.js +124 -138
  67. package/dist/ui/file-upload.js.map +1 -1
  68. package/dist/ui/form.d.ts +7 -0
  69. package/dist/ui/form.d.ts.map +1 -1
  70. package/dist/ui/form.js +4 -2
  71. package/dist/ui/form.js.map +1 -1
  72. package/dist/ui/icon-button.d.ts +2 -1
  73. package/dist/ui/icon-button.d.ts.map +1 -1
  74. package/dist/ui/icon-button.js +1 -1
  75. package/dist/ui/icon-button.js.map +1 -1
  76. package/dist/ui/index.js +30 -30
  77. package/dist/ui/label.d.ts.map +1 -1
  78. package/dist/ui/label.js +7 -6
  79. package/dist/ui/label.js.map +1 -1
  80. package/dist/ui/search-input.js +4 -4
  81. package/dist/ui/sidebar.js +7 -7
  82. package/dist/ui/spinner.d.ts.map +1 -1
  83. package/dist/ui/spinner.js +50 -44
  84. package/dist/ui/spinner.js.map +1 -1
  85. package/dist/ui/switch.d.ts.map +1 -1
  86. package/dist/ui/switch.js +24 -24
  87. package/dist/ui/switch.js.map +1 -1
  88. package/dist/ui/table.js +1 -1
  89. package/dist/ui/table.js.map +1 -1
  90. package/docs/components/composed/bulk-action-bar.md +9 -3
  91. package/docs/components/composed/error-boundary.md +18 -2
  92. package/docs/components/composed/master-detail.md +12 -2
  93. package/docs/components/composed/page-skeletons.md +2 -2
  94. package/docs/components/composed/priority-indicator.md +22 -11
  95. package/docs/components/composed/rich-chat-input.md +18 -6
  96. package/docs/components/composed/schedule-view.md +20 -5
  97. package/docs/components/composed/simple-tooltip.md +1 -1
  98. package/docs/components/shell/app-command-palette.md +2 -1
  99. package/docs/components/shell/bottom-navbar.md +28 -9
  100. package/docs/components/shell/command-registry.md +2 -2
  101. package/docs/components/shell/link-context.md +2 -2
  102. package/docs/components/shell/top-bar.md +1 -1
  103. package/docs/components/ui/autocomplete.md +26 -10
  104. package/docs/components/ui/search-input.md +2 -2
  105. package/docs/components/ui/slider.md +2 -2
  106. package/docs/components/ui/split-button.md +3 -3
  107. package/llms.txt +2 -2
  108. package/make-kit/Guidelines.md +1 -1
  109. package/make-kit/components/overview.md +2 -2
  110. package/make-kit/foundations/surfaces.md +1 -1
  111. package/mcp-manifest.json +581 -172
  112. package/package.json +1 -6
  113. package/skill/SKILL.md +1 -1
  114. package/skill/chat-skill/README.md +18 -0
  115. package/skill/chat-skill/SKILL.md +78 -0
  116. package/skill/chat-skill/chatgpt-instructions.md +26 -0
  117. package/skill/chat-skill/gemini-instructions.md +25 -0
  118. package/skill/references/components.md +2 -2
  119. package/dist/shell/sidebar.d.ts +0 -113
  120. package/dist/shell/sidebar.d.ts.map +0 -1
  121. package/dist/shell/sidebar.js +0 -293
  122. package/dist/shell/sidebar.js.map +0 -1
  123. package/docs/components/shell/sidebar.md +0 -103
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.js","names":[],"sources":["../../src/composed/command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandPalette -- Keyboard-driven command palette (Ctrl+K / Cmd+K).\n *\n * Adapted from Karm V2. Uses ui/Dialog as the overlay.\n * All V1 color tokens replaced with semantic design-system tokens.\n */\nimport { IconArrowDown,IconArrowUp, IconCornerDownLeft, IconSearch } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface CommandItem {\n id: string\n /** Display label — string or ReactNode. When ReactNode, provide `filterValue` for search filtering. */\n label: string | React.ReactNode\n /** Optional description — string or ReactNode. */\n description?: string | React.ReactNode\n icon?: IconInput\n /** Keyboard shortcut hint displayed as keycap badges (e.g., \"G D\", \"Ctrl+N\"). */\n shortcut?: string\n /** Custom render override for the label. Receives the current search query for match highlighting. */\n renderLabel?: (query: string) => React.ReactNode\n /** Plain-text value used for search filtering when `label` is a ReactNode. Falls back to `label` if string. */\n filterValue?: string\n onSelect: () => void\n}\n\nexport interface CommandGroup {\n label: string\n items: CommandItem[]\n}\n\n/** A single keyboard hint shown in the footer. */\nexport interface FooterHint {\n /** Key(s) to display — rendered as text inside `<kbd>` or as an icon. */\n keys: string\n /** Human-readable label for the hint (e.g., \"Navigate\", \"Select\"). */\n label: string\n}\n\n/**\n * A searchable command palette with keyboard navigation (Ctrl+K / Cmd+K).\n * Supports grouped items, custom keybindings, controlled/uncontrolled open state,\n * and custom empty states.\n */\nexport interface CommandPaletteProps extends React.ComponentPropsWithoutRef<'div'> {\n /** Item groups displayed in the palette. Each group has a label and an array of CommandItems. */\n groups?: CommandGroup[]\n /** Placeholder text for the search input. */\n placeholder?: string\n /** Called on every search input change with the current query string. */\n onSearch?: (query: string) => void\n /** Simple text shown when no results match. Overridden by `emptyState` if provided. */\n emptyMessage?: string\n /** Full custom empty state ReactNode — overrides `emptyMessage` when provided. */\n emptyState?: React.ReactNode\n // -- Controlled/uncontrolled open state (P1 #4) --\n /** Controlled open state. */\n open?: boolean\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n // -- Keyboard shortcut customization (P1 #6) --\n /** Keybinding(s) to toggle the palette. Pass `false` to disable.\n * String format: modifier+key, e.g., 'mod+k', 'ctrl+shift+p'.\n * 'mod' maps to Meta on macOS, Ctrl otherwise. */\n keybinding?: string | string[] | false\n // -- Configurable max-height (P2 #8) --\n /** Max height of the results container. CSS value. Default '320px'. */\n maxHeight?: string | number\n // -- Custom footer hints (P2 #11) --\n /** Custom footer keyboard hints. Pass `false` to hide the footer entirely. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\n\n/** Get the text-searchable value from a CommandItem. */\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\n/** Get the text-searchable description from a CommandItem. */\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n/** Parse a shortcut string like \"G D\" or \"Ctrl+N\" into individual keycap segments. */\nfunction parseShortcutKeys(shortcut: string): string[] {\n // If it has \"+\" separator (Ctrl+Shift+N style), split on +\n if (shortcut.includes('+')) {\n return shortcut.split('+').map(s => s.trim()).filter(Boolean)\n }\n // Otherwise split on spaces (G D style)\n return shortcut.split(/\\s+/).filter(Boolean)\n}\n\n// -----------------------------------------------------------------------\n// CommandPalette\n// -----------------------------------------------------------------------\n\nconst CommandPalette = React.forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n groups = [],\n placeholder = 'Search or jump to...',\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+k',\n maxHeight = '320px',\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n // Use a ref for the current open value to avoid stale closures in setOpen\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved = typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(0)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-palette-listbox-${instanceId}`\n\n // -- Reduced motion (P2 #12) --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection (P2 #13) --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // Filter groups based on query\n const filteredGroups = React.useMemo(() => {\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Global keyboard shortcut\n React.useEffect(() => {\n if (keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [keybinding, setOpen])\n\n // Reset state when opening\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActiveIndex(0)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [open])\n\n // Keyboard navigation inside the palette\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n break\n }\n case 'Enter': {\n e.preventDefault()\n const item = filteredItems[activeIndex]\n if (item) {\n item.onSelect()\n setOpen(false)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n break\n }\n }\n }\n\n // Scroll active item into view\n React.useEffect(() => {\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(0)\n onSearch?.(value)\n }\n\n // Build a map of item id -> flat index for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Resolve motion transitions --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // -- Resolve max height CSS value --\n const maxHeightValue = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Resolve footer hints --\n const resolvedFooterHints: FooterHint[] | false =\n footerHints === false\n ? false\n : footerHints ?? [\n { keys: '↑↓', label: 'Navigate' },\n { keys: '↵', label: 'Select' },\n { keys: 'Esc', label: 'Close' },\n ]\n\n // Handle dialog open change (from Dialog's own close mechanisms)\n const handleDialogOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n setOpen(nextOpen)\n },\n [setOpen],\n )\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay\n className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\"\n />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n onKeyDown={handleKeyDown}\n >\n <VisuallyHidden>\n <DialogTitle>Command Palette</DialogTitle>\n <DialogDescription>\n Search or jump to pages, projects, tasks, and actions\n </DialogDescription>\n </VisuallyHidden>\n\n {/* Search input */}\n <div className=\"flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <motion.span\n initial={noInit ?? { opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springSnappy}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconSearch} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls={listboxId}\n aria-activedescendant={filteredItems[activeIndex] ? `command-item-${instanceId}-${filteredItems[activeIndex].id}` : undefined}\n aria-autocomplete=\"list\"\n className={cn(\n 'flex-1 bg-transparent text-body-lg text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n <kbd className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\">\n Esc\n </kbd>\n </div>\n\n {/* Results */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={isReduced ? noMotionTransition : { ...tweens.fade, delay: groupIdx * 0.06 }}\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={isReduced ? noMotionTransition : { ...springs.snappy, delay: itemIndex * 0.03 }}\n onClick={() => {\n item.onSelect()\n setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive ? 'text-accent-11' : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-body-md\">\n {item.renderLabel ? item.renderLabel(query) : item.label}\n </span>\n {item.description && (\n <span className=\"line-clamp-1 text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && (\n <span className=\"flex shrink-0 items-center gap-ds-01\">\n {parseShortcutKeys(item.shortcut).map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-body-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-accent-2 text-accent-11 border-accent-6'\n : 'bg-surface-raised text-surface-fg-subtle border-surface-border-strong',\n )}\n >\n {key === 'Ctrl' || key === 'ctrl' ? getModifierDisplay(isMac) : key}\n </kbd>\n ))}\n </span>\n )}\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconCornerDownLeft} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n\n {/* Footer with keyboard hints */}\n {resolvedFooterHints !== false && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {resolvedFooterHints.map((hint, i) => (\n <div key={i} className=\"flex items-center gap-ds-02b\">\n {hint.keys === '↑↓' ? (\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n ) : hint.keys === '↵' ? (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n ) : (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n {hint.keys}\n </kbd>\n )}\n <span className=\"text-caption text-surface-fg-subtle\">\n {hint.label}\n </span>\n </div>\n ))}\n </motion.div>\n )}\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandPalette.displayName = 'CommandPalette'\n\nexport { CommandPalette }\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-palette.js","names":[],"sources":["../../src/composed/command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandPalette -- Keyboard-driven command palette (Ctrl+K / Cmd+K).\n *\n * Adapted from Karm V2. Uses ui/Dialog as the overlay.\n * All V1 color tokens replaced with semantic design-system tokens.\n */\nimport { IconArrowDown,IconArrowUp, IconCornerDownLeft, IconSearch } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface CommandItem {\n id: string\n /** Display label — string or ReactNode. When ReactNode, provide `filterValue` for search filtering. */\n label: string | React.ReactNode\n /** Optional description — string or ReactNode. */\n description?: string | React.ReactNode\n icon?: IconInput\n /** Keyboard shortcut hint displayed as keycap badges (e.g., \"G D\", \"Ctrl+N\"). */\n shortcut?: string\n /** Custom render override for the label. Receives the current search query for match highlighting. */\n renderLabel?: (query: string) => React.ReactNode\n /** Plain-text value used for search filtering when `label` is a ReactNode. Falls back to `label` if string. */\n filterValue?: string\n onSelect: () => void\n}\n\nexport interface CommandGroup {\n label: string\n items: CommandItem[]\n}\n\n/** A single keyboard hint shown in the footer. */\nexport interface FooterHint {\n /** Key(s) to display — rendered as text inside `<kbd>` or as an icon. */\n keys: string\n /** Human-readable label for the hint (e.g., \"Navigate\", \"Select\"). */\n label: string\n}\n\n/**\n * A searchable command palette with keyboard navigation (Ctrl+K / Cmd+K).\n * Supports grouped items, custom keybindings, controlled/uncontrolled open state,\n * and custom empty states.\n */\nexport interface CommandPaletteProps extends React.ComponentPropsWithoutRef<'div'> {\n /** Item groups displayed in the palette. Each group has a label and an array of CommandItems. */\n groups?: CommandGroup[]\n /** Placeholder text for the search input. */\n placeholder?: string\n /** Called on every search input change with the current query string. */\n onSearch?: (query: string) => void\n /** Simple text shown when no results match. Overridden by `emptyState` if provided. */\n emptyMessage?: string\n /** Full custom empty state ReactNode — overrides `emptyMessage` when provided. */\n emptyState?: React.ReactNode\n // -- Controlled/uncontrolled open state (P1 #4) --\n /** Controlled open state. */\n open?: boolean\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n // -- Keyboard shortcut customization (P1 #6) --\n /** Keybinding(s) to toggle the palette. Pass `false` to disable.\n * String format: modifier+key, e.g., 'mod+k', 'ctrl+shift+p'.\n * 'mod' maps to Meta on macOS, Ctrl otherwise. */\n keybinding?: string | string[] | false\n // -- Configurable max-height (P2 #8) --\n /** Max height of the results container. CSS value. Default '320px'. */\n maxHeight?: string | number\n // -- Custom footer hints (P2 #11) --\n /** Custom footer keyboard hints. Pass `false` to hide the footer entirely. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\n\n/** Get the text-searchable value from a CommandItem. */\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\n/** Get the text-searchable description from a CommandItem. */\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n/** Parse a shortcut string like \"G D\" or \"Ctrl+N\" into individual keycap segments. */\nfunction parseShortcutKeys(shortcut: string): string[] {\n // If it has \"+\" separator (Ctrl+Shift+N style), split on +\n if (shortcut.includes('+')) {\n return shortcut.split('+').map(s => s.trim()).filter(Boolean)\n }\n // Otherwise split on spaces (G D style)\n return shortcut.split(/\\s+/).filter(Boolean)\n}\n\n// -----------------------------------------------------------------------\n// CommandPalette\n// -----------------------------------------------------------------------\n\nconst CommandPalette = React.forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n groups = [],\n placeholder = 'Search or jump to...',\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+k',\n maxHeight = '320px',\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n // Use a ref for the current open value to avoid stale closures in setOpen\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved = typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(0)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-palette-listbox-${instanceId}`\n\n // -- Reduced motion (P2 #12) --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection (P2 #13) --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // Filter groups based on query\n const filteredGroups = React.useMemo(() => {\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Global keyboard shortcut\n React.useEffect(() => {\n if (keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [keybinding, setOpen])\n\n // Reset state when opening\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActiveIndex(0)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [open])\n\n // Keyboard navigation inside the palette\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n break\n }\n case 'Enter': {\n e.preventDefault()\n const item = filteredItems[activeIndex]\n if (item) {\n item.onSelect()\n setOpen(false)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n break\n }\n }\n }\n\n // Scroll active item into view\n React.useEffect(() => {\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(0)\n onSearch?.(value)\n }\n\n // Build a map of item id -> flat index for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Resolve motion transitions --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // -- Resolve max height CSS value --\n const maxHeightValue = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Resolve footer hints --\n const resolvedFooterHints: FooterHint[] | false =\n footerHints === false\n ? false\n : footerHints ?? [\n { keys: '↑↓', label: 'Navigate' },\n { keys: '↵', label: 'Select' },\n { keys: 'Esc', label: 'Close' },\n ]\n\n // Handle dialog open change (from Dialog's own close mechanisms)\n const handleDialogOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n setOpen(nextOpen)\n },\n [setOpen],\n )\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay\n className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\"\n />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n onKeyDown={handleKeyDown}\n >\n <VisuallyHidden>\n <DialogTitle>Command Palette</DialogTitle>\n <DialogDescription>\n Search or jump to pages, projects, tasks, and actions\n </DialogDescription>\n </VisuallyHidden>\n\n {/* Search input */}\n <div className=\"flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <motion.span\n initial={noInit ?? { opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springSnappy}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconSearch} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls={listboxId}\n aria-activedescendant={filteredItems[activeIndex] ? `command-item-${instanceId}-${filteredItems[activeIndex].id}` : undefined}\n aria-autocomplete=\"list\"\n className={cn(\n 'flex-1 bg-transparent text-body-lg text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n <kbd className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\">\n Esc\n </kbd>\n </div>\n\n {/* Results */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={isReduced ? noMotionTransition : { ...tweens.fade, delay: groupIdx * 0.06 }}\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={isReduced ? noMotionTransition : { ...springs.snappy, delay: itemIndex * 0.03 }}\n onClick={() => {\n item.onSelect()\n setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive ? 'text-accent-11' : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-body-md\">\n {item.renderLabel ? item.renderLabel(query) : item.label}\n </span>\n {item.description && (\n <span className=\"line-clamp-1 text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && (\n <span className=\"flex shrink-0 items-center gap-ds-01\">\n {parseShortcutKeys(item.shortcut).map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-body-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-accent-2 text-accent-11 border-accent-6'\n : 'bg-surface-raised text-surface-fg-subtle border-surface-border-strong',\n )}\n >\n {key === 'Ctrl' || key === 'ctrl' ? getModifierDisplay(isMac) : key}\n </kbd>\n ))}\n </span>\n )}\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconCornerDownLeft} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n\n {/* Footer with keyboard hints */}\n {resolvedFooterHints !== false && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {resolvedFooterHints.map((hint, i) => (\n <div key={i} className=\"flex items-center gap-ds-02b\">\n {hint.keys === '↑↓' ? (\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n ) : hint.keys === '↵' ? (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n ) : (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n {hint.keys}\n </kbd>\n )}\n <span className=\"text-caption text-surface-fg-subtle\">\n {hint.label}\n </span>\n </div>\n ))}\n </motion.div>\n )}\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandPalette.displayName = 'CommandPalette'\n\nexport { CommandPalette }\n"],"mappings":"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"}
@@ -3,16 +3,26 @@ import * as React from 'react';
3
3
  export interface ErrorDisplayProps extends React.ComponentPropsWithoutRef<'div'> {
4
4
  error: unknown;
5
5
  onReset?: () => void;
6
+ /** Custom recovery actions. When set, replaces the default "Try Again" button. */
7
+ actions?: React.ReactNode;
8
+ /** Center in a full-viewport-height region (error page). @default true */
9
+ fullPage?: boolean;
10
+ /** Move focus to the recovery button on mount (set by ErrorBoundary on swap). @default false */
11
+ autoFocusReset?: boolean;
6
12
  }
7
13
  declare const ErrorDisplay: React.ForwardRefExoticComponent<ErrorDisplayProps & React.RefAttributes<HTMLDivElement>>;
8
14
  interface ErrorBoundaryProps {
9
15
  children: React.ReactNode;
10
- /** Optional callback when the user clicks "Try Again" */
16
+ /** Called when the user clicks "Try Again" (after the boundary resets). */
11
17
  onReset?: () => void;
12
- /** Optional custom fallback receives the caught error. Defaults to ErrorDisplay. */
18
+ /** Called when an error is caught wire your logger/Sentry here. */
19
+ onError?: (error: unknown, info: React.ErrorInfo) => void;
20
+ /** Auto-reset when any value in this array changes (react-error-boundary parity). */
21
+ resetKeys?: unknown[];
22
+ /** Custom fallback — receives the caught error + a reset callback. Defaults to ErrorDisplay. */
13
23
  fallback?: (props: {
14
24
  error: unknown;
15
- onReset?: () => void;
25
+ onReset: () => void;
16
26
  }) => React.ReactNode;
17
27
  }
18
28
  interface ErrorBoundaryState {
@@ -21,6 +31,8 @@ interface ErrorBoundaryState {
21
31
  declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
22
32
  constructor(props: ErrorBoundaryProps);
23
33
  static getDerivedStateFromError(error: unknown): ErrorBoundaryState;
34
+ componentDidCatch(error: unknown, info: React.ErrorInfo): void;
35
+ componentDidUpdate(prev: ErrorBoundaryProps): void;
24
36
  private handleReset;
25
37
  render(): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
26
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../../src/composed/error-boundary.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC;IAC9E,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAmFD,QAAA,MAAM,YAAY,0FA2EjB,CAAA;AAID,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAA;CAChF;AAED,UAAU,kBAAkB;IAC1B,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACtB;AAED,cAAM,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;gBACrE,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB;IAInE,OAAO,CAAC,WAAW,CAGlB;IAED,MAAM;CASP;AAED,OAAO,EAAE,aAAa,EAAC,YAAY,EAAE,CAAA;AACrC,YAAY,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../../src/composed/error-boundary.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC;IAC9E,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,kFAAkF;IAClF,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gGAAgG;IAChG,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAgDD,QAAA,MAAM,YAAY,0FAuDjB,CAAA;AAGD,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAA;IACzD,qFAAqF;IACrF,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;IACrB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAA;CAC/E;AAED,UAAU,kBAAkB;IAC1B,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACtB;AAQD,cAAM,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;gBACrE,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB;IAInE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS;IAIvD,kBAAkB,CAAC,IAAI,EAAE,kBAAkB;IAO3C,OAAO,CAAC,WAAW,CAGlB;IAED,MAAM;CASP;AAED,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA;AACtC,YAAY,EAAE,kBAAkB,EAAE,CAAA"}
@@ -19,9 +19,12 @@ function d(e) {
19
19
  if (typeof e == "string") return e;
20
20
  }
21
21
  function f(e) {
22
- if (e instanceof Error) return e.stack;
22
+ return e instanceof Error ? e.stack : void 0;
23
23
  }
24
- function p(e) {
24
+ function p() {
25
+ return typeof process < "u" && !!process.env && process.env.NODE_ENV === "development";
26
+ }
27
+ function m(e) {
25
28
  switch (e) {
26
29
  case 404: return {
27
30
  icon: c,
@@ -53,71 +56,84 @@ function p(e) {
53
56
  };
54
57
  }
55
58
  }
56
- var m = r.forwardRef(function({ error: r, onReset: o, className: s, ...c }, l) {
57
- let m = u(r), h = d(r), g = f(r), _ = typeof process < "u" && process.env && process.env.NODE_ENV === "development", v = p(m), y = v.icon;
58
- return /* @__PURE__ */ i("div", {
59
- ref: l,
60
- ...c,
61
- className: e("flex min-h-[60vh] items-center justify-center p-ds-05", s),
59
+ var h = r.forwardRef(function({ error: o, onReset: s, actions: c, fullPage: l = !0, autoFocusReset: h = !1, className: g, ..._ }, v) {
60
+ let y = u(o), b = d(o), x = f(o), S = p(), C = m(y), w = C.icon, T = r.useRef(null), E = S && b || C.message;
61
+ return r.useEffect(() => {
62
+ h && T.current?.focus();
63
+ }, [h]), /* @__PURE__ */ i("div", {
64
+ ref: v,
65
+ ..._,
66
+ className: e("flex items-center justify-center p-ds-05", l && "min-h-[60vh]", g),
62
67
  children: /* @__PURE__ */ a("div", {
68
+ role: "alert",
63
69
  className: "flex w-full max-w-lg flex-col items-center gap-ds-06 rounded-overlay-lg bg-surface-raised p-ds-07 text-center shadow-raised",
64
70
  children: [
65
71
  /* @__PURE__ */ i("div", {
66
- className: e("flex h-ds-lg w-ds-lg items-center justify-center rounded-bubble", v.bgClass),
72
+ className: e("flex h-ds-lg w-ds-lg items-center justify-center rounded-bubble", C.bgClass),
67
73
  children: /* @__PURE__ */ i(t, {
68
- icon: y,
74
+ icon: w,
69
75
  size: "2xl",
70
- className: v.iconClass
76
+ className: C.iconClass
71
77
  })
72
78
  }),
73
79
  /* @__PURE__ */ a("div", {
74
80
  className: "flex flex-col gap-ds-03",
75
81
  children: [
76
- m && /* @__PURE__ */ a("span", {
82
+ y && /* @__PURE__ */ a("span", {
77
83
  className: "text-body-sm text-surface-fg-subtle",
78
- children: ["Error ", m]
84
+ children: ["Error ", y]
79
85
  }),
80
86
  /* @__PURE__ */ i("h2", {
81
87
  className: "text-heading-md font-semibold text-surface-fg",
82
- children: v.title
88
+ children: C.title
83
89
  }),
84
90
  /* @__PURE__ */ i("p", {
85
91
  className: "text-body-lg text-surface-fg-subtle",
86
- children: h || v.message
92
+ children: E
87
93
  })
88
94
  ]
89
95
  }),
90
- o && /* @__PURE__ */ i("div", {
96
+ (c || s) && /* @__PURE__ */ i("div", {
91
97
  className: "flex items-center gap-ds-04",
92
- children: /* @__PURE__ */ i(n, {
98
+ children: c ?? /* @__PURE__ */ i(n, {
99
+ ref: T,
93
100
  variant: "soft",
94
101
  size: "md",
95
- onClick: o,
102
+ onClick: s,
96
103
  children: "Try Again"
97
104
  })
98
105
  }),
99
- _ && g && /* @__PURE__ */ a("div", {
100
- className: "w-full overflow-auto rounded-surface border border-card-strong bg-surface-raised p-ds-05 text-left",
106
+ S && x && /* @__PURE__ */ a("div", {
107
+ className: "w-full overflow-auto rounded-surface border border-card bg-surface-raised p-ds-05 text-left",
101
108
  children: [/* @__PURE__ */ i("p", {
102
109
  className: "text-body-sm mb-ds-03 font-semibold text-surface-fg",
103
110
  children: "Stack Trace (development only)"
104
111
  }), /* @__PURE__ */ i("pre", {
105
112
  className: "whitespace-pre-wrap text-body-sm text-surface-fg-subtle",
106
- children: g
113
+ children: x
107
114
  })]
108
115
  })
109
116
  ]
110
117
  })
111
118
  });
112
119
  });
113
- m.displayName = "ErrorDisplay";
114
- var h = class extends r.Component {
120
+ h.displayName = "ErrorDisplay";
121
+ function g(e, t) {
122
+ return !e || !t ? !1 : e.length !== t.length || e.some((e, n) => !Object.is(e, t[n]));
123
+ }
124
+ var _ = class extends r.Component {
115
125
  constructor(e) {
116
126
  super(e), this.state = { error: null };
117
127
  }
118
128
  static getDerivedStateFromError(e) {
119
129
  return { error: e };
120
130
  }
131
+ componentDidCatch(e, t) {
132
+ this.props.onError?.(e, t);
133
+ }
134
+ componentDidUpdate(e) {
135
+ this.state.error !== null && g(e.resetKeys, this.props.resetKeys) && this.setState({ error: null });
136
+ }
121
137
  handleReset = () => {
122
138
  this.setState({ error: null }), this.props.onReset?.();
123
139
  };
@@ -125,11 +141,12 @@ var h = class extends r.Component {
125
141
  return this.state.error === null ? this.props.children : this.props.fallback ? this.props.fallback({
126
142
  error: this.state.error,
127
143
  onReset: this.handleReset
128
- }) : /* @__PURE__ */ i(m, {
144
+ }) : /* @__PURE__ */ i(h, {
129
145
  error: this.state.error,
130
- onReset: this.handleReset
146
+ onReset: this.handleReset,
147
+ autoFocusReset: !0
131
148
  });
132
149
  }
133
150
  };
134
151
  //#endregion
135
- export { h as ErrorBoundary, m as ErrorDisplay };
152
+ export { _ as ErrorBoundary, h as ErrorDisplay };
@@ -1 +1 @@
1
- {"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/composed/error-boundary.tsx"],"sourcesContent":["'use client'\n\nimport { IconAlertTriangle, IconBan, IconFileUnknown, IconServerOff } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Button } from '../ui/button'\nimport { Icon } from '../ui/icon'\nimport { cn } from '../ui/lib/utils'\n\ndeclare const process: { env: { NODE_ENV?: string } } | undefined\n\nexport interface ErrorDisplayProps extends React.ComponentPropsWithoutRef<'div'> {\n error: unknown\n onReset?: () => void\n}\n\nfunction getStatusFromError(error: unknown): number | undefined {\n if (\n error &&\n typeof error === 'object' &&\n 'status' in error &&\n typeof (error as Record<string, unknown>).status === 'number'\n ) {\n return (error as Record<string, unknown>).status as number\n }\n return undefined\n}\n\nfunction getMessageFromError(error: unknown): string | undefined {\n if (error instanceof Error) {\n return error.message\n }\n if (\n error &&\n typeof error === 'object' &&\n 'data' in error\n ) {\n const data = (error as Record<string, unknown>).data\n if (typeof data === 'string') return data\n if (data && typeof data === 'object' && 'message' in data) {\n return String((data as Record<string, unknown>).message)\n }\n }\n if (typeof error === 'string') {\n return error\n }\n return undefined\n}\n\nfunction getStackFromError(error: unknown): string | undefined {\n if (error instanceof Error) {\n return error.stack\n }\n return undefined\n}\n\nfunction getErrorConfig(status?: number) {\n switch (status) {\n case 404:\n return {\n icon: IconFileUnknown,\n title: 'Page not found',\n message:\n 'The page you are looking for does not exist or has been moved.',\n bgClass: 'bg-accent-2',\n iconClass: 'text-accent-11',\n }\n case 403:\n return {\n icon: IconBan,\n title: 'Access denied',\n message:\n 'You do not have permission to view this page. Contact your administrator if you believe this is a mistake.',\n bgClass: 'bg-warning-3',\n iconClass: 'text-warning-11',\n }\n case 500:\n return {\n icon: IconServerOff,\n title: 'Server error',\n message:\n 'Something went wrong on our end. Please try again later or contact support if the issue persists.',\n bgClass: 'bg-error-3',\n iconClass: 'text-error-11',\n }\n default:\n return {\n icon: IconAlertTriangle,\n title: 'Something went wrong',\n message:\n 'An unexpected error occurred. Please try again or go back to the home page.',\n bgClass: 'bg-accent-2',\n iconClass: 'text-accent-11',\n }\n }\n}\n\nconst ErrorDisplay = React.forwardRef<HTMLDivElement, ErrorDisplayProps>(\n function ErrorDisplay({ error, onReset, className, ...props }, ref) {\n const status = getStatusFromError(error)\n const message = getMessageFromError(error)\n const stack = getStackFromError(error)\n const isDev =\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development'\n\n const errorConfig = getErrorConfig(status)\n const ErrorIcon = errorConfig.icon\n\n return (\n <div ref={ref} {...props} className={cn(\"flex min-h-[60vh] items-center justify-center p-ds-05\", className)}>\n <div\n className=\"flex w-full max-w-lg flex-col items-center gap-ds-06 rounded-overlay-lg bg-surface-raised p-ds-07 text-center shadow-raised\"\n >\n {/* Error Icon */}\n <div\n className={cn(\n 'flex h-ds-lg w-ds-lg items-center justify-center rounded-bubble',\n errorConfig.bgClass,\n )}\n >\n <Icon\n icon={ErrorIcon}\n size=\"2xl\"\n className={errorConfig.iconClass}\n />\n </div>\n\n {/* Error IconInfoCircle */}\n <div className=\"flex flex-col gap-ds-03\">\n {status && (\n <span className=\"text-body-sm text-surface-fg-subtle\">\n Error {status}\n </span>\n )}\n <h2 className=\"text-heading-md font-semibold text-surface-fg\">\n {errorConfig.title}\n </h2>\n <p className=\"text-body-lg text-surface-fg-subtle\">\n {message || errorConfig.message}\n </p>\n </div>\n\n {/* Actions */}\n {onReset && (\n <div className=\"flex items-center gap-ds-04\">\n <Button\n variant=\"soft\"\n size=\"md\"\n onClick={onReset}\n >\n Try Again\n </Button>\n </div>\n )}\n\n {/* Dev stack trace */}\n {isDev && stack && (\n <div className=\"w-full overflow-auto rounded-surface border border-card-strong bg-surface-raised p-ds-05 text-left\">\n <p className=\"text-body-sm mb-ds-03 font-semibold text-surface-fg\">\n Stack Trace (development only)\n </p>\n <pre className=\"whitespace-pre-wrap text-body-sm text-surface-fg-subtle\">\n {stack}\n </pre>\n </div>\n )}\n </div>\n </div>\n )\n},\n)\n\nErrorDisplay.displayName = 'ErrorDisplay'\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode\n /** Optional callback when the user clicks \"Try Again\" */\n onReset?: () => void\n /** Optional custom fallback — receives the caught error. Defaults to ErrorDisplay. */\n fallback?: (props: { error: unknown; onReset?: () => void }) => React.ReactNode\n}\n\ninterface ErrorBoundaryState {\n error: unknown | null\n}\n\nclass ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { error: null }\n }\n\n static getDerivedStateFromError(error: unknown): ErrorBoundaryState {\n return { error }\n }\n\n private handleReset = () => {\n this.setState({ error: null })\n this.props.onReset?.()\n }\n\n render() {\n if (this.state.error !== null) {\n if (this.props.fallback) {\n return this.props.fallback({ error: this.state.error, onReset: this.handleReset })\n }\n return <ErrorDisplay error={this.state.error} onReset={this.handleReset} />\n }\n return this.props.children\n }\n}\n\nexport { ErrorBoundary,ErrorDisplay }\nexport type { ErrorBoundaryProps }\n"],"mappings":"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"}
1
+ {"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/composed/error-boundary.tsx"],"sourcesContent":["'use client'\n\nimport { IconAlertTriangle, IconBan, IconFileUnknown, IconServerOff } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Button } from '../ui/button'\nimport { Icon } from '../ui/icon'\nimport { cn } from '../ui/lib/utils'\n\ndeclare const process: { env: { NODE_ENV?: string } } | undefined\n\nexport interface ErrorDisplayProps extends React.ComponentPropsWithoutRef<'div'> {\n error: unknown\n onReset?: () => void\n /** Custom recovery actions. When set, replaces the default \"Try Again\" button. */\n actions?: React.ReactNode\n /** Center in a full-viewport-height region (error page). @default true */\n fullPage?: boolean\n /** Move focus to the recovery button on mount (set by ErrorBoundary on swap). @default false */\n autoFocusReset?: boolean\n}\n\nfunction getStatusFromError(error: unknown): number | undefined {\n if (\n error &&\n typeof error === 'object' &&\n 'status' in error &&\n typeof (error as Record<string, unknown>).status === 'number'\n ) {\n return (error as Record<string, unknown>).status as number\n }\n return undefined\n}\n\nfunction getMessageFromError(error: unknown): string | undefined {\n if (error instanceof Error) return error.message\n if (error && typeof error === 'object' && 'data' in error) {\n const data = (error as Record<string, unknown>).data\n if (typeof data === 'string') return data\n if (data && typeof data === 'object' && 'message' in data) {\n return String((data as Record<string, unknown>).message)\n }\n }\n if (typeof error === 'string') return error\n return undefined\n}\n\nfunction getStackFromError(error: unknown): string | undefined {\n return error instanceof Error ? error.stack : undefined\n}\n\nfunction isDevEnv() {\n return typeof process !== 'undefined' && !!process.env && process.env.NODE_ENV === 'development'\n}\n\nfunction getErrorConfig(status?: number) {\n switch (status) {\n case 404:\n return { icon: IconFileUnknown, title: 'Page not found', message: 'The page you are looking for does not exist or has been moved.', bgClass: 'bg-accent-2', iconClass: 'text-accent-11' }\n case 403:\n return { icon: IconBan, title: 'Access denied', message: 'You do not have permission to view this page. Contact your administrator if you believe this is a mistake.', bgClass: 'bg-warning-3', iconClass: 'text-warning-11' }\n case 500:\n return { icon: IconServerOff, title: 'Server error', message: 'Something went wrong on our end. Please try again later or contact support if the issue persists.', bgClass: 'bg-error-3', iconClass: 'text-error-11' }\n default:\n return { icon: IconAlertTriangle, title: 'Something went wrong', message: 'An unexpected error occurred. Please try again or go back to the home page.', bgClass: 'bg-accent-2', iconClass: 'text-accent-11' }\n }\n}\n\nconst ErrorDisplay = React.forwardRef<HTMLDivElement, ErrorDisplayProps>(\n function ErrorDisplay({ error, onReset, actions, fullPage = true, autoFocusReset = false, className, ...props }, ref) {\n const status = getStatusFromError(error)\n const rawMessage = getMessageFromError(error)\n const stack = getStackFromError(error)\n const isDev = isDevEnv()\n const errorConfig = getErrorConfig(status)\n const ErrorIcon = errorConfig.icon\n const resetRef = React.useRef<HTMLButtonElement>(null)\n\n // Only surface the raw error message in development — in production it can leak\n // internal detail; users see the friendly, status-mapped copy instead.\n const shownMessage = isDev ? rawMessage || errorConfig.message : errorConfig.message\n\n React.useEffect(() => {\n if (autoFocusReset) resetRef.current?.focus()\n }, [autoFocusReset])\n\n return (\n <div ref={ref} {...props} className={cn('flex items-center justify-center p-ds-05', fullPage && 'min-h-[60vh]', className)}>\n {/* role=alert → assertive live region: AT announces the error on appearance. */}\n <div\n role=\"alert\"\n className=\"flex w-full max-w-lg flex-col items-center gap-ds-06 rounded-overlay-lg bg-surface-raised p-ds-07 text-center shadow-raised\"\n >\n <div className={cn('flex h-ds-lg w-ds-lg items-center justify-center rounded-bubble', errorConfig.bgClass)}>\n <Icon icon={ErrorIcon} size=\"2xl\" className={errorConfig.iconClass} />\n </div>\n\n <div className=\"flex flex-col gap-ds-03\">\n {status && <span className=\"text-body-sm text-surface-fg-subtle\">Error {status}</span>}\n <h2 className=\"text-heading-md font-semibold text-surface-fg\">{errorConfig.title}</h2>\n <p className=\"text-body-lg text-surface-fg-subtle\">{shownMessage}</p>\n </div>\n\n {(actions || onReset) && (\n <div className=\"flex items-center gap-ds-04\">\n {actions ?? (\n <Button ref={resetRef} variant=\"soft\" size=\"md\" onClick={onReset}>\n Try Again\n </Button>\n )}\n </div>\n )}\n\n {isDev && stack && (\n <div className=\"w-full overflow-auto rounded-surface border border-card bg-surface-raised p-ds-05 text-left\">\n <p className=\"text-body-sm mb-ds-03 font-semibold text-surface-fg\">Stack Trace (development only)</p>\n <pre className=\"whitespace-pre-wrap text-body-sm text-surface-fg-subtle\">{stack}</pre>\n </div>\n )}\n </div>\n </div>\n )\n },\n)\nErrorDisplay.displayName = 'ErrorDisplay'\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode\n /** Called when the user clicks \"Try Again\" (after the boundary resets). */\n onReset?: () => void\n /** Called when an error is caught — wire your logger/Sentry here. */\n onError?: (error: unknown, info: React.ErrorInfo) => void\n /** Auto-reset when any value in this array changes (react-error-boundary parity). */\n resetKeys?: unknown[]\n /** Custom fallback — receives the caught error + a reset callback. Defaults to ErrorDisplay. */\n fallback?: (props: { error: unknown; onReset: () => void }) => React.ReactNode\n}\n\ninterface ErrorBoundaryState {\n error: unknown | null\n}\n\nfunction keysChanged(a: unknown[] | undefined, b: unknown[] | undefined) {\n if (!a || !b) return false\n if (a.length !== b.length) return true\n return a.some((v, i) => !Object.is(v, b[i]))\n}\n\nclass ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { error: null }\n }\n\n static getDerivedStateFromError(error: unknown): ErrorBoundaryState {\n return { error }\n }\n\n componentDidCatch(error: unknown, info: React.ErrorInfo) {\n this.props.onError?.(error, info)\n }\n\n componentDidUpdate(prev: ErrorBoundaryProps) {\n // Auto-recover when the reset dependencies change.\n if (this.state.error !== null && keysChanged(prev.resetKeys, this.props.resetKeys)) {\n this.setState({ error: null })\n }\n }\n\n private handleReset = () => {\n this.setState({ error: null })\n this.props.onReset?.()\n }\n\n render() {\n if (this.state.error !== null) {\n if (this.props.fallback) {\n return this.props.fallback({ error: this.state.error, onReset: this.handleReset })\n }\n return <ErrorDisplay error={this.state.error} onReset={this.handleReset} autoFocusReset />\n }\n return this.props.children\n }\n}\n\nexport { ErrorBoundary, ErrorDisplay }\nexport type { ErrorBoundaryProps }\n"],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import * as React from 'react';
2
2
  export interface CardSkeletonProps extends React.ComponentPropsWithoutRef<'div'> {
3
3
  className?: string;
4
+ /** Accessible label for the loading region. @default 'Loading' */
5
+ label?: string;
4
6
  }
5
7
  declare const CardSkeleton: React.ForwardRefExoticComponent<CardSkeletonProps & React.RefAttributes<HTMLDivElement>>;
6
8
  export interface TableSkeletonProps extends CardSkeletonProps {
@@ -1 +1 @@
1
- {"version":3,"file":"loading-skeleton.d.ts","sourceRoot":"","sources":["../../src/composed/loading-skeleton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,YAAY,0FA2BjB,CAAA;AAID,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,QAAA,MAAM,aAAa,2FAqDlB,CAAA;AAID,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,QAAA,MAAM,aAAa,2FAiDlB,CAAA;AAID,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,QAAA,MAAM,YAAY,0FA+BjB,CAAA;AAID,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAC,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"loading-skeleton.d.ts","sourceRoot":"","sources":["../../src/composed/loading-skeleton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAkB9B,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,QAAA,MAAM,YAAY,0FA0BjB,CAAA;AAGD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,QAAA,MAAM,aAAa,2FAsClB,CAAA;AAGD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,QAAA,MAAM,aAAa,2FA0ClB,CAAA;AAGD,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,QAAA,MAAM,YAAY,0FAyBjB,CAAA;AAGD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,CAAA"}
@@ -3,102 +3,125 @@ import { Skeleton as t } from "../ui/skeleton.js";
3
3
  import * as n from "react";
4
4
  import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
5
  //#region src/composed/loading-skeleton.tsx
6
- var a = n.forwardRef(function({ className: n, ...a }, o) {
6
+ var a = (e, t) => Math.max(0, Math.floor(typeof e == "number" && !Number.isNaN(e) ? e : t));
7
+ function o(e) {
8
+ return {
9
+ role: "status",
10
+ "aria-busy": !0,
11
+ "aria-label": e ?? "Loading"
12
+ };
13
+ }
14
+ function s({ label: e }) {
15
+ return /* @__PURE__ */ i("span", {
16
+ className: "sr-only",
17
+ children: [e ?? "Loading", "…"]
18
+ });
19
+ }
20
+ var c = n.forwardRef(function({ className: n, label: a, ...c }, l) {
7
21
  return /* @__PURE__ */ i("div", {
8
- ref: o,
9
- ...a,
10
- className: e("rounded-surface border border-card-strong bg-surface-raised p-ds-05b", n),
22
+ ref: l,
23
+ ...o(a),
24
+ ...c,
25
+ className: e("rounded-surface border border-card bg-surface-raised p-ds-05b", n),
11
26
  children: [
27
+ /* @__PURE__ */ r(s, { label: a }),
12
28
  /* @__PURE__ */ i("div", {
13
29
  className: "flex items-center justify-between pb-ds-05",
14
- children: [/* @__PURE__ */ r(t, { className: "h-ds-05 w-[128px] bg-surface-raised-hover" }), /* @__PURE__ */ r(t, { className: "h-ico-sm w-ico-sm rounded bg-surface-raised-hover" })]
30
+ children: [/* @__PURE__ */ r(t, { className: "h-ds-05 w-ds-13" }), /* @__PURE__ */ r(t, { className: "h-ico-sm w-ico-sm rounded" })]
15
31
  }),
16
32
  /* @__PURE__ */ i("div", {
17
33
  className: "space-y-ds-04",
18
34
  children: [
19
- /* @__PURE__ */ r(t, { className: "h-ds-04 w-full bg-surface-raised-hover" }),
20
- /* @__PURE__ */ r(t, { className: "h-ds-04 w-4/5 bg-surface-raised-hover" }),
21
- /* @__PURE__ */ r(t, { className: "h-ds-04 w-3/5 bg-surface-raised-hover" })
35
+ /* @__PURE__ */ r(t, { className: "h-ds-04 w-full" }),
36
+ /* @__PURE__ */ r(t, { className: "h-ds-04 w-4/5" }),
37
+ /* @__PURE__ */ r(t, { className: "h-ds-04 w-3/5" })
22
38
  ]
23
39
  }),
24
40
  /* @__PURE__ */ i("div", {
25
41
  className: "flex items-center gap-ds-03 pt-ds-05",
26
- children: [/* @__PURE__ */ r(t, { className: "h-ds-xs w-ds-xs rounded-pill bg-surface-raised-hover" }), /* @__PURE__ */ r(t, { className: "h-ds-04 w-ds-11 bg-surface-raised-hover" })]
42
+ children: [/* @__PURE__ */ r(t, { className: "h-ds-xs w-ds-xs rounded-pill" }), /* @__PURE__ */ r(t, { className: "h-ds-04 w-ds-11" })]
27
43
  })
28
44
  ]
29
45
  });
30
46
  });
31
- a.displayName = "CardSkeleton";
32
- var o = n.forwardRef(function({ rows: n = 5, columns: a = 4, className: o, ...s }, c) {
47
+ c.displayName = "CardSkeleton";
48
+ var l = n.forwardRef(function({ rows: n = 5, columns: c = 4, className: l, label: u, ...d }, f) {
49
+ let p = a(n, 5), m = Math.max(1, a(c, 4));
33
50
  return /* @__PURE__ */ i("div", {
34
- ref: c,
35
- ...s,
36
- className: e("overflow-hidden rounded-surface border border-card-strong", o),
37
- children: [/* @__PURE__ */ r("div", {
38
- className: "flex items-center gap-ds-05 border-b border-surface-border-strong bg-surface-raised px-ds-05 py-ds-04",
39
- children: Array.from({ length: a }).map((n, i) => /* @__PURE__ */ r(t, { className: e("h-ds-04 bg-surface-raised-hover", i === 0 ? "w-ds-13" : "flex-1") }, `head-${i}`))
40
- }), Array.from({ length: n }).map((i, o) => /* @__PURE__ */ r("div", {
41
- className: e("flex items-center gap-ds-05 px-ds-05 py-ds-04", o < n - 1 && "border-b border-surface-border-strong"),
42
- style: { animationDelay: `${o * 50}ms` },
43
- children: Array.from({ length: a }).map((n, i) => /* @__PURE__ */ r(t, { className: e("h-ds-04 bg-surface-raised-hover", i === 0 ? "w-ds-13" : "flex-1") }, `cell-${o}-${i}`))
44
- }, `row-${o}`))]
51
+ ref: f,
52
+ ...o(u),
53
+ ...d,
54
+ className: e("overflow-hidden rounded-surface border border-card", l),
55
+ children: [
56
+ /* @__PURE__ */ r(s, { label: u }),
57
+ /* @__PURE__ */ r("div", {
58
+ className: "flex items-center gap-ds-05 border-b border-surface-border-strong bg-surface-raised px-ds-05 py-ds-04",
59
+ children: Array.from({ length: m }).map((n, i) => /* @__PURE__ */ r(t, { className: e("h-ds-04", i === 0 ? "w-ds-13" : "flex-1") }, `head-${i}`))
60
+ }),
61
+ Array.from({ length: p }).map((n, i) => /* @__PURE__ */ r("div", {
62
+ className: e("flex items-center gap-ds-05 px-ds-05 py-ds-04", i < p - 1 && "border-b border-surface-border-strong"),
63
+ children: Array.from({ length: m }).map((n, a) => /* @__PURE__ */ r(t, { className: e("h-ds-04", a === 0 ? "w-ds-13" : "flex-1") }, `cell-${i}-${a}`))
64
+ }, `row-${i}`))
65
+ ]
45
66
  });
46
67
  });
47
- o.displayName = "TableSkeleton";
48
- var s = n.forwardRef(function({ columns: n = 4, cardsPerColumn: a = 3, className: o, ...s }, c) {
49
- return /* @__PURE__ */ r("div", {
50
- ref: c,
51
- ...s,
52
- className: e("flex gap-ds-05 overflow-x-auto", o),
53
- children: Array.from({ length: n }).map((e, n) => /* @__PURE__ */ i("div", {
68
+ l.displayName = "TableSkeleton";
69
+ var u = n.forwardRef(function({ columns: n = 4, cardsPerColumn: c = 3, className: l, label: u, ...d }, f) {
70
+ let p = a(n, 4), m = a(c, 3);
71
+ return /* @__PURE__ */ i("div", {
72
+ ref: f,
73
+ ...o(u),
74
+ ...d,
75
+ className: e("flex gap-ds-05 overflow-x-auto", l),
76
+ children: [/* @__PURE__ */ r(s, { label: u }), Array.from({ length: p }).map((e, n) => /* @__PURE__ */ i("div", {
54
77
  className: "flex w-[272px] shrink-0 flex-col gap-ds-03",
55
78
  children: [/* @__PURE__ */ i("div", {
56
79
  className: "flex items-center justify-between px-ds-02 py-ds-03",
57
80
  children: [/* @__PURE__ */ i("div", {
58
81
  className: "flex items-center gap-ds-03",
59
82
  children: [
60
- /* @__PURE__ */ r(t, { className: "h-ds-04 w-ds-04 rounded bg-surface-raised-hover" }),
61
- /* @__PURE__ */ r(t, { className: "h-ds-04 w-ds-11 bg-surface-raised-hover" }),
62
- /* @__PURE__ */ r(t, { className: "h-ds-05 w-ds-05b rounded-pill bg-surface-raised-hover" })
83
+ /* @__PURE__ */ r(t, { className: "h-ds-04 w-ds-04 rounded" }),
84
+ /* @__PURE__ */ r(t, { className: "h-ds-04 w-ds-11" }),
85
+ /* @__PURE__ */ r(t, { className: "h-ds-05 w-ds-05b rounded-pill" })
63
86
  ]
64
- }), /* @__PURE__ */ r(t, { className: "h-ico-sm w-ico-sm rounded bg-surface-raised-hover" })]
65
- }), Array.from({ length: a }).map((e, o) => /* @__PURE__ */ i("div", {
66
- className: "rounded-surface border border-card-strong bg-surface-raised p-ds-04",
67
- style: { animationDelay: `${(n * a + o) * 50}ms` },
87
+ }), /* @__PURE__ */ r(t, { className: "h-ico-sm w-ico-sm rounded" })]
88
+ }), Array.from({ length: m }).map((e, a) => /* @__PURE__ */ i("div", {
89
+ className: "rounded-surface border border-card bg-surface-raised p-ds-04",
68
90
  children: [/* @__PURE__ */ i("div", {
69
91
  className: "space-y-ds-03",
70
- children: [/* @__PURE__ */ r(t, { className: "h-ds-04 w-4/5 bg-surface-raised-hover" }), /* @__PURE__ */ r(t, { className: "h-ds-04 w-3/5 bg-surface-raised-hover" })]
92
+ children: [/* @__PURE__ */ r(t, { className: "h-ds-04 w-4/5" }), /* @__PURE__ */ r(t, { className: "h-ds-04 w-3/5" })]
71
93
  }), /* @__PURE__ */ i("div", {
72
94
  className: "flex items-center justify-between pt-ds-04",
73
95
  children: [/* @__PURE__ */ i("div", {
74
96
  className: "flex items-center gap-ds-02b",
75
- children: [/* @__PURE__ */ r(t, { className: "h-ico-md w-ico-md rounded-pill bg-surface-raised-hover" }), /* @__PURE__ */ r(t, { className: "h-ds-03 w-ds-10 bg-surface-raised-hover" })]
76
- }), /* @__PURE__ */ r(t, { className: "h-ds-05 w-ds-lg rounded-pill bg-surface-raised-hover" })]
97
+ children: [/* @__PURE__ */ r(t, { className: "h-ico-md w-ico-md rounded-pill" }), /* @__PURE__ */ r(t, { className: "h-ds-03 w-ds-10" })]
98
+ }), /* @__PURE__ */ r(t, { className: "h-ds-05 w-ds-lg rounded-pill" })]
77
99
  })]
78
- }, `card-${n}-${o}`))]
79
- }, `col-${n}`))
100
+ }, `card-${n}-${a}`))]
101
+ }, `col-${n}`))]
80
102
  });
81
103
  });
82
- s.displayName = "BoardSkeleton";
83
- var c = n.forwardRef(function({ rows: n = 6, showAvatar: a = !0, className: o, ...s }, c) {
84
- return /* @__PURE__ */ r("div", {
85
- ref: c,
86
- ...s,
87
- className: e("flex flex-col", o),
88
- children: Array.from({ length: n }).map((o, s) => /* @__PURE__ */ i("div", {
89
- className: e("flex items-center gap-ds-04 py-ds-04", s < n - 1 && "border-b border-surface-border-strong"),
90
- style: { animationDelay: `${s * 50}ms` },
104
+ u.displayName = "BoardSkeleton";
105
+ var d = n.forwardRef(function({ rows: n = 6, showAvatar: c = !0, className: l, label: u, ...d }, f) {
106
+ let p = a(n, 6);
107
+ return /* @__PURE__ */ i("div", {
108
+ ref: f,
109
+ ...o(u),
110
+ ...d,
111
+ className: e("flex flex-col", l),
112
+ children: [/* @__PURE__ */ r(s, { label: u }), Array.from({ length: p }).map((n, a) => /* @__PURE__ */ i("div", {
113
+ className: e("flex items-center gap-ds-04 py-ds-04", a < p - 1 && "border-b border-surface-border-strong"),
91
114
  children: [
92
- a && /* @__PURE__ */ r(t, { className: "h-ds-sm w-ds-sm shrink-0 rounded-pill bg-surface-raised-hover" }),
115
+ c && /* @__PURE__ */ r(t, { className: "h-ds-sm w-ds-sm shrink-0 rounded-pill" }),
93
116
  /* @__PURE__ */ i("div", {
94
117
  className: "flex flex-1 flex-col gap-ds-02b",
95
- children: [/* @__PURE__ */ r(t, { className: "h-ds-04 w-2/5 bg-surface-raised-hover" }), /* @__PURE__ */ r(t, { className: "h-ds-03 w-3/5 bg-surface-raised-hover" })]
118
+ children: [/* @__PURE__ */ r(t, { className: "h-ds-04 w-2/5" }), /* @__PURE__ */ r(t, { className: "h-ds-03 w-3/5" })]
96
119
  }),
97
- /* @__PURE__ */ r(t, { className: "h-ds-05b w-[56px] rounded-pill bg-surface-raised-hover" })
120
+ /* @__PURE__ */ r(t, { className: "h-ds-05b w-ds-09 rounded-pill" })
98
121
  ]
99
- }, `list-${s}`))
122
+ }, `list-${a}`))]
100
123
  });
101
124
  });
102
- c.displayName = "ListSkeleton";
125
+ d.displayName = "ListSkeleton";
103
126
  //#endregion
104
- export { s as BoardSkeleton, a as CardSkeleton, c as ListSkeleton, o as TableSkeleton };
127
+ export { u as BoardSkeleton, c as CardSkeleton, d as ListSkeleton, l as TableSkeleton };