@caratlogic/design-system 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/layouts/AppShell/DashboardShell.d.ts.map +1 -1
- package/dist/components/molecules/Sidebar/Sidebar.parts.d.ts.map +1 -1
- package/dist/index.cjs.js +54 -5
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +54 -5
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -57449,7 +57449,11 @@ const SidebarInset = React.forwardRef(({ className, ...props }, ref) => (jsx("ma
|
|
|
57449
57449
|
SidebarInset.displayName = 'SidebarInset';
|
|
57450
57450
|
const SidebarInput = React.forwardRef(({ className, ...props }, ref) => (jsx("input", { ref: ref, "data-sidebar": "input", className: cn('h-8 w-full bg-background text-sm shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring', className), ...props })));
|
|
57451
57451
|
SidebarInput.displayName = 'SidebarInput';
|
|
57452
|
-
const SidebarHeader = React.forwardRef(({ className, ...props }, ref) => (jsx("div", { ref: ref, "data-sidebar": "header",
|
|
57452
|
+
const SidebarHeader = React.forwardRef(({ className, ...props }, ref) => (jsx("div", { ref: ref, "data-sidebar": "header",
|
|
57453
|
+
/* Icon mode drops the asymmetric pl-4/pr-1 (which is there for the expanded
|
|
57454
|
+
brand + collapse button row) so a centred brand lands on the same axis as
|
|
57455
|
+
the nav icons below it. */
|
|
57456
|
+
className: cn('flex flex-col gap-2 pr-1 pt-3 pb-4 pl-4 group-data-[collapsible=icon]:px-0', className), ...props })));
|
|
57453
57457
|
SidebarHeader.displayName = 'SidebarHeader';
|
|
57454
57458
|
const SidebarFooter = React.forwardRef(({ className, ...props }, ref) => (jsx("div", { ref: ref, "data-sidebar": "footer", className: cn('flex flex-col gap-2 pr-1 py-4 pl-4', className), ...props })));
|
|
57455
57459
|
SidebarFooter.displayName = 'SidebarFooter';
|
|
@@ -57475,6 +57479,21 @@ const SidebarMenu = React.forwardRef(({ className, ...props }, ref) => (jsx("ul"
|
|
|
57475
57479
|
SidebarMenu.displayName = 'SidebarMenu';
|
|
57476
57480
|
const SidebarMenuItem = React.forwardRef(({ className, ...props }, ref) => (jsx("li", { ref: ref, "data-sidebar": "menu-item", className: cn('group/menu-item relative', className), ...props })));
|
|
57477
57481
|
SidebarMenuItem.displayName = 'SidebarMenuItem';
|
|
57482
|
+
/**
|
|
57483
|
+
* Owns a nav tooltip's open state so every tooltip closes when the sidebar
|
|
57484
|
+
* expands or collapses. The width transition slides buttons out from under a
|
|
57485
|
+
* stationary pointer without firing `pointerleave`, so Radix otherwise keeps
|
|
57486
|
+
* each tooltip it opened on the way in — they surface together the moment the
|
|
57487
|
+
* rail renders them, and only a fresh hover dismisses them one by one.
|
|
57488
|
+
*/
|
|
57489
|
+
const useSidebarTooltipOpen = () => {
|
|
57490
|
+
const { state } = useSidebar();
|
|
57491
|
+
const [open, setOpen] = React.useState(false);
|
|
57492
|
+
React.useEffect(() => {
|
|
57493
|
+
setOpen(false);
|
|
57494
|
+
}, [state]);
|
|
57495
|
+
return { open, setOpen };
|
|
57496
|
+
};
|
|
57478
57497
|
const sidebarMenuButtonVariants = cva('peer/menu-button relative flex h-9 w-full cursor-pointer items-center gap-2 overflow-hidden rounded-sm px-2.5 py-1.5 text-left text-sm text-sidebar-foreground outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-active-bg data-[active=true]:text-sidebar-foreground data-[state=open]:hover:bg-sidebar-active-bg data-[state=open]:hover:text-sidebar-foreground group-data-[collapsible=icon]:!size-9 group-data-[collapsible=icon]:!p-2 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:[&>span]:hidden [&>span]:truncate [&>svg]:size-4 [&>svg]:shrink-0', {
|
|
57479
57498
|
variants: {
|
|
57480
57499
|
variant: {
|
|
@@ -57497,13 +57516,15 @@ const SidebarMenuButton = React.forwardRef(({ asChild = false, isActive = false,
|
|
|
57497
57516
|
const { state } = useSidebar();
|
|
57498
57517
|
const [innerRef, setRef] = useForwardedRef(ref);
|
|
57499
57518
|
const truncatedText = useTruncatedText(innerRef);
|
|
57519
|
+
const { open: tooltipOpen, setOpen: setTooltipOpen } = useSidebarTooltipOpen();
|
|
57500
57520
|
const button = (jsx(Comp, { ref: setRef, "data-sidebar": "menu-button", "data-size": size, "data-active": isActive, className: cn(sidebarMenuButtonVariants({ variant, size }), className), ...props }));
|
|
57501
57521
|
// Tooltip when collapsed (icon-only) OR when the expanded label is clipped.
|
|
57502
57522
|
// The Tooltip structure stays mounted and only the content is conditional,
|
|
57503
57523
|
// so toggling it never remounts the button.
|
|
57504
57524
|
const collapsed = !!tooltip && state === 'collapsed';
|
|
57505
57525
|
const collapsedProps = typeof tooltip === 'string' ? { children: tooltip } : tooltip;
|
|
57506
|
-
|
|
57526
|
+
const tooltipContent = collapsed ? (jsx(TooltipContent, { side: "right", align: "center", className: TRUNCATION_TOOLTIP_CLASS, ...collapsedProps })) : truncatedText ? (jsx(TooltipContent, { side: "right", align: "center", className: TRUNCATION_TOOLTIP_CLASS, children: truncatedText })) : null;
|
|
57527
|
+
return (jsxs(Tooltip, { open: !!tooltipContent && tooltipOpen, onOpenChange: setTooltipOpen, children: [jsx(TooltipTrigger, { asChild: true, children: button }), tooltipContent] }));
|
|
57507
57528
|
});
|
|
57508
57529
|
SidebarMenuButton.displayName = 'SidebarMenuButton';
|
|
57509
57530
|
const SidebarMenuAction = React.forwardRef(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
|
|
@@ -57527,9 +57548,10 @@ const SidebarMenuSubButton = React.forwardRef(({ asChild = false, size = 'md', i
|
|
|
57527
57548
|
const Comp = asChild ? Slot : 'a';
|
|
57528
57549
|
const [innerRef, setRef] = useForwardedRef(ref);
|
|
57529
57550
|
const truncatedText = useTruncatedText(innerRef);
|
|
57551
|
+
const { open: tooltipOpen, setOpen: setTooltipOpen } = useSidebarTooltipOpen();
|
|
57530
57552
|
const button = (jsx(Comp, { ref: setRef, "data-sidebar": "menu-sub-button", "data-size": size, "data-active": isActive, className: cn('relative flex h-9 w-full min-w-0 cursor-pointer items-center gap-2 overflow-hidden rounded-sm pl-3 pr-1 py-1.5 text-left text-sidebar-foreground/80 outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span]:truncate [&>svg]:size-4 [&>svg]:shrink-0', 'data-[active=true]:bg-sidebar-primary data-[active=true]:text-sidebar-primary-foreground', size === 'sm' && 'text-xs', size === 'md' && 'text-sm', 'group-data-[collapsible=icon]:hidden', className), ...props }));
|
|
57531
57553
|
// Keep the Tooltip mounted; render the content only when the label is clipped.
|
|
57532
|
-
return (jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: button }), truncatedText && (jsx(TooltipContent, { side: "right", align: "center", className: TRUNCATION_TOOLTIP_CLASS, children: truncatedText }))] }));
|
|
57554
|
+
return (jsxs(Tooltip, { open: !!truncatedText && tooltipOpen, onOpenChange: setTooltipOpen, children: [jsx(TooltipTrigger, { asChild: true, children: button }), truncatedText && (jsx(TooltipContent, { side: "right", align: "center", className: TRUNCATION_TOOLTIP_CLASS, children: truncatedText }))] }));
|
|
57533
57555
|
});
|
|
57534
57556
|
SidebarMenuSubButton.displayName = 'SidebarMenuSubButton';
|
|
57535
57557
|
const Collapsible = CollapsiblePrimitive.Root;
|
|
@@ -65799,6 +65821,15 @@ const DEFAULT_SIDEBAR_WIDTH = '248px';
|
|
|
65799
65821
|
/** Green pill marking the active top-level item. Rendered in-flow as the row's
|
|
65800
65822
|
* first flex child (hidden when the sidebar collapses to icons). */
|
|
65801
65823
|
const ActiveRail = () => (jsx("span", { "aria-hidden": "true", className: "pointer-events-none h-9 w-[4px] shrink-0 rounded-full bg-sidebar-primary group-data-[collapsible=icon]:hidden" }));
|
|
65824
|
+
/** Collapsed, the rail is also the way back into the menu: clicking any nav
|
|
65825
|
+
* item opens the sidebar, not just the brand. */
|
|
65826
|
+
const useCollapsedSidebar = () => {
|
|
65827
|
+
const { state, isMobile, setOpen } = useSidebar();
|
|
65828
|
+
return {
|
|
65829
|
+
collapsed: !isMobile && state === 'collapsed',
|
|
65830
|
+
expandSidebar: () => setOpen(true),
|
|
65831
|
+
};
|
|
65832
|
+
};
|
|
65802
65833
|
const BrandHeader = ({ brand }) => {
|
|
65803
65834
|
const { state, isMobile, openMobile, toggleSidebar } = useSidebar();
|
|
65804
65835
|
const expanded = state === 'expanded' || (isMobile && openMobile);
|
|
@@ -65810,13 +65841,31 @@ const BrandHeader = ({ brand }) => {
|
|
|
65810
65841
|
const NavLeaf = ({ item, currentPath, onNavigate }) => {
|
|
65811
65842
|
const Icon = item.icon;
|
|
65812
65843
|
const active = isPathActive(currentPath, item.path);
|
|
65813
|
-
|
|
65844
|
+
const { collapsed, expandSidebar } = useCollapsedSidebar();
|
|
65845
|
+
return (jsxs(SidebarMenuItem, { className: cn(active && 'flex items-center gap-1.5 group-data-[collapsible=icon]:block'), children: [active && jsx(ActiveRail, {}), jsxs(SidebarMenuButton, { isActive: active, tooltip: item.label, onClick: () => {
|
|
65846
|
+
if (collapsed)
|
|
65847
|
+
expandSidebar();
|
|
65848
|
+
if (item.path)
|
|
65849
|
+
onNavigate(item.path);
|
|
65850
|
+
}, className: cn(active && 'min-w-0 flex-1 group-data-[collapsible=icon]:flex-none'), children: [Icon && jsx(Icon, {}), jsx("span", { children: item.label })] }), item.badge != null && (jsx(SidebarMenuBadge, { className: "h-5 w-5 min-w-5 rounded-full border border-primary bg-primary/10 p-0 text-primary", children: item.badge }))] }));
|
|
65814
65851
|
};
|
|
65815
65852
|
const NavParent = ({ item, currentPath, onNavigate }) => {
|
|
65816
65853
|
const Icon = item.icon;
|
|
65817
65854
|
const children = (item.children ?? []).filter((s) => s.visible !== false);
|
|
65818
65855
|
const parentActive = children.some((s) => isPathActive(currentPath, s.path));
|
|
65819
|
-
|
|
65856
|
+
const { collapsed, expandSidebar } = useCollapsedSidebar();
|
|
65857
|
+
const [open, setOpen] = useState(parentActive);
|
|
65858
|
+
// Collapsed, the sub-menu is hidden, so a click opens the sidebar and this
|
|
65859
|
+
// group instead of silently toggling something the user cannot see.
|
|
65860
|
+
const handleOpenChange = (next) => {
|
|
65861
|
+
if (!collapsed) {
|
|
65862
|
+
setOpen(next);
|
|
65863
|
+
return;
|
|
65864
|
+
}
|
|
65865
|
+
expandSidebar();
|
|
65866
|
+
setOpen(true);
|
|
65867
|
+
};
|
|
65868
|
+
return (jsx(Collapsible, { asChild: true, open: open, onOpenChange: handleOpenChange, children: jsxs(SidebarMenuItem, { className: "group/collapsible", children: [jsxs("div", { className: cn(parentActive &&
|
|
65820
65869
|
'flex items-center gap-1.5 group-data-[collapsible=icon]:block'), children: [parentActive && jsx(ActiveRail, {}), jsx(CollapsibleTrigger, { asChild: true, children: jsxs(SidebarMenuButton, { isActive: parentActive, tooltip: item.label, className: cn(parentActive &&
|
|
65821
65870
|
'min-w-0 flex-1 group-data-[collapsible=icon]:flex-none'), children: [Icon && jsx(Icon, {}), jsx("span", { children: item.label }), jsx(ChevronRight, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90 group-data-[collapsible=icon]:hidden" })] }) })] }), jsx(CollapsibleContent, { children: jsx(SidebarMenuSub, { children: children.map((sub) => {
|
|
65822
65871
|
const SubIcon = sub.icon;
|