@broberg/app-shell 0.19.0 → 0.20.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/preact.d.cts CHANGED
@@ -459,6 +459,34 @@ type PreactNavGroup = NavGroup<Icon>;
459
459
  type Navigate = (href: string) => void;
460
460
  /** True below 768px. Follows the window as it resizes. */
461
461
  declare function useIsMobile(): boolean;
462
+ interface ItemActionsMenuProps {
463
+ /** The menu's items — the same NavAction[] a sidebar row takes (kbd, submenu, input, confirm, danger). */
464
+ actions: NavAction[];
465
+ /** What the menu opens from: positioned from it, and focus returns to it on close. */
466
+ anchor: HTMLElement;
467
+ /** An action was chosen (value = the text, for an input action). The menu has closed. */
468
+ onAction: (actionId: string, value?: string) => void;
469
+ /** The menu closed — by a pick, Escape, a click outside, scroll or resize. Unmount it here. */
470
+ onClose: () => void;
471
+ lang: Lang;
472
+ /** The menu's accessible name, e.g. the conversation's title. */
473
+ label: string;
474
+ /** "auto" (default): below the anchor if it fits, else above. "down": always below. */
475
+ placement?: "auto" | "down";
476
+ /** testids: `<prefix>-menu`, `<prefix>-action-<id>`, `<prefix>-back`, `<prefix>-input`, `<prefix>-save`. Default "item-actions". */
477
+ testidPrefix?: string;
478
+ }
479
+ /**
480
+ * F092.29 — the row-action menu on its own, so a title «⌄» and a sidebar row «…»
481
+ * open THE SAME menu (scout #2745). The sidebar's row menu is this component: one
482
+ * implementation, so keyboard, confirm, input and submenu cannot drift apart.
483
+ * Mount it while open; it closes itself through onClose.
484
+ *
485
+ * Keys (F092.21/.22): focus moves into the menu when it opens; arrows move real
486
+ * focus; Enter/Space act on the FOCUSED item; a kbd letter picks; ←/Backspace goes
487
+ * back from a submenu; Escape closes and returns focus to the anchor.
488
+ */
489
+ declare function ItemActionsMenu(props: ItemActionsMenuProps): JSX.Element;
462
490
  interface SidebarProps {
463
491
  groups: PreactNavGroup[];
464
492
  footer?: PreactNavItem[];
@@ -774,4 +802,4 @@ interface ConfirmDialogProps {
774
802
  }
775
803
  declare function ConfirmDialog(p: ConfirmDialogProps): JSX.Element | null;
776
804
 
777
- 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 NavAction, type NavGroup, type NavItem, type NavSection, 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 };
805
+ 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, ItemActionsMenu, type ItemActionsMenuProps, type Lang, type NavAction, type NavGroup, type NavItem, type NavSection, 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
@@ -459,6 +459,34 @@ type PreactNavGroup = NavGroup<Icon>;
459
459
  type Navigate = (href: string) => void;
460
460
  /** True below 768px. Follows the window as it resizes. */
461
461
  declare function useIsMobile(): boolean;
462
+ interface ItemActionsMenuProps {
463
+ /** The menu's items — the same NavAction[] a sidebar row takes (kbd, submenu, input, confirm, danger). */
464
+ actions: NavAction[];
465
+ /** What the menu opens from: positioned from it, and focus returns to it on close. */
466
+ anchor: HTMLElement;
467
+ /** An action was chosen (value = the text, for an input action). The menu has closed. */
468
+ onAction: (actionId: string, value?: string) => void;
469
+ /** The menu closed — by a pick, Escape, a click outside, scroll or resize. Unmount it here. */
470
+ onClose: () => void;
471
+ lang: Lang;
472
+ /** The menu's accessible name, e.g. the conversation's title. */
473
+ label: string;
474
+ /** "auto" (default): below the anchor if it fits, else above. "down": always below. */
475
+ placement?: "auto" | "down";
476
+ /** testids: `<prefix>-menu`, `<prefix>-action-<id>`, `<prefix>-back`, `<prefix>-input`, `<prefix>-save`. Default "item-actions". */
477
+ testidPrefix?: string;
478
+ }
479
+ /**
480
+ * F092.29 — the row-action menu on its own, so a title «⌄» and a sidebar row «…»
481
+ * open THE SAME menu (scout #2745). The sidebar's row menu is this component: one
482
+ * implementation, so keyboard, confirm, input and submenu cannot drift apart.
483
+ * Mount it while open; it closes itself through onClose.
484
+ *
485
+ * Keys (F092.21/.22): focus moves into the menu when it opens; arrows move real
486
+ * focus; Enter/Space act on the FOCUSED item; a kbd letter picks; ←/Backspace goes
487
+ * back from a submenu; Escape closes and returns focus to the anchor.
488
+ */
489
+ declare function ItemActionsMenu(props: ItemActionsMenuProps): JSX.Element;
462
490
  interface SidebarProps {
463
491
  groups: PreactNavGroup[];
464
492
  footer?: PreactNavItem[];
@@ -774,4 +802,4 @@ interface ConfirmDialogProps {
774
802
  }
775
803
  declare function ConfirmDialog(p: ConfirmDialogProps): JSX.Element | null;
776
804
 
777
- 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 NavAction, type NavGroup, type NavItem, type NavSection, 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 };
805
+ 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, ItemActionsMenu, type ItemActionsMenuProps, type Lang, type NavAction, type NavGroup, type NavItem, type NavSection, 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
@@ -1,8 +1,8 @@
1
- import { useState, useEffect, useRef, useMemo, useLayoutEffect } from 'preact/hooks';
1
+ import { useState, useEffect, useRef, useLayoutEffect, useMemo } from 'preact/hooks';
2
2
  import { createBellShell } from '@broberg/notifications/shell';
3
3
  import { selectKeyReducer } from '@broberg/ui-controls-core';
4
4
  import { getPreference, getPalette, getSurfaces, getBackdrop, onThemeChange, onPaletteChange, onSurfacesChange, onBackdropChange, setPreference, setPalette, PALETTES, PALETTE_LABELS, setSurfaces, setBackdrop } from '@broberg/theme';
5
- import { jsxs, Fragment, jsx } from 'preact/jsx-runtime';
5
+ import { jsxs, jsx, Fragment } from 'preact/jsx-runtime';
6
6
 
7
7
  // src/preact.tsx
8
8
 
@@ -514,12 +514,17 @@ var IconBuilding = () => svg(/* @__PURE__ */ jsxs(Fragment, { children: [
514
514
  /* @__PURE__ */ jsx("path", { d: "M9 22v-4h6v4" }),
515
515
  /* @__PURE__ */ jsx("path", { d: "M8 6h.01M16 6h.01M12 6h.01M12 10h.01M12 14h.01M16 10h.01M16 14h.01M8 10h.01M8 14h.01" })
516
516
  ] }), 15);
517
- function RowActions(props) {
517
+ function ItemActionsMenu(props) {
518
518
  const t = TEXT[props.lang];
519
- const id = props.item.id;
520
- const btn = useRef(null);
519
+ const pre = props.testidPrefix ?? "item-actions";
521
520
  const menu = useRef(null);
522
- const [stack, setStack] = useState([]);
521
+ const first = [{ kind: "list", actions: props.actions }];
522
+ const [stack, setStack] = useState(first);
523
+ const stackRef = useRef(first);
524
+ const setStackNow = (next) => {
525
+ stackRef.current = next;
526
+ setStack(next);
527
+ };
523
528
  const [hi, setHiState] = useState(0);
524
529
  const hiRef = useRef(0);
525
530
  const setHi = (n) => {
@@ -538,16 +543,12 @@ function RowActions(props) {
538
543
  const [value, setValue] = useState("");
539
544
  const [pos, setPos] = useState(void 0);
540
545
  const view = stack[stack.length - 1];
541
- const open = !!view;
542
- const stackRef = useRef([]);
543
- const setStackNow = (next) => {
544
- stackRef.current = next;
545
- setStack(next);
546
- };
546
+ const closed = useRef(false);
547
547
  const close = (refocus = true) => {
548
- setStackNow([]);
549
- setArmed(null);
550
- if (refocus) btn.current?.focus();
548
+ if (closed.current) return;
549
+ closed.current = true;
550
+ if (refocus) props.anchor.focus();
551
+ props.onClose();
551
552
  };
552
553
  const show = (v) => {
553
554
  setStackNow([...stackRef.current, v]);
@@ -572,25 +573,24 @@ function RowActions(props) {
572
573
  props.onAction(a.id, value);
573
574
  };
574
575
  useLayoutEffect(() => {
575
- if (!open || !btn.current) return setPos(void 0);
576
- const r = btn.current.getBoundingClientRect();
576
+ const r = props.anchor.getBoundingClientRect();
577
577
  const vw = window.innerWidth, vh = window.innerHeight, m = 8;
578
578
  const w = Math.min(240, vw - 2 * m);
579
579
  const h = menu.current?.offsetHeight ?? 0;
580
580
  const left = Math.max(m, Math.min(r.right - w, vw - w - m));
581
- const top = r.bottom + 4 + h <= vh - m || r.top - 4 - h < m ? Math.min(r.bottom + 4, vh - m - h) : r.top - 4 - h;
581
+ const fitsBelow = r.bottom + 4 + h <= vh - m;
582
+ const top = props.placement === "down" || fitsBelow || r.top - 4 - h < m ? Math.min(r.bottom + 4, vh - m - h) : r.top - 4 - h;
582
583
  setPos({ position: "fixed", left: `${left}px`, top: `${Math.max(m, top)}px`, width: `${w}px` });
583
- }, [open, stack.length]);
584
+ }, [stack.length]);
584
585
  useLayoutEffect(() => {
585
- if (!open || !pos) return;
586
- if (view?.kind === "input") menu.current?.querySelector("input")?.focus();
586
+ if (!pos) return;
587
+ if (view.kind === "input") menu.current?.querySelector("input")?.focus();
587
588
  else items.current[hiRef.current]?.focus();
588
- }, [open, pos, hi, stack.length]);
589
+ }, [pos, hi, stack.length]);
589
590
  useLayoutEffect(() => {
590
- if (!open) return;
591
591
  const outside = (e) => {
592
592
  const n = e.target instanceof Node ? e.target : null;
593
- if (n && (menu.current?.contains(n) || btn.current?.contains(n))) return;
593
+ if (n && (menu.current?.contains(n) || props.anchor.contains(n))) return;
594
594
  close(false);
595
595
  };
596
596
  const early = (e) => {
@@ -609,8 +609,9 @@ function RowActions(props) {
609
609
  window.removeEventListener("scroll", outside, true);
610
610
  window.removeEventListener("resize", outside);
611
611
  };
612
- }, [open]);
612
+ }, []);
613
613
  const onKeyDown = (e) => {
614
+ if (closed.current) return;
614
615
  const stack2 = stackRef.current;
615
616
  const view2 = stack2[stack2.length - 1];
616
617
  if (!view2) return;
@@ -653,6 +654,82 @@ function RowActions(props) {
653
654
  }
654
655
  };
655
656
  onKeyDownRef.current = onKeyDown;
657
+ return /* @__PURE__ */ jsxs(
658
+ "div",
659
+ {
660
+ ref: menu,
661
+ class: "bas-rowmenu",
662
+ role: "menu",
663
+ tabIndex: -1,
664
+ "aria-label": view.kind === "list" && view.title ? view.title : props.label,
665
+ "data-testid": `${pre}-menu`,
666
+ style: pos ?? { position: "fixed", visibility: "hidden" },
667
+ onKeyDown,
668
+ children: [
669
+ stack.length > 1 ? /* @__PURE__ */ jsxs("button", { type: "button", class: "bas-rowmenu__back", "data-testid": `${pre}-back`, "aria-label": t.back, onClick: back, children: [
670
+ /* @__PURE__ */ jsx(IconChevronLeft, {}),
671
+ /* @__PURE__ */ jsx("span", { children: view.kind === "list" ? view.title : view.action.label })
672
+ ] }) : null,
673
+ view.kind === "list" ? view.actions.map((a, i) => /* @__PURE__ */ jsxs(
674
+ "button",
675
+ {
676
+ type: "button",
677
+ role: "menuitem",
678
+ ref: (el) => {
679
+ items.current[i] = el;
680
+ },
681
+ tabIndex: i === hi ? 0 : -1,
682
+ class: "bas-rowmenu__item" + (i === hi ? " is-active" : "") + (a.danger ? " is-danger" : "") + (armed === a.id ? " is-armed" : ""),
683
+ "data-testid": `${pre}-action-${a.id}`,
684
+ onMouseEnter: () => setHi(i),
685
+ onFocus: () => setHi(i),
686
+ onClick: () => pick(a),
687
+ children: [
688
+ a.icon ? /* @__PURE__ */ jsx("span", { class: "bas-rowmenu__icon", children: a.icon }) : null,
689
+ /* @__PURE__ */ jsx("span", { class: "bas-rowmenu__label", children: armed === a.id && a.confirm ? a.confirm.label : a.label }),
690
+ a.submenu?.length ? /* @__PURE__ */ jsx(IconChevronRight, {}) : a.kbd ? /* @__PURE__ */ jsx("kbd", { class: "bas-rowmenu__kbd", children: a.kbd.toUpperCase() }) : null
691
+ ]
692
+ },
693
+ a.id
694
+ )) : /* @__PURE__ */ jsxs(
695
+ "form",
696
+ {
697
+ class: "bas-rowmenu__form",
698
+ "data-testid": `${pre}-form`,
699
+ onSubmit: (e) => {
700
+ e.preventDefault();
701
+ save(view.action);
702
+ },
703
+ children: [
704
+ /* @__PURE__ */ jsx(
705
+ "input",
706
+ {
707
+ class: "bas-rowmenu__input",
708
+ "data-testid": `${pre}-input`,
709
+ "aria-label": view.action.label,
710
+ value,
711
+ placeholder: view.action.input.placeholder,
712
+ onInput: (e) => setValue(e.currentTarget.value)
713
+ }
714
+ ),
715
+ /* @__PURE__ */ jsx("button", { type: "submit", class: "bas-rowmenu__save", "data-testid": `${pre}-save`, children: view.action.input.saveLabel ?? t.save })
716
+ ]
717
+ }
718
+ )
719
+ ]
720
+ }
721
+ );
722
+ }
723
+ function RowActions(props) {
724
+ const t = TEXT[props.lang];
725
+ const id = props.item.id;
726
+ const btn = useRef(null);
727
+ const [open, setOpenState] = useState(false);
728
+ const openRef = useRef(false);
729
+ const setOpen = (v) => {
730
+ openRef.current = v;
731
+ setOpenState(v);
732
+ };
656
733
  return /* @__PURE__ */ jsxs(Fragment, { children: [
657
734
  /* @__PURE__ */ jsx(
658
735
  "button",
@@ -664,73 +741,24 @@ function RowActions(props) {
664
741
  "aria-label": `${t.moreFor} ${props.item.label}`,
665
742
  "aria-haspopup": "menu",
666
743
  "aria-expanded": open,
667
- onClick: () => stackRef.current.length ? close() : show({ kind: "list", actions: props.item.actions }),
744
+ onClick: () => {
745
+ if (!openRef.current) return setOpen(true);
746
+ setOpen(false);
747
+ btn.current?.focus();
748
+ },
668
749
  children: /* @__PURE__ */ jsx(IconMore, {})
669
750
  }
670
751
  ),
671
- view ? /* @__PURE__ */ jsxs(
672
- "div",
752
+ open && btn.current ? /* @__PURE__ */ jsx(
753
+ ItemActionsMenu,
673
754
  {
674
- ref: menu,
675
- class: "bas-rowmenu",
676
- role: "menu",
677
- tabIndex: -1,
678
- "aria-label": view.kind === "list" && view.title ? view.title : props.item.label,
679
- "data-testid": `sidebar-item-${id}-menu`,
680
- style: pos ?? { position: "fixed", visibility: "hidden" },
681
- onKeyDown,
682
- children: [
683
- stack.length > 1 ? /* @__PURE__ */ jsxs("button", { type: "button", class: "bas-rowmenu__back", "data-testid": `sidebar-item-${id}-back`, "aria-label": t.back, onClick: back, children: [
684
- /* @__PURE__ */ jsx(IconChevronLeft, {}),
685
- /* @__PURE__ */ jsx("span", { children: view.kind === "list" ? view.title : view.action.label })
686
- ] }) : null,
687
- view.kind === "list" ? view.actions.map((a, i) => /* @__PURE__ */ jsxs(
688
- "button",
689
- {
690
- type: "button",
691
- role: "menuitem",
692
- ref: (el) => {
693
- items.current[i] = el;
694
- },
695
- tabIndex: i === hi ? 0 : -1,
696
- class: "bas-rowmenu__item" + (i === hi ? " is-active" : "") + (a.danger ? " is-danger" : "") + (armed === a.id ? " is-armed" : ""),
697
- "data-testid": `sidebar-item-${id}-action-${a.id}`,
698
- onMouseEnter: () => setHi(i),
699
- onFocus: () => setHi(i),
700
- onClick: () => pick(a),
701
- children: [
702
- a.icon ? /* @__PURE__ */ jsx("span", { class: "bas-rowmenu__icon", children: a.icon }) : null,
703
- /* @__PURE__ */ jsx("span", { class: "bas-rowmenu__label", children: armed === a.id && a.confirm ? a.confirm.label : a.label }),
704
- a.submenu?.length ? /* @__PURE__ */ jsx(IconChevronRight, {}) : a.kbd ? /* @__PURE__ */ jsx("kbd", { class: "bas-rowmenu__kbd", children: a.kbd.toUpperCase() }) : null
705
- ]
706
- },
707
- a.id
708
- )) : /* @__PURE__ */ jsxs(
709
- "form",
710
- {
711
- class: "bas-rowmenu__form",
712
- "data-testid": `sidebar-item-${id}-form`,
713
- onSubmit: (e) => {
714
- e.preventDefault();
715
- save(view.action);
716
- },
717
- children: [
718
- /* @__PURE__ */ jsx(
719
- "input",
720
- {
721
- class: "bas-rowmenu__input",
722
- "data-testid": `sidebar-item-${id}-input`,
723
- "aria-label": view.action.label,
724
- value,
725
- placeholder: view.action.input.placeholder,
726
- onInput: (e) => setValue(e.currentTarget.value)
727
- }
728
- ),
729
- /* @__PURE__ */ jsx("button", { type: "submit", class: "bas-rowmenu__save", "data-testid": `sidebar-item-${id}-save`, children: view.action.input.saveLabel ?? t.save })
730
- ]
731
- }
732
- )
733
- ]
755
+ actions: props.item.actions,
756
+ anchor: btn.current,
757
+ lang: props.lang,
758
+ label: props.item.label,
759
+ testidPrefix: `sidebar-item-${id}`,
760
+ onAction: props.onAction,
761
+ onClose: () => setOpen(false)
734
762
  }
735
763
  ) : null
736
764
  ] });
@@ -2026,6 +2054,6 @@ function ConfirmDialog(p) {
2026
2054
  );
2027
2055
  }
2028
2056
 
2029
- export { AVATAR_MAX_BYTES, AVATAR_TYPES, AccountError, AccountPage, AnalyticsError, AnalyticsPage, AppShell, Avatar, ConfirmDialog, NotificationBell, PageHeader, PageTabs, Sidebar, TEXT, TenantLoadError, TenantSwitcher, TopBar, UserMenu, accountErrorKind, activeNavLabel, analyticsErrorKind, badgeLabel, changePct, checkAvatarFile, copenhagenDay, createFetchAccountAdapter, createFetchAnalyticsAdapter, createFetchNotificationSource, createFetchTenantAdapter, createMemoryNotificationSource, defaultReauthHref, fillDays, initials, isActivePath, isExternal, readFlag, readSet, relativeTime, safeNavigate, useIsMobile, writeFlag, writeSet };
2057
+ export { AVATAR_MAX_BYTES, AVATAR_TYPES, AccountError, AccountPage, AnalyticsError, AnalyticsPage, AppShell, Avatar, ConfirmDialog, ItemActionsMenu, NotificationBell, PageHeader, PageTabs, Sidebar, TEXT, TenantLoadError, TenantSwitcher, TopBar, UserMenu, accountErrorKind, activeNavLabel, analyticsErrorKind, badgeLabel, changePct, checkAvatarFile, copenhagenDay, createFetchAccountAdapter, createFetchAnalyticsAdapter, createFetchNotificationSource, createFetchTenantAdapter, createMemoryNotificationSource, defaultReauthHref, fillDays, initials, isActivePath, isExternal, readFlag, readSet, relativeTime, safeNavigate, useIsMobile, writeFlag, writeSet };
2030
2058
  //# sourceMappingURL=preact.js.map
2031
2059
  //# sourceMappingURL=preact.js.map