@neasg/design-system 0.4.8 → 0.4.9

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 (115) hide show
  1. package/README.md +4 -4
  2. package/dist/alert.d.ts +21 -2
  3. package/dist/alert.js +10 -3
  4. package/dist/avatar.d.ts +5 -2
  5. package/dist/avatar.js +76 -8
  6. package/dist/back-button.d.ts +2 -0
  7. package/dist/back-button.js +1 -1
  8. package/dist/badge.d.ts +3 -2
  9. package/dist/badge.js +9 -3
  10. package/dist/breadcrumb.js +2 -1
  11. package/dist/button.d.ts +1 -1
  12. package/dist/button.js +12 -9
  13. package/dist/calendar.js +10 -9
  14. package/dist/card.d.ts +29 -1
  15. package/dist/card.js +61 -7
  16. package/dist/checkbox.d.ts +2 -0
  17. package/dist/checkbox.js +2 -2
  18. package/dist/close-button.d.ts +6 -0
  19. package/dist/close-button.js +8 -0
  20. package/dist/collapsible.d.ts +7 -1
  21. package/dist/collapsible.js +2 -2
  22. package/dist/command-search.d.ts +16 -1
  23. package/dist/command-search.js +42 -16
  24. package/dist/command.js +3 -3
  25. package/dist/copy-button.d.ts +3 -1
  26. package/dist/copy-button.js +4 -2
  27. package/dist/count-badge.d.ts +3 -1
  28. package/dist/count-badge.js +10 -5
  29. package/dist/date-input.d.ts +18 -3
  30. package/dist/date-input.js +94 -21
  31. package/dist/dialog-primitive.js +4 -3
  32. package/dist/draggable-tabs.d.ts +7 -0
  33. package/dist/draggable-tabs.js +6 -5
  34. package/dist/drawer.js +2 -2
  35. package/dist/dropdown-button.d.ts +18 -0
  36. package/dist/dropdown-button.js +31 -0
  37. package/dist/edit-button.d.ts +10 -0
  38. package/dist/edit-button.js +7 -0
  39. package/dist/editable-table.d.ts +3 -1
  40. package/dist/editable-table.js +25 -12
  41. package/dist/field.d.ts +2 -2
  42. package/dist/field.js +4 -3
  43. package/dist/file-upload-status-toast.d.ts +28 -0
  44. package/dist/file-upload-status-toast.js +136 -0
  45. package/dist/file-upload.js +8 -7
  46. package/dist/filter-popover.d.ts +37 -0
  47. package/dist/filter-popover.js +73 -0
  48. package/dist/filter-toggle.js +2 -2
  49. package/dist/index.d.ts +45 -14
  50. package/dist/index.js +19 -4
  51. package/dist/input-control.d.ts +3 -2
  52. package/dist/input-control.js +3 -2
  53. package/dist/label-value-grid.d.ts +4 -2
  54. package/dist/label-value-grid.js +7 -6
  55. package/dist/label-value.js +3 -1
  56. package/dist/layout-right-panel-edge.d.ts +6 -0
  57. package/dist/layout-right-panel-edge.js +6 -0
  58. package/dist/layout.d.ts +77 -5
  59. package/dist/layout.js +439 -35
  60. package/dist/lib/date-utils.d.ts +10 -2
  61. package/dist/lib/date-utils.js +91 -11
  62. package/dist/lib/utils.js +8 -1
  63. package/dist/link.js +2 -2
  64. package/dist/message-item.d.ts +62 -0
  65. package/dist/message-item.js +148 -0
  66. package/dist/multi-select.js +31 -5
  67. package/dist/notification.d.ts +82 -0
  68. package/dist/notification.js +121 -0
  69. package/dist/otp-input.js +1 -1
  70. package/dist/page-header.js +1 -1
  71. package/dist/page-section.d.ts +2 -1
  72. package/dist/page-section.js +4 -3
  73. package/dist/pagination.js +2 -2
  74. package/dist/popover-menu.d.ts +23 -1
  75. package/dist/popover-menu.js +75 -5
  76. package/dist/popover-primitive.js +1 -1
  77. package/dist/progress.d.ts +5 -2
  78. package/dist/progress.js +6 -3
  79. package/dist/radio-group.d.ts +21 -0
  80. package/dist/radio-group.js +41 -0
  81. package/dist/rich-text-editor.d.ts +56 -0
  82. package/dist/rich-text-editor.js +394 -0
  83. package/dist/routing-timeline.d.ts +22 -0
  84. package/dist/routing-timeline.js +58 -0
  85. package/dist/scroll-hint.d.ts +8 -0
  86. package/dist/scroll-hint.js +7 -0
  87. package/dist/search-input-shell.js +1 -1
  88. package/dist/search-input.js +2 -2
  89. package/dist/section-nav.js +4 -4
  90. package/dist/select-primitive.js +3 -3
  91. package/dist/select.js +1 -1
  92. package/dist/skeleton.js +1 -1
  93. package/dist/styles.css +235 -57
  94. package/dist/table-column-visibility.d.ts +21 -0
  95. package/dist/table-column-visibility.js +74 -0
  96. package/dist/table-toolbar.js +1 -1
  97. package/dist/table.d.ts +12 -1
  98. package/dist/table.js +67 -33
  99. package/dist/tabs.d.ts +14 -3
  100. package/dist/tabs.js +60 -6
  101. package/dist/tailwind-preset.js +46 -0
  102. package/dist/task-mode-shell.d.ts +24 -0
  103. package/dist/task-mode-shell.js +110 -0
  104. package/dist/textarea.js +2 -1
  105. package/dist/theme-switcher.d.ts +28 -0
  106. package/dist/theme-switcher.js +27 -0
  107. package/dist/theme.d.ts +167 -0
  108. package/dist/theme.js +112 -0
  109. package/dist/toaster.js +5 -4
  110. package/dist/tooltip.js +1 -1
  111. package/dist/typography.d.ts +1 -1
  112. package/dist/typography.js +5 -5
  113. package/dist/workspace-header.d.ts +13 -0
  114. package/dist/workspace-header.js +11 -0
  115. package/package.json +15 -1
package/dist/layout.js CHANGED
@@ -2,21 +2,87 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
5
+ import { GripVertical } from "lucide-react";
5
6
  import { ChevronDownIcon } from "./animated-icons/chevron-down";
6
7
  import { ChevronLeftIcon } from "./animated-icons/chevron-left";
7
8
  import { ChevronRightIcon } from "./animated-icons/chevron-right";
8
- import { Badge } from "./badge";
9
+ import { AvatarProfile } from "./avatar";
9
10
  import { Button } from "./button";
10
11
  import { CountBadge } from "./count-badge";
12
+ import { ScrollHint } from "./scroll-hint";
13
+ import { Tabs } from "./tabs";
11
14
  import { Tooltip } from "./tooltip";
15
+ import { Typography } from "./typography";
12
16
  import { cn } from "./lib/utils";
17
+ import { rightPanelEdgeClassName, rightPanelEdgeClosedClassName, rightPanelEdgeOpenClassName, rightPanelResizeHandleSurfaceClassName, } from "./layout-right-panel-edge";
13
18
  const COLLAPSE_BREAKPOINT = 1280;
19
+ const RIGHT_PANEL_AUTO_COLLAPSE_BREAKPOINT = 1600;
20
+ const RIGHT_PANEL_TRANSITION_MS = 300;
21
+ const RIGHT_PANEL_RESIZE_DEFAULT_WIDTH = 432;
22
+ const RIGHT_PANEL_RESIZE_MIN_WIDTH = 320;
23
+ const RIGHT_PANEL_RESIZE_MAX_WIDTH = 640;
24
+ const RIGHT_PANEL_FIXED_WIDTH_RATIO = 0.24;
25
+ const RIGHT_PANEL_SCROLL_HINT_THRESHOLD = 8;
26
+ const collapsedSidebarControlClassName = "h-control min-h-control w-control min-w-control max-w-control shrink-0 rounded-control p-0";
14
27
  const TOP_OFFSET_CSS_VAR = "--layout-top-offset";
15
28
  const SidebarContext = React.createContext(undefined);
16
29
  const useIsomorphicLayoutEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect;
17
- export function SidebarProvider({ children }) {
18
- const [isCollapsed, setIsCollapsed] = React.useState(false);
19
- const manualCollapsedRef = React.useRef(false);
30
+ function useScrollOverflowHint() {
31
+ const scrollRef = React.useRef(null);
32
+ const [canScrollDown, setCanScrollDown] = React.useState(false);
33
+ const updateScrollHint = React.useCallback(() => {
34
+ const node = scrollRef.current;
35
+ if (!node) {
36
+ setCanScrollDown(false);
37
+ return;
38
+ }
39
+ const nextCanScrollDown = node.scrollHeight - node.scrollTop - node.clientHeight >
40
+ RIGHT_PANEL_SCROLL_HINT_THRESHOLD;
41
+ setCanScrollDown((current) => current === nextCanScrollDown ? current : nextCanScrollDown);
42
+ }, []);
43
+ useIsomorphicLayoutEffect(() => {
44
+ updateScrollHint();
45
+ });
46
+ useIsomorphicLayoutEffect(() => {
47
+ const node = scrollRef.current;
48
+ if (!node) {
49
+ setCanScrollDown(false);
50
+ return undefined;
51
+ }
52
+ updateScrollHint();
53
+ node.addEventListener("scroll", updateScrollHint, { passive: true });
54
+ window.addEventListener("resize", updateScrollHint);
55
+ const resizeObserver = typeof ResizeObserver === "undefined"
56
+ ? undefined
57
+ : new ResizeObserver(() => updateScrollHint());
58
+ const mutationObserver = typeof MutationObserver === "undefined"
59
+ ? undefined
60
+ : new MutationObserver(() => updateScrollHint());
61
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(node);
62
+ Array.from(node.children).forEach((child) => {
63
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(child);
64
+ });
65
+ mutationObserver === null || mutationObserver === void 0 ? void 0 : mutationObserver.observe(node, {
66
+ childList: true,
67
+ characterData: true,
68
+ subtree: true,
69
+ });
70
+ return () => {
71
+ node.removeEventListener("scroll", updateScrollHint);
72
+ window.removeEventListener("resize", updateScrollHint);
73
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
74
+ mutationObserver === null || mutationObserver === void 0 ? void 0 : mutationObserver.disconnect();
75
+ };
76
+ }, [updateScrollHint]);
77
+ return { scrollRef, canScrollDown };
78
+ }
79
+ export function SidebarProvider({ children, defaultCollapsed = false, }) {
80
+ const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed);
81
+ const manualCollapsedRef = React.useRef(defaultCollapsed);
82
+ const collapse = React.useCallback(() => {
83
+ setIsCollapsed(true);
84
+ manualCollapsedRef.current = true;
85
+ }, []);
20
86
  const toggle = () => {
21
87
  setIsCollapsed((prev) => {
22
88
  const next = !prev;
@@ -37,7 +103,7 @@ export function SidebarProvider({ children }) {
37
103
  window.addEventListener("resize", handleResize);
38
104
  return () => window.removeEventListener("resize", handleResize);
39
105
  }, []);
40
- return (_jsx(SidebarContext.Provider, { value: { isCollapsed, toggle }, children: children }));
106
+ return (_jsx(SidebarContext.Provider, { value: { isCollapsed, toggle, collapse }, children: children }));
41
107
  }
42
108
  export function useSidebar() {
43
109
  const context = React.useContext(SidebarContext);
@@ -46,7 +112,7 @@ export function useSidebar() {
46
112
  }
47
113
  return context;
48
114
  }
49
- function DashboardLayout({ className, masthead, prototypeBanner, sidebar, surfaceClassName, contentClassName, children, style, ...props }) {
115
+ function DashboardLayout({ className, masthead, prototypeBanner, sidebar, rightPanel, surfaceClassName, contentClassName, rightPanelClassName, rightPanelFallbackTrigger, rightPanelMode, rightPanelResizable, rightPanelDefaultWidth, rightPanelMinWidth, rightPanelMaxWidth, rightPanelAutoCollapseSidebarBreakpoint, defaultSidebarCollapsed = false, children, style, ...props }) {
50
116
  const chromeRef = React.useRef(null);
51
117
  const [topOffset, setTopOffset] = React.useState(0);
52
118
  const layoutStyle = React.useMemo(() => ({
@@ -71,18 +137,18 @@ function DashboardLayout({ className, masthead, prototypeBanner, sidebar, surfac
71
137
  observer.observe(node);
72
138
  return () => observer.disconnect();
73
139
  }, [masthead, prototypeBanner]);
74
- return (_jsx(SidebarProvider, { children: _jsxs("div", { className: cn("flex min-h-screen flex-col bg-[hsl(var(--layout-shell-background))]", className), style: layoutStyle, ...props, children: [masthead || prototypeBanner ? (_jsxs("div", { ref: chromeRef, className: "sticky top-0 z-40 shrink-0", children: [masthead, prototypeBanner] })) : null, _jsxs("div", { className: "flex min-h-0 flex-1", children: [sidebar, _jsx(DashboardContent, { className: contentClassName, surfaceClassName: surfaceClassName, children: children })] })] }) }));
140
+ return (_jsx(SidebarProvider, { defaultCollapsed: defaultSidebarCollapsed, children: _jsxs("div", { className: cn("flex min-h-screen flex-col bg-[hsl(var(--layout-shell-background))]", className), style: layoutStyle, ...props, children: [masthead || prototypeBanner ? (_jsxs("div", { ref: chromeRef, className: "sticky top-0 z-40 shrink-0", children: [masthead, prototypeBanner] })) : null, _jsxs("div", { className: "flex min-h-0 flex-1", children: [sidebar, _jsx(DashboardContent, { className: contentClassName, hasSidebar: Boolean(sidebar), rightPanel: rightPanel, rightPanelClassName: rightPanelClassName, rightPanelFallbackTrigger: rightPanelFallbackTrigger, rightPanelMode: rightPanelMode, rightPanelResizable: rightPanelResizable, rightPanelDefaultWidth: rightPanelDefaultWidth, rightPanelMinWidth: rightPanelMinWidth, rightPanelMaxWidth: rightPanelMaxWidth, rightPanelAutoCollapseSidebarBreakpoint: rightPanelAutoCollapseSidebarBreakpoint, surfaceClassName: surfaceClassName, children: children })] })] }) }));
75
141
  }
76
142
  function SidebarShell({ isCollapsed, className, children, ...props }) {
77
- return (_jsx("aside", { className: cn("fixed left-0 top-[var(--layout-top-offset)] z-30 flex h-[calc(100dvh-var(--layout-top-offset))] shrink-0 flex-col overflow-hidden bg-[hsl(var(--layout-shell-background))] pb-2 pl-[var(--layout-sidebar-padding-inline)] pt-[var(--layout-sidebar-padding-top)] transition-all duration-300 ease-in-out", isCollapsed
78
- ? "w-[var(--layout-sidebar-collapsed-width)]"
79
- : "w-[var(--layout-sidebar-width)]", className), ...props, children: children }));
143
+ return (_jsx("aside", { className: cn("fixed left-0 top-[var(--layout-top-offset)] z-30 flex h-[calc(100dvh-var(--layout-top-offset))] shrink-0 flex-col bg-[hsl(var(--layout-sidebar-background))] pb-2 pt-[var(--layout-sidebar-padding-top)] transition-all duration-300 ease-in-out", isCollapsed
144
+ ? "w-[var(--layout-sidebar-collapsed-width)] overflow-visible px-[var(--layout-sidebar-padding-inline)]"
145
+ : "w-[var(--layout-sidebar-width)] overflow-hidden px-[var(--layout-sidebar-padding-inline)]", className), ...props, children: children }));
80
146
  }
81
147
  function SidebarHeader({ className, children, }) {
82
148
  return _jsx("div", { className: cn("shrink-0", className), children: children });
83
149
  }
84
150
  function SidebarContent({ className, children, }) {
85
- return (_jsx("div", { className: cn("flex-1 overflow-y-auto", className), children: children }));
151
+ return (_jsx("div", { className: cn("scrollbar-none flex-1 overflow-y-auto", className), children: children }));
86
152
  }
87
153
  function SidebarFooter({ className, children, }) {
88
154
  return _jsx("div", { className: cn("shrink-0", className), children: children });
@@ -91,20 +157,22 @@ function SidebarGroup({ className, children, }) {
91
157
  return _jsx("div", { className: className, children: children });
92
158
  }
93
159
  function SidebarGroupLabel({ className, children, }) {
94
- return (_jsx("p", { className: cn("px-3 py-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground", className), children: children }));
160
+ return (_jsx("p", { className: cn("px-2.5 py-1 text-xs font-normal text-muted-foreground/70", className), children: children }));
95
161
  }
96
162
  function SidebarMenu({ className, children, }) {
97
- return _jsx("ul", { className: cn("space-y-1", className), children: children });
163
+ return _jsx("ul", { className: cn("space-y-0.5", className), children: children });
98
164
  }
99
- function SidebarMenuItem({ className, children, }) {
100
- return _jsx("li", { className: className, children: children });
165
+ function SidebarMenuItem({ className, children, collapsed = false, }) {
166
+ return (_jsx("li", { className: cn(collapsed && "flex h-control w-full items-center justify-center", className), children: children }));
101
167
  }
102
- const SidebarMenuButton = React.forwardRef(({ active = false, collapsed = false, disabled = false, className, asChild = false, children, ...props }, ref) => {
103
- return (_jsx(Button, { ref: ref, asChild: asChild, variant: "ghost", disabled: disabled, className: cn("h-control w-full justify-start gap-3 rounded-lg text-sm font-medium shadow-none", collapsed ? "justify-center px-3" : "px-3", disabled
168
+ const SidebarMenuButton = React.forwardRef(({ active = false, collapsed = false, depth: _depth = 0, disabled = false, className, asChild = false, children, ...props }, ref) => {
169
+ return (_jsx(Button, { ref: ref, asChild: asChild, variant: "ghost", size: collapsed ? "icon" : "default", disabled: disabled, className: cn("relative text-sm font-medium shadow-none transition-[background-color,color,box-shadow] duration-150", collapsed
170
+ ? cn(collapsedSidebarControlClassName, "gap-0")
171
+ : "h-control w-full justify-start gap-2.5 px-3", disabled
104
172
  ? "text-muted-foreground/50 hover:bg-transparent hover:text-muted-foreground/50"
105
173
  : active
106
- ? "bg-white text-foreground hover:bg-white hover:text-foreground"
107
- : "text-muted-foreground hover:bg-white hover:text-foreground", className), ...props, children: children }));
174
+ ? "border-none bg-card text-card-foreground shadow-sm hover:bg-card hover:text-card-foreground"
175
+ : "text-muted-foreground hover:bg-card hover:text-foreground", className), ...props, children: children }));
108
176
  });
109
177
  SidebarMenuButton.displayName = "SidebarMenuButton";
110
178
  function isDropdownSidebarItem(item) {
@@ -126,10 +194,13 @@ function renderSidebarSlot(slot, isCollapsed) {
126
194
  return slot !== null && slot !== void 0 ? slot : null;
127
195
  }
128
196
  function DashboardSidebarItemButton({ item, isCollapsed, active, expanded, depth = 0, onClick, ariaExpanded, }) {
197
+ var _a;
129
198
  const Icon = item.icon;
130
199
  const iconRef = React.useRef(null);
131
- const showWipBadge = item.disabled || item.wip;
132
200
  const hasDropdown = isDropdownSidebarItem(item);
201
+ const hasCollapsedBadge = isCollapsed && item.badgeCount !== undefined;
202
+ const shouldRenderIconSlot = Boolean(Icon) || isCollapsed;
203
+ const collapsedBadge = hasCollapsedBadge ? (_jsx(CountBadge, { count: (_a = item.badgeCount) !== null && _a !== void 0 ? _a : 0, max: 9, variant: item.badgeVariant, size: "sm", pulse: item.badgePulse, className: "pointer-events-none absolute -right-1.5 -top-1.5 z-10" })) : null;
133
204
  const handleMouseEnter = () => {
134
205
  var _a, _b, _c;
135
206
  if (!item.disabled) {
@@ -144,15 +215,24 @@ function DashboardSidebarItemButton({ item, isCollapsed, active, expanded, depth
144
215
  (_c = item.onHoverEnd) === null || _c === void 0 ? void 0 : _c.call(item);
145
216
  }
146
217
  };
147
- const content = (_jsxs(_Fragment, { children: [Icon ? (_jsxs("div", { className: "relative flex h-5 w-5 shrink-0 items-center justify-center", children: [_jsx(Icon, { ref: iconRef, size: 16 }), isCollapsed && item.badgeCount !== undefined ? (_jsx(CountBadge, { count: item.badgeCount, variant: item.badgeVariant, size: "sm", pulse: item.badgePulse, className: "absolute -right-2 -top-2" })) : null] })) : (_jsxs("div", { "aria-hidden": "true", className: "relative flex h-5 w-5 shrink-0 items-center justify-center", children: [_jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current/35" }), isCollapsed && item.badgeCount !== undefined ? (_jsx(CountBadge, { count: item.badgeCount, variant: item.badgeVariant, size: "sm", pulse: item.badgePulse, className: "absolute -right-2 -top-2" })) : null] })), !isCollapsed ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex-1 truncate text-left", children: item.label }), showWipBadge ? _jsx(Badge, { variant: "muted", children: "WIP" }) : null, item.trailing, item.badgeCount !== undefined ? (_jsx(CountBadge, { count: item.badgeCount, variant: item.badgeVariant, size: "md", pulse: item.badgePulse })) : null, hasDropdown ? (_jsx(ChevronDownIcon, { "aria-hidden": "true", className: cn("shrink-0 text-muted-foreground transition-transform duration-200", expanded && "rotate-180 text-foreground"), size: 16 })) : null] })) : null] }));
148
- const tooltipLabel = `${item.label}${showWipBadge ? " (WIP)" : ""}`;
149
- const button = (_jsx(SidebarMenuButton, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleMouseEnter, onBlur: handleMouseLeave, onClick: onClick, disabled: item.disabled, active: active, collapsed: isCollapsed, "aria-current": active && !hasDropdown ? "page" : undefined, "aria-expanded": ariaExpanded, "aria-label": isCollapsed ? tooltipLabel : undefined, children: content }));
150
- const interactive = !hasDropdown && item.href && !item.disabled ? (_jsx(SidebarMenuButton, { asChild: true, onClick: item.onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleMouseEnter, onBlur: handleMouseLeave, active: active, collapsed: isCollapsed, "aria-current": active ? "page" : undefined, "aria-label": isCollapsed ? tooltipLabel : undefined, children: _jsx("a", { href: item.href, target: item.target, rel: item.rel, children: content }) })) : (button);
218
+ const content = (_jsxs(_Fragment, { children: [Icon ? (_jsx("div", { className: cn("relative flex h-6 w-6 shrink-0 items-center justify-center transition-transform", hasCollapsedBadge && "translate-y-0.5"), children: _jsx(Icon, { ref: iconRef, size: 18 }) })) : shouldRenderIconSlot ? (_jsx("div", { "aria-hidden": "true", className: cn("relative flex h-6 w-6 shrink-0 items-center justify-center transition-transform", hasCollapsedBadge && "translate-y-0.5"), children: _jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current/35" }) })) : null, !isCollapsed ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex-1 truncate text-left", children: item.label }), item.trailing, item.badgeCount !== undefined ? (_jsx(CountBadge, { count: item.badgeCount, variant: item.badgeVariant, size: "md", pulse: item.badgePulse })) : null, hasDropdown ? (_jsx(ChevronDownIcon, { "aria-hidden": "true", className: cn("shrink-0 text-muted-foreground transition-transform duration-200", expanded && "rotate-180 text-foreground"), size: 18 })) : null] })) : null] }));
219
+ const tooltipLabel = item.label;
220
+ const button = (_jsx(SidebarMenuButton, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleMouseEnter, onBlur: handleMouseLeave, onClick: onClick, disabled: item.disabled, active: active, collapsed: isCollapsed, depth: depth, "aria-current": active && !hasDropdown ? "page" : undefined, "aria-expanded": ariaExpanded, "aria-label": isCollapsed ? tooltipLabel : undefined, children: content }));
221
+ const interactive = !hasDropdown && item.href && !item.disabled ? (_jsx(SidebarMenuButton, { asChild: true, onClick: item.onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleMouseEnter, onBlur: handleMouseLeave, active: active, collapsed: isCollapsed, depth: depth, "aria-current": active ? "page" : undefined, "aria-label": isCollapsed ? tooltipLabel : undefined, children: _jsx("a", { href: item.href, target: item.target, rel: item.rel, children: content }) })) : (button);
151
222
  if (isCollapsed) {
152
- return (_jsx(Tooltip, { side: "right", content: _jsx("p", { children: tooltipLabel }), children: item.disabled ? (_jsx("span", { className: "block w-full cursor-not-allowed", children: interactive })) : (interactive) }));
223
+ return (_jsx(Tooltip, { side: "right", content: _jsx("p", { children: tooltipLabel }), children: _jsxs("span", { className: cn("relative inline-flex h-control w-control shrink-0 items-center justify-center overflow-visible", item.disabled && "cursor-not-allowed"), children: [interactive, collapsedBadge] }) }));
153
224
  }
154
225
  return interactive;
155
226
  }
227
+ function DashboardSidebarProfile({ isCollapsed = false, status = "online", name, role, rolePlacement = "below", size = "sm", ...props }) {
228
+ const statusClassName = {
229
+ online: "bg-primary",
230
+ busy: "bg-[hsl(var(--status-warning-foreground))]",
231
+ offline: "bg-muted-foreground",
232
+ none: "",
233
+ }[status];
234
+ return (_jsx("div", { className: cn(isCollapsed ? "px-0" : "px-2", "pb-4 pt-2"), children: _jsx(AvatarProfile, { ...props, size: size, name: isCollapsed ? undefined : name, role: isCollapsed ? undefined : role, rolePlacement: rolePlacement, className: cn("rounded-control px-2 py-2 text-muted-foreground transition-colors hover:bg-card hover:text-foreground", isCollapsed ? "justify-center px-0" : "min-w-0"), avatarClassName: "h-9 w-9 ring-1 ring-border/60 shadow-sm", fallbackClassName: "bg-background text-foreground", avatarOverlay: status === "none" ? undefined : (_jsx("span", { className: cn("absolute bottom-0 right-0 h-3 w-3 rounded-full border-2 border-[hsl(var(--layout-sidebar-background))] shadow-sm", statusClassName) })) }) }));
235
+ }
156
236
  function DashboardSidebarLeafItem({ item, isCollapsed, depth = 0, }) {
157
237
  return (_jsx(DashboardSidebarItemButton, { item: item, isCollapsed: isCollapsed, active: sidebarItemIsActive(item), depth: depth, onClick: item.onClick }));
158
238
  }
@@ -192,7 +272,7 @@ function DashboardSidebarDropdownItem({ item, isCollapsed, depth = 0, }) {
192
272
  }
193
273
  handleOpenChange(!expanded);
194
274
  }, [expanded, handleOpenChange, isCollapsed, item.disabled, setExpanded, toggle]);
195
- return (_jsxs(CollapsiblePrimitive.Root, { open: expanded, onOpenChange: handleOpenChange, children: [_jsx(DashboardSidebarItemButton, { item: item, isCollapsed: isCollapsed, active: item.active || hasActiveDescendant, expanded: expanded, depth: depth, onClick: handleClick, ariaExpanded: isCollapsed ? undefined : expanded }), !isCollapsed ? (_jsx(CollapsiblePrimitive.Content, { className: "overflow-hidden", children: _jsx("div", { className: "ml-5 mt-1 border-l border-border/70 pl-2", children: _jsx(SidebarMenu, { className: "space-y-1", children: item.items.map((child) => (_jsx(SidebarMenuItem, { children: _jsx(DashboardSidebarItem, { item: child, isCollapsed: false, depth: depth + 1 }) }, child.id))) }) }) })) : null] }));
275
+ return (_jsxs(CollapsiblePrimitive.Root, { open: expanded, onOpenChange: handleOpenChange, children: [_jsx(DashboardSidebarItemButton, { item: item, isCollapsed: isCollapsed, active: item.active || hasActiveDescendant, expanded: expanded, depth: depth, onClick: handleClick, ariaExpanded: isCollapsed ? undefined : expanded }), !isCollapsed ? (_jsx(CollapsiblePrimitive.Content, { className: "overflow-hidden", children: _jsx("div", { className: "ml-5 mt-1 border-l border-[hsl(var(--layout-sidebar-border))] pl-2", children: _jsx(SidebarMenu, { className: "space-y-1", children: item.items.map((child) => (_jsx(SidebarMenuItem, { collapsed: isCollapsed, children: _jsx(DashboardSidebarItem, { item: child, isCollapsed: false, depth: depth + 1 }) }, child.id))) }) }) })) : null] }));
196
276
  }
197
277
  function DashboardSidebarItem({ item, isCollapsed, depth = 0, }) {
198
278
  if (isDropdownSidebarItem(item)) {
@@ -211,20 +291,344 @@ function DashboardSidebar({ className, children, logo, search, navGroups, footer
211
291
  if (!hasStructuredSidebar) {
212
292
  return (_jsx(SidebarShell, { isCollapsed: isCollapsed, className: className, ...props, children: children }));
213
293
  }
214
- return (_jsxs(SidebarShell, { isCollapsed: isCollapsed, className: className, ...props, children: [_jsxs(SidebarHeader, { className: cn("flex h-14 items-center gap-2", isCollapsed ? "justify-center px-2" : "justify-between px-3"), children: [renderSidebarSlot(logo, isCollapsed), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": toggleAriaLabel, className: "h-7 w-7 shrink-0", onClick: toggle, children: isCollapsed ? (_jsx(ChevronRightIcon, { size: 16 })) : (_jsx(ChevronLeftIcon, { size: 16 })) })] }), search ? (_jsx(SidebarHeader, { className: "px-2 pb-3 pt-2", children: renderSidebarSlot(search, isCollapsed) })) : null, search || ((_a = navGroups === null || navGroups === void 0 ? void 0 : navGroups.length) !== null && _a !== void 0 ? _a : 0) > 0 ? (_jsx(SidebarHeader, { className: "mx-2 mb-2 border-t" })) : null, (navGroups === null || navGroups === void 0 ? void 0 : navGroups.length) ? (_jsx(SidebarContent, { className: "p-2", children: _jsx("nav", { "aria-label": "Sidebar navigation", children: navGroups.map((group, groupIndex) => {
294
+ return (_jsxs(SidebarShell, { isCollapsed: isCollapsed, className: className, ...props, children: [_jsxs(SidebarHeader, { className: cn("flex h-14 items-center gap-2", isCollapsed ? "justify-center px-0" : "justify-between px-3"), children: [renderSidebarSlot(logo, isCollapsed), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": toggleAriaLabel, className: cn("shrink-0 rounded-control", isCollapsed ? collapsedSidebarControlClassName : "h-7 w-7"), onClick: toggle, children: isCollapsed ? (_jsx(ChevronRightIcon, { size: 16 })) : (_jsx(ChevronLeftIcon, { size: 16 })) })] }), search ? (_jsx(SidebarHeader, { className: cn(isCollapsed
295
+ ? "flex justify-center px-0 pb-3 pt-2"
296
+ : "px-2 pb-3 pt-2"), children: renderSidebarSlot(search, isCollapsed) })) : null, search || ((_a = navGroups === null || navGroups === void 0 ? void 0 : navGroups.length) !== null && _a !== void 0 ? _a : 0) > 0 ? (_jsx(SidebarHeader, { className: "mx-2 mb-2 border-t border-[hsl(var(--layout-sidebar-border))]" })) : null, (navGroups === null || navGroups === void 0 ? void 0 : navGroups.length) ? (_jsx(SidebarContent, { className: cn(isCollapsed
297
+ ? "overflow-visible p-0"
298
+ : "p-[var(--layout-sidebar-content-padding)]"), children: _jsx("nav", { "aria-label": "Sidebar navigation", children: navGroups.map((group, groupIndex) => {
215
299
  var _a;
216
- return (_jsxs(SidebarGroup, { children: [isCollapsed && groupIndex > 0 ? (_jsx("div", { className: "mx-2 my-2 border-t" })) : null, _jsxs("div", { className: cn(!isCollapsed && groupIndex > 0 && "mt-4"), children: [!isCollapsed && group.label ? (_jsx(SidebarGroupLabel, { children: group.label })) : null, _jsx(SidebarMenu, { children: group.items.map((item) => (_jsx(SidebarMenuItem, { children: _jsx(DashboardSidebarItem, { item: item, isCollapsed: isCollapsed }) }, item.id))) })] })] }, `${(_a = group.label) !== null && _a !== void 0 ? _a : "group"}-${groupIndex}`));
217
- }) }) })) : null, (footerItems === null || footerItems === void 0 ? void 0 : footerItems.length) ? (_jsx(SidebarFooter, { className: "px-2 py-1", children: _jsx(SidebarMenu, { children: footerItems.map((item) => (_jsx(SidebarMenuItem, { children: _jsx(DashboardSidebarItem, { item: item, isCollapsed: isCollapsed }) }, item.id))) }) })) : null, footer ? _jsx(SidebarFooter, { className: "mx-2 mt-2 border-t pt-2" }) : null, footer ? (_jsx(SidebarFooter, { children: renderSidebarSlot(footer, isCollapsed) })) : null] }));
300
+ return (_jsxs(SidebarGroup, { children: [isCollapsed && groupIndex > 0 ? (_jsx("div", { className: "mx-2 my-2 border-t border-[hsl(var(--layout-sidebar-border))]" })) : null, _jsxs("div", { className: cn(!isCollapsed &&
301
+ groupIndex > 0 &&
302
+ "mt-[var(--layout-sidebar-section-gap)]"), children: [!isCollapsed && group.label ? (_jsx(SidebarGroupLabel, { children: group.label })) : null, _jsx(SidebarMenu, { children: group.items.map((item) => (_jsx(SidebarMenuItem, { collapsed: isCollapsed, children: _jsx(DashboardSidebarItem, { item: item, isCollapsed: isCollapsed }) }, item.id))) })] })] }, `${(_a = group.label) !== null && _a !== void 0 ? _a : "group"}-${groupIndex}`));
303
+ }) }) })) : null, (footerItems === null || footerItems === void 0 ? void 0 : footerItems.length) ? (_jsx(SidebarFooter, { className: cn(isCollapsed ? "px-0 py-1" : "px-1.5 py-1"), children: _jsx(SidebarMenu, { children: footerItems.map((item) => (_jsx(SidebarMenuItem, { collapsed: isCollapsed, children: _jsx(DashboardSidebarItem, { item: item, isCollapsed: isCollapsed }) }, item.id))) }) })) : null, footer ? _jsx(SidebarFooter, { className: "mx-1.5 mt-1.5 border-t border-[hsl(var(--layout-sidebar-border))] pt-1.5" }) : null, footer ? (_jsx(SidebarFooter, { children: renderSidebarSlot(footer, isCollapsed) })) : null] }));
218
304
  }
219
- function DashboardContent({ className, surfaceClassName, children, ...props }) {
220
- const { isCollapsed, toggle } = useSidebar();
305
+ function DashboardRightPanelSection({ className, title, description, titleClassName, descriptionClassName, children, ...props }) {
306
+ return (_jsxs("section", { className: cn("space-y-[var(--layout-right-panel-section-gap)]", className), ...props, children: [title || description ? (_jsxs("div", { className: "space-y-[var(--layout-right-panel-heading-gap)]", children: [title ? (_jsx(Typography, { as: "h3", variant: "body", className: cn("font-semibold", titleClassName), children: title })) : null, description ? (_jsx(Typography, { as: "p", variant: "caption", className: descriptionClassName, children: description })) : null] })) : null, children] }));
307
+ }
308
+ function DashboardRightPanelTabs({ className, listWrapperClassName, panelClassName, ...props }) {
309
+ return (_jsx(Tabs, { className: cn("flex min-h-0 flex-1 flex-col space-y-0", className), listWrapperClassName: cn("scrollbar-none w-full min-w-0 max-w-full shrink-0 self-stretch overflow-x-auto overflow-y-hidden px-[var(--layout-right-panel-padding)] pb-[var(--layout-right-panel-tabs-gap)] pt-[var(--layout-right-panel-padding)]", listWrapperClassName), panelClassName: cn("min-h-0 flex-1 flex-col overflow-hidden pt-0 data-[state=active]:flex", panelClassName), ...props }));
310
+ }
311
+ function DashboardRightPanel({ className, ...props }) {
312
+ return (_jsx("div", { className: cn("flex min-h-0 flex-1 flex-col bg-[hsl(var(--layout-right-panel-background))]", className), ...props }));
313
+ }
314
+ function DashboardRightPanelHeader({ className, title, subtitle, badge, action, children, ...props }) {
315
+ return (_jsx("div", { className: cn("shrink-0 p-[var(--layout-right-panel-padding)]", className), ...props, children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Typography, { as: "h2", variant: "body", className: "font-semibold", children: title }), badge] }), subtitle ? (_jsx(Typography, { as: "p", variant: "caption", children: subtitle })) : null, children] }), action ? _jsx("div", { className: "shrink-0", children: action }) : null] }) }));
316
+ }
317
+ function DashboardRightPanelBody({ className, contentClassName, footer, footerClassName, children, ...props }) {
318
+ const { scrollRef, canScrollDown } = useScrollOverflowHint();
319
+ if (footer) {
320
+ return (_jsxs("div", { className: cn("flex min-h-0 flex-1 flex-col overflow-hidden p-[var(--layout-right-panel-padding)]", className), ...props, children: [_jsxs("div", { className: "relative min-h-0 flex-1", children: [_jsx("div", { ref: scrollRef, className: cn("scrollbar-none h-full min-h-0 space-y-[var(--layout-right-panel-gap)] overflow-y-auto", contentClassName), children: children }), _jsx(ScrollHint, { visible: canScrollDown })] }), _jsx("div", { className: cn("shrink-0 space-y-[var(--layout-right-panel-footer-gap)] pt-[var(--layout-right-panel-gap)]", footerClassName), children: footer })] }));
321
+ }
322
+ return (_jsxs("div", { className: "relative min-h-0 flex-1", children: [_jsx("div", { ref: scrollRef, className: cn("scrollbar-none h-full min-h-0 space-y-[var(--layout-right-panel-gap)] overflow-y-auto p-[var(--layout-right-panel-padding)]", className), ...props, children: children }), _jsx(ScrollHint, { visible: canScrollDown })] }));
323
+ }
324
+ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanelClassName, rightPanelFallbackTrigger, rightPanelMode = "responsive", rightPanelResizable = false, rightPanelDefaultWidth = RIGHT_PANEL_RESIZE_DEFAULT_WIDTH, rightPanelMinWidth = RIGHT_PANEL_RESIZE_MIN_WIDTH, rightPanelMaxWidth = RIGHT_PANEL_RESIZE_MAX_WIDTH, rightPanelAutoCollapseSidebarBreakpoint = RIGHT_PANEL_AUTO_COLLAPSE_BREAKPOINT, surfaceClassName, children, ...props }) {
325
+ const { isCollapsed, toggle, collapse } = useSidebar();
326
+ const hasRightPanel = Boolean(rightPanel);
327
+ const persistentRightPanelMinWidth = Math.min(rightPanelMinWidth, rightPanelMaxWidth);
328
+ const persistentRightPanelMaxWidth = Math.max(rightPanelMinWidth, rightPanelMaxWidth);
329
+ const [persistentRightPanelWidth, setPersistentRightPanelWidth] = React.useState(rightPanelDefaultWidth);
330
+ const persistentRightPanelWidthRef = React.useRef(persistentRightPanelWidth);
331
+ const workspaceSurfaceRef = React.useRef(null);
332
+ const persistentRightPanelSlotRef = React.useRef(null);
333
+ const persistentRightPanelSurfaceRef = React.useRef(null);
334
+ const [renderedRightPanel, setRenderedRightPanel] = React.useState(rightPanel);
335
+ const [shouldRenderRightPanel, setShouldRenderRightPanel] = React.useState(hasRightPanel);
336
+ const [rightPanelOpen, setRightPanelOpen] = React.useState(hasRightPanel);
337
+ const [rightPanelOverlayOpen, setRightPanelOverlayOpen] = React.useState(false);
338
+ const [fixedRightPanelWidth, setFixedRightPanelWidth] = React.useState(null);
339
+ const wasRightPanelVisibleRef = React.useRef(hasRightPanel);
340
+ const isCollapsedRef = React.useRef(isCollapsed);
341
+ const hasPersistentRightPanel = rightPanelMode === "persistent" && shouldRenderRightPanel;
342
+ const isPersistentRightPanelResizable = hasPersistentRightPanel && rightPanelResizable;
343
+ const firstChild = React.Children.toArray(children).find((child) => child !== null && child !== undefined);
344
+ const hasLeadingWorkspaceHeader = React.isValidElement(firstChild) &&
345
+ firstChild.type.displayName ===
346
+ "WorkspaceHeader";
347
+ React.useEffect(() => {
348
+ isCollapsedRef.current = isCollapsed;
349
+ }, [isCollapsed]);
350
+ React.useEffect(() => {
351
+ persistentRightPanelWidthRef.current = persistentRightPanelWidth;
352
+ }, [persistentRightPanelWidth]);
353
+ const getPersistentRightPanelGridTemplate = React.useCallback((width) => `minmax(0, 1fr) ${width}px`, []);
354
+ const getFixedPersistentRightPanelGridTemplate = React.useCallback((width, isOpen) => `minmax(0, 1fr) ${isOpen
355
+ ? width
356
+ ? `${width}px`
357
+ : `${RIGHT_PANEL_FIXED_WIDTH_RATIO * 100}%`
358
+ : "0px"}`, []);
359
+ const measureFixedRightPanelWidth = React.useCallback(() => {
360
+ var _a, _b;
361
+ const surfaceWidth = (_b = (_a = workspaceSurfaceRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) !== null && _b !== void 0 ? _b : 0;
362
+ if (surfaceWidth <= 0) {
363
+ return null;
364
+ }
365
+ return Math.round(surfaceWidth * RIGHT_PANEL_FIXED_WIDTH_RATIO);
366
+ }, []);
367
+ useIsomorphicLayoutEffect(() => {
368
+ if (!isPersistentRightPanelResizable) {
369
+ return;
370
+ }
371
+ const width = `${persistentRightPanelWidth}px`;
372
+ if (workspaceSurfaceRef.current) {
373
+ workspaceSurfaceRef.current.style.gridTemplateColumns =
374
+ getPersistentRightPanelGridTemplate(rightPanelOpen ? persistentRightPanelWidth : 0);
375
+ }
376
+ if (persistentRightPanelSurfaceRef.current) {
377
+ persistentRightPanelSurfaceRef.current.style.width = width;
378
+ }
379
+ }, [
380
+ getPersistentRightPanelGridTemplate,
381
+ isPersistentRightPanelResizable,
382
+ persistentRightPanelWidth,
383
+ rightPanelOpen,
384
+ ]);
385
+ useIsomorphicLayoutEffect(() => {
386
+ if (!hasPersistentRightPanel ||
387
+ isPersistentRightPanelResizable ||
388
+ !rightPanelOpen ||
389
+ !workspaceSurfaceRef.current) {
390
+ return undefined;
391
+ }
392
+ const measureRightPanel = () => {
393
+ const nextWidth = measureFixedRightPanelWidth();
394
+ if (!nextWidth) {
395
+ return;
396
+ }
397
+ setFixedRightPanelWidth((currentWidth) => currentWidth === nextWidth ? currentWidth : nextWidth);
398
+ };
399
+ measureRightPanel();
400
+ const resizeObserver = typeof ResizeObserver === "undefined"
401
+ ? undefined
402
+ : new ResizeObserver(measureRightPanel);
403
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(workspaceSurfaceRef.current);
404
+ window.addEventListener("resize", measureRightPanel);
405
+ return () => {
406
+ resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
407
+ window.removeEventListener("resize", measureRightPanel);
408
+ };
409
+ }, [
410
+ hasPersistentRightPanel,
411
+ isPersistentRightPanelResizable,
412
+ measureFixedRightPanelWidth,
413
+ rightPanelOpen,
414
+ ]);
415
+ React.useEffect(() => {
416
+ if (!rightPanelResizable) {
417
+ return;
418
+ }
419
+ setPersistentRightPanelWidth((width) => Math.min(Math.max(width, persistentRightPanelMinWidth), persistentRightPanelMaxWidth));
420
+ }, [
421
+ persistentRightPanelMaxWidth,
422
+ persistentRightPanelMinWidth,
423
+ rightPanelResizable,
424
+ ]);
425
+ useIsomorphicLayoutEffect(() => {
426
+ let frame = 0;
427
+ let nextFrame = 0;
428
+ let timeout = 0;
429
+ if (rightPanelMode === "persistent") {
430
+ setRightPanelOverlayOpen(false);
431
+ }
432
+ if (hasRightPanel) {
433
+ if (rightPanelMode === "persistent" && !rightPanelResizable) {
434
+ const nextFixedRightPanelWidth = measureFixedRightPanelWidth();
435
+ if (nextFixedRightPanelWidth) {
436
+ setFixedRightPanelWidth((currentWidth) => currentWidth === nextFixedRightPanelWidth
437
+ ? currentWidth
438
+ : nextFixedRightPanelWidth);
439
+ }
440
+ }
441
+ if (rightPanelAutoCollapseSidebarBreakpoint !== false &&
442
+ !isCollapsedRef.current &&
443
+ window.innerWidth < rightPanelAutoCollapseSidebarBreakpoint) {
444
+ collapse();
445
+ }
446
+ setRenderedRightPanel(rightPanel);
447
+ setShouldRenderRightPanel(true);
448
+ if (wasRightPanelVisibleRef.current) {
449
+ setRightPanelOpen(true);
450
+ }
451
+ else {
452
+ setRightPanelOpen(false);
453
+ frame = window.requestAnimationFrame(() => {
454
+ nextFrame = window.requestAnimationFrame(() => {
455
+ setRightPanelOpen(true);
456
+ });
457
+ });
458
+ }
459
+ }
460
+ else if (wasRightPanelVisibleRef.current) {
461
+ setRightPanelOpen(false);
462
+ setRightPanelOverlayOpen(false);
463
+ timeout = window.setTimeout(() => {
464
+ setShouldRenderRightPanel(false);
465
+ setRenderedRightPanel(null);
466
+ }, RIGHT_PANEL_TRANSITION_MS);
467
+ }
468
+ else {
469
+ setShouldRenderRightPanel(false);
470
+ setRenderedRightPanel(null);
471
+ setRightPanelOverlayOpen(false);
472
+ }
473
+ wasRightPanelVisibleRef.current = hasRightPanel;
474
+ return () => {
475
+ if (frame) {
476
+ window.cancelAnimationFrame(frame);
477
+ }
478
+ if (nextFrame) {
479
+ window.cancelAnimationFrame(nextFrame);
480
+ }
481
+ if (timeout) {
482
+ window.clearTimeout(timeout);
483
+ }
484
+ };
485
+ }, [
486
+ collapse,
487
+ hasRightPanel,
488
+ rightPanel,
489
+ rightPanelMode,
490
+ rightPanelResizable,
491
+ measureFixedRightPanelWidth,
492
+ rightPanelAutoCollapseSidebarBreakpoint,
493
+ ]);
494
+ React.useEffect(() => {
495
+ if (rightPanelMode !== "persistent" ||
496
+ !hasRightPanel ||
497
+ rightPanelAutoCollapseSidebarBreakpoint === false) {
498
+ return undefined;
499
+ }
500
+ const maybeCollapseSidebar = () => {
501
+ if (!isCollapsedRef.current &&
502
+ window.innerWidth < rightPanelAutoCollapseSidebarBreakpoint) {
503
+ collapse();
504
+ }
505
+ };
506
+ maybeCollapseSidebar();
507
+ window.addEventListener("resize", maybeCollapseSidebar);
508
+ return () => window.removeEventListener("resize", maybeCollapseSidebar);
509
+ }, [
510
+ collapse,
511
+ hasRightPanel,
512
+ rightPanelMode,
513
+ rightPanelAutoCollapseSidebarBreakpoint,
514
+ ]);
221
515
  const handleContentClick = React.useCallback(() => {
222
516
  if (!isCollapsed && window.innerWidth < COLLAPSE_BREAKPOINT) {
223
517
  toggle();
224
518
  }
225
519
  }, [isCollapsed, toggle]);
226
- return (_jsx("main", { onClick: handleContentClick, className: cn("flex min-h-[calc(100dvh-var(--layout-top-offset))] min-w-0 flex-1 flex-col bg-[hsl(var(--layout-shell-background))] pb-[var(--layout-content-padding)] pl-[var(--layout-content-gap-start)] pr-[var(--layout-content-padding)] pt-[var(--layout-content-padding)] transition-all duration-300 md:pb-[var(--layout-content-padding-md)] md:pl-[var(--layout-content-gap-start-md)] md:pr-[var(--layout-content-padding-md)] md:pt-[var(--layout-content-padding-md)] lg:pb-[var(--layout-content-padding-lg)] lg:pl-[var(--layout-content-gap-start-lg)] lg:pr-[var(--layout-content-padding-lg)] lg:pt-[var(--layout-content-padding-lg)]", isCollapsed
227
- ? "ml-[var(--layout-sidebar-collapsed-width)]"
228
- : "ml-[var(--layout-sidebar-width)]", className), ...props, children: _jsx("div", { className: cn("flex flex-1 flex-col gap-[var(--layout-surface-gap)] overflow-x-clip rounded-[var(--radius-lg)] bg-background p-[var(--layout-surface-padding)] shadow-sm md:p-[var(--layout-surface-padding-md)] lg:p-[var(--layout-surface-padding-lg)]", surfaceClassName), children: children }) }));
520
+ const handleRightPanelResizePointerDown = React.useCallback((event) => {
521
+ if (!isPersistentRightPanelResizable) {
522
+ return;
523
+ }
524
+ event.preventDefault();
525
+ const startX = event.clientX;
526
+ const startWidth = persistentRightPanelWidthRef.current;
527
+ const previousCursor = document.body.style.cursor;
528
+ const previousUserSelect = document.body.style.userSelect;
529
+ document.body.style.cursor = "col-resize";
530
+ document.body.style.userSelect = "none";
531
+ let pendingWidth = startWidth;
532
+ let frame = 0;
533
+ const applyPendingWidth = () => {
534
+ frame = 0;
535
+ persistentRightPanelWidthRef.current = pendingWidth;
536
+ if (workspaceSurfaceRef.current) {
537
+ workspaceSurfaceRef.current.style.gridTemplateColumns =
538
+ getPersistentRightPanelGridTemplate(pendingWidth);
539
+ }
540
+ if (persistentRightPanelSurfaceRef.current) {
541
+ persistentRightPanelSurfaceRef.current.style.width = `${pendingWidth}px`;
542
+ }
543
+ };
544
+ const handlePointerMove = (moveEvent) => {
545
+ pendingWidth = Math.min(Math.max(startWidth + startX - moveEvent.clientX, persistentRightPanelMinWidth), persistentRightPanelMaxWidth);
546
+ if (!frame) {
547
+ frame = window.requestAnimationFrame(applyPendingWidth);
548
+ }
549
+ };
550
+ const finishResize = () => {
551
+ if (frame) {
552
+ window.cancelAnimationFrame(frame);
553
+ applyPendingWidth();
554
+ }
555
+ document.body.style.cursor = previousCursor;
556
+ document.body.style.userSelect = previousUserSelect;
557
+ window.removeEventListener("pointermove", handlePointerMove);
558
+ window.removeEventListener("pointerup", finishResize);
559
+ window.removeEventListener("pointercancel", finishResize);
560
+ setPersistentRightPanelWidth(pendingWidth);
561
+ };
562
+ window.addEventListener("pointermove", handlePointerMove);
563
+ window.addEventListener("pointerup", finishResize, { once: true });
564
+ window.addEventListener("pointercancel", finishResize, { once: true });
565
+ }, [
566
+ getPersistentRightPanelGridTemplate,
567
+ isPersistentRightPanelResizable,
568
+ persistentRightPanelMaxWidth,
569
+ persistentRightPanelMinWidth,
570
+ ]);
571
+ const workspaceSurfaceStyle = React.useMemo(() => {
572
+ if (!hasPersistentRightPanel) {
573
+ return undefined;
574
+ }
575
+ if (!isPersistentRightPanelResizable) {
576
+ return {
577
+ columnGap: rightPanelOpen ? "var(--space-6)" : 0,
578
+ gridTemplateColumns: getFixedPersistentRightPanelGridTemplate(fixedRightPanelWidth, rightPanelOpen),
579
+ };
580
+ }
581
+ return {
582
+ columnGap: 0,
583
+ gridTemplateColumns: getPersistentRightPanelGridTemplate(rightPanelOpen ? persistentRightPanelWidth : 0),
584
+ };
585
+ }, [
586
+ getFixedPersistentRightPanelGridTemplate,
587
+ getPersistentRightPanelGridTemplate,
588
+ fixedRightPanelWidth,
589
+ hasPersistentRightPanel,
590
+ isPersistentRightPanelResizable,
591
+ persistentRightPanelWidth,
592
+ rightPanelOpen,
593
+ ]);
594
+ const persistentRightPanelSurfaceStyle = React.useMemo(() => {
595
+ if (!hasPersistentRightPanel) {
596
+ return undefined;
597
+ }
598
+ if (isPersistentRightPanelResizable) {
599
+ return { width: persistentRightPanelWidth };
600
+ }
601
+ return fixedRightPanelWidth ? { width: fixedRightPanelWidth } : undefined;
602
+ }, [
603
+ fixedRightPanelWidth,
604
+ hasPersistentRightPanel,
605
+ isPersistentRightPanelResizable,
606
+ persistentRightPanelWidth,
607
+ ]);
608
+ return (_jsxs("main", { onClick: handleContentClick, className: cn("flex h-[calc(100dvh-var(--layout-top-offset))] min-w-0 flex-1 overflow-hidden bg-[hsl(var(--layout-shell-background))] pb-[var(--layout-content-padding)] pl-[var(--layout-content-gap-start)] pr-[var(--layout-content-padding)] pt-[var(--layout-content-padding)] transition-all duration-300 md:pb-[var(--layout-content-padding-md)] md:pl-[var(--layout-content-gap-start-md)] md:pr-[var(--layout-content-padding-md)] md:pt-[var(--layout-content-padding-md)] lg:pb-[var(--layout-content-padding-lg)] lg:pl-[var(--layout-content-gap-start-lg)] lg:pr-[var(--layout-content-padding-lg)] lg:pt-[var(--layout-content-padding-lg)]", hasSidebar &&
609
+ (isCollapsed
610
+ ? "ml-[var(--layout-sidebar-collapsed-width)]"
611
+ : "ml-[var(--layout-sidebar-width)]"), className), ...props, children: [_jsxs("div", { ref: workspaceSurfaceRef, "data-slot": "dashboard-workspace-surface", className: cn("h-full min-h-0 min-w-0 flex-1 overflow-hidden rounded-surface border border-[hsl(var(--layout-surface-border))] bg-[hsl(var(--layout-surface-background))] shadow-[var(--layout-surface-shadow)]", hasPersistentRightPanel
612
+ ? "grid transition-[grid-template-columns,column-gap] duration-300 ease-out motion-reduce:transition-none"
613
+ : "flex"), style: workspaceSurfaceStyle, children: [_jsx("div", { className: cn("scrollbar-none flex min-h-0 min-w-0 flex-1 flex-col gap-[var(--layout-surface-gap)] overflow-y-auto overflow-x-clip p-[var(--layout-surface-padding)] md:p-[var(--layout-surface-padding-md)] lg:p-[var(--layout-surface-padding-lg)]", hasPersistentRightPanel && "min-w-0", hasLeadingWorkspaceHeader && "pt-0 md:pt-0 lg:pt-0", surfaceClassName), children: children }), hasPersistentRightPanel ? (_jsx("aside", { ref: persistentRightPanelSlotRef, "aria-hidden": rightPanelOpen ? undefined : true, className: cn("relative min-h-0 transition-[border-color,box-shadow] duration-300 ease-out motion-reduce:transition-none", rightPanelEdgeClassName, rightPanelOpen
614
+ ? rightPanelEdgeOpenClassName
615
+ : rightPanelEdgeClosedClassName, !rightPanelOpen && "pointer-events-none", isPersistentRightPanelResizable
616
+ ? "min-w-0 overflow-visible"
617
+ : "min-w-0 overflow-hidden"), children: _jsx("div", { "data-slot": "dashboard-right-panel-viewport", className: "relative h-full w-full min-w-0 overflow-hidden", children: _jsxs("div", { ref: persistentRightPanelSurfaceRef, "data-slot": "dashboard-right-panel-surface", className: cn("absolute inset-y-0 right-0 flex h-full w-full min-w-0 bg-[hsl(var(--layout-right-panel-background))] transition-[opacity,transform] duration-300 ease-out motion-reduce:transition-none", rightPanelOpen
618
+ ? "translate-x-0 opacity-100"
619
+ : "translate-x-full opacity-0", isPersistentRightPanelResizable
620
+ ? "overflow-visible"
621
+ : "overflow-hidden", rightPanelClassName), style: persistentRightPanelSurfaceStyle, children: [isPersistentRightPanelResizable && rightPanelOpen ? (_jsx("button", { type: "button", "aria-label": "Resize right panel", className: "group absolute inset-y-0 -left-3 z-10 flex w-6 cursor-col-resize items-center justify-center rounded-none outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", onPointerDown: handleRightPanelResizePointerDown, children: _jsx("span", { "aria-hidden": "true", className: cn("flex h-10 w-4 items-center justify-center rounded-full border text-muted-foreground/80 shadow-sm transition-[border-color,color,box-shadow] group-hover:border-ring group-hover:text-foreground group-hover:shadow-md group-focus-visible:border-ring group-focus-visible:text-foreground group-focus-visible:shadow-md", rightPanelResizeHandleSurfaceClassName), children: _jsx(GripVertical, { className: "h-3.5 w-3.5 stroke-[2.25]" }) }) })) : null, _jsx("div", { "data-slot": "dashboard-right-panel-content", className: cn("scrollbar-none flex h-full w-full min-w-0 shrink-0 flex-col overflow-y-auto overflow-x-hidden"), children: renderedRightPanel })] }) }) })) : shouldRenderRightPanel ? (_jsx("aside", { "aria-hidden": rightPanelOpen ? undefined : true, className: cn("hidden min-h-0 shrink-0 overflow-hidden bg-[hsl(var(--layout-right-panel-background))] transition-[width,border-color,box-shadow] duration-300 ease-out will-change-[width] motion-reduce:transition-none xl:flex", rightPanelEdgeClassName, rightPanelOpen
622
+ ? [
623
+ "w-[var(--layout-right-panel-width)]",
624
+ rightPanelEdgeOpenClassName,
625
+ ]
626
+ : ["pointer-events-none w-0", rightPanelEdgeClosedClassName], rightPanelClassName), children: _jsx("div", { className: cn("scrollbar-none flex h-full w-[var(--layout-right-panel-width)] shrink-0 flex-col overflow-y-auto overflow-x-hidden motion-reduce:animate-none", rightPanelOpen
627
+ ? "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-right-full motion-safe:duration-300"
628
+ : "motion-safe:animate-out motion-safe:fade-out-0 motion-safe:slide-out-to-right-full motion-safe:duration-300"), children: renderedRightPanel }) })) : null] }), rightPanelMode !== "persistent" &&
629
+ shouldRenderRightPanel &&
630
+ rightPanelFallbackTrigger ? (_jsxs(_Fragment, { children: [_jsx(Button, { type: "button", className: cn("fixed bottom-4 right-4 z-50 xl:hidden", rightPanelOverlayOpen && "hidden"), onClick: () => setRightPanelOverlayOpen(true), children: rightPanelFallbackTrigger }), _jsx("aside", { "aria-hidden": rightPanelOverlayOpen ? undefined : true, className: cn("fixed bottom-0 right-0 top-[var(--layout-top-offset)] z-50 flex w-[min(100vw,var(--layout-right-panel-width))] max-w-full overflow-hidden bg-[hsl(var(--layout-right-panel-background))] transition-transform duration-200 ease-out motion-reduce:transition-none xl:hidden", rightPanelEdgeClassName, rightPanelEdgeOpenClassName, rightPanelOverlayOpen
631
+ ? "translate-x-0"
632
+ : "pointer-events-none translate-x-full", rightPanelClassName), children: _jsx("div", { className: "scrollbar-none flex h-full w-full flex-col overflow-y-auto overflow-x-hidden", children: renderedRightPanel }) })] })) : null] }));
229
633
  }
230
- export { DashboardLayout, DashboardSidebar, DashboardContent };
634
+ export { DashboardLayout, DashboardSidebar, DashboardSidebarProfile, DashboardContent, DashboardRightPanel, DashboardRightPanelHeader, DashboardRightPanelBody, DashboardRightPanelSection, DashboardRightPanelTabs, };
@@ -1,7 +1,15 @@
1
+ export interface ParseDateTimeOptions {
2
+ /** Base date used for relative strings like "Today" and dates without a year. */
3
+ referenceDate?: Date;
4
+ }
1
5
  /**
2
- * Parse a date string in DD/MM/YYYY HH:MM AM/PM format to a timestamp (ms).
6
+ * Parse common CLIP date/time strings to a timestamp (ms).
7
+ *
8
+ * Supports numeric dates (`23/03/2025 01:51 AM`), compact meridiem times
9
+ * (`12/05/2026 10:00AM`), month-name dates (`13 Feb 2026, 03:13 PM`), and
10
+ * relative sandbox labels (`Today, 11:12 AM`, `Yesterday, 5:28 PM`).
3
11
  */
4
- export declare function parseDateTime(dateStr: string): number;
12
+ export declare function parseDateTime(dateStr: string, options?: ParseDateTimeOptions): number;
5
13
  /**
6
14
  * Format a Date object or ISO string to DD/MM/YYYY HH:MM AM/PM format.
7
15
  * Returns `"-"` for null/undefined/invalid input.