@flipdish/ui-library 0.33.0 → 0.34.1
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/atoms/Flag/flag.utils.cjs +1 -1
- package/dist/components/atoms/Flag/flag.utils.cjs.map +1 -1
- package/dist/components/atoms/Flag/flag.utils.js +2 -2
- package/dist/components/atoms/Flag/flag.utils.js.map +1 -1
- package/dist/components/molecules/CodeSnippet/codeSnippet.utils.cjs +73 -0
- package/dist/components/molecules/CodeSnippet/codeSnippet.utils.cjs.map +1 -1
- package/dist/components/molecules/CodeSnippet/codeSnippet.utils.d.ts +48 -0
- package/dist/components/molecules/CodeSnippet/codeSnippet.utils.d.ts.map +1 -1
- package/dist/components/molecules/CodeSnippet/codeSnippet.utils.js +70 -1
- package/dist/components/molecules/CodeSnippet/codeSnippet.utils.js.map +1 -1
- package/dist/components/molecules/CodeSnippet/hooks/useCodeSnippetHighlight.cjs +24 -2
- package/dist/components/molecules/CodeSnippet/hooks/useCodeSnippetHighlight.cjs.map +1 -1
- package/dist/components/molecules/CodeSnippet/hooks/useCodeSnippetHighlight.d.ts +2 -1
- package/dist/components/molecules/CodeSnippet/hooks/useCodeSnippetHighlight.d.ts.map +1 -1
- package/dist/components/molecules/CodeSnippet/hooks/useCodeSnippetHighlight.js +25 -3
- package/dist/components/molecules/CodeSnippet/hooks/useCodeSnippetHighlight.js.map +1 -1
- package/dist/components/molecules/CodeSnippet/index.cjs +7 -25
- package/dist/components/molecules/CodeSnippet/index.cjs.map +1 -1
- package/dist/components/molecules/CodeSnippet/index.d.ts +8 -4
- package/dist/components/molecules/CodeSnippet/index.d.ts.map +1 -1
- package/dist/components/molecules/CodeSnippet/index.js +8 -26
- package/dist/components/molecules/CodeSnippet/index.js.map +1 -1
- package/dist/components/organisms/Calendar/calendar.utils.cjs +35 -0
- package/dist/components/organisms/Calendar/calendar.utils.cjs.map +1 -1
- package/dist/components/organisms/Calendar/calendar.utils.d.ts +29 -0
- package/dist/components/organisms/Calendar/calendar.utils.d.ts.map +1 -1
- package/dist/components/organisms/Calendar/calendar.utils.js +36 -2
- package/dist/components/organisms/Calendar/calendar.utils.js.map +1 -1
- package/dist/components/organisms/Calendar/hooks/useCalendarClock.cjs +30 -0
- package/dist/components/organisms/Calendar/hooks/useCalendarClock.cjs.map +1 -0
- package/dist/components/organisms/Calendar/hooks/useCalendarClock.d.ts +12 -0
- package/dist/components/organisms/Calendar/hooks/useCalendarClock.d.ts.map +1 -0
- package/dist/components/organisms/Calendar/hooks/useCalendarClock.js +28 -0
- package/dist/components/organisms/Calendar/hooks/useCalendarClock.js.map +1 -0
- package/dist/components/organisms/Calendar/index.cjs +13 -42
- package/dist/components/organisms/Calendar/index.cjs.map +1 -1
- package/dist/components/organisms/Calendar/index.d.ts.map +1 -1
- package/dist/components/organisms/Calendar/index.js +15 -44
- package/dist/components/organisms/Calendar/index.js.map +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavAccountCard.cjs +9 -2
- package/dist/components/organisms/SidebarNavigation/components/NavAccountCard.cjs.map +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavAccountCard.d.ts +12 -1
- package/dist/components/organisms/SidebarNavigation/components/NavAccountCard.d.ts.map +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavAccountCard.js +9 -2
- package/dist/components/organisms/SidebarNavigation/components/NavAccountCard.js.map +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavItem.cjs +10 -4
- package/dist/components/organisms/SidebarNavigation/components/NavItem.cjs.map +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavItem.d.ts +12 -1
- package/dist/components/organisms/SidebarNavigation/components/NavItem.d.ts.map +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavItem.js +10 -4
- package/dist/components/organisms/SidebarNavigation/components/NavItem.js.map +1 -1
- package/dist/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.cjs +85 -0
- package/dist/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.cjs.map +1 -0
- package/dist/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.d.ts +47 -0
- package/dist/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.d.ts.map +1 -0
- package/dist/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.js +82 -0
- package/dist/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.js.map +1 -0
- package/dist/components/organisms/SidebarNavigation/index.cjs +19 -26
- package/dist/components/organisms/SidebarNavigation/index.cjs.map +1 -1
- package/dist/components/organisms/SidebarNavigation/index.d.ts.map +1 -1
- package/dist/components/organisms/SidebarNavigation/index.js +19 -26
- package/dist/components/organisms/SidebarNavigation/index.js.map +1 -1
- package/dist/utilities/renderUtils/index.cjs +21 -0
- package/dist/utilities/renderUtils/index.cjs.map +1 -1
- package/dist/utilities/renderUtils/index.d.ts +10 -0
- package/dist/utilities/renderUtils/index.d.ts.map +1 -1
- package/dist/utilities/renderUtils/index.js +21 -1
- package/dist/utilities/renderUtils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/organisms/SidebarNavigation/components/NavButton.cjs +0 -32
- package/dist/components/organisms/SidebarNavigation/components/NavButton.cjs.map +0 -1
- package/dist/components/organisms/SidebarNavigation/components/NavButton.d.ts +0 -36
- package/dist/components/organisms/SidebarNavigation/components/NavButton.d.ts.map +0 -1
- package/dist/components/organisms/SidebarNavigation/components/NavButton.js +0 -30
- package/dist/components/organisms/SidebarNavigation/components/NavButton.js.map +0 -1
|
@@ -34,7 +34,7 @@ const NavAccountMenu = ({ className, menuItems = [], bottomMenuItems = [], testI
|
|
|
34
34
|
}, "data-testid": menuItemTestId(prefix, item) }, item.label));
|
|
35
35
|
return (jsx(Dialog, { ...dialogProps, className: cx('w-66 rounded-xl bg-secondary_alt shadow-lg ring ring-secondary_alt outline-hidden', className), children: ({ close }) => (jsxs(Fragment, { children: [menuItems.length > 0 && (jsx("div", { className: "rounded-xl bg-primary ring-1 ring-secondary", children: jsx("div", { className: "flex flex-col gap-0.5 py-1.5", children: menuItems.map((item) => renderItem(item, close)) }) })), bottomMenuItems.length > 0 && jsx("div", { className: "pt-1 pb-1.5", children: bottomMenuItems.map((item) => renderItem(item, close)) })] })) }));
|
|
36
36
|
};
|
|
37
|
-
const NavAccountCard = ({ popoverPlacement, account, avatarRounded, menuItems, bottomMenuItems, variant = 'full', onOpenChange, 'data-testid': dataTestId, }) => {
|
|
37
|
+
const NavAccountCard = ({ popoverPlacement, account, avatarRounded, menuItems, bottomMenuItems, variant = 'full', collapsed, resizing, onOpenChange, 'data-testid': dataTestId, }) => {
|
|
38
38
|
const triggerRef = useRef(null);
|
|
39
39
|
const isDesktop = useBreakpoints('lg');
|
|
40
40
|
// The trigger is icon/avatar-only with no visible text, so it needs an explicit
|
|
@@ -45,7 +45,14 @@ const NavAccountCard = ({ popoverPlacement, account, avatarRounded, menuItems, b
|
|
|
45
45
|
if (variant === 'avatar') {
|
|
46
46
|
return (jsxs(DialogTrigger, { onOpenChange: onOpenChange, children: [jsx(Button, { "aria-label": triggerLabel, ...testIdProps(accountTestId), className: ({ isPressed, isFocused }) => cx('group relative inline-flex cursor-pointer rounded-full', (isPressed || isFocused) && 'outline-2 outline-offset-2 outline-focus-ring'), children: jsx(Avatar, { border: true, status: account.status, src: account.avatar, size: "md", alt: account.name, rounded: avatarRounded }) }), jsx(Popover, { placement: popoverPlacement ?? 'right bottom', offset: 8, crossOffset: 6, className: POPOVER_ANIMATION, children: menu })] }));
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
const isRail = collapsed !== undefined;
|
|
49
|
+
// In rail mode the text and chevron fade as one; the fade-in waits for the rail to open a little.
|
|
50
|
+
const fadeClassName = isRail && cx('transition-opacity motion-reduce:transition-none', collapsed ? 'opacity-0 duration-150' : 'delay-100 duration-150');
|
|
51
|
+
return (jsxs("div", { ref: triggerRef, className: cx('relative flex items-center rounded-xl bg-primary p-3 ring-1 ring-secondary ring-inset', isRail && 'transition-[padding,margin,background-color,box-shadow] duration-300 ease-out motion-reduce:transition-none',
|
|
52
|
+
// Collapsed, the card is the 44px avatar slot of the icon-only rail: 2px of padding around the 40px avatar, overhanging the 36px rows by 4px.
|
|
53
|
+
collapsed && '-mx-1 bg-transparent p-0.5 ring-transparent'), children: [jsx("div", { className: "-m-1 flex min-w-0 flex-1 overflow-hidden p-1", children: jsx(AvatarLabelGroup, { size: "md", src: account.avatar,
|
|
54
|
+
// Block spans keep each line single-line at its natural width while the card resizes, so the name never wraps as the card narrows.
|
|
55
|
+
title: jsx("span", { className: cx('block truncate', fadeClassName), children: account.name }), subtitle: jsx("span", { className: cx('block truncate', fadeClassName), children: account.email }), status: account.status, rounded: avatarRounded, className: resizing ? 'min-w-max' : undefined }) }), jsxs(DialogTrigger, { onOpenChange: onOpenChange, children: [jsx(Button, { "aria-label": triggerLabel, ...testIdProps(accountTestId), className: cx('peer absolute flex cursor-pointer items-center justify-center outline-focus-ring transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2', collapsed ? 'inset-0.5 rounded-full' : 'top-2 right-2 size-7 rounded-md hover:bg-primary_hover pressed:bg-primary_hover') }), jsx(Popover, { placement: popoverPlacement ?? (isDesktop ? 'right bottom' : 'top right'), triggerRef: triggerRef, offset: 8, className: POPOVER_ANIMATION, children: menu })] }), jsx(ChevronSelectorVertical, { "aria-hidden": "true", className: cx('pointer-events-none absolute top-3.5 right-3.5 size-4 shrink-0 stroke-[2.25px] text-fg-quaternary peer-hover:text-fg-quaternary_hover peer-pressed:text-fg-quaternary_hover', fadeClassName) })] }));
|
|
49
56
|
};
|
|
50
57
|
|
|
51
58
|
export { NavAccountCard, NavAccountMenu };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavAccountCard.js","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavAccountCard.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx","AriaLink","AriaDialog","_Fragment","AriaDialogTrigger","AriaButton","AriaPopover"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"NavAccountCard.js","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavAccountCard.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx","AriaLink","AriaDialog","_Fragment","AriaDialogTrigger","AriaButton","AriaPopover"],"mappings":"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"}
|
|
@@ -20,7 +20,8 @@ const styles = cx.sortCx({
|
|
|
20
20
|
rootSelected: 'bg-brand-primary hover:bg-brand-primary',
|
|
21
21
|
});
|
|
22
22
|
const StatusDot = ({ status }) => (jsxRuntime.jsx("span", { "aria-hidden": "true", className: cx.cx('mr-2 size-2 shrink-0 rounded-full', status === 'online' ? 'bg-success-solid' : 'bg-fg-quaternary') }));
|
|
23
|
-
const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, children, truncate = true, status, onClick, hasSubmenu, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'data-testid': dataTestId, }) => {
|
|
23
|
+
const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, children, truncate = true, status, onClick, hasSubmenu, collapsed, resizing, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'data-testid': dataTestId, }) => {
|
|
24
|
+
const isRail = collapsed !== undefined;
|
|
24
25
|
// `current` means "this is the current page" (→ aria-current); `selected` is the
|
|
25
26
|
// brand-highlight state (open/selected section), which may differ from the page.
|
|
26
27
|
const isSelected = selected ?? current;
|
|
@@ -28,11 +29,16 @@ const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, childre
|
|
|
28
29
|
useAriaDisclosureAttrs.useAriaDisclosureAttrs(linkRef, { ariaExpanded, ariaControls });
|
|
29
30
|
const iconElement = Icon && (jsxRuntime.jsx(Icon, { "aria-hidden": "true", className: cx.cx('mr-2 size-5 shrink-0 text-fg-quaternary transition-inherit-all group-hover/item:text-fg-quaternary_hover', isSelected && 'text-fg-brand-primary group-hover/item:text-fg-brand-primary') }));
|
|
30
31
|
const badgeElement = badge && (typeof badge === 'string' || typeof badge === 'number') ? (jsxRuntime.jsx(Badge.Badge, { className: "ml-3", color: isSelected ? 'brand' : 'gray', type: "pill-color", size: "sm", children: badge })) : (badge);
|
|
31
|
-
const labelElement = (jsxRuntime.jsx("span", { className: cx.cx('flex-1 text-sm font-semibold text-secondary transition-inherit-all group-hover/item:text-secondary_hover', truncate && 'truncate', isSelected && 'text-brand-secondary group-hover/item:text-brand-secondary'), children: children }));
|
|
32
|
+
const labelElement = (jsxRuntime.jsx("span", { className: cx.cx('flex-1 text-sm font-semibold text-secondary transition-inherit-all group-hover/item:text-secondary_hover', truncate && (resizing ? 'whitespace-nowrap' : 'truncate'), isSelected && 'text-brand-secondary group-hover/item:text-brand-secondary'), children: children }));
|
|
32
33
|
const isExternal = hrefUtils.isExternalHref(href);
|
|
33
34
|
const externalIcon = isExternal && jsxRuntime.jsx(uiIcons.Share04, { className: "size-4 stroke-[2.5px] text-fg-quaternary" });
|
|
34
35
|
// A trailing chevron on a section parent signals it has a revealable sub-navigation tier.
|
|
35
36
|
const submenuChevron = hasSubmenu && (jsxRuntime.jsx(uiIcons.ChevronRight, { "aria-hidden": "true", className: cx.cx('ml-3 size-4 shrink-0 stroke-[2.5px] text-fg-quaternary', isSelected && 'text-fg-brand-primary') }));
|
|
37
|
+
// Everything after the icon fades as one block in rail mode. While resizing it keeps its natural width so the
|
|
38
|
+
// row's edge wipes it in or out instead of the label reflowing; the fade-in waits for the rail to open a little.
|
|
39
|
+
const trailingElement = (jsxRuntime.jsxs("span", { className: cx.cx('flex flex-1 items-center', resizing ? 'shrink-0' : 'min-w-0', isRail && 'transition-opacity motion-reduce:transition-none', isRail && (collapsed ? 'opacity-0 duration-150' : 'delay-100 duration-150')), children: [labelElement, externalIcon, badgeElement, submenuChevron] }));
|
|
40
|
+
// The icon's margin and the trailing block overflow a collapsed row; clipping keeps the hover surface the row itself.
|
|
41
|
+
const railClassName = isRail && 'overflow-hidden';
|
|
36
42
|
if (type === 'collapsible') {
|
|
37
43
|
return (
|
|
38
44
|
// biome-ignore lint/a11y/noStaticElementInteractions: This is a summary element
|
|
@@ -43,9 +49,9 @@ const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, childre
|
|
|
43
49
|
}
|
|
44
50
|
// useButton forwards aria-expanded/aria-controls as plain props, unlike useLink — no ref workaround needed here.
|
|
45
51
|
if (type === 'disclosure') {
|
|
46
|
-
return (jsxRuntime.jsxs(reactAriaComponents.Button, { "data-testid": dataTestId, className: cx.cx('group/item p-2', styles.root, isSelected && styles.rootSelected), onClick: onClick, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, children: [status && jsxRuntime.jsx(StatusDot, { status: status }), iconElement,
|
|
52
|
+
return (jsxRuntime.jsxs(reactAriaComponents.Button, { "data-testid": dataTestId, className: cx.cx('group/item p-2', styles.root, isSelected && styles.rootSelected, railClassName), onClick: onClick, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, children: [status && jsxRuntime.jsx(StatusDot, { status: status }), iconElement, trailingElement] }));
|
|
47
53
|
}
|
|
48
|
-
return (jsxRuntime.jsxs(reactAriaComponents.Link, { ref: linkRef, href: hrefUtils.safeHref(href), target: isExternal ? '_blank' : '_self', rel: "noopener noreferrer", "data-testid": dataTestId, className: cx.cx('group/item p-2', styles.root, isSelected && styles.rootSelected), onClick: onClick, "aria-current": current ? 'page' : undefined, children: [status && jsxRuntime.jsx(StatusDot, { status: status }), iconElement,
|
|
54
|
+
return (jsxRuntime.jsxs(reactAriaComponents.Link, { ref: linkRef, href: hrefUtils.safeHref(href), target: isExternal ? '_blank' : '_self', rel: "noopener noreferrer", "data-testid": dataTestId, className: cx.cx('group/item p-2', styles.root, isSelected && styles.rootSelected, railClassName), onClick: onClick, "aria-current": current ? 'page' : undefined, children: [status && jsxRuntime.jsx(StatusDot, { status: status }), iconElement, trailingElement] }));
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
exports.NavItemBase = NavItemBase;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavItem.cjs","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavItem.tsx"],"sourcesContent":[null],"names":["sortCx","_jsx","cx","useRef","useAriaDisclosureAttrs","Badge","isExternalHref","Share04","ChevronRight","_jsxs","ChevronDown","AriaLink","safeHref","AriaButton"],"mappings":";;;;;;;;;;;AAWA;;;;AAIG;AACH,MAAM,MAAM,GAAGA,SAAM,CAAC;;AAEpB,IAAA,IAAI,EAAE,+QAA+Q;AACrR,IAAA,YAAY,EAAE,yCAAyC;AACxD,CAAA,CAAC;
|
|
1
|
+
{"version":3,"file":"NavItem.cjs","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavItem.tsx"],"sourcesContent":[null],"names":["sortCx","_jsx","cx","useRef","useAriaDisclosureAttrs","Badge","isExternalHref","Share04","ChevronRight","_jsxs","ChevronDown","AriaLink","safeHref","AriaButton"],"mappings":"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"}
|
|
@@ -18,6 +18,17 @@ interface NavItemBaseProps {
|
|
|
18
18
|
selected?: boolean;
|
|
19
19
|
/** Whether to truncate the label text. */
|
|
20
20
|
truncate?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Rail mode, for `link` and `disclosure` items in the collapsible sidebar: `true` shrinks the item to its
|
|
23
|
+
* icon, fading out the label, badge and chevron as the row narrows with the rail; `false` fades them back
|
|
24
|
+
* in. The label stays in the DOM so the item keeps its accessible name. Omit outside the rail.
|
|
25
|
+
*/
|
|
26
|
+
collapsed?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Set while the rail animates between widths. The label keeps its full width and is clipped by the row's
|
|
29
|
+
* edge instead of re-truncating every frame, so a long label never reflows mid-motion.
|
|
30
|
+
*/
|
|
31
|
+
resizing?: boolean;
|
|
21
32
|
/** Optional leading status dot rendered before the icon. */
|
|
22
33
|
status?: NavItemStatus;
|
|
23
34
|
/** Handler for click events. */
|
|
@@ -33,6 +44,6 @@ interface NavItemBaseProps {
|
|
|
33
44
|
/** Content to display. */
|
|
34
45
|
children?: ReactNode;
|
|
35
46
|
}
|
|
36
|
-
export declare const NavItemBase: ({ current, selected, type, badge, href, icon: Icon, children, truncate, status, onClick, hasSubmenu, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, "data-testid": dataTestId, }: NavItemBaseProps) => import("react").JSX.Element;
|
|
47
|
+
export declare const NavItemBase: ({ current, selected, type, badge, href, icon: Icon, children, truncate, status, onClick, hasSubmenu, collapsed, resizing, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, "data-testid": dataTestId, }: NavItemBaseProps) => import("react").JSX.Element;
|
|
37
48
|
export {};
|
|
38
49
|
//# sourceMappingURL=NavItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavItem.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavItem.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAgB9E,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,UAAU,gBAAgB;IACxB,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wHAAwH;IACxH,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,mBAAmB,GAAG,YAAY,CAAC;IAClE,iCAAiC;IACjC,IAAI,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC5C,wBAAwB;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2IAA2I;IAC3I,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gCAAgC;IAChC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,sHAAsH;IACtH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wFAAwF;IACxF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAMD,eAAO,MAAM,WAAW,GAAI,
|
|
1
|
+
{"version":3,"file":"NavItem.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavItem.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAgB9E,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,UAAU,gBAAgB;IACxB,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wHAAwH;IACxH,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,mBAAmB,GAAG,YAAY,CAAC;IAClE,iCAAiC;IACjC,IAAI,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC5C,wBAAwB;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2IAA2I;IAC3I,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gCAAgC;IAChC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,sHAAsH;IACtH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wFAAwF;IACxF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAMD,eAAO,MAAM,WAAW,GAAI,sNAiBzB,gBAAgB,gCAuIlB,CAAC"}
|
|
@@ -18,7 +18,8 @@ const styles = sortCx({
|
|
|
18
18
|
rootSelected: 'bg-brand-primary hover:bg-brand-primary',
|
|
19
19
|
});
|
|
20
20
|
const StatusDot = ({ status }) => (jsx("span", { "aria-hidden": "true", className: cx('mr-2 size-2 shrink-0 rounded-full', status === 'online' ? 'bg-success-solid' : 'bg-fg-quaternary') }));
|
|
21
|
-
const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, children, truncate = true, status, onClick, hasSubmenu, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'data-testid': dataTestId, }) => {
|
|
21
|
+
const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, children, truncate = true, status, onClick, hasSubmenu, collapsed, resizing, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'data-testid': dataTestId, }) => {
|
|
22
|
+
const isRail = collapsed !== undefined;
|
|
22
23
|
// `current` means "this is the current page" (→ aria-current); `selected` is the
|
|
23
24
|
// brand-highlight state (open/selected section), which may differ from the page.
|
|
24
25
|
const isSelected = selected ?? current;
|
|
@@ -26,11 +27,16 @@ const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, childre
|
|
|
26
27
|
useAriaDisclosureAttrs(linkRef, { ariaExpanded, ariaControls });
|
|
27
28
|
const iconElement = Icon && (jsx(Icon, { "aria-hidden": "true", className: cx('mr-2 size-5 shrink-0 text-fg-quaternary transition-inherit-all group-hover/item:text-fg-quaternary_hover', isSelected && 'text-fg-brand-primary group-hover/item:text-fg-brand-primary') }));
|
|
28
29
|
const badgeElement = badge && (typeof badge === 'string' || typeof badge === 'number') ? (jsx(Badge, { className: "ml-3", color: isSelected ? 'brand' : 'gray', type: "pill-color", size: "sm", children: badge })) : (badge);
|
|
29
|
-
const labelElement = (jsx("span", { className: cx('flex-1 text-sm font-semibold text-secondary transition-inherit-all group-hover/item:text-secondary_hover', truncate && 'truncate', isSelected && 'text-brand-secondary group-hover/item:text-brand-secondary'), children: children }));
|
|
30
|
+
const labelElement = (jsx("span", { className: cx('flex-1 text-sm font-semibold text-secondary transition-inherit-all group-hover/item:text-secondary_hover', truncate && (resizing ? 'whitespace-nowrap' : 'truncate'), isSelected && 'text-brand-secondary group-hover/item:text-brand-secondary'), children: children }));
|
|
30
31
|
const isExternal = isExternalHref(href);
|
|
31
32
|
const externalIcon = isExternal && jsx(Share04, { className: "size-4 stroke-[2.5px] text-fg-quaternary" });
|
|
32
33
|
// A trailing chevron on a section parent signals it has a revealable sub-navigation tier.
|
|
33
34
|
const submenuChevron = hasSubmenu && (jsx(ChevronRight, { "aria-hidden": "true", className: cx('ml-3 size-4 shrink-0 stroke-[2.5px] text-fg-quaternary', isSelected && 'text-fg-brand-primary') }));
|
|
35
|
+
// Everything after the icon fades as one block in rail mode. While resizing it keeps its natural width so the
|
|
36
|
+
// row's edge wipes it in or out instead of the label reflowing; the fade-in waits for the rail to open a little.
|
|
37
|
+
const trailingElement = (jsxs("span", { className: cx('flex flex-1 items-center', resizing ? 'shrink-0' : 'min-w-0', isRail && 'transition-opacity motion-reduce:transition-none', isRail && (collapsed ? 'opacity-0 duration-150' : 'delay-100 duration-150')), children: [labelElement, externalIcon, badgeElement, submenuChevron] }));
|
|
38
|
+
// The icon's margin and the trailing block overflow a collapsed row; clipping keeps the hover surface the row itself.
|
|
39
|
+
const railClassName = isRail && 'overflow-hidden';
|
|
34
40
|
if (type === 'collapsible') {
|
|
35
41
|
return (
|
|
36
42
|
// biome-ignore lint/a11y/noStaticElementInteractions: This is a summary element
|
|
@@ -41,9 +47,9 @@ const NavItemBase = ({ current, selected, type, badge, href, icon: Icon, childre
|
|
|
41
47
|
}
|
|
42
48
|
// useButton forwards aria-expanded/aria-controls as plain props, unlike useLink — no ref workaround needed here.
|
|
43
49
|
if (type === 'disclosure') {
|
|
44
|
-
return (jsxs(Button, { "data-testid": dataTestId, className: cx('group/item p-2', styles.root, isSelected && styles.rootSelected), onClick: onClick, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, children: [status && jsx(StatusDot, { status: status }), iconElement,
|
|
50
|
+
return (jsxs(Button, { "data-testid": dataTestId, className: cx('group/item p-2', styles.root, isSelected && styles.rootSelected, railClassName), onClick: onClick, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, children: [status && jsx(StatusDot, { status: status }), iconElement, trailingElement] }));
|
|
45
51
|
}
|
|
46
|
-
return (jsxs(Link, { ref: linkRef, href: safeHref(href), target: isExternal ? '_blank' : '_self', rel: "noopener noreferrer", "data-testid": dataTestId, className: cx('group/item p-2', styles.root, isSelected && styles.rootSelected), onClick: onClick, "aria-current": current ? 'page' : undefined, children: [status && jsx(StatusDot, { status: status }), iconElement,
|
|
52
|
+
return (jsxs(Link, { ref: linkRef, href: safeHref(href), target: isExternal ? '_blank' : '_self', rel: "noopener noreferrer", "data-testid": dataTestId, className: cx('group/item p-2', styles.root, isSelected && styles.rootSelected, railClassName), onClick: onClick, "aria-current": current ? 'page' : undefined, children: [status && jsx(StatusDot, { status: status }), iconElement, trailingElement] }));
|
|
47
53
|
};
|
|
48
54
|
|
|
49
55
|
export { NavItemBase };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavItem.js","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavItem.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs","AriaLink","AriaButton"],"mappings":";;;;;;;;;AAWA;;;;AAIG;AACH,MAAM,MAAM,GAAG,MAAM,CAAC;;AAEpB,IAAA,IAAI,EAAE,+QAA+Q;AACrR,IAAA,YAAY,EAAE,yCAAyC;AACxD,CAAA,CAAC;
|
|
1
|
+
{"version":3,"file":"NavItem.js","sources":["../../../../../src/components/organisms/SidebarNavigation/components/NavItem.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs","AriaLink","AriaButton"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var localStorageUtils = require('@flipdish/ui-library/utilities/localStorageUtils');
|
|
4
|
+
var react = require('motion/react');
|
|
5
|
+
var React = require('react');
|
|
6
|
+
|
|
7
|
+
/** One spring for the rail, the page beside it and the secondary panel, so everything that resizes moves together. */
|
|
8
|
+
const SIDEBAR_SPRING = { type: 'spring', damping: 26, stiffness: 220, bounce: 0 };
|
|
9
|
+
const INSTANT = { duration: 0 };
|
|
10
|
+
/**
|
|
11
|
+
* Collapsed state of the sidebar rail and the flags its width animation needs. Resolves controlled versus
|
|
12
|
+
* uncontrolled state, restores a persisted preference after hydration without animating it, and tracks whether
|
|
13
|
+
* the rail is between widths so labels can hold their width while it moves.
|
|
14
|
+
*
|
|
15
|
+
* @param options The collapse props of `SidebarNavigation`.
|
|
16
|
+
* @returns The resolved state, its setter, the two animation flags, the Motion transition for the width, and the
|
|
17
|
+
* callback to pass to the rail's `onAnimationComplete`.
|
|
18
|
+
*/
|
|
19
|
+
const useSidebarCollapse = ({ collapsed, defaultCollapsed, onCollapsedChange, persistCollapsed }) => {
|
|
20
|
+
const isControlled = collapsed !== undefined;
|
|
21
|
+
const [internalCollapsed, setInternalCollapsed] = React.useState(defaultCollapsed);
|
|
22
|
+
const isCollapsed = isControlled ? collapsed : internalCollapsed;
|
|
23
|
+
// The stored preference is applied after hydration (reading it during render would mismatch the server markup), so
|
|
24
|
+
// it must not animate: a returning user would watch the rail and the page spring closed on every load. The flag makes
|
|
25
|
+
// that one change instant for Motion and lets the rail switch off its CSS fades.
|
|
26
|
+
const [isApplyingStoredPreference, setIsApplyingStoredPreference] = React.useState(false);
|
|
27
|
+
React.useLayoutEffect(() => {
|
|
28
|
+
if (isControlled || !persistCollapsed)
|
|
29
|
+
return;
|
|
30
|
+
const stored = localStorageUtils.sidebarCollapsedStorage.get();
|
|
31
|
+
if (stored === null || stored === defaultCollapsed)
|
|
32
|
+
return;
|
|
33
|
+
setIsApplyingStoredPreference(true);
|
|
34
|
+
setInternalCollapsed(stored);
|
|
35
|
+
}, [isControlled, persistCollapsed, defaultCollapsed]);
|
|
36
|
+
const setCollapsed = (next) => {
|
|
37
|
+
onCollapsedChange?.(next);
|
|
38
|
+
if (isControlled)
|
|
39
|
+
return;
|
|
40
|
+
setInternalCollapsed(next);
|
|
41
|
+
if (persistCollapsed)
|
|
42
|
+
localStorageUtils.sidebarCollapsedStorage.set(next);
|
|
43
|
+
};
|
|
44
|
+
const shouldReduceMotion = react.useReducedMotion();
|
|
45
|
+
const resizeTransition = shouldReduceMotion || isApplyingStoredPreference ? INSTANT : SIDEBAR_SPRING;
|
|
46
|
+
// While the rail is between widths its labels keep their width and get wiped by the row's edge rather than re-truncating
|
|
47
|
+
// every frame. Tracked from the resolved state, so a controlled toggle counts too, and cleared when the width settles.
|
|
48
|
+
const [isResizing, setIsResizing] = React.useState(false);
|
|
49
|
+
const [settledCollapsed, setSettledCollapsed] = React.useState(isCollapsed);
|
|
50
|
+
if (settledCollapsed !== isCollapsed) {
|
|
51
|
+
setSettledCollapsed(isCollapsed);
|
|
52
|
+
setIsResizing(true);
|
|
53
|
+
}
|
|
54
|
+
// The fades come back only after a paint: cleared any earlier, the browser would compute the collapsed styles with
|
|
55
|
+
// the transitions already restored and the logo and toggle would still animate from the default state. The instant
|
|
56
|
+
// width change has settled by then too, so the resize flag clears here rather than waiting on Motion's callback for a
|
|
57
|
+
// zero-duration run. In a background tab the frames wait for the tab to show, which is harmless since nothing painted.
|
|
58
|
+
React.useEffect(() => {
|
|
59
|
+
if (!isApplyingStoredPreference)
|
|
60
|
+
return;
|
|
61
|
+
let frame = requestAnimationFrame(() => {
|
|
62
|
+
frame = requestAnimationFrame(() => {
|
|
63
|
+
setIsApplyingStoredPreference(false);
|
|
64
|
+
setIsResizing(false);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
return () => cancelAnimationFrame(frame);
|
|
68
|
+
}, [isApplyingStoredPreference]);
|
|
69
|
+
return {
|
|
70
|
+
isCollapsed,
|
|
71
|
+
setCollapsed,
|
|
72
|
+
/** True while the rail animates between widths. */
|
|
73
|
+
isResizing,
|
|
74
|
+
/** True for the first paint of a restored preference, while the rail must not transition anything. */
|
|
75
|
+
isApplyingStoredPreference,
|
|
76
|
+
/** The Motion transition for the rail's width and the page placeholder beside it. */
|
|
77
|
+
resizeTransition,
|
|
78
|
+
/** Pass to the rail's `onAnimationComplete`. */
|
|
79
|
+
onResizeComplete: () => setIsResizing(false),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
exports.SIDEBAR_SPRING = SIDEBAR_SPRING;
|
|
84
|
+
exports.useSidebarCollapse = useSidebarCollapse;
|
|
85
|
+
//# sourceMappingURL=useSidebarCollapse.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSidebarCollapse.cjs","sources":["../../../../../src/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.ts"],"sourcesContent":[null],"names":["useState","useLayoutEffect","sidebarCollapsedStorage","useReducedMotion","useEffect"],"mappings":";;;;;;AAMA;MACa,cAAc,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAEtF,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAW;AAaxC;;;;;;;;AAQG;AACI,MAAM,kBAAkB,GAAG,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAA0B,KAAI;AACjI,IAAA,MAAM,YAAY,GAAG,SAAS,KAAK,SAAS;IAC5C,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAGA,cAAQ,CAAC,gBAAgB,CAAC;IAC5E,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,iBAAiB;;;;IAKhE,MAAM,CAAC,0BAA0B,EAAE,6BAA6B,CAAC,GAAGA,cAAQ,CAAC,KAAK,CAAC;IACnFC,qBAAe,CAAC,MAAK;QACnB,IAAI,YAAY,IAAI,CAAC,gBAAgB;YAAE;AACvC,QAAA,MAAM,MAAM,GAAGC,yCAAuB,CAAC,GAAG,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,gBAAgB;YAAE;QACpD,6BAA6B,CAAC,IAAI,CAAC;QACnC,oBAAoB,CAAC,MAAM,CAAC;IAC9B,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAEtD,IAAA,MAAM,YAAY,GAAG,CAAC,IAAa,KAAI;AACrC,QAAA,iBAAiB,GAAG,IAAI,CAAC;AACzB,QAAA,IAAI,YAAY;YAAE;QAClB,oBAAoB,CAAC,IAAI,CAAC;AAC1B,QAAA,IAAI,gBAAgB;AAAE,YAAAA,yCAAuB,CAAC,GAAG,CAAC,IAAI,CAAC;AACzD,IAAA,CAAC;AAED,IAAA,MAAM,kBAAkB,GAAGC,sBAAgB,EAAE;AAC7C,IAAA,MAAM,gBAAgB,GAAG,kBAAkB,IAAI,0BAA0B,GAAG,OAAO,GAAG,cAAc;;;IAIpG,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAGH,cAAQ,CAAC,KAAK,CAAC;IACnD,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAGA,cAAQ,CAAC,WAAW,CAAC;AACrE,IAAA,IAAI,gBAAgB,KAAK,WAAW,EAAE;QACpC,mBAAmB,CAAC,WAAW,CAAC;QAChC,aAAa,CAAC,IAAI,CAAC;IACrB;;;;;IAMAI,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,0BAA0B;YAAE;AACjC,QAAA,IAAI,KAAK,GAAG,qBAAqB,CAAC,MAAK;AACrC,YAAA,KAAK,GAAG,qBAAqB,CAAC,MAAK;gBACjC,6BAA6B,CAAC,KAAK,CAAC;gBACpC,aAAa,CAAC,KAAK,CAAC;AACtB,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,MAAM,oBAAoB,CAAC,KAAK,CAAC;AAC1C,IAAA,CAAC,EAAE,CAAC,0BAA0B,CAAC,CAAC;IAEhC,OAAO;QACL,WAAW;QACX,YAAY;;QAEZ,UAAU;;QAEV,0BAA0B;;QAE1B,gBAAgB;;AAEhB,QAAA,gBAAgB,EAAE,MAAM,aAAa,CAAC,KAAK,CAAC;KAC7C;AACH;;;"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** One spring for the rail, the page beside it and the secondary panel, so everything that resizes moves together. */
|
|
2
|
+
export declare const SIDEBAR_SPRING: {
|
|
3
|
+
readonly type: "spring";
|
|
4
|
+
readonly damping: 26;
|
|
5
|
+
readonly stiffness: 220;
|
|
6
|
+
readonly bounce: 0;
|
|
7
|
+
};
|
|
8
|
+
interface SidebarCollapseOptions {
|
|
9
|
+
/** Controlled collapsed state. When provided the parent owns the state and its persistence. */
|
|
10
|
+
collapsed?: boolean;
|
|
11
|
+
/** Initial collapsed state when uncontrolled. */
|
|
12
|
+
defaultCollapsed: boolean;
|
|
13
|
+
/** Called whenever the user toggles the rail. */
|
|
14
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
15
|
+
/** Persist the collapsed state to localStorage (uncontrolled mode only). */
|
|
16
|
+
persistCollapsed: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Collapsed state of the sidebar rail and the flags its width animation needs. Resolves controlled versus
|
|
20
|
+
* uncontrolled state, restores a persisted preference after hydration without animating it, and tracks whether
|
|
21
|
+
* the rail is between widths so labels can hold their width while it moves.
|
|
22
|
+
*
|
|
23
|
+
* @param options The collapse props of `SidebarNavigation`.
|
|
24
|
+
* @returns The resolved state, its setter, the two animation flags, the Motion transition for the width, and the
|
|
25
|
+
* callback to pass to the rail's `onAnimationComplete`.
|
|
26
|
+
*/
|
|
27
|
+
export declare const useSidebarCollapse: ({ collapsed, defaultCollapsed, onCollapsedChange, persistCollapsed }: SidebarCollapseOptions) => {
|
|
28
|
+
isCollapsed: boolean;
|
|
29
|
+
setCollapsed: (next: boolean) => void;
|
|
30
|
+
/** True while the rail animates between widths. */
|
|
31
|
+
isResizing: boolean;
|
|
32
|
+
/** True for the first paint of a restored preference, while the rail must not transition anything. */
|
|
33
|
+
isApplyingStoredPreference: boolean;
|
|
34
|
+
/** The Motion transition for the rail's width and the page placeholder beside it. */
|
|
35
|
+
resizeTransition: {
|
|
36
|
+
readonly type: "spring";
|
|
37
|
+
readonly damping: 26;
|
|
38
|
+
readonly stiffness: 220;
|
|
39
|
+
readonly bounce: 0;
|
|
40
|
+
} | {
|
|
41
|
+
readonly duration: 0;
|
|
42
|
+
};
|
|
43
|
+
/** Pass to the rail's `onAnimationComplete`. */
|
|
44
|
+
onResizeComplete: () => void;
|
|
45
|
+
};
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=useSidebarCollapse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSidebarCollapse.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.ts"],"names":[],"mappings":"AAMA,sHAAsH;AACtH,eAAO,MAAM,cAAc;;;;;CAAsE,CAAC;AAIlG,UAAU,sBAAsB;IAC9B,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,4EAA4E;IAC5E,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,sEAAsE,sBAAsB;;yBAiBjG,OAAO;IAqCjC,mDAAmD;;IAEnD,sGAAsG;;IAEtG,qFAAqF;;;;;;;;;IAErF,gDAAgD;;CAGnD,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { sidebarCollapsedStorage } from '@flipdish/ui-library/utilities/localStorageUtils';
|
|
2
|
+
import { useReducedMotion } from 'motion/react';
|
|
3
|
+
import { useState, useLayoutEffect, useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
/** One spring for the rail, the page beside it and the secondary panel, so everything that resizes moves together. */
|
|
6
|
+
const SIDEBAR_SPRING = { type: 'spring', damping: 26, stiffness: 220, bounce: 0 };
|
|
7
|
+
const INSTANT = { duration: 0 };
|
|
8
|
+
/**
|
|
9
|
+
* Collapsed state of the sidebar rail and the flags its width animation needs. Resolves controlled versus
|
|
10
|
+
* uncontrolled state, restores a persisted preference after hydration without animating it, and tracks whether
|
|
11
|
+
* the rail is between widths so labels can hold their width while it moves.
|
|
12
|
+
*
|
|
13
|
+
* @param options The collapse props of `SidebarNavigation`.
|
|
14
|
+
* @returns The resolved state, its setter, the two animation flags, the Motion transition for the width, and the
|
|
15
|
+
* callback to pass to the rail's `onAnimationComplete`.
|
|
16
|
+
*/
|
|
17
|
+
const useSidebarCollapse = ({ collapsed, defaultCollapsed, onCollapsedChange, persistCollapsed }) => {
|
|
18
|
+
const isControlled = collapsed !== undefined;
|
|
19
|
+
const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
|
|
20
|
+
const isCollapsed = isControlled ? collapsed : internalCollapsed;
|
|
21
|
+
// The stored preference is applied after hydration (reading it during render would mismatch the server markup), so
|
|
22
|
+
// it must not animate: a returning user would watch the rail and the page spring closed on every load. The flag makes
|
|
23
|
+
// that one change instant for Motion and lets the rail switch off its CSS fades.
|
|
24
|
+
const [isApplyingStoredPreference, setIsApplyingStoredPreference] = useState(false);
|
|
25
|
+
useLayoutEffect(() => {
|
|
26
|
+
if (isControlled || !persistCollapsed)
|
|
27
|
+
return;
|
|
28
|
+
const stored = sidebarCollapsedStorage.get();
|
|
29
|
+
if (stored === null || stored === defaultCollapsed)
|
|
30
|
+
return;
|
|
31
|
+
setIsApplyingStoredPreference(true);
|
|
32
|
+
setInternalCollapsed(stored);
|
|
33
|
+
}, [isControlled, persistCollapsed, defaultCollapsed]);
|
|
34
|
+
const setCollapsed = (next) => {
|
|
35
|
+
onCollapsedChange?.(next);
|
|
36
|
+
if (isControlled)
|
|
37
|
+
return;
|
|
38
|
+
setInternalCollapsed(next);
|
|
39
|
+
if (persistCollapsed)
|
|
40
|
+
sidebarCollapsedStorage.set(next);
|
|
41
|
+
};
|
|
42
|
+
const shouldReduceMotion = useReducedMotion();
|
|
43
|
+
const resizeTransition = shouldReduceMotion || isApplyingStoredPreference ? INSTANT : SIDEBAR_SPRING;
|
|
44
|
+
// While the rail is between widths its labels keep their width and get wiped by the row's edge rather than re-truncating
|
|
45
|
+
// every frame. Tracked from the resolved state, so a controlled toggle counts too, and cleared when the width settles.
|
|
46
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
47
|
+
const [settledCollapsed, setSettledCollapsed] = useState(isCollapsed);
|
|
48
|
+
if (settledCollapsed !== isCollapsed) {
|
|
49
|
+
setSettledCollapsed(isCollapsed);
|
|
50
|
+
setIsResizing(true);
|
|
51
|
+
}
|
|
52
|
+
// The fades come back only after a paint: cleared any earlier, the browser would compute the collapsed styles with
|
|
53
|
+
// the transitions already restored and the logo and toggle would still animate from the default state. The instant
|
|
54
|
+
// width change has settled by then too, so the resize flag clears here rather than waiting on Motion's callback for a
|
|
55
|
+
// zero-duration run. In a background tab the frames wait for the tab to show, which is harmless since nothing painted.
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (!isApplyingStoredPreference)
|
|
58
|
+
return;
|
|
59
|
+
let frame = requestAnimationFrame(() => {
|
|
60
|
+
frame = requestAnimationFrame(() => {
|
|
61
|
+
setIsApplyingStoredPreference(false);
|
|
62
|
+
setIsResizing(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
return () => cancelAnimationFrame(frame);
|
|
66
|
+
}, [isApplyingStoredPreference]);
|
|
67
|
+
return {
|
|
68
|
+
isCollapsed,
|
|
69
|
+
setCollapsed,
|
|
70
|
+
/** True while the rail animates between widths. */
|
|
71
|
+
isResizing,
|
|
72
|
+
/** True for the first paint of a restored preference, while the rail must not transition anything. */
|
|
73
|
+
isApplyingStoredPreference,
|
|
74
|
+
/** The Motion transition for the rail's width and the page placeholder beside it. */
|
|
75
|
+
resizeTransition,
|
|
76
|
+
/** Pass to the rail's `onAnimationComplete`. */
|
|
77
|
+
onResizeComplete: () => setIsResizing(false),
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { SIDEBAR_SPRING, useSidebarCollapse };
|
|
82
|
+
//# sourceMappingURL=useSidebarCollapse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSidebarCollapse.js","sources":["../../../../../src/components/organisms/SidebarNavigation/hooks/useSidebarCollapse.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAMA;MACa,cAAc,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAEtF,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAW;AAaxC;;;;;;;;AAQG;AACI,MAAM,kBAAkB,GAAG,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAA0B,KAAI;AACjI,IAAA,MAAM,YAAY,GAAG,SAAS,KAAK,SAAS;IAC5C,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC;IAC5E,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,iBAAiB;;;;IAKhE,MAAM,CAAC,0BAA0B,EAAE,6BAA6B,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IACnF,eAAe,CAAC,MAAK;QACnB,IAAI,YAAY,IAAI,CAAC,gBAAgB;YAAE;AACvC,QAAA,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,gBAAgB;YAAE;QACpD,6BAA6B,CAAC,IAAI,CAAC;QACnC,oBAAoB,CAAC,MAAM,CAAC;IAC9B,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAEtD,IAAA,MAAM,YAAY,GAAG,CAAC,IAAa,KAAI;AACrC,QAAA,iBAAiB,GAAG,IAAI,CAAC;AACzB,QAAA,IAAI,YAAY;YAAE;QAClB,oBAAoB,CAAC,IAAI,CAAC;AAC1B,QAAA,IAAI,gBAAgB;AAAE,YAAA,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC;AACzD,IAAA,CAAC;AAED,IAAA,MAAM,kBAAkB,GAAG,gBAAgB,EAAE;AAC7C,IAAA,MAAM,gBAAgB,GAAG,kBAAkB,IAAI,0BAA0B,GAAG,OAAO,GAAG,cAAc;;;IAIpG,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IACnD,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC;AACrE,IAAA,IAAI,gBAAgB,KAAK,WAAW,EAAE;QACpC,mBAAmB,CAAC,WAAW,CAAC;QAChC,aAAa,CAAC,IAAI,CAAC;IACrB;;;;;IAMA,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,0BAA0B;YAAE;AACjC,QAAA,IAAI,KAAK,GAAG,qBAAqB,CAAC,MAAK;AACrC,YAAA,KAAK,GAAG,qBAAqB,CAAC,MAAK;gBACjC,6BAA6B,CAAC,KAAK,CAAC;gBACpC,aAAa,CAAC,KAAK,CAAC;AACtB,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,MAAM,oBAAoB,CAAC,KAAK,CAAC;AAC1C,IAAA,CAAC,EAAE,CAAC,0BAA0B,CAAC,CAAC;IAEhC,OAAO;QACL,WAAW;QACX,YAAY;;QAEZ,UAAU;;QAEV,0BAA0B;;QAE1B,gBAAgB;;AAEhB,QAAA,gBAAgB,EAAE,MAAM,aAAa,CAAC,KAAK,CAAC;KAC7C;AACH;;"}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var uiIcons = require('@flipdish/ui-icons');
|
|
5
|
+
var Tooltip = require('@flipdish/ui-library/components/atoms/Tooltip');
|
|
5
6
|
var UtilityButton = require('@flipdish/ui-library/components/atoms/UtilityButton');
|
|
6
7
|
var useBreakpoints = require('@flipdish/ui-library/hooks/useBreakpoints');
|
|
7
8
|
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
8
9
|
var hrefUtils = require('@flipdish/ui-library/utilities/hrefUtils');
|
|
9
|
-
var localStorageUtils = require('@flipdish/ui-library/utilities/localStorageUtils');
|
|
10
10
|
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
11
11
|
var react = require('motion/react');
|
|
12
12
|
var React = require('react');
|
|
@@ -15,11 +15,11 @@ var SearchTrigger = require('../ApplicationHeader/components/SearchTrigger.cjs')
|
|
|
15
15
|
var LogoLink = require('./components/LogoLink.cjs');
|
|
16
16
|
var MobileHeader = require('./components/MobileHeader.cjs');
|
|
17
17
|
var NavAccountCard = require('./components/NavAccountCard.cjs');
|
|
18
|
-
var NavButton = require('./components/NavButton.cjs');
|
|
19
18
|
var NavItem = require('./components/NavItem.cjs');
|
|
20
19
|
var NavList = require('./components/NavList.cjs');
|
|
21
20
|
var NavSectionToggle = require('./components/NavSectionToggle.cjs');
|
|
22
21
|
var useDualTierKeyboard = require('./hooks/useDualTierKeyboard.cjs');
|
|
22
|
+
var useSidebarCollapse = require('./hooks/useSidebarCollapse.cjs');
|
|
23
23
|
var SidebarMenuButton = require('./components/SidebarMenuButton.cjs');
|
|
24
24
|
|
|
25
25
|
const COLLAPSED_WIDTH = 68;
|
|
@@ -41,9 +41,12 @@ const SidebarNavigation = ({ activeUrl, items, footerItems = [], account, onNavi
|
|
|
41
41
|
onNavigate?.(destination);
|
|
42
42
|
};
|
|
43
43
|
const navItemTestId = (item) => item['data-testid'] ?? testIdUtils.joinTestId(rootTestId, `nav-item-${item.id ?? testIdUtils.slugifyTestId(item.label)}`);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const { isCollapsed, setCollapsed, isResizing, isApplyingStoredPreference, resizeTransition, onResizeComplete } = useSidebarCollapse.useSidebarCollapse({
|
|
45
|
+
collapsed,
|
|
46
|
+
defaultCollapsed,
|
|
47
|
+
onCollapsedChange,
|
|
48
|
+
persistCollapsed,
|
|
49
|
+
});
|
|
47
50
|
// Mobile drawer open-state: controlled when `mobileMenuOpen` is provided, else internal.
|
|
48
51
|
const isMobileMenuControlled = mobileMenuOpen !== undefined;
|
|
49
52
|
const [internalMobileMenuOpen, setInternalMobileMenuOpen] = React.useState(false);
|
|
@@ -60,22 +63,6 @@ const SidebarNavigation = ({ activeUrl, items, footerItems = [], account, onNavi
|
|
|
60
63
|
if (isDesktop && isMobileMenuOpen)
|
|
61
64
|
setMobileMenuOpen(false);
|
|
62
65
|
}, [isDesktop]);
|
|
63
|
-
// Hydrate the persisted preference after mount to avoid an SSR hydration mismatch.
|
|
64
|
-
React.useEffect(() => {
|
|
65
|
-
if (isControlled || !persistCollapsed)
|
|
66
|
-
return;
|
|
67
|
-
const stored = localStorageUtils.sidebarCollapsedStorage.get();
|
|
68
|
-
if (stored !== null)
|
|
69
|
-
setInternalCollapsed(stored);
|
|
70
|
-
}, [isControlled, persistCollapsed]);
|
|
71
|
-
const setCollapsed = (next) => {
|
|
72
|
-
onCollapsedChange?.(next);
|
|
73
|
-
if (isControlled)
|
|
74
|
-
return;
|
|
75
|
-
setInternalCollapsed(next);
|
|
76
|
-
if (persistCollapsed)
|
|
77
|
-
localStorageUtils.sidebarCollapsedStorage.set(next);
|
|
78
|
-
};
|
|
79
66
|
// Dual-tier reveal: the secondary panel is shown whenever the
|
|
80
67
|
// pointer is over — or focus is within — the sidebar, and it always lists the
|
|
81
68
|
// children of `currentItem`. `currentItem` is seeded from the active route and
|
|
@@ -153,10 +140,16 @@ const SidebarNavigation = ({ activeUrl, items, footerItems = [], account, onNavi
|
|
|
153
140
|
};
|
|
154
141
|
const itemTestId = navItemTestId(item);
|
|
155
142
|
// A parent's own `href` (if any) is ignored — it reveals the panel, not navigates.
|
|
156
|
-
|
|
143
|
+
// The same item serves both rail widths: collapsed it shrinks to its icon and shows its label as a tooltip instead.
|
|
144
|
+
return (jsxRuntime.jsx("li", { className: "py-px", onKeyDown: handleTriggerKeyDown(item.label, hasChildren), children: jsxRuntime.jsx(Tooltip.Tooltip, { isDisabled: !isCollapsed, title: item.label, placement: "right", children: jsxRuntime.jsx(NavItem.NavItemBase, { type: hasChildren ? 'disclosure' : 'link', current: isCurrentPage, selected: isSelected, href: hasChildren ? undefined : item.href, icon: item.icon, badge: item.badge, hasSubmenu: hasChildren, collapsed: isCollapsed, resizing: isResizing, onClick: selectSection, "data-testid": itemTestId, ...disclosure, children: item.label }) }) }, item.label));
|
|
157
145
|
});
|
|
158
|
-
const mainSidebar = (jsxRuntime.jsxs(react.motion.aside
|
|
159
|
-
|
|
146
|
+
const mainSidebar = (jsxRuntime.jsxs(react.motion.aside
|
|
147
|
+
// initial={false} starts at the `animate` value; without it Motion reads the DOM and springs from there on mount.
|
|
148
|
+
, {
|
|
149
|
+
// initial={false} starts at the `animate` value; without it Motion reads the DOM and springs from there on mount.
|
|
150
|
+
initial: false, animate: { width: isCollapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH }, transition: resizeTransition, onAnimationComplete: onResizeComplete, className: cx.cx('flex h-full max-h-full flex-col justify-between overflow-x-hidden overflow-y-auto bg-secondary', !hideBorder && 'border-r border-secondary',
|
|
151
|
+
// Every fade and slide in the rail is a CSS transition; the stored preference must land without any of them.
|
|
152
|
+
isApplyingStoredPreference && '**:transition-none!'), children: [jsxRuntime.jsxs("div", { className: "flex flex-col", children: [jsxRuntime.jsxs("div", { className: "relative flex h-18 items-center px-5", children: [jsxRuntime.jsx("div", { inert: isCollapsed, className: cx.cx('flex transition-opacity motion-reduce:transition-none', isCollapsed ? 'opacity-0 duration-150' : 'delay-150 duration-150'), children: jsxRuntime.jsx(LogoLink.LogoLink, { href: homeHref, size: "md", onClick: () => reportNavigation(homeHref), "data-testid": testIdUtils.joinTestId(rootTestId, 'logo') }) }), jsxRuntime.jsx("div", { className: cx.cx('absolute top-5 transition-[right] duration-300 ease-out motion-reduce:transition-none', isCollapsed ? 'right-4.5' : 'right-4'), children: jsxRuntime.jsx(UtilityButton.ButtonUtility, { size: "sm", color: "tertiary", tooltip: isCollapsed ? 'Expand' : 'Collapse', "aria-label": isCollapsed ? 'Expand navigation' : 'Collapse navigation', icon: isCollapsed ? uiIcons.ChevronRightDouble : uiIcons.ChevronLeftDouble, "data-testid": testIdUtils.joinTestId(rootTestId, isCollapsed ? 'expand' : 'collapse'), onClick: () => setCollapsed(!isCollapsed) }) })] }), jsxRuntime.jsx("nav", { "aria-label": "Main", children: jsxRuntime.jsx("ul", { className: "flex flex-col gap-0.5 px-4 pt-1", children: renderPrimaryItems(items) }) })] }), jsxRuntime.jsxs("div", { className: "mt-auto flex flex-col gap-3 px-4 py-4", children: [footerItems.length > 0 && (jsxRuntime.jsx("nav", { "aria-label": "Footer", children: jsxRuntime.jsx("ul", { className: "flex flex-col gap-0.5", children: renderPrimaryItems(footerItems) }) })), account && (jsxRuntime.jsx(NavAccountCard.NavAccountCard, { account: account.account, menuItems: account.menuItems, bottomMenuItems: account.bottomMenuItems, collapsed: isCollapsed, resizing: isResizing, onOpenChange: setIsAccountMenuOpen, "data-testid": account['data-testid'] }))] })] }));
|
|
160
153
|
const handleMobileNavigate = (href) => {
|
|
161
154
|
const destination = hrefUtils.safeHref(href);
|
|
162
155
|
if (destination === undefined)
|
|
@@ -170,8 +163,8 @@ const SidebarNavigation = ({ activeUrl, items, footerItems = [], account, onNavi
|
|
|
170
163
|
onClick?.();
|
|
171
164
|
};
|
|
172
165
|
const withMobileMenuClose = (menuItems) => menuItems?.map((item) => ({ ...item, onClick: closeMobileMenuThen(item.onClick) }));
|
|
173
|
-
const secondarySidebar = currentItem && (jsxRuntime.jsx(react.AnimatePresence, { initial: false, children: isSecondarySidebarVisible && (jsxRuntime.jsx(react.motion.div, { ref: panelRef, id: panelId, onKeyDown: handlePanelKeyDown, role: "group", "aria-label": `${currentItem.label} pages`, initial: { width: 0, borderColor: 'var(--color-border-secondary)' }, animate: { width: SECONDARY_SIDEBAR_WIDTH, borderColor: 'var(--color-border-secondary)' }, exit: { width: 0, borderColor: 'rgba(0,0,0,0)', transition: { borderColor: { type: 'tween', delay: 0.05 } } }, transition:
|
|
174
|
-
return (jsxRuntime.jsxs(testIdUtils.TestIdProvider, { value: rootTestId, children: [jsxRuntime.jsxs("div", { className: "z-40 hidden lg:fixed lg:inset-y-0 lg:left-0 lg:flex", onPointerEnter: () => setIsHovering(true), onPointerMove: handleContainerPointerMove, onPointerLeave: () => setIsHovering(false), onFocus: handleContainerFocus, onBlur: handleContainerBlur, children: [mainSidebar, secondarySidebar] }), jsxRuntime.jsx(
|
|
166
|
+
const secondarySidebar = currentItem && (jsxRuntime.jsx(react.AnimatePresence, { initial: false, children: isSecondarySidebarVisible && (jsxRuntime.jsx(react.motion.div, { ref: panelRef, id: panelId, onKeyDown: handlePanelKeyDown, role: "group", "aria-label": `${currentItem.label} pages`, initial: { width: 0, borderColor: 'var(--color-border-secondary)' }, animate: { width: SECONDARY_SIDEBAR_WIDTH, borderColor: 'var(--color-border-secondary)' }, exit: { width: 0, borderColor: 'rgba(0,0,0,0)', transition: { borderColor: { type: 'tween', delay: 0.05 } } }, transition: useSidebarCollapse.SIDEBAR_SPRING, className: cx.cx('relative h-full overflow-x-hidden overflow-y-auto bg-primary', !(hideBorder || hideRightBorder) && 'box-content border-r border-secondary'), children: jsxRuntime.jsxs("div", { style: { width: SECONDARY_SIDEBAR_WIDTH }, className: "flex h-full flex-col px-4 pt-6", children: [jsxRuntime.jsx("h3", { className: "px-2 text-sm font-semibold text-tertiary", children: currentItem.label }), jsxRuntime.jsx("ul", { className: "py-2", children: currentItem.items?.map((item) => (jsxRuntime.jsx("li", { className: "py-px", children: jsxRuntime.jsx(NavItem.NavItemBase, { type: "link", current: item.href === activeHref, href: item.href, icon: item.icon, badge: item.badge, onClick: () => reportNavigation(item.href), "data-testid": item['data-testid'] ?? testIdUtils.joinTestId(navItemTestId(currentItem), `sub-item-${item.id ?? testIdUtils.slugifyTestId(item.label)}`), children: item.label }) }, item.label))) }), currentItem.toggle && (jsxRuntime.jsx(NavSectionToggle.NavSectionToggleRow, { toggle: currentItem.toggle, testIdPrefix: navItemTestId(currentItem), className: "mt-auto mb-4" }))] }) })) }));
|
|
167
|
+
return (jsxRuntime.jsxs(testIdUtils.TestIdProvider, { value: rootTestId, children: [jsxRuntime.jsxs("div", { className: "z-40 hidden lg:fixed lg:inset-y-0 lg:left-0 lg:flex", onPointerEnter: () => setIsHovering(true), onPointerMove: handleContainerPointerMove, onPointerLeave: () => setIsHovering(false), onFocus: handleContainerFocus, onBlur: handleContainerBlur, children: [mainSidebar, secondarySidebar] }), jsxRuntime.jsx(react.motion.div, { initial: false, animate: { paddingLeft: isCollapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH }, transition: resizeTransition, className: "invisible hidden lg:sticky lg:top-0 lg:bottom-0 lg:left-0 lg:block" }), showMobileHeader && (jsxRuntime.jsx(MobileHeader.MobileNavigationHeader, { isOpen: isMobileMenuOpen, onOpenChange: setMobileMenuOpen, controls: mobileMenuId, homeHref: homeHref, onHomePress: () => reportNavigation(homeHref), logoTestId: testIdUtils.joinTestId(rootTestId, 'mobile-logo'), "data-testid": testIdUtils.joinTestId(rootTestId, 'mobile-toggle') })), jsxRuntime.jsx(MobileHeader.MobileNavigationDrawer, { id: mobileMenuId, isOpen: isMobileMenuOpen, onOpenChange: setMobileMenuOpen, "data-testid": testIdUtils.joinTestId(rootTestId, 'mobile-close'), children: jsxRuntime.jsxs("aside", { className: "group flex h-full max-h-full w-full max-w-full flex-col justify-between overflow-y-auto bg-secondary pt-4", children: [jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-7 px-4", children: [jsxRuntime.jsx(LogoLink.LogoLink, { href: homeHref, size: "sm", onClick: () => handleMobileNavigate(homeHref), "data-testid": testIdUtils.joinTestId(rootTestId, 'drawer-logo') }), search && (jsxRuntime.jsx(SearchTrigger.SearchTrigger, { size: "md", placeholder: search.placeholder ?? 'Search', label: search.label ?? 'Search', onPress: closeMobileMenuThen(search.onPress), className: "w-full", "data-testid": search['data-testid'] ?? testIdUtils.joinTestId(rootTestId, 'search') }))] }), jsxRuntime.jsx("nav", { "aria-label": "Main", children: jsxRuntime.jsx(NavList.NavList, { activeUrl: activeUrl, items: items, onNavigate: handleMobileNavigate, testIdPrefix: rootTestId }) }), jsxRuntime.jsxs("div", { className: "mt-auto flex flex-col gap-3 p-4", children: [footerItems.length > 0 && (jsxRuntime.jsx("nav", { "aria-label": "Footer", children: jsxRuntime.jsx(NavList.NavList, { activeUrl: activeUrl, items: footerItems, onNavigate: handleMobileNavigate, testIdPrefix: rootTestId, className: "px-0 pt-0" }) })), account && (jsxRuntime.jsx(NavAccountCard.NavAccountCard, { account: account.account, menuItems: withMobileMenuClose(account.menuItems), bottomMenuItems: withMobileMenuClose(account.bottomMenuItems), "data-testid": account['data-testid'] }))] })] }) })] }));
|
|
175
168
|
};
|
|
176
169
|
|
|
177
170
|
exports.NavAccountCard = NavAccountCard.NavAccountCard;
|