@campfire-interactive/shell-header 0.15.2 → 0.16.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/index.d.ts CHANGED
@@ -67,8 +67,16 @@ interface ShellUser {
67
67
  interface TenantOption {
68
68
  id: string;
69
69
  name: string;
70
- /** Human-readable role label ("owner", "admin", "member"). Optional. */
71
- role?: string;
70
+ /**
71
+ * Human-readable role label ("owner", "admin", "member"). Optional.
72
+ *
73
+ * No longer rendered — the switcher's role chip was removed (see UserMenu).
74
+ * Kept so hosts that still pass it compile, and `null` is accepted because
75
+ * identity-client types the active tenant's `role` as `string | null`
76
+ * (absent on tokens minted before the claim existed). Without the null,
77
+ * every host passing `user.tenant` straight through fails to typecheck.
78
+ */
79
+ role?: string | null;
72
80
  }
73
81
  /**
74
82
  * A host-supplied action rendered in the user (avatar) menu, above Sign out.
@@ -245,8 +253,19 @@ interface ShellHeaderProps {
245
253
  /**
246
254
  * The user's role in their currently-active tenant (e.g. "admin", "owner",
247
255
  * "member"). Apps in the catalog with `requiresRole` are shown only when
248
- * this matches one of the allowed roles. Hosts typically derive this from
249
- * `user.tenants.find(t => t.id === user.tenant.id)?.role`.
256
+ * this matches one of the allowed roles.
257
+ *
258
+ * Derive this from the JWT's `data.tenant.role` — the active tenant's own
259
+ * claim. The old recipe, `user.tenants.find(t => t.id === user.tenant.id)?.role`,
260
+ * still works but reads the `data.tenants[]` array that is being removed from
261
+ * the token (nextgen docs/plans/2026-08-07-slim-identity-jwt-tenants.md); once
262
+ * it is gone that lookup silently yields `undefined` and every `requiresRole`
263
+ * app disappears from the switcher. Prefer `tenant.role`, fall back to the
264
+ * array while both exist.
265
+ *
266
+ * NOTE this is distinct from the role that used to render beside each row in
267
+ * the tenant switcher — that chip has been removed. This one still gates the
268
+ * app catalog and is unaffected.
250
269
  */
251
270
  currentTenantRole?: string;
252
271
  /** Unread count for the bell badge. */
package/dist/index.js CHANGED
@@ -512,7 +512,7 @@ function UserMenu({
512
512
  disabled: updating || active,
513
513
  children: [
514
514
  /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-item-label", children: t.name }),
515
- active ? /* @__PURE__ */ jsx4(Check, { size: 14, className: "cfi-sh-tenant-check" }) : t.role ? /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-item-code", children: t.role }) : null
515
+ active ? /* @__PURE__ */ jsx4(Check, { size: 14, className: "cfi-sh-tenant-check" }) : null
516
516
  ]
517
517
  },
518
518
  t.id
@@ -843,13 +843,8 @@ async function captureTabScreenshot() {
843
843
  var MAX_ENTRIES = 50;
844
844
  var MAX_MESSAGE_CHARS = 500;
845
845
  var consoleBuffer = [];
846
- var networkFailureBuffer = [];
847
- var networkSuccessBuffer = [];
846
+ var networkBuffer = [];
848
847
  var installed = false;
849
- function stripQuery(url) {
850
- const i = url.indexOf("?");
851
- return i === -1 ? url : url.slice(0, i);
852
- }
853
848
  function push(buffer, entry) {
854
849
  buffer.push(entry);
855
850
  if (buffer.length > MAX_ENTRIES) buffer.shift();
@@ -898,7 +893,7 @@ function installBugReportCapture() {
898
893
  try {
899
894
  const res = await originalFetch(input, init);
900
895
  if (!res.ok) {
901
- push(networkFailureBuffer, {
896
+ push(networkBuffer, {
902
897
  at: (/* @__PURE__ */ new Date()).toISOString(),
903
898
  method: method.toUpperCase(),
904
899
  url,
@@ -906,19 +901,10 @@ function installBugReportCapture() {
906
901
  durationMs: Math.round(performance.now() - started),
907
902
  requestId: res.headers.get("x-request-id") ?? void 0
908
903
  });
909
- } else {
910
- push(networkSuccessBuffer, {
911
- at: (/* @__PURE__ */ new Date()).toISOString(),
912
- method: method.toUpperCase(),
913
- url: stripQuery(url),
914
- status: res.status,
915
- durationMs: Math.round(performance.now() - started),
916
- requestId: res.headers.get("x-request-id") ?? void 0
917
- });
918
904
  }
919
905
  return res;
920
906
  } catch (err) {
921
- push(networkFailureBuffer, {
907
+ push(networkBuffer, {
922
908
  at: (/* @__PURE__ */ new Date()).toISOString(),
923
909
  method: method.toUpperCase(),
924
910
  url,
@@ -930,10 +916,7 @@ function installBugReportCapture() {
930
916
  };
931
917
  }
932
918
  function snapshotBugReportCapture() {
933
- const network = [...networkFailureBuffer, ...networkSuccessBuffer].sort(
934
- (a, b) => a.at.localeCompare(b.at)
935
- );
936
- return { console: [...consoleBuffer], network };
919
+ return { console: [...consoleBuffer], network: [...networkBuffer] };
937
920
  }
938
921
 
939
922
  // src/BugReportModal.tsx
@@ -1411,16 +1394,14 @@ function useBugReportShortcut(enabled, onShortcut) {
1411
1394
  function handleKeyDown(e) {
1412
1395
  const platformMod = e.ctrlKey || e.metaKey;
1413
1396
  if (!platformMod || !e.altKey || e.shiftKey) return;
1414
- const isB = e.code === "KeyB" || e.key.toLowerCase() === "b";
1415
- const isS = e.code === "KeyS" || e.key.toLowerCase() === "s";
1416
- if (!isB && !isS) return;
1397
+ if (e.code !== "KeyB" && e.key.toLowerCase() !== "b") return;
1417
1398
  const target = e.target;
1418
1399
  if (target) {
1419
1400
  const tag = target.tagName;
1420
1401
  if (tag === "INPUT" || tag === "TEXTAREA" || target.isContentEditable) return;
1421
1402
  }
1422
1403
  e.preventDefault();
1423
- handlerRef.current(isS ? "screenshot" : "plain");
1404
+ handlerRef.current();
1424
1405
  }
1425
1406
  document.addEventListener("keydown", handleKeyDown);
1426
1407
  return () => document.removeEventListener("keydown", handleKeyDown);
@@ -1469,17 +1450,12 @@ function ShellHeader({
1469
1450
  const [bugOpen, setBugOpen] = useState7(false);
1470
1451
  const [bugShot, setBugShot] = useState7(null);
1471
1452
  const bugCaptureBusy = useRef6(false);
1472
- useBugReportShortcut(bugReport !== void 0, (variant) => {
1453
+ useBugReportShortcut(bugReport !== void 0, () => {
1473
1454
  if (bugOpen) {
1474
1455
  setBugOpen(false);
1475
1456
  return;
1476
1457
  }
1477
1458
  if (bugCaptureBusy.current) return;
1478
- if (variant === "plain") {
1479
- setBugShot(null);
1480
- setBugOpen(true);
1481
- return;
1482
- }
1483
1459
  bugCaptureBusy.current = true;
1484
1460
  captureTabScreenshot().then((shot) => setBugShot(shot)).catch(() => setBugShot(null)).finally(() => {
1485
1461
  bugCaptureBusy.current = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/shell-header",
3
- "version": "0.15.2",
3
+ "version": "0.16.1",
4
4
  "description": "Shared shell header with app switcher for Campfire Suite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",