@lobehub/ui 5.48.2 → 5.49.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/es/Highlighter/FullFeatured.mjs +1 -1
- package/es/Highlighter/FullFeatured.mjs.map +1 -1
- package/es/Highlighter/LangSelect.mjs +1 -1
- package/es/Highlighter/LangSelect.mjs.map +1 -1
- package/es/Highlighter/style.mjs +14 -11
- package/es/Highlighter/style.mjs.map +1 -1
- package/es/Mermaid/FullFeatured.mjs +1 -1
- package/es/Mermaid/FullFeatured.mjs.map +1 -1
- package/es/ThemeProvider/ThemeProvider.mjs +2 -2
- package/es/ThemeProvider/ThemeProvider.mjs.map +1 -1
- package/es/awesome/AgentSkillCard/AgentSkillCard.d.mts +6 -0
- package/es/awesome/AgentSkillCard/AgentSkillCard.mjs +83 -0
- package/es/awesome/AgentSkillCard/AgentSkillCard.mjs.map +1 -0
- package/es/awesome/AgentSkillCard/agents.d.mts +6 -0
- package/es/awesome/AgentSkillCard/agents.mjs +40 -0
- package/es/awesome/AgentSkillCard/agents.mjs.map +1 -0
- package/es/awesome/AgentSkillCard/index.d.mts +4 -0
- package/es/awesome/AgentSkillCard/style.mjs +85 -0
- package/es/awesome/AgentSkillCard/style.mjs.map +1 -0
- package/es/awesome/AgentSkillCard/type.d.mts +41 -0
- package/es/awesome/BentoGrid/BentoCard.d.mts +6 -0
- package/es/awesome/BentoGrid/BentoCard.mjs +39 -0
- package/es/awesome/BentoGrid/BentoCard.mjs.map +1 -0
- package/es/awesome/BentoGrid/BentoGrid.d.mts +6 -0
- package/es/awesome/BentoGrid/BentoGrid.mjs +20 -0
- package/es/awesome/BentoGrid/BentoGrid.mjs.map +1 -0
- package/es/awesome/BentoGrid/index.d.mts +4 -0
- package/es/awesome/BentoGrid/style.mjs +102 -0
- package/es/awesome/BentoGrid/style.mjs.map +1 -0
- package/es/awesome/BentoGrid/type.d.mts +40 -0
- package/es/awesome/CodeShowcase/CodeShowcase.d.mts +6 -0
- package/es/awesome/CodeShowcase/CodeShowcase.mjs +51 -0
- package/es/awesome/CodeShowcase/CodeShowcase.mjs.map +1 -0
- package/es/awesome/CodeShowcase/index.d.mts +3 -0
- package/es/awesome/CodeShowcase/style.mjs +50 -0
- package/es/awesome/CodeShowcase/style.mjs.map +1 -0
- package/es/awesome/CodeShowcase/type.d.mts +27 -0
- package/es/awesome/FeatureGrid/FeatureGrid.d.mts +6 -0
- package/es/awesome/FeatureGrid/FeatureGrid.mjs +48 -0
- package/es/awesome/FeatureGrid/FeatureGrid.mjs.map +1 -0
- package/es/awesome/FeatureGrid/index.d.mts +3 -0
- package/es/awesome/FeatureGrid/style.mjs +75 -0
- package/es/awesome/FeatureGrid/style.mjs.map +1 -0
- package/es/awesome/FeatureGrid/type.d.mts +25 -0
- package/es/awesome/FluidGradient/FluidGradient.d.mts +6 -0
- package/es/awesome/FluidGradient/FluidGradient.mjs +293 -0
- package/es/awesome/FluidGradient/FluidGradient.mjs.map +1 -0
- package/es/awesome/FluidGradient/index.d.mts +3 -0
- package/es/awesome/FluidGradient/style.mjs +52 -0
- package/es/awesome/FluidGradient/style.mjs.map +1 -0
- package/es/awesome/FluidGradient/type.d.mts +22 -0
- package/es/awesome/InstallBanner/InstallBanner.d.mts +6 -0
- package/es/awesome/InstallBanner/InstallBanner.mjs +35 -0
- package/es/awesome/InstallBanner/InstallBanner.mjs.map +1 -0
- package/es/awesome/InstallBanner/index.d.mts +3 -0
- package/es/awesome/InstallBanner/style.mjs +46 -0
- package/es/awesome/InstallBanner/style.mjs.map +1 -0
- package/es/awesome/InstallBanner/type.d.mts +18 -0
- package/es/awesome/LandingHero/LandingHero.d.mts +6 -0
- package/es/awesome/LandingHero/LandingHero.mjs +55 -0
- package/es/awesome/LandingHero/LandingHero.mjs.map +1 -0
- package/es/awesome/LandingHero/index.d.mts +3 -0
- package/es/awesome/LandingHero/style.mjs +155 -0
- package/es/awesome/LandingHero/style.mjs.map +1 -0
- package/es/awesome/LandingHero/type.d.mts +29 -0
- package/es/awesome/LandingSection/LandingSection.d.mts +6 -0
- package/es/awesome/LandingSection/LandingSection.mjs +61 -0
- package/es/awesome/LandingSection/LandingSection.mjs.map +1 -0
- package/es/awesome/LandingSection/index.d.mts +3 -0
- package/es/awesome/LandingSection/style.mjs +88 -0
- package/es/awesome/LandingSection/style.mjs.map +1 -0
- package/es/awesome/LandingSection/type.d.mts +40 -0
- package/es/awesome/LogoMarquee/LogoMarquee.d.mts +6 -0
- package/es/awesome/LogoMarquee/LogoMarquee.mjs +52 -0
- package/es/awesome/LogoMarquee/LogoMarquee.mjs.map +1 -0
- package/es/awesome/LogoMarquee/index.d.mts +3 -0
- package/es/awesome/LogoMarquee/style.mjs +70 -0
- package/es/awesome/LogoMarquee/style.mjs.map +1 -0
- package/es/awesome/LogoMarquee/type.d.mts +40 -0
- package/es/awesome/index.d.mts +33 -1
- package/es/awesome/index.mjs +13 -1
- package/es/awesome/landingActions.d.mts +20 -0
- package/es/awesome/landingActions.mjs +123 -0
- package/es/awesome/landingActions.mjs.map +1 -0
- package/es/awesome/landingIcon.mjs +13 -0
- package/es/awesome/landingIcon.mjs.map +1 -0
- package/es/awesome/landingLink.d.mts +12 -0
- package/es/awesome/landingLink.mjs +23 -0
- package/es/awesome/landingLink.mjs.map +1 -0
- package/es/awesome/landingTokens.d.mts +10 -0
- package/es/awesome/landingTokens.mjs +19 -0
- package/es/awesome/landingTokens.mjs.map +1 -0
- package/es/base-ui/Input/style.d.mts +1 -1
- package/es/base-ui/Segmented/atoms.mjs +1 -0
- package/es/base-ui/Segmented/atoms.mjs.map +1 -1
- package/es/base-ui/Segmented/style.mjs +127 -125
- package/es/base-ui/Segmented/style.mjs.map +1 -1
- package/es/base-ui/index.mjs +4 -4
- package/es/dashboard/AuthLayout/AuthLayout.d.mts +9 -0
- package/es/dashboard/AuthLayout/AuthLayout.mjs +54 -0
- package/es/dashboard/AuthLayout/AuthLayout.mjs.map +1 -0
- package/es/dashboard/AuthLayout/index.d.mts +3 -0
- package/es/dashboard/AuthLayout/style.mjs +120 -0
- package/es/dashboard/AuthLayout/style.mjs.map +1 -0
- package/es/dashboard/AuthLayout/type.d.mts +16 -0
- package/es/dashboard/Breadcrumb/Breadcrumb.d.mts +9 -0
- package/es/dashboard/Breadcrumb/Breadcrumb.mjs +55 -0
- package/es/dashboard/Breadcrumb/Breadcrumb.mjs.map +1 -0
- package/es/dashboard/Breadcrumb/index.d.mts +3 -0
- package/es/dashboard/Breadcrumb/style.mjs +66 -0
- package/es/dashboard/Breadcrumb/style.mjs.map +1 -0
- package/es/dashboard/Breadcrumb/type.d.mts +25 -0
- package/es/dashboard/ConsoleNav/ConsoleNav.d.mts +9 -0
- package/es/dashboard/ConsoleNav/ConsoleNav.mjs +275 -0
- package/es/dashboard/ConsoleNav/ConsoleNav.mjs.map +1 -0
- package/es/dashboard/ConsoleNav/active.d.mts +7 -0
- package/es/dashboard/ConsoleNav/active.mjs +29 -0
- package/es/dashboard/ConsoleNav/active.mjs.map +1 -0
- package/es/dashboard/ConsoleNav/index.d.mts +4 -0
- package/es/dashboard/ConsoleNav/style.mjs +283 -0
- package/es/dashboard/ConsoleNav/style.mjs.map +1 -0
- package/es/dashboard/ConsoleNav/type.d.mts +71 -0
- package/es/dashboard/ConsoleShell/ConsoleBrand.d.mts +9 -0
- package/es/dashboard/ConsoleShell/ConsoleBrand.mjs +37 -0
- package/es/dashboard/ConsoleShell/ConsoleBrand.mjs.map +1 -0
- package/es/dashboard/ConsoleShell/ConsoleShell.d.mts +9 -0
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs +149 -0
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs.map +1 -0
- package/es/dashboard/ConsoleShell/context.d.mts +6 -0
- package/es/dashboard/ConsoleShell/context.mjs +16 -0
- package/es/dashboard/ConsoleShell/context.mjs.map +1 -0
- package/es/dashboard/ConsoleShell/index.d.mts +5 -0
- package/es/dashboard/ConsoleShell/style.mjs +209 -0
- package/es/dashboard/ConsoleShell/style.mjs.map +1 -0
- package/es/dashboard/ConsoleShell/type.d.mts +67 -0
- package/es/dashboard/FilterSidebar/FilterSidebar.d.mts +17 -0
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs +151 -0
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs.map +1 -0
- package/es/dashboard/FilterSidebar/context.d.mts +7 -0
- package/es/dashboard/FilterSidebar/context.mjs +19 -0
- package/es/dashboard/FilterSidebar/context.mjs.map +1 -0
- package/es/dashboard/FilterSidebar/index.d.mts +4 -0
- package/es/dashboard/FilterSidebar/style.mjs +155 -0
- package/es/dashboard/FilterSidebar/style.mjs.map +1 -0
- package/es/dashboard/FilterSidebar/type.d.mts +44 -0
- package/es/dashboard/FilterSidebar/width.mjs +18 -0
- package/es/dashboard/FilterSidebar/width.mjs.map +1 -0
- package/es/dashboard/PageHeader/PageHeader.d.mts +9 -0
- package/es/dashboard/PageHeader/PageHeader.mjs +37 -0
- package/es/dashboard/PageHeader/PageHeader.mjs.map +1 -0
- package/es/dashboard/PageHeader/index.d.mts +3 -0
- package/es/dashboard/PageHeader/style.mjs +47 -0
- package/es/dashboard/PageHeader/style.mjs.map +1 -0
- package/es/dashboard/PageHeader/type.d.mts +14 -0
- package/es/dashboard/PageSkeleton/PageSkeleton.d.mts +25 -0
- package/es/dashboard/PageSkeleton/PageSkeleton.mjs +136 -0
- package/es/dashboard/PageSkeleton/PageSkeleton.mjs.map +1 -0
- package/es/dashboard/PageSkeleton/style.mjs +122 -0
- package/es/dashboard/PageSkeleton/style.mjs.map +1 -0
- package/es/dashboard/PageSkeleton/type.d.mts +22 -0
- package/es/dashboard/PageTabs/PageTabs.d.mts +9 -0
- package/es/dashboard/PageTabs/PageTabs.mjs +37 -0
- package/es/dashboard/PageTabs/PageTabs.mjs.map +1 -0
- package/es/dashboard/PageTabs/index.d.mts +3 -0
- package/es/dashboard/PageTabs/style.mjs +57 -0
- package/es/dashboard/PageTabs/style.mjs.map +1 -0
- package/es/dashboard/PageTabs/type.d.mts +17 -0
- package/es/dashboard/RouteProgress/RouteProgress.d.mts +9 -0
- package/es/dashboard/RouteProgress/RouteProgress.mjs +44 -0
- package/es/dashboard/RouteProgress/RouteProgress.mjs.map +1 -0
- package/es/dashboard/RouteProgress/style.mjs +19 -0
- package/es/dashboard/RouteProgress/style.mjs.map +1 -0
- package/es/dashboard/RouteProgress/type.d.mts +8 -0
- package/es/dashboard/StatCard/StatCard.d.mts +9 -0
- package/es/dashboard/StatCard/StatCard.mjs +84 -0
- package/es/dashboard/StatCard/StatCard.mjs.map +1 -0
- package/es/dashboard/StatCard/index.d.mts +3 -0
- package/es/dashboard/StatCard/style.mjs +135 -0
- package/es/dashboard/StatCard/style.mjs.map +1 -0
- package/es/dashboard/StatCard/type.d.mts +26 -0
- package/es/dashboard/Surface/Surface.d.mts +13 -0
- package/es/dashboard/Surface/Surface.mjs +20 -0
- package/es/dashboard/Surface/Surface.mjs.map +1 -0
- package/es/dashboard/Surface/index.d.mts +4 -0
- package/es/dashboard/Surface/style.d.mts +14 -0
- package/es/dashboard/Surface/style.mjs +22 -0
- package/es/dashboard/Surface/style.mjs.map +1 -0
- package/es/dashboard/Surface/type.d.mts +8 -0
- package/es/dashboard/hooks.mjs +49 -0
- package/es/dashboard/hooks.mjs.map +1 -0
- package/es/dashboard/index.d.mts +37 -0
- package/es/dashboard/index.d.ts +1 -0
- package/es/dashboard/index.js +1 -0
- package/es/dashboard/index.mjs +17 -0
- package/es/static-css/registry.mjs +2 -2
- package/es/static-css/registry.mjs.map +1 -1
- package/es/storybook/StoryBook/index.mjs +4 -0
- package/es/storybook/StoryBook/index.mjs.map +1 -1
- package/es/storybook/StoryBook/style.mjs +7 -2
- package/es/storybook/StoryBook/style.mjs.map +1 -1
- package/es/styles/theme/token/base.mjs +2 -2
- package/es/styles/theme/token/base.mjs.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import Icon from "../../Icon/Icon.mjs";
|
|
3
|
+
import { Tooltip } from "../../base-ui/Tooltip/Tooltip.mjs";
|
|
4
|
+
import ScrollShadow from "../../ScrollShadow/ScrollShadow.mjs";
|
|
5
|
+
import { collectNavItems, findActiveBranch, resolveActiveHref } from "./active.mjs";
|
|
6
|
+
import { useConsoleShellState } from "../ConsoleShell/context.mjs";
|
|
7
|
+
import { useLocalStorage, usePrefersReducedMotion } from "../hooks.mjs";
|
|
8
|
+
import { styles } from "./style.mjs";
|
|
9
|
+
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { ChevronDown, Play } from "lucide-react";
|
|
12
|
+
//#region src/dashboard/ConsoleNav/ConsoleNav.tsx
|
|
13
|
+
const PANEL_TRANSITION_MS = 160;
|
|
14
|
+
/** Older builds stored the closed group keys as an array. */
|
|
15
|
+
function readOverrides(value) {
|
|
16
|
+
if (Array.isArray(value)) return Object.fromEntries(value.map((key) => [String(key), false]));
|
|
17
|
+
return value && typeof value === "object" ? value : {};
|
|
18
|
+
}
|
|
19
|
+
function scrollActiveIntoView(container) {
|
|
20
|
+
const link = container.querySelector("[aria-current=\"page\"]") ?? [...container.querySelectorAll("button[data-active=\"true\"]")].at(-1);
|
|
21
|
+
if (!link) return;
|
|
22
|
+
const containerRect = container.getBoundingClientRect();
|
|
23
|
+
const linkRect = link.getBoundingClientRect();
|
|
24
|
+
if (linkRect.top >= containerRect.top && linkRect.bottom <= containerRect.bottom) return;
|
|
25
|
+
container.scrollTop += linkRect.top - containerRect.top - (containerRect.height - linkRect.height) / 2;
|
|
26
|
+
}
|
|
27
|
+
function NavLink({ active, collapsed, context, href, icon, indent = 0, item, name }) {
|
|
28
|
+
const shell = useConsoleShellState();
|
|
29
|
+
const label = item?.label ?? name;
|
|
30
|
+
const follow = () => {
|
|
31
|
+
context.onNavigate?.(href);
|
|
32
|
+
shell?.closeNavigation();
|
|
33
|
+
};
|
|
34
|
+
const linkProps = {
|
|
35
|
+
"aria-current": active ? "page" : void 0,
|
|
36
|
+
"aria-label": collapsed ? name : void 0,
|
|
37
|
+
"children": /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
38
|
+
icon ? /* @__PURE__ */ jsx(Icon, {
|
|
39
|
+
icon,
|
|
40
|
+
size: 18
|
|
41
|
+
}) : null,
|
|
42
|
+
collapsed ? null : /* @__PURE__ */ jsx("span", {
|
|
43
|
+
className: styles.itemLabel,
|
|
44
|
+
children: label
|
|
45
|
+
}),
|
|
46
|
+
!collapsed && item?.badge ? /* @__PURE__ */ jsx("span", {
|
|
47
|
+
className: styles.badge,
|
|
48
|
+
children: item.badge
|
|
49
|
+
}) : null,
|
|
50
|
+
collapsed && item?.badge ? /* @__PURE__ */ jsx("span", {
|
|
51
|
+
"aria-hidden": true,
|
|
52
|
+
className: styles.dot
|
|
53
|
+
}) : null
|
|
54
|
+
] }),
|
|
55
|
+
"className": styles.item,
|
|
56
|
+
"data-active": active,
|
|
57
|
+
"data-collapsed": collapsed,
|
|
58
|
+
"data-indent": indent,
|
|
59
|
+
"external": item?.external,
|
|
60
|
+
href,
|
|
61
|
+
"onClick": follow,
|
|
62
|
+
"title": collapsed ? void 0 : label
|
|
63
|
+
};
|
|
64
|
+
const link = context.renderLink ? context.renderLink(linkProps) : /* @__PURE__ */ jsx("a", {
|
|
65
|
+
"aria-current": linkProps["aria-current"],
|
|
66
|
+
"aria-label": linkProps["aria-label"],
|
|
67
|
+
className: linkProps.className,
|
|
68
|
+
"data-active": active,
|
|
69
|
+
"data-collapsed": collapsed,
|
|
70
|
+
"data-indent": indent,
|
|
71
|
+
href,
|
|
72
|
+
rel: item?.external ? "noreferrer" : void 0,
|
|
73
|
+
target: item?.external ? "_blank" : void 0,
|
|
74
|
+
title: linkProps.title,
|
|
75
|
+
onClick: (event) => {
|
|
76
|
+
if (context.onNavigate && !item?.external) event.preventDefault();
|
|
77
|
+
follow();
|
|
78
|
+
},
|
|
79
|
+
children: linkProps.children
|
|
80
|
+
});
|
|
81
|
+
if (!collapsed) return link;
|
|
82
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
83
|
+
placement: "right",
|
|
84
|
+
title: name,
|
|
85
|
+
children: link
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function ConsoleNav({ collapsed: collapsedProp, defaultExpanded = "all", groups = [], items = [], label = "Primary", onNavigate, pathname, renderLink, storageKey }) {
|
|
89
|
+
const id = useId();
|
|
90
|
+
const navRef = useRef(null);
|
|
91
|
+
const shell = useConsoleShellState();
|
|
92
|
+
const collapsed = collapsedProp ?? shell?.collapsed ?? false;
|
|
93
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
94
|
+
const [storedOverrides, setStoredOverrides] = useLocalStorage(storageKey, {});
|
|
95
|
+
const overrides = readOverrides(storedOverrides);
|
|
96
|
+
const context = {
|
|
97
|
+
onNavigate,
|
|
98
|
+
renderLink
|
|
99
|
+
};
|
|
100
|
+
const activeHref = resolveActiveHref(pathname, [...items, ...collectNavItems(groups)]);
|
|
101
|
+
const activeBranch = findActiveBranch(pathname, groups, activeHref);
|
|
102
|
+
const [trackedPathname, setTrackedPathname] = useState(pathname);
|
|
103
|
+
if (trackedPathname !== pathname) {
|
|
104
|
+
setTrackedPathname(pathname);
|
|
105
|
+
if (activeBranch.some((key) => overrides[key] === false)) {
|
|
106
|
+
const next = { ...overrides };
|
|
107
|
+
for (const key of activeBranch) delete next[key];
|
|
108
|
+
setStoredOverrides(next);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const isExpanded = (group) => overrides[group.key] ?? (activeBranch.includes(group.key) || (group.defaultExpanded ?? defaultExpanded === "all"));
|
|
112
|
+
const toggleGroup = useCallback((key, expanded) => {
|
|
113
|
+
setStoredOverrides((current) => ({
|
|
114
|
+
...readOverrides(current),
|
|
115
|
+
[key]: !expanded
|
|
116
|
+
}));
|
|
117
|
+
}, [setStoredOverrides]);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
const container = navRef.current;
|
|
120
|
+
if (!container) return;
|
|
121
|
+
scrollActiveIntoView(container);
|
|
122
|
+
if (reducedMotion) return;
|
|
123
|
+
const timer = window.setTimeout(() => scrollActiveIntoView(container), PANEL_TRANSITION_MS);
|
|
124
|
+
return () => window.clearTimeout(timer);
|
|
125
|
+
}, [
|
|
126
|
+
activeHref,
|
|
127
|
+
collapsed,
|
|
128
|
+
pathname,
|
|
129
|
+
reducedMotion
|
|
130
|
+
]);
|
|
131
|
+
const renderItems = (list, indent, groupLabel) => list.map((item) => /* @__PURE__ */ jsx(NavLink, {
|
|
132
|
+
active: item.href === activeHref,
|
|
133
|
+
collapsed: false,
|
|
134
|
+
context,
|
|
135
|
+
href: item.href,
|
|
136
|
+
icon: item.icon,
|
|
137
|
+
indent: item.icon ? Math.max(0, indent - 1) : indent,
|
|
138
|
+
item,
|
|
139
|
+
name: groupLabel ? `${groupLabel} / ${item.label}` : item.label
|
|
140
|
+
}, item.href));
|
|
141
|
+
if (collapsed) {
|
|
142
|
+
const railItems = (list, groupLabel) => list.filter((item) => item.icon).map((item) => /* @__PURE__ */ jsx(NavLink, {
|
|
143
|
+
collapsed: true,
|
|
144
|
+
active: item.href === activeHref,
|
|
145
|
+
context,
|
|
146
|
+
href: item.href,
|
|
147
|
+
icon: item.icon,
|
|
148
|
+
item,
|
|
149
|
+
name: groupLabel ? `${groupLabel} / ${item.label}` : item.label
|
|
150
|
+
}, item.href));
|
|
151
|
+
const topRail = railItems(items);
|
|
152
|
+
const iconGroups = groups.filter((group) => group.icon);
|
|
153
|
+
return /* @__PURE__ */ jsxs(ScrollShadow, {
|
|
154
|
+
"aria-label": label,
|
|
155
|
+
as: "nav",
|
|
156
|
+
className: styles.nav,
|
|
157
|
+
"data-collapsed": "",
|
|
158
|
+
orientation: "vertical",
|
|
159
|
+
ref: navRef,
|
|
160
|
+
size: 8,
|
|
161
|
+
children: [
|
|
162
|
+
topRail.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
163
|
+
className: styles.railTop,
|
|
164
|
+
children: topRail
|
|
165
|
+
}) : null,
|
|
166
|
+
iconGroups.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
167
|
+
className: styles.railGroup,
|
|
168
|
+
"data-first": topRail.length === 0,
|
|
169
|
+
role: "group",
|
|
170
|
+
children: iconGroups.map((group) => {
|
|
171
|
+
const href = group.href ?? collectNavItems([group])[0]?.href;
|
|
172
|
+
if (!href) return null;
|
|
173
|
+
return /* @__PURE__ */ jsx(NavLink, {
|
|
174
|
+
collapsed: true,
|
|
175
|
+
active: activeBranch[0] === group.key,
|
|
176
|
+
context,
|
|
177
|
+
href,
|
|
178
|
+
icon: group.icon,
|
|
179
|
+
name: group.label
|
|
180
|
+
}, group.key);
|
|
181
|
+
})
|
|
182
|
+
}) : null,
|
|
183
|
+
groups.filter((group) => !group.icon).map((group, index) => {
|
|
184
|
+
const rail = railItems(collectNavItems([group]), group.label);
|
|
185
|
+
if (rail.length === 0) return null;
|
|
186
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
187
|
+
className: styles.railGroup,
|
|
188
|
+
"data-first": topRail.length === 0 && iconGroups.length === 0 && index === 0,
|
|
189
|
+
role: "group",
|
|
190
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
191
|
+
className: styles.srOnly,
|
|
192
|
+
children: group.label
|
|
193
|
+
}), rail]
|
|
194
|
+
}, group.key);
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const renderGroup = (group, level, indent) => {
|
|
200
|
+
const expanded = isExpanded(group);
|
|
201
|
+
const panelId = `${id}-${group.key}`;
|
|
202
|
+
const childIndent = indent + (group.icon ? 1 : 0);
|
|
203
|
+
const active = activeBranch.includes(group.key);
|
|
204
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
205
|
+
className: styles.group,
|
|
206
|
+
"data-icon": Boolean(group.icon),
|
|
207
|
+
"data-level": level,
|
|
208
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
209
|
+
"aria-controls": panelId,
|
|
210
|
+
"aria-expanded": expanded,
|
|
211
|
+
className: styles.groupHeader,
|
|
212
|
+
"data-active": active,
|
|
213
|
+
"data-icon": Boolean(group.icon),
|
|
214
|
+
"data-indent": indent,
|
|
215
|
+
"data-level": level,
|
|
216
|
+
type: "button",
|
|
217
|
+
onClick: () => toggleGroup(group.key, expanded),
|
|
218
|
+
children: [
|
|
219
|
+
group.icon ? /* @__PURE__ */ jsx(Icon, {
|
|
220
|
+
icon: group.icon,
|
|
221
|
+
size: 16
|
|
222
|
+
}) : null,
|
|
223
|
+
/* @__PURE__ */ jsx("span", {
|
|
224
|
+
className: styles.itemLabel,
|
|
225
|
+
"data-label": "",
|
|
226
|
+
children: group.label
|
|
227
|
+
}),
|
|
228
|
+
level === 0 ? /* @__PURE__ */ jsx(Icon, {
|
|
229
|
+
className: styles.chevron,
|
|
230
|
+
"data-expanded": expanded,
|
|
231
|
+
icon: ChevronDown,
|
|
232
|
+
size: 14
|
|
233
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
234
|
+
className: styles.indicator,
|
|
235
|
+
"data-expanded": expanded,
|
|
236
|
+
children: /* @__PURE__ */ jsx(Play, {
|
|
237
|
+
fill: "currentColor",
|
|
238
|
+
size: 7,
|
|
239
|
+
strokeWidth: 1
|
|
240
|
+
})
|
|
241
|
+
})
|
|
242
|
+
]
|
|
243
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
244
|
+
"aria-hidden": !expanded,
|
|
245
|
+
className: styles.groupPanel,
|
|
246
|
+
"data-expanded": expanded,
|
|
247
|
+
"data-instant": reducedMotion,
|
|
248
|
+
id: panelId,
|
|
249
|
+
inert: expanded ? void 0 : true,
|
|
250
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
251
|
+
className: styles.groupItems,
|
|
252
|
+
children: [renderItems(group.items ?? [], childIndent, group.label), (group.groups ?? []).map((child) => renderGroup(child, level + 1, childIndent))]
|
|
253
|
+
})
|
|
254
|
+
})]
|
|
255
|
+
}, group.key);
|
|
256
|
+
};
|
|
257
|
+
return /* @__PURE__ */ jsxs(ScrollShadow, {
|
|
258
|
+
"aria-label": label,
|
|
259
|
+
as: "nav",
|
|
260
|
+
className: styles.nav,
|
|
261
|
+
orientation: "vertical",
|
|
262
|
+
ref: navRef,
|
|
263
|
+
size: 4,
|
|
264
|
+
children: [items.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
265
|
+
className: styles.topItems,
|
|
266
|
+
"data-divided": groups.length > 0,
|
|
267
|
+
children: renderItems(items, 0)
|
|
268
|
+
}) : null, groups.map((group) => renderGroup(group, 0, 0))]
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
ConsoleNav.displayName = "ConsoleNav";
|
|
272
|
+
//#endregion
|
|
273
|
+
export { ConsoleNav as default };
|
|
274
|
+
|
|
275
|
+
//# sourceMappingURL=ConsoleNav.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsoleNav.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/ConsoleNav.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronDown, Play } from 'lucide-react';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\n\nimport Tooltip from '@/base-ui/Tooltip';\nimport Icon from '@/Icon';\nimport ScrollShadow from '@/ScrollShadow';\n\nimport { useConsoleShellState } from '../ConsoleShell/context';\nimport { useLocalStorage, usePrefersReducedMotion } from '../hooks';\nimport { collectNavItems, findActiveBranch, resolveActiveHref } from './active';\nimport { styles } from './style';\nimport type { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps } from './type';\n\nconst PANEL_TRANSITION_MS = 160;\n\ntype ExpandedOverrides = Record<string, boolean>;\n\n/** Older builds stored the closed group keys as an array. */\nfunction readOverrides(value: unknown): ExpandedOverrides {\n if (Array.isArray(value)) {\n return Object.fromEntries(value.map((key) => [String(key), false]));\n }\n return value && typeof value === 'object' ? (value as ExpandedOverrides) : {};\n}\n\nfunction scrollActiveIntoView(container: HTMLElement) {\n const link =\n container.querySelector<HTMLElement>('[aria-current=\"page\"]') ??\n [...container.querySelectorAll<HTMLElement>('button[data-active=\"true\"]')].at(-1);\n if (!link) return;\n const containerRect = container.getBoundingClientRect();\n const linkRect = link.getBoundingClientRect();\n if (linkRect.top >= containerRect.top && linkRect.bottom <= containerRect.bottom) return;\n container.scrollTop +=\n linkRect.top - containerRect.top - (containerRect.height - linkRect.height) / 2;\n}\n\ninterface LinkContext {\n onNavigate?: (href: string) => void;\n renderLink?: ConsoleNavProps['renderLink'];\n}\n\nfunction NavLink({\n active,\n collapsed,\n context,\n href,\n icon,\n indent = 0,\n item,\n name,\n}: {\n active: boolean;\n collapsed: boolean;\n context: LinkContext;\n href: string;\n icon?: ConsoleNavItem['icon'];\n indent?: number;\n item?: ConsoleNavItem;\n name: string;\n}) {\n const shell = useConsoleShellState();\n const label = item?.label ?? name;\n const follow = () => {\n context.onNavigate?.(href);\n shell?.closeNavigation();\n };\n const linkProps: ConsoleNavLinkProps = {\n 'aria-current': active ? 'page' : undefined,\n 'aria-label': collapsed ? name : undefined,\n 'children': (\n <>\n {icon ? <Icon icon={icon} size={18} /> : null}\n {collapsed ? null : <span className={styles.itemLabel}>{label}</span>}\n {!collapsed && item?.badge ? <span className={styles.badge}>{item.badge}</span> : null}\n {collapsed && item?.badge ? <span aria-hidden className={styles.dot} /> : null}\n </>\n ),\n 'className': styles.item,\n 'data-active': active,\n 'data-collapsed': collapsed,\n 'data-indent': indent,\n 'external': item?.external,\n href,\n 'onClick': follow,\n 'title': collapsed ? undefined : label,\n };\n\n const link = context.renderLink ? (\n context.renderLink(linkProps)\n ) : (\n <a\n aria-current={linkProps['aria-current']}\n aria-label={linkProps['aria-label']}\n className={linkProps.className}\n data-active={active}\n data-collapsed={collapsed}\n data-indent={indent}\n href={href}\n rel={item?.external ? 'noreferrer' : undefined}\n target={item?.external ? '_blank' : undefined}\n title={linkProps.title}\n onClick={(event) => {\n if (context.onNavigate && !item?.external) event.preventDefault();\n follow();\n }}\n >\n {linkProps.children}\n </a>\n );\n\n if (!collapsed) return link;\n return (\n <Tooltip placement=\"right\" title={name}>\n {link}\n </Tooltip>\n );\n}\n\nfunction ConsoleNav({\n collapsed: collapsedProp,\n defaultExpanded = 'all',\n groups = [],\n items = [],\n label = 'Primary',\n onNavigate,\n pathname,\n renderLink,\n storageKey,\n}: ConsoleNavProps) {\n const id = useId();\n const navRef = useRef<HTMLDivElement>(null);\n const shell = useConsoleShellState();\n const collapsed = collapsedProp ?? shell?.collapsed ?? false;\n const reducedMotion = usePrefersReducedMotion();\n const [storedOverrides, setStoredOverrides] = useLocalStorage<unknown>(storageKey, {});\n const overrides = readOverrides(storedOverrides);\n const context: LinkContext = { onNavigate, renderLink };\n\n const activeHref = resolveActiveHref(pathname, [...items, ...collectNavItems(groups)]);\n const activeBranch = findActiveBranch(pathname, groups, activeHref);\n\n // Arriving on a page reopens its branch even if it was closed by hand earlier.\n const [trackedPathname, setTrackedPathname] = useState(pathname);\n if (trackedPathname !== pathname) {\n setTrackedPathname(pathname);\n if (activeBranch.some((key) => overrides[key] === false)) {\n const next = { ...overrides };\n for (const key of activeBranch) delete next[key];\n setStoredOverrides(next);\n }\n }\n\n const isExpanded = (group: ConsoleNavGroup) =>\n overrides[group.key] ??\n (activeBranch.includes(group.key) || (group.defaultExpanded ?? defaultExpanded === 'all'));\n\n const toggleGroup = useCallback(\n (key: string, expanded: boolean) => {\n setStoredOverrides((current: unknown) => ({ ...readOverrides(current), [key]: !expanded }));\n },\n [setStoredOverrides],\n );\n\n useEffect(() => {\n const container = navRef.current;\n if (!container) return;\n scrollActiveIntoView(container);\n if (reducedMotion) return;\n const timer = window.setTimeout(() => scrollActiveIntoView(container), PANEL_TRANSITION_MS);\n return () => window.clearTimeout(timer);\n }, [activeHref, collapsed, pathname, reducedMotion]);\n\n const renderItems = (list: ConsoleNavItem[], indent: number, groupLabel?: string) =>\n list.map((item) => (\n <NavLink\n active={item.href === activeHref}\n collapsed={false}\n context={context}\n href={item.href}\n icon={item.icon}\n indent={item.icon ? Math.max(0, indent - 1) : indent}\n item={item}\n key={item.href}\n name={groupLabel ? `${groupLabel} / ${item.label}` : item.label}\n />\n ));\n\n if (collapsed) {\n const railItems = (list: ConsoleNavItem[], groupLabel?: string) =>\n list\n .filter((item) => item.icon)\n .map((item) => (\n <NavLink\n collapsed\n active={item.href === activeHref}\n context={context}\n href={item.href}\n icon={item.icon}\n item={item}\n key={item.href}\n name={groupLabel ? `${groupLabel} / ${item.label}` : item.label}\n />\n ));\n const topRail = railItems(items);\n const iconGroups = groups.filter((group) => group.icon);\n\n return (\n <ScrollShadow\n aria-label={label}\n as={'nav'}\n className={styles.nav}\n data-collapsed=\"\"\n orientation={'vertical'}\n ref={navRef}\n size={8}\n >\n {topRail.length > 0 ? <div className={styles.railTop}>{topRail}</div> : null}\n {iconGroups.length > 0 ? (\n <div className={styles.railGroup} data-first={topRail.length === 0} role=\"group\">\n {iconGroups.map((group) => {\n const href = group.href ?? collectNavItems([group])[0]?.href;\n if (!href) return null;\n return (\n <NavLink\n collapsed\n active={activeBranch[0] === group.key}\n context={context}\n href={href}\n icon={group.icon}\n key={group.key}\n name={group.label}\n />\n );\n })}\n </div>\n ) : null}\n {groups\n .filter((group) => !group.icon)\n .map((group, index) => {\n const rail = railItems(collectNavItems([group]), group.label);\n if (rail.length === 0) return null;\n return (\n <div\n className={styles.railGroup}\n data-first={topRail.length === 0 && iconGroups.length === 0 && index === 0}\n key={group.key}\n role=\"group\"\n >\n <h2 className={styles.srOnly}>{group.label}</h2>\n {rail}\n </div>\n );\n })}\n </ScrollShadow>\n );\n }\n\n const renderGroup = (group: ConsoleNavGroup, level: number, indent: number) => {\n const expanded = isExpanded(group);\n const panelId = `${id}-${group.key}`;\n // Nested groups are headings over their items, so the items keep the same indent.\n const childIndent = indent + (group.icon ? 1 : 0);\n const active = activeBranch.includes(group.key);\n\n return (\n <div\n className={styles.group}\n data-icon={Boolean(group.icon)}\n data-level={level}\n key={group.key}\n >\n <button\n aria-controls={panelId}\n aria-expanded={expanded}\n className={styles.groupHeader}\n data-active={active}\n data-icon={Boolean(group.icon)}\n data-indent={indent}\n data-level={level}\n type=\"button\"\n onClick={() => toggleGroup(group.key, expanded)}\n >\n {group.icon ? <Icon icon={group.icon} size={16} /> : null}\n <span className={styles.itemLabel} data-label=\"\">\n {group.label}\n </span>\n {level === 0 ? (\n <Icon\n className={styles.chevron}\n data-expanded={expanded}\n icon={ChevronDown}\n size={14}\n />\n ) : (\n <span className={styles.indicator} data-expanded={expanded}>\n <Play fill={'currentColor'} size={7} strokeWidth={1} />\n </span>\n )}\n </button>\n <div\n aria-hidden={!expanded}\n className={styles.groupPanel}\n data-expanded={expanded}\n data-instant={reducedMotion}\n id={panelId}\n inert={expanded ? undefined : true}\n >\n <div className={styles.groupItems}>\n {renderItems(group.items ?? [], childIndent, group.label)}\n {(group.groups ?? []).map((child) => renderGroup(child, level + 1, childIndent))}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <ScrollShadow\n aria-label={label}\n as={'nav'}\n className={styles.nav}\n orientation={'vertical'}\n ref={navRef}\n size={4}\n >\n {items.length > 0 ? (\n <div className={styles.topItems} data-divided={groups.length > 0}>\n {renderItems(items, 0)}\n </div>\n ) : null}\n {groups.map((group) => renderGroup(group, 0, 0))}\n </ScrollShadow>\n );\n}\n\nConsoleNav.displayName = 'ConsoleNav';\n\nexport default ConsoleNav;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ConsoleNavItem } from "./type.mjs";
|
|
2
|
+
//#region src/dashboard/ConsoleNav/active.d.ts
|
|
3
|
+
/** Longest matching href wins, so `/resources/new` does not also light up `/`. */
|
|
4
|
+
declare function resolveActiveHref(pathname: string, items: readonly ConsoleNavItem[]): string;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { resolveActiveHref };
|
|
7
|
+
//# sourceMappingURL=active.d.mts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/dashboard/ConsoleNav/active.ts
|
|
2
|
+
function matchesNavPath(pathname, item) {
|
|
3
|
+
if (item.end || item.href === "/") return pathname === item.href;
|
|
4
|
+
return pathname === item.href || pathname.startsWith(`${item.href}/`);
|
|
5
|
+
}
|
|
6
|
+
/** Longest matching href wins, so `/resources/new` does not also light up `/`. */
|
|
7
|
+
function resolveActiveHref(pathname, items) {
|
|
8
|
+
return items.filter((item) => matchesNavPath(pathname, item)).sort((left, right) => right.href.length - left.href.length)[0]?.href;
|
|
9
|
+
}
|
|
10
|
+
function collectNavItems(groups) {
|
|
11
|
+
return groups.flatMap((group) => [...group.items ?? [], ...collectNavItems(group.groups ?? [])]);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Keys of the groups on the path to the active page, outermost first. A group
|
|
15
|
+
* overview page (`href`) counts as being inside that group.
|
|
16
|
+
*/
|
|
17
|
+
function findActiveBranch(pathname, groups, activeHref) {
|
|
18
|
+
for (const group of groups) {
|
|
19
|
+
if (group.href && pathname === group.href) return [group.key];
|
|
20
|
+
const nested = findActiveBranch(pathname, group.groups ?? [], activeHref);
|
|
21
|
+
if (nested.length > 0) return [group.key, ...nested];
|
|
22
|
+
if (activeHref && group.items?.some((item) => item.href === activeHref)) return [group.key];
|
|
23
|
+
}
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { collectNavItems, findActiveBranch, matchesNavPath, resolveActiveHref };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=active.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"active.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/active.ts"],"sourcesContent":["import type { ConsoleNavGroup, ConsoleNavItem } from './type';\n\nexport function matchesNavPath(pathname: string, item: Pick<ConsoleNavItem, 'end' | 'href'>) {\n if (item.end || item.href === '/') return pathname === item.href;\n return pathname === item.href || pathname.startsWith(`${item.href}/`);\n}\n\n/** Longest matching href wins, so `/resources/new` does not also light up `/`. */\nexport function resolveActiveHref(pathname: string, items: readonly ConsoleNavItem[]) {\n return items\n .filter((item) => matchesNavPath(pathname, item))\n .sort((left, right) => right.href.length - left.href.length)[0]?.href;\n}\n\nexport function collectNavItems(groups: readonly ConsoleNavGroup[]): ConsoleNavItem[] {\n return groups.flatMap((group) => [\n ...(group.items ?? []),\n ...collectNavItems(group.groups ?? []),\n ]);\n}\n\n/**\n * Keys of the groups on the path to the active page, outermost first. A group\n * overview page (`href`) counts as being inside that group.\n */\nexport function findActiveBranch(\n pathname: string,\n groups: readonly ConsoleNavGroup[],\n activeHref: string | undefined,\n): string[] {\n for (const group of groups) {\n if (group.href && pathname === group.href) return [group.key];\n const nested = findActiveBranch(pathname, group.groups ?? [], activeHref);\n if (nested.length > 0) return [group.key, ...nested];\n if (activeHref && group.items?.some((item) => item.href === activeHref)) return [group.key];\n }\n return [];\n}\n"],"mappings":";AAEA,SAAgB,eAAe,UAAkB,MAA4C;CAC3F,IAAI,KAAK,OAAO,KAAK,SAAS,KAAK,OAAO,aAAa,KAAK;CAC5D,OAAO,aAAa,KAAK,QAAQ,SAAS,WAAW,GAAG,KAAK,KAAK,EAAE;AACtE;;AAGA,SAAgB,kBAAkB,UAAkB,OAAkC;CACpF,OAAO,MACJ,QAAQ,SAAS,eAAe,UAAU,IAAI,CAAC,CAAC,CAChD,MAAM,MAAM,UAAU,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAAC,EAAE,EAAE;AACrE;AAEA,SAAgB,gBAAgB,QAAsD;CACpF,OAAO,OAAO,SAAS,UAAU,CAC/B,GAAI,MAAM,SAAS,CAAC,GACpB,GAAG,gBAAgB,MAAM,UAAU,CAAC,CAAC,CACvC,CAAC;AACH;;;;;AAMA,SAAgB,iBACd,UACA,QACA,YACU;CACV,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,MAAM,QAAQ,aAAa,MAAM,MAAM,OAAO,CAAC,MAAM,GAAG;EAC5D,MAAM,SAAS,iBAAiB,UAAU,MAAM,UAAU,CAAC,GAAG,UAAU;EACxE,IAAI,OAAO,SAAS,GAAG,OAAO,CAAC,MAAM,KAAK,GAAG,MAAM;EACnD,IAAI,cAAc,MAAM,OAAO,MAAM,SAAS,KAAK,SAAS,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG;CAC5F;CACA,OAAO,CAAC;AACV"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps } from "./type.mjs";
|
|
2
|
+
import { resolveActiveHref } from "./active.mjs";
|
|
3
|
+
import ConsoleNav from "./ConsoleNav.mjs";
|
|
4
|
+
export { type ConsoleNavGroup, type ConsoleNavItem, type ConsoleNavProps, ConsoleNav as default, resolveActiveHref };
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { createStaticStyles } from "antd-style";
|
|
2
|
+
//#region src/dashboard/ConsoleNav/style.ts
|
|
3
|
+
const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
|
|
4
|
+
badge: css`
|
|
5
|
+
flex: none;
|
|
6
|
+
|
|
7
|
+
min-inline-size: 20px;
|
|
8
|
+
padding-inline: 6px;
|
|
9
|
+
border-radius: 999px;
|
|
10
|
+
|
|
11
|
+
font-size: ${cssVar.fontSizeSM};
|
|
12
|
+
font-variant-numeric: tabular-nums;
|
|
13
|
+
color: ${cssVar.colorError};
|
|
14
|
+
text-align: center;
|
|
15
|
+
|
|
16
|
+
background: color-mix(in srgb, ${cssVar.colorError} 12%, transparent);
|
|
17
|
+
`,
|
|
18
|
+
chevron: css`
|
|
19
|
+
flex: none;
|
|
20
|
+
transition: transform 160ms ease;
|
|
21
|
+
|
|
22
|
+
&[data-expanded='false'] {
|
|
23
|
+
transform: rotate(-90deg);
|
|
24
|
+
}
|
|
25
|
+
`,
|
|
26
|
+
indicator: css`
|
|
27
|
+
display: flex;
|
|
28
|
+
flex: none;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
|
|
32
|
+
width: 18px;
|
|
33
|
+
height: 18px;
|
|
34
|
+
margin-inline-start: -6px;
|
|
35
|
+
|
|
36
|
+
color: ${cssVar.colorTextDescription};
|
|
37
|
+
|
|
38
|
+
transition: transform 160ms ease;
|
|
39
|
+
|
|
40
|
+
&[data-expanded='true'] {
|
|
41
|
+
transform: rotate(90deg);
|
|
42
|
+
}
|
|
43
|
+
`,
|
|
44
|
+
dot: css`
|
|
45
|
+
position: absolute;
|
|
46
|
+
inset-block-start: 7px;
|
|
47
|
+
inset-inline-end: 9px;
|
|
48
|
+
|
|
49
|
+
inline-size: 7px;
|
|
50
|
+
block-size: 7px;
|
|
51
|
+
border-radius: 999px;
|
|
52
|
+
|
|
53
|
+
background: ${cssVar.colorError};
|
|
54
|
+
`,
|
|
55
|
+
group: css`
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
margin-block-start: 12px;
|
|
59
|
+
|
|
60
|
+
&[data-level='0'][data-icon='true'] {
|
|
61
|
+
margin-block-start: 2px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&:not([data-level='0']) {
|
|
65
|
+
margin-block-start: 6px;
|
|
66
|
+
}
|
|
67
|
+
`,
|
|
68
|
+
groupHeader: css`
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
|
|
71
|
+
display: flex;
|
|
72
|
+
gap: 8px;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: space-between;
|
|
75
|
+
|
|
76
|
+
min-block-size: 32px;
|
|
77
|
+
padding-inline: 10px;
|
|
78
|
+
border: none;
|
|
79
|
+
border-radius: ${cssVar.borderRadius};
|
|
80
|
+
|
|
81
|
+
font-size: ${cssVar.fontSizeSM};
|
|
82
|
+
font-weight: 500;
|
|
83
|
+
color: ${cssVar.colorTextSecondary};
|
|
84
|
+
text-align: start;
|
|
85
|
+
|
|
86
|
+
background: none;
|
|
87
|
+
|
|
88
|
+
&:hover,
|
|
89
|
+
&[data-active='true'] {
|
|
90
|
+
color: ${cssVar.colorText};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&[data-icon='true'] {
|
|
94
|
+
gap: 12px;
|
|
95
|
+
justify-content: flex-start;
|
|
96
|
+
min-block-size: 36px;
|
|
97
|
+
font-size: ${cssVar.fontSize};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&[data-level='0'][data-icon='true']:hover {
|
|
101
|
+
background: ${cssVar.colorFillTertiary};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Nested groups read as quiet subheadings with the indicator right after the label. */
|
|
105
|
+
&:not([data-level='0']) {
|
|
106
|
+
gap: 8px;
|
|
107
|
+
justify-content: flex-start;
|
|
108
|
+
|
|
109
|
+
min-block-size: 26px;
|
|
110
|
+
|
|
111
|
+
font-size: ${cssVar.fontSizeSM};
|
|
112
|
+
font-weight: 400;
|
|
113
|
+
color: ${cssVar.colorTextDescription};
|
|
114
|
+
|
|
115
|
+
> [data-label] {
|
|
116
|
+
flex: 0 1 auto;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&:hover,
|
|
120
|
+
&[data-active='true'] {
|
|
121
|
+
color: ${cssVar.colorTextSecondary};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&[data-indent='1'] {
|
|
126
|
+
padding-inline-start: 38px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
&[data-indent='2'] {
|
|
130
|
+
padding-inline-start: 56px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
> [role='img'] {
|
|
134
|
+
display: flex;
|
|
135
|
+
flex: none;
|
|
136
|
+
}
|
|
137
|
+
`,
|
|
138
|
+
groupItems: css`
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
gap: 2px;
|
|
142
|
+
min-block-size: 0;
|
|
143
|
+
`,
|
|
144
|
+
groupPanel: css`
|
|
145
|
+
display: grid;
|
|
146
|
+
grid-template-rows: 1fr;
|
|
147
|
+
transition: grid-template-rows 160ms ease;
|
|
148
|
+
|
|
149
|
+
> div {
|
|
150
|
+
overflow: hidden;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
&[data-expanded='false'] {
|
|
154
|
+
grid-template-rows: 0fr;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
&[data-instant='true'] {
|
|
158
|
+
transition: none;
|
|
159
|
+
}
|
|
160
|
+
`,
|
|
161
|
+
item: css`
|
|
162
|
+
position: relative;
|
|
163
|
+
|
|
164
|
+
display: flex;
|
|
165
|
+
gap: 10px;
|
|
166
|
+
align-items: center;
|
|
167
|
+
|
|
168
|
+
min-block-size: 36px;
|
|
169
|
+
padding-inline: 10px;
|
|
170
|
+
border-radius: ${cssVar.borderRadius};
|
|
171
|
+
|
|
172
|
+
color: ${cssVar.colorTextSecondary};
|
|
173
|
+
text-decoration: none;
|
|
174
|
+
|
|
175
|
+
transition:
|
|
176
|
+
background 120ms ease,
|
|
177
|
+
color 120ms ease;
|
|
178
|
+
|
|
179
|
+
&:hover {
|
|
180
|
+
color: ${cssVar.colorText};
|
|
181
|
+
background: ${cssVar.colorFillTertiary};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
&[data-active='true'] {
|
|
185
|
+
font-weight: 500;
|
|
186
|
+
color: ${cssVar.colorText};
|
|
187
|
+
background: ${cssVar.colorFillSecondary};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
&[data-indent='1'],
|
|
191
|
+
&[data-indent='2'] {
|
|
192
|
+
min-block-size: 32px;
|
|
193
|
+
color: ${cssVar.colorText};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
&[data-indent='1'] {
|
|
197
|
+
padding-inline-start: 38px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
&[data-indent='2'] {
|
|
201
|
+
padding-inline-start: 56px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
> [role='img'] {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex: none;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
&[data-collapsed='true'] {
|
|
210
|
+
justify-content: center;
|
|
211
|
+
min-block-size: 40px;
|
|
212
|
+
padding-inline: 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
${responsive.mobile} {
|
|
216
|
+
min-block-size: 44px;
|
|
217
|
+
}
|
|
218
|
+
`,
|
|
219
|
+
itemLabel: css`
|
|
220
|
+
overflow: hidden;
|
|
221
|
+
flex: 1;
|
|
222
|
+
text-overflow: ellipsis;
|
|
223
|
+
white-space: nowrap;
|
|
224
|
+
`,
|
|
225
|
+
nav: css`
|
|
226
|
+
scrollbar-width: thin;
|
|
227
|
+
|
|
228
|
+
display: flex;
|
|
229
|
+
flex: 1;
|
|
230
|
+
flex-direction: column;
|
|
231
|
+
gap: 2px;
|
|
232
|
+
|
|
233
|
+
min-block-size: 0;
|
|
234
|
+
padding-block-end: 12px;
|
|
235
|
+
padding-inline: 8px;
|
|
236
|
+
`,
|
|
237
|
+
railGroup: css`
|
|
238
|
+
display: flex;
|
|
239
|
+
flex-direction: column;
|
|
240
|
+
gap: 2px;
|
|
241
|
+
|
|
242
|
+
margin-block-start: 6px;
|
|
243
|
+
padding-block-start: 6px;
|
|
244
|
+
border-block-start: 1px solid ${cssVar.colorBorderSecondary};
|
|
245
|
+
|
|
246
|
+
&[data-first='true'] {
|
|
247
|
+
margin-block-start: 0;
|
|
248
|
+
border-block-start: none;
|
|
249
|
+
}
|
|
250
|
+
`,
|
|
251
|
+
railTop: css`
|
|
252
|
+
display: flex;
|
|
253
|
+
flex-direction: column;
|
|
254
|
+
gap: 2px;
|
|
255
|
+
`,
|
|
256
|
+
topItems: css`
|
|
257
|
+
display: flex;
|
|
258
|
+
flex-direction: column;
|
|
259
|
+
gap: 2px;
|
|
260
|
+
|
|
261
|
+
&[data-divided='true'] {
|
|
262
|
+
margin-block-end: 6px;
|
|
263
|
+
padding-block-end: 8px;
|
|
264
|
+
border-block-end: 1px solid ${cssVar.colorBorderSecondary};
|
|
265
|
+
}
|
|
266
|
+
`,
|
|
267
|
+
srOnly: css`
|
|
268
|
+
position: absolute;
|
|
269
|
+
|
|
270
|
+
overflow: hidden;
|
|
271
|
+
|
|
272
|
+
inline-size: 1px;
|
|
273
|
+
block-size: 1px;
|
|
274
|
+
|
|
275
|
+
white-space: nowrap;
|
|
276
|
+
|
|
277
|
+
clip-path: inset(50%);
|
|
278
|
+
`
|
|
279
|
+
}));
|
|
280
|
+
//#endregion
|
|
281
|
+
export { styles };
|
|
282
|
+
|
|
283
|
+
//# sourceMappingURL=style.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => ({\n badge: css`\n flex: none;\n\n min-inline-size: 20px;\n padding-inline: 6px;\n border-radius: 999px;\n\n font-size: ${cssVar.fontSizeSM};\n font-variant-numeric: tabular-nums;\n color: ${cssVar.colorError};\n text-align: center;\n\n background: color-mix(in srgb, ${cssVar.colorError} 12%, transparent);\n `,\n chevron: css`\n flex: none;\n transition: transform 160ms ease;\n\n &[data-expanded='false'] {\n transform: rotate(-90deg);\n }\n `,\n indicator: css`\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n\n width: 18px;\n height: 18px;\n margin-inline-start: -6px;\n\n color: ${cssVar.colorTextDescription};\n\n transition: transform 160ms ease;\n\n &[data-expanded='true'] {\n transform: rotate(90deg);\n }\n `,\n dot: css`\n position: absolute;\n inset-block-start: 7px;\n inset-inline-end: 9px;\n\n inline-size: 7px;\n block-size: 7px;\n border-radius: 999px;\n\n background: ${cssVar.colorError};\n `,\n group: css`\n display: flex;\n flex-direction: column;\n margin-block-start: 12px;\n\n &[data-level='0'][data-icon='true'] {\n margin-block-start: 2px;\n }\n\n &:not([data-level='0']) {\n margin-block-start: 6px;\n }\n `,\n groupHeader: css`\n cursor: pointer;\n\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: space-between;\n\n min-block-size: 32px;\n padding-inline: 10px;\n border: none;\n border-radius: ${cssVar.borderRadius};\n\n font-size: ${cssVar.fontSizeSM};\n font-weight: 500;\n color: ${cssVar.colorTextSecondary};\n text-align: start;\n\n background: none;\n\n &:hover,\n &[data-active='true'] {\n color: ${cssVar.colorText};\n }\n\n &[data-icon='true'] {\n gap: 12px;\n justify-content: flex-start;\n min-block-size: 36px;\n font-size: ${cssVar.fontSize};\n }\n\n &[data-level='0'][data-icon='true']:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n /* Nested groups read as quiet subheadings with the indicator right after the label. */\n &:not([data-level='0']) {\n gap: 8px;\n justify-content: flex-start;\n\n min-block-size: 26px;\n\n font-size: ${cssVar.fontSizeSM};\n font-weight: 400;\n color: ${cssVar.colorTextDescription};\n\n > [data-label] {\n flex: 0 1 auto;\n }\n\n &:hover,\n &[data-active='true'] {\n color: ${cssVar.colorTextSecondary};\n }\n }\n\n &[data-indent='1'] {\n padding-inline-start: 38px;\n }\n\n &[data-indent='2'] {\n padding-inline-start: 56px;\n }\n\n > [role='img'] {\n display: flex;\n flex: none;\n }\n `,\n groupItems: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-block-size: 0;\n `,\n groupPanel: css`\n display: grid;\n grid-template-rows: 1fr;\n transition: grid-template-rows 160ms ease;\n\n > div {\n overflow: hidden;\n }\n\n &[data-expanded='false'] {\n grid-template-rows: 0fr;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n `,\n item: css`\n position: relative;\n\n display: flex;\n gap: 10px;\n align-items: center;\n\n min-block-size: 36px;\n padding-inline: 10px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorTextSecondary};\n text-decoration: none;\n\n transition:\n background 120ms ease,\n color 120ms ease;\n\n &:hover {\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-active='true'] {\n font-weight: 500;\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-indent='1'],\n &[data-indent='2'] {\n min-block-size: 32px;\n color: ${cssVar.colorText};\n }\n\n &[data-indent='1'] {\n padding-inline-start: 38px;\n }\n\n &[data-indent='2'] {\n padding-inline-start: 56px;\n }\n\n > [role='img'] {\n display: flex;\n flex: none;\n }\n\n &[data-collapsed='true'] {\n justify-content: center;\n min-block-size: 40px;\n padding-inline: 0;\n }\n\n ${responsive.mobile} {\n min-block-size: 44px;\n }\n `,\n itemLabel: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n nav: css`\n scrollbar-width: thin;\n\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 2px;\n\n min-block-size: 0;\n padding-block-end: 12px;\n padding-inline: 8px;\n `,\n railGroup: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n\n margin-block-start: 6px;\n padding-block-start: 6px;\n border-block-start: 1px solid ${cssVar.colorBorderSecondary};\n\n &[data-first='true'] {\n margin-block-start: 0;\n border-block-start: none;\n }\n `,\n railTop: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n `,\n topItems: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n\n &[data-divided='true'] {\n margin-block-end: 6px;\n padding-block-end: 8px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n }\n `,\n srOnly: css`\n position: absolute;\n\n overflow: hidden;\n\n inline-size: 1px;\n block-size: 1px;\n\n white-space: nowrap;\n\n clip-path: inset(50%);\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,kBAAkB;CACzE,OAAO,GAAG;;;;;;;iBAOK,OAAO,WAAW;;aAEtB,OAAO,WAAW;;;qCAGM,OAAO,WAAW;;CAErD,SAAS,GAAG;;;;;;;;CAQZ,WAAW,GAAG;;;;;;;;;;aAUH,OAAO,qBAAqB;;;;;;;;CAQvC,KAAK,GAAG;;;;;;;;;kBASQ,OAAO,WAAW;;CAElC,OAAO,GAAG;;;;;;;;;;;;;CAaV,aAAa,GAAG;;;;;;;;;;;qBAWG,OAAO,aAAa;;iBAExB,OAAO,WAAW;;aAEtB,OAAO,mBAAmB;;;;;;;eAOxB,OAAO,UAAU;;;;;;;mBAOb,OAAO,SAAS;;;;oBAIf,OAAO,kBAAkB;;;;;;;;;;mBAU1B,OAAO,WAAW;;eAEtB,OAAO,qBAAqB;;;;;;;;iBAQ1B,OAAO,mBAAmB;;;;;;;;;;;;;;;;;CAiBzC,YAAY,GAAG;;;;;;CAMf,YAAY,GAAG;;;;;;;;;;;;;;;;;CAiBf,MAAM,GAAG;;;;;;;;;qBASU,OAAO,aAAa;;aAE5B,OAAO,mBAAmB;;;;;;;;eAQxB,OAAO,UAAU;oBACZ,OAAO,kBAAkB;;;;;eAK9B,OAAO,UAAU;oBACZ,OAAO,mBAAmB;;;;;;eAM/B,OAAO,UAAU;;;;;;;;;;;;;;;;;;;;;;MAsB1B,WAAW,OAAO;;;;CAItB,WAAW,GAAG;;;;;;CAMd,KAAK,GAAG;;;;;;;;;;;;CAYR,WAAW,GAAG;;;;;;;oCAOoB,OAAO,qBAAqB;;;;;;;CAO9D,SAAS,GAAG;;;;;CAKZ,UAAU,GAAG;;;;;;;;oCAQqB,OAAO,qBAAqB;;;CAG9D,QAAQ,GAAG;;;;;;;;;;;;AAYb,EAAE"}
|