@campfire-interactive/shell-header 0.5.1 → 0.5.6

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
@@ -10,6 +10,12 @@ interface AppDefinition {
10
10
  color: string;
11
11
  /** Local dev port (e.g., 3000). Omit if the app doesn't run locally. */
12
12
  localPort?: number;
13
+ /**
14
+ * If set, the app tile is only visible when the host passes a
15
+ * `currentTenantRole` that matches one of these values. Used to gate
16
+ * admin-style apps (e.g. User Management → ['admin', 'owner']).
17
+ */
18
+ requiresRole?: string[];
13
19
  }
14
20
  interface ShellUser {
15
21
  name: string;
@@ -53,6 +59,13 @@ interface ShellHeaderProps {
53
59
  user: ShellUser;
54
60
  /** App IDs the user is authorized to access in the current tenant */
55
61
  authorizedApps: string[];
62
+ /**
63
+ * The user's role in their currently-active tenant (e.g. "admin", "owner",
64
+ * "member"). Apps in the catalog with `requiresRole` are shown only when
65
+ * this matches one of the allowed roles. Hosts typically derive this from
66
+ * `user.tenants.find(t => t.id === user.tenant.id)?.role`.
67
+ */
68
+ currentTenantRole?: string;
56
69
  /** Unread count for the bell badge. */
57
70
  notificationCount?: number;
58
71
  /**
@@ -116,7 +129,7 @@ interface ShellHeaderProps {
116
129
  children?: React.ReactNode;
117
130
  }
118
131
 
119
- declare function ShellHeader({ appId, user, authorizedApps, notificationCount, onNotificationClick, notifications, onMarkRead, onMarkAllRead, onNotificationItemClick, onLogout, locale, supportedLocales, onLocaleChange, tenant, tenants, onTenantSwitch, brandWidth, children, }: ShellHeaderProps): react_jsx_runtime.JSX.Element;
132
+ declare function ShellHeader({ appId, user, authorizedApps, currentTenantRole, notificationCount, onNotificationClick, notifications, onMarkRead, onMarkAllRead, onNotificationItemClick, onLogout, locale, supportedLocales, onLocaleChange, tenant, tenants, onTenantSwitch, brandWidth, children, }: ShellHeaderProps): react_jsx_runtime.JSX.Element;
120
133
 
121
134
  interface LocaleSwitcherProps {
122
135
  currentLocale: string;
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ var appCatalog = [
34
34
  { id: "pim", name: "Price Index", icon: "BarChart3", letter: "P", color: "#f97316", localPort: 3300 },
35
35
  { id: "cpq", name: "CPQ", icon: "Calculator", letter: "C", color: "#4f46e5", localPort: 3400 },
36
36
  { id: "omsf", name: "OMSF", icon: "FileText", letter: "O", color: "#0ea5e9", localPort: 3500 },
37
- { id: "identity", name: "Identity", icon: "Shield", letter: "I", color: "#8b5cf6", localPort: 3600 },
37
+ { id: "identity", name: "User Management", icon: "Shield", letter: "U", color: "#8b5cf6", localPort: 3600, requiresRole: ["admin", "owner"] },
38
38
  { id: "bom", name: "BOM", icon: "Network", letter: "B", color: "#0d9488", localPort: 3700 }
39
39
  ];
40
40
  function getAppUrl(app) {
@@ -97,10 +97,12 @@ function GridIcon({ size = 20 }) {
97
97
 
98
98
  // src/AppSwitcher.tsx
99
99
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
100
- function AppSwitcher({ currentAppId, authorizedApps }) {
100
+ function AppSwitcher({ currentAppId, authorizedApps, currentTenantRole }) {
101
101
  const [open, setOpen] = useState(false);
102
102
  const ref = useRef(null);
103
- const visibleApps = appCatalog.filter((a) => authorizedApps.includes(a.id));
103
+ const visibleApps = appCatalog.filter(
104
+ (a) => authorizedApps.includes(a.id) && (!a.requiresRole || currentTenantRole !== void 0 && a.requiresRole.includes(currentTenantRole))
105
+ );
104
106
  useEffect(() => {
105
107
  function handleClickOutside(e) {
106
108
  if (ref.current && !ref.current.contains(e.target)) {
@@ -310,15 +312,6 @@ function UserMenu({
310
312
  setTenantExpanded(false);
311
313
  return;
312
314
  }
313
- const target = tenants?.find((t) => t.id === tenantId);
314
- const targetName = target?.name ?? "this tenant";
315
- const confirmed = window.confirm(
316
- `Switch to ${targetName}? Other open suite tabs will reload.`
317
- );
318
- if (!confirmed) {
319
- setTenantExpanded(false);
320
- return;
321
- }
322
315
  setUpdating(true);
323
316
  try {
324
317
  await onTenantSwitch(tenantId);
@@ -356,8 +349,7 @@ function UserMenu({
356
349
  disabled: updating,
357
350
  children: [
358
351
  /* @__PURE__ */ jsx4(Building2, { size: 14 }),
359
- /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-row-label", children: "Tenant" }),
360
- /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-row-current", children: tenant.name }),
352
+ /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-row-label", children: tenant.name }),
361
353
  /* @__PURE__ */ jsx4(
362
354
  ChevronDown,
363
355
  {
@@ -369,8 +361,7 @@ function UserMenu({
369
361
  }
370
362
  ) : /* @__PURE__ */ jsxs4("div", { className: "cfi-sh-menu-item cfi-sh-tenant-static", children: [
371
363
  /* @__PURE__ */ jsx4(Building2, { size: 14 }),
372
- /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-row-label", children: "Tenant" }),
373
- /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-row-current", children: tenant.name })
364
+ /* @__PURE__ */ jsx4("span", { className: "cfi-sh-locale-row-label", children: tenant.name })
374
365
  ] }),
375
366
  canSwitchTenant && tenantExpanded && /* @__PURE__ */ jsx4("div", { className: "cfi-sh-locale-sublist", children: tenants.map((t) => {
376
367
  const active = t.id === tenant.id;
@@ -451,6 +442,7 @@ function ShellHeader({
451
442
  appId,
452
443
  user,
453
444
  authorizedApps,
445
+ currentTenantRole,
454
446
  notificationCount,
455
447
  onNotificationClick,
456
448
  notifications,
@@ -489,7 +481,7 @@ function ShellHeader({
489
481
  onItemClick: onNotificationItemClick
490
482
  }
491
483
  ),
492
- /* @__PURE__ */ jsx5(AppSwitcher, { currentAppId: appId, authorizedApps }),
484
+ /* @__PURE__ */ jsx5(AppSwitcher, { currentAppId: appId, authorizedApps, currentTenantRole }),
493
485
  /* @__PURE__ */ jsx5(
494
486
  UserMenu,
495
487
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/shell-header",
3
- "version": "0.5.1",
3
+ "version": "0.5.6",
4
4
  "description": "Shared shell header with app switcher for Campfire Suite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",