@common-origin/design-system 3.0.0 → 3.1.0
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/client.js +2175 -687
- package/dist/client.js.map +1 -1
- package/dist/components/atoms/Tooltip/Tooltip.d.mts +41 -0
- package/dist/components/atoms/Tooltip/Tooltip.d.ts +41 -0
- package/dist/components/atoms/Tooltip/Tooltip.mjs +204 -0
- package/dist/components/atoms/Tooltip/Tooltip.mjs.map +1 -0
- package/dist/components/atoms/Tooltip/index.d.mts +2 -0
- package/dist/components/atoms/Tooltip/index.d.ts +2 -0
- package/dist/components/atoms/index.d.mts +1 -0
- package/dist/components/atoms/index.d.ts +1 -0
- package/dist/components/index.d.mts +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/molecules/ActionSheet/ActionSheet.mjs +1 -0
- package/dist/components/molecules/Alert/Alert.mjs +1 -1
- package/dist/components/molecules/ChipGroup/ChipGroup.mjs +1 -0
- package/dist/components/molecules/List/List.d.mts +2 -0
- package/dist/components/molecules/List/List.d.ts +2 -0
- package/dist/components/molecules/List/ListItem.d.mts +2 -0
- package/dist/components/molecules/List/ListItem.d.ts +2 -0
- package/dist/components/molecules/List/ListItem.mjs +5 -5
- package/dist/components/molecules/Menu/Menu.d.mts +117 -0
- package/dist/components/molecules/Menu/Menu.d.ts +117 -0
- package/dist/components/molecules/Menu/Menu.mjs +473 -0
- package/dist/components/molecules/Menu/Menu.mjs.map +1 -0
- package/dist/components/molecules/Menu/index.d.mts +2 -0
- package/dist/components/molecules/Menu/index.d.ts +2 -0
- package/dist/components/molecules/SearchField/SearchField.mjs +2 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavContext.d.mts +13 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavContext.d.ts +13 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavContext.mjs +13 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavContext.mjs.map +1 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavItem.d.mts +43 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavItem.d.ts +43 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavItem.mjs +148 -0
- package/dist/components/molecules/SidebarNavItem/SidebarNavItem.mjs.map +1 -0
- package/dist/components/molecules/SidebarNavItem/index.d.mts +2 -0
- package/dist/components/molecules/SidebarNavItem/index.d.ts +2 -0
- package/dist/components/molecules/SidebarNavSection/SidebarNavSection.d.mts +36 -0
- package/dist/components/molecules/SidebarNavSection/SidebarNavSection.d.ts +36 -0
- package/dist/components/molecules/SidebarNavSection/SidebarNavSection.mjs +188 -0
- package/dist/components/molecules/SidebarNavSection/SidebarNavSection.mjs.map +1 -0
- package/dist/components/molecules/SidebarNavSection/index.d.mts +2 -0
- package/dist/components/molecules/SidebarNavSection/index.d.ts +2 -0
- package/dist/components/molecules/TransactionListItem/TransactionListItem.mjs +1 -1
- package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.d.mts +39 -0
- package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.d.ts +39 -0
- package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.mjs +131 -0
- package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.mjs.map +1 -0
- package/dist/components/molecules/WorkspaceSwitcher/index.d.mts +2 -0
- package/dist/components/molecules/WorkspaceSwitcher/index.d.ts +2 -0
- package/dist/components/molecules/index.d.mts +4 -0
- package/dist/components/molecules/index.d.ts +4 -0
- package/dist/components/organisms/SidebarNav/SidebarNav.d.mts +52 -0
- package/dist/components/organisms/SidebarNav/SidebarNav.d.ts +52 -0
- package/dist/components/organisms/SidebarNav/SidebarNav.mjs +235 -0
- package/dist/components/organisms/SidebarNav/SidebarNav.mjs.map +1 -0
- package/dist/components/organisms/SidebarNav/index.d.mts +2 -0
- package/dist/components/organisms/SidebarNav/index.d.ts +2 -0
- package/dist/components/organisms/index.d.mts +1 -0
- package/dist/components/organisms/index.d.ts +1 -0
- package/dist/data.js +59 -9
- package/dist/data.js.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -1
- package/dist/lib/floatingPosition.d.mts +43 -0
- package/dist/lib/floatingPosition.d.ts +43 -0
- package/dist/lib/floatingPosition.mjs +86 -0
- package/dist/lib/floatingPosition.mjs.map +1 -0
- package/dist/lib/keyboardFocus.d.mts +6 -0
- package/dist/lib/keyboardFocus.d.ts +6 -0
- package/dist/lib/keyboardFocus.mjs +17 -0
- package/dist/lib/keyboardFocus.mjs.map +1 -0
- package/dist/lib/useFloatingLayer.d.mts +25 -0
- package/dist/lib/useFloatingLayer.d.ts +25 -0
- package/dist/lib/useFloatingLayer.mjs +86 -0
- package/dist/lib/useFloatingLayer.mjs.map +1 -0
- package/dist/styles/icons.json +30 -1
- package/dist/styles/icons.json.mjs +34 -3
- package/dist/styles/icons.json.mjs.map +1 -1
- package/dist/styles/tokens.d.mts +46 -8
- package/dist/styles/tokens.d.ts +46 -8
- package/dist/styles/tokens.json +26 -7
- package/dist/styles/tokens.json.mjs +26 -7
- package/dist/styles/tokens.json.mjs.map +1 -1
- package/dist/tokens/index.js +26 -7
- package/dist/tokens/index.js.map +1 -1
- package/dist/tokens/index.mjs +26 -7
- package/dist/tokens/index.mjs.map +1 -1
- package/dist/tokens/styles/tokens.d.mts +46 -8
- package/dist/tokens/styles/tokens.d.ts +46 -8
- package/dist/tokens.css +35 -15
- package/dist/types/icons.d.mts +1 -1
- package/dist/types/icons.d.ts +1 -1
- package/dist/types/icons.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { __makeTemplateObject } from '../../../vendor/tslib/tslib.es6.mjs';
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { useEffect } from 'react';
|
|
5
|
+
import styled$module, { css } from 'styled-components';
|
|
6
|
+
const styled = styled$module.default || styled$module;
|
|
7
|
+
import tokens from '../../../lib/cssTokens.mjs';
|
|
8
|
+
import { interactiveRow } from '../../../lib/styleUtils.mjs';
|
|
9
|
+
import { Avatar } from '../../atoms/Avatar/Avatar.mjs';
|
|
10
|
+
import { Icon } from '../../atoms/Icon/Icon.mjs';
|
|
11
|
+
import { Tooltip } from '../../atoms/Tooltip/Tooltip.mjs';
|
|
12
|
+
import { Menu, MenuGroup, MenuItemRadio, MenuDivider } from '../Menu/Menu.mjs';
|
|
13
|
+
import { useSidebarNav } from '../SidebarNavItem/SidebarNavContext.mjs';
|
|
14
|
+
|
|
15
|
+
var semantic = tokens.semantic;
|
|
16
|
+
var space = semantic.space,
|
|
17
|
+
color = semantic.color,
|
|
18
|
+
motion = semantic.motion,
|
|
19
|
+
radius = semantic.radius,
|
|
20
|
+
size = semantic.size,
|
|
21
|
+
border = semantic.border,
|
|
22
|
+
typography = semantic.typography;
|
|
23
|
+
var Trigger = /*#__PURE__*/styled.button.withConfig({
|
|
24
|
+
shouldForwardProp: function shouldForwardProp(prop) {
|
|
25
|
+
return !prop.startsWith('$');
|
|
26
|
+
},
|
|
27
|
+
displayName: "WorkspaceSwitcher__Trigger",
|
|
28
|
+
componentId: "sc-s35ke-0"
|
|
29
|
+
})(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n min-height: ", ";\n padding: ", " ", ";\n border: none;\n border-radius: ", ";\n background: none;\n font: ", ";\n color: ", ";\n text-align: left;\n cursor: pointer;\n transition: background-color ", " ", ";\n\n ", "\n\n ", "\n\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: ", ";\n outline-offset: calc(-1 * ", ");\n }\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n min-height: ", ";\n padding: ", " ", ";\n border: none;\n border-radius: ", ";\n background: none;\n font: ", ";\n color: ", ";\n text-align: left;\n cursor: pointer;\n transition: background-color ", " ", ";\n\n ", "\n\n ", "\n\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: ", ";\n outline-offset: calc(-1 * ", ");\n }\n"])), space[200], size.row.sm, space.inset.xs, space.inset.sm, radius.sm, typography.label, color.text["default"], motion.duration.fast, motion.easing.decelerate, interactiveRow(), function (_a) {
|
|
30
|
+
var $collapsed = _a.$collapsed;
|
|
31
|
+
return $collapsed && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n justify-content: center;\n padding: ", ";\n "], ["\n justify-content: center;\n padding: ", ";\n "])), space.inset.xs);
|
|
32
|
+
}, border.focus, border.focusOffset);
|
|
33
|
+
var Name = /*#__PURE__*/styled.span.withConfig({
|
|
34
|
+
displayName: "WorkspaceSwitcher__Name",
|
|
35
|
+
componentId: "sc-s35ke-1"
|
|
36
|
+
})(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n"], ["\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n"])));
|
|
37
|
+
var Decoration = /*#__PURE__*/styled.span.withConfig({
|
|
38
|
+
displayName: "WorkspaceSwitcher__Decoration",
|
|
39
|
+
componentId: "sc-s35ke-2"
|
|
40
|
+
})(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n display: inline-flex;\n flex-shrink: 0;\n color: ", ";\n"], ["\n display: inline-flex;\n flex-shrink: 0;\n color: ", ";\n"
|
|
41
|
+
/**
|
|
42
|
+
* Shows the current workspace and switches between workspaces (#330), from SidebarNav's header.
|
|
43
|
+
* Built on Menu: a labelled group of the workspaces as radio items, then any actions.
|
|
44
|
+
*/])), color.text.muted);
|
|
45
|
+
/**
|
|
46
|
+
* Shows the current workspace and switches between workspaces (#330), from SidebarNav's header.
|
|
47
|
+
* Built on Menu: a labelled group of the workspaces as radio items, then any actions.
|
|
48
|
+
*/
|
|
49
|
+
var WorkspaceSwitcher = function WorkspaceSwitcher(_a) {
|
|
50
|
+
var workspaces = _a.workspaces,
|
|
51
|
+
value = _a.value,
|
|
52
|
+
onChange = _a.onChange,
|
|
53
|
+
_b = _a.label,
|
|
54
|
+
label = _b === void 0 ? 'Workspaces' : _b,
|
|
55
|
+
children = _a.children,
|
|
56
|
+
dataTestId = _a["data-testid"];
|
|
57
|
+
var collapsed = useSidebarNav().collapsed;
|
|
58
|
+
var match = workspaces.find(function (workspace) {
|
|
59
|
+
return workspace.id === value;
|
|
60
|
+
});
|
|
61
|
+
var fallback = !match && workspaces.length > 0 ? workspaces[0].name : undefined;
|
|
62
|
+
// Showing the first keeps the header usable, but the app's value is wrong, so say so, once per value
|
|
63
|
+
useEffect(function () {
|
|
64
|
+
if (fallback) console.warn("WorkspaceSwitcher: no workspace has the id \"".concat(value, "\"; showing \"").concat(fallback, "\""));
|
|
65
|
+
}, [value, fallback]);
|
|
66
|
+
var current = match !== null && match !== void 0 ? match : workspaces[0];
|
|
67
|
+
if (!current) return null;
|
|
68
|
+
var trigger = jsxs(Trigger, {
|
|
69
|
+
type: "button",
|
|
70
|
+
"$collapsed": collapsed,
|
|
71
|
+
"aria-label": collapsed ? current.name : undefined,
|
|
72
|
+
"data-testid": dataTestId,
|
|
73
|
+
children: [jsx(Decoration, {
|
|
74
|
+
"aria-hidden": "true",
|
|
75
|
+
children: jsx(Avatar, {
|
|
76
|
+
name: current.name,
|
|
77
|
+
picture: current.picture,
|
|
78
|
+
size: "xs"
|
|
79
|
+
})
|
|
80
|
+
}), !collapsed && jsxs(Fragment, {
|
|
81
|
+
children: [jsx(Name, {
|
|
82
|
+
children: current.name
|
|
83
|
+
}), jsx(Decoration, {
|
|
84
|
+
"aria-hidden": "true",
|
|
85
|
+
children: jsx(Icon, {
|
|
86
|
+
name: "caretDown",
|
|
87
|
+
size: "sm",
|
|
88
|
+
iconColor: "inherit"
|
|
89
|
+
})
|
|
90
|
+
})]
|
|
91
|
+
})]
|
|
92
|
+
});
|
|
93
|
+
return jsxs(Menu, {
|
|
94
|
+
trigger: collapsed ? jsx(Tooltip, {
|
|
95
|
+
text: current.name,
|
|
96
|
+
side: "right",
|
|
97
|
+
children: trigger
|
|
98
|
+
}) : trigger,
|
|
99
|
+
side: collapsed ? 'right' : 'bottom',
|
|
100
|
+
align: "start",
|
|
101
|
+
children: [jsx(MenuGroup, {
|
|
102
|
+
label: label,
|
|
103
|
+
children: workspaces.map(function (workspace) {
|
|
104
|
+
return jsx(MenuItemRadio, {
|
|
105
|
+
checked: workspace.id === current.id,
|
|
106
|
+
// Choosing the current workspace again changes nothing
|
|
107
|
+
onSelect: function onSelect() {
|
|
108
|
+
return workspace.id !== current.id && onChange(workspace.id);
|
|
109
|
+
},
|
|
110
|
+
icon: jsx(Avatar, {
|
|
111
|
+
name: workspace.name,
|
|
112
|
+
picture: workspace.picture,
|
|
113
|
+
size: "xs"
|
|
114
|
+
}),
|
|
115
|
+
description: workspace.description,
|
|
116
|
+
textValue: workspace.name,
|
|
117
|
+
children: workspace.name
|
|
118
|
+
}, workspace.id);
|
|
119
|
+
})
|
|
120
|
+
}), children && jsxs(Fragment, {
|
|
121
|
+
children: [jsx(MenuDivider, {}), jsx(MenuGroup, {
|
|
122
|
+
children: children
|
|
123
|
+
})]
|
|
124
|
+
})]
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
WorkspaceSwitcher.displayName = 'WorkspaceSwitcher';
|
|
128
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4;
|
|
129
|
+
|
|
130
|
+
export { WorkspaceSwitcher };
|
|
131
|
+
//# sourceMappingURL=WorkspaceSwitcher.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkspaceSwitcher.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -14,6 +14,9 @@ export * from './EmptyState/index.mjs';
|
|
|
14
14
|
export * from './FeatureBlock/index.mjs';
|
|
15
15
|
export * from './Dropdown/index.mjs';
|
|
16
16
|
export * from './List/index.mjs';
|
|
17
|
+
export * from './Menu/index.mjs';
|
|
18
|
+
export * from './SidebarNavItem/index.mjs';
|
|
19
|
+
export * from './SidebarNavSection/index.mjs';
|
|
17
20
|
export * from './Modal/index.mjs';
|
|
18
21
|
export * from './NumberInput/index.mjs';
|
|
19
22
|
export * from './PasswordField/index.mjs';
|
|
@@ -23,3 +26,4 @@ export * from './Slider/index.mjs';
|
|
|
23
26
|
export * from './TabBar/index.mjs';
|
|
24
27
|
export * from './TextField/index.mjs';
|
|
25
28
|
export * from './TransactionListItem/index.mjs';
|
|
29
|
+
export * from './WorkspaceSwitcher/index.mjs';
|
|
@@ -14,6 +14,9 @@ export * from './EmptyState';
|
|
|
14
14
|
export * from './FeatureBlock';
|
|
15
15
|
export * from './Dropdown';
|
|
16
16
|
export * from './List';
|
|
17
|
+
export * from './Menu';
|
|
18
|
+
export * from './SidebarNavItem';
|
|
19
|
+
export * from './SidebarNavSection';
|
|
17
20
|
export * from './Modal';
|
|
18
21
|
export * from './NumberInput';
|
|
19
22
|
export * from './PasswordField';
|
|
@@ -23,3 +26,4 @@ export * from './Slider';
|
|
|
23
26
|
export * from './TabBar';
|
|
24
27
|
export * from './TextField';
|
|
25
28
|
export * from './TransactionListItem';
|
|
29
|
+
export * from './WorkspaceSwitcher';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type SidebarNavContextValue } from '../../molecules/SidebarNavItem/SidebarNavContext.mjs';
|
|
3
|
+
export type SidebarNavWidth = 'narrow' | 'default' | 'wide';
|
|
4
|
+
export interface SidebarNavProps {
|
|
5
|
+
/** Names the navigation landmark, such as "Main" or "Workspace" */
|
|
6
|
+
label: string;
|
|
7
|
+
/**
|
|
8
|
+
* The body: SidebarNavItems and SidebarNavSections, in order, wrapped in components or Fragments
|
|
9
|
+
* if you like. It's one list, and scrolls when it's too tall.
|
|
10
|
+
*/
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
/** Content above the body, such as a WorkspaceSwitcher. The collapse toggle sits beside it. */
|
|
13
|
+
header?: React.ReactNode;
|
|
14
|
+
/** Content below the body, such as an upgrade prompt. Hidden in the rail. */
|
|
15
|
+
footer?: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* The expanded width. Collapsed, it's always the rail.
|
|
18
|
+
* @default 'default'
|
|
19
|
+
*/
|
|
20
|
+
width?: SidebarNavWidth;
|
|
21
|
+
/** Whether it's the icon rail (controlled). Use with `onCollapsedChange`. */
|
|
22
|
+
collapsed?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Whether it starts as the rail (uncontrolled). Saving the state between visits is the
|
|
25
|
+
* product's job.
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
defaultCollapsed?: boolean;
|
|
29
|
+
/** Called when the toggle collapses or expands it */
|
|
30
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Whether it has a collapse toggle. Turn it off where it can't collapse, such as inside a Sheet.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
collapsible?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* A router's link component for internal URLs, such as Next's `Link`, used by every item
|
|
38
|
+
* (decision 0008). Without one, items render plain links.
|
|
39
|
+
*/
|
|
40
|
+
linkComponent?: SidebarNavContextValue['linkComponent'];
|
|
41
|
+
/** Test identifier for the nav */
|
|
42
|
+
'data-testid'?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A product's sidebar navigation (#331): a header, a scrolling body of items and sections, and a
|
|
46
|
+
* footer, that collapses to an icon rail. Row heights follow density (0051); the width is a prop.
|
|
47
|
+
* On small screens, place it in a Sheet with `collapsible={false}`.
|
|
48
|
+
*/
|
|
49
|
+
export declare const SidebarNav: {
|
|
50
|
+
({ label, children, header, footer, width, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, collapsible, linkComponent, "data-testid": dataTestId, }: SidebarNavProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
displayName: string;
|
|
52
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type SidebarNavContextValue } from '../../molecules/SidebarNavItem/SidebarNavContext';
|
|
3
|
+
export type SidebarNavWidth = 'narrow' | 'default' | 'wide';
|
|
4
|
+
export interface SidebarNavProps {
|
|
5
|
+
/** Names the navigation landmark, such as "Main" or "Workspace" */
|
|
6
|
+
label: string;
|
|
7
|
+
/**
|
|
8
|
+
* The body: SidebarNavItems and SidebarNavSections, in order, wrapped in components or Fragments
|
|
9
|
+
* if you like. It's one list, and scrolls when it's too tall.
|
|
10
|
+
*/
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
/** Content above the body, such as a WorkspaceSwitcher. The collapse toggle sits beside it. */
|
|
13
|
+
header?: React.ReactNode;
|
|
14
|
+
/** Content below the body, such as an upgrade prompt. Hidden in the rail. */
|
|
15
|
+
footer?: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* The expanded width. Collapsed, it's always the rail.
|
|
18
|
+
* @default 'default'
|
|
19
|
+
*/
|
|
20
|
+
width?: SidebarNavWidth;
|
|
21
|
+
/** Whether it's the icon rail (controlled). Use with `onCollapsedChange`. */
|
|
22
|
+
collapsed?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Whether it starts as the rail (uncontrolled). Saving the state between visits is the
|
|
25
|
+
* product's job.
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
defaultCollapsed?: boolean;
|
|
29
|
+
/** Called when the toggle collapses or expands it */
|
|
30
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Whether it has a collapse toggle. Turn it off where it can't collapse, such as inside a Sheet.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
collapsible?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* A router's link component for internal URLs, such as Next's `Link`, used by every item
|
|
38
|
+
* (decision 0008). Without one, items render plain links.
|
|
39
|
+
*/
|
|
40
|
+
linkComponent?: SidebarNavContextValue['linkComponent'];
|
|
41
|
+
/** Test identifier for the nav */
|
|
42
|
+
'data-testid'?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A product's sidebar navigation (#331): a header, a scrolling body of items and sections, and a
|
|
46
|
+
* footer, that collapses to an icon rail. Row heights follow density (0051); the width is a prop.
|
|
47
|
+
* On small screens, place it in a Sheet with `collapsible={false}`.
|
|
48
|
+
*/
|
|
49
|
+
export declare const SidebarNav: {
|
|
50
|
+
({ label, children, header, footer, width, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, collapsible, linkComponent, "data-testid": dataTestId, }: SidebarNavProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
displayName: string;
|
|
52
|
+
};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { __makeTemplateObject, __assign } from '../../../vendor/tslib/tslib.es6.mjs';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import { useState, useRef } from 'react';
|
|
5
|
+
import styled$module, { css } from 'styled-components';
|
|
6
|
+
const styled = styled$module.default || styled$module;
|
|
7
|
+
import tokens from '../../../lib/cssTokens.mjs';
|
|
8
|
+
import { reducedMotion, forcedColors } from '../../../lib/styleUtils.mjs';
|
|
9
|
+
import { IconButton } from '../../atoms/IconButton/IconButton.mjs';
|
|
10
|
+
import { Tooltip } from '../../atoms/Tooltip/Tooltip.mjs';
|
|
11
|
+
import { isKeyboardFocus } from '../../../lib/keyboardFocus.mjs';
|
|
12
|
+
import { SidebarNavContext } from '../../molecules/SidebarNavItem/SidebarNavContext.mjs';
|
|
13
|
+
|
|
14
|
+
var semantic = tokens.semantic,
|
|
15
|
+
component = tokens.component;
|
|
16
|
+
var space = semantic.space,
|
|
17
|
+
motion = semantic.motion,
|
|
18
|
+
radius = semantic.radius,
|
|
19
|
+
border = semantic.border,
|
|
20
|
+
color = semantic.color;
|
|
21
|
+
var widths = component.sidebarNav.width;
|
|
22
|
+
var Nav = /*#__PURE__*/styled.nav.withConfig({
|
|
23
|
+
shouldForwardProp: function shouldForwardProp(prop) {
|
|
24
|
+
return !prop.startsWith('$');
|
|
25
|
+
},
|
|
26
|
+
displayName: "SidebarNav__Nav",
|
|
27
|
+
componentId: "sc-1as46tp-0"
|
|
28
|
+
})(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n gap: ", ";\n box-sizing: border-box;\n /* Its width is set; in a flex app shell it mustn't shrink to make room */\n flex-shrink: 0;\n width: ", ";\n height: 100%;\n padding: ", ";\n overflow: hidden;\n /* Quiet chrome (P1): the page's own background, with a thin edge */\n border-right: ", ";\n transition: width ", " ", ";\n\n ", " {\n transition: none;\n }\n"], ["\n display: flex;\n flex-direction: column;\n gap: ", ";\n box-sizing: border-box;\n /* Its width is set; in a flex app shell it mustn't shrink to make room */\n flex-shrink: 0;\n width: ", ";\n height: 100%;\n padding: ", ";\n overflow: hidden;\n /* Quiet chrome (P1): the page's own background, with a thin edge */\n border-right: ", ";\n transition: width ", " ", ";\n\n ", " {\n transition: none;\n }\n"])), space[200], function (_a) {
|
|
29
|
+
var $width = _a.$width;
|
|
30
|
+
return $width;
|
|
31
|
+
}, space[200], border["default"], motion.duration.moderate, motion.easing.standard, reducedMotion);
|
|
32
|
+
var Header = /*#__PURE__*/styled.div.withConfig({
|
|
33
|
+
shouldForwardProp: function shouldForwardProp(prop) {
|
|
34
|
+
return !prop.startsWith('$');
|
|
35
|
+
},
|
|
36
|
+
displayName: "SidebarNav__Header",
|
|
37
|
+
componentId: "sc-1as46tp-1"
|
|
38
|
+
})(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: ", ";\n\n ", "\n"], ["\n display: flex;\n align-items: center;\n gap: ", ";\n\n ", "\n"])), space[100], function (_a) {
|
|
39
|
+
var $collapsed = _a.$collapsed;
|
|
40
|
+
return $collapsed && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n flex-direction: column;\n "], ["\n flex-direction: column;\n "])));
|
|
41
|
+
});
|
|
42
|
+
var HeaderContent = /*#__PURE__*/styled.div.withConfig({
|
|
43
|
+
displayName: "SidebarNav__HeaderContent",
|
|
44
|
+
componentId: "sc-1as46tp-2"
|
|
45
|
+
})(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n flex: 1;\n min-width: 0;\n width: 100%;\n"], ["\n flex: 1;\n min-width: 0;\n width: 100%;\n"])));
|
|
46
|
+
var Body = /*#__PURE__*/styled.div.withConfig({
|
|
47
|
+
displayName: "SidebarNav__Body",
|
|
48
|
+
componentId: "sc-1as46tp-3"
|
|
49
|
+
})(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n flex: 1;\n min-height: 0;\n overflow-x: hidden;\n overflow-y: auto;\n"], ["\n flex: 1;\n min-height: 0;\n overflow-x: hidden;\n overflow-y: auto;\n"
|
|
50
|
+
// The rows and the highlight share this box, so the highlight scrolls with the rows
|
|
51
|
+
])));
|
|
52
|
+
// The rows and the highlight share this box, so the highlight scrolls with the rows
|
|
53
|
+
var Content = /*#__PURE__*/styled.div.withConfig({
|
|
54
|
+
displayName: "SidebarNav__Content",
|
|
55
|
+
componentId: "sc-1as46tp-4"
|
|
56
|
+
})(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n & [data-sidebar-row] {\n position: relative;\n z-index: 1;\n }\n"], ["\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n & [data-sidebar-row] {\n position: relative;\n z-index: 1;\n }\n"])));
|
|
57
|
+
var List = /*#__PURE__*/styled.ul.withConfig({
|
|
58
|
+
displayName: "SidebarNav__List",
|
|
59
|
+
componentId: "sc-1as46tp-5"
|
|
60
|
+
})(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n"], ["\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n"])));
|
|
61
|
+
// One highlight glides to the hovered or keyboard-focused row (0053): the row hover colour,
|
|
62
|
+
// moving over duration.fast. It jumps under reduced motion and hides in forced colours, where
|
|
63
|
+
// rows outline themselves instead.
|
|
64
|
+
var Highlight = /*#__PURE__*/styled.div.withConfig({
|
|
65
|
+
shouldForwardProp: function shouldForwardProp(prop) {
|
|
66
|
+
return !prop.startsWith('$');
|
|
67
|
+
},
|
|
68
|
+
displayName: "SidebarNav__Highlight",
|
|
69
|
+
componentId: "sc-1as46tp-6"
|
|
70
|
+
})(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n z-index: 0;\n border-radius: ", ";\n background-color: ", ";\n pointer-events: none;\n opacity: ", ";\n transition: ", ";\n\n ", " {\n transition: opacity ", " ", ";\n }\n\n ", " {\n display: none;\n }\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n z-index: 0;\n border-radius: ", ";\n background-color: ", ";\n pointer-events: none;\n opacity: ", ";\n transition: ", ";\n\n ", " {\n transition: opacity ", " ", ";\n }\n\n ", " {\n display: none;\n }\n"])), radius.sm, color.fill.muted, function (_a) {
|
|
71
|
+
var $visible = _a.$visible;
|
|
72
|
+
return $visible ? 1 : 0;
|
|
73
|
+
}, function (_a) {
|
|
74
|
+
var $instant = _a.$instant;
|
|
75
|
+
return $instant ? "opacity ".concat(motion.duration.fast, " ").concat(motion.easing.decelerate) : "transform ".concat(motion.duration.fast, " ").concat(motion.easing.decelerate, ",\n height ").concat(motion.duration.fast, " ").concat(motion.easing.decelerate, ",\n width ").concat(motion.duration.fast, " ").concat(motion.easing.decelerate, ",\n opacity ").concat(motion.duration.fast, " ").concat(motion.easing.decelerate);
|
|
76
|
+
}, reducedMotion, motion.duration.fast, motion.easing.decelerate, forcedColors);
|
|
77
|
+
var Footer = /*#__PURE__*/styled.div.withConfig({
|
|
78
|
+
displayName: "SidebarNav__Footer",
|
|
79
|
+
componentId: "sc-1as46tp-7"
|
|
80
|
+
})(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n flex-shrink: 0;\n"], ["\n flex-shrink: 0;\n"
|
|
81
|
+
/**
|
|
82
|
+
* A product's sidebar navigation (#331): a header, a scrolling body of items and sections, and a
|
|
83
|
+
* footer, that collapses to an icon rail. Row heights follow density (0051); the width is a prop.
|
|
84
|
+
* On small screens, place it in a Sheet with `collapsible={false}`.
|
|
85
|
+
*/])));
|
|
86
|
+
/**
|
|
87
|
+
* A product's sidebar navigation (#331): a header, a scrolling body of items and sections, and a
|
|
88
|
+
* footer, that collapses to an icon rail. Row heights follow density (0051); the width is a prop.
|
|
89
|
+
* On small screens, place it in a Sheet with `collapsible={false}`.
|
|
90
|
+
*/
|
|
91
|
+
var SidebarNav = function SidebarNav(_a) {
|
|
92
|
+
var label = _a.label,
|
|
93
|
+
children = _a.children,
|
|
94
|
+
header = _a.header,
|
|
95
|
+
footer = _a.footer,
|
|
96
|
+
_b = _a.width,
|
|
97
|
+
width = _b === void 0 ? 'default' : _b,
|
|
98
|
+
collapsedProp = _a.collapsed,
|
|
99
|
+
_c = _a.defaultCollapsed,
|
|
100
|
+
defaultCollapsed = _c === void 0 ? false : _c,
|
|
101
|
+
onCollapsedChange = _a.onCollapsedChange,
|
|
102
|
+
_d = _a.collapsible,
|
|
103
|
+
collapsible = _d === void 0 ? true : _d,
|
|
104
|
+
linkComponent = _a.linkComponent,
|
|
105
|
+
dataTestId = _a["data-testid"];
|
|
106
|
+
var _e = useState(defaultCollapsed),
|
|
107
|
+
uncontrolledCollapsed = _e[0],
|
|
108
|
+
setUncontrolledCollapsed = _e[1];
|
|
109
|
+
var isControlled = collapsedProp !== undefined;
|
|
110
|
+
var collapsed = collapsible && (isControlled ? collapsedProp : uncontrolledCollapsed);
|
|
111
|
+
var contentRef = useRef(null);
|
|
112
|
+
var _f = useState({
|
|
113
|
+
box: null,
|
|
114
|
+
visible: false,
|
|
115
|
+
instant: true
|
|
116
|
+
}),
|
|
117
|
+
highlight = _f[0],
|
|
118
|
+
setHighlight = _f[1];
|
|
119
|
+
var toggle = function toggle() {
|
|
120
|
+
var next = !collapsed;
|
|
121
|
+
if (!isControlled) setUncontrolledCollapsed(next);
|
|
122
|
+
onCollapsedChange === null || onCollapsedChange === void 0 ? void 0 : onCollapsedChange(next);
|
|
123
|
+
};
|
|
124
|
+
var hide = function hide() {
|
|
125
|
+
return setHighlight(function (state) {
|
|
126
|
+
return __assign(__assign({}, state), {
|
|
127
|
+
visible: false
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
// Collapsing or expanding moves every row, so the highlight's box is stale: hide it until the
|
|
132
|
+
// pointer or focus finds a row again (adjusted during render, React's pattern for a prop change)
|
|
133
|
+
var _g = useState(collapsed),
|
|
134
|
+
layout = _g[0],
|
|
135
|
+
setLayout = _g[1];
|
|
136
|
+
if (layout !== collapsed) {
|
|
137
|
+
setLayout(collapsed);
|
|
138
|
+
setHighlight(function (state) {
|
|
139
|
+
return __assign(__assign({}, state), {
|
|
140
|
+
visible: false,
|
|
141
|
+
instant: true
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// Move the highlight to a row, or step aside for the current page's row, which has its own fill
|
|
146
|
+
var highlightRow = function highlightRow(target) {
|
|
147
|
+
var content = contentRef.current;
|
|
148
|
+
var row = target instanceof Element ? target.closest('[data-sidebar-row]') : null;
|
|
149
|
+
if (!content || !row || !content.contains(row) || row.getAttribute('aria-current') === 'page') return hide();
|
|
150
|
+
var outer = content.getBoundingClientRect();
|
|
151
|
+
var box = row.getBoundingClientRect();
|
|
152
|
+
setHighlight(function (state) {
|
|
153
|
+
return {
|
|
154
|
+
box: {
|
|
155
|
+
top: box.top - outer.top,
|
|
156
|
+
left: box.left - outer.left,
|
|
157
|
+
width: box.width,
|
|
158
|
+
height: box.height
|
|
159
|
+
},
|
|
160
|
+
visible: true,
|
|
161
|
+
// Appearing, it starts at the row rather than sliding from where it last was
|
|
162
|
+
instant: !state.visible
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
var context = {
|
|
167
|
+
collapsed: collapsed,
|
|
168
|
+
linkComponent: linkComponent,
|
|
169
|
+
glide: true,
|
|
170
|
+
inNav: true
|
|
171
|
+
};
|
|
172
|
+
var toggleLabel = collapsed ? 'Expand sidebar' : 'Collapse sidebar';
|
|
173
|
+
var toggleButton = collapsible && jsx(Tooltip, {
|
|
174
|
+
text: toggleLabel,
|
|
175
|
+
side: collapsed ? 'right' : 'bottom',
|
|
176
|
+
children: jsx(IconButton, {
|
|
177
|
+
variant: "naked",
|
|
178
|
+
size: "small",
|
|
179
|
+
iconName: "sidebar",
|
|
180
|
+
"aria-label": toggleLabel,
|
|
181
|
+
"aria-expanded": !collapsed,
|
|
182
|
+
onClick: toggle
|
|
183
|
+
})
|
|
184
|
+
});
|
|
185
|
+
return jsx(SidebarNavContext.Provider, {
|
|
186
|
+
value: context,
|
|
187
|
+
children: jsxs(Nav, {
|
|
188
|
+
"aria-label": label,
|
|
189
|
+
"$width": collapsed ? widths.rail : widths[width],
|
|
190
|
+
"data-collapsed": collapsed || undefined,
|
|
191
|
+
"data-testid": dataTestId,
|
|
192
|
+
children: [(header || toggleButton) && jsxs(Header, {
|
|
193
|
+
"$collapsed": collapsed,
|
|
194
|
+
children: [header && jsx(HeaderContent, {
|
|
195
|
+
children: header
|
|
196
|
+
}), toggleButton]
|
|
197
|
+
}), jsx(Body, {
|
|
198
|
+
children: jsxs(Content, {
|
|
199
|
+
ref: contentRef,
|
|
200
|
+
onPointerOver: function onPointerOver(event) {
|
|
201
|
+
return event.pointerType !== 'touch' && highlightRow(event.target);
|
|
202
|
+
},
|
|
203
|
+
onPointerLeave: hide,
|
|
204
|
+
onFocus: function onFocus(event) {
|
|
205
|
+
return isKeyboardFocus(event.target) && highlightRow(event.target);
|
|
206
|
+
},
|
|
207
|
+
onBlur: function onBlur(event) {
|
|
208
|
+
var _a;
|
|
209
|
+
if (!((_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.relatedTarget))) hide();
|
|
210
|
+
},
|
|
211
|
+
children: [jsx(Highlight, {
|
|
212
|
+
"aria-hidden": "true",
|
|
213
|
+
"data-sidebar-highlight": "",
|
|
214
|
+
"$visible": highlight.visible,
|
|
215
|
+
"$instant": highlight.instant,
|
|
216
|
+
style: highlight.box ? {
|
|
217
|
+
transform: "translate(".concat(highlight.box.left, "px, ").concat(highlight.box.top, "px)"),
|
|
218
|
+
width: highlight.box.width,
|
|
219
|
+
height: highlight.box.height
|
|
220
|
+
} : undefined
|
|
221
|
+
}), jsx(List, {
|
|
222
|
+
children: children
|
|
223
|
+
})]
|
|
224
|
+
})
|
|
225
|
+
}), footer && !collapsed && jsx(Footer, {
|
|
226
|
+
children: footer
|
|
227
|
+
})]
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
SidebarNav.displayName = 'SidebarNav';
|
|
232
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9;
|
|
233
|
+
|
|
234
|
+
export { SidebarNav };
|
|
235
|
+
//# sourceMappingURL=SidebarNav.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SidebarNav.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SidebarNav/index.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SidebarNav';
|