@wallarm-org/design-system 0.43.0 → 0.44.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/AppShell/story-content/_storyConfigRenderer.d.ts +7 -0
- package/dist/components/AppShell/story-content/_storyConfigRenderer.js +46 -0
- package/dist/components/AppShell/story-content/_storyHomeContent.d.ts +2 -0
- package/dist/components/AppShell/story-content/_storyHomeContent.js +15 -0
- package/dist/components/AppShell/story-content/_storyNavConfigs.d.ts +6 -0
- package/dist/components/AppShell/story-content/_storyNavConfigs.js +693 -0
- package/dist/components/AppShell/story-content/index.d.ts +3 -0
- package/dist/components/AppShell/story-content/index.js +4 -0
- package/dist/components/Breadcrumbs/BreadcrumbsItem.js +2 -1
- package/dist/components/Breadcrumbs/BreadcrumbsScopeSwitcher.d.ts +18 -0
- package/dist/components/Breadcrumbs/BreadcrumbsScopeSwitcher.js +60 -0
- package/dist/components/Breadcrumbs/index.d.ts +1 -0
- package/dist/components/Breadcrumbs/index.js +2 -1
- package/dist/components/NavPanel/NavPanel.d.ts +8 -0
- package/dist/components/NavPanel/NavPanel.js +93 -0
- package/dist/components/NavPanel/NavPanelBack.d.ts +6 -0
- package/dist/components/NavPanel/NavPanelBack.js +31 -0
- package/dist/components/NavPanel/NavPanelContext.d.ts +12 -0
- package/dist/components/NavPanel/NavPanelContext.js +9 -0
- package/dist/components/NavPanel/NavPanelDivider.d.ts +3 -0
- package/dist/components/NavPanel/NavPanelDivider.js +10 -0
- package/dist/components/NavPanel/NavPanelGroup.d.ts +18 -0
- package/dist/components/NavPanel/NavPanelGroup.js +49 -0
- package/dist/components/NavPanel/NavPanelGroupContent.d.ts +6 -0
- package/dist/components/NavPanel/NavPanelGroupContent.js +36 -0
- package/dist/components/NavPanel/NavPanelGroupItem.d.ts +10 -0
- package/dist/components/NavPanel/NavPanelGroupItem.js +40 -0
- package/dist/components/NavPanel/NavPanelGroupLabel.d.ts +8 -0
- package/dist/components/NavPanel/NavPanelGroupLabel.js +48 -0
- package/dist/components/NavPanel/NavPanelHeader.d.ts +6 -0
- package/dist/components/NavPanel/NavPanelHeader.js +21 -0
- package/dist/components/NavPanel/NavPanelItem.d.ts +10 -0
- package/dist/components/NavPanel/NavPanelItem.js +35 -0
- package/dist/components/NavPanel/NavPanelResizeHandle.d.ts +2 -0
- package/dist/components/NavPanel/NavPanelResizeHandle.js +81 -0
- package/dist/components/NavPanel/NavPanelSectionHeader.d.ts +6 -0
- package/dist/components/NavPanel/NavPanelSectionHeader.js +22 -0
- package/dist/components/NavPanel/classes.d.ts +6 -0
- package/dist/components/NavPanel/classes.js +24 -0
- package/dist/components/NavPanel/index.d.ts +10 -0
- package/dist/components/NavPanel/index.js +11 -0
- package/dist/components/NavRail/NavRail.js +33 -2
- package/dist/components/NavRail/NavRailItem.js +10 -3
- package/dist/components/NavRail/classes.js +2 -2
- package/dist/components/NavRail/useShortcut.d.ts +2 -0
- package/dist/components/NavRail/useShortcut.js +44 -0
- package/dist/components/ProductNav/ProductNav.d.ts +13 -0
- package/dist/components/ProductNav/ProductNav.js +100 -0
- package/dist/components/ProductNav/ProductNavBreadcrumbs.d.ts +2 -0
- package/dist/components/ProductNav/ProductNavBreadcrumbs.js +38 -0
- package/dist/components/ProductNav/ProductNavContext.d.ts +22 -0
- package/dist/components/ProductNav/ProductNavContext.js +9 -0
- package/dist/components/ProductNav/ProductNavPanel.d.ts +6 -0
- package/dist/components/ProductNav/ProductNavPanel.js +82 -0
- package/dist/components/ProductNav/index.d.ts +10 -0
- package/dist/components/ProductNav/index.js +9 -0
- package/dist/components/ProductNav/matchNav.d.ts +16 -0
- package/dist/components/ProductNav/matchNav.js +108 -0
- package/dist/components/ProductNav/navUtils.d.ts +5 -0
- package/dist/components/ProductNav/navUtils.js +26 -0
- package/dist/components/ProductNav/types.d.ts +69 -0
- package/dist/components/ProductNav/types.js +0 -0
- package/dist/components/ProductNav/useLocationPathname.d.ts +4 -0
- package/dist/components/ProductNav/useLocationPathname.js +24 -0
- package/dist/components/ProductNav/useProductNav.d.ts +16 -0
- package/dist/components/ProductNav/useProductNav.js +19 -0
- package/dist/components/RemoteShell/RemoteShell.d.ts +7 -0
- package/dist/components/RemoteShell/RemoteShell.js +16 -0
- package/dist/components/RemoteShell/RemoteShellBreadcrumb.d.ts +6 -0
- package/dist/components/RemoteShell/RemoteShellBreadcrumb.js +16 -0
- package/dist/components/RemoteShell/RemoteShellContent.d.ts +6 -0
- package/dist/components/RemoteShell/RemoteShellContent.js +16 -0
- package/dist/components/RemoteShell/RemoteShellPanel.d.ts +6 -0
- package/dist/components/RemoteShell/RemoteShellPanel.js +16 -0
- package/dist/components/RemoteShell/index.d.ts +4 -0
- package/dist/components/RemoteShell/index.js +5 -0
- package/dist/components/SimpleCharts/LineChart/LineChart.js +5 -5
- package/dist/components/SimpleCharts/LineChart/LineChartZoomBrush.js +66 -12
- package/dist/components/SimpleCharts/LineChart/hooks/useLineChartActiveKey.js +4 -3
- package/dist/components/SimpleCharts/LineChart/hooks/useLineChartZoomState.d.ts +9 -2
- package/dist/components/SimpleCharts/LineChart/hooks/useLineChartZoomState.js +88 -34
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/useArrowNav.d.ts +7 -0
- package/dist/hooks/useArrowNav.js +98 -0
- package/dist/icons/ChevronUpDown.d.ts +3 -0
- package/dist/icons/ChevronUpDown.js +12 -0
- package/dist/icons/MapPin.d.ts +3 -0
- package/dist/icons/MapPin.js +12 -0
- package/dist/icons/index.d.ts +2 -0
- package/dist/icons/index.js +3 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -1
- package/dist/metadata/components.json +4829 -682
- package/package.json +1 -1
|
@@ -27,9 +27,10 @@ const breadcrumbsItemVariants = cva([
|
|
|
27
27
|
const BreadcrumbsItem = ({ className, isCurrent = false, href, children, onClick, 'aria-label': ariaLabel, ...props })=>{
|
|
28
28
|
const testId = useTestId('item');
|
|
29
29
|
const isLink = href && !isCurrent;
|
|
30
|
+
const isInteractive = !!href || !!onClick;
|
|
30
31
|
const commonClasses = cn(breadcrumbsItemVariants({
|
|
31
32
|
isCurrent
|
|
32
|
-
}), className);
|
|
33
|
+
}), !isInteractive && 'cursor-default hover:bg-transparent active:bg-transparent', className);
|
|
33
34
|
return /*#__PURE__*/ jsx("li", {
|
|
34
35
|
children: isLink ? /*#__PURE__*/ jsx("a", {
|
|
35
36
|
href: href,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FC, ReactNode, Ref } from 'react';
|
|
2
|
+
export interface ScopeSwitcherItem {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
href: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BreadcrumbsScopeSwitcherProps {
|
|
9
|
+
ref?: Ref<HTMLButtonElement>;
|
|
10
|
+
value: string;
|
|
11
|
+
items: ScopeSwitcherItem[];
|
|
12
|
+
onSelect: (item: ScopeSwitcherItem) => void;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
className?: string;
|
|
15
|
+
/** @internal - set automatically by parent */
|
|
16
|
+
isCurrent?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const BreadcrumbsScopeSwitcher: FC<BreadcrumbsScopeSwitcherProps>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Check, ChevronUpDown } from "../../icons/index.js";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuItemText, DropdownMenuShortcut, DropdownMenuTrigger } from "../DropdownMenu/index.js";
|
|
6
|
+
const BreadcrumbsScopeSwitcher = ({ ref, value, items, onSelect, children, className, isCurrent = false })=>{
|
|
7
|
+
const testId = useTestId('scope-switcher');
|
|
8
|
+
return /*#__PURE__*/ jsx("li", {
|
|
9
|
+
children: /*#__PURE__*/ jsxs(DropdownMenu, {
|
|
10
|
+
children: [
|
|
11
|
+
/*#__PURE__*/ jsx(DropdownMenuTrigger, {
|
|
12
|
+
asChild: true,
|
|
13
|
+
children: /*#__PURE__*/ jsxs("button", {
|
|
14
|
+
ref: ref,
|
|
15
|
+
type: "button",
|
|
16
|
+
"aria-haspopup": "dialog",
|
|
17
|
+
"data-slot": "breadcrumbs-scope-switcher",
|
|
18
|
+
"data-testid": testId,
|
|
19
|
+
className: cn('flex items-center gap-4 rounded-6 px-4 py-0 text-sm transition-colors', 'hover:bg-states-primary-hover active:bg-states-primary-pressed cursor-pointer', 'focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-focus-primary', isCurrent ? 'font-medium text-text-primary' : 'font-normal text-text-secondary', className),
|
|
20
|
+
children: [
|
|
21
|
+
children,
|
|
22
|
+
/*#__PURE__*/ jsx(ChevronUpDown, {
|
|
23
|
+
size: "sm",
|
|
24
|
+
className: "text-text-secondary"
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
})
|
|
28
|
+
}),
|
|
29
|
+
/*#__PURE__*/ jsx(DropdownMenuContent, {
|
|
30
|
+
children: items.map((item)=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
|
|
31
|
+
onSelect: ()=>onSelect(item),
|
|
32
|
+
children: [
|
|
33
|
+
/*#__PURE__*/ jsx(DropdownMenuItemText, {
|
|
34
|
+
children: /*#__PURE__*/ jsxs("span", {
|
|
35
|
+
className: "flex flex-col",
|
|
36
|
+
children: [
|
|
37
|
+
/*#__PURE__*/ jsx("span", {
|
|
38
|
+
children: item.label
|
|
39
|
+
}),
|
|
40
|
+
item.description && /*#__PURE__*/ jsx("span", {
|
|
41
|
+
className: "text-xs text-text-secondary",
|
|
42
|
+
children: item.description
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
})
|
|
46
|
+
}),
|
|
47
|
+
item.id === value && /*#__PURE__*/ jsx(DropdownMenuShortcut, {
|
|
48
|
+
children: /*#__PURE__*/ jsx(Check, {
|
|
49
|
+
size: "sm"
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
]
|
|
53
|
+
}, item.id))
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
BreadcrumbsScopeSwitcher.displayName = 'BreadcrumbsScopeSwitcher';
|
|
60
|
+
export { BreadcrumbsScopeSwitcher };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Breadcrumbs, type BreadcrumbsProps } from './Breadcrumbs';
|
|
2
2
|
export { BreadcrumbsEllipsis, type BreadcrumbsEllipsisProps, } from './BreadcrumbsEllipsis';
|
|
3
3
|
export { BreadcrumbsItem, type BreadcrumbsItemProps } from './BreadcrumbsItem';
|
|
4
|
+
export { BreadcrumbsScopeSwitcher, type BreadcrumbsScopeSwitcherProps, type ScopeSwitcherItem, } from './BreadcrumbsScopeSwitcher';
|
|
4
5
|
export { BreadcrumbsSeparator, type BreadcrumbsSeparatorProps, } from './BreadcrumbsSeparator';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Breadcrumbs } from "./Breadcrumbs.js";
|
|
2
2
|
import { BreadcrumbsEllipsis } from "./BreadcrumbsEllipsis.js";
|
|
3
3
|
import { BreadcrumbsItem } from "./BreadcrumbsItem.js";
|
|
4
|
+
import { BreadcrumbsScopeSwitcher } from "./BreadcrumbsScopeSwitcher.js";
|
|
4
5
|
import { BreadcrumbsSeparator } from "./BreadcrumbsSeparator.js";
|
|
5
|
-
export { Breadcrumbs, BreadcrumbsEllipsis, BreadcrumbsItem, BreadcrumbsSeparator };
|
|
6
|
+
export { Breadcrumbs, BreadcrumbsEllipsis, BreadcrumbsItem, BreadcrumbsScopeSwitcher, BreadcrumbsSeparator };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type FC, type HTMLAttributes, type ReactNode, type Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId';
|
|
3
|
+
export interface NavPanelProps extends HTMLAttributes<HTMLElement>, TestableProps {
|
|
4
|
+
ref?: Ref<HTMLElement>;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
resizable?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const NavPanel: FC<NavPanelProps>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { composeRefs } from "@radix-ui/react-compose-refs";
|
|
4
|
+
import { useArrowNav } from "../../hooks/useArrowNav.js";
|
|
5
|
+
import { cn } from "../../utils/cn.js";
|
|
6
|
+
import { TestIdProvider } from "../../utils/testId.js";
|
|
7
|
+
import { NavPanelInternalProvider } from "./NavPanelContext.js";
|
|
8
|
+
import { NavPanelResizeHandle } from "./NavPanelResizeHandle.js";
|
|
9
|
+
const DEFAULT_WIDTH = 216;
|
|
10
|
+
const MIN_WIDTH = 164;
|
|
11
|
+
const MAX_WIDTH = 256;
|
|
12
|
+
const NavPanel = ({ ref, className, children, resizable = false, 'data-testid': testId, 'aria-label': ariaLabel = 'Product navigation', ...props })=>{
|
|
13
|
+
const internalRef = useRef(null);
|
|
14
|
+
const focusRail = useCallback(()=>{
|
|
15
|
+
const rail = document.querySelector('[data-slot="nav-rail"]');
|
|
16
|
+
const target = rail?.querySelector('[tabindex="0"]');
|
|
17
|
+
target?.focus();
|
|
18
|
+
}, []);
|
|
19
|
+
const focusFirstItemAfterNav = useCallback(()=>{
|
|
20
|
+
const container = internalRef.current;
|
|
21
|
+
if (!container) return;
|
|
22
|
+
const observer = new MutationObserver(()=>{
|
|
23
|
+
const back = container.querySelector('[data-slot="nav-panel-back"]');
|
|
24
|
+
const first = container.querySelector('[data-slot="nav-panel-item"], [data-slot="nav-panel-back"]');
|
|
25
|
+
const target = back ?? first;
|
|
26
|
+
if (target) {
|
|
27
|
+
target.setAttribute('tabindex', '0');
|
|
28
|
+
target.focus();
|
|
29
|
+
observer.disconnect();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
observer.observe(container, {
|
|
33
|
+
childList: true,
|
|
34
|
+
subtree: true
|
|
35
|
+
});
|
|
36
|
+
setTimeout(()=>observer.disconnect(), 2000);
|
|
37
|
+
}, []);
|
|
38
|
+
useArrowNav(internalRef, '[data-slot="nav-panel-item"], [data-slot="nav-panel-group-label"], [data-slot="nav-panel-group-item"], [data-slot="nav-panel-back"]', {
|
|
39
|
+
onArrowLeft: focusRail,
|
|
40
|
+
onEnter: focusFirstItemAfterNav
|
|
41
|
+
});
|
|
42
|
+
const [width, setWidth] = useState(DEFAULT_WIDTH);
|
|
43
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
44
|
+
const contextValue = useMemo(()=>({
|
|
45
|
+
width,
|
|
46
|
+
setWidth,
|
|
47
|
+
isResizing,
|
|
48
|
+
setIsResizing,
|
|
49
|
+
minWidth: MIN_WIDTH,
|
|
50
|
+
maxWidth: MAX_WIDTH
|
|
51
|
+
}), [
|
|
52
|
+
width,
|
|
53
|
+
isResizing
|
|
54
|
+
]);
|
|
55
|
+
if (resizable) return /*#__PURE__*/ jsx(TestIdProvider, {
|
|
56
|
+
value: testId,
|
|
57
|
+
children: /*#__PURE__*/ jsx(NavPanelInternalProvider, {
|
|
58
|
+
value: contextValue,
|
|
59
|
+
children: /*#__PURE__*/ jsxs("aside", {
|
|
60
|
+
...props,
|
|
61
|
+
ref: composeRefs(internalRef, ref),
|
|
62
|
+
"aria-label": ariaLabel,
|
|
63
|
+
"data-slot": "nav-panel",
|
|
64
|
+
"data-testid": testId,
|
|
65
|
+
style: {
|
|
66
|
+
width
|
|
67
|
+
},
|
|
68
|
+
className: cn('relative h-full shrink-0 border-r border-border-primary pt-8', isResizing && 'select-none', className),
|
|
69
|
+
children: [
|
|
70
|
+
/*#__PURE__*/ jsx("div", {
|
|
71
|
+
className: "flex h-full flex-col gap-2 overflow-y-auto [scrollbar-width:thin] px-8 pb-8",
|
|
72
|
+
children: children
|
|
73
|
+
}),
|
|
74
|
+
/*#__PURE__*/ jsx(NavPanelResizeHandle, {})
|
|
75
|
+
]
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
return /*#__PURE__*/ jsx(TestIdProvider, {
|
|
80
|
+
value: testId,
|
|
81
|
+
children: /*#__PURE__*/ jsx("aside", {
|
|
82
|
+
...props,
|
|
83
|
+
ref: composeRefs(internalRef, ref),
|
|
84
|
+
"aria-label": ariaLabel,
|
|
85
|
+
"data-slot": "nav-panel",
|
|
86
|
+
"data-testid": testId,
|
|
87
|
+
className: cn('flex h-full w-[216px] shrink-0 flex-col gap-2 overflow-y-auto [scrollbar-width:thin] border-r border-border-primary p-8', className),
|
|
88
|
+
children: children
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
NavPanel.displayName = 'NavPanel';
|
|
93
|
+
export { NavPanel };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, FC, ReactNode, Ref } from 'react';
|
|
2
|
+
export interface NavPanelBackProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
3
|
+
ref?: Ref<HTMLButtonElement>;
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
export declare const NavPanelBack: FC<NavPanelBackProps>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CornerUpLeft } from "../../icons/index.js";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { Text } from "../Text/index.js";
|
|
6
|
+
const NavPanelBack = ({ ref, className, children, ...props })=>{
|
|
7
|
+
const testId = useTestId('back');
|
|
8
|
+
return /*#__PURE__*/ jsxs("button", {
|
|
9
|
+
...props,
|
|
10
|
+
ref: ref,
|
|
11
|
+
type: "button",
|
|
12
|
+
"data-slot": "nav-panel-back",
|
|
13
|
+
"data-testid": testId,
|
|
14
|
+
className: cn('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-6 p-8 text-sm text-text-secondary transition-colors outline-none hover:overlay-states-primary-hover focus-visible:overlay-states-primary-hover active:overlay-states-primary-pressed', className),
|
|
15
|
+
children: [
|
|
16
|
+
/*#__PURE__*/ jsx(CornerUpLeft, {
|
|
17
|
+
size: "md"
|
|
18
|
+
}),
|
|
19
|
+
/*#__PURE__*/ jsxs(Text, {
|
|
20
|
+
size: "sm",
|
|
21
|
+
truncate: true,
|
|
22
|
+
children: [
|
|
23
|
+
"Back to ",
|
|
24
|
+
children
|
|
25
|
+
]
|
|
26
|
+
})
|
|
27
|
+
]
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
NavPanelBack.displayName = 'NavPanelBack';
|
|
31
|
+
export { NavPanelBack };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Dispatch, type SetStateAction } from 'react';
|
|
2
|
+
interface NavPanelInternalContextValue {
|
|
3
|
+
width: number;
|
|
4
|
+
setWidth: Dispatch<SetStateAction<number>>;
|
|
5
|
+
isResizing: boolean;
|
|
6
|
+
setIsResizing: Dispatch<SetStateAction<boolean>>;
|
|
7
|
+
minWidth: number;
|
|
8
|
+
maxWidth: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const NavPanelInternalProvider: import("react").Provider<NavPanelInternalContextValue | null>;
|
|
11
|
+
export declare function useNavPanelInternalContext(): NavPanelInternalContextValue;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
const NavPanelInternalContext = /*#__PURE__*/ createContext(null);
|
|
3
|
+
const NavPanelInternalProvider = NavPanelInternalContext.Provider;
|
|
4
|
+
function useNavPanelInternalContext() {
|
|
5
|
+
const ctx = useContext(NavPanelInternalContext);
|
|
6
|
+
if (!ctx) throw new Error('useNavPanelInternalContext must be used within NavPanelInternalProvider');
|
|
7
|
+
return ctx;
|
|
8
|
+
}
|
|
9
|
+
export { NavPanelInternalProvider, useNavPanelInternalContext };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
const NavPanelDivider = ({ className, ...props })=>/*#__PURE__*/ jsx("div", {
|
|
4
|
+
...props,
|
|
5
|
+
role: "none",
|
|
6
|
+
"data-slot": "nav-panel-divider",
|
|
7
|
+
className: cn('my-4 mx-8 h-px shrink-0 bg-border-primary', className)
|
|
8
|
+
});
|
|
9
|
+
NavPanelDivider.displayName = 'NavPanelDivider';
|
|
10
|
+
export { NavPanelDivider };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type FC, type HTMLAttributes, type ReactNode, type Ref } from 'react';
|
|
2
|
+
interface NavPanelGroupContextValue {
|
|
3
|
+
expanded: boolean;
|
|
4
|
+
toggle: () => void;
|
|
5
|
+
contentId: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function useNavPanelGroupContext(): NavPanelGroupContextValue;
|
|
8
|
+
declare const NavPanelDepthContext: import("react").Context<number>;
|
|
9
|
+
export declare function useNavPanelDepth(): number;
|
|
10
|
+
export { NavPanelDepthContext };
|
|
11
|
+
export interface NavPanelGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
12
|
+
ref?: Ref<HTMLDivElement>;
|
|
13
|
+
expanded?: boolean;
|
|
14
|
+
defaultExpanded?: boolean;
|
|
15
|
+
onExpandedChange?: (expanded: boolean) => void;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export declare const NavPanelGroup: FC<NavPanelGroupProps>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useId, useState } from "react";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
const NavPanelGroupContext = /*#__PURE__*/ createContext({
|
|
6
|
+
expanded: false,
|
|
7
|
+
toggle: ()=>{},
|
|
8
|
+
contentId: ''
|
|
9
|
+
});
|
|
10
|
+
function useNavPanelGroupContext() {
|
|
11
|
+
return useContext(NavPanelGroupContext);
|
|
12
|
+
}
|
|
13
|
+
const NavPanelDepthContext = /*#__PURE__*/ createContext(0);
|
|
14
|
+
function useNavPanelDepth() {
|
|
15
|
+
return useContext(NavPanelDepthContext);
|
|
16
|
+
}
|
|
17
|
+
const NavPanelGroup = ({ ref, expanded: controlledExpanded, defaultExpanded = false, onExpandedChange, className, children, ...props })=>{
|
|
18
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultExpanded);
|
|
19
|
+
const isControlled = void 0 !== controlledExpanded;
|
|
20
|
+
const expanded = isControlled ? controlledExpanded : uncontrolledExpanded;
|
|
21
|
+
const contentId = useId();
|
|
22
|
+
const testId = useTestId('group');
|
|
23
|
+
const toggle = useCallback(()=>{
|
|
24
|
+
const next = !expanded;
|
|
25
|
+
if (!isControlled) setUncontrolledExpanded(next);
|
|
26
|
+
onExpandedChange?.(next);
|
|
27
|
+
}, [
|
|
28
|
+
expanded,
|
|
29
|
+
isControlled,
|
|
30
|
+
onExpandedChange
|
|
31
|
+
]);
|
|
32
|
+
return /*#__PURE__*/ jsx(NavPanelGroupContext.Provider, {
|
|
33
|
+
value: {
|
|
34
|
+
expanded,
|
|
35
|
+
toggle,
|
|
36
|
+
contentId
|
|
37
|
+
},
|
|
38
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
39
|
+
...props,
|
|
40
|
+
ref: ref,
|
|
41
|
+
"data-slot": "nav-panel-group",
|
|
42
|
+
"data-testid": testId,
|
|
43
|
+
className: cn('flex flex-col', className),
|
|
44
|
+
children: children
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
NavPanelGroup.displayName = 'NavPanelGroup';
|
|
49
|
+
export { NavPanelDepthContext, NavPanelGroup, useNavPanelDepth, useNavPanelGroupContext };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type FC, type HTMLAttributes, type ReactNode, type Ref } from 'react';
|
|
2
|
+
export interface NavPanelGroupContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
ref?: Ref<HTMLDivElement>;
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
export declare const NavPanelGroupContent: FC<NavPanelGroupContentProps>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { NavPanelDepthContext, useNavPanelDepth, useNavPanelGroupContext } from "./NavPanelGroup.js";
|
|
5
|
+
const NavPanelGroupContent = ({ ref, className, children, ...props })=>{
|
|
6
|
+
const { expanded, contentId } = useNavPanelGroupContext();
|
|
7
|
+
const parentDepth = useNavPanelDepth();
|
|
8
|
+
const depth = parentDepth + 1;
|
|
9
|
+
const innerRef = useRef(null);
|
|
10
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
11
|
+
...props,
|
|
12
|
+
ref: ref,
|
|
13
|
+
id: contentId,
|
|
14
|
+
role: "group",
|
|
15
|
+
"data-slot": "nav-panel-group-content",
|
|
16
|
+
className: cn('relative grid transition-[grid-template-rows] duration-150 ease-out', expanded ? 'grid-rows-[1fr] mt-2' : 'grid-rows-[0fr]', className),
|
|
17
|
+
children: [
|
|
18
|
+
/*#__PURE__*/ jsx("div", {
|
|
19
|
+
className: "absolute top-0 bottom-0 w-px bg-border-primary",
|
|
20
|
+
style: {
|
|
21
|
+
left: 16 * depth + 8 * parentDepth
|
|
22
|
+
}
|
|
23
|
+
}),
|
|
24
|
+
/*#__PURE__*/ jsx(NavPanelDepthContext.Provider, {
|
|
25
|
+
value: depth,
|
|
26
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
27
|
+
ref: innerRef,
|
|
28
|
+
className: "flex flex-col gap-2 overflow-hidden",
|
|
29
|
+
children: children
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
NavPanelGroupContent.displayName = 'NavPanelGroupContent';
|
|
36
|
+
export { NavPanelGroupContent };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ComponentType, FC, ReactNode, Ref } from 'react';
|
|
2
|
+
import type { SvgIconProps } from '../../icons/SvgIcon';
|
|
3
|
+
export interface NavPanelGroupItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
4
|
+
ref?: Ref<HTMLAnchorElement>;
|
|
5
|
+
asChild?: boolean;
|
|
6
|
+
icon?: ComponentType<SvgIconProps>;
|
|
7
|
+
active?: boolean;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare const NavPanelGroupItem: FC<NavPanelGroupItemProps>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { Text } from "../Text/index.js";
|
|
6
|
+
import { navPanelGroupItemVariants } from "./classes.js";
|
|
7
|
+
import { useNavPanelDepth } from "./NavPanelGroup.js";
|
|
8
|
+
const NavPanelGroupItem = ({ ref, asChild = false, icon: Icon, active = false, className, children, ...props })=>{
|
|
9
|
+
const testId = useTestId('group-item');
|
|
10
|
+
const depth = useNavPanelDepth();
|
|
11
|
+
const Comp = asChild ? Slot : 'a';
|
|
12
|
+
return /*#__PURE__*/ jsxs(Comp, {
|
|
13
|
+
...props,
|
|
14
|
+
ref: ref,
|
|
15
|
+
"aria-current": active ? 'page' : void 0,
|
|
16
|
+
"data-slot": "nav-panel-group-item",
|
|
17
|
+
"data-testid": testId,
|
|
18
|
+
className: cn(navPanelGroupItemVariants({
|
|
19
|
+
active
|
|
20
|
+
}), className),
|
|
21
|
+
style: {
|
|
22
|
+
paddingLeft: 8 + 24 * depth
|
|
23
|
+
},
|
|
24
|
+
children: [
|
|
25
|
+
Icon && /*#__PURE__*/ jsx("span", {
|
|
26
|
+
className: "flex shrink-0 items-center justify-center",
|
|
27
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
28
|
+
size: "md"
|
|
29
|
+
})
|
|
30
|
+
}),
|
|
31
|
+
/*#__PURE__*/ jsx(Text, {
|
|
32
|
+
size: "sm",
|
|
33
|
+
truncate: true,
|
|
34
|
+
children: children
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
NavPanelGroupItem.displayName = 'NavPanelGroupItem';
|
|
40
|
+
export { NavPanelGroupItem };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, ComponentType, FC, ReactNode, Ref } from 'react';
|
|
2
|
+
import type { SvgIconProps } from '../../icons/SvgIcon';
|
|
3
|
+
export interface NavPanelGroupLabelProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
ref?: Ref<HTMLButtonElement>;
|
|
5
|
+
icon?: ComponentType<SvgIconProps>;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const NavPanelGroupLabel: FC<NavPanelGroupLabelProps>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronRight } from "../../icons/index.js";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { Text } from "../Text/index.js";
|
|
6
|
+
import { useNavPanelDepth, useNavPanelGroupContext } from "./NavPanelGroup.js";
|
|
7
|
+
const NavPanelGroupLabel = ({ ref, icon: Icon, className, children, ...props })=>{
|
|
8
|
+
const { expanded, toggle, contentId } = useNavPanelGroupContext();
|
|
9
|
+
const depth = useNavPanelDepth();
|
|
10
|
+
const testId = useTestId('group-label');
|
|
11
|
+
return /*#__PURE__*/ jsxs("button", {
|
|
12
|
+
...props,
|
|
13
|
+
ref: ref,
|
|
14
|
+
type: "button",
|
|
15
|
+
"aria-expanded": expanded,
|
|
16
|
+
"aria-controls": contentId,
|
|
17
|
+
"data-slot": "nav-panel-group-label",
|
|
18
|
+
"data-testid": testId,
|
|
19
|
+
onClick: toggle,
|
|
20
|
+
style: {
|
|
21
|
+
paddingLeft: 8 + 24 * depth
|
|
22
|
+
},
|
|
23
|
+
className: cn('overlay flex h-32 shrink-0 w-full cursor-pointer items-center gap-8 rounded-6 py-8 pr-8 text-sm text-text-secondary transition-colors outline-none hover:overlay-states-primary-hover focus-visible:overlay-states-primary-hover active:overlay-states-primary-pressed', className),
|
|
24
|
+
children: [
|
|
25
|
+
Icon && /*#__PURE__*/ jsx("span", {
|
|
26
|
+
className: "flex shrink-0 items-center justify-center",
|
|
27
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
28
|
+
size: "md"
|
|
29
|
+
})
|
|
30
|
+
}),
|
|
31
|
+
/*#__PURE__*/ jsx(Text, {
|
|
32
|
+
size: "sm",
|
|
33
|
+
style: {
|
|
34
|
+
flex: 1
|
|
35
|
+
},
|
|
36
|
+
align: "left",
|
|
37
|
+
truncate: true,
|
|
38
|
+
children: children
|
|
39
|
+
}),
|
|
40
|
+
/*#__PURE__*/ jsx(ChevronRight, {
|
|
41
|
+
size: "sm",
|
|
42
|
+
className: cn('shrink-0 transition-transform duration-150', expanded && 'rotate-90')
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
NavPanelGroupLabel.displayName = 'NavPanelGroupLabel';
|
|
48
|
+
export { NavPanelGroupLabel };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { useTestId } from "../../utils/testId.js";
|
|
4
|
+
import { Text } from "../Text/index.js";
|
|
5
|
+
const NavPanelHeader = ({ ref, className, children, ...props })=>{
|
|
6
|
+
const testId = useTestId('header');
|
|
7
|
+
return /*#__PURE__*/ jsx("div", {
|
|
8
|
+
...props,
|
|
9
|
+
ref: ref,
|
|
10
|
+
"data-slot": "nav-panel-header",
|
|
11
|
+
"data-testid": testId,
|
|
12
|
+
className: cn('sticky top-0 z-10 flex shrink-0 items-center bg-bg-surface-1 p-4', className),
|
|
13
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
14
|
+
size: "sm",
|
|
15
|
+
weight: "medium",
|
|
16
|
+
children: children
|
|
17
|
+
})
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
NavPanelHeader.displayName = 'NavPanelHeader';
|
|
21
|
+
export { NavPanelHeader };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ComponentType, FC, ReactNode, Ref } from 'react';
|
|
2
|
+
import type { SvgIconProps } from '../../icons/SvgIcon';
|
|
3
|
+
export interface NavPanelItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
4
|
+
ref?: Ref<HTMLAnchorElement>;
|
|
5
|
+
asChild?: boolean;
|
|
6
|
+
icon?: ComponentType<SvgIconProps>;
|
|
7
|
+
active?: boolean;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare const NavPanelItem: FC<NavPanelItemProps>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { Text } from "../Text/index.js";
|
|
6
|
+
import { navPanelItemVariants } from "./classes.js";
|
|
7
|
+
const NavPanelItem = ({ ref, asChild = false, icon: Icon, active = false, className, children, ...props })=>{
|
|
8
|
+
const testId = useTestId('item');
|
|
9
|
+
const Comp = asChild ? Slot : 'a';
|
|
10
|
+
return /*#__PURE__*/ jsxs(Comp, {
|
|
11
|
+
...props,
|
|
12
|
+
ref: ref,
|
|
13
|
+
"aria-current": active ? 'page' : void 0,
|
|
14
|
+
"data-slot": "nav-panel-item",
|
|
15
|
+
"data-testid": testId,
|
|
16
|
+
className: cn(navPanelItemVariants({
|
|
17
|
+
active
|
|
18
|
+
}), className),
|
|
19
|
+
children: [
|
|
20
|
+
Icon && /*#__PURE__*/ jsx("span", {
|
|
21
|
+
className: "flex shrink-0 items-center justify-center",
|
|
22
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
23
|
+
size: "md"
|
|
24
|
+
})
|
|
25
|
+
}),
|
|
26
|
+
/*#__PURE__*/ jsx(Text, {
|
|
27
|
+
size: "sm",
|
|
28
|
+
truncate: true,
|
|
29
|
+
children: children
|
|
30
|
+
})
|
|
31
|
+
]
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
NavPanelItem.displayName = 'NavPanelItem';
|
|
35
|
+
export { NavPanelItem };
|