@neasg/design-system 0.4.11 → 0.4.13

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 (44) hide show
  1. package/README.md +147 -5
  2. package/dist/avatar-profile-popover.d.ts +34 -0
  3. package/dist/avatar-profile-popover.js +27 -0
  4. package/dist/badge.d.ts +1 -1
  5. package/dist/button.d.ts +1 -1
  6. package/dist/card.d.ts +2 -0
  7. package/dist/card.js +72 -3
  8. package/dist/command-search.d.ts +47 -2
  9. package/dist/command-search.js +173 -24
  10. package/dist/command.d.ts +2 -0
  11. package/dist/command.js +2 -2
  12. package/dist/dialog-primitive.js +1 -1
  13. package/dist/draggable-tabs.d.ts +3 -0
  14. package/dist/draggable-tabs.js +4 -0
  15. package/dist/editable-table.js +2 -2
  16. package/dist/guidance-tip.d.ts +26 -0
  17. package/dist/guidance-tip.js +162 -0
  18. package/dist/index.d.ts +15 -6
  19. package/dist/index.js +6 -2
  20. package/dist/jump-target-highlight.d.ts +13 -0
  21. package/dist/jump-target-highlight.js +95 -0
  22. package/dist/layout.d.ts +27 -5
  23. package/dist/layout.js +128 -34
  24. package/dist/message-item.js +9 -10
  25. package/dist/notification.js +1 -1
  26. package/dist/page-layout.d.ts +22 -0
  27. package/dist/page-layout.js +38 -0
  28. package/dist/page-section.js +1 -1
  29. package/dist/popover-menu.js +2 -2
  30. package/dist/routing-timeline.js +1 -1
  31. package/dist/styles.css +16 -0
  32. package/dist/table-column-visibility.d.ts +2 -1
  33. package/dist/table-column-visibility.js +9 -8
  34. package/dist/table-toolbar.d.ts +2 -1
  35. package/dist/table-toolbar.js +7 -2
  36. package/dist/table.d.ts +31 -2
  37. package/dist/table.js +298 -23
  38. package/dist/tabs.d.ts +2 -1
  39. package/dist/tabs.js +8 -5
  40. package/dist/theme-switcher.d.ts +1 -1
  41. package/dist/theme-switcher.js +4 -6
  42. package/dist/theme.d.ts +336 -77
  43. package/dist/theme.js +269 -55
  44. package/package.json +1 -1
package/dist/layout.js CHANGED
@@ -2,11 +2,12 @@
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
+ import { GripVertical, PanelRightClose, PanelRightOpen } from "lucide-react";
6
6
  import { ChevronDownIcon } from "./animated-icons/chevron-down";
7
7
  import { ChevronLeftIcon } from "./animated-icons/chevron-left";
8
8
  import { ChevronRightIcon } from "./animated-icons/chevron-right";
9
- import { AvatarProfile } from "./avatar";
9
+ import { Avatar, AvatarProfile } from "./avatar";
10
+ import { AvatarProfilePopover, } from "./avatar-profile-popover";
10
11
  import { Button } from "./button";
11
12
  import { CountBadge } from "./count-badge";
12
13
  import { ScrollHint } from "./scroll-hint";
@@ -15,12 +16,14 @@ import { Tooltip } from "./tooltip";
15
16
  import { Typography } from "./typography";
16
17
  import { cn } from "./lib/utils";
17
18
  import { rightPanelEdgeClassName, rightPanelEdgeClosedClassName, rightPanelEdgeOpenClassName, rightPanelResizeHandleSurfaceClassName, } from "./layout-right-panel-edge";
18
- const COLLAPSE_BREAKPOINT = 1280;
19
- const RIGHT_PANEL_AUTO_COLLAPSE_BREAKPOINT = 1600;
19
+ const COLLAPSE_BREAKPOINT = 1800;
20
+ const RIGHT_PANEL_AUTO_COLLAPSE_BREAKPOINT = 1800;
20
21
  const RIGHT_PANEL_TRANSITION_MS = 300;
21
22
  const RIGHT_PANEL_RESIZE_DEFAULT_WIDTH = 432;
22
23
  const RIGHT_PANEL_RESIZE_MIN_WIDTH = 320;
23
24
  const RIGHT_PANEL_RESIZE_MAX_WIDTH = 640;
25
+ const RIGHT_PANEL_COLLAPSED_WIDTH = 40;
26
+ const RIGHT_PANEL_COLLAPSE_BUTTON_SIZE = 32;
24
27
  const RIGHT_PANEL_FIXED_WIDTH_RATIO = 0.24;
25
28
  const RIGHT_PANEL_SCROLL_HINT_THRESHOLD = 8;
26
29
  const collapsedSidebarControlClassName = "h-control min-h-control w-control min-w-control max-w-control shrink-0 rounded-control p-0";
@@ -112,7 +115,7 @@ export function useSidebar() {
112
115
  }
113
116
  return context;
114
117
  }
115
- function DashboardLayout({ className, masthead, prototypeBanner, sidebar, rightPanel, surfaceClassName, contentClassName, rightPanelClassName, rightPanelFallbackTrigger, rightPanelMode, rightPanelResizable, rightPanelDefaultWidth, rightPanelMinWidth, rightPanelMaxWidth, rightPanelAutoCollapseSidebarBreakpoint, defaultSidebarCollapsed = false, children, style, ...props }) {
118
+ function DashboardLayout({ className, masthead, prototypeBanner, sidebar, rightPanel, surfaceClassName, contentClassName, rightPanelClassName, rightPanelFallbackTrigger, rightPanelMode, rightPanelResizable, rightPanelCollapsible, rightPanelCollapsed, defaultRightPanelCollapsed, onRightPanelCollapsedChange, rightPanelDefaultWidth, rightPanelMinWidth, rightPanelMaxWidth, rightPanelAutoCollapseSidebarBreakpoint, defaultSidebarCollapsed = false, children, style, ...props }) {
116
119
  const chromeRef = React.useRef(null);
117
120
  const [topOffset, setTopOffset] = React.useState(0);
118
121
  const layoutStyle = React.useMemo(() => ({
@@ -137,7 +140,7 @@ function DashboardLayout({ className, masthead, prototypeBanner, sidebar, rightP
137
140
  observer.observe(node);
138
141
  return () => observer.disconnect();
139
142
  }, [masthead, prototypeBanner]);
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 })] })] }) }));
143
+ 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, rightPanelCollapsible: rightPanelCollapsible, rightPanelCollapsed: rightPanelCollapsed, defaultRightPanelCollapsed: defaultRightPanelCollapsed, onRightPanelCollapsedChange: onRightPanelCollapsedChange, rightPanelDefaultWidth: rightPanelDefaultWidth, rightPanelMinWidth: rightPanelMinWidth, rightPanelMaxWidth: rightPanelMaxWidth, rightPanelAutoCollapseSidebarBreakpoint: rightPanelAutoCollapseSidebarBreakpoint, surfaceClassName: surfaceClassName, children: children })] })] }) }));
141
144
  }
142
145
  function SidebarShell({ isCollapsed, className, children, ...props }) {
143
146
  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
@@ -168,7 +171,7 @@ function SidebarMenuItem({ className, children, collapsed = false, }) {
168
171
  const SidebarMenuButton = React.forwardRef(({ active = false, collapsed = false, depth: _depth = 0, disabled = false, className, asChild = false, children, ...props }, ref) => {
169
172
  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
173
  ? cn(collapsedSidebarControlClassName, "gap-0")
171
- : "h-control w-full justify-start gap-2.5 px-3", disabled
174
+ : "h-control w-full justify-start gap-2.5 px-2", disabled
172
175
  ? "text-muted-foreground/50 hover:bg-transparent hover:text-muted-foreground/50"
173
176
  : active
174
177
  ? "border-none bg-card text-card-foreground shadow-sm hover:bg-card hover:text-card-foreground"
@@ -224,14 +227,46 @@ function DashboardSidebarItemButton({ item, isCollapsed, active, expanded, depth
224
227
  }
225
228
  return interactive;
226
229
  }
227
- function DashboardSidebarProfile({ isCollapsed = false, status = "online", name, role, rolePlacement = "below", size = "sm", ...props }) {
228
- const statusClassName = {
230
+ function getDashboardSidebarProfileStatusClassName(status) {
231
+ return {
229
232
  online: "bg-primary",
230
233
  busy: "bg-[hsl(var(--status-warning-foreground))]",
231
234
  offline: "bg-muted-foreground",
232
235
  none: "",
233
236
  }[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) })) }) }));
237
+ }
238
+ function getDashboardSidebarProfileAvatarOverlay(status) {
239
+ if (status === "none") {
240
+ return undefined;
241
+ }
242
+ return (_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", getDashboardSidebarProfileStatusClassName(status)) }));
243
+ }
244
+ function DashboardSidebarProfileView({ isCollapsed = false, status = "online", name, role, rolePlacement = "below", size = "sm", ...props }) {
245
+ return (_jsx(AvatarProfile, { ...props, size: size, name: isCollapsed ? undefined : name, role: isCollapsed ? undefined : role, rolePlacement: rolePlacement, className: cn("rounded-control py-2 text-muted-foreground transition-colors hover:bg-card hover:text-foreground", isCollapsed ? "justify-center px-0" : "min-w-0 px-1.5"), avatarClassName: "h-9 w-9 ring-1 ring-border/60 shadow-sm", fallbackClassName: "bg-background text-foreground", avatarOverlay: getDashboardSidebarProfileAvatarOverlay(status) }));
246
+ }
247
+ function DashboardSidebarProfile({ isCollapsed = false, ...props }) {
248
+ return (_jsx("div", { className: cn(isCollapsed ? "px-0" : "px-1", "pb-4 pt-2"), children: _jsx(DashboardSidebarProfileView, { isCollapsed: isCollapsed, ...props }) }));
249
+ }
250
+ const DashboardSidebarProfileTrigger = React.forwardRef(({ isCollapsed = false, name, nameAs: _NameElement, nameRowClassName: _nameRowClassName, nameTrailing, role, rolePlacement = "below", size = "sm", src, alt = "", fallback, loading = false, status = "online", topInfo, bottomInfo, triggerAriaLabel, triggerClassName, ...triggerProps }, ref) => {
251
+ const buttonProps = triggerProps;
252
+ const profileLabel = triggerAriaLabel !== null && triggerAriaLabel !== void 0 ? triggerAriaLabel : (typeof name === "string"
253
+ ? `Open profile menu for ${name}`
254
+ : "Open profile menu");
255
+ const resolvedTop = topInfo !== null && topInfo !== void 0 ? topInfo : (rolePlacement === "above" ? role : undefined);
256
+ const resolvedBottom = bottomInfo !== null && bottomInfo !== void 0 ? bottomInfo : (rolePlacement === "below" ? role : undefined);
257
+ const hasSupportingInfo = (resolvedTop !== undefined && resolvedTop !== null) ||
258
+ (resolvedBottom !== undefined && resolvedBottom !== null);
259
+ const hasMeta = name !== undefined ||
260
+ nameTrailing !== undefined ||
261
+ resolvedTop !== undefined ||
262
+ resolvedBottom !== undefined;
263
+ const infoClassName = "min-w-0 truncate text-xs leading-4 text-muted-foreground";
264
+ const nameNode = name !== undefined && name !== null ? (_jsx("span", { className: "min-w-0 truncate text-sm font-medium leading-5 text-foreground", children: name })) : null;
265
+ return (_jsx("div", { className: cn(isCollapsed ? "px-0" : "px-1", "pb-4 pt-2"), children: _jsx("button", { ...buttonProps, ref: ref, type: "button", "aria-label": profileLabel, "aria-busy": loading ? "true" : undefined, className: cn("group/profile-trigger block h-auto w-full cursor-pointer rounded-control border-0 bg-transparent p-0 text-left text-muted-foreground ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0", isCollapsed ? "justify-center" : "justify-start", triggerClassName), children: _jsxs("span", { className: cn("flex min-w-0 max-w-full rounded-control py-2 transition-colors hover:bg-card hover:text-foreground", hasSupportingInfo ? "items-start" : "items-center", isCollapsed ? "justify-center px-0" : "gap-2.5 px-1.5"), children: [_jsxs("span", { className: "relative shrink-0", children: [loading ? (_jsx("span", { "aria-hidden": "true", className: cn("block h-9 w-9 shrink-0 animate-pulse rounded-full bg-muted ring-1 ring-border/60 shadow-sm", hasSupportingInfo && "mt-0.5") })) : (_jsx(Avatar, { src: src, alt: alt, fallback: fallback, size: size, className: cn("h-9 w-9 ring-1 ring-border/60 shadow-sm", hasSupportingInfo && "mt-0.5") })), getDashboardSidebarProfileAvatarOverlay(status)] }), !isCollapsed && hasMeta ? (_jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-[2px]", children: [resolvedTop !== undefined && resolvedTop !== null ? (_jsx("span", { className: infoClassName, children: resolvedTop })) : null, nameTrailing !== undefined && nameTrailing !== null ? (_jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [nameNode, nameTrailing] })) : (nameNode), resolvedBottom !== undefined && resolvedBottom !== null ? (_jsx("span", { className: infoClassName, children: resolvedBottom })) : null] })) : null, !isCollapsed ? (_jsx(ChevronDownIcon, { "aria-hidden": "true", className: cn("mt-2 shrink-0 text-muted-foreground transition-transform duration-200", "group-data-[state=open]/profile-trigger:rotate-180 group-hover/profile-trigger:text-foreground"), size: 16 })) : null] }) }) }));
266
+ });
267
+ DashboardSidebarProfileTrigger.displayName = "DashboardSidebarProfileTrigger";
268
+ function DashboardSidebarProfilePopover({ align = "end", alignOffset, avoidCollisions, children, collisionPadding = 8, contentClassName, defaultOpen, modal, onOpenChange, open, side = "right", sideOffset = 4, triggerAriaLabel, triggerClassName, ...profileProps }) {
269
+ return (_jsx(AvatarProfilePopover, { defaultOpen: defaultOpen, modal: modal, onOpenChange: onOpenChange, open: open, side: side, align: align, alignOffset: alignOffset, avoidCollisions: avoidCollisions, collisionPadding: collisionPadding, sideOffset: sideOffset, contentClassName: contentClassName, trigger: _jsx(DashboardSidebarProfileTrigger, { ...profileProps, triggerAriaLabel: triggerAriaLabel, triggerClassName: triggerClassName }), children: children }));
235
270
  }
236
271
  function DashboardSidebarLeafItem({ item, isCollapsed, depth = 0, }) {
237
272
  return (_jsx(DashboardSidebarItemButton, { item: item, isCollapsed: isCollapsed, active: sidebarItemIsActive(item), depth: depth, onClick: item.onClick }));
@@ -294,25 +329,23 @@ function DashboardSidebar({ className, children, logo, search, navGroups, footer
294
329
  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
330
  ? "flex justify-center px-0 pb-3 pt-2"
296
331
  : "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"
332
+ ? "overflow-visible p-[var(--layout-sidebar-content-padding)]"
298
333
  : "p-[var(--layout-sidebar-content-padding)]"), children: _jsx("nav", { "aria-label": "Sidebar navigation", children: navGroups.map((group, groupIndex) => {
299
334
  var _a;
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}`));
335
+ return (_jsx(SidebarGroup, { children: _jsxs("div", { className: cn(groupIndex > 0 && "mt-[var(--layout-sidebar-section-gap)]"), children: [group.label ? (_jsx(SidebarGroupLabel, { "aria-hidden": isCollapsed ? true : undefined, className: isCollapsed ? "invisible" : undefined, 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
336
  }) }) })) : 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] }));
304
337
  }
305
338
  function DashboardRightPanelSection({ className, title, description, titleClassName, descriptionClassName, children, ...props }) {
306
339
  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
340
  }
308
341
  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 }));
342
+ 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 pb-[var(--layout-right-panel-tabs-gap)] pl-[var(--layout-right-panel-padding)] pr-[calc(var(--layout-right-panel-padding)+var(--layout-right-panel-action-space,0px))] 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
343
  }
311
344
  function DashboardRightPanel({ className, ...props }) {
312
345
  return (_jsx("div", { className: cn("flex min-h-0 flex-1 flex-col bg-[hsl(var(--layout-right-panel-background))]", className), ...props }));
313
346
  }
314
347
  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] }) }));
348
+ return (_jsx("div", { className: cn("shrink-0 pb-[var(--layout-right-panel-padding)] pl-[var(--layout-right-panel-padding)] pr-[calc(var(--layout-right-panel-padding)+var(--layout-right-panel-action-space,0px))] pt-[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
349
  }
317
350
  function DashboardRightPanelBody({ className, contentClassName, footer, footerClassName, children, ...props }) {
318
351
  const { scrollRef, canScrollDown } = useScrollOverflowHint();
@@ -321,9 +354,14 @@ function DashboardRightPanelBody({ className, contentClassName, footer, footerCl
321
354
  }
322
355
  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
356
  }
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 }) {
357
+ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanelClassName, rightPanelFallbackTrigger, rightPanelMode = "responsive", rightPanelResizable = false, rightPanelCollapsible = false, rightPanelCollapsed, defaultRightPanelCollapsed = false, onRightPanelCollapsedChange, 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
358
  const { isCollapsed, toggle, collapse } = useSidebar();
326
359
  const hasRightPanel = Boolean(rightPanel);
360
+ const isRightPanelCollapseControlled = rightPanelCollapsed !== undefined;
361
+ const [uncontrolledRightPanelCollapsed, setUncontrolledRightPanelCollapsed,] = React.useState(defaultRightPanelCollapsed);
362
+ const canCollapsePersistentRightPanel = rightPanelMode === "persistent" && rightPanelCollapsible && hasRightPanel;
363
+ const effectiveRightPanelCollapsed = canCollapsePersistentRightPanel &&
364
+ (rightPanelCollapsed !== null && rightPanelCollapsed !== void 0 ? rightPanelCollapsed : uncontrolledRightPanelCollapsed);
327
365
  const persistentRightPanelMinWidth = Math.min(rightPanelMinWidth, rightPanelMaxWidth);
328
366
  const persistentRightPanelMaxWidth = Math.max(rightPanelMinWidth, rightPanelMaxWidth);
329
367
  const [persistentRightPanelWidth, setPersistentRightPanelWidth] = React.useState(rightPanelDefaultWidth);
@@ -331,14 +369,16 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
331
369
  const workspaceSurfaceRef = React.useRef(null);
332
370
  const persistentRightPanelSlotRef = React.useRef(null);
333
371
  const persistentRightPanelSurfaceRef = React.useRef(null);
372
+ const rightPanelContentId = React.useId();
334
373
  const [renderedRightPanel, setRenderedRightPanel] = React.useState(rightPanel);
335
374
  const [shouldRenderRightPanel, setShouldRenderRightPanel] = React.useState(hasRightPanel);
336
- const [rightPanelOpen, setRightPanelOpen] = React.useState(hasRightPanel);
375
+ const [rightPanelOpen, setRightPanelOpen] = React.useState(hasRightPanel && !effectiveRightPanelCollapsed);
337
376
  const [rightPanelOverlayOpen, setRightPanelOverlayOpen] = React.useState(false);
338
377
  const [fixedRightPanelWidth, setFixedRightPanelWidth] = React.useState(null);
339
378
  const wasRightPanelVisibleRef = React.useRef(hasRightPanel);
340
379
  const isCollapsedRef = React.useRef(isCollapsed);
341
380
  const hasPersistentRightPanel = rightPanelMode === "persistent" && shouldRenderRightPanel;
381
+ const hasCollapsedPersistentRightPanelRail = hasPersistentRightPanel && hasRightPanel && effectiveRightPanelCollapsed;
342
382
  const isPersistentRightPanelResizable = hasPersistentRightPanel && rightPanelResizable;
343
383
  const firstChild = React.Children.toArray(children).find((child) => child !== null && child !== undefined);
344
384
  const hasLeadingWorkspaceHeader = React.isValidElement(firstChild) &&
@@ -350,12 +390,18 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
350
390
  React.useEffect(() => {
351
391
  persistentRightPanelWidthRef.current = persistentRightPanelWidth;
352
392
  }, [persistentRightPanelWidth]);
393
+ const setRightPanelCollapsedState = React.useCallback((collapsed) => {
394
+ if (!isRightPanelCollapseControlled) {
395
+ setUncontrolledRightPanelCollapsed(collapsed);
396
+ }
397
+ onRightPanelCollapsedChange === null || onRightPanelCollapsedChange === void 0 ? void 0 : onRightPanelCollapsedChange(collapsed);
398
+ }, [isRightPanelCollapseControlled, onRightPanelCollapsedChange]);
353
399
  const getPersistentRightPanelGridTemplate = React.useCallback((width) => `minmax(0, 1fr) ${width}px`, []);
354
- const getFixedPersistentRightPanelGridTemplate = React.useCallback((width, isOpen) => `minmax(0, 1fr) ${isOpen
400
+ const getFixedPersistentRightPanelGridTemplate = React.useCallback((width, isOpen, collapsedWidth = 0) => `minmax(0, 1fr) ${isOpen
355
401
  ? width
356
402
  ? `${width}px`
357
403
  : `${RIGHT_PANEL_FIXED_WIDTH_RATIO * 100}%`
358
- : "0px"}`, []);
404
+ : `${collapsedWidth}px`}`, []);
359
405
  const measureFixedRightPanelWidth = React.useCallback(() => {
360
406
  var _a, _b;
361
407
  const surfaceWidth = (_b = (_a = workspaceSurfaceRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) !== null && _b !== void 0 ? _b : 0;
@@ -371,13 +417,18 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
371
417
  const width = `${persistentRightPanelWidth}px`;
372
418
  if (workspaceSurfaceRef.current) {
373
419
  workspaceSurfaceRef.current.style.gridTemplateColumns =
374
- getPersistentRightPanelGridTemplate(rightPanelOpen ? persistentRightPanelWidth : 0);
420
+ getPersistentRightPanelGridTemplate(hasCollapsedPersistentRightPanelRail
421
+ ? RIGHT_PANEL_COLLAPSED_WIDTH
422
+ : rightPanelOpen
423
+ ? persistentRightPanelWidth
424
+ : 0);
375
425
  }
376
426
  if (persistentRightPanelSurfaceRef.current) {
377
427
  persistentRightPanelSurfaceRef.current.style.width = width;
378
428
  }
379
429
  }, [
380
430
  getPersistentRightPanelGridTemplate,
431
+ hasCollapsedPersistentRightPanelRail,
381
432
  isPersistentRightPanelResizable,
382
433
  persistentRightPanelWidth,
383
434
  rightPanelOpen,
@@ -429,6 +480,7 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
429
480
  if (rightPanelMode === "persistent") {
430
481
  setRightPanelOverlayOpen(false);
431
482
  }
483
+ const shouldOpenRightPanel = hasRightPanel && !effectiveRightPanelCollapsed;
432
484
  if (hasRightPanel) {
433
485
  if (rightPanelMode === "persistent" && !rightPanelResizable) {
434
486
  const nextFixedRightPanelWidth = measureFixedRightPanelWidth();
@@ -438,14 +490,18 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
438
490
  : nextFixedRightPanelWidth);
439
491
  }
440
492
  }
441
- if (rightPanelAutoCollapseSidebarBreakpoint !== false &&
493
+ if (shouldOpenRightPanel &&
494
+ rightPanelAutoCollapseSidebarBreakpoint !== false &&
442
495
  !isCollapsedRef.current &&
443
496
  window.innerWidth < rightPanelAutoCollapseSidebarBreakpoint) {
444
497
  collapse();
445
498
  }
446
499
  setRenderedRightPanel(rightPanel);
447
500
  setShouldRenderRightPanel(true);
448
- if (wasRightPanelVisibleRef.current) {
501
+ if (!shouldOpenRightPanel) {
502
+ setRightPanelOpen(false);
503
+ }
504
+ else if (wasRightPanelVisibleRef.current) {
449
505
  setRightPanelOpen(true);
450
506
  }
451
507
  else {
@@ -485,6 +541,7 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
485
541
  }, [
486
542
  collapse,
487
543
  hasRightPanel,
544
+ effectiveRightPanelCollapsed,
488
545
  rightPanel,
489
546
  rightPanelMode,
490
547
  rightPanelResizable,
@@ -494,6 +551,7 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
494
551
  React.useEffect(() => {
495
552
  if (rightPanelMode !== "persistent" ||
496
553
  !hasRightPanel ||
554
+ effectiveRightPanelCollapsed ||
497
555
  rightPanelAutoCollapseSidebarBreakpoint === false) {
498
556
  return undefined;
499
557
  }
@@ -509,14 +567,15 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
509
567
  }, [
510
568
  collapse,
511
569
  hasRightPanel,
570
+ effectiveRightPanelCollapsed,
512
571
  rightPanelMode,
513
572
  rightPanelAutoCollapseSidebarBreakpoint,
514
573
  ]);
515
574
  const handleContentClick = React.useCallback(() => {
516
575
  if (!isCollapsed && window.innerWidth < COLLAPSE_BREAKPOINT) {
517
- toggle();
576
+ collapse();
518
577
  }
519
- }, [isCollapsed, toggle]);
578
+ }, [collapse, isCollapsed]);
520
579
  const handleRightPanelResizePointerDown = React.useCallback((event) => {
521
580
  if (!isPersistentRightPanelResizable) {
522
581
  return;
@@ -575,17 +634,24 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
575
634
  if (!isPersistentRightPanelResizable) {
576
635
  return {
577
636
  columnGap: rightPanelOpen ? "var(--space-6)" : 0,
578
- gridTemplateColumns: getFixedPersistentRightPanelGridTemplate(fixedRightPanelWidth, rightPanelOpen),
637
+ gridTemplateColumns: getFixedPersistentRightPanelGridTemplate(fixedRightPanelWidth, rightPanelOpen, hasCollapsedPersistentRightPanelRail
638
+ ? RIGHT_PANEL_COLLAPSED_WIDTH
639
+ : 0),
579
640
  };
580
641
  }
581
642
  return {
582
643
  columnGap: 0,
583
- gridTemplateColumns: getPersistentRightPanelGridTemplate(rightPanelOpen ? persistentRightPanelWidth : 0),
644
+ gridTemplateColumns: getPersistentRightPanelGridTemplate(hasCollapsedPersistentRightPanelRail
645
+ ? RIGHT_PANEL_COLLAPSED_WIDTH
646
+ : rightPanelOpen
647
+ ? persistentRightPanelWidth
648
+ : 0),
584
649
  };
585
650
  }, [
586
651
  getFixedPersistentRightPanelGridTemplate,
587
652
  getPersistentRightPanelGridTemplate,
588
653
  fixedRightPanelWidth,
654
+ hasCollapsedPersistentRightPanelRail,
589
655
  hasPersistentRightPanel,
590
656
  isPersistentRightPanelResizable,
591
657
  persistentRightPanelWidth,
@@ -605,30 +671,58 @@ function DashboardContent({ className, hasSidebar = true, rightPanel, rightPanel
605
671
  isPersistentRightPanelResizable,
606
672
  persistentRightPanelWidth,
607
673
  ]);
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 &&
674
+ const rightPanelContentStyle = React.useMemo(() => {
675
+ if (!canCollapsePersistentRightPanel) {
676
+ return undefined;
677
+ }
678
+ return {
679
+ "--layout-right-panel-action-space": "var(--space-10)",
680
+ };
681
+ }, [canCollapsePersistentRightPanel]);
682
+ const rightPanelCollapseToggleStyle = React.useMemo(() => {
683
+ if (!hasPersistentRightPanel || !canCollapsePersistentRightPanel) {
684
+ return undefined;
685
+ }
686
+ if (hasCollapsedPersistentRightPanelRail) {
687
+ return {
688
+ right: `${(RIGHT_PANEL_COLLAPSED_WIDTH - RIGHT_PANEL_COLLAPSE_BUTTON_SIZE) / 2}px`,
689
+ };
690
+ }
691
+ return { right: "var(--space-3)" };
692
+ }, [
693
+ canCollapsePersistentRightPanel,
694
+ hasCollapsedPersistentRightPanelRail,
695
+ hasPersistentRightPanel,
696
+ ]);
697
+ const rightPanelCollapseToggleLabel = rightPanelOpen
698
+ ? "Collapse right panel"
699
+ : "Expand right panel";
700
+ return (_jsxs("main", { onClickCapture: 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
701
  (isCollapsed
610
702
  ? "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
703
+ : "ml-[var(--layout-sidebar-width)]"), className), ...props, children: [_jsxs("div", { ref: workspaceSurfaceRef, "data-slot": "dashboard-workspace-surface", className: cn("relative 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
704
  ? "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
705
+ : "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 || hasCollapsedPersistentRightPanelRail
614
706
  ? rightPanelEdgeOpenClassName
615
- : rightPanelEdgeClosedClassName, !rightPanelOpen && "pointer-events-none", isPersistentRightPanelResizable
707
+ : rightPanelEdgeClosedClassName, !rightPanelOpen &&
708
+ !hasCollapsedPersistentRightPanelRail &&
709
+ "pointer-events-none", isPersistentRightPanelResizable
616
710
  ? "min-w-0 overflow-visible"
617
711
  : "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
712
  ? "translate-x-0 opacity-100"
619
713
  : "translate-x-full opacity-0", isPersistentRightPanelResizable
620
714
  ? "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
715
+ : "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", { id: rightPanelContentId, "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"), style: rightPanelContentStyle, 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
716
  ? [
623
717
  "w-[var(--layout-right-panel-width)]",
624
718
  rightPanelEdgeOpenClassName,
625
719
  ]
626
720
  : ["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
721
  ? "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" &&
722
+ : "motion-safe:animate-out motion-safe:fade-out-0 motion-safe:slide-out-to-right-full motion-safe:duration-300"), children: renderedRightPanel }) })) : null, canCollapsePersistentRightPanel ? (_jsx(Tooltip, { content: rightPanelCollapseToggleLabel, side: "left", children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", "aria-controls": rightPanelContentId, "aria-expanded": rightPanelOpen, "aria-label": rightPanelCollapseToggleLabel, className: "absolute top-3 z-30 text-muted-foreground transition-[right,background-color,color] duration-300 ease-out hover:text-foreground motion-reduce:transition-none", style: rightPanelCollapseToggleStyle, onClick: () => setRightPanelCollapsedState(!effectiveRightPanelCollapsed), children: rightPanelOpen ? (_jsx(PanelRightClose, { "aria-hidden": "true" })) : (_jsx(PanelRightOpen, { "aria-hidden": "true" })) }) })) : null] }), rightPanelMode !== "persistent" &&
629
723
  shouldRenderRightPanel &&
630
724
  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
725
  ? "translate-x-0"
632
726
  : "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] }));
633
727
  }
634
- export { DashboardLayout, DashboardSidebar, DashboardSidebarProfile, DashboardContent, DashboardRightPanel, DashboardRightPanelHeader, DashboardRightPanelBody, DashboardRightPanelSection, DashboardRightPanelTabs, };
728
+ export { DashboardLayout, DashboardSidebar, DashboardSidebarProfile, DashboardSidebarProfilePopover, DashboardContent, DashboardRightPanel, DashboardRightPanelHeader, DashboardRightPanelBody, DashboardRightPanelSection, DashboardRightPanelTabs, };
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { Download, FileText } from "lucide-react";
4
+ import { FileText } from "lucide-react";
5
+ import { DownloadIcon } from "./animated-icons";
5
6
  import { AvatarProfile } from "./avatar";
6
7
  import { Badge } from "./badge";
7
8
  import { Separator } from "./separator";
@@ -9,13 +10,11 @@ import { Typography } from "./typography";
9
10
  import { cn } from "./lib/utils";
10
11
  export const formatMessageDate = (date) => {
11
12
  const d = new Date(date);
12
- return d.toLocaleDateString("en-SG", {
13
- day: "numeric",
14
- month: "short",
15
- year: "numeric",
16
- hour: "2-digit",
17
- minute: "2-digit",
18
- });
13
+ const hours = d.getHours();
14
+ const twelveHour = hours % 12 || 12;
15
+ const period = hours >= 12 ? "PM" : "AM";
16
+ const pad = (value) => String(value).padStart(2, "0");
17
+ return `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${d.getFullYear()} ${pad(twelveHour)}:${pad(d.getMinutes())} ${period}`;
19
18
  };
20
19
  function getInitials(name) {
21
20
  if (!name)
@@ -43,7 +42,7 @@ export function MessageNewDivider({ children = "New Message", className, }) {
43
42
  export function MessageAttachmentRow({ attachment, downloadUrl, downloadLabel = `Download ${attachment.name}`, className, ...props }) {
44
43
  const renderContent = (isInteractive) => (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground", children: _jsx(FileText, { className: "h-4 w-4" }) }), _jsxs("div", { className: "min-w-0 pr-1", children: [_jsx(Typography, { as: "p", variant: "bodySm", className: "line-clamp-2 font-medium", children: attachment.name }), attachment.size ? (_jsx(Typography, { as: "p", variant: "caption", children: attachment.size })) : null] }), _jsx("span", { "aria-hidden": "true", className: cn("flex h-8 w-8 shrink-0 items-center justify-center rounded-control border border-border bg-background text-muted-foreground transition-colors", isInteractive
45
44
  ? "group-hover:border-primary/40 group-hover:bg-primary/10 group-hover:text-primary group-focus-visible:border-primary/40 group-focus-visible:bg-primary/10 group-focus-visible:text-primary"
46
- : "opacity-60"), children: _jsx(Download, { className: "h-3.5 w-3.5" }) })] }));
45
+ : "opacity-60"), children: _jsx(DownloadIcon, { size: 14 }) })] }));
47
46
  if (downloadUrl) {
48
47
  return (_jsx("a", { className: cn("group grid min-w-0 cursor-pointer grid-cols-[auto_minmax(0,1fr)_2.75rem] items-center gap-3 rounded-lg border border-border bg-card px-3 py-2 text-foreground no-underline shadow-sm transition hover:border-primary/50 hover:bg-primary/5 hover:no-underline hover:shadow-md focus-visible:border-primary/50 focus-visible:bg-primary/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", className), href: downloadUrl, target: "_blank", rel: "noopener noreferrer", download: attachment.name, "aria-label": downloadLabel, title: downloadLabel, ...props, children: renderContent(true) }));
49
48
  }
@@ -135,7 +134,7 @@ export function MessageItem({ message, caseId, showNewBadge = false, newMessageL
135
134
  const downloadCaseId = caseId !== null && caseId !== void 0 ? caseId : message.caseId;
136
135
  const contentHtml = toHtmlContent(message.content);
137
136
  const richContentClassName = cn("break-words leading-6", "[&_p]:my-0 [&_p+p]:mt-2", "[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5", "[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5", "[&_li]:my-1", "[&_a]:text-primary [&_a]:underline [&_a:hover]:text-primary/80", "[&_h1]:mb-2 [&_h1]:mt-3 [&_h1]:text-xl [&_h1]:font-semibold", "[&_h2]:mb-2 [&_h2]:mt-3 [&_h2]:text-lg [&_h2]:font-semibold", "[&_h3]:mb-1.5 [&_h3]:mt-3 [&_h3]:text-base [&_h3]:font-semibold", "[&_h4]:mb-1.5 [&_h4]:mt-3 [&_h4]:font-semibold", "[&_h5]:mb-1.5 [&_h5]:mt-3 [&_h5]:font-semibold", "[&_h6]:mb-1.5 [&_h6]:mt-3 [&_h6]:font-semibold", "[&_blockquote]:my-2 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground", "[&_table]:my-2 [&_table]:w-full [&_table]:border-collapse", "[&_td]:border [&_td]:border-border [&_td]:p-2", "[&_th]:border [&_th]:border-border [&_th]:bg-[hsl(var(--table-header-background))] [&_th]:p-2 [&_th]:font-semibold", "[&_pre]:my-2 [&_pre]:overflow-x-auto [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:font-mono [&_pre]:text-[0.85em]", "[&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.85em]", "[&_pre_code]:bg-transparent [&_pre_code]:p-0", "[&_mark]:rounded-sm [&_mark]:bg-[hsl(var(--status-warning))] [&_mark]:px-0.5 [&_mark]:text-[hsl(var(--status-warning-foreground))]", "[&_img]:h-auto [&_img]:max-w-full", contentClassName);
138
- return (_jsxs(_Fragment, { children: [showUnreadDivider && (_jsx(MessageNewDivider, { children: newMessageLabel })), _jsxs("article", { ref: messageRef, className: cn("min-w-0", className), children: [_jsxs("div", { className: "flex min-w-0 items-start justify-between gap-x-3 gap-y-1", children: [_jsx(AvatarProfile, { fallback: getInitials(initialsName), name: senderName, nameAs: "h3", nameTrailing: isApplicant ? (_jsx(Badge, { variant: "warning", bordered: true, children: "Applicant" })) : undefined, role: hasSenderProfileRole ? (_jsx("span", { "data-slot": "message-author-role", children: senderProfileRole })) : undefined, rolePlacement: "below", className: "min-w-0 flex-1 [column-gap:var(--space-3)]", avatarClassName: "h-9 w-9 shrink-0", fallbackClassName: "text-xs font-medium", nameClassName: "max-w-full whitespace-normal break-words [overflow-wrap:anywhere]" }), _jsx("time", { className: "shrink-0 whitespace-nowrap pt-0.5", dateTime: messageDate.toISOString(), children: _jsx(Typography, { as: "span", variant: "caption", children: formatTimestamp
137
+ return (_jsxs(_Fragment, { children: [showUnreadDivider && (_jsx(MessageNewDivider, { children: newMessageLabel })), _jsxs("article", { ref: messageRef, className: cn("min-w-0", className), children: [_jsxs("div", { className: "flex min-w-0 items-start justify-between gap-x-3 gap-y-1", children: [_jsx(AvatarProfile, { fallback: getInitials(initialsName), name: senderName, nameAs: "h3", nameTrailing: isApplicant ? (_jsx(Badge, { variant: "warning", bordered: true, children: "Applicant" })) : undefined, role: hasSenderProfileRole ? (_jsx("span", { "data-slot": "message-author-role", children: senderProfileRole })) : undefined, rolePlacement: "below", className: "min-w-0 flex-1 [column-gap:var(--space-3)]", avatarClassName: "h-9 w-9 shrink-0", fallbackClassName: "text-xs font-medium", nameClassName: "max-w-full whitespace-normal break-words [overflow-wrap:anywhere]" }), _jsx("time", { className: "shrink-0 whitespace-nowrap pt-0.5", dateTime: messageDate.toISOString(), children: _jsx(Typography, { as: "span", variant: "caption", className: "text-muted-foreground/60", children: formatTimestamp
139
138
  ? formatTimestamp(messageDate, message)
140
139
  : formatMessageDate(messageDate) }) })] }), _jsxs("div", { className: "ml-[calc(2.25rem+var(--space-3))] pt-2", children: [_jsx(Typography, { as: "div", variant: "bodySm", color: "inherit", className: richContentClassName, dangerouslySetInnerHTML: { __html: contentHtml } }), attachments.length > 0 ? (_jsx("div", { className: "mt-3 space-y-2", children: attachments.map((attachment, idx) => (_jsx(MessageAttachmentRow, { attachment: attachment, downloadUrl: getAttachmentDownloadUrl === null || getAttachmentDownloadUrl === void 0 ? void 0 : getAttachmentDownloadUrl(attachment, message, downloadCaseId) }, `${attachment.name}-${idx}`))) })) : null] })] })] }));
141
140
  }
@@ -73,7 +73,7 @@ function NotificationItem({ notification, density = "default", labelLines = 2, d
73
73
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(notification);
74
74
  }
75
75
  };
76
- const content = (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", className: cn("mt-0.5 flex shrink-0 items-center justify-center rounded-control border", density === "compact" ? "h-7 w-7" : "h-8 w-8", notificationToneClasses[tone]), children: _jsx(Icon, { className: density === "compact" ? "h-3.5 w-3.5" : "h-4 w-4" }) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-start gap-3", children: [_jsx(Typography, { as: "span", variant: "bodySm", className: cn("min-w-0 text-left text-foreground", isUnread ? "font-semibold" : "font-medium", labelLineClasses[labelLines]), children: notification.title }), meta || (isUnread && unreadLabel !== null) ? (_jsxs("span", { className: "flex min-w-0 shrink-0 items-center justify-end gap-1.5 text-right", children: [meta ? (_jsx(Typography, { as: "span", variant: "caption", className: "min-w-0 max-w-24 truncate whitespace-nowrap text-muted-foreground", children: meta })) : null, isUnread && unreadLabel !== null ? (_jsx("span", { "data-slot": "notification-unread-indicator", className: "mt-1 h-2.5 w-2.5 shrink-0 rounded-full bg-primary ring-2 ring-background", children: _jsx("span", { className: "sr-only", children: unreadLabel }) })) : null] })) : null] }), notification.description !== undefined ? (_jsx(Typography, { as: "span", variant: "caption", className: cn("mt-1.5 block text-left", isUnread ? "text-foreground/75" : "text-muted-foreground", descriptionLineClasses[descriptionLines]), children: notification.description })) : null, hasActions ? (_jsx("span", { className: "mt-4 flex flex-wrap gap-2", children: actions.map((action, index) => {
76
+ const content = (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", className: cn("mt-0.5 flex shrink-0 items-center justify-center rounded-control border", density === "compact" ? "h-7 w-7" : "h-8 w-8", notificationToneClasses[tone]), children: _jsx(Icon, { className: density === "compact" ? "h-3.5 w-3.5" : "h-4 w-4" }) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-start gap-3", children: [_jsx(Typography, { as: "span", variant: "bodySm", className: cn("min-w-0 text-left text-foreground", isUnread ? "font-semibold" : "font-medium", labelLineClasses[labelLines]), children: notification.title }), meta || (isUnread && unreadLabel !== null) ? (_jsxs("span", { className: "flex min-w-0 shrink-0 items-center justify-end gap-1.5 text-right", children: [meta ? (_jsx(Typography, { as: "span", variant: "caption", className: "min-w-0 max-w-24 truncate whitespace-nowrap text-muted-foreground/60", children: meta })) : null, isUnread && unreadLabel !== null ? (_jsx("span", { "data-slot": "notification-unread-indicator", className: "mt-1 h-2.5 w-2.5 shrink-0 rounded-full bg-primary ring-2 ring-background", children: _jsx("span", { className: "sr-only", children: unreadLabel }) })) : null] })) : null] }), notification.description !== undefined ? (_jsx(Typography, { as: "span", variant: "caption", className: cn("mt-1.5 block text-left", isUnread ? "text-foreground/75" : "text-muted-foreground", descriptionLineClasses[descriptionLines]), children: notification.description })) : null, hasActions ? (_jsx("span", { className: "mt-4 flex flex-wrap gap-2", children: actions.map((action, index) => {
77
77
  var _a, _b;
78
78
  return (_jsx(Button, { type: "button", variant: (_a = action.variant) !== null && _a !== void 0 ? _a : (index === 0 ? "outline" : "default"), size: "sm", disabled: action.disabled, className: cn("min-w-24", action.className), onClick: (event) => {
79
79
  var _a;
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ export type PageLayoutGap = "page" | "header" | "section" | "control" | "context";
3
+ export type PageLayoutStackGap = Exclude<PageLayoutGap, "page"> | "title";
4
+ declare const pageLayoutGapClassNames: Record<PageLayoutGap, string>;
5
+ declare const pageLayoutStackGapClassNames: Record<PageLayoutStackGap, string>;
6
+ export interface PageLayoutProps extends React.HTMLAttributes<HTMLDivElement> {
7
+ gap?: PageLayoutGap;
8
+ }
9
+ declare function PageLayout({ gap, className, ...props }: PageLayoutProps): import("react/jsx-runtime").JSX.Element;
10
+ export interface PageLayoutStackProps extends React.HTMLAttributes<HTMLDivElement> {
11
+ gap?: PageLayoutStackGap;
12
+ titleOffset?: boolean;
13
+ }
14
+ declare function PageLayoutStack({ gap, titleOffset, className, ...props }: PageLayoutStackProps): import("react/jsx-runtime").JSX.Element;
15
+ type PageLayoutNamedStackProps = Omit<PageLayoutStackProps, "gap">;
16
+ export type PageLayoutTitleProps = PageLayoutNamedStackProps;
17
+ declare function PageLayoutTitle(props: PageLayoutTitleProps): import("react/jsx-runtime").JSX.Element;
18
+ declare function PageLayoutHeader(props: PageLayoutNamedStackProps): import("react/jsx-runtime").JSX.Element;
19
+ declare function PageLayoutSection(props: PageLayoutNamedStackProps): import("react/jsx-runtime").JSX.Element;
20
+ declare function PageLayoutControls(props: PageLayoutNamedStackProps): import("react/jsx-runtime").JSX.Element;
21
+ declare function PageLayoutContext(props: PageLayoutNamedStackProps): import("react/jsx-runtime").JSX.Element;
22
+ export { PageLayout, PageLayoutStack, PageLayoutTitle, PageLayoutHeader, PageLayoutSection, PageLayoutControls, PageLayoutContext, pageLayoutGapClassNames, pageLayoutStackGapClassNames, };
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "./lib/utils";
3
+ const pageLayoutGapClassNames = {
4
+ page: "space-y-[var(--layout-page-gap)]",
5
+ header: "space-y-[var(--layout-page-header-gap)]",
6
+ section: "space-y-[var(--layout-page-section-gap)]",
7
+ control: "space-y-[var(--layout-page-control-gap)]",
8
+ context: "space-y-[var(--layout-page-context-gap)]",
9
+ };
10
+ const pageLayoutStackGapClassNames = {
11
+ header: pageLayoutGapClassNames.header,
12
+ section: pageLayoutGapClassNames.section,
13
+ control: pageLayoutGapClassNames.control,
14
+ context: pageLayoutGapClassNames.context,
15
+ title: "space-y-[var(--space-1)]",
16
+ };
17
+ function PageLayout({ gap = "page", className, ...props }) {
18
+ return (_jsx("div", { "data-slot": "page-layout", className: cn(pageLayoutGapClassNames[gap], className), ...props }));
19
+ }
20
+ function PageLayoutStack({ gap = "section", titleOffset = false, className, ...props }) {
21
+ return (_jsx("div", { "data-slot": "page-layout-stack", className: cn(pageLayoutStackGapClassNames[gap], titleOffset && "pt-[var(--layout-page-title-offset)]", className), ...props }));
22
+ }
23
+ function PageLayoutTitle(props) {
24
+ return (_jsx(PageLayoutStack, { gap: "title", "data-slot": "page-layout-title", ...props }));
25
+ }
26
+ function PageLayoutHeader(props) {
27
+ return (_jsx(PageLayoutStack, { gap: "header", "data-slot": "page-layout-header", ...props }));
28
+ }
29
+ function PageLayoutSection(props) {
30
+ return (_jsx(PageLayoutStack, { gap: "section", "data-slot": "page-layout-section", ...props }));
31
+ }
32
+ function PageLayoutControls(props) {
33
+ return (_jsx(PageLayoutStack, { gap: "control", "data-slot": "page-layout-controls", ...props }));
34
+ }
35
+ function PageLayoutContext(props) {
36
+ return (_jsx(PageLayoutStack, { gap: "context", "data-slot": "page-layout-context", ...props }));
37
+ }
38
+ export { PageLayout, PageLayoutStack, PageLayoutTitle, PageLayoutHeader, PageLayoutSection, PageLayoutControls, PageLayoutContext, pageLayoutGapClassNames, pageLayoutStackGapClassNames, };
@@ -9,6 +9,6 @@ function PageSectionGroup({ variant = "divided", className, ...props }) {
9
9
  function PageSection({ title, description, headerAction, titleAdornment, className, headerClassName, contentClassName, children, ...props }) {
10
10
  const renderedTitle = React.isValidElement(title) ? (title) : (_jsx(Typography, { as: "h3", variant: "subheading", children: title }));
11
11
  const renderedDescription = description == null ? null : React.isValidElement(description) ? (description) : (_jsx(Typography, { as: "p", variant: "caption", children: description }));
12
- return (_jsxs("section", { "data-slot": "page-section", className: cn("py-6", className), ...props, children: [_jsxs("div", { className: cn("flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", headerClassName), children: [_jsxs("div", { className: "min-w-0 space-y-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [renderedTitle, titleAdornment] }), renderedDescription] }), headerAction ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-1.5 sm:shrink-0", children: headerAction })) : null] }), children ? (_jsx("div", { className: cn("pt-4", contentClassName), children: children })) : null] }));
12
+ return (_jsxs("section", { "data-slot": "page-section", className: cn("py-6", className), ...props, children: [_jsxs("div", { className: cn("flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", headerClassName), children: [_jsxs("div", { className: "min-w-0 space-y-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [renderedTitle, titleAdornment] }), renderedDescription] }), headerAction ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-3 sm:shrink-0", children: headerAction })) : null] }), children ? (_jsx("div", { className: cn("pt-4", contentClassName), children: children })) : null] }));
13
13
  }
14
14
  export { PageSection, PageSectionGroup };
@@ -19,7 +19,7 @@ function PopoverMenuSection({ className, children, ...props }) {
19
19
  return (_jsx("div", { className: cn("space-y-0", className), ...props, children: children }));
20
20
  }
21
21
  function PopoverMenuItem({ className, children, active, type = "button", ...props }) {
22
- return (_jsxs(Button, { type: type, variant: "ghost", className: cn("h-auto min-h-8 w-full justify-start gap-2 rounded-sm px-2 py-2 text-left font-normal whitespace-normal", active &&
22
+ return (_jsxs(Button, { type: type, variant: "ghost", className: cn("h-auto min-h-8 w-full justify-start gap-2 rounded-sm px-2 py-2 text-left font-normal whitespace-normal focus-visible:ring-inset focus-visible:ring-1 focus-visible:ring-offset-0", active &&
23
23
  "bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground", className), ...props, children: [children, active ? _jsx(Check, { "aria-hidden": "true", className: "ml-auto h-4 w-4 shrink-0" }) : null] }));
24
24
  }
25
25
  function PopoverMenuCheckboxItem({ className, children, checked = false, description, disabled, onChange, readOnly, ...props }) {
@@ -33,7 +33,7 @@ function PopoverMenuFooter({ className, children, inset = "menu", ...props }) {
33
33
  return (_jsx("div", { className: cn("flex items-center gap-2 border-t p-1.5", inset === "menu" && "-mx-1 -mb-1", inset === "flush" && "m-0", className), ...props, children: children }));
34
34
  }
35
35
  function PopoverMenuFooterAction({ className, type = "button", ...props }) {
36
- return (_jsx(Button, { type: type, variant: "ghost", size: "sm", className: cn("h-auto min-h-8 w-full justify-start px-2 py-1.5 text-left whitespace-normal", className), ...props }));
36
+ return (_jsx(Button, { type: type, variant: "ghost", size: "sm", className: cn("h-auto min-h-8 w-full justify-start px-2 py-1.5 text-left whitespace-normal focus-visible:ring-inset focus-visible:ring-1 focus-visible:ring-offset-0", className), ...props }));
37
37
  }
38
38
  function PopoverMenuFooterMeta({ className, children, ...props }) {
39
39
  return (_jsx(Typography, { as: "span", variant: "bodySm", color: "muted", className: cn("shrink-0 px-2 font-medium", className), ...props, children: children }));
@@ -52,7 +52,7 @@ function RoutingTimeline({ items, emptyMessage = "No routing activity yet.", cla
52
52
  const hasCompleteRoute = Boolean(item.from && item.to);
53
53
  const title = (_b = item.title) !== null && _b !== void 0 ? _b : config.title;
54
54
  const remark = (_c = item.remark) !== null && _c !== void 0 ? _c : item.description;
55
- return (_jsxs("li", { className: "relative grid grid-cols-[var(--space-3)_minmax(0,1fr)] gap-[var(--space-3)] pb-[var(--space-5)] last:pb-0", children: [_jsx("div", { className: "relative flex justify-center", children: _jsx("span", { "aria-hidden": "true", "data-slot": "routing-timeline-marker", className: cn("relative z-10 mt-[var(--space-1)] size-[var(--space-2)] rounded-full border", config.markerClassName) }) }), _jsxs("div", { "data-slot": "routing-timeline-event-card", className: "min-w-0 rounded-surface border border-border/70 bg-card p-[var(--space-3)] text-card-foreground", children: [_jsxs("div", { className: "min-w-0 space-y-[var(--space-1)]", children: [_jsxs("div", { className: "flex min-w-0 items-start justify-between gap-[var(--space-2)]", children: [_jsx(Typography, { as: "p", variant: "label", className: "min-w-0 flex-1 font-semibold", children: title }), _jsx(Badge, { variant: config.badgeVariant, bordered: true, className: "max-w-full shrink-0 self-start", children: (_d = item.badgeLabel) !== null && _d !== void 0 ? _d : config.label })] }), item.timestamp || item.actor ? (_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-[var(--space-1)] gap-y-[var(--space-1)]", children: [item.timestamp ? (_jsx(Typography, { as: "time", variant: "caption", className: "shrink-0", children: item.timestamp })) : null, item.actor ? (_jsxs(Typography, { as: "p", variant: "caption", className: "inline-flex min-w-0 items-center gap-x-[var(--space-1)]", children: [item.timestamp ? (_jsx("span", { "aria-hidden": "true", children: "\u00B7" })) : null, "By ", item.actor] })) : null] })) : null] }), remark ? (_jsx(Typography, { as: "div", variant: "bodySm", "data-slot": "routing-timeline-remark", className: "mt-[var(--space-4)] font-normal", children: remark })) : null, hasRouteEndpoints ? (_jsxs("footer", { "data-slot": "routing-timeline-handoff", "data-complete-route": hasCompleteRoute ? "true" : undefined, className: "mt-[var(--space-4)] flex flex-col space-y-[var(--space-2)] text-xs text-muted-foreground", children: [item.from ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.from })) : null, item.from && item.to ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "sr-only", children: "to" }), _jsx(ArrowDown, { "aria-hidden": "true", "data-slot": "routing-timeline-handoff-arrow", className: "ml-1 size-4 shrink-0 text-muted-foreground" })] })) : null, item.to ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.to })) : null] })) : null] })] }, item.id));
55
+ return (_jsxs("li", { className: "relative grid grid-cols-[var(--space-3)_minmax(0,1fr)] gap-[var(--space-3)] pb-[var(--space-5)] last:pb-0", children: [_jsx("div", { className: "relative flex justify-center", children: _jsx("span", { "aria-hidden": "true", "data-slot": "routing-timeline-marker", className: cn("relative z-10 mt-[var(--space-1)] size-[var(--space-2)] rounded-full border", config.markerClassName) }) }), _jsxs("div", { "data-slot": "routing-timeline-event-card", className: "min-w-0 rounded-surface border border-border/70 bg-card p-[var(--space-3)] text-card-foreground", children: [_jsxs("div", { className: "min-w-0 space-y-[var(--space-1)]", children: [_jsxs("div", { className: "flex min-w-0 items-start justify-between gap-[var(--space-2)]", children: [_jsx(Typography, { as: "p", variant: "label", className: "min-w-0 flex-1 font-semibold", children: title }), _jsx(Badge, { variant: config.badgeVariant, bordered: true, className: "max-w-full shrink-0 self-start", children: (_d = item.badgeLabel) !== null && _d !== void 0 ? _d : config.label })] }), item.timestamp || item.actor ? (_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-[var(--space-1)] gap-y-[var(--space-1)]", children: [item.timestamp ? (_jsx(Typography, { as: "time", variant: "caption", className: "shrink-0 text-muted-foreground/60", children: item.timestamp })) : null, item.actor ? (_jsxs(Typography, { as: "p", variant: "caption", className: "inline-flex min-w-0 items-center gap-x-[var(--space-1)]", children: [item.timestamp ? (_jsx("span", { "aria-hidden": "true", children: "\u00B7" })) : null, "By ", item.actor] })) : null] })) : null] }), remark ? (_jsx(Typography, { as: "div", variant: "bodySm", "data-slot": "routing-timeline-remark", className: "mt-[var(--space-4)] font-normal", children: remark })) : null, hasRouteEndpoints ? (_jsxs("footer", { "data-slot": "routing-timeline-handoff", "data-complete-route": hasCompleteRoute ? "true" : undefined, className: "mt-[var(--space-4)] flex flex-col space-y-[var(--space-2)] text-xs text-muted-foreground", children: [item.from ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.from })) : null, item.from && item.to ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "sr-only", children: "to" }), _jsx(ArrowDown, { "aria-hidden": "true", "data-slot": "routing-timeline-handoff-arrow", className: "ml-1 size-4 shrink-0 text-muted-foreground" })] })) : null, item.to ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.to })) : null] })) : null] })] }, item.id));
56
56
  }) }) }));
57
57
  }
58
58
  export { RoutingTimeline };