rift-ds 1.0.0 → 1.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/LICENSE +1 -1
- package/README.md +11 -3
- 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/Nav/Nav.d.ts +11 -3
- package/components/Nav/Nav.js +3 -2
- 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 +25 -1
- package/components/registry.json.d.ts +25 -1
- package/components/registry.json.js +1 -1
- package/index.d.ts +3 -0
- package/index.js +6 -0
- package/package.json +5 -1
|
@@ -5,6 +5,7 @@ import { useLayer } from "../../behaviors/useLayer.js";
|
|
|
5
5
|
import { useFocusScope } from "../../behaviors/useFocusScope.js";
|
|
6
6
|
import { useScrollLock } from "../../behaviors/useScrollLock.js";
|
|
7
7
|
import { Avatar } from "../Avatar/Avatar.js";
|
|
8
|
+
import { SidebarPanel } from "../SidebarPanel/SidebarPanel.js";
|
|
8
9
|
import "./AppSidebar.css";
|
|
9
10
|
import "../../fonts/material-symbols.css";
|
|
10
11
|
function DefaultLogo() {
|
|
@@ -30,6 +31,11 @@ const AppSidebar = ({
|
|
|
30
31
|
profile,
|
|
31
32
|
activeKey,
|
|
32
33
|
activeSubKey,
|
|
34
|
+
activeTertiaryKey,
|
|
35
|
+
subNav = "accordion",
|
|
36
|
+
defaultPanelOpen = true,
|
|
37
|
+
panelOpen: controlledPanelOpen,
|
|
38
|
+
onPanelOpenChange,
|
|
33
39
|
defaultExpanded = false,
|
|
34
40
|
expanded: controlledExpanded,
|
|
35
41
|
onExpandedChange,
|
|
@@ -83,7 +89,20 @@ const AppSidebar = ({
|
|
|
83
89
|
query.addEventListener("change", onChange);
|
|
84
90
|
return () => query.removeEventListener("change", onChange);
|
|
85
91
|
}, [mobileOpen]);
|
|
86
|
-
const [openKeys, setOpenKeys] = useState(
|
|
92
|
+
const [openKeys, setOpenKeys] = useState(() => {
|
|
93
|
+
const initial = /* @__PURE__ */ new Set();
|
|
94
|
+
if (subNav !== "panel" && (activeSubKey || activeTertiaryKey)) {
|
|
95
|
+
for (const section of sections) {
|
|
96
|
+
for (const item of section.items) {
|
|
97
|
+
const holdsActive = item.children?.some(
|
|
98
|
+
(sub) => sub.key === activeSubKey || sub.children?.some((leaf) => leaf.key === activeTertiaryKey)
|
|
99
|
+
);
|
|
100
|
+
if (holdsActive) initial.add(item.key);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return initial;
|
|
105
|
+
});
|
|
87
106
|
const toggleAccordion = useCallback((key) => {
|
|
88
107
|
setOpenKeys((prev) => {
|
|
89
108
|
const next = new Set(prev);
|
|
@@ -95,6 +114,85 @@ const AppSidebar = ({
|
|
|
95
114
|
return next;
|
|
96
115
|
});
|
|
97
116
|
}, []);
|
|
117
|
+
const isPanelMode = subNav === "panel";
|
|
118
|
+
const [panelSourceKey, setPanelSourceKey] = useState(() => {
|
|
119
|
+
for (const section of sections) {
|
|
120
|
+
for (const item of section.items) {
|
|
121
|
+
if (isPanelMode) {
|
|
122
|
+
if (item.children?.length && (item.key === activeKey || item.children.some((c) => c.key === activeSubKey))) {
|
|
123
|
+
return item.key;
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
for (const sub of item.children ?? []) {
|
|
127
|
+
if (sub.children?.length && (sub.key === activeSubKey || sub.children.some((c) => c.key === activeTertiaryKey))) {
|
|
128
|
+
return sub.key;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return void 0;
|
|
135
|
+
});
|
|
136
|
+
let panelSource;
|
|
137
|
+
for (const section of sections) {
|
|
138
|
+
for (const item of section.items) {
|
|
139
|
+
if (isPanelMode && item.key === panelSourceKey && item.children?.length) {
|
|
140
|
+
panelSource = { label: item.label, items: item.children };
|
|
141
|
+
}
|
|
142
|
+
if (!isPanelMode) {
|
|
143
|
+
for (const sub of item.children ?? []) {
|
|
144
|
+
if (sub.key === panelSourceKey && sub.children?.length) {
|
|
145
|
+
panelSource = {
|
|
146
|
+
label: sub.label,
|
|
147
|
+
parentLabel: item.label,
|
|
148
|
+
items: sub.children.map(({ children: _deeper, ...leaf }) => leaf)
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const [internalPanelOpen, setInternalPanelOpen] = useState(defaultPanelOpen);
|
|
156
|
+
const isPanelOpen = controlledPanelOpen ?? internalPanelOpen;
|
|
157
|
+
const setPanelOpen = useCallback(
|
|
158
|
+
(next) => {
|
|
159
|
+
setInternalPanelOpen(next);
|
|
160
|
+
if (next !== isPanelOpen) onPanelOpenChange?.(next);
|
|
161
|
+
},
|
|
162
|
+
[isPanelOpen, onPanelOpenChange]
|
|
163
|
+
);
|
|
164
|
+
const panelVisible = Boolean(panelSource) && isPanelOpen;
|
|
165
|
+
const panelId = useId();
|
|
166
|
+
const [drilled, setDrilled] = useState(false);
|
|
167
|
+
const focusAfterDrill = useRef(null);
|
|
168
|
+
const openMobile = useCallback(() => {
|
|
169
|
+
setDrilled(Boolean(panelSource));
|
|
170
|
+
setMobileOpen(true);
|
|
171
|
+
}, [panelSource]);
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
const target = focusAfterDrill.current;
|
|
174
|
+
focusAfterDrill.current = null;
|
|
175
|
+
if (!target || !drawerRef.current) return;
|
|
176
|
+
const selector = target === "in" ? ".ds-sidebar-panel__back" : '[data-panel-source="true"]';
|
|
177
|
+
drawerRef.current.querySelector(selector)?.focus();
|
|
178
|
+
}, [drilled]);
|
|
179
|
+
const selectPanelSource = useCallback(
|
|
180
|
+
(key) => {
|
|
181
|
+
if (mobileOpen) {
|
|
182
|
+
setPanelSourceKey(key);
|
|
183
|
+
focusAfterDrill.current = "in";
|
|
184
|
+
setDrilled(true);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (key === panelSourceKey && isPanelOpen) {
|
|
188
|
+
setPanelOpen(false);
|
|
189
|
+
} else {
|
|
190
|
+
setPanelSourceKey(key);
|
|
191
|
+
setPanelOpen(true);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
[mobileOpen, panelSourceKey, isPanelOpen, setPanelOpen]
|
|
195
|
+
);
|
|
98
196
|
const classes = [
|
|
99
197
|
baseClass,
|
|
100
198
|
// The drawer always shows the expanded layout: an icon rail inside
|
|
@@ -102,6 +200,7 @@ const AppSidebar = ({
|
|
|
102
200
|
isExpanded || mobileOpen ? `${baseClass}--expanded` : "",
|
|
103
201
|
floating ? `${baseClass}--floating` : "",
|
|
104
202
|
mobileOpen ? `${baseClass}--mobile-open` : "",
|
|
203
|
+
isPanelMode ? `${baseClass}--panel-mode` : "",
|
|
105
204
|
className
|
|
106
205
|
].filter(Boolean).join(" ");
|
|
107
206
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -113,7 +212,7 @@ const AppSidebar = ({
|
|
|
113
212
|
"aria-label": "Open navigation",
|
|
114
213
|
"aria-expanded": mobileOpen,
|
|
115
214
|
"aria-controls": drawerId,
|
|
116
|
-
onClick:
|
|
215
|
+
onClick: openMobile,
|
|
117
216
|
children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", "aria-hidden": "true", children: "menu" })
|
|
118
217
|
}
|
|
119
218
|
),
|
|
@@ -153,12 +252,28 @@ const AppSidebar = ({
|
|
|
153
252
|
)
|
|
154
253
|
] }),
|
|
155
254
|
topSlot && /* @__PURE__ */ jsx("div", { className: `${baseClass}__top-slot`, children: topSlot }),
|
|
156
|
-
|
|
255
|
+
mobileOpen && drilled && panelSource ? /* @__PURE__ */ jsx(
|
|
256
|
+
SidebarPanel,
|
|
257
|
+
{
|
|
258
|
+
className: `${baseClass}__drill`,
|
|
259
|
+
items: panelSource.items,
|
|
260
|
+
title: panelSource.label,
|
|
261
|
+
activeKey: activeTertiaryKey ?? activeSubKey,
|
|
262
|
+
onBack: () => {
|
|
263
|
+
focusAfterDrill.current = "out";
|
|
264
|
+
setDrilled(false);
|
|
265
|
+
},
|
|
266
|
+
backLabel: panelSource.parentLabel ?? "Menu"
|
|
267
|
+
},
|
|
268
|
+
panelSourceKey
|
|
269
|
+
) : /* @__PURE__ */ jsx("div", { className: `${baseClass}__sections`, children: sections.map((section, si) => /* @__PURE__ */ jsxs("div", { className: `${baseClass}__nav`, children: [
|
|
157
270
|
section.category && /* @__PURE__ */ jsx("div", { className: `${baseClass}__category`, children: section.category }),
|
|
158
271
|
section.items.map((item) => {
|
|
159
272
|
const hasChildren = item.children && item.children.length > 0;
|
|
160
273
|
const isOpen = openKeys.has(item.key);
|
|
161
|
-
const
|
|
274
|
+
const feedsPanel = isPanelMode && hasChildren;
|
|
275
|
+
const isSource = feedsPanel && item.key === panelSourceKey;
|
|
276
|
+
const isActive = isPanelMode && panelVisible ? isSource : activeKey === item.key;
|
|
162
277
|
const isLink = Boolean(item.href) && !hasChildren;
|
|
163
278
|
const itemClasses = [
|
|
164
279
|
`${baseClass}__btn`,
|
|
@@ -181,7 +296,7 @@ const AppSidebar = ({
|
|
|
181
296
|
{
|
|
182
297
|
className: [
|
|
183
298
|
`${baseClass}__btn-chevron material-symbols-rounded`,
|
|
184
|
-
isOpen ? `${baseClass}__btn-chevron--open` : ""
|
|
299
|
+
isOpen && !isPanelMode ? `${baseClass}__btn-chevron--open` : ""
|
|
185
300
|
].filter(Boolean).join(" "),
|
|
186
301
|
children: "chevron_right"
|
|
187
302
|
}
|
|
@@ -204,18 +319,27 @@ const AppSidebar = ({
|
|
|
204
319
|
type: "button",
|
|
205
320
|
className: itemClasses,
|
|
206
321
|
onClick: () => {
|
|
207
|
-
if (
|
|
208
|
-
|
|
322
|
+
if (feedsPanel) {
|
|
323
|
+
selectPanelSource(item.key);
|
|
324
|
+
} else if (hasChildren) {
|
|
325
|
+
if (!isExpanded && !mobileOpen) {
|
|
326
|
+
toggleExpanded();
|
|
327
|
+
setOpenKeys((prev) => new Set(prev).add(item.key));
|
|
328
|
+
} else {
|
|
329
|
+
toggleAccordion(item.key);
|
|
330
|
+
}
|
|
209
331
|
}
|
|
210
332
|
item.onClick?.();
|
|
211
333
|
},
|
|
212
|
-
"aria-expanded": hasChildren ? isOpen : void 0,
|
|
213
|
-
"aria-
|
|
214
|
-
|
|
334
|
+
"aria-expanded": feedsPanel ? mobileOpen ? void 0 : isSource && panelVisible : hasChildren ? isOpen : void 0,
|
|
335
|
+
"aria-controls": feedsPanel && !mobileOpen ? panelId : void 0,
|
|
336
|
+
"aria-current": activeKey === item.key ? "page" : void 0,
|
|
337
|
+
"data-panel-source": isSource ? "true" : void 0,
|
|
338
|
+
title: !isExpanded && !isPanelMode ? item.label : void 0,
|
|
215
339
|
children: itemContent
|
|
216
340
|
}
|
|
217
341
|
),
|
|
218
|
-
hasChildren && /* @__PURE__ */ jsx(
|
|
342
|
+
hasChildren && !isPanelMode && /* @__PURE__ */ jsx(
|
|
219
343
|
"div",
|
|
220
344
|
{
|
|
221
345
|
className: [
|
|
@@ -223,15 +347,43 @@ const AppSidebar = ({
|
|
|
223
347
|
isOpen && isExpanded ? `${baseClass}__sub-items--open` : ""
|
|
224
348
|
].filter(Boolean).join(" "),
|
|
225
349
|
children: item.children.map((sub) => {
|
|
226
|
-
const
|
|
350
|
+
const subHasChildren = Boolean(sub.children?.length);
|
|
351
|
+
const subIsSource = subHasChildren && sub.key === panelSourceKey;
|
|
352
|
+
const subActive = panelVisible && subHasChildren ? subIsSource : activeSubKey === sub.key;
|
|
227
353
|
const subClasses = [
|
|
228
354
|
`${baseClass}__sub-btn`,
|
|
229
355
|
subActive ? `${baseClass}__sub-btn--active` : ""
|
|
230
356
|
].filter(Boolean).join(" ");
|
|
231
|
-
const subLabel = /* @__PURE__ */
|
|
357
|
+
const subLabel = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
358
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__sub-label`, children: sub.label }),
|
|
359
|
+
sub.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-badge`, children: sub.badge }),
|
|
360
|
+
subHasChildren && /* @__PURE__ */ jsx(
|
|
361
|
+
"span",
|
|
362
|
+
{
|
|
363
|
+
className: `${baseClass}__sub-chevron material-symbols-rounded`,
|
|
364
|
+
"aria-hidden": "true",
|
|
365
|
+
children: "chevron_right"
|
|
366
|
+
}
|
|
367
|
+
)
|
|
368
|
+
] });
|
|
232
369
|
return /* @__PURE__ */ jsxs("div", { className: `${baseClass}__sub-item`, children: [
|
|
233
370
|
/* @__PURE__ */ jsx("div", { className: `${baseClass}__sub-line` }),
|
|
234
|
-
|
|
371
|
+
subHasChildren ? /* @__PURE__ */ jsx(
|
|
372
|
+
"button",
|
|
373
|
+
{
|
|
374
|
+
type: "button",
|
|
375
|
+
className: subClasses,
|
|
376
|
+
onClick: () => {
|
|
377
|
+
selectPanelSource(sub.key);
|
|
378
|
+
sub.onClick?.();
|
|
379
|
+
},
|
|
380
|
+
"aria-expanded": mobileOpen ? void 0 : subIsSource && panelVisible,
|
|
381
|
+
"aria-controls": mobileOpen ? void 0 : panelId,
|
|
382
|
+
"aria-current": activeSubKey === sub.key ? "page" : void 0,
|
|
383
|
+
"data-panel-source": subIsSource ? "true" : void 0,
|
|
384
|
+
children: subLabel
|
|
385
|
+
}
|
|
386
|
+
) : sub.href ? /* @__PURE__ */ jsx(
|
|
235
387
|
"a",
|
|
236
388
|
{
|
|
237
389
|
className: subClasses,
|
|
@@ -256,7 +408,7 @@ const AppSidebar = ({
|
|
|
256
408
|
)
|
|
257
409
|
] }, item.key);
|
|
258
410
|
})
|
|
259
|
-
] }, si))
|
|
411
|
+
] }, si)) })
|
|
260
412
|
] }),
|
|
261
413
|
/* @__PURE__ */ jsxs("div", { className: `${baseClass}__bottom`, children: [
|
|
262
414
|
footerSlot && /* @__PURE__ */ jsx("div", { className: `${baseClass}__footer-slot`, children: footerSlot }),
|
|
@@ -287,7 +439,26 @@ const AppSidebar = ({
|
|
|
287
439
|
)
|
|
288
440
|
] })
|
|
289
441
|
] })
|
|
290
|
-
] })
|
|
442
|
+
] }),
|
|
443
|
+
panelSource && !mobileOpen && /* @__PURE__ */ jsx(
|
|
444
|
+
SidebarPanel,
|
|
445
|
+
{
|
|
446
|
+
id: panelId,
|
|
447
|
+
className: [
|
|
448
|
+
`${baseClass}__panel`,
|
|
449
|
+
panelVisible ? `${baseClass}__panel--visible` : "",
|
|
450
|
+
isExpanded ? `${baseClass}__panel--beside-expanded` : "",
|
|
451
|
+
isPanelMode ? `${baseClass}__panel--panel-mode` : "",
|
|
452
|
+
floating ? `${baseClass}__panel--floating` : ""
|
|
453
|
+
].filter(Boolean).join(" "),
|
|
454
|
+
items: panelSource.items,
|
|
455
|
+
title: panelSource.label,
|
|
456
|
+
activeKey: activeTertiaryKey ?? activeSubKey,
|
|
457
|
+
onCollapse: () => setPanelOpen(false),
|
|
458
|
+
inert: !panelVisible
|
|
459
|
+
},
|
|
460
|
+
panelSourceKey
|
|
461
|
+
)
|
|
291
462
|
] });
|
|
292
463
|
};
|
|
293
464
|
export {
|