@umodeapporg/ui 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/umode-ui.css +148 -0
- package/dist/components/Shell/AppHeader.d.ts +19 -0
- package/dist/components/Shell/AppHeader.js +64 -0
- package/dist/components/Shell/AppHeader.js.map +1 -0
- package/dist/components/Shell/AppShell.d.ts +20 -0
- package/dist/components/Shell/AppShell.js +100 -0
- package/dist/components/Shell/AppShell.js.map +1 -0
- package/dist/components/Shell/AppSidebar.d.ts +15 -0
- package/dist/components/Shell/AppSidebar.js +63 -0
- package/dist/components/Shell/AppSidebar.js.map +1 -0
- package/dist/components/Shell/LanguageToggle.d.ts +8 -0
- package/dist/components/Shell/LanguageToggle.js +59 -0
- package/dist/components/Shell/LanguageToggle.js.map +1 -0
- package/dist/components/Shell/SidebarMenu.d.ts +24 -0
- package/dist/components/Shell/SidebarMenu.js +204 -0
- package/dist/components/Shell/SidebarMenu.js.map +1 -0
- package/dist/components/Shell/ThemeToggle.d.ts +11 -0
- package/dist/components/Shell/ThemeToggle.js +55 -0
- package/dist/components/Shell/ThemeToggle.js.map +1 -0
- package/dist/components/Shell/headerControlStyles.d.ts +10 -0
- package/dist/components/Shell/headerControlStyles.js +11 -0
- package/dist/components/Shell/headerControlStyles.js.map +1 -0
- package/dist/components/Shell/useSidebarState.d.ts +14 -0
- package/dist/components/Shell/useSidebarState.js +106 -0
- package/dist/components/Shell/useSidebarState.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +44 -36
- package/dist/index.js.map +1 -1
- package/dist/locales/en/ui.json.d.ts +21 -0
- package/dist/locales/en/ui.json.js +9 -0
- package/dist/locales/en/ui.json.js.map +1 -1
- package/dist/locales/index.d.ts +42 -0
- package/dist/locales/pt/ui.json.d.ts +21 -0
- package/dist/locales/pt/ui.json.js +9 -0
- package/dist/locales/pt/ui.json.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/styles/base.css +14 -2
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef, useEffect } from "react";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import ControlledButton from "../Form/ControlledButton.js";
|
|
6
|
+
import { useUiNavigation } from "../Navigation/UiNavigationContext.js";
|
|
7
|
+
import { MaterialSymbol } from "../UI/MaterialSymbol/index.js";
|
|
8
|
+
const resolveSidebarItemId = (item) => item.id ?? `${item.to}:${item.text}`;
|
|
9
|
+
const matchesRoute = (location, target, end = false) => {
|
|
10
|
+
if (!target || target === "#") return false;
|
|
11
|
+
if (target.includes("?")) {
|
|
12
|
+
const [pathPart, queryPart] = target.split("?");
|
|
13
|
+
const samePath = end ? location.pathname === pathPart : location.pathname === pathPart || location.pathname.startsWith(`${pathPart}/`);
|
|
14
|
+
if (!samePath) return false;
|
|
15
|
+
const currentParams = new URLSearchParams(location.search);
|
|
16
|
+
const expectedParams = new URLSearchParams(queryPart);
|
|
17
|
+
return Array.from(expectedParams.entries()).every(([key, value]) => currentParams.get(key) === value);
|
|
18
|
+
}
|
|
19
|
+
return end ? location.pathname === target : location.pathname === target || location.pathname.startsWith(`${target}/`);
|
|
20
|
+
};
|
|
21
|
+
const containsActiveRoute = (item, location) => item.children?.length ? item.children.some((child) => containsActiveRoute(child, location)) : matchesRoute(location, item.to, item.end);
|
|
22
|
+
const SidebarMenuRow = ({
|
|
23
|
+
item,
|
|
24
|
+
isOpen,
|
|
25
|
+
collapsed,
|
|
26
|
+
onToggle,
|
|
27
|
+
activeClass,
|
|
28
|
+
activeIconClass,
|
|
29
|
+
onNavigate,
|
|
30
|
+
level
|
|
31
|
+
}) => {
|
|
32
|
+
const { location, Link: NavigationLink } = useUiNavigation();
|
|
33
|
+
const contentRef = useRef(null);
|
|
34
|
+
const [maxHeight, setMaxHeight] = useState("0px");
|
|
35
|
+
const hasChildren = Boolean(item.children?.length);
|
|
36
|
+
const isActive = hasChildren ? containsActiveRoute(item, location) : matchesRoute(location, item.to, item.end);
|
|
37
|
+
const submenuOpen = isOpen && !collapsed;
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const content = contentRef.current;
|
|
40
|
+
if (!content) return;
|
|
41
|
+
if (!submenuOpen) {
|
|
42
|
+
setMaxHeight("0px");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const updateHeight = () => setMaxHeight(`${content.scrollHeight}px`);
|
|
46
|
+
updateHeight();
|
|
47
|
+
const observer = new ResizeObserver(updateHeight);
|
|
48
|
+
observer.observe(content);
|
|
49
|
+
return () => observer.disconnect();
|
|
50
|
+
}, [submenuOpen]);
|
|
51
|
+
const rowClassName = classNames(
|
|
52
|
+
"relative flex h-9 w-full items-center gap-x-3 rounded-lg px-3 text-left transition-colors duration-base",
|
|
53
|
+
isActive ? activeClass : "text-foreground-muted hover:bg-muted-hover hover:text-foreground"
|
|
54
|
+
);
|
|
55
|
+
const iconClassName = classNames(
|
|
56
|
+
"shrink-0",
|
|
57
|
+
isActive ? activeIconClass ?? "text-brand-emphasis" : "text-foreground-muted"
|
|
58
|
+
);
|
|
59
|
+
const activeBar = isActive ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute left-0 top-1/2 h-5 w-0.5 -translate-y-1/2 rounded-full bg-brand" }) : null;
|
|
60
|
+
const icon = /* @__PURE__ */ jsx(MaterialSymbol, { icon: item.icon, size: 20, weight: item.weight || 400, className: iconClassName });
|
|
61
|
+
const label = /* @__PURE__ */ jsx("span", { className: classNames("sidebar-label text-sm", { "is-collapsed": collapsed }), children: item.text });
|
|
62
|
+
if (item.externalUrl) {
|
|
63
|
+
return /* @__PURE__ */ jsx("li", { className: "flex flex-col", children: /* @__PURE__ */ jsxs(
|
|
64
|
+
"a",
|
|
65
|
+
{
|
|
66
|
+
href: item.externalUrl,
|
|
67
|
+
target: "_blank",
|
|
68
|
+
rel: "noopener noreferrer",
|
|
69
|
+
className: rowClassName,
|
|
70
|
+
onClick: onNavigate,
|
|
71
|
+
children: [
|
|
72
|
+
activeBar,
|
|
73
|
+
icon,
|
|
74
|
+
label
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
) });
|
|
78
|
+
}
|
|
79
|
+
if (hasChildren) {
|
|
80
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex flex-col", children: [
|
|
81
|
+
/* @__PURE__ */ jsxs(ControlledButton, { defaultHtmlButton: true, onClick: onToggle, "aria-expanded": submenuOpen, className: rowClassName, children: [
|
|
82
|
+
activeBar,
|
|
83
|
+
icon,
|
|
84
|
+
label,
|
|
85
|
+
/* @__PURE__ */ jsx(
|
|
86
|
+
MaterialSymbol,
|
|
87
|
+
{
|
|
88
|
+
icon: "chevron_right",
|
|
89
|
+
size: 18,
|
|
90
|
+
className: classNames("sidebar-chevron ml-auto shrink-0 text-foreground-subtle", {
|
|
91
|
+
"is-collapsed": collapsed,
|
|
92
|
+
"is-open": submenuOpen
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
] }),
|
|
97
|
+
/* @__PURE__ */ jsx("div", { style: { maxHeight }, className: classNames("sidebar-submenu", { "mt-1": submenuOpen }), children: /* @__PURE__ */ jsx("div", { ref: contentRef, className: "pl-5", children: /* @__PURE__ */ jsx(
|
|
98
|
+
SidebarMenu,
|
|
99
|
+
{
|
|
100
|
+
items: item.children ?? [],
|
|
101
|
+
collapsed,
|
|
102
|
+
activeClass,
|
|
103
|
+
activeIconClass,
|
|
104
|
+
onNavigate,
|
|
105
|
+
level: level + 1
|
|
106
|
+
}
|
|
107
|
+
) }) })
|
|
108
|
+
] });
|
|
109
|
+
}
|
|
110
|
+
return /* @__PURE__ */ jsx("li", { className: "flex flex-col", children: /* @__PURE__ */ jsxs(NavigationLink, { to: item.to, className: rowClassName, onClick: onNavigate, children: [
|
|
111
|
+
activeBar,
|
|
112
|
+
icon,
|
|
113
|
+
label
|
|
114
|
+
] }) });
|
|
115
|
+
};
|
|
116
|
+
const SECTION_LABEL_KEYS = {
|
|
117
|
+
management: "sidebar.sections.management",
|
|
118
|
+
registration: "sidebar.sections.registration"
|
|
119
|
+
};
|
|
120
|
+
const SidebarSectionHeader = ({ section, collapsed, withDivider }) => {
|
|
121
|
+
const { t } = useTranslation("ui");
|
|
122
|
+
if (collapsed) {
|
|
123
|
+
if (!withDivider) return null;
|
|
124
|
+
return /* @__PURE__ */ jsx("li", { "aria-hidden": true, className: "flex flex-col px-3", children: /* @__PURE__ */ jsx("span", { className: "border-t border-border/70" }) });
|
|
125
|
+
}
|
|
126
|
+
return /* @__PURE__ */ jsxs("li", { className: classNames("flex flex-col", withDivider ? "mt-2" : "mt-1"), children: [
|
|
127
|
+
withDivider && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mx-3 mb-2 border-t border-border/70" }),
|
|
128
|
+
/* @__PURE__ */ jsx("span", { className: "px-3 pb-0.5 text-xxs font-semibold uppercase tracking-wide text-foreground-subtle", children: t(SECTION_LABEL_KEYS[section]) })
|
|
129
|
+
] });
|
|
130
|
+
};
|
|
131
|
+
const SECTION_ORDER = ["management", "registration"];
|
|
132
|
+
const groupItemsBySection = (items) => {
|
|
133
|
+
const itemsWithoutSection = (items ?? []).filter((item) => !item.section);
|
|
134
|
+
const sectionGroups = SECTION_ORDER.map((section) => ({
|
|
135
|
+
section,
|
|
136
|
+
items: (items ?? []).filter((item) => item.section === section)
|
|
137
|
+
})).filter((group) => group.items.length > 0);
|
|
138
|
+
return itemsWithoutSection.length ? [{ section: null, items: itemsWithoutSection }, ...sectionGroups] : sectionGroups;
|
|
139
|
+
};
|
|
140
|
+
const SidebarMenu = ({
|
|
141
|
+
items,
|
|
142
|
+
activeClass,
|
|
143
|
+
collapsed,
|
|
144
|
+
activeIconClass,
|
|
145
|
+
onNavigate,
|
|
146
|
+
level = 0
|
|
147
|
+
}) => {
|
|
148
|
+
const { location } = useUiNavigation();
|
|
149
|
+
const activeKey = items.filter((item) => Boolean(item.children?.length) && containsActiveRoute(item, location)).map(resolveSidebarItemId)[0] ?? null;
|
|
150
|
+
const [openKey, setOpenKey] = useState(activeKey);
|
|
151
|
+
const previousActiveKey = useRef(activeKey);
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (activeKey && activeKey !== previousActiveKey.current) {
|
|
154
|
+
setOpenKey(activeKey);
|
|
155
|
+
}
|
|
156
|
+
previousActiveKey.current = activeKey;
|
|
157
|
+
}, [activeKey]);
|
|
158
|
+
const handleToggle = (key) => {
|
|
159
|
+
setOpenKey((current) => current === key ? null : key);
|
|
160
|
+
};
|
|
161
|
+
const showSections = level === 0;
|
|
162
|
+
const groups = showSections ? groupItemsBySection(items) : [{ section: null, items: items ?? [] }];
|
|
163
|
+
return /* @__PURE__ */ jsx("ul", { className: classNames("flex flex-col", level === 0 ? "gap-y-2" : "gap-y-1"), children: groups.flatMap((group, groupIndex) => {
|
|
164
|
+
const rows = [];
|
|
165
|
+
if (group.section) {
|
|
166
|
+
rows.push(
|
|
167
|
+
/* @__PURE__ */ jsx(
|
|
168
|
+
SidebarSectionHeader,
|
|
169
|
+
{
|
|
170
|
+
section: group.section,
|
|
171
|
+
collapsed,
|
|
172
|
+
withDivider: groupIndex > 0
|
|
173
|
+
},
|
|
174
|
+
`section-${group.section}`
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
group.items.forEach((item) => {
|
|
179
|
+
const itemId = resolveSidebarItemId(item);
|
|
180
|
+
rows.push(
|
|
181
|
+
/* @__PURE__ */ jsx(
|
|
182
|
+
SidebarMenuRow,
|
|
183
|
+
{
|
|
184
|
+
item,
|
|
185
|
+
isOpen: openKey === itemId,
|
|
186
|
+
collapsed,
|
|
187
|
+
onToggle: () => handleToggle(itemId),
|
|
188
|
+
activeClass,
|
|
189
|
+
activeIconClass,
|
|
190
|
+
onNavigate,
|
|
191
|
+
level
|
|
192
|
+
},
|
|
193
|
+
itemId
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
return rows;
|
|
198
|
+
}) });
|
|
199
|
+
};
|
|
200
|
+
export {
|
|
201
|
+
SidebarMenu as default,
|
|
202
|
+
resolveSidebarItemId
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=SidebarMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SidebarMenu.js","sources":["../../../src/components/Shell/SidebarMenu.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport classNames from 'classnames';\nimport { useTranslation } from 'react-i18next';\n\nimport ControlledButton from '@/components/Form/ControlledButton';\nimport { useUiNavigation } from '@/components/Navigation/UiNavigationContext';\nimport { MaterialSymbol, MaterialSymbolWeight, SymbolCodepoints } from '@/components/UI/MaterialSymbol';\n\nexport type TUiSidebarSection = 'management' | 'registration';\n\nexport interface ISidebarMenuItem {\n id?: string;\n weight?: MaterialSymbolWeight;\n icon: SymbolCodepoints;\n text: string;\n to: string;\n externalUrl?: string;\n end?: boolean;\n section?: TUiSidebarSection;\n children?: Array<ISidebarMenuItem>;\n}\n\nexport const resolveSidebarItemId = (item: ISidebarMenuItem): string => item.id ?? `${item.to}:${item.text}`;\n\ninterface ISidebarLocation {\n pathname: string;\n search: string;\n}\n\ninterface ISidebarMenuProps {\n items: Array<ISidebarMenuItem>;\n activeClass: string;\n collapsed: boolean;\n activeIconClass?: string;\n onNavigate?: () => void;\n level?: number;\n}\n\nconst matchesRoute = (location: ISidebarLocation, target: string, end = false): boolean => {\n if (!target || target === '#') return false;\n\n if (target.includes('?')) {\n const [pathPart, queryPart] = target.split('?');\n const samePath = end\n ? location.pathname === pathPart\n : location.pathname === pathPart || location.pathname.startsWith(`${pathPart}/`);\n if (!samePath) return false;\n\n const currentParams = new URLSearchParams(location.search);\n const expectedParams = new URLSearchParams(queryPart);\n\n return Array.from(expectedParams.entries()).every(([key, value]) => currentParams.get(key) === value);\n }\n\n return end\n ? location.pathname === target\n : location.pathname === target || location.pathname.startsWith(`${target}/`);\n};\n\nconst containsActiveRoute = (item: ISidebarMenuItem, location: ISidebarLocation): boolean =>\n item.children?.length\n ? item.children.some((child) => containsActiveRoute(child, location))\n : matchesRoute(location, item.to, item.end);\n\ninterface ISidebarMenuRowProps {\n item: ISidebarMenuItem;\n isOpen: boolean;\n collapsed: boolean;\n onToggle: () => void;\n activeClass: string;\n activeIconClass?: string;\n onNavigate?: () => void;\n level: number;\n}\n\nconst SidebarMenuRow: React.FC<ISidebarMenuRowProps> = ({\n item,\n isOpen,\n collapsed,\n onToggle,\n activeClass,\n activeIconClass,\n onNavigate,\n level,\n}) => {\n const { location, Link: NavigationLink } = useUiNavigation();\n const contentRef = useRef<HTMLDivElement>(null);\n const [maxHeight, setMaxHeight] = useState('0px');\n\n const hasChildren = Boolean(item.children?.length);\n const isActive = hasChildren ? containsActiveRoute(item, location) : matchesRoute(location, item.to, item.end);\n const submenuOpen = isOpen && !collapsed;\n\n useEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n\n if (!submenuOpen) {\n setMaxHeight('0px');\n return;\n }\n\n const updateHeight = () => setMaxHeight(`${content.scrollHeight}px`);\n updateHeight();\n\n const observer = new ResizeObserver(updateHeight);\n observer.observe(content);\n\n return () => observer.disconnect();\n }, [submenuOpen]);\n\n const rowClassName = classNames(\n 'relative flex h-9 w-full items-center gap-x-3 rounded-lg px-3 text-left transition-colors duration-base',\n isActive ? activeClass : 'text-foreground-muted hover:bg-muted-hover hover:text-foreground',\n );\n\n const iconClassName = classNames(\n 'shrink-0',\n isActive ? (activeIconClass ?? 'text-brand-emphasis') : 'text-foreground-muted',\n );\n\n const activeBar = isActive ? (\n <span aria-hidden className=\"absolute left-0 top-1/2 h-5 w-0.5 -translate-y-1/2 rounded-full bg-brand\" />\n ) : null;\n\n const icon = <MaterialSymbol icon={item.icon} size={20} weight={item.weight || 400} className={iconClassName} />;\n const label = <span className={classNames('sidebar-label text-sm', { 'is-collapsed': collapsed })}>{item.text}</span>;\n\n if (item.externalUrl) {\n return (\n <li className=\"flex flex-col\">\n <a\n href={item.externalUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={rowClassName}\n onClick={onNavigate}\n >\n {activeBar}\n {icon}\n {label}\n </a>\n </li>\n );\n }\n\n if (hasChildren) {\n return (\n <li className=\"flex flex-col\">\n <ControlledButton defaultHtmlButton onClick={onToggle} aria-expanded={submenuOpen} className={rowClassName}>\n {activeBar}\n {icon}\n {label}\n <MaterialSymbol\n icon=\"chevron_right\"\n size={18}\n className={classNames('sidebar-chevron ml-auto shrink-0 text-foreground-subtle', {\n 'is-collapsed': collapsed,\n 'is-open': submenuOpen,\n })}\n />\n </ControlledButton>\n\n <div style={{ maxHeight }} className={classNames('sidebar-submenu', { 'mt-1': submenuOpen })}>\n <div ref={contentRef} className=\"pl-5\">\n <SidebarMenu\n items={item.children ?? []}\n collapsed={collapsed}\n activeClass={activeClass}\n activeIconClass={activeIconClass}\n onNavigate={onNavigate}\n level={level + 1}\n />\n </div>\n </div>\n </li>\n );\n }\n\n return (\n <li className=\"flex flex-col\">\n <NavigationLink to={item.to} className={rowClassName} onClick={onNavigate}>\n {activeBar}\n {icon}\n {label}\n </NavigationLink>\n </li>\n );\n};\n\nconst SECTION_LABEL_KEYS: Record<TUiSidebarSection, string> = {\n management: 'sidebar.sections.management',\n registration: 'sidebar.sections.registration',\n};\n\ninterface ISidebarSectionHeaderProps {\n section: TUiSidebarSection;\n collapsed: boolean;\n withDivider: boolean;\n}\n\nconst SidebarSectionHeader: React.FC<ISidebarSectionHeaderProps> = ({ section, collapsed, withDivider }) => {\n const { t } = useTranslation('ui');\n\n if (collapsed) {\n if (!withDivider) return null;\n return (\n <li aria-hidden className=\"flex flex-col px-3\">\n <span className=\"border-t border-border/70\" />\n </li>\n );\n }\n\n return (\n <li className={classNames('flex flex-col', withDivider ? 'mt-2' : 'mt-1')}>\n {withDivider && <span aria-hidden className=\"mx-3 mb-2 border-t border-border/70\" />}\n <span className=\"px-3 pb-0.5 text-xxs font-semibold uppercase tracking-wide text-foreground-subtle\">\n {t(SECTION_LABEL_KEYS[section])}\n </span>\n </li>\n );\n};\n\nconst SECTION_ORDER: Array<TUiSidebarSection> = ['management', 'registration'];\n\ninterface ISidebarMenuGroup {\n section: TUiSidebarSection | null;\n items: Array<ISidebarMenuItem>;\n}\n\nconst groupItemsBySection = (items: Array<ISidebarMenuItem>): Array<ISidebarMenuGroup> => {\n const itemsWithoutSection = (items ?? []).filter((item) => !item.section);\n const sectionGroups = SECTION_ORDER.map((section) => ({\n section,\n items: (items ?? []).filter((item) => item.section === section),\n })).filter((group) => group.items.length > 0);\n\n return itemsWithoutSection.length ? [{ section: null, items: itemsWithoutSection }, ...sectionGroups] : sectionGroups;\n};\n\nconst SidebarMenu: React.FC<ISidebarMenuProps> = ({\n items,\n activeClass,\n collapsed,\n activeIconClass,\n onNavigate,\n level = 0,\n}) => {\n const { location } = useUiNavigation();\n\n const activeKey =\n items\n .filter((item) => Boolean(item.children?.length) && containsActiveRoute(item, location))\n .map(resolveSidebarItemId)[0] ?? null;\n\n const [openKey, setOpenKey] = useState<string | null>(activeKey);\n const previousActiveKey = useRef(activeKey);\n\n useEffect(() => {\n if (activeKey && activeKey !== previousActiveKey.current) {\n setOpenKey(activeKey);\n }\n previousActiveKey.current = activeKey;\n }, [activeKey]);\n\n const handleToggle = (key: string) => {\n setOpenKey((current) => (current === key ? null : key));\n };\n\n const showSections = level === 0;\n const groups = showSections ? groupItemsBySection(items) : [{ section: null, items: items ?? [] }];\n\n return (\n <ul className={classNames('flex flex-col', level === 0 ? 'gap-y-2' : 'gap-y-1')}>\n {groups.flatMap((group, groupIndex) => {\n const rows: Array<React.ReactElement> = [];\n\n if (group.section) {\n rows.push(\n <SidebarSectionHeader\n key={`section-${group.section}`}\n section={group.section}\n collapsed={collapsed}\n withDivider={groupIndex > 0}\n />,\n );\n }\n\n group.items.forEach((item) => {\n const itemId = resolveSidebarItemId(item);\n\n rows.push(\n <SidebarMenuRow\n key={itemId}\n item={item}\n isOpen={openKey === itemId}\n collapsed={collapsed}\n onToggle={() => handleToggle(itemId)}\n activeClass={activeClass}\n activeIconClass={activeIconClass}\n onNavigate={onNavigate}\n level={level}\n />,\n );\n });\n\n return rows;\n })}\n </ul>\n );\n};\n\nexport default SidebarMenu;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type TUiThemePreference = 'light' | 'system' | 'dark';
|
|
2
|
+
interface IThemeToggleProps {
|
|
3
|
+
preference: TUiThemePreference;
|
|
4
|
+
onChange: (preference: TUiThemePreference) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Three-state control: an explicit light/dark choice, or `system` to follow the OS. The host
|
|
8
|
+
* owns the preference (persistence + writing `data-theme` on <html>); this renders the knob.
|
|
9
|
+
*/
|
|
10
|
+
declare const ThemeToggle: React.FC<IThemeToggleProps>;
|
|
11
|
+
export default ThemeToggle;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import ControlledButton from "../Form/ControlledButton.js";
|
|
5
|
+
import ControlledTooltip from "../UI/ControlledTooltip.js";
|
|
6
|
+
import { MaterialSymbol } from "../UI/MaterialSymbol/index.js";
|
|
7
|
+
import { HEADER_CONTROL_SHELL_CLASS, HEADER_CONTROL_SIZE_REM } from "./headerControlStyles.js";
|
|
8
|
+
const OPTION_SIZE_REM = HEADER_CONTROL_SIZE_REM;
|
|
9
|
+
const OPTIONS = [
|
|
10
|
+
{ value: "light", icon: "light_mode", labelKey: "theme.light" },
|
|
11
|
+
{ value: "system", icon: "computer", labelKey: "theme.system" },
|
|
12
|
+
{ value: "dark", icon: "dark_mode", labelKey: "theme.dark" }
|
|
13
|
+
];
|
|
14
|
+
const ThemeToggle = ({ preference, onChange }) => {
|
|
15
|
+
const { t } = useTranslation("ui");
|
|
16
|
+
const activeIndex = Math.max(
|
|
17
|
+
0,
|
|
18
|
+
OPTIONS.findIndex((option) => option.value === preference)
|
|
19
|
+
);
|
|
20
|
+
return /* @__PURE__ */ jsx("div", { role: "group", "aria-label": t("theme.toggle"), className: HEADER_CONTROL_SHELL_CLASS, children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
|
|
21
|
+
/* @__PURE__ */ jsx(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
"aria-hidden": true,
|
|
25
|
+
className: "pointer-events-none absolute left-0 top-0 rounded-full bg-surface shadow-elevation1 ring-1 ring-border transition-transform duration-base ease-enter",
|
|
26
|
+
style: {
|
|
27
|
+
width: `${OPTION_SIZE_REM}rem`,
|
|
28
|
+
height: `${OPTION_SIZE_REM}rem`,
|
|
29
|
+
transform: `translateX(${activeIndex * OPTION_SIZE_REM}rem)`
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
),
|
|
33
|
+
OPTIONS.map((option) => {
|
|
34
|
+
const isActive = option.value === preference;
|
|
35
|
+
return /* @__PURE__ */ jsx(ControlledTooltip, { content: t(option.labelKey), children: /* @__PURE__ */ jsx(
|
|
36
|
+
ControlledButton,
|
|
37
|
+
{
|
|
38
|
+
defaultHtmlButton: true,
|
|
39
|
+
"aria-pressed": isActive,
|
|
40
|
+
onClick: () => onChange(option.value),
|
|
41
|
+
className: classNames(
|
|
42
|
+
"relative z-10 flex shrink-0 items-center justify-center rounded-full leading-none transition-colors duration-base",
|
|
43
|
+
isActive ? "text-brand-emphasis" : "text-foreground-faint hover:text-foreground-muted"
|
|
44
|
+
),
|
|
45
|
+
style: { width: `${OPTION_SIZE_REM}rem`, height: `${OPTION_SIZE_REM}rem` },
|
|
46
|
+
children: /* @__PURE__ */ jsx(MaterialSymbol, { icon: option.icon, size: 15, fill: isActive })
|
|
47
|
+
}
|
|
48
|
+
) }, option.value);
|
|
49
|
+
})
|
|
50
|
+
] }) });
|
|
51
|
+
};
|
|
52
|
+
export {
|
|
53
|
+
ThemeToggle as default
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=ThemeToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeToggle.js","sources":["../../../src/components/Shell/ThemeToggle.tsx"],"sourcesContent":["import classNames from 'classnames';\nimport { useTranslation } from 'react-i18next';\n\nimport ControlledButton from '@/components/Form/ControlledButton';\nimport ControlledTooltip from '@/components/UI/ControlledTooltip';\nimport { MaterialSymbol, SymbolCodepoints } from '@/components/UI/MaterialSymbol';\n\nimport { HEADER_CONTROL_SHELL_CLASS, HEADER_CONTROL_SIZE_REM } from './headerControlStyles';\n\nconst OPTION_SIZE_REM = HEADER_CONTROL_SIZE_REM;\n\nexport type TUiThemePreference = 'light' | 'system' | 'dark';\n\nconst OPTIONS: Array<{ value: TUiThemePreference; icon: SymbolCodepoints; labelKey: string }> = [\n { value: 'light', icon: 'light_mode', labelKey: 'theme.light' },\n { value: 'system', icon: 'computer', labelKey: 'theme.system' },\n { value: 'dark', icon: 'dark_mode', labelKey: 'theme.dark' },\n];\n\ninterface IThemeToggleProps {\n preference: TUiThemePreference;\n onChange: (preference: TUiThemePreference) => void;\n}\n\n/**\n * Three-state control: an explicit light/dark choice, or `system` to follow the OS. The host\n * owns the preference (persistence + writing `data-theme` on <html>); this renders the knob.\n */\nconst ThemeToggle: React.FC<IThemeToggleProps> = ({ preference, onChange }) => {\n const { t } = useTranslation('ui');\n\n const activeIndex = Math.max(\n 0,\n OPTIONS.findIndex((option) => option.value === preference),\n );\n\n return (\n <div role=\"group\" aria-label={t('theme.toggle')} className={HEADER_CONTROL_SHELL_CLASS}>\n <div className=\"relative flex items-center\">\n <div\n aria-hidden\n className=\"pointer-events-none absolute left-0 top-0 rounded-full bg-surface shadow-elevation1 ring-1 ring-border transition-transform duration-base ease-enter\"\n style={{\n width: `${OPTION_SIZE_REM}rem`,\n height: `${OPTION_SIZE_REM}rem`,\n transform: `translateX(${activeIndex * OPTION_SIZE_REM}rem)`,\n }}\n />\n\n {OPTIONS.map((option) => {\n const isActive = option.value === preference;\n\n return (\n <ControlledTooltip key={option.value} content={t(option.labelKey)}>\n <ControlledButton\n defaultHtmlButton\n aria-pressed={isActive}\n onClick={() => onChange(option.value)}\n className={classNames(\n 'relative z-10 flex shrink-0 items-center justify-center rounded-full leading-none transition-colors duration-base',\n isActive ? 'text-brand-emphasis' : 'text-foreground-faint hover:text-foreground-muted',\n )}\n style={{ width: `${OPTION_SIZE_REM}rem`, height: `${OPTION_SIZE_REM}rem` }}\n >\n <MaterialSymbol icon={option.icon} size={15} fill={isActive} />\n </ControlledButton>\n </ControlledTooltip>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default ThemeToggle;\n"],"names":[],"mappings":";;;;;;;AASA,MAAM,kBAAkB;AAIxB,MAAM,UAA0F;AAAA,EAC9F,EAAE,OAAO,SAAS,MAAM,cAAc,UAAU,cAAA;AAAA,EAChD,EAAE,OAAO,UAAU,MAAM,YAAY,UAAU,eAAA;AAAA,EAC/C,EAAE,OAAO,QAAQ,MAAM,aAAa,UAAU,aAAA;AAChD;AAWA,MAAM,cAA2C,CAAC,EAAE,YAAY,eAAe;AAC7E,QAAM,EAAE,EAAA,IAAM,eAAe,IAAI;AAEjC,QAAM,cAAc,KAAK;AAAA,IACvB;AAAA,IACA,QAAQ,UAAU,CAAC,WAAW,OAAO,UAAU,UAAU;AAAA,EAAA;AAG3D,SACE,oBAAC,OAAA,EAAI,MAAK,SAAQ,cAAY,EAAE,cAAc,GAAG,WAAW,4BAC1D,UAAA,qBAAC,OAAA,EAAI,WAAU,8BACb,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,eAAW;AAAA,QACX,WAAU;AAAA,QACV,OAAO;AAAA,UACL,OAAO,GAAG,eAAe;AAAA,UACzB,QAAQ,GAAG,eAAe;AAAA,UAC1B,WAAW,cAAc,cAAc,eAAe;AAAA,QAAA;AAAA,MACxD;AAAA,IAAA;AAAA,IAGD,QAAQ,IAAI,CAAC,WAAW;AACvB,YAAM,WAAW,OAAO,UAAU;AAElC,iCACG,mBAAA,EAAqC,SAAS,EAAE,OAAO,QAAQ,GAC9D,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,mBAAiB;AAAA,UACjB,gBAAc;AAAA,UACd,SAAS,MAAM,SAAS,OAAO,KAAK;AAAA,UACpC,WAAW;AAAA,YACT;AAAA,YACA,WAAW,wBAAwB;AAAA,UAAA;AAAA,UAErC,OAAO,EAAE,OAAO,GAAG,eAAe,OAAO,QAAQ,GAAG,eAAe,MAAA;AAAA,UAEnE,UAAA,oBAAC,kBAAe,MAAM,OAAO,MAAM,MAAM,IAAI,MAAM,SAAA,CAAU;AAAA,QAAA;AAAA,MAAA,EAC/D,GAZsB,OAAO,KAa/B;AAAA,IAEJ,CAAC;AAAA,EAAA,EAAA,CACH,EAAA,CACF;AAEJ;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every control on the right side of the header (workspace actions, theme, language) lives
|
|
3
|
+
* inside the same pill shell, so they read as one family instead of three unrelated widgets.
|
|
4
|
+
* The size is a constant because the theme/language knobs travel by exactly one option width:
|
|
5
|
+
* any drift between the knob and the buttons puts the highlight off the icon.
|
|
6
|
+
*/
|
|
7
|
+
export declare const HEADER_CONTROL_SIZE_REM = 1.75;
|
|
8
|
+
export declare const HEADER_CONTROL_SHELL_CLASS = "flex items-center rounded-full border border-border bg-muted p-[3px]";
|
|
9
|
+
export declare const HEADER_ICON_ACTION_CLASS = "interactive relative flex size-7 shrink-0 items-center justify-center rounded-full text-foreground-subtle hover:bg-surface hover:text-foreground hover:shadow-elevation1";
|
|
10
|
+
export declare const HEADER_ICON_ACTION_SIZE = 18;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const HEADER_CONTROL_SIZE_REM = 1.75;
|
|
2
|
+
const HEADER_CONTROL_SHELL_CLASS = "flex items-center rounded-full border border-border bg-muted p-[3px]";
|
|
3
|
+
const HEADER_ICON_ACTION_CLASS = "interactive relative flex size-7 shrink-0 items-center justify-center rounded-full text-foreground-subtle hover:bg-surface hover:text-foreground hover:shadow-elevation1";
|
|
4
|
+
const HEADER_ICON_ACTION_SIZE = 18;
|
|
5
|
+
export {
|
|
6
|
+
HEADER_CONTROL_SHELL_CLASS,
|
|
7
|
+
HEADER_CONTROL_SIZE_REM,
|
|
8
|
+
HEADER_ICON_ACTION_CLASS,
|
|
9
|
+
HEADER_ICON_ACTION_SIZE
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=headerControlStyles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headerControlStyles.js","sources":["../../../src/components/Shell/headerControlStyles.ts"],"sourcesContent":["/**\n * Every control on the right side of the header (workspace actions, theme, language) lives\n * inside the same pill shell, so they read as one family instead of three unrelated widgets.\n * The size is a constant because the theme/language knobs travel by exactly one option width:\n * any drift between the knob and the buttons puts the highlight off the icon.\n */\nexport const HEADER_CONTROL_SIZE_REM = 1.75;\n\nexport const HEADER_CONTROL_SHELL_CLASS = 'flex items-center rounded-full border border-border bg-muted p-[3px]';\n\nexport const HEADER_ICON_ACTION_CLASS =\n 'interactive relative flex size-7 shrink-0 items-center justify-center rounded-full text-foreground-subtle hover:bg-surface hover:text-foreground hover:shadow-elevation1';\n\nexport const HEADER_ICON_ACTION_SIZE = 18;\n"],"names":[],"mappings":"AAMO,MAAM,0BAA0B;AAEhC,MAAM,6BAA6B;AAEnC,MAAM,2BACX;AAEK,MAAM,0BAA0B;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ISidebarState {
|
|
2
|
+
isMobile: boolean;
|
|
3
|
+
isVisible: boolean;
|
|
4
|
+
isExpanded: boolean;
|
|
5
|
+
isDocked: boolean;
|
|
6
|
+
isOverlayOnMobile: boolean;
|
|
7
|
+
showRail: boolean;
|
|
8
|
+
toggleLabelKey: string;
|
|
9
|
+
togglePrimary: () => void;
|
|
10
|
+
onHoverEnter: () => void;
|
|
11
|
+
onHoverLeave: () => void;
|
|
12
|
+
closeMobileDrawer: () => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const useSidebarState: () => ISidebarState;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useState, useRef, useCallback, useEffect } from "react";
|
|
2
|
+
import { writeUiPreference, readUiPreference } from "../../helpers/uiPreferences.js";
|
|
3
|
+
import { useMobile } from "../../hooks/useMobile.js";
|
|
4
|
+
const HOVER_OPEN_DELAY_MS = 250;
|
|
5
|
+
const HOVER_CLOSE_DELAY_MS = 250;
|
|
6
|
+
const PIN_STORAGE_KEY = "sidebar_pinned";
|
|
7
|
+
const TOGGLE_SHORTCUT_KEY = "\\";
|
|
8
|
+
const readPinnedPreference = () => readUiPreference(PIN_STORAGE_KEY) ?? false;
|
|
9
|
+
const useSidebarState = () => {
|
|
10
|
+
const isMobile = useMobile();
|
|
11
|
+
const [isPinned, setIsPinned] = useState(readPinnedPreference);
|
|
12
|
+
const [isHovering, setIsHovering] = useState(false);
|
|
13
|
+
const [isMobileOpen, setIsMobileOpen] = useState(false);
|
|
14
|
+
const openTimerRef = useRef(null);
|
|
15
|
+
const closeTimerRef = useRef(null);
|
|
16
|
+
const clearOpenTimer = useCallback(() => {
|
|
17
|
+
if (openTimerRef.current !== null) {
|
|
18
|
+
window.clearTimeout(openTimerRef.current);
|
|
19
|
+
openTimerRef.current = null;
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
const clearCloseTimer = useCallback(() => {
|
|
23
|
+
if (closeTimerRef.current !== null) {
|
|
24
|
+
window.clearTimeout(closeTimerRef.current);
|
|
25
|
+
closeTimerRef.current = null;
|
|
26
|
+
}
|
|
27
|
+
}, []);
|
|
28
|
+
const clearTimers = useCallback(() => {
|
|
29
|
+
clearOpenTimer();
|
|
30
|
+
clearCloseTimer();
|
|
31
|
+
}, [clearOpenTimer, clearCloseTimer]);
|
|
32
|
+
const persistPinned = useCallback((next) => {
|
|
33
|
+
setIsPinned(next);
|
|
34
|
+
writeUiPreference(PIN_STORAGE_KEY, next);
|
|
35
|
+
}, []);
|
|
36
|
+
const togglePrimary = useCallback(() => {
|
|
37
|
+
clearTimers();
|
|
38
|
+
if (isMobile) {
|
|
39
|
+
setIsMobileOpen((open) => !open);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
setIsHovering(false);
|
|
43
|
+
persistPinned(!isPinned);
|
|
44
|
+
}, [clearTimers, isMobile, isPinned, persistPinned]);
|
|
45
|
+
const onHoverEnter = useCallback(() => {
|
|
46
|
+
if (isMobile || isPinned) return;
|
|
47
|
+
clearCloseTimer();
|
|
48
|
+
if (isHovering || openTimerRef.current !== null) return;
|
|
49
|
+
openTimerRef.current = window.setTimeout(() => {
|
|
50
|
+
openTimerRef.current = null;
|
|
51
|
+
setIsHovering(true);
|
|
52
|
+
}, HOVER_OPEN_DELAY_MS);
|
|
53
|
+
}, [clearCloseTimer, isHovering, isMobile, isPinned]);
|
|
54
|
+
const onHoverLeave = useCallback(() => {
|
|
55
|
+
if (isMobile || isPinned) return;
|
|
56
|
+
clearOpenTimer();
|
|
57
|
+
if (closeTimerRef.current !== null) return;
|
|
58
|
+
closeTimerRef.current = window.setTimeout(() => {
|
|
59
|
+
closeTimerRef.current = null;
|
|
60
|
+
setIsHovering(false);
|
|
61
|
+
}, HOVER_CLOSE_DELAY_MS);
|
|
62
|
+
}, [clearOpenTimer, isMobile, isPinned]);
|
|
63
|
+
const closeMobileDrawer = useCallback(() => {
|
|
64
|
+
setIsMobileOpen(false);
|
|
65
|
+
}, []);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
const handleKeyDown = (event) => {
|
|
68
|
+
if ((event.ctrlKey || event.metaKey) && event.key === TOGGLE_SHORTCUT_KEY) {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
togglePrimary();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
74
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
75
|
+
}, [togglePrimary]);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
clearTimers();
|
|
78
|
+
setIsHovering(false);
|
|
79
|
+
setIsMobileOpen(false);
|
|
80
|
+
}, [isMobile, clearTimers]);
|
|
81
|
+
useEffect(() => clearTimers, [clearTimers]);
|
|
82
|
+
const isDocked = !isMobile && isPinned;
|
|
83
|
+
const isExpanded = isMobile ? isMobileOpen : isPinned || isHovering;
|
|
84
|
+
const isVisible = isMobile ? isMobileOpen : true;
|
|
85
|
+
const showRail = !isMobile && !isExpanded;
|
|
86
|
+
const isOverlayOnMobile = isMobile && isMobileOpen;
|
|
87
|
+
const willCollapse = isMobile ? isMobileOpen : isPinned;
|
|
88
|
+
const toggleLabelKey = willCollapse ? "sidebar.collapseSidebar" : "sidebar.openSidebar";
|
|
89
|
+
return {
|
|
90
|
+
isMobile,
|
|
91
|
+
isVisible,
|
|
92
|
+
isExpanded,
|
|
93
|
+
isDocked,
|
|
94
|
+
isOverlayOnMobile,
|
|
95
|
+
showRail,
|
|
96
|
+
toggleLabelKey,
|
|
97
|
+
togglePrimary,
|
|
98
|
+
onHoverEnter,
|
|
99
|
+
onHoverLeave,
|
|
100
|
+
closeMobileDrawer
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
export {
|
|
104
|
+
useSidebarState
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=useSidebarState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSidebarState.js","sources":["../../../src/components/Shell/useSidebarState.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { readUiPreference, writeUiPreference } from '@/helpers/uiPreferences';\nimport { useMobile } from '@/hooks/useMobile';\n\nconst HOVER_OPEN_DELAY_MS = 250;\nconst HOVER_CLOSE_DELAY_MS = 250;\nconst PIN_STORAGE_KEY = 'sidebar_pinned';\nconst TOGGLE_SHORTCUT_KEY = '\\\\';\n\nconst readPinnedPreference = (): boolean => readUiPreference<boolean>(PIN_STORAGE_KEY) ?? false;\n\nexport interface ISidebarState {\n isMobile: boolean;\n isVisible: boolean;\n isExpanded: boolean;\n isDocked: boolean;\n isOverlayOnMobile: boolean;\n showRail: boolean;\n toggleLabelKey: string;\n togglePrimary: () => void;\n onHoverEnter: () => void;\n onHoverLeave: () => void;\n closeMobileDrawer: () => void;\n}\n\nexport const useSidebarState = (): ISidebarState => {\n const isMobile = useMobile();\n\n const [isPinned, setIsPinned] = useState<boolean>(readPinnedPreference);\n const [isHovering, setIsHovering] = useState(false);\n const [isMobileOpen, setIsMobileOpen] = useState(false);\n\n const openTimerRef = useRef<number | null>(null);\n const closeTimerRef = useRef<number | null>(null);\n\n const clearOpenTimer = useCallback(() => {\n if (openTimerRef.current !== null) {\n window.clearTimeout(openTimerRef.current);\n openTimerRef.current = null;\n }\n }, []);\n\n const clearCloseTimer = useCallback(() => {\n if (closeTimerRef.current !== null) {\n window.clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n }, []);\n\n const clearTimers = useCallback(() => {\n clearOpenTimer();\n clearCloseTimer();\n }, [clearOpenTimer, clearCloseTimer]);\n\n const persistPinned = useCallback((next: boolean) => {\n setIsPinned(next);\n writeUiPreference(PIN_STORAGE_KEY, next);\n }, []);\n\n const togglePrimary = useCallback(() => {\n clearTimers();\n if (isMobile) {\n setIsMobileOpen((open) => !open);\n return;\n }\n setIsHovering(false);\n persistPinned(!isPinned);\n }, [clearTimers, isMobile, isPinned, persistPinned]);\n\n const onHoverEnter = useCallback(() => {\n if (isMobile || isPinned) return;\n clearCloseTimer();\n if (isHovering || openTimerRef.current !== null) return;\n openTimerRef.current = window.setTimeout(() => {\n openTimerRef.current = null;\n setIsHovering(true);\n }, HOVER_OPEN_DELAY_MS);\n }, [clearCloseTimer, isHovering, isMobile, isPinned]);\n\n const onHoverLeave = useCallback(() => {\n if (isMobile || isPinned) return;\n clearOpenTimer();\n if (closeTimerRef.current !== null) return;\n closeTimerRef.current = window.setTimeout(() => {\n closeTimerRef.current = null;\n setIsHovering(false);\n }, HOVER_CLOSE_DELAY_MS);\n }, [clearOpenTimer, isMobile, isPinned]);\n\n const closeMobileDrawer = useCallback(() => {\n setIsMobileOpen(false);\n }, []);\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if ((event.ctrlKey || event.metaKey) && event.key === TOGGLE_SHORTCUT_KEY) {\n event.preventDefault();\n togglePrimary();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [togglePrimary]);\n\n useEffect(() => {\n clearTimers();\n setIsHovering(false);\n setIsMobileOpen(false);\n }, [isMobile, clearTimers]);\n\n useEffect(() => clearTimers, [clearTimers]);\n\n const isDocked = !isMobile && isPinned;\n const isExpanded = isMobile ? isMobileOpen : isPinned || isHovering;\n const isVisible = isMobile ? isMobileOpen : true;\n const showRail = !isMobile && !isExpanded;\n const isOverlayOnMobile = isMobile && isMobileOpen;\n const willCollapse = isMobile ? isMobileOpen : isPinned;\n const toggleLabelKey = willCollapse ? 'sidebar.collapseSidebar' : 'sidebar.openSidebar';\n\n return {\n isMobile,\n isVisible,\n isExpanded,\n isDocked,\n isOverlayOnMobile,\n showRail,\n toggleLabelKey,\n togglePrimary,\n onHoverEnter,\n onHoverLeave,\n closeMobileDrawer,\n };\n};\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ export { default as PageTitle } from './components/Navigation/PageTitle';
|
|
|
16
16
|
export * from './components/Navigation/PageTitleNavigationContext';
|
|
17
17
|
export * from './components/Navigation/UiNavigationContext';
|
|
18
18
|
export { default as UnifiedSearchBar } from './components/Search/UnifiedSearchBar';
|
|
19
|
+
export { default as AppShell } from './components/Shell/AppShell';
|
|
20
|
+
export { default as ShellLanguageToggle } from './components/Shell/LanguageToggle';
|
|
21
|
+
export * from './components/Shell/SidebarMenu';
|
|
22
|
+
export { default as ShellThemeToggle } from './components/Shell/ThemeToggle';
|
|
19
23
|
export * from './components/UI/access/UiAccessContext';
|
|
20
24
|
export { default as BaseDataCard } from './components/UI/BaseDataCard';
|
|
21
25
|
export { default as OutlinedChip } from './components/UI/Chips/OutlinedChip';
|
package/dist/index.js
CHANGED
|
@@ -16,26 +16,30 @@ import { default as default15 } from "./components/Navigation/PageTitle.js";
|
|
|
16
16
|
import { PageTitleNavigationProvider, usePageTitleNavigation } from "./components/Navigation/PageTitleNavigationContext.js";
|
|
17
17
|
import { UiNavigationProvider, useUiNavigation } from "./components/Navigation/UiNavigationContext.js";
|
|
18
18
|
import { default as default16 } from "./components/Search/UnifiedSearchBar.js";
|
|
19
|
+
import { default as default17 } from "./components/Shell/AppShell.js";
|
|
20
|
+
import { default as default18 } from "./components/Shell/LanguageToggle.js";
|
|
21
|
+
import { resolveSidebarItemId } from "./components/Shell/SidebarMenu.js";
|
|
22
|
+
import { default as default19 } from "./components/Shell/ThemeToggle.js";
|
|
19
23
|
import { UiAccessProvider, useUiAccess } from "./components/UI/access/UiAccessContext.js";
|
|
20
|
-
import { default as
|
|
21
|
-
import { default as
|
|
22
|
-
import { default as
|
|
23
|
-
import { default as
|
|
24
|
-
import { default as
|
|
25
|
-
import { default as
|
|
26
|
-
import { default as
|
|
27
|
-
import { default as
|
|
28
|
-
import { default as
|
|
29
|
-
import { default as
|
|
30
|
-
import { default as
|
|
31
|
-
import { default as
|
|
32
|
-
import { default as
|
|
33
|
-
import { default as
|
|
34
|
-
import { default as
|
|
24
|
+
import { default as default20 } from "./components/UI/BaseDataCard.js";
|
|
25
|
+
import { default as default21 } from "./components/UI/Chips/OutlinedChip.js";
|
|
26
|
+
import { default as default22 } from "./components/UI/Colors.js";
|
|
27
|
+
import { default as default23 } from "./components/UI/ColorSwatch.js";
|
|
28
|
+
import { default as default24 } from "./components/UI/ControlledAccordion.js";
|
|
29
|
+
import { default as default25 } from "./components/UI/ControlledCollapse.js";
|
|
30
|
+
import { default as default26 } from "./components/UI/ControlledMenu.js";
|
|
31
|
+
import { default as default27 } from "./components/UI/ControlledPopover.js";
|
|
32
|
+
import { default as default28 } from "./components/UI/ControlledProgress.js";
|
|
33
|
+
import { default as default29 } from "./components/UI/ControlledSlider.js";
|
|
34
|
+
import { default as default30 } from "./components/UI/ControlledTooltip.js";
|
|
35
|
+
import { default as default31 } from "./components/UI/CustomBadge.js";
|
|
36
|
+
import { default as default32 } from "./components/UI/CustomCard.js";
|
|
37
|
+
import { default as default33 } from "./components/UI/InformationCard.js";
|
|
38
|
+
import { default as default34 } from "./components/UI/LoadingSpinner.js";
|
|
35
39
|
import { MaterialSymbol, combineClasses } from "./components/UI/MaterialSymbol/index.js";
|
|
36
|
-
import { default as
|
|
37
|
-
import { default as
|
|
38
|
-
import { default as
|
|
40
|
+
import { default as default35 } from "./components/UI/NoDataFound/index.js";
|
|
41
|
+
import { default as default36 } from "./components/UI/SkeletonLoading.js";
|
|
42
|
+
import { default as default37 } from "./components/UI/UserMenu.js";
|
|
39
43
|
import { composeRefs } from "./helpers/composeRefs.js";
|
|
40
44
|
import { isPressOnLayeredSurface } from "./helpers/layeredSurfaces.js";
|
|
41
45
|
import { readThemeToken, useThemeChartTokens } from "./helpers/themeTokens.js";
|
|
@@ -52,46 +56,49 @@ import { uiLocales } from "./locales/index.js";
|
|
|
52
56
|
import { collapseVariants, createDrawerVariants, dialogVariants, fadeVariants, floatingVariants, scrimVariants, tooltipVariants } from "./motion/motionPresets.js";
|
|
53
57
|
import { MOTION_OFFSET_PX, enterTransition, exitTransition, motionDuration, motionEase } from "./motion/motionTokens.js";
|
|
54
58
|
export {
|
|
59
|
+
default17 as AppShell,
|
|
55
60
|
BREAKPOINTS,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
default20 as BaseDataCard,
|
|
62
|
+
default23 as ColorSwatch,
|
|
63
|
+
default22 as Colors,
|
|
64
|
+
default24 as ControlledAccordion,
|
|
60
65
|
default13 as ControlledBreadcrumb,
|
|
61
66
|
default2 as ControlledButton,
|
|
62
67
|
default3 as ControlledCheckbox,
|
|
63
|
-
|
|
68
|
+
default25 as ControlledCollapse,
|
|
64
69
|
default4 as ControlledDialog,
|
|
65
70
|
default5 as ControlledDrawer,
|
|
66
71
|
default6 as ControlledImage,
|
|
67
72
|
default7 as ControlledInput,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
default26 as ControlledMenu,
|
|
74
|
+
default27 as ControlledPopover,
|
|
75
|
+
default28 as ControlledProgress,
|
|
71
76
|
default8 as ControlledRadio,
|
|
72
77
|
ControlledSelect,
|
|
73
|
-
|
|
78
|
+
default29 as ControlledSlider,
|
|
74
79
|
default9 as ControlledSwitch,
|
|
75
80
|
default10 as ControlledTabs,
|
|
76
81
|
default11 as ControlledTextarea,
|
|
77
|
-
|
|
82
|
+
default30 as ControlledTooltip,
|
|
78
83
|
default12 as ControlledViewToggle,
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
default31 as CustomBadge,
|
|
85
|
+
default32 as CustomCard,
|
|
81
86
|
default14 as ErrorPage,
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
default33 as InformationCard,
|
|
88
|
+
default34 as LoadingSpinner,
|
|
84
89
|
MOTION_OFFSET_PX,
|
|
85
90
|
MaterialSymbol,
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
default35 as NoDataFound,
|
|
92
|
+
default21 as OutlinedChip,
|
|
88
93
|
default15 as PageTitle,
|
|
89
94
|
PageTitleNavigationProvider,
|
|
90
|
-
|
|
95
|
+
default18 as ShellLanguageToggle,
|
|
96
|
+
default19 as ShellThemeToggle,
|
|
97
|
+
default36 as SkeletonLoading,
|
|
91
98
|
UiAccessProvider,
|
|
92
99
|
UiNavigationProvider,
|
|
93
100
|
default16 as UnifiedSearchBar,
|
|
94
|
-
|
|
101
|
+
default37 as UserMenu,
|
|
95
102
|
collapseVariants,
|
|
96
103
|
combineClasses,
|
|
97
104
|
composeRefs,
|
|
@@ -108,6 +115,7 @@ export {
|
|
|
108
115
|
motionEase,
|
|
109
116
|
readThemeToken,
|
|
110
117
|
readUiPreference,
|
|
118
|
+
resolveSidebarItemId,
|
|
111
119
|
resolveUiPreferenceScopeId,
|
|
112
120
|
scrimVariants,
|
|
113
121
|
tooltipVariants,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|