@broberg/app-shell 0.9.2 → 0.10.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/README.md +26 -0
- package/css/app-shell.css +31 -1
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/preact.cjs +103 -11
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.cts +43 -2
- package/dist/preact.d.ts +43 -2
- package/dist/preact.js +103 -11
- package/dist/preact.js.map +1 -1
- package/package.json +1 -1
package/dist/preact.d.cts
CHANGED
|
@@ -237,6 +237,9 @@ declare const TEXT: {
|
|
|
237
237
|
readonly closeMenu: "Luk menu";
|
|
238
238
|
readonly home: "Forside";
|
|
239
239
|
readonly language: "Sprog";
|
|
240
|
+
readonly zoom: "Zoom";
|
|
241
|
+
readonly zoomOut: "Zoom ud";
|
|
242
|
+
readonly zoomIn: "Zoom ind";
|
|
240
243
|
readonly couldNotMarkAll: "Kunne ikke markere alle som læst. Prøv igen.";
|
|
241
244
|
readonly collapse: "Skjul sidemenu";
|
|
242
245
|
readonly expand: "Vis sidemenu";
|
|
@@ -305,6 +308,9 @@ declare const TEXT: {
|
|
|
305
308
|
readonly closeMenu: "Close menu";
|
|
306
309
|
readonly home: "Home";
|
|
307
310
|
readonly language: "Language";
|
|
311
|
+
readonly zoom: "Zoom";
|
|
312
|
+
readonly zoomOut: "Zoom out";
|
|
313
|
+
readonly zoomIn: "Zoom in";
|
|
308
314
|
readonly couldNotMarkAll: "Could not mark all as read. Try again.";
|
|
309
315
|
readonly collapse: "Hide sidebar";
|
|
310
316
|
readonly expand: "Show sidebar";
|
|
@@ -412,6 +418,8 @@ interface SidebarProps {
|
|
|
412
418
|
/** localStorage key for which items with children are open (F092.5). */
|
|
413
419
|
itemsKey?: string;
|
|
414
420
|
lang: Lang;
|
|
421
|
+
/** F092.15 — rendered at the very bottom of the sidebar (the user menu in "sidebar-footer"). */
|
|
422
|
+
bottom?: ComponentChildren;
|
|
415
423
|
}
|
|
416
424
|
declare function Sidebar(p: SidebarProps): JSX.Element;
|
|
417
425
|
interface NotificationBellProps {
|
|
@@ -427,6 +435,8 @@ interface ShellUser {
|
|
|
427
435
|
email?: string;
|
|
428
436
|
/** Broberg ID OIDC `picture`. Without it: initials. Never Gravatar (D-1dc849). */
|
|
429
437
|
picture?: string;
|
|
438
|
+
/** F092.15 — a line under the name, e.g. «Administrator · Enhed Nord». */
|
|
439
|
+
subtitle?: string;
|
|
430
440
|
}
|
|
431
441
|
interface UserMenuItem {
|
|
432
442
|
id: string;
|
|
@@ -434,6 +444,19 @@ interface UserMenuItem {
|
|
|
434
444
|
icon?: Icon;
|
|
435
445
|
href?: string;
|
|
436
446
|
onSelect?: () => void;
|
|
447
|
+
/** F092.15 — right-aligned hint, e.g. a shortcut «⌘K». The app owns the shortcut itself. */
|
|
448
|
+
hint?: string;
|
|
449
|
+
}
|
|
450
|
+
/** F092.15 — a radio group in the user menu (organisation, unit, area …). The app owns the choice. */
|
|
451
|
+
interface UserMenuSection {
|
|
452
|
+
id: string;
|
|
453
|
+
label: string;
|
|
454
|
+
items: {
|
|
455
|
+
id: string;
|
|
456
|
+
label: string;
|
|
457
|
+
hint?: string;
|
|
458
|
+
checked?: boolean;
|
|
459
|
+
}[];
|
|
437
460
|
}
|
|
438
461
|
interface UserMenuProps {
|
|
439
462
|
user: ShellUser;
|
|
@@ -456,6 +479,19 @@ interface UserMenuProps {
|
|
|
456
479
|
}[];
|
|
457
480
|
onChange: (id: string) => void;
|
|
458
481
|
};
|
|
482
|
+
/** F092.15 — radio groups shown after your items; a pick calls onSectionSelect and closes the menu. */
|
|
483
|
+
sections?: UserMenuSection[];
|
|
484
|
+
onSectionSelect?: (sectionId: string, itemId: string) => void;
|
|
485
|
+
/** F092.15 — a «Zoom» row: − / value % / +. The app owns the value (percent). */
|
|
486
|
+
zoom?: {
|
|
487
|
+
value: number;
|
|
488
|
+
onChange: (value: number) => void;
|
|
489
|
+
min?: number;
|
|
490
|
+
max?: number;
|
|
491
|
+
step?: number;
|
|
492
|
+
};
|
|
493
|
+
/** F092.15 — where the shell put the menu. "sidebar-footer" opens upward. Set by AppShell. */
|
|
494
|
+
placement?: "topbar" | "sidebar-footer";
|
|
459
495
|
lang: Lang;
|
|
460
496
|
}
|
|
461
497
|
declare function Avatar({ user, size }: {
|
|
@@ -518,7 +554,12 @@ interface AppShellProps {
|
|
|
518
554
|
/** The notification centre's source. The bell is shown either way. */
|
|
519
555
|
notifications?: NotificationSource;
|
|
520
556
|
user?: ShellUser;
|
|
521
|
-
userMenu?: Omit<UserMenuProps, "user" | "lang" | "onNavigate">;
|
|
557
|
+
userMenu?: Omit<UserMenuProps, "user" | "lang" | "onNavigate" | "placement">;
|
|
558
|
+
/**
|
|
559
|
+
* F092.15 — where the user menu sits. "topbar" (default): the content's top row
|
|
560
|
+
* (or the full-width bar). "sidebar-footer": the bottom of the sidebar, opening upward.
|
|
561
|
+
*/
|
|
562
|
+
userMenuPlacement?: "topbar" | "sidebar-footer";
|
|
522
563
|
/** Phone behaviour: a slide-in drawer, or a 60px icon rail. */
|
|
523
564
|
mobile?: "drawer" | "rail";
|
|
524
565
|
/**
|
|
@@ -641,4 +682,4 @@ interface ConfirmDialogProps {
|
|
|
641
682
|
}
|
|
642
683
|
declare function ConfirmDialog(p: ConfirmDialogProps): JSX.Element | null;
|
|
643
684
|
|
|
644
|
-
export { AVATAR_MAX_BYTES, AVATAR_TYPES, type AccountAdapter, AccountError, AccountPage, type AccountPageProps, type AccountProfile, type AnalyticsAdapter, type AnalyticsData, type AnalyticsDay, AnalyticsError, AnalyticsPage, type AnalyticsPageProps, AppShell, type AppShellProps, Avatar, ConfirmDialog, type ConfirmDialogProps, type Lang, type NavGroup, type NavItem, type Navigate, NotificationBell, type NotificationBellProps, type NotificationSource, PageHeader, type PageTab, PageTabs, type PreactNavGroup, type PreactNavItem, type ShellUser, Sidebar, type SidebarProps, TEXT, type TenantAdapter, TenantLoadError, type TenantMembershipRow, TenantSwitcher, type TenantSwitcherProps, TopBar, type TopBarProps, UserMenu, type UserMenuItem, type UserMenuProps, accountErrorKind, activeNavLabel, analyticsErrorKind, badgeLabel, changePct, checkAvatarFile, copenhagenDay, createFetchAccountAdapter, createFetchAnalyticsAdapter, createFetchNotificationSource, createFetchTenantAdapter, createMemoryNotificationSource, defaultReauthHref, fillDays, initials, isActivePath, isExternal, readFlag, readSet, relativeTime, safeNavigate, useIsMobile, writeFlag, writeSet };
|
|
685
|
+
export { AVATAR_MAX_BYTES, AVATAR_TYPES, type AccountAdapter, AccountError, AccountPage, type AccountPageProps, type AccountProfile, type AnalyticsAdapter, type AnalyticsData, type AnalyticsDay, AnalyticsError, AnalyticsPage, type AnalyticsPageProps, AppShell, type AppShellProps, Avatar, ConfirmDialog, type ConfirmDialogProps, type Lang, type NavGroup, type NavItem, type Navigate, NotificationBell, type NotificationBellProps, type NotificationSource, PageHeader, type PageTab, PageTabs, type PreactNavGroup, type PreactNavItem, type ShellUser, Sidebar, type SidebarProps, TEXT, type TenantAdapter, TenantLoadError, type TenantMembershipRow, TenantSwitcher, type TenantSwitcherProps, TopBar, type TopBarProps, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuSection, accountErrorKind, activeNavLabel, analyticsErrorKind, badgeLabel, changePct, checkAvatarFile, copenhagenDay, createFetchAccountAdapter, createFetchAnalyticsAdapter, createFetchNotificationSource, createFetchTenantAdapter, createMemoryNotificationSource, defaultReauthHref, fillDays, initials, isActivePath, isExternal, readFlag, readSet, relativeTime, safeNavigate, useIsMobile, writeFlag, writeSet };
|
package/dist/preact.d.ts
CHANGED
|
@@ -237,6 +237,9 @@ declare const TEXT: {
|
|
|
237
237
|
readonly closeMenu: "Luk menu";
|
|
238
238
|
readonly home: "Forside";
|
|
239
239
|
readonly language: "Sprog";
|
|
240
|
+
readonly zoom: "Zoom";
|
|
241
|
+
readonly zoomOut: "Zoom ud";
|
|
242
|
+
readonly zoomIn: "Zoom ind";
|
|
240
243
|
readonly couldNotMarkAll: "Kunne ikke markere alle som læst. Prøv igen.";
|
|
241
244
|
readonly collapse: "Skjul sidemenu";
|
|
242
245
|
readonly expand: "Vis sidemenu";
|
|
@@ -305,6 +308,9 @@ declare const TEXT: {
|
|
|
305
308
|
readonly closeMenu: "Close menu";
|
|
306
309
|
readonly home: "Home";
|
|
307
310
|
readonly language: "Language";
|
|
311
|
+
readonly zoom: "Zoom";
|
|
312
|
+
readonly zoomOut: "Zoom out";
|
|
313
|
+
readonly zoomIn: "Zoom in";
|
|
308
314
|
readonly couldNotMarkAll: "Could not mark all as read. Try again.";
|
|
309
315
|
readonly collapse: "Hide sidebar";
|
|
310
316
|
readonly expand: "Show sidebar";
|
|
@@ -412,6 +418,8 @@ interface SidebarProps {
|
|
|
412
418
|
/** localStorage key for which items with children are open (F092.5). */
|
|
413
419
|
itemsKey?: string;
|
|
414
420
|
lang: Lang;
|
|
421
|
+
/** F092.15 — rendered at the very bottom of the sidebar (the user menu in "sidebar-footer"). */
|
|
422
|
+
bottom?: ComponentChildren;
|
|
415
423
|
}
|
|
416
424
|
declare function Sidebar(p: SidebarProps): JSX.Element;
|
|
417
425
|
interface NotificationBellProps {
|
|
@@ -427,6 +435,8 @@ interface ShellUser {
|
|
|
427
435
|
email?: string;
|
|
428
436
|
/** Broberg ID OIDC `picture`. Without it: initials. Never Gravatar (D-1dc849). */
|
|
429
437
|
picture?: string;
|
|
438
|
+
/** F092.15 — a line under the name, e.g. «Administrator · Enhed Nord». */
|
|
439
|
+
subtitle?: string;
|
|
430
440
|
}
|
|
431
441
|
interface UserMenuItem {
|
|
432
442
|
id: string;
|
|
@@ -434,6 +444,19 @@ interface UserMenuItem {
|
|
|
434
444
|
icon?: Icon;
|
|
435
445
|
href?: string;
|
|
436
446
|
onSelect?: () => void;
|
|
447
|
+
/** F092.15 — right-aligned hint, e.g. a shortcut «⌘K». The app owns the shortcut itself. */
|
|
448
|
+
hint?: string;
|
|
449
|
+
}
|
|
450
|
+
/** F092.15 — a radio group in the user menu (organisation, unit, area …). The app owns the choice. */
|
|
451
|
+
interface UserMenuSection {
|
|
452
|
+
id: string;
|
|
453
|
+
label: string;
|
|
454
|
+
items: {
|
|
455
|
+
id: string;
|
|
456
|
+
label: string;
|
|
457
|
+
hint?: string;
|
|
458
|
+
checked?: boolean;
|
|
459
|
+
}[];
|
|
437
460
|
}
|
|
438
461
|
interface UserMenuProps {
|
|
439
462
|
user: ShellUser;
|
|
@@ -456,6 +479,19 @@ interface UserMenuProps {
|
|
|
456
479
|
}[];
|
|
457
480
|
onChange: (id: string) => void;
|
|
458
481
|
};
|
|
482
|
+
/** F092.15 — radio groups shown after your items; a pick calls onSectionSelect and closes the menu. */
|
|
483
|
+
sections?: UserMenuSection[];
|
|
484
|
+
onSectionSelect?: (sectionId: string, itemId: string) => void;
|
|
485
|
+
/** F092.15 — a «Zoom» row: − / value % / +. The app owns the value (percent). */
|
|
486
|
+
zoom?: {
|
|
487
|
+
value: number;
|
|
488
|
+
onChange: (value: number) => void;
|
|
489
|
+
min?: number;
|
|
490
|
+
max?: number;
|
|
491
|
+
step?: number;
|
|
492
|
+
};
|
|
493
|
+
/** F092.15 — where the shell put the menu. "sidebar-footer" opens upward. Set by AppShell. */
|
|
494
|
+
placement?: "topbar" | "sidebar-footer";
|
|
459
495
|
lang: Lang;
|
|
460
496
|
}
|
|
461
497
|
declare function Avatar({ user, size }: {
|
|
@@ -518,7 +554,12 @@ interface AppShellProps {
|
|
|
518
554
|
/** The notification centre's source. The bell is shown either way. */
|
|
519
555
|
notifications?: NotificationSource;
|
|
520
556
|
user?: ShellUser;
|
|
521
|
-
userMenu?: Omit<UserMenuProps, "user" | "lang" | "onNavigate">;
|
|
557
|
+
userMenu?: Omit<UserMenuProps, "user" | "lang" | "onNavigate" | "placement">;
|
|
558
|
+
/**
|
|
559
|
+
* F092.15 — where the user menu sits. "topbar" (default): the content's top row
|
|
560
|
+
* (or the full-width bar). "sidebar-footer": the bottom of the sidebar, opening upward.
|
|
561
|
+
*/
|
|
562
|
+
userMenuPlacement?: "topbar" | "sidebar-footer";
|
|
522
563
|
/** Phone behaviour: a slide-in drawer, or a 60px icon rail. */
|
|
523
564
|
mobile?: "drawer" | "rail";
|
|
524
565
|
/**
|
|
@@ -641,4 +682,4 @@ interface ConfirmDialogProps {
|
|
|
641
682
|
}
|
|
642
683
|
declare function ConfirmDialog(p: ConfirmDialogProps): JSX.Element | null;
|
|
643
684
|
|
|
644
|
-
export { AVATAR_MAX_BYTES, AVATAR_TYPES, type AccountAdapter, AccountError, AccountPage, type AccountPageProps, type AccountProfile, type AnalyticsAdapter, type AnalyticsData, type AnalyticsDay, AnalyticsError, AnalyticsPage, type AnalyticsPageProps, AppShell, type AppShellProps, Avatar, ConfirmDialog, type ConfirmDialogProps, type Lang, type NavGroup, type NavItem, type Navigate, NotificationBell, type NotificationBellProps, type NotificationSource, PageHeader, type PageTab, PageTabs, type PreactNavGroup, type PreactNavItem, type ShellUser, Sidebar, type SidebarProps, TEXT, type TenantAdapter, TenantLoadError, type TenantMembershipRow, TenantSwitcher, type TenantSwitcherProps, TopBar, type TopBarProps, UserMenu, type UserMenuItem, type UserMenuProps, accountErrorKind, activeNavLabel, analyticsErrorKind, badgeLabel, changePct, checkAvatarFile, copenhagenDay, createFetchAccountAdapter, createFetchAnalyticsAdapter, createFetchNotificationSource, createFetchTenantAdapter, createMemoryNotificationSource, defaultReauthHref, fillDays, initials, isActivePath, isExternal, readFlag, readSet, relativeTime, safeNavigate, useIsMobile, writeFlag, writeSet };
|
|
685
|
+
export { AVATAR_MAX_BYTES, AVATAR_TYPES, type AccountAdapter, AccountError, AccountPage, type AccountPageProps, type AccountProfile, type AnalyticsAdapter, type AnalyticsData, type AnalyticsDay, AnalyticsError, AnalyticsPage, type AnalyticsPageProps, AppShell, type AppShellProps, Avatar, ConfirmDialog, type ConfirmDialogProps, type Lang, type NavGroup, type NavItem, type Navigate, NotificationBell, type NotificationBellProps, type NotificationSource, PageHeader, type PageTab, PageTabs, type PreactNavGroup, type PreactNavItem, type ShellUser, Sidebar, type SidebarProps, TEXT, type TenantAdapter, TenantLoadError, type TenantMembershipRow, TenantSwitcher, type TenantSwitcherProps, TopBar, type TopBarProps, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuSection, accountErrorKind, activeNavLabel, analyticsErrorKind, badgeLabel, changePct, checkAvatarFile, copenhagenDay, createFetchAccountAdapter, createFetchAnalyticsAdapter, createFetchNotificationSource, createFetchTenantAdapter, createMemoryNotificationSource, defaultReauthHref, fillDays, initials, isActivePath, isExternal, readFlag, readSet, relativeTime, safeNavigate, useIsMobile, writeFlag, writeSet };
|
package/dist/preact.js
CHANGED
|
@@ -304,6 +304,9 @@ var TEXT = {
|
|
|
304
304
|
closeMenu: "Luk menu",
|
|
305
305
|
home: "Forside",
|
|
306
306
|
language: "Sprog",
|
|
307
|
+
zoom: "Zoom",
|
|
308
|
+
zoomOut: "Zoom ud",
|
|
309
|
+
zoomIn: "Zoom ind",
|
|
307
310
|
couldNotMarkAll: "Kunne ikke markere alle som l\xE6st. Pr\xF8v igen.",
|
|
308
311
|
collapse: "Skjul sidemenu",
|
|
309
312
|
expand: "Vis sidemenu",
|
|
@@ -372,6 +375,9 @@ var TEXT = {
|
|
|
372
375
|
closeMenu: "Close menu",
|
|
373
376
|
home: "Home",
|
|
374
377
|
language: "Language",
|
|
378
|
+
zoom: "Zoom",
|
|
379
|
+
zoomOut: "Zoom out",
|
|
380
|
+
zoomIn: "Zoom in",
|
|
375
381
|
couldNotMarkAll: "Could not mark all as read. Try again.",
|
|
376
382
|
collapse: "Hide sidebar",
|
|
377
383
|
expand: "Show sidebar",
|
|
@@ -655,7 +661,8 @@ function Sidebar(p) {
|
|
|
655
661
|
open ? g.items.map(item) : null
|
|
656
662
|
] }, g.label);
|
|
657
663
|
}) }),
|
|
658
|
-
p.footer?.length ? /* @__PURE__ */ jsx("div", { class: "bas-sidebar__foot", children: p.footer.map(item) }) : null
|
|
664
|
+
p.footer?.length ? /* @__PURE__ */ jsx("div", { class: "bas-sidebar__foot", children: p.footer.map(item) }) : null,
|
|
665
|
+
p.bottom ? /* @__PURE__ */ jsx("div", { class: "bas-sidebar__user", "data-testid": "sidebar-user", children: p.bottom }) : null
|
|
659
666
|
]
|
|
660
667
|
}
|
|
661
668
|
)
|
|
@@ -876,28 +883,48 @@ function UserMenu(p) {
|
|
|
876
883
|
setOpen(false);
|
|
877
884
|
}
|
|
878
885
|
};
|
|
879
|
-
|
|
886
|
+
const inSidebar = p.placement === "sidebar-footer";
|
|
887
|
+
const btn = useRef(null);
|
|
888
|
+
const [upPos, setUpPos] = useState(void 0);
|
|
889
|
+
useLayoutEffect(() => {
|
|
890
|
+
if (!open || !inSidebar || !btn.current) return;
|
|
891
|
+
const r = btn.current.getBoundingClientRect();
|
|
892
|
+
const vw = window.innerWidth, vh = window.innerHeight;
|
|
893
|
+
const railed = !!btn.current.closest(".is-railed");
|
|
894
|
+
const width = Math.min(320, vw - 16);
|
|
895
|
+
const left = railed ? r.right + 8 : Math.max(8, Math.min(r.left, vw - width - 8));
|
|
896
|
+
const bottom = railed ? Math.max(8, vh - r.bottom) : vh - r.top + 8;
|
|
897
|
+
setUpPos({ position: "fixed", left: `${left}px`, bottom: `${bottom}px`, width: `${width}px`, maxHeight: `${vh - bottom - 8}px` });
|
|
898
|
+
}, [open, inSidebar]);
|
|
899
|
+
const zoom = p.zoom;
|
|
900
|
+
const zMin = zoom?.min ?? 50, zMax = zoom?.max ?? 200, zStep = zoom?.step ?? 10;
|
|
901
|
+
return /* @__PURE__ */ jsxs("div", { class: "bas-usermenu" + (inSidebar ? " is-sidebar" : ""), ref: root, children: [
|
|
880
902
|
/* @__PURE__ */ jsxs(
|
|
881
903
|
"button",
|
|
882
904
|
{
|
|
905
|
+
ref: btn,
|
|
883
906
|
type: "button",
|
|
884
|
-
class: "bas-userbtn" + (open ? " is-open" : ""),
|
|
885
|
-
"data-testid": "topbar-user-menu",
|
|
907
|
+
class: "bas-userbtn" + (open ? " is-open" : "") + (inSidebar ? " is-sidebar" : ""),
|
|
908
|
+
"data-testid": inSidebar ? "sidebar-user-menu" : "topbar-user-menu",
|
|
886
909
|
"aria-haspopup": "menu",
|
|
887
910
|
"aria-expanded": open,
|
|
888
911
|
"aria-label": p.user.email ?? p.user.name ?? t.account,
|
|
889
912
|
onClick: () => setOpen((v) => !v),
|
|
890
913
|
children: [
|
|
891
|
-
/* @__PURE__ */ jsx(Avatar, { user: p.user }),
|
|
892
|
-
/* @__PURE__ */
|
|
914
|
+
/* @__PURE__ */ jsx(Avatar, { user: p.user, size: inSidebar ? 32 : 28 }),
|
|
915
|
+
inSidebar ? /* @__PURE__ */ jsxs("span", { class: "bas-userbtn__text", children: [
|
|
916
|
+
/* @__PURE__ */ jsx("span", { class: "bas-userbtn__name", children: p.user.name ?? firstName }),
|
|
917
|
+
p.user.subtitle ? /* @__PURE__ */ jsx("span", { class: "bas-userbtn__sub", "data-testid": "sidebar-user-subtitle", children: p.user.subtitle }) : null
|
|
918
|
+
] }) : /* @__PURE__ */ jsx("span", { class: "bas-userbtn__name", children: firstName })
|
|
893
919
|
]
|
|
894
920
|
}
|
|
895
921
|
),
|
|
896
|
-
open ? /* @__PURE__ */ jsxs("div", { class: "bas-menu", role: "menu", "data-testid": "topbar-user-menu-dropdown", children: [
|
|
922
|
+
open ? /* @__PURE__ */ jsxs("div", { class: "bas-menu" + (inSidebar ? " is-up" : ""), style: inSidebar ? upPos : void 0, role: "menu", "data-testid": "topbar-user-menu-dropdown", children: [
|
|
897
923
|
/* @__PURE__ */ jsxs("div", { class: "bas-menu__who", children: [
|
|
898
924
|
/* @__PURE__ */ jsx(Avatar, { user: p.user, size: 36 }),
|
|
899
925
|
/* @__PURE__ */ jsxs("div", { class: "bas-menu__whotext", children: [
|
|
900
926
|
p.user.name ? /* @__PURE__ */ jsx("div", { class: "bas-menu__name", children: p.user.name }) : null,
|
|
927
|
+
p.user.subtitle ? /* @__PURE__ */ jsx("div", { class: "bas-menu__sub", children: p.user.subtitle }) : null,
|
|
901
928
|
p.user.email ? /* @__PURE__ */ jsx("div", { class: "bas-menu__email", children: p.user.email }) : null
|
|
902
929
|
] })
|
|
903
930
|
] }),
|
|
@@ -909,7 +936,8 @@ function UserMenu(p) {
|
|
|
909
936
|
(p.items ?? []).map(
|
|
910
937
|
(it) => it.href ? /* @__PURE__ */ jsxs(NavLink, { href: it.href, onNavigate: p.onNavigate, onAfter: () => setOpen(false), class: "bas-mi", "data-testid": `user-menu-${it.id}`, children: [
|
|
911
938
|
it.icon ?? null,
|
|
912
|
-
/* @__PURE__ */ jsx("span", { children: it.label })
|
|
939
|
+
/* @__PURE__ */ jsx("span", { children: it.label }),
|
|
940
|
+
it.hint ? /* @__PURE__ */ jsx("span", { class: "bas-mi__hint", children: it.hint }) : null
|
|
913
941
|
] }, it.id) : /* @__PURE__ */ jsxs(
|
|
914
942
|
"button",
|
|
915
943
|
{
|
|
@@ -923,12 +951,37 @@ function UserMenu(p) {
|
|
|
923
951
|
},
|
|
924
952
|
children: [
|
|
925
953
|
it.icon ?? null,
|
|
926
|
-
/* @__PURE__ */ jsx("span", { children: it.label })
|
|
954
|
+
/* @__PURE__ */ jsx("span", { children: it.label }),
|
|
955
|
+
it.hint ? /* @__PURE__ */ jsx("span", { class: "bas-mi__hint", children: it.hint }) : null
|
|
927
956
|
]
|
|
928
957
|
},
|
|
929
958
|
it.id
|
|
930
959
|
)
|
|
931
960
|
),
|
|
961
|
+
(p.sections ?? []).map((sec) => /* @__PURE__ */ jsxs("div", { class: "bas-menu__section", role: "group", "aria-label": sec.label, "data-testid": `user-menu-section-${sec.id}`, children: [
|
|
962
|
+
/* @__PURE__ */ jsx("div", { class: "bas-sep" }),
|
|
963
|
+
/* @__PURE__ */ jsx("div", { class: "bas-menu__label", children: sec.label }),
|
|
964
|
+
sec.items.map((it) => /* @__PURE__ */ jsxs(
|
|
965
|
+
"button",
|
|
966
|
+
{
|
|
967
|
+
type: "button",
|
|
968
|
+
class: "bas-mi" + (it.checked ? " is-checked" : ""),
|
|
969
|
+
role: "menuitemradio",
|
|
970
|
+
"aria-checked": it.checked ? "true" : "false",
|
|
971
|
+
"data-testid": `user-menu-section-${sec.id}-${it.id}`,
|
|
972
|
+
onClick: () => {
|
|
973
|
+
setOpen(false);
|
|
974
|
+
p.onSectionSelect?.(sec.id, it.id);
|
|
975
|
+
},
|
|
976
|
+
children: [
|
|
977
|
+
/* @__PURE__ */ jsx("span", { class: "bas-mi__check", "aria-hidden": "true", children: it.checked ? "\u2713" : "" }),
|
|
978
|
+
/* @__PURE__ */ jsx("span", { children: it.label }),
|
|
979
|
+
it.hint ? /* @__PURE__ */ jsx("span", { class: "bas-mi__hint", children: it.hint }) : null
|
|
980
|
+
]
|
|
981
|
+
},
|
|
982
|
+
it.id
|
|
983
|
+
))
|
|
984
|
+
] }, sec.id)),
|
|
932
985
|
p.appearance !== false ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
933
986
|
/* @__PURE__ */ jsx("div", { class: "bas-sep" }),
|
|
934
987
|
/* @__PURE__ */ jsxs("div", { class: "bas-prefs", children: [
|
|
@@ -977,6 +1030,42 @@ function UserMenu(p) {
|
|
|
977
1030
|
)
|
|
978
1031
|
] }) })
|
|
979
1032
|
] }) : null,
|
|
1033
|
+
zoom ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1034
|
+
p.appearance === false && !p.language ? /* @__PURE__ */ jsx("div", { class: "bas-sep" }) : null,
|
|
1035
|
+
/* @__PURE__ */ jsx("div", { class: "bas-prefs", children: /* @__PURE__ */ jsxs("div", { class: "bas-pref", children: [
|
|
1036
|
+
/* @__PURE__ */ jsx("span", { children: t.zoom }),
|
|
1037
|
+
/* @__PURE__ */ jsxs("div", { class: "bas-zoom", role: "group", "aria-label": t.zoom, children: [
|
|
1038
|
+
/* @__PURE__ */ jsx(
|
|
1039
|
+
"button",
|
|
1040
|
+
{
|
|
1041
|
+
type: "button",
|
|
1042
|
+
class: "bas-zoom__btn",
|
|
1043
|
+
"data-testid": "user-menu-zoom-out",
|
|
1044
|
+
"aria-label": t.zoomOut,
|
|
1045
|
+
disabled: zoom.value - zStep < zMin,
|
|
1046
|
+
onClick: () => zoom.onChange(Math.max(zMin, zoom.value - zStep)),
|
|
1047
|
+
children: "\u2212"
|
|
1048
|
+
}
|
|
1049
|
+
),
|
|
1050
|
+
/* @__PURE__ */ jsxs("span", { class: "bas-zoom__value", "data-testid": "user-menu-zoom-value", children: [
|
|
1051
|
+
zoom.value,
|
|
1052
|
+
" %"
|
|
1053
|
+
] }),
|
|
1054
|
+
/* @__PURE__ */ jsx(
|
|
1055
|
+
"button",
|
|
1056
|
+
{
|
|
1057
|
+
type: "button",
|
|
1058
|
+
class: "bas-zoom__btn",
|
|
1059
|
+
"data-testid": "user-menu-zoom-in",
|
|
1060
|
+
"aria-label": t.zoomIn,
|
|
1061
|
+
disabled: zoom.value + zStep > zMax,
|
|
1062
|
+
onClick: () => zoom.onChange(Math.min(zMax, zoom.value + zStep)),
|
|
1063
|
+
children: "+"
|
|
1064
|
+
}
|
|
1065
|
+
)
|
|
1066
|
+
] })
|
|
1067
|
+
] }) })
|
|
1068
|
+
] }) : null,
|
|
980
1069
|
p.onSignOut ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
981
1070
|
/* @__PURE__ */ jsx("div", { class: "bas-sep" }),
|
|
982
1071
|
/* @__PURE__ */ jsxs("button", { type: "button", class: "bas-mi is-danger", role: "menuitem", "data-testid": "topbar-sign-out", disabled: busy, onClick: () => void signOut(), children: [
|
|
@@ -1043,6 +1132,8 @@ function AppShell(p) {
|
|
|
1043
1132
|
const expanded = drawerMode ? drawer : !collapsed;
|
|
1044
1133
|
const triggerLabel = drawerMode ? drawer ? t.closeMenu : t.openMenu : collapsed ? t.expand : t.collapse;
|
|
1045
1134
|
const heading = p.title ?? activeNavLabel(p.groups, p.footer, p.currentPath);
|
|
1135
|
+
const userInSidebar = p.userMenuPlacement === "sidebar-footer";
|
|
1136
|
+
const sidebarUser = userInSidebar && p.user ? /* @__PURE__ */ jsx(UserMenu, { user: p.user, ...p.userMenu, placement: "sidebar-footer", onNavigate: p.onNavigate, lang: p.lang }) : null;
|
|
1046
1137
|
return /* @__PURE__ */ jsxs("div", { class: "bas-root", "data-testid": "app-shell", "data-mobile": mode, "data-layout": layout, children: [
|
|
1047
1138
|
inset ? null : /* @__PURE__ */ jsx(
|
|
1048
1139
|
TopBar,
|
|
@@ -1052,7 +1143,7 @@ function AppShell(p) {
|
|
|
1052
1143
|
onHome: () => setDrawer(false),
|
|
1053
1144
|
actions: p.actions,
|
|
1054
1145
|
notifications: p.notifications,
|
|
1055
|
-
user: p.user,
|
|
1146
|
+
user: userInSidebar ? void 0 : p.user,
|
|
1056
1147
|
userMenu: p.userMenu,
|
|
1057
1148
|
onNavigate: p.onNavigate,
|
|
1058
1149
|
lang: p.lang
|
|
@@ -1078,6 +1169,7 @@ function AppShell(p) {
|
|
|
1078
1169
|
brandTestId: inset ? "brand-home" : void 0,
|
|
1079
1170
|
groupsKey: `${prefix}.groups`,
|
|
1080
1171
|
itemsKey: `${prefix}.items`,
|
|
1172
|
+
bottom: sidebarUser,
|
|
1081
1173
|
lang: p.lang
|
|
1082
1174
|
}
|
|
1083
1175
|
),
|
|
@@ -1104,7 +1196,7 @@ function AppShell(p) {
|
|
|
1104
1196
|
/* @__PURE__ */ jsx("div", { class: "bas-spacer" }),
|
|
1105
1197
|
p.actions ? /* @__PURE__ */ jsx("div", { class: "bas-contenthead__actions", children: p.actions }) : null,
|
|
1106
1198
|
/* @__PURE__ */ jsx(NotificationBell, { source: p.notifications, onNavigate: p.onNavigate, lang: p.lang }),
|
|
1107
|
-
p.user ? /* @__PURE__ */ jsx(UserMenu, { user: p.user, ...p.userMenu, onNavigate: p.onNavigate, lang: p.lang }) : null
|
|
1199
|
+
p.user && !userInSidebar ? /* @__PURE__ */ jsx(UserMenu, { user: p.user, ...p.userMenu, onNavigate: p.onNavigate, lang: p.lang }) : null
|
|
1108
1200
|
] }) : null
|
|
1109
1201
|
] }),
|
|
1110
1202
|
p.children
|