@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.
Files changed (97) hide show
  1. package/dist/client.js +2175 -687
  2. package/dist/client.js.map +1 -1
  3. package/dist/components/atoms/Tooltip/Tooltip.d.mts +41 -0
  4. package/dist/components/atoms/Tooltip/Tooltip.d.ts +41 -0
  5. package/dist/components/atoms/Tooltip/Tooltip.mjs +204 -0
  6. package/dist/components/atoms/Tooltip/Tooltip.mjs.map +1 -0
  7. package/dist/components/atoms/Tooltip/index.d.mts +2 -0
  8. package/dist/components/atoms/Tooltip/index.d.ts +2 -0
  9. package/dist/components/atoms/index.d.mts +1 -0
  10. package/dist/components/atoms/index.d.ts +1 -0
  11. package/dist/components/index.d.mts +1 -0
  12. package/dist/components/index.d.ts +1 -0
  13. package/dist/components/molecules/ActionSheet/ActionSheet.mjs +1 -0
  14. package/dist/components/molecules/Alert/Alert.mjs +1 -1
  15. package/dist/components/molecules/ChipGroup/ChipGroup.mjs +1 -0
  16. package/dist/components/molecules/List/List.d.mts +2 -0
  17. package/dist/components/molecules/List/List.d.ts +2 -0
  18. package/dist/components/molecules/List/ListItem.d.mts +2 -0
  19. package/dist/components/molecules/List/ListItem.d.ts +2 -0
  20. package/dist/components/molecules/List/ListItem.mjs +5 -5
  21. package/dist/components/molecules/Menu/Menu.d.mts +117 -0
  22. package/dist/components/molecules/Menu/Menu.d.ts +117 -0
  23. package/dist/components/molecules/Menu/Menu.mjs +473 -0
  24. package/dist/components/molecules/Menu/Menu.mjs.map +1 -0
  25. package/dist/components/molecules/Menu/index.d.mts +2 -0
  26. package/dist/components/molecules/Menu/index.d.ts +2 -0
  27. package/dist/components/molecules/SearchField/SearchField.mjs +2 -0
  28. package/dist/components/molecules/SidebarNavItem/SidebarNavContext.d.mts +13 -0
  29. package/dist/components/molecules/SidebarNavItem/SidebarNavContext.d.ts +13 -0
  30. package/dist/components/molecules/SidebarNavItem/SidebarNavContext.mjs +13 -0
  31. package/dist/components/molecules/SidebarNavItem/SidebarNavContext.mjs.map +1 -0
  32. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.d.mts +43 -0
  33. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.d.ts +43 -0
  34. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.mjs +148 -0
  35. package/dist/components/molecules/SidebarNavItem/SidebarNavItem.mjs.map +1 -0
  36. package/dist/components/molecules/SidebarNavItem/index.d.mts +2 -0
  37. package/dist/components/molecules/SidebarNavItem/index.d.ts +2 -0
  38. package/dist/components/molecules/SidebarNavSection/SidebarNavSection.d.mts +36 -0
  39. package/dist/components/molecules/SidebarNavSection/SidebarNavSection.d.ts +36 -0
  40. package/dist/components/molecules/SidebarNavSection/SidebarNavSection.mjs +188 -0
  41. package/dist/components/molecules/SidebarNavSection/SidebarNavSection.mjs.map +1 -0
  42. package/dist/components/molecules/SidebarNavSection/index.d.mts +2 -0
  43. package/dist/components/molecules/SidebarNavSection/index.d.ts +2 -0
  44. package/dist/components/molecules/TransactionListItem/TransactionListItem.mjs +1 -1
  45. package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.d.mts +39 -0
  46. package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.d.ts +39 -0
  47. package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.mjs +131 -0
  48. package/dist/components/molecules/WorkspaceSwitcher/WorkspaceSwitcher.mjs.map +1 -0
  49. package/dist/components/molecules/WorkspaceSwitcher/index.d.mts +2 -0
  50. package/dist/components/molecules/WorkspaceSwitcher/index.d.ts +2 -0
  51. package/dist/components/molecules/index.d.mts +4 -0
  52. package/dist/components/molecules/index.d.ts +4 -0
  53. package/dist/components/organisms/SidebarNav/SidebarNav.d.mts +52 -0
  54. package/dist/components/organisms/SidebarNav/SidebarNav.d.ts +52 -0
  55. package/dist/components/organisms/SidebarNav/SidebarNav.mjs +235 -0
  56. package/dist/components/organisms/SidebarNav/SidebarNav.mjs.map +1 -0
  57. package/dist/components/organisms/SidebarNav/index.d.mts +2 -0
  58. package/dist/components/organisms/SidebarNav/index.d.ts +2 -0
  59. package/dist/components/organisms/index.d.mts +1 -0
  60. package/dist/components/organisms/index.d.ts +1 -0
  61. package/dist/data.js +59 -9
  62. package/dist/data.js.map +1 -1
  63. package/dist/index.js +11 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +6 -0
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/lib/floatingPosition.d.mts +43 -0
  68. package/dist/lib/floatingPosition.d.ts +43 -0
  69. package/dist/lib/floatingPosition.mjs +86 -0
  70. package/dist/lib/floatingPosition.mjs.map +1 -0
  71. package/dist/lib/keyboardFocus.d.mts +6 -0
  72. package/dist/lib/keyboardFocus.d.ts +6 -0
  73. package/dist/lib/keyboardFocus.mjs +17 -0
  74. package/dist/lib/keyboardFocus.mjs.map +1 -0
  75. package/dist/lib/useFloatingLayer.d.mts +25 -0
  76. package/dist/lib/useFloatingLayer.d.ts +25 -0
  77. package/dist/lib/useFloatingLayer.mjs +86 -0
  78. package/dist/lib/useFloatingLayer.mjs.map +1 -0
  79. package/dist/styles/icons.json +30 -1
  80. package/dist/styles/icons.json.mjs +34 -3
  81. package/dist/styles/icons.json.mjs.map +1 -1
  82. package/dist/styles/tokens.d.mts +46 -8
  83. package/dist/styles/tokens.d.ts +46 -8
  84. package/dist/styles/tokens.json +26 -7
  85. package/dist/styles/tokens.json.mjs +26 -7
  86. package/dist/styles/tokens.json.mjs.map +1 -1
  87. package/dist/tokens/index.js +26 -7
  88. package/dist/tokens/index.js.map +1 -1
  89. package/dist/tokens/index.mjs +26 -7
  90. package/dist/tokens/index.mjs.map +1 -1
  91. package/dist/tokens/styles/tokens.d.mts +46 -8
  92. package/dist/tokens/styles/tokens.d.ts +46 -8
  93. package/dist/tokens.css +35 -15
  94. package/dist/types/icons.d.mts +1 -1
  95. package/dist/types/icons.d.ts +1 -1
  96. package/dist/types/icons.mjs.map +1 -1
  97. 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":""}
@@ -0,0 +1,2 @@
1
+ export { WorkspaceSwitcher } from './WorkspaceSwitcher.mjs';
2
+ export type { WorkspaceSwitcherProps, Workspace } from './WorkspaceSwitcher.mjs';
@@ -0,0 +1,2 @@
1
+ export { WorkspaceSwitcher } from './WorkspaceSwitcher';
2
+ export type { WorkspaceSwitcherProps, Workspace } from './WorkspaceSwitcher';
@@ -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,2 @@
1
+ export { SidebarNav } from './SidebarNav.mjs';
2
+ export type { SidebarNavProps, SidebarNavWidth } from './SidebarNav.mjs';
@@ -0,0 +1,2 @@
1
+ export { SidebarNav } from './SidebarNav';
2
+ export type { SidebarNavProps, SidebarNavWidth } from './SidebarNav';
@@ -0,0 +1 @@
1
+ export * from './SidebarNav/index.mjs';
@@ -0,0 +1 @@
1
+ export * from './SidebarNav';