@espressif/dashboard-ui-components 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ try {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ } catch (e) {
11
+ throw mod = 0, e;
12
+ }
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+
31
+ export { __commonJS, __toESM };
@@ -0,0 +1,488 @@
1
+ import { FooterCard, MyAccountMenu, ProfileCard, AppLogo } from './chunk-SYEKNRS5.js';
2
+ import { useSidebar, SidebarTrigger, SidebarProvider, Sidebar2, SidebarInset, parseTextMarkup, isPathPrefixOf, isSidebarGroup } from './chunk-34PXJOCS.js';
3
+ import { Button, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator } from './chunk-F5P6S7K2.js';
4
+ import { cn } from './chunk-VU4CZ76T.js';
5
+ import { Menu, Palette, Check, Globe, LogOut } from 'lucide-react';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import React, { useMemo } from 'react';
8
+
9
+ function Header({
10
+ leftContent,
11
+ rightContent,
12
+ endContent,
13
+ showSidebarTrigger = false,
14
+ mobileLogo
15
+ }) {
16
+ const { state, isMobile, toggleSidebar } = useSidebar();
17
+ const isCollapsed = state === "collapsed";
18
+ const sidebarWidth = isCollapsed ? "calc(var(--espd-sidebar-width-collapsed) - 1px)" : "calc(var(--espd-sidebar-width) - 1px)";
19
+ return /* @__PURE__ */ jsx(
20
+ "header",
21
+ {
22
+ className: "fixed top-0 z-50 border-b backdrop-blur supports-[backdrop-filter]:bg-header transition-[left,width] duration-200 ease-linear border-header-border",
23
+ style: {
24
+ left: isMobile ? 0 : `calc(${sidebarWidth})`,
25
+ width: isMobile ? "100%" : `calc(100% - ${sidebarWidth})`,
26
+ height: "var(--espd-header-height)"
27
+ },
28
+ children: /* @__PURE__ */ jsxs("div", { className: "flex h-full items-center gap-3 pr-4", children: [
29
+ showSidebarTrigger && /* @__PURE__ */ jsx("div", { className: "sidebar-trigger shrink-0", children: isMobile ? /* @__PURE__ */ jsxs(
30
+ Button,
31
+ {
32
+ variant: "ghost",
33
+ size: "icon",
34
+ className: "size-10",
35
+ onClick: toggleSidebar,
36
+ children: [
37
+ /* @__PURE__ */ jsx(Menu, { className: "!size-6" }),
38
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle Sidebar" })
39
+ ]
40
+ }
41
+ ) : /* @__PURE__ */ jsx(SidebarTrigger, {}) }),
42
+ isMobile && mobileLogo && /* @__PURE__ */ jsx("div", { className: "mobile-logo shrink-0", children: mobileLogo }),
43
+ leftContent && /* @__PURE__ */ jsx("div", { className: cn("min-w-0", !rightContent && "flex-1"), children: leftContent }),
44
+ rightContent && /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: rightContent }),
45
+ endContent && /* @__PURE__ */ jsx("div", { className: "shrink-0 ml-auto flex items-center gap-2", children: endContent })
46
+ ] })
47
+ }
48
+ );
49
+ }
50
+ function Footer({ hidden = false }) {
51
+ return /* @__PURE__ */ jsx(
52
+ "footer",
53
+ {
54
+ className: cn(
55
+ "bg-sidebar",
56
+ hidden ? "h-[var(--espd-hidden-footer-height)]" : "h-[var(--espd-footer-height)]"
57
+ ),
58
+ children: !hidden && /* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground h-full flex items-center justify-center tracking-normal", children: /* @__PURE__ */ jsx(FooterCard, {}) })
59
+ }
60
+ );
61
+ }
62
+ function AccountMenu({
63
+ userName,
64
+ userEmail,
65
+ userProfilePictureUrl,
66
+ avatarBadgeColor,
67
+ onLogoutClick,
68
+ onProfileCardClick,
69
+ onColorThemeChange,
70
+ colorTheme,
71
+ onLanguageChange,
72
+ languages,
73
+ currentLanguage,
74
+ additionalItems
75
+ }) {
76
+ const menuItems = useMemo(() => {
77
+ const groups = [];
78
+ if (userName || userEmail) {
79
+ const profileCard = /* @__PURE__ */ jsx(
80
+ ProfileCard,
81
+ {
82
+ name: userName,
83
+ email: userEmail,
84
+ imageUrl: userProfilePictureUrl
85
+ },
86
+ "profile"
87
+ );
88
+ groups.push({
89
+ id: "profile",
90
+ items: [
91
+ onProfileCardClick ? /* @__PURE__ */ jsx(
92
+ "button",
93
+ {
94
+ type: "button",
95
+ onClick: onProfileCardClick,
96
+ className: "w-full text-left cursor-pointer",
97
+ children: profileCard
98
+ },
99
+ "profile"
100
+ ) : profileCard
101
+ ]
102
+ });
103
+ }
104
+ if (onColorThemeChange) {
105
+ const isDark = colorTheme === "dark";
106
+ const themeItems = [
107
+ {
108
+ id: "theme-dark",
109
+ label: "Dark mode",
110
+ endIcon: isDark ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : void 0,
111
+ isSelected: isDark,
112
+ onClick: () => onColorThemeChange("dark")
113
+ },
114
+ {
115
+ id: "theme-light",
116
+ label: "Light mode",
117
+ endIcon: !isDark ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : void 0,
118
+ isSelected: !isDark,
119
+ onClick: () => onColorThemeChange("light")
120
+ }
121
+ ];
122
+ groups.push({
123
+ id: "theme",
124
+ items: [
125
+ {
126
+ id: "color-theme",
127
+ label: "Color theme",
128
+ startIcon: /* @__PURE__ */ jsx(Palette, { className: "h-4 w-4" }),
129
+ items: themeItems
130
+ }
131
+ ]
132
+ });
133
+ }
134
+ if (onLanguageChange && languages?.length) {
135
+ const langItems = languages.map((lang) => ({
136
+ id: `lang-${lang.code}`,
137
+ label: lang.label,
138
+ endIcon: lang.code === currentLanguage ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : void 0,
139
+ isSelected: lang.code === currentLanguage,
140
+ onClick: () => onLanguageChange(lang.code)
141
+ }));
142
+ groups.push({
143
+ id: "language",
144
+ items: [
145
+ {
146
+ id: "language",
147
+ label: "Language",
148
+ startIcon: /* @__PURE__ */ jsx(Globe, { className: "h-4 w-4" }),
149
+ items: langItems
150
+ }
151
+ ]
152
+ });
153
+ }
154
+ if (additionalItems?.length) {
155
+ groups.push(...additionalItems);
156
+ }
157
+ if (onLogoutClick) {
158
+ groups.push({
159
+ id: "logout",
160
+ items: [
161
+ {
162
+ id: "logout",
163
+ label: "Logout",
164
+ startIcon: /* @__PURE__ */ jsx(LogOut, { className: "h-4 w-4" }),
165
+ color: "error",
166
+ onClick: onLogoutClick
167
+ }
168
+ ]
169
+ });
170
+ }
171
+ return groups;
172
+ }, [
173
+ userName,
174
+ userEmail,
175
+ userProfilePictureUrl,
176
+ onProfileCardClick,
177
+ onColorThemeChange,
178
+ colorTheme,
179
+ onLanguageChange,
180
+ languages,
181
+ currentLanguage,
182
+ additionalItems,
183
+ onLogoutClick
184
+ ]);
185
+ if (menuItems.length === 0) return null;
186
+ return /* @__PURE__ */ jsx(
187
+ MyAccountMenu,
188
+ {
189
+ name: userName,
190
+ email: userEmail,
191
+ imageUrl: userProfilePictureUrl,
192
+ badgeColor: avatarBadgeColor,
193
+ menuItems,
194
+ minWidth: "220px"
195
+ }
196
+ );
197
+ }
198
+ function WorkspaceBreadcrumbs({
199
+ items,
200
+ LinkComponent,
201
+ collapseOnMobile = false
202
+ }) {
203
+ const { isMobile } = useSidebar();
204
+ if (items.length === 0) return null;
205
+ const visibleItems = collapseOnMobile && isMobile ? items.slice(-1) : items;
206
+ return /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { children: visibleItems.map((item, index) => {
207
+ const isLast = index === visibleItems.length - 1;
208
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
209
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: item.path ? /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(LinkComponent, { to: item.path, children: item.label }) }) : /* @__PURE__ */ jsx(BreadcrumbPage, { children: item.label }) }),
210
+ !isLast && /* @__PURE__ */ jsx(BreadcrumbSeparator, {})
211
+ ] }, item.path ?? index);
212
+ }) }) });
213
+ }
214
+
215
+ // src/layouts/workspace-layout/breadcrumbs/derive-breadcrumbs.ts
216
+ function labelFromPath(path) {
217
+ const last = path.split("/").filter(Boolean).pop();
218
+ if (!last) return "Home";
219
+ return last.charAt(0).toUpperCase() + last.slice(1).replace(/-/g, " ");
220
+ }
221
+ function deriveBreadcrumbs(groups, currentPath, indexPath) {
222
+ const matches = [];
223
+ if (indexPath && isPathPrefixOf(indexPath, currentPath)) {
224
+ const coveredBySidebar = groups.some((entry) => {
225
+ if (isSidebarGroup(entry)) {
226
+ return entry.items.some((item) => item.path === indexPath);
227
+ }
228
+ return entry.path === indexPath;
229
+ });
230
+ if (!coveredBySidebar) {
231
+ matches.push({ label: labelFromPath(indexPath), path: indexPath });
232
+ }
233
+ }
234
+ for (const entry of groups) {
235
+ if (isSidebarGroup(entry)) {
236
+ for (const item of entry.items) {
237
+ if (isPathPrefixOf(item.path, currentPath)) {
238
+ matches.push({ label: item.label, path: item.path });
239
+ }
240
+ }
241
+ } else if (isPathPrefixOf(entry.path, currentPath)) {
242
+ matches.push({ label: entry.label, path: entry.path });
243
+ }
244
+ }
245
+ if (matches.length === 0) return [];
246
+ matches.sort((a, b) => a.path.length - b.path.length);
247
+ return matches.map((match) => ({
248
+ label: match.label,
249
+ path: match.path === currentPath ? void 0 : match.path
250
+ }));
251
+ }
252
+ function renderLogoForState({
253
+ logo,
254
+ logoCollapsed,
255
+ logoAssets,
256
+ appName,
257
+ darkMode,
258
+ collapsed
259
+ }) {
260
+ const nodeOverride = collapsed ? logoCollapsed ?? logo : logo;
261
+ if (nodeOverride !== void 0) return nodeOverride;
262
+ if (logoAssets) {
263
+ return /* @__PURE__ */ jsx(AppLogo, { logo: logoAssets, darkMode, minimal: collapsed });
264
+ }
265
+ if (appName) {
266
+ return /* @__PURE__ */ jsx(AppLogo, { name: appName, darkMode, minimal: collapsed });
267
+ }
268
+ return null;
269
+ }
270
+ function SidebarLogo({
271
+ logo,
272
+ logoCollapsed,
273
+ logoAssets,
274
+ appName,
275
+ darkMode,
276
+ indexPath,
277
+ LinkComponent
278
+ }) {
279
+ const { state, isMobile } = useSidebar();
280
+ const node = renderLogoForState({
281
+ logo,
282
+ logoCollapsed,
283
+ logoAssets,
284
+ appName,
285
+ darkMode,
286
+ // The mobile sheet is full-width, so always show the full logo there even if
287
+ // the desktop sidebar was left collapsed.
288
+ collapsed: state === "collapsed" && !isMobile
289
+ });
290
+ if (node === null) return null;
291
+ if (indexPath && LinkComponent) {
292
+ return /* @__PURE__ */ jsx(LinkComponent, { to: indexPath, className: "no-underline", children: node });
293
+ }
294
+ return node;
295
+ }
296
+ function EspressifFooterBranding({ darkMode }) {
297
+ const { state } = useSidebar();
298
+ return /* @__PURE__ */ jsx(
299
+ "a",
300
+ {
301
+ href: "https://www.espressif.com/",
302
+ target: "_blank",
303
+ rel: "noopener noreferrer",
304
+ className: "no-underline flex justify-center w-full opacity-25 transition-opacity duration-500 ease-in-out hover:opacity-100",
305
+ "aria-label": "Espressif",
306
+ children: /* @__PURE__ */ jsx(
307
+ AppLogo,
308
+ {
309
+ width: 120,
310
+ darkMode,
311
+ minimal: state === "collapsed"
312
+ }
313
+ )
314
+ }
315
+ );
316
+ }
317
+ function WorkspaceLayout({
318
+ appName,
319
+ logo,
320
+ logoCollapsed,
321
+ logoMobile,
322
+ logoAssets,
323
+ footerBranding,
324
+ children,
325
+ sidebarConfig,
326
+ headerConfig,
327
+ footerConfig,
328
+ sidebarOpen,
329
+ defaultSidebarOpen,
330
+ onSidebarOpenChange,
331
+ onLogoutClick,
332
+ onProfileCardClick,
333
+ onColorThemeChange,
334
+ colorTheme,
335
+ onLanguageChange,
336
+ languages,
337
+ currentLanguage,
338
+ accountMenuItems,
339
+ hideBreadcrumbs
340
+ }) {
341
+ const hideFooter = footerConfig?.hidden ?? false;
342
+ const darkMode = colorTheme === "dark";
343
+ const contentHeight = hideFooter ? "calc(100vh - var(--espd-header-height) - var(--espd-hidden-footer-height))" : "calc(100vh - var(--espd-header-height) - var(--espd-footer-height))";
344
+ const breadcrumbItems = hideBreadcrumbs ? [] : headerConfig?.breadcrumbs ?? deriveBreadcrumbs(
345
+ sidebarConfig.items,
346
+ sidebarConfig.currentPath,
347
+ sidebarConfig.indexPath
348
+ );
349
+ const defaultMobileLogo = logoAssets ? /* @__PURE__ */ jsx(AppLogo, { logo: logoAssets, darkMode, minimal: true, width: 24 }) : appName ? /* @__PURE__ */ jsx(AppLogo, { name: appName, darkMode, minimal: true, width: 24 }) : null;
350
+ const mobileLogoNode = logoMobile ?? defaultMobileLogo;
351
+ const mobileLogo = mobileLogoNode && sidebarConfig.indexPath ? /* @__PURE__ */ jsx(
352
+ sidebarConfig.LinkComponent,
353
+ {
354
+ to: sidebarConfig.indexPath,
355
+ className: "no-underline",
356
+ children: mobileLogoNode
357
+ }
358
+ ) : mobileLogoNode;
359
+ const headerLeftContent = breadcrumbItems.length > 0 ? /* @__PURE__ */ jsx(
360
+ WorkspaceBreadcrumbs,
361
+ {
362
+ items: breadcrumbItems,
363
+ LinkComponent: sidebarConfig.LinkComponent,
364
+ collapseOnMobile: headerConfig?.collapseBreadcrumbsOnMobile ?? false
365
+ }
366
+ ) : null;
367
+ let footerBrandingNode = null;
368
+ if (footerBranding === false) {
369
+ footerBrandingNode = null;
370
+ } else if (footerBranding !== void 0) {
371
+ footerBrandingNode = footerBranding;
372
+ } else if (appName && sidebarConfig.hideCompanyBranding !== true) {
373
+ footerBrandingNode = /* @__PURE__ */ jsx(EspressifFooterBranding, { darkMode });
374
+ }
375
+ const sidebarFooter = sidebarConfig.footer != null || footerBrandingNode != null ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 w-full", children: [
376
+ sidebarConfig.footer,
377
+ footerBrandingNode
378
+ ] }) : void 0;
379
+ const accountMenu = /* @__PURE__ */ jsx(
380
+ AccountMenu,
381
+ {
382
+ userName: headerConfig?.userName,
383
+ userEmail: headerConfig?.userEmail,
384
+ userProfilePictureUrl: headerConfig?.userProfilePictureUrl,
385
+ avatarBadgeColor: headerConfig?.avatarBadgeColor,
386
+ onLogoutClick,
387
+ onProfileCardClick,
388
+ onColorThemeChange,
389
+ colorTheme,
390
+ onLanguageChange,
391
+ languages,
392
+ currentLanguage,
393
+ additionalItems: accountMenuItems
394
+ }
395
+ );
396
+ return /* @__PURE__ */ jsxs(
397
+ SidebarProvider,
398
+ {
399
+ open: sidebarOpen,
400
+ defaultOpen: defaultSidebarOpen,
401
+ onOpenChange: onSidebarOpenChange,
402
+ children: [
403
+ /* @__PURE__ */ jsx(
404
+ Sidebar2,
405
+ {
406
+ items: sidebarConfig.items,
407
+ currentPath: sidebarConfig.currentPath,
408
+ header: /* @__PURE__ */ jsx(
409
+ SidebarLogo,
410
+ {
411
+ logo,
412
+ logoCollapsed,
413
+ logoAssets,
414
+ appName,
415
+ darkMode,
416
+ indexPath: sidebarConfig.indexPath,
417
+ LinkComponent: sidebarConfig.LinkComponent
418
+ }
419
+ ),
420
+ headerHeight: "var(--espd-header-height)",
421
+ footer: sidebarFooter,
422
+ LinkComponent: sidebarConfig.LinkComponent,
423
+ collapsible: sidebarConfig.allowCollapsible ? "icon" : "none",
424
+ variant: sidebarConfig.variant
425
+ }
426
+ ),
427
+ /* @__PURE__ */ jsxs(SidebarInset, { className: "overflow-hidden h-dvh max-h-dvh", children: [
428
+ /* @__PURE__ */ jsx(
429
+ Header,
430
+ {
431
+ leftContent: headerLeftContent,
432
+ rightContent: headerConfig?.rightContent,
433
+ endContent: accountMenu,
434
+ showSidebarTrigger: sidebarConfig.allowCollapsible,
435
+ mobileLogo
436
+ }
437
+ ),
438
+ /* @__PURE__ */ jsx(
439
+ "div",
440
+ {
441
+ className: "flex flex-1 flex-col gap-4 bg-sidebar",
442
+ style: {
443
+ paddingTop: "var(--espd-header-height)",
444
+ height: contentHeight
445
+ },
446
+ children: /* @__PURE__ */ jsx("main", { className: "flex-1 bg-background h-full overflow-y-auto md:rounded-tl-2xl md:rounded-bl-2xl pb-10", children })
447
+ }
448
+ ),
449
+ /* @__PURE__ */ jsx(Footer, { hidden: hideFooter })
450
+ ] })
451
+ ]
452
+ }
453
+ );
454
+ }
455
+
456
+ // src/layouts/entry-layout/entry-layout-bg.webp
457
+ var entry_layout_bg_default = "./assets/entry-layout-bg-JPI7GJ42.webp";
458
+ function EntryLayout({
459
+ appName,
460
+ children,
461
+ backgroundImageUrl,
462
+ heading,
463
+ darkMode,
464
+ logo,
465
+ logoAssets
466
+ }) {
467
+ const bgImage = backgroundImageUrl ?? entry_layout_bg_default;
468
+ const resolvedLogo = logo !== void 0 ? logo : logoAssets ? /* @__PURE__ */ jsx(AppLogo, { logo: logoAssets, darkMode, width: 256 }) : appName ? /* @__PURE__ */ jsx(AppLogo, { name: appName, darkMode, width: 256 }) : null;
469
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen w-full", children: [
470
+ /* @__PURE__ */ jsxs("div", { className: "w-[40%] flex flex-col py-12 px-10 bg-gradient-to-b from-background to-transparent max-xl:w-full max-xl:py-8 max-xl:px-5", children: [
471
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
472
+ resolvedLogo !== null && /* @__PURE__ */ jsx("div", { className: "shrink-0 flex justify-center mb-12", children: resolvedLogo }),
473
+ children
474
+ ] }),
475
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 text-center text-xs text-muted-foreground", children: /* @__PURE__ */ jsx(FooterCard, {}) })
476
+ ] }),
477
+ /* @__PURE__ */ jsx(
478
+ "div",
479
+ {
480
+ className: "w-[60%] relative bg-cover bg-center bg-no-repeat max-xl:hidden",
481
+ style: { backgroundImage: `url(${bgImage})` },
482
+ children: heading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-black/30 to-transparent flex items-center justify-center p-12", children: /* @__PURE__ */ jsx("h1", { className: "text-white text-[3.25rem] leading-[1.25] text-center max-w-full px-6 font-bold tracking-tight", children: typeof heading === "string" ? parseTextMarkup(heading) : heading }) })
483
+ }
484
+ )
485
+ ] });
486
+ }
487
+
488
+ export { AccountMenu, EntryLayout, Footer, Header, WorkspaceLayout };
@@ -1,7 +1,8 @@
1
- export { CopyrightCard, PageLoader } from '../chunk-J7YNQMAC.js';
2
- export { AnimatedRainmakerLogo } from '../chunk-MOYKF2ZC.js';
1
+ export { CopyrightCard, PageLoader } from '../chunk-742PUXQ6.js';
2
+ export { AnimatedRainmakerLogo } from '../chunk-KF3NDMZW.js';
3
3
  import '../chunk-JPMN2UMF.js';
4
4
  export { AppLogo, FooterCard, MyAccountMenu, ProfileCard } from '../chunk-SYEKNRS5.js';
5
5
  import '../chunk-34PXJOCS.js';
6
6
  import '../chunk-F5P6S7K2.js';
7
7
  import '../chunk-VU4CZ76T.js';
8
+ import '../chunk-TRTQSARU.js';