@broberg/app-shell 0.17.0 → 0.19.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/dist/preact.d.cts CHANGED
@@ -68,6 +68,23 @@ interface NavGroup<Icon = unknown> {
68
68
  * it is the group's key and its accessible name.
69
69
  */
70
70
  hideLabel?: boolean;
71
+ /**
72
+ * F092.26 — false: the heading is plain text (no fold button, no chevron) and the
73
+ * group is always open, even with a stored fold for this label. Default true.
74
+ */
75
+ collapsible?: boolean;
76
+ /**
77
+ * F092.28 — a small icon button at the right of the heading row (e.g. «Filtrér og
78
+ * sortér»). The app opens its own menu from `onClick(anchor)`. Clicking it never
79
+ * folds the group. Not shown with `hideLabel` (there is no heading row).
80
+ */
81
+ action?: {
82
+ icon: Icon;
83
+ label: string;
84
+ expanded?: boolean;
85
+ onClick: (anchor: HTMLElement) => void;
86
+ testid?: string;
87
+ };
71
88
  }
72
89
  /**
73
90
  * Is this item the current page? Exact match for "/", otherwise the path is the
@@ -495,6 +512,8 @@ interface ShellUser {
495
512
  picture?: string;
496
513
  /** F092.15 — a line under the name, e.g. «Administrator · Enhed Nord». */
497
514
  subtitle?: string;
515
+ /** F092.27 — the organisation, e.g. «broberg.ai». Shown ONLY in the menu's top, with a building icon. */
516
+ org?: string;
498
517
  }
499
518
  interface UserMenuItem {
500
519
  id: string;
package/dist/preact.d.ts CHANGED
@@ -68,6 +68,23 @@ interface NavGroup<Icon = unknown> {
68
68
  * it is the group's key and its accessible name.
69
69
  */
70
70
  hideLabel?: boolean;
71
+ /**
72
+ * F092.26 — false: the heading is plain text (no fold button, no chevron) and the
73
+ * group is always open, even with a stored fold for this label. Default true.
74
+ */
75
+ collapsible?: boolean;
76
+ /**
77
+ * F092.28 — a small icon button at the right of the heading row (e.g. «Filtrér og
78
+ * sortér»). The app opens its own menu from `onClick(anchor)`. Clicking it never
79
+ * folds the group. Not shown with `hideLabel` (there is no heading row).
80
+ */
81
+ action?: {
82
+ icon: Icon;
83
+ label: string;
84
+ expanded?: boolean;
85
+ onClick: (anchor: HTMLElement) => void;
86
+ testid?: string;
87
+ };
71
88
  }
72
89
  /**
73
90
  * Is this item the current page? Exact match for "/", otherwise the path is the
@@ -495,6 +512,8 @@ interface ShellUser {
495
512
  picture?: string;
496
513
  /** F092.15 — a line under the name, e.g. «Administrator · Enhed Nord». */
497
514
  subtitle?: string;
515
+ /** F092.27 — the organisation, e.g. «broberg.ai». Shown ONLY in the menu's top, with a building icon. */
516
+ org?: string;
498
517
  }
499
518
  interface UserMenuItem {
500
519
  id: string;
package/dist/preact.js CHANGED
@@ -509,6 +509,11 @@ var IconUser = () => svg(/* @__PURE__ */ jsxs(Fragment, { children: [
509
509
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "8", r: "4" }),
510
510
  /* @__PURE__ */ jsx("path", { d: "M4 21a8 8 0 0 1 16 0" })
511
511
  ] }), 14);
512
+ var IconBuilding = () => svg(/* @__PURE__ */ jsxs(Fragment, { children: [
513
+ /* @__PURE__ */ jsx("rect", { width: "16", height: "20", x: "4", y: "2", rx: "2" }),
514
+ /* @__PURE__ */ jsx("path", { d: "M9 22v-4h6v4" }),
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
+ ] }), 15);
512
517
  function RowActions(props) {
513
518
  const t = TEXT[props.lang];
514
519
  const id = props.item.id;
@@ -899,7 +904,8 @@ function Sidebar(p) {
899
904
  ) : p.brandMark }) : null
900
905
  ] }) : null,
901
906
  /* @__PURE__ */ jsx("nav", { class: "bas-sidebar__nav", children: p.groups.map((g) => {
902
- const open = railed || g.hideLabel || !folded.has(g.label);
907
+ const fixed = g.hideLabel || g.collapsible === false;
908
+ const open = railed || fixed || !folded.has(g.label);
903
909
  const slug = g.label.toLowerCase().replace(/[^a-z0-9]+/g, "-");
904
910
  return /* @__PURE__ */ jsxs(
905
911
  "div",
@@ -909,10 +915,32 @@ function Sidebar(p) {
909
915
  "aria-label": g.hideLabel ? g.label : void 0,
910
916
  "data-testid": g.hideLabel ? `sidebar-group-${slug}-unlabelled` : void 0,
911
917
  children: [
912
- g.hideLabel ? null : /* @__PURE__ */ jsxs("button", { type: "button", class: "bas-group__label", "data-testid": `sidebar-group-${slug}`, "aria-expanded": open, onClick: () => toggleGroup(g.label), children: [
913
- /* @__PURE__ */ jsx(IconChevron, { open }),
914
- /* @__PURE__ */ jsx("span", { children: g.label })
915
- ] }),
918
+ (() => {
919
+ if (g.hideLabel) return null;
920
+ const heading = g.collapsible === false ? /* @__PURE__ */ jsx("div", { class: "bas-group__label bas-group__label--static", "data-testid": `sidebar-group-${slug}`, children: /* @__PURE__ */ jsx("span", { children: g.label }) }) : /* @__PURE__ */ jsxs("button", { type: "button", class: "bas-group__label", "data-testid": `sidebar-group-${slug}`, "aria-expanded": open, onClick: () => toggleGroup(g.label), children: [
921
+ /* @__PURE__ */ jsx(IconChevron, { open }),
922
+ /* @__PURE__ */ jsx("span", { children: g.label })
923
+ ] });
924
+ if (!g.action) return heading;
925
+ const a = g.action;
926
+ return /* @__PURE__ */ jsxs("div", { class: "bas-group__head", children: [
927
+ heading,
928
+ /* @__PURE__ */ jsx(
929
+ "button",
930
+ {
931
+ type: "button",
932
+ class: "bas-group__action",
933
+ "data-testid": a.testid ?? `sidebar-group-${slug}-action`,
934
+ "aria-label": a.label,
935
+ title: a.label,
936
+ "aria-haspopup": "menu",
937
+ "aria-expanded": a.expanded ?? false,
938
+ onClick: (e) => a.onClick(e.currentTarget),
939
+ children: a.icon
940
+ }
941
+ )
942
+ ] });
943
+ })(),
916
944
  open ? g.items.map(item) : null,
917
945
  open ? g.sections?.map((sec) => /* @__PURE__ */ jsxs("div", { class: "bas-section", "data-testid": `sidebar-section-${slug}-${sec.label.toLowerCase().replace(/[^a-z0-9æøå]+/g, "-")}`, children: [
918
946
  /* @__PURE__ */ jsx("div", { class: "bas-section__label", children: sec.label }),
@@ -1272,7 +1300,11 @@ function UserMenu(p) {
1272
1300
  /* @__PURE__ */ jsxs("div", { class: "bas-menu__whotext", children: [
1273
1301
  p.user.name ? /* @__PURE__ */ jsx("div", { class: "bas-menu__name", children: p.user.name }) : null,
1274
1302
  p.user.subtitle ? /* @__PURE__ */ jsx("div", { class: "bas-menu__sub", children: p.user.subtitle }) : null,
1275
- p.user.email ? /* @__PURE__ */ jsx("div", { class: "bas-menu__email", children: p.user.email }) : null
1303
+ p.user.email ? /* @__PURE__ */ jsx("div", { class: "bas-menu__email", children: p.user.email }) : null,
1304
+ p.user.org ? /* @__PURE__ */ jsxs("div", { class: "bas-menu__org", "data-testid": "user-menu-org", children: [
1305
+ /* @__PURE__ */ jsx(IconBuilding, {}),
1306
+ /* @__PURE__ */ jsx("span", { children: p.user.org })
1307
+ ] }) : null
1276
1308
  ] })
1277
1309
  ] }),
1278
1310
  /* @__PURE__ */ jsx("div", { class: "bas-sep" }),