@growth-operations/ui-shared 1.27.0 → 1.28.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-operations/ui-shared",
3
- "version": "1.27.0",
3
+ "version": "1.28.0",
4
4
  "description": "Shared HubSpot UI-extension modules (Home, Billing) for Growth Operations apps.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -61,16 +61,19 @@ function RecommendedTile({ notInUse, isSuperAdmin, onNavigate }) {
61
61
  <Flex direction="column" gap="small">
62
62
  <Text format={{ fontWeight: "bold" }}>Recommended to explore</Text>
63
63
  {picks.map((f) => {
64
- // Setup CTAs point at admin-only surfaces (the layout editor above
65
- // all) — show them to super admins only; everyone else gets name +
66
- // rationale alone (a non-admin clicking into a HubSpot permission
67
- // wall is worse than no link).
64
+ // Setup CTAs are gated PER ITEM (1.28.0): adminOnly items point at
65
+ // HubSpot permission-wall surfaces (the layout editor above all) —
66
+ // super admins only, since a non-admin clicking into a permission
67
+ // wall is worse than no link. Items marked adminOnly: false are
68
+ // per-user surfaces (install the Chrome extension, open the in-app
69
+ // extension page) and render for everyone. Old backends emit no
70
+ // marker → adminOnly defaults true → the blanket gate is preserved.
68
71
  //
69
72
  // "Learn more →" (docs_url) intentionally NOT rendered (Jasper
70
73
  // 2026-10-14): every feature's docs_url points at the same single
71
74
  // setup guide — noise until per-feature articles exist. docs_url
72
75
  // stays in the wire contract; re-enabling is a one-line revert.
73
- const ctas = isSuperAdmin ? f.ctas : [];
76
+ const ctas = f.ctas.filter((c) => !c.adminOnly || isSuperAdmin);
74
77
  return (
75
78
  <Flex key={f.key} direction="column" gap="extra-small">
76
79
  <Text format={{ fontWeight: "demibold" }}>{f.name}</Text>
@@ -18,13 +18,17 @@ const normalizeUnit = (u) =>
18
18
  // One well-formed setup CTA is {label: non-empty string, url XOR route:
19
19
  // non-empty string}. Anything else (missing label, both targets, neither
20
20
  // target, wrong types) is dropped — a malformed item never renders.
21
+ // admin_only (1.28.0): an explicit false marks a per-user surface (installing
22
+ // the Chrome extension) that renders for EVERYONE; a missing marker means
23
+ // admin-only, so old backends keep the blanket super-admin gate.
21
24
  const normalizeCta = (c) => {
22
25
  if (!c || typeof c !== "object") return null;
23
26
  const label = typeof c.label === "string" && c.label ? c.label : null;
24
27
  const url = typeof c.url === "string" && c.url ? c.url : null;
25
28
  const route = typeof c.route === "string" && c.route ? c.route : null;
26
29
  if (!label || !(url || route) || (url && route)) return null;
27
- return url ? { label, url } : { label, route };
30
+ const adminOnly = c.admin_only !== false;
31
+ return { label, ...(url ? { url } : { route }), adminOnly };
28
32
  };
29
33
 
30
34
  // Resolve the feature_usage block into render-ready shape: