@broberg/app-shell 0.8.0 → 0.9.2

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
@@ -622,5 +622,23 @@ interface TenantSwitcherProps {
622
622
  * With one organisation it is a plain label, not a menu.
623
623
  */
624
624
  declare function TenantSwitcher({ lang, activeSlug, adapter, onSwitch, roleLabel }: TenantSwitcherProps): JSX.Element;
625
+ interface ConfirmDialogProps {
626
+ open: boolean;
627
+ title: ComponentChildren;
628
+ body?: ComponentChildren;
629
+ confirmLabel?: string;
630
+ cancelLabel?: string;
631
+ /** Red confirm button, for an action that cannot be undone. */
632
+ destructive?: boolean;
633
+ /** The confirm action is running: buttons disabled, the window cannot be dismissed. */
634
+ busy?: boolean;
635
+ /** Shown inside the window; the window stays open so the user can retry or cancel. */
636
+ error?: ComponentChildren;
637
+ onConfirm: () => void;
638
+ onCancel: () => void;
639
+ /** Prefix for every data-testid. Default "confirm-dialog". */
640
+ testId?: string;
641
+ }
642
+ declare function ConfirmDialog(p: ConfirmDialogProps): JSX.Element | null;
625
643
 
626
- 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, 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 };
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 };
package/dist/preact.d.ts CHANGED
@@ -622,5 +622,23 @@ interface TenantSwitcherProps {
622
622
  * With one organisation it is a plain label, not a menu.
623
623
  */
624
624
  declare function TenantSwitcher({ lang, activeSlug, adapter, onSwitch, roleLabel }: TenantSwitcherProps): JSX.Element;
625
+ interface ConfirmDialogProps {
626
+ open: boolean;
627
+ title: ComponentChildren;
628
+ body?: ComponentChildren;
629
+ confirmLabel?: string;
630
+ cancelLabel?: string;
631
+ /** Red confirm button, for an action that cannot be undone. */
632
+ destructive?: boolean;
633
+ /** The confirm action is running: buttons disabled, the window cannot be dismissed. */
634
+ busy?: boolean;
635
+ /** Shown inside the window; the window stays open so the user can retry or cancel. */
636
+ error?: ComponentChildren;
637
+ onConfirm: () => void;
638
+ onCancel: () => void;
639
+ /** Prefix for every data-testid. Default "confirm-dialog". */
640
+ testId?: string;
641
+ }
642
+ declare function ConfirmDialog(p: ConfirmDialogProps): JSX.Element | null;
625
643
 
626
- 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, 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 };
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 };
package/dist/preact.js CHANGED
@@ -1452,7 +1452,98 @@ function TenantSwitcher({ lang, activeSlug, adapter, onSwitch, roleLabel }) {
1452
1452
  ] }) : null
1453
1453
  ] });
1454
1454
  }
1455
+ var confirmDialogSeq = 0;
1456
+ function ConfirmDialog(p) {
1457
+ const t = p.testId ?? "confirm-dialog";
1458
+ const panel = useRef(null);
1459
+ const cancelBtn = useRef(null);
1460
+ const ids = useMemo(() => {
1461
+ const n = ++confirmDialogSeq;
1462
+ return { title: `bas-confirm-title-${n}`, body: `bas-confirm-body-${n}` };
1463
+ }, []);
1464
+ const live = useRef(p);
1465
+ live.current = p;
1466
+ useLayoutEffect(() => {
1467
+ if (!p.open) return;
1468
+ const before = document.activeElement;
1469
+ cancelBtn.current?.focus();
1470
+ const onKey = (e) => {
1471
+ if (e.key === "Escape") {
1472
+ e.preventDefault();
1473
+ if (!live.current.busy) live.current.onCancel();
1474
+ return;
1475
+ }
1476
+ if (e.key !== "Tab" || !panel.current) return;
1477
+ const focusable = [...panel.current.querySelectorAll("button:not([disabled])")];
1478
+ if (focusable.length === 0) {
1479
+ e.preventDefault();
1480
+ return;
1481
+ }
1482
+ const first = focusable[0];
1483
+ const last = focusable[focusable.length - 1];
1484
+ const active = document.activeElement;
1485
+ if (e.shiftKey && (active === first || !panel.current.contains(active))) {
1486
+ e.preventDefault();
1487
+ last.focus();
1488
+ } else if (!e.shiftKey && (active === last || !panel.current.contains(active))) {
1489
+ e.preventDefault();
1490
+ first.focus();
1491
+ }
1492
+ };
1493
+ document.addEventListener("keydown", onKey);
1494
+ return () => {
1495
+ document.removeEventListener("keydown", onKey);
1496
+ if (before && typeof before.focus === "function" && document.contains(before)) before.focus();
1497
+ };
1498
+ }, [p.open]);
1499
+ if (!p.open) return null;
1500
+ return /* @__PURE__ */ jsx(
1501
+ "div",
1502
+ {
1503
+ class: "bas-confirm-backdrop",
1504
+ "data-testid": `${t}-backdrop`,
1505
+ onMouseDown: (e) => {
1506
+ if (e.target === e.currentTarget && !p.busy) p.onCancel();
1507
+ },
1508
+ children: /* @__PURE__ */ jsxs(
1509
+ "div",
1510
+ {
1511
+ ref: panel,
1512
+ class: "bas-confirm",
1513
+ role: "alertdialog",
1514
+ "aria-modal": "true",
1515
+ "aria-labelledby": ids.title,
1516
+ "aria-describedby": p.body ? ids.body : void 0,
1517
+ "aria-busy": p.busy ? "true" : void 0,
1518
+ "data-testid": t,
1519
+ children: [
1520
+ /* @__PURE__ */ jsx("h2", { class: "bas-confirm__title", id: ids.title, "data-testid": `${t}-title`, children: p.title }),
1521
+ p.body ? /* @__PURE__ */ jsx("div", { class: "bas-confirm__body", id: ids.body, "data-testid": `${t}-body`, children: p.body }) : null,
1522
+ p.error ? /* @__PURE__ */ jsx("div", { class: "bas-confirm__error", role: "alert", "data-testid": `${t}-error`, children: p.error }) : null,
1523
+ /* @__PURE__ */ jsxs("div", { class: "bas-confirm__actions", children: [
1524
+ /* @__PURE__ */ jsx("button", { ref: cancelBtn, type: "button", class: "bas-confirm__btn", disabled: p.busy, "data-testid": `${t}-cancel`, onClick: () => p.onCancel(), children: p.cancelLabel ?? "Annuller" }),
1525
+ /* @__PURE__ */ jsxs(
1526
+ "button",
1527
+ {
1528
+ type: "button",
1529
+ class: `bas-confirm__btn is-primary${p.destructive ? " is-danger" : ""}${p.busy ? " is-busy" : ""}`,
1530
+ disabled: p.busy,
1531
+ "data-testid": `${t}-confirm`,
1532
+ onClick: () => p.onConfirm(),
1533
+ children: [
1534
+ p.busy ? /* @__PURE__ */ jsx("span", { class: "bas-confirm__spinner", "aria-hidden": "true" }) : null,
1535
+ p.confirmLabel ?? "Bekr\xE6ft"
1536
+ ]
1537
+ }
1538
+ )
1539
+ ] })
1540
+ ]
1541
+ }
1542
+ )
1543
+ }
1544
+ );
1545
+ }
1455
1546
 
1456
- export { AVATAR_MAX_BYTES, AVATAR_TYPES, AccountError, AccountPage, AnalyticsError, AnalyticsPage, AppShell, Avatar, 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 };
1547
+ 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 };
1457
1548
  //# sourceMappingURL=preact.js.map
1458
1549
  //# sourceMappingURL=preact.js.map