rift-ds 1.0.1 → 1.2.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/LICENSE +1 -1
- package/README.md +8 -2
- package/components/AppLayout/AppLayout.css +13 -3
- package/components/AppLayout/AppLayout.d.ts +5 -1
- package/components/AppLayout/AppLayout.js +4 -0
- package/components/AppSidebar/AppSidebar.css +237 -0
- package/components/AppSidebar/AppSidebar.d.ts +32 -3
- package/components/AppSidebar/AppSidebar.js +187 -16
- package/components/BottomNav/BottomNav.css +417 -0
- package/components/BottomNav/BottomNav.d.ts +73 -0
- package/components/BottomNav/BottomNav.js +100 -0
- package/components/Chart/AreaChart.js +67 -56
- package/components/Chart/BarChart.js +67 -56
- package/components/Chart/ComboChart.js +93 -82
- package/components/Chart/LineChart.js +59 -48
- package/components/Chart/PieChart.js +56 -45
- package/components/Chart/RadarChart.js +60 -49
- package/components/Chart/RadialChart.js +70 -59
- package/components/Chart/ScatterChart.js +61 -50
- package/components/Chart/StackedBarChart.js +64 -53
- package/components/Chart/Treemap.js +34 -23
- package/components/Inspector/Inspector.css +511 -0
- package/components/Inspector/InspectorDropdown.d.ts +39 -0
- package/components/Inspector/InspectorDropdown.js +68 -0
- package/components/Inspector/InspectorInput.d.ts +32 -0
- package/components/Inspector/InspectorInput.js +52 -0
- package/components/Inspector/InspectorSection.d.ts +32 -0
- package/components/Inspector/InspectorSection.js +70 -0
- package/components/Inspector/InspectorSegmentedControl.d.ts +46 -0
- package/components/Inspector/InspectorSegmentedControl.js +62 -0
- package/components/Inspector/InspectorSlider.d.ts +41 -0
- package/components/Inspector/InspectorSlider.js +81 -0
- package/components/Inspector/InspectorToggleSwitch.d.ts +29 -0
- package/components/Inspector/InspectorToggleSwitch.js +51 -0
- package/components/Nav/Nav.d.ts +11 -3
- package/components/Nav/Nav.js +3 -2
- package/components/SegmentedControl/SegmentedControl.css +7 -5
- package/components/SidebarPanel/SidebarPanel.css +291 -0
- package/components/SidebarPanel/SidebarPanel.d.ts +45 -0
- package/components/SidebarPanel/SidebarPanel.js +166 -0
- package/components/Stepper/Stepper.d.ts +3 -1
- package/components/Stepper/Stepper.js +1 -1
- package/components/TopAppBar/TopAppBar.css +464 -0
- package/components/TopAppBar/TopAppBar.d.ts +80 -0
- package/components/TopAppBar/TopAppBar.js +138 -0
- package/components/registry.json +84 -1
- package/components/registry.json.d.ts +84 -1
- package/components/registry.json.js +2 -2
- package/index.d.ts +9 -0
- package/index.js +18 -0
- package/package.json +5 -1
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
SIDEBAR PANEL — the secondary navigation column
|
|
3
|
+
A heading, optional group labels, flat rows and
|
|
4
|
+
one level of accordion nesting. Row geometry
|
|
5
|
+
repeats AppSidebar's sub-items (40px pill rows,
|
|
6
|
+
12px edge inset, tree-line connectors), so the
|
|
7
|
+
two columns read as one navigation system.
|
|
8
|
+
============================================ */
|
|
9
|
+
|
|
10
|
+
/* ============================================
|
|
11
|
+
WRAPPER
|
|
12
|
+
============================================ */
|
|
13
|
+
.ds-sidebar-panel {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: var(--gap-400);
|
|
17
|
+
width: var(--ds-sidebar-panel-width, 240px);
|
|
18
|
+
height: 100%;
|
|
19
|
+
min-height: 0;
|
|
20
|
+
padding: var(--padding-500) 0;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
background-color: var(--color-bg-page-primary);
|
|
23
|
+
color: var(--color-text-primary);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* ============================================
|
|
27
|
+
BACK ROW — the drill-in's way out
|
|
28
|
+
============================================ */
|
|
29
|
+
.ds-sidebar-panel__back {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
gap: var(--gap-100);
|
|
33
|
+
height: 40px;
|
|
34
|
+
margin: 0 var(--padding-300);
|
|
35
|
+
padding: var(--padding-200);
|
|
36
|
+
/* The chevron glyph carries its own side bearing, so the row drops its
|
|
37
|
+
left padding and the glyph's ink lands on the rows' text edge. */
|
|
38
|
+
padding-left: 0;
|
|
39
|
+
border: none;
|
|
40
|
+
border-radius: var(--radius-pill);
|
|
41
|
+
background: transparent;
|
|
42
|
+
color: var(--color-text-secondary);
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
text-align: left;
|
|
45
|
+
flex-shrink: 0;
|
|
46
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ds-sidebar-panel__back:hover {
|
|
50
|
+
background-color: var(--color-action-passive-bg-hover);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ds-sidebar-panel__back-icon {
|
|
54
|
+
--icon-size: var(--icon-size-600);
|
|
55
|
+
color: inherit;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ============================================
|
|
59
|
+
HEADER — title + collapse control
|
|
60
|
+
============================================ */
|
|
61
|
+
.ds-sidebar-panel__header {
|
|
62
|
+
display: flex;
|
|
63
|
+
justify-content: space-between;
|
|
64
|
+
align-items: flex-start;
|
|
65
|
+
gap: var(--gap-200);
|
|
66
|
+
min-height: 24px;
|
|
67
|
+
padding: 0 var(--padding-500);
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.ds-sidebar-panel__title {
|
|
72
|
+
margin: 0;
|
|
73
|
+
font-family: var(--font-overline-family);
|
|
74
|
+
font-size: var(--font-overline-size);
|
|
75
|
+
font-weight: var(--font-overline-weight);
|
|
76
|
+
line-height: var(--font-overline-line-height);
|
|
77
|
+
letter-spacing: var(--font-overline-letter-spacing);
|
|
78
|
+
text-transform: uppercase;
|
|
79
|
+
color: var(--color-text-secondary);
|
|
80
|
+
min-width: 0;
|
|
81
|
+
/* Wraps rather than truncates: the heading names the section, and a
|
|
82
|
+
clipped name is the one thing the reader cannot recover from. */
|
|
83
|
+
overflow-wrap: anywhere;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ds-sidebar-panel__collapse {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
justify-content: center;
|
|
90
|
+
width: 32px;
|
|
91
|
+
height: 32px;
|
|
92
|
+
/* Pulls the 32px hit area back so the 24px glyph sits on the same
|
|
93
|
+
right edge as the rows' badges and chevrons. */
|
|
94
|
+
margin-right: calc(var(--padding-100) * -1);
|
|
95
|
+
/* Centred on the heading's first line however many lines it wraps to. */
|
|
96
|
+
margin-top: calc((var(--font-overline-line-height) - 32px) / 2);
|
|
97
|
+
margin-bottom: calc((var(--font-overline-line-height) - 32px) / 2);
|
|
98
|
+
padding: 0;
|
|
99
|
+
flex-shrink: 0;
|
|
100
|
+
border: none;
|
|
101
|
+
border-radius: var(--radius-pill);
|
|
102
|
+
background: transparent;
|
|
103
|
+
color: var(--color-icon-primary);
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.ds-sidebar-panel__collapse:hover {
|
|
109
|
+
background-color: var(--color-action-passive-bg-hover);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.ds-sidebar-panel__collapse .material-symbols-rounded {
|
|
113
|
+
--icon-size: var(--icon-size-600);
|
|
114
|
+
color: inherit;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* ============================================
|
|
118
|
+
BODY + GROUPS
|
|
119
|
+
============================================ */
|
|
120
|
+
.ds-sidebar-panel__body {
|
|
121
|
+
display: flex;
|
|
122
|
+
flex-direction: column;
|
|
123
|
+
gap: var(--gap-500);
|
|
124
|
+
flex: 1;
|
|
125
|
+
min-height: 0;
|
|
126
|
+
overflow-y: auto;
|
|
127
|
+
overflow-x: hidden;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.ds-sidebar-panel__group {
|
|
131
|
+
display: flex;
|
|
132
|
+
flex-direction: column;
|
|
133
|
+
gap: var(--gap-100);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.ds-sidebar-panel__group-label {
|
|
137
|
+
padding: 0 var(--padding-500);
|
|
138
|
+
font-family: var(--font-paragraph-sm-family);
|
|
139
|
+
font-size: var(--font-paragraph-sm-size);
|
|
140
|
+
font-weight: var(--font-paragraph-sm-weight);
|
|
141
|
+
line-height: var(--font-paragraph-sm-line-height);
|
|
142
|
+
color: var(--color-text-tertiary);
|
|
143
|
+
white-space: nowrap;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.ds-sidebar-panel__list,
|
|
147
|
+
.ds-sidebar-panel__nested-list {
|
|
148
|
+
display: flex;
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
gap: var(--gap-100);
|
|
151
|
+
margin: 0;
|
|
152
|
+
padding: 0;
|
|
153
|
+
list-style: none;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* ============================================
|
|
157
|
+
ROWS
|
|
158
|
+
============================================ */
|
|
159
|
+
.ds-sidebar-panel__row {
|
|
160
|
+
display: flex;
|
|
161
|
+
align-items: center;
|
|
162
|
+
gap: var(--gap-200);
|
|
163
|
+
width: calc(100% - var(--padding-300) * 2);
|
|
164
|
+
height: 40px;
|
|
165
|
+
margin: 0 var(--padding-300);
|
|
166
|
+
padding: var(--padding-200);
|
|
167
|
+
box-sizing: border-box;
|
|
168
|
+
border: none;
|
|
169
|
+
border-radius: var(--radius-pill);
|
|
170
|
+
background: transparent;
|
|
171
|
+
color: var(--color-text-primary);
|
|
172
|
+
cursor: pointer;
|
|
173
|
+
text-align: left;
|
|
174
|
+
text-decoration: none;
|
|
175
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.ds-sidebar-panel__row:hover,
|
|
179
|
+
.ds-sidebar-panel__row--active {
|
|
180
|
+
background-color: var(--color-action-passive-bg-hover);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.ds-sidebar-panel__row:focus-visible,
|
|
184
|
+
.ds-sidebar-panel__back:focus-visible,
|
|
185
|
+
.ds-sidebar-panel__collapse:focus-visible {
|
|
186
|
+
outline: 2px solid var(--color-action-primary-bg);
|
|
187
|
+
outline-offset: -2px;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.ds-sidebar-panel__label {
|
|
191
|
+
flex: 1;
|
|
192
|
+
min-width: 0;
|
|
193
|
+
font-family: var(--font-paragraph-family);
|
|
194
|
+
font-size: var(--font-paragraph-size);
|
|
195
|
+
font-weight: var(--font-paragraph-weight);
|
|
196
|
+
line-height: var(--font-paragraph-line-height);
|
|
197
|
+
letter-spacing: var(--font-paragraph-letter-spacing);
|
|
198
|
+
color: inherit;
|
|
199
|
+
white-space: nowrap;
|
|
200
|
+
overflow: hidden;
|
|
201
|
+
text-overflow: ellipsis;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* The current page and a collapsed accordion hiding it carry the same
|
|
205
|
+
emphasis, so a reader can find their place without opening anything. */
|
|
206
|
+
.ds-sidebar-panel__row--active .ds-sidebar-panel__label,
|
|
207
|
+
.ds-sidebar-panel__row--holds-active .ds-sidebar-panel__label {
|
|
208
|
+
font-family: var(--font-paragraph-emphasis-family);
|
|
209
|
+
font-weight: var(--font-paragraph-emphasis-weight);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.ds-sidebar-panel__badge {
|
|
213
|
+
flex-shrink: 0;
|
|
214
|
+
font-family: var(--font-caption-family);
|
|
215
|
+
font-size: var(--font-caption-size);
|
|
216
|
+
font-weight: var(--font-paragraph-sm-emphasis-weight);
|
|
217
|
+
line-height: var(--font-caption-line-height);
|
|
218
|
+
color: var(--color-text-secondary);
|
|
219
|
+
background-color: var(--color-bg-container-tertiary);
|
|
220
|
+
border-radius: var(--radius-pill);
|
|
221
|
+
padding: var(--padding-050) var(--padding-200);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* On a filled row the pill steps back to the page ground, or it would
|
|
225
|
+
share the row's fill and dissolve into it. */
|
|
226
|
+
.ds-sidebar-panel__row--active .ds-sidebar-panel__badge,
|
|
227
|
+
.ds-sidebar-panel__row:hover .ds-sidebar-panel__badge {
|
|
228
|
+
background-color: var(--color-bg-page-primary);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.ds-sidebar-panel__chevron {
|
|
232
|
+
--icon-size: var(--icon-size-500);
|
|
233
|
+
flex-shrink: 0;
|
|
234
|
+
/* Pulls the glyph's side bearing out, so its ink ends on the same right
|
|
235
|
+
edge as a badge in the row above. */
|
|
236
|
+
margin-right: calc(var(--padding-100) * -1);
|
|
237
|
+
color: var(--color-icon-secondary);
|
|
238
|
+
transition: transform var(--motion-duration-slow) var(--motion-ease-emphasized);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.ds-sidebar-panel__chevron--open {
|
|
242
|
+
transform: rotate(180deg);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* ============================================
|
|
246
|
+
NESTED ROWS (accordion children)
|
|
247
|
+
The grid-row trick animates to the content's
|
|
248
|
+
own height, with no max-height guess to clip.
|
|
249
|
+
============================================ */
|
|
250
|
+
.ds-sidebar-panel__nested {
|
|
251
|
+
display: grid;
|
|
252
|
+
grid-template-rows: 0fr;
|
|
253
|
+
transition: grid-template-rows var(--motion-duration-slow) var(--motion-ease-emphasized);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.ds-sidebar-panel__nested--open {
|
|
257
|
+
grid-template-rows: 1fr;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.ds-sidebar-panel__nested-list {
|
|
261
|
+
min-height: 0;
|
|
262
|
+
overflow: hidden;
|
|
263
|
+
/* The tree line: aligned under the parent label's first letter, so the
|
|
264
|
+
children visibly hang from it (12px inset + 8px row padding). */
|
|
265
|
+
position: relative;
|
|
266
|
+
padding-top: var(--gap-100);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.ds-sidebar-panel__nested-list::before {
|
|
270
|
+
content: '';
|
|
271
|
+
position: absolute;
|
|
272
|
+
top: var(--gap-100);
|
|
273
|
+
bottom: 0;
|
|
274
|
+
left: calc(var(--padding-300) + var(--padding-200));
|
|
275
|
+
width: var(--border-025);
|
|
276
|
+
background-color: var(--color-bg-container-border);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.ds-sidebar-panel__row--nested {
|
|
280
|
+
width: calc(100% - var(--padding-300) * 2 - var(--padding-400));
|
|
281
|
+
margin-left: calc(var(--padding-300) + var(--padding-400));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Icons take the colour of the text around them, whatever a consumer
|
|
285
|
+
stylesheet sets on the icon font class globally. */
|
|
286
|
+
.ds-sidebar-panel .material-symbols-rounded {
|
|
287
|
+
color: inherit;
|
|
288
|
+
}
|
|
289
|
+
.ds-sidebar-panel .ds-sidebar-panel__chevron {
|
|
290
|
+
color: var(--color-icon-secondary);
|
|
291
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface SidebarPanelItem {
|
|
3
|
+
/** Unique key for this item */
|
|
4
|
+
key: string;
|
|
5
|
+
/** Display label */
|
|
6
|
+
label: string;
|
|
7
|
+
/** Renders the item as a real link to this URL instead of a button. Ignored when the item has children, whose row is the accordion toggle */
|
|
8
|
+
href?: string;
|
|
9
|
+
/** Click handler — also fires on a link item, so a consumer can route client-side */
|
|
10
|
+
onClick?: () => void;
|
|
11
|
+
/** Trailing count pill, e.g. unread items */
|
|
12
|
+
badge?: string | number;
|
|
13
|
+
/** Group heading this item sits under; consecutive items sharing a group render beneath one heading */
|
|
14
|
+
group?: string;
|
|
15
|
+
/** Nested items — turns this row into an accordion. One level deep: grandchildren are not rendered */
|
|
16
|
+
children?: SidebarPanelItem[];
|
|
17
|
+
}
|
|
18
|
+
type SidebarPanelOwnProps = {
|
|
19
|
+
/** Items to list, optionally grouped with `group` and nested one level with `children` */
|
|
20
|
+
items: SidebarPanelItem[];
|
|
21
|
+
/** Heading at the top of the panel, usually the label of the item that opened it. Also the panel's accessible name */
|
|
22
|
+
title?: string;
|
|
23
|
+
/** Key of the item for the current page. Its accordion parent starts open */
|
|
24
|
+
activeKey?: string;
|
|
25
|
+
/** Keys of the accordion rows open on first render, in addition to the active item's parent */
|
|
26
|
+
defaultOpenKeys?: string[];
|
|
27
|
+
/** Renders a collapse button beside the heading and calls this when it is pressed */
|
|
28
|
+
onCollapse?: () => void;
|
|
29
|
+
/** Renders a back row above the heading and calls this when it is pressed; the drill-in navigation on small screens */
|
|
30
|
+
onBack?: () => void;
|
|
31
|
+
/** Label of the back row */
|
|
32
|
+
backLabel?: string;
|
|
33
|
+
/** Additional CSS classes */
|
|
34
|
+
className?: string;
|
|
35
|
+
};
|
|
36
|
+
export interface SidebarPanelProps extends SidebarPanelOwnProps, Omit<React.ComponentPropsWithoutRef<'nav'>, keyof SidebarPanelOwnProps> {
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* SidebarPanel — the secondary column of app navigation. Lists the pages
|
|
40
|
+
* inside one section, with optional group headings and one level of
|
|
41
|
+
* accordion nesting. Stands alone, or opens beside `AppSidebar` when its
|
|
42
|
+
* items carry deeper levels (see `subNav` there).
|
|
43
|
+
*/
|
|
44
|
+
export declare const SidebarPanel: React.ForwardRefExoticComponent<SidebarPanelProps & React.RefAttributes<HTMLElement>>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { useId, useState, useCallback } from "react";
|
|
4
|
+
import "./SidebarPanel.css";
|
|
5
|
+
import "../../fonts/material-symbols.css";
|
|
6
|
+
function groupRuns(items) {
|
|
7
|
+
const runs = [];
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
const last = runs[runs.length - 1];
|
|
10
|
+
if (last && last.group === item.group) last.items.push(item);
|
|
11
|
+
else runs.push({ group: item.group, items: [item] });
|
|
12
|
+
}
|
|
13
|
+
return runs;
|
|
14
|
+
}
|
|
15
|
+
const SidebarPanel = React.forwardRef(
|
|
16
|
+
({
|
|
17
|
+
items,
|
|
18
|
+
title,
|
|
19
|
+
activeKey,
|
|
20
|
+
defaultOpenKeys,
|
|
21
|
+
onCollapse,
|
|
22
|
+
onBack,
|
|
23
|
+
backLabel = "Back",
|
|
24
|
+
className = "",
|
|
25
|
+
...rest
|
|
26
|
+
}, ref) => {
|
|
27
|
+
const baseClass = "ds-sidebar-panel";
|
|
28
|
+
const uid = useId();
|
|
29
|
+
const [openKeys, setOpenKeys] = useState(() => {
|
|
30
|
+
const initial = new Set(defaultOpenKeys ?? []);
|
|
31
|
+
if (activeKey) {
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
if (item.children?.some((child) => child.key === activeKey)) initial.add(item.key);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return initial;
|
|
37
|
+
});
|
|
38
|
+
const toggle = useCallback((key) => {
|
|
39
|
+
setOpenKeys((prev) => {
|
|
40
|
+
const next = new Set(prev);
|
|
41
|
+
if (next.has(key)) next.delete(key);
|
|
42
|
+
else next.add(key);
|
|
43
|
+
return next;
|
|
44
|
+
});
|
|
45
|
+
}, []);
|
|
46
|
+
const renderLeaf = (item, nested) => {
|
|
47
|
+
const isActive = item.key === activeKey;
|
|
48
|
+
const classes = [
|
|
49
|
+
`${baseClass}__row`,
|
|
50
|
+
nested ? `${baseClass}__row--nested` : "",
|
|
51
|
+
isActive ? `${baseClass}__row--active` : ""
|
|
52
|
+
].filter(Boolean).join(" ");
|
|
53
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
54
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: item.label }),
|
|
55
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__badge`, children: item.badge })
|
|
56
|
+
] });
|
|
57
|
+
return item.href ? /* @__PURE__ */ jsx(
|
|
58
|
+
"a",
|
|
59
|
+
{
|
|
60
|
+
className: classes,
|
|
61
|
+
href: item.href,
|
|
62
|
+
onClick: () => item.onClick?.(),
|
|
63
|
+
"aria-current": isActive ? "page" : void 0,
|
|
64
|
+
children: content
|
|
65
|
+
}
|
|
66
|
+
) : /* @__PURE__ */ jsx(
|
|
67
|
+
"button",
|
|
68
|
+
{
|
|
69
|
+
type: "button",
|
|
70
|
+
className: classes,
|
|
71
|
+
onClick: () => item.onClick?.(),
|
|
72
|
+
"aria-current": isActive ? "page" : void 0,
|
|
73
|
+
children: content
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
const renderItem = (item) => {
|
|
78
|
+
const children = item.children ?? [];
|
|
79
|
+
if (children.length === 0) {
|
|
80
|
+
return /* @__PURE__ */ jsx("li", { children: renderLeaf(item, false) }, item.key);
|
|
81
|
+
}
|
|
82
|
+
const isOpen = openKeys.has(item.key);
|
|
83
|
+
const holdsActive = children.some((child) => child.key === activeKey);
|
|
84
|
+
const regionId = `${uid}-${item.key.replace(/\s+/g, "-")}`;
|
|
85
|
+
return /* @__PURE__ */ jsxs("li", { children: [
|
|
86
|
+
/* @__PURE__ */ jsxs(
|
|
87
|
+
"button",
|
|
88
|
+
{
|
|
89
|
+
type: "button",
|
|
90
|
+
className: [
|
|
91
|
+
`${baseClass}__row`,
|
|
92
|
+
`${baseClass}__row--parent`,
|
|
93
|
+
holdsActive && !isOpen ? `${baseClass}__row--holds-active` : ""
|
|
94
|
+
].filter(Boolean).join(" "),
|
|
95
|
+
"aria-expanded": isOpen,
|
|
96
|
+
"aria-controls": regionId,
|
|
97
|
+
onClick: () => {
|
|
98
|
+
toggle(item.key);
|
|
99
|
+
item.onClick?.();
|
|
100
|
+
},
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: item.label }),
|
|
103
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__badge`, children: item.badge }),
|
|
104
|
+
/* @__PURE__ */ jsx(
|
|
105
|
+
"span",
|
|
106
|
+
{
|
|
107
|
+
className: [
|
|
108
|
+
`${baseClass}__chevron material-symbols-rounded`,
|
|
109
|
+
isOpen ? `${baseClass}__chevron--open` : ""
|
|
110
|
+
].filter(Boolean).join(" "),
|
|
111
|
+
"aria-hidden": "true",
|
|
112
|
+
children: "expand_more"
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
/* @__PURE__ */ jsx(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
id: regionId,
|
|
122
|
+
className: [`${baseClass}__nested`, isOpen ? `${baseClass}__nested--open` : ""].filter(Boolean).join(" "),
|
|
123
|
+
inert: !isOpen,
|
|
124
|
+
children: /* @__PURE__ */ jsx("ul", { className: `${baseClass}__nested-list`, children: children.map((child) => /* @__PURE__ */ jsx("li", { children: renderLeaf(child, true) }, child.key)) })
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
] }, item.key);
|
|
128
|
+
};
|
|
129
|
+
return /* @__PURE__ */ jsxs(
|
|
130
|
+
"nav",
|
|
131
|
+
{
|
|
132
|
+
...rest,
|
|
133
|
+
ref,
|
|
134
|
+
className: [baseClass, className].filter(Boolean).join(" "),
|
|
135
|
+
"aria-label": rest["aria-label"] ?? title ?? "Section navigation",
|
|
136
|
+
children: [
|
|
137
|
+
onBack && /* @__PURE__ */ jsxs("button", { type: "button", className: `${baseClass}__back`, onClick: onBack, children: [
|
|
138
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__back-icon material-symbols-rounded`, "aria-hidden": "true", children: "chevron_left" }),
|
|
139
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: backLabel })
|
|
140
|
+
] }),
|
|
141
|
+
(title || onCollapse) && /* @__PURE__ */ jsxs("div", { className: `${baseClass}__header`, children: [
|
|
142
|
+
title && /* @__PURE__ */ jsx("h2", { className: `${baseClass}__title`, children: title }),
|
|
143
|
+
onCollapse && /* @__PURE__ */ jsx(
|
|
144
|
+
"button",
|
|
145
|
+
{
|
|
146
|
+
type: "button",
|
|
147
|
+
className: `${baseClass}__collapse`,
|
|
148
|
+
onClick: onCollapse,
|
|
149
|
+
"aria-label": title ? `Collapse ${title}` : "Collapse panel",
|
|
150
|
+
children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", "aria-hidden": "true", children: "left_panel_close" })
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
] }),
|
|
154
|
+
/* @__PURE__ */ jsx("div", { className: `${baseClass}__body`, children: groupRuns(items).map((run, i) => /* @__PURE__ */ jsxs("div", { className: `${baseClass}__group`, children: [
|
|
155
|
+
run.group && /* @__PURE__ */ jsx("div", { className: `${baseClass}__group-label`, children: run.group }),
|
|
156
|
+
/* @__PURE__ */ jsx("ul", { className: `${baseClass}__list`, children: run.items.map(renderItem) })
|
|
157
|
+
] }, `${run.group ?? ""}-${i}`)) })
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
SidebarPanel.displayName = "SidebarPanel";
|
|
164
|
+
export {
|
|
165
|
+
SidebarPanel
|
|
166
|
+
};
|
|
@@ -35,7 +35,9 @@ export interface StepperProps extends StepperOwnProps, Omit<React.ComponentProps
|
|
|
35
35
|
* connectors: completed steps show a check, the active step carries
|
|
36
36
|
* `aria-current="step"`, and upcoming steps show their number.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
38
|
+
* The list is labelled "Progress" by default; pass `aria-label` to name it
|
|
39
|
+
* for its flow. Forwards a ref to the `<ol>` and spreads unrecognised props
|
|
40
|
+
* onto it.
|
|
39
41
|
*/
|
|
40
42
|
export declare const Stepper: React.ForwardRefExoticComponent<StepperProps & React.RefAttributes<HTMLOListElement>>;
|
|
41
43
|
export {};
|
|
@@ -18,7 +18,7 @@ const Stepper = React.forwardRef(
|
|
|
18
18
|
orientation === "vertical" && `${baseClass}--vertical`,
|
|
19
19
|
className
|
|
20
20
|
].filter(Boolean).join(" ");
|
|
21
|
-
return /* @__PURE__ */ jsx("ol", { ...rest, ref, className: classes, children: steps.map((step, index) => {
|
|
21
|
+
return /* @__PURE__ */ jsx("ol", { "aria-label": "Progress", ...rest, ref, className: classes, children: steps.map((step, index) => {
|
|
22
22
|
const status = index < activeStep ? "complete" : index === activeStep ? "active" : "upcoming";
|
|
23
23
|
const interactive = Boolean(onStepClick) && status !== "upcoming";
|
|
24
24
|
const indicator = /* @__PURE__ */ jsx("span", { className: `${baseClass}__indicator`, "aria-hidden": "true", children: status === "complete" ? /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", children: "check" }) : index + 1 });
|