@burdenoff/fe-libs 2026.719.2 → 2026.719.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"DynamicFooter.d.ts","sourceRoot":"","sources":["../../src/chrome/DynamicFooter.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AA8DzD,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,kDAAkD;IAClD,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAW,EACX,WAAW,EACX,OAAO,EACP,OAAkB,EAClB,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,iBAAiB,EAC9B,cAAiC,EACjC,eAAuB,GACxB,EAAE,kBAAkB,2CAgJpB"}
1
+ {"version":3,"file":"DynamicFooter.d.ts","sourceRoot":"","sources":["../../src/chrome/DynamicFooter.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AA+DzD,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,kDAAkD;IAClD,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAW,EACX,WAAW,EACX,OAAO,EACP,OAAkB,EAClB,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,iBAAiB,EAC9B,cAAiC,EACjC,eAAuB,GACxB,EAAE,kBAAkB,2CAiJpB"}
@@ -2,13 +2,14 @@ import { useGatewayClient as e } from "../shared/graphql/GatewayContext.js";
2
2
  import "../shared-graphql.js";
3
3
  import { useActiveContext as t } from "../shared/providers/shell/ActiveContextProvider.js";
4
4
  import { DEFAULT_FOOTER_COLUMNS as n, DEFAULT_SOCIAL_LINKS as r, Footer as i } from "./Footer.js";
5
- import { useEffect as a, useMemo as o, useState as s } from "react";
6
- import { Github as c, Globe as l, Linkedin as u, MessageCircle as d, Twitter as f, Youtube as p } from "lucide-react";
7
- import { jsx as m } from "react/jsx-runtime";
8
- import { gql as h } from "@apollo/client/core";
9
- import { Link as g } from "react-router-dom";
5
+ import { BrandMark as a } from "./BrandMark.js";
6
+ import { useEffect as o, useMemo as s, useState as c } from "react";
7
+ import { Github as l, Globe as u, Linkedin as d, MessageCircle as f, Twitter as p, Youtube as m } from "lucide-react";
8
+ import { jsx as h } from "react/jsx-runtime";
9
+ import { gql as g } from "@apollo/client/core";
10
+ import { Link as _ } from "react-router-dom";
10
11
  //#region src/chrome/DynamicFooter.tsx
11
- var _ = h`
12
+ var v = g`
12
13
  query GetFooterContentPages($filter: ContentPageFilterInput, $limit: Int) {
13
14
  contentPages(filter: $filter, limit: $limit) {
14
15
  items {
@@ -20,14 +21,14 @@ var _ = h`
20
21
  }
21
22
  }
22
23
  }
23
- `, v = h`
24
+ `, y = g`
24
25
  query GetFooterProduct($slug: String!) {
25
26
  platformProductBySlug(slug: $slug) {
26
27
  id
27
28
  socialLinks
28
29
  }
29
30
  }
30
- `, y = {
31
+ `, b = {
31
32
  "privacy-policy": "privacy",
32
33
  "terms-of-service": "terms",
33
34
  "cookie-policy": "cookies",
@@ -38,14 +39,14 @@ var _ = h`
38
39
  compliance: "compliance",
39
40
  about: "about",
40
41
  contact: "contact"
41
- }, b = {
42
- twitter: /* @__PURE__ */ m(f, { className: "size-5" }),
43
- x: /* @__PURE__ */ m(f, { className: "size-5" }),
44
- github: /* @__PURE__ */ m(c, { className: "size-5" }),
45
- discord: /* @__PURE__ */ m(d, { className: "size-5" }),
46
- linkedin: /* @__PURE__ */ m(u, { className: "size-5" }),
47
- youtube: /* @__PURE__ */ m(p, { className: "size-5" })
48
- }, x = [
42
+ }, x = {
43
+ twitter: /* @__PURE__ */ h(p, { className: "size-5" }),
44
+ x: /* @__PURE__ */ h(p, { className: "size-5" }),
45
+ github: /* @__PURE__ */ h(l, { className: "size-5" }),
46
+ discord: /* @__PURE__ */ h(f, { className: "size-5" }),
47
+ linkedin: /* @__PURE__ */ h(d, { className: "size-5" }),
48
+ youtube: /* @__PURE__ */ h(m, { className: "size-5" })
49
+ }, S = [
49
50
  "terms-of-service",
50
51
  "privacy-policy",
51
52
  "security",
@@ -55,13 +56,13 @@ var _ = h`
55
56
  "sla",
56
57
  "refund-policy"
57
58
  ];
58
- function S({ productSlug: c, productName: u, tagline: d, version: f = "v1.0.0", columns: p, socialLinks: h, legalPageOrder: S = x, deferRemoteData: C = !1 }) {
59
- let { workspaceId: w, projectId: T } = t(), E = e("global"), [D, O] = s(null), [k, A] = s(null);
60
- return a(() => {
61
- if (!E || C) return;
59
+ function C({ productSlug: l, productName: d, tagline: f, version: p = "v1.0.0", columns: m, socialLinks: g, legalPageOrder: C = S, deferRemoteData: w = !1 }) {
60
+ let { workspaceId: T, projectId: E } = t(), D = e("global"), [O, k] = c(null), [A, j] = c(null);
61
+ o(() => {
62
+ if (!D || w) return;
62
63
  let e = !1;
63
- return E.query({
64
- query: _,
64
+ return D.query({
65
+ query: v,
65
66
  variables: {
66
67
  filter: { isPublished: !0 },
67
68
  limit: 50
@@ -70,25 +71,25 @@ function S({ productSlug: c, productName: u, tagline: d, version: f = "v1.0.0",
70
71
  }).then((t) => {
71
72
  let n = t.data;
72
73
  if (e || !n?.contentPages?.items) return;
73
- let r = n.contentPages.items, i = S.map((e) => r.find((t) => t.slug === e)).filter((e) => e != null).map((e) => ({
74
+ let r = n.contentPages.items, i = C.map((e) => r.find((t) => t.slug === e)).filter((e) => e != null).map((e) => ({
74
75
  id: e.slug,
75
76
  label: e.title,
76
- href: `/legal/${y[e.slug] || e.slug}`
77
+ href: `/legal/${b[e.slug] || e.slug}`
77
78
  }));
78
- i.length > 0 && O(i);
79
+ i.length > 0 && k(i);
79
80
  }).catch(() => {}), () => {
80
81
  e = !0;
81
82
  };
82
83
  }, [
83
- C,
84
- E,
85
- S
86
- ]), a(() => {
87
- if (!E || h || C) return;
84
+ w,
85
+ D,
86
+ C
87
+ ]), o(() => {
88
+ if (!D || g || w) return;
88
89
  let e = !1;
89
- return E.query({
90
- query: v,
91
- variables: { slug: c },
90
+ return D.query({
91
+ query: y,
92
+ variables: { slug: l },
92
93
  fetchPolicy: "cache-first"
93
94
  }).then((t) => {
94
95
  if (e) return;
@@ -98,40 +99,43 @@ function S({ productSlug: c, productName: u, tagline: d, version: f = "v1.0.0",
98
99
  id: e,
99
100
  label: e.charAt(0).toUpperCase() + e.slice(1),
100
101
  href: t,
101
- icon: b[e.toLowerCase()] || /* @__PURE__ */ m(l, { className: "size-5" })
102
+ icon: x[e.toLowerCase()] || /* @__PURE__ */ h(u, { className: "size-5" })
102
103
  }));
103
- r.length > 0 && A(r);
104
+ r.length > 0 && j(r);
104
105
  }).catch(() => {}), () => {
105
106
  e = !0;
106
107
  };
107
108
  }, [
108
- h,
109
- C,
110
- E,
111
- c
112
- ]), /* @__PURE__ */ m(i, {
113
- productName: u,
114
- tagline: d,
115
- columns: o(() => {
116
- let e = p ?? n;
117
- return D ? e.map((e) => e.title === "Legal" ? {
118
- ...e,
119
- links: D
120
- } : e) : e;
121
- }, [D, p]),
122
- socialLinks: h ?? k ?? r,
123
- version: f,
109
+ g,
110
+ w,
111
+ D,
112
+ l
113
+ ]);
114
+ let M = s(() => {
115
+ let e = m ?? n;
116
+ return O ? e.map((e) => e.title === "Legal" ? {
117
+ ...e,
118
+ links: O
119
+ } : e) : e;
120
+ }, [O, m]);
121
+ return /* @__PURE__ */ h(i, {
122
+ logo: /* @__PURE__ */ h(a, { size: "sidenav" }),
123
+ productName: d,
124
+ tagline: f,
125
+ columns: M,
126
+ socialLinks: g ?? A ?? r,
127
+ version: p,
124
128
  context: {
125
- workspace: w ?? void 0,
126
- project: T ?? void 0
129
+ workspace: T ?? void 0,
130
+ project: E ?? void 0
127
131
  },
128
- renderLink: ({ href: e, external: t, children: n, className: r }) => t ? /* @__PURE__ */ m("a", {
132
+ renderLink: ({ href: e, external: t, children: n, className: r }) => t ? /* @__PURE__ */ h("a", {
129
133
  href: e,
130
134
  target: "_blank",
131
135
  rel: "noopener noreferrer",
132
136
  className: r,
133
137
  children: n
134
- }) : /* @__PURE__ */ m(g, {
138
+ }) : /* @__PURE__ */ h(_, {
135
139
  to: e,
136
140
  className: r,
137
141
  children: n
@@ -139,4 +143,4 @@ function S({ productSlug: c, productName: u, tagline: d, version: f = "v1.0.0",
139
143
  });
140
144
  }
141
145
  //#endregion
142
- export { S as DynamicFooter };
146
+ export { C as DynamicFooter };
@@ -4,6 +4,8 @@ export interface Product {
4
4
  name: string;
5
5
  description?: string;
6
6
  icon?: ReactNode;
7
+ /** Real product logo (the app's `/icons/icon.svg`). Preferred over `icon`. */
8
+ logoUrl?: string;
7
9
  url?: string;
8
10
  isActive?: boolean;
9
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProductPickerSheet.d.ts","sourceRoot":"","sources":["../../src/chrome/ProductPickerSheet.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAO3C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAiI1D,CAAC"}
1
+ {"version":3,"file":"ProductPickerSheet.d.ts","sourceRoot":"","sources":["../../src/chrome/ProductPickerSheet.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAO3C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkCD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAuH1D,CAAC"}
@@ -1,99 +1,110 @@
1
1
  import { Sheet as e, SheetContent as t, SheetHeader as n, SheetTitle as r } from "../ui/sheet.js";
2
- import { filterProducts as i } from "./ProductSwitcher.js";
3
- import { useMemo as a, useState as o } from "react";
4
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
2
+ import { filterProducts as i, resolveProductLogo as a } from "./ProductSwitcher.js";
3
+ import { useMemo as o, useState as s } from "react";
4
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
5
  //#region src/chrome/ProductPickerSheet.tsx
6
- var l = 6, u = ({ open: u, onOpenChange: d, products: f, currentProductId: p, onProductChange: m }) => {
7
- let [h, g] = o(""), _ = f.length > l, v = a(() => i(f, h), [f, h]), y = (e) => {
8
- m && m(e), d(!1);
6
+ var u = 6, d = ({ product: e }) => {
7
+ let [t, n] = s(!1), r = a(e);
8
+ return r && !t ? /* @__PURE__ */ c("div", {
9
+ className: "size-10 rounded-lg bg-white p-1 ring-1 ring-border-default dark:ring-border-strong flex items-center justify-center flex-shrink-0 overflow-hidden",
10
+ children: /* @__PURE__ */ c("img", {
11
+ src: r,
12
+ alt: e.name,
13
+ className: "size-full object-contain",
14
+ onError: () => n(!0)
15
+ })
16
+ }) : e.icon ? /* @__PURE__ */ c("div", {
17
+ className: "size-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center flex-shrink-0",
18
+ children: e.icon
19
+ }) : /* @__PURE__ */ c("div", {
20
+ className: "size-10 rounded-lg bg-action-primary-bg flex items-center justify-center flex-shrink-0",
21
+ children: /* @__PURE__ */ c("span", {
22
+ className: "text-action-primary-text font-bold text-sm",
23
+ children: e.name.substring(0, 2).toUpperCase()
24
+ })
25
+ });
26
+ }, f = ({ open: a, onOpenChange: f, products: p, currentProductId: m, onProductChange: h }) => {
27
+ let [g, _] = s(""), v = p.length > u, y = o(() => i(p, g), [p, g]), b = (e) => {
28
+ h && h(e), f(!1);
9
29
  };
10
- return /* @__PURE__ */ s(e, {
11
- open: u,
30
+ return /* @__PURE__ */ c(e, {
31
+ open: a,
12
32
  onOpenChange: (e) => {
13
- e || g(""), d(e);
33
+ e || _(""), f(e);
14
34
  },
15
- children: /* @__PURE__ */ c(t, {
35
+ children: /* @__PURE__ */ l(t, {
16
36
  side: "bottom",
17
37
  className: "h-[60vh] flex flex-col p-0",
18
38
  children: [
19
- /* @__PURE__ */ s(n, {
39
+ /* @__PURE__ */ c(n, {
20
40
  className: "px-4 pt-4 pb-2 border-b border-border-subtle",
21
- children: /* @__PURE__ */ s(r, {
41
+ children: /* @__PURE__ */ c(r, {
22
42
  className: "text-text-primary",
23
43
  children: "Switch Product"
24
44
  })
25
45
  }),
26
- _ && /* @__PURE__ */ c("div", {
46
+ v && /* @__PURE__ */ l("div", {
27
47
  className: "relative px-4 py-2 border-b border-border-subtle",
28
- children: [/* @__PURE__ */ s("svg", {
48
+ children: [/* @__PURE__ */ c("svg", {
29
49
  className: "pointer-events-none absolute left-7 top-1/2 -translate-y-1/2 size-4 text-text-muted",
30
50
  fill: "none",
31
51
  stroke: "currentColor",
32
52
  viewBox: "0 0 24 24",
33
- children: /* @__PURE__ */ s("path", {
53
+ children: /* @__PURE__ */ c("path", {
34
54
  strokeLinecap: "round",
35
55
  strokeLinejoin: "round",
36
56
  strokeWidth: 2,
37
57
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
38
58
  })
39
- }), /* @__PURE__ */ s("input", {
59
+ }), /* @__PURE__ */ c("input", {
40
60
  type: "text",
41
- value: h,
42
- onChange: (e) => g(e.target.value),
61
+ value: g,
62
+ onChange: (e) => _(e.target.value),
43
63
  placeholder: "Search products…",
44
64
  "aria-label": "Search products",
45
65
  className: "w-full rounded-md border border-border-subtle bg-bg-surface py-2.5 pl-9 pr-3 text-sm text-text-primary placeholder:text-text-muted focus:border-transparent focus:outline-none focus:ring-2 focus:ring-[var(--color-action-primary-border)]"
46
66
  })]
47
67
  }),
48
- /* @__PURE__ */ c("div", {
68
+ /* @__PURE__ */ l("div", {
49
69
  className: "flex-1 overflow-y-auto py-2",
50
- children: [v.length === 0 && /* @__PURE__ */ c("p", {
70
+ children: [y.length === 0 && /* @__PURE__ */ l("p", {
51
71
  className: "px-4 py-6 text-center text-body-sm text-text-muted",
52
72
  children: [
53
73
  "No products match “",
54
- h,
74
+ g,
55
75
  "”"
56
76
  ]
57
- }), v.map((e) => /* @__PURE__ */ c("button", {
58
- onClick: () => y(e),
59
- className: `w-full flex items-center gap-4 px-4 py-3.5 text-body-sm transition-colors ${e.id === p ? "bg-[var(--color-accent-soft)]" : "hover:bg-bg-sunken"}`,
77
+ }), y.map((e) => /* @__PURE__ */ l("button", {
78
+ onClick: () => b(e),
79
+ className: `w-full flex items-center gap-4 px-4 py-3.5 text-body-sm transition-colors ${e.id === m ? "bg-[var(--color-accent-soft)]" : "hover:bg-bg-sunken"}`,
60
80
  children: [
61
- e.icon ? /* @__PURE__ */ s("div", {
62
- className: "size-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center flex-shrink-0",
63
- children: e.icon
64
- }) : /* @__PURE__ */ s("div", {
65
- className: "size-10 rounded-lg bg-action-primary-bg flex items-center justify-center flex-shrink-0",
66
- children: /* @__PURE__ */ s("span", {
67
- className: "text-action-primary-text font-bold text-sm",
68
- children: e.name.substring(0, 2).toUpperCase()
69
- })
70
- }),
71
- /* @__PURE__ */ c("div", {
81
+ /* @__PURE__ */ c(d, { product: e }),
82
+ /* @__PURE__ */ l("div", {
72
83
  className: "flex-1 text-left min-w-0",
73
- children: [/* @__PURE__ */ s("p", {
84
+ children: [/* @__PURE__ */ c("p", {
74
85
  className: "font-medium text-text-primary",
75
86
  children: e.name
76
- }), e.description && /* @__PURE__ */ s("p", {
87
+ }), e.description && /* @__PURE__ */ c("p", {
77
88
  className: "text-xs text-text-secondary truncate",
78
89
  children: e.description
79
90
  })]
80
91
  }),
81
- e.id === p && /* @__PURE__ */ s("svg", {
92
+ e.id === m && /* @__PURE__ */ c("svg", {
82
93
  className: "size-5 text-action-primary-bg flex-shrink-0",
83
94
  fill: "currentColor",
84
95
  viewBox: "0 0 20 20",
85
- children: /* @__PURE__ */ s("path", {
96
+ children: /* @__PURE__ */ c("path", {
86
97
  fillRule: "evenodd",
87
98
  d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
88
99
  clipRule: "evenodd"
89
100
  })
90
101
  }),
91
- e.url && e.id !== p && /* @__PURE__ */ s("svg", {
102
+ e.url && e.id !== m && /* @__PURE__ */ c("svg", {
92
103
  className: "size-4 text-text-muted flex-shrink-0",
93
104
  fill: "none",
94
105
  stroke: "currentColor",
95
106
  viewBox: "0 0 24 24",
96
- children: /* @__PURE__ */ s("path", {
107
+ children: /* @__PURE__ */ c("path", {
97
108
  strokeLinecap: "round",
98
109
  strokeLinejoin: "round",
99
110
  strokeWidth: 2,
@@ -108,4 +119,4 @@ var l = 6, u = ({ open: u, onOpenChange: d, products: f, currentProductId: p, on
108
119
  });
109
120
  };
110
121
  //#endregion
111
- export { u as ProductPickerSheet };
122
+ export { f as ProductPickerSheet };
@@ -5,9 +5,21 @@ export interface Product {
5
5
  url: string;
6
6
  icon?: string;
7
7
  color?: string;
8
+ /** Real product logo (the app's `/icons/icon.svg`). Rendered as an <img>. */
9
+ logoUrl?: string;
8
10
  /** When true, render as disabled with a "Coming soon" badge. */
9
11
  comingSoon?: boolean;
10
12
  }
13
+ /**
14
+ * Resolve a product's logo URL: prefer an explicit `logoUrl`, else derive it
15
+ * from the product's app URL (every product app serves its real brand mark at
16
+ * `/icons/icon.svg`). This keeps the switcher showing real logos for ALL shells
17
+ * without each shell having to thread `logoUrl` through its product list.
18
+ */
19
+ export declare function resolveProductLogo(product?: {
20
+ logoUrl?: string;
21
+ url?: string;
22
+ }): string | undefined;
11
23
  /**
12
24
  * Filter a product list by a free-text query, matching against name, id, and
13
25
  * (when present) description — case-insensitive, whitespace-trimmed. An empty
@@ -1 +1 @@
1
- {"version":3,"file":"ProductSwitcher.d.ts","sourceRoot":"","sources":["../../src/chrome/ProductSwitcher.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAShC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACzF,QAAQ,EAAE,CAAC,EAAE,EACb,KAAK,EAAE,MAAM,GACZ,CAAC,EAAE,CASL;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,OAAO,EAAE,EACnB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,GAAG,SAAS,CAKrB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CA0NpD,CAAC"}
1
+ {"version":3,"file":"ProductSwitcher.d.ts","sourceRoot":"","sources":["../../src/chrome/ProductSwitcher.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAShC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,GAAG,SAAS,CAKrB;AA0CD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACzF,QAAQ,EAAE,CAAC,EAAE,EACb,KAAK,EAAE,MAAM,GACZ,CAAC,EAAE,CASL;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,OAAO,EAAE,EACnB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,GAAG,SAAS,CAKrB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CA4MpD,CAAC"}
@@ -2,57 +2,75 @@ import { useEffect as e, useMemo as t, useRef as n, useState as r } from "react"
2
2
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
3
3
  //#region src/chrome/ProductSwitcher.tsx
4
4
  var o = 6;
5
- function s(e, t) {
5
+ function s(e) {
6
+ if (e?.logoUrl) return e.logoUrl;
7
+ let t = e?.url;
8
+ if (!(!t || t === "#")) return `${t.replace(/\/+$/, "")}/icons/icon.svg`;
9
+ }
10
+ var c = ({ product: e, sizeClass: t, textClass: n }) => {
11
+ let [a, o] = r(!1), c = s(e), l = !!c && !a;
12
+ return /* @__PURE__ */ i("div", {
13
+ className: `${t} rounded-md flex items-center justify-center flex-shrink-0 overflow-hidden ${l ? "bg-white p-0.5 ring-1 ring-border-default dark:ring-border-strong" : `text-text-inverse font-semibold ${n}`}`,
14
+ style: l ? void 0 : { backgroundColor: e?.color || "var(--color-action-primary-bg)" },
15
+ children: l ? /* @__PURE__ */ i("img", {
16
+ src: c,
17
+ alt: e?.name ?? "",
18
+ className: "size-full object-contain",
19
+ onError: () => o(!0)
20
+ }) : e?.icon || e?.name.charAt(0)
21
+ });
22
+ };
23
+ function l(e, t) {
6
24
  let n = t.trim().toLowerCase();
7
25
  return n ? e.filter((e) => e.name.toLowerCase().includes(n) || e.id.toLowerCase().includes(n) || (e.description ? e.description.toLowerCase().includes(n) : !1)) : e;
8
26
  }
9
- function c(e, t) {
27
+ function u(e, t) {
10
28
  return e.find((e) => e.id === t) ?? (t ? {
11
29
  id: t,
12
30
  name: t,
13
31
  url: "#"
14
32
  } : e[0]);
15
33
  }
16
- var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1 }) => {
17
- let [p, m] = r(!1), [h, g] = r(""), _ = n(null), v = n(null), y = c(l, u), b = l.length > o, x = t(() => s(l, h), [l, h]);
34
+ var d = ({ products: s, currentProductId: d, onProductChange: f, compact: p = !1 }) => {
35
+ let [m, h] = r(!1), [g, _] = r(""), v = n(null), y = n(null), b = u(s, d), x = s.length > o, S = t(() => l(s, g), [s, g]);
18
36
  e(() => {
19
37
  let e = (e) => {
20
- _.current && !_.current.contains(e.target) && m(!1);
38
+ v.current && !v.current.contains(e.target) && h(!1);
21
39
  };
22
- if (p) return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
23
- }, [p]), e(() => {
24
- if (!p) {
25
- g("");
40
+ if (m) return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
41
+ }, [m]), e(() => {
42
+ if (!m) {
43
+ _("");
26
44
  return;
27
45
  }
28
- if (b) {
29
- let e = setTimeout(() => v.current?.focus(), 60);
46
+ if (x) {
47
+ let e = setTimeout(() => y.current?.focus(), 60);
30
48
  return () => clearTimeout(e);
31
49
  }
32
- }, [p, b]);
33
- let S = (e) => {
34
- e.comingSoon || (d ? d(e) : window.location.href = e.url, m(!1));
50
+ }, [m, x]);
51
+ let C = (e) => {
52
+ e.comingSoon || (f ? f(e) : window.location.href = e.url, h(!1));
35
53
  };
36
54
  return /* @__PURE__ */ a("div", {
37
55
  className: "relative",
38
- ref: _,
56
+ ref: v,
39
57
  children: [/* @__PURE__ */ a("button", {
40
- onClick: () => m(!p),
41
- className: `flex items-center gap-2 px-3 py-2 rounded-button hover:bg-bg-sunken transition-colors ${p ? "bg-bg-sunken" : ""}`,
58
+ onClick: () => h(!m),
59
+ className: `flex items-center gap-2 px-3 py-2 rounded-button hover:bg-bg-sunken transition-colors ${m ? "bg-bg-sunken" : ""}`,
42
60
  "aria-label": "Switch product",
43
- "aria-expanded": p,
61
+ "aria-expanded": m,
44
62
  children: [
45
- /* @__PURE__ */ i("div", {
46
- className: "size-6 rounded-md flex items-center justify-center flex-shrink-0 text-text-inverse font-semibold text-xs",
47
- style: { backgroundColor: y?.color || "var(--color-action-primary-bg)" },
48
- children: y?.icon || y?.name.charAt(0)
63
+ /* @__PURE__ */ i(c, {
64
+ product: b,
65
+ sizeClass: "size-6",
66
+ textClass: "text-xs"
49
67
  }),
50
- !f && /* @__PURE__ */ i("span", {
68
+ !p && /* @__PURE__ */ i("span", {
51
69
  className: "text-body-sm font-medium text-text-primary",
52
- children: y?.name
70
+ children: b?.name
53
71
  }),
54
- !f && /* @__PURE__ */ i("svg", {
55
- className: `w-4 h-4 text-text-secondary transition-transform ${p ? "rotate-180" : ""}`,
72
+ !p && /* @__PURE__ */ i("svg", {
73
+ className: `w-4 h-4 text-text-secondary transition-transform ${m ? "rotate-180" : ""}`,
56
74
  fill: "none",
57
75
  stroke: "currentColor",
58
76
  viewBox: "0 0 24 24",
@@ -64,7 +82,7 @@ var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1
64
82
  })
65
83
  })
66
84
  ]
67
- }), p && /* @__PURE__ */ a("div", {
85
+ }), m && /* @__PURE__ */ a("div", {
68
86
  className: "absolute right-0 mt-2 w-[calc(100vw-1.5rem)] sm:w-64 max-w-64 bg-bg-elevated border border-border-subtle rounded-card shadow-[var(--shadow-elevation-4)] z-50 py-2 overflow-hidden animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-200",
69
87
  children: [
70
88
  /* @__PURE__ */ i("div", {
@@ -74,7 +92,7 @@ var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1
74
92
  children: "Switch Product"
75
93
  })
76
94
  }),
77
- b && /* @__PURE__ */ a("div", {
95
+ x && /* @__PURE__ */ a("div", {
78
96
  className: "relative px-3 py-2 border-b border-border-subtle",
79
97
  children: [
80
98
  /* @__PURE__ */ i("svg", {
@@ -90,20 +108,20 @@ var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1
90
108
  })
91
109
  }),
92
110
  /* @__PURE__ */ i("input", {
93
- ref: v,
111
+ ref: y,
94
112
  type: "text",
95
- value: h,
96
- onChange: (e) => g(e.target.value),
113
+ value: g,
114
+ onChange: (e) => _(e.target.value),
97
115
  onKeyDown: (e) => {
98
- e.key === "Escape" && (h ? (e.stopPropagation(), g("")) : m(!1));
116
+ e.key === "Escape" && (g ? (e.stopPropagation(), _("")) : h(!1));
99
117
  },
100
118
  placeholder: "Search products…",
101
119
  "aria-label": "Search products",
102
120
  className: "w-full rounded-md border border-border-subtle bg-bg-surface py-2 pl-9 pr-8 text-sm text-text-primary placeholder:text-text-muted transition-all duration-200 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-[var(--color-action-primary-border)]"
103
121
  }),
104
- h && /* @__PURE__ */ i("button", {
122
+ g && /* @__PURE__ */ i("button", {
105
123
  type: "button",
106
- onClick: () => g(""),
124
+ onClick: () => _(""),
107
125
  "aria-label": "Clear search",
108
126
  className: "absolute right-5 top-1/2 -translate-y-1/2 rounded-button p-1 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
109
127
  children: /* @__PURE__ */ i("svg", {
@@ -123,24 +141,24 @@ var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1
123
141
  }),
124
142
  /* @__PURE__ */ a("div", {
125
143
  className: "py-1 max-h-96 overflow-y-auto",
126
- children: [x.length === 0 && /* @__PURE__ */ a("p", {
144
+ children: [S.length === 0 && /* @__PURE__ */ a("p", {
127
145
  className: "px-4 py-6 text-center text-body-sm text-text-muted",
128
146
  children: [
129
147
  "No products match “",
130
- h,
148
+ g,
131
149
  "”"
132
150
  ]
133
- }), x.map((e) => /* @__PURE__ */ a("button", {
134
- onClick: () => S(e),
151
+ }), S.map((e) => /* @__PURE__ */ a("button", {
152
+ onClick: () => C(e),
135
153
  disabled: e.comingSoon,
136
154
  "aria-disabled": e.comingSoon,
137
155
  title: e.comingSoon ? "Coming soon" : void 0,
138
- className: `w-full flex items-center gap-3 px-4 py-2.5 text-body-sm transition-colors ${e.comingSoon ? "text-text-muted cursor-not-allowed opacity-60" : e.id === u ? "bg-[var(--color-accent-soft)] text-text-primary font-medium" : "text-text-primary hover:bg-bg-sunken"}`,
156
+ className: `w-full flex items-center gap-3 px-4 py-2.5 text-body-sm transition-colors ${e.comingSoon ? "text-text-muted cursor-not-allowed opacity-60" : e.id === d ? "bg-[var(--color-accent-soft)] text-text-primary font-medium" : "text-text-primary hover:bg-bg-sunken"}`,
139
157
  children: [
140
- /* @__PURE__ */ i("div", {
141
- className: "size-8 rounded-md flex items-center justify-center flex-shrink-0 text-text-inverse font-semibold text-sm",
142
- style: { backgroundColor: e.color || "var(--color-action-primary-bg)" },
143
- children: e.icon || e.name.charAt(0)
158
+ /* @__PURE__ */ i(c, {
159
+ product: e,
160
+ sizeClass: "size-8",
161
+ textClass: "text-sm"
144
162
  }),
145
163
  /* @__PURE__ */ i("span", {
146
164
  className: "flex-1 truncate text-left",
@@ -149,7 +167,7 @@ var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1
149
167
  e.comingSoon ? /* @__PURE__ */ i("span", {
150
168
  className: "shrink-0 whitespace-nowrap rounded-full border border-border-subtle bg-bg-sunken px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-text-secondary",
151
169
  children: "Coming soon"
152
- }) : e.id === u && /* @__PURE__ */ i("svg", {
170
+ }) : e.id === d && /* @__PURE__ */ i("svg", {
153
171
  className: "size-5 text-action-primary-bg",
154
172
  fill: "currentColor",
155
173
  viewBox: "0 0 20 20",
@@ -167,4 +185,4 @@ var l = ({ products: l, currentProductId: u, onProductChange: d, compact: f = !1
167
185
  });
168
186
  };
169
187
  //#endregion
170
- export { l as ProductSwitcher, s as filterProducts };
188
+ export { d as ProductSwitcher, l as filterProducts, s as resolveProductLogo };
package/dist/chrome.js CHANGED
@@ -23,15 +23,15 @@ import { ProductPickerSheet as C } from "./chrome/ProductPickerSheet.js";
23
23
  import { AccountSwitcher as w } from "./chrome/AccountSwitcher.js";
24
24
  import { AutoBreadcrumbs as T, registerBreadcrumbName as E, unregisterBreadcrumbName as D } from "./chrome/AutoBreadcrumbs.js";
25
25
  import { ProductSideNav as O } from "./chrome/ProductSideNav.js";
26
- import { DynamicFooter as k } from "./chrome/DynamicFooter.js";
27
- import { PanelTabs as A } from "./chrome/PanelTabs.js";
28
- import { PanelContainer as j } from "./chrome/PanelContainer.js";
29
- import { StatusBar as M } from "./chrome/StatusBar.js";
30
- import { PluginRoutes as N } from "./chrome/PluginRoutes.js";
31
- import { PluginSettingsPage as P } from "./chrome/PluginSettingsPage.js";
32
- import { PluginToolbar as F } from "./chrome/PluginToolbar.js";
33
- import { PluginWidgetGrid as I } from "./chrome/PluginWidgetGrid.js";
34
- import { PluginContextMenuTarget as L } from "./chrome/PluginContextMenuTarget.js";
35
- import { ThemePreferences as R } from "./chrome/ThemePreferences.js";
36
- import { BrandMark as z } from "./chrome/BrandMark.js";
37
- export { w as AccountSwitcher, t as AppShellLayout, T as AutoBreadcrumbs, z as BrandMark, f as Breadcrumbs, d as CommandPalette, y as ContextSwitcher, o as DEFAULT_FOOTER_COLUMNS, s as DEFAULT_SOCIAL_LINKS, k as DynamicFooter, c as Footer, i as FooterBar, b as GeographySwitcher, u as GlobalSearch, r as HeaderBar, S as LanguagePickerSheet, v as LanguageSwitcher, p as NavLink, x as NotificationCenter, n as PageHeader, j as PanelContainer, A as PanelTabs, L as PluginContextMenuTarget, a as PluginFooterStrip, N as PluginRoutes, P as PluginSettingsPage, F as PluginToolbar, I as PluginWidgetGrid, C as ProductPickerSheet, O as ProductSideNav, _ as ProductSwitcher, g as ProfileSwitcher, e as ShortcutHelpDialog, l as SideNavigation, h as Sidebar, M as StatusBar, m as Tabs, R as ThemePreferences, E as registerBreadcrumbName, D as unregisterBreadcrumbName };
26
+ import { BrandMark as k } from "./chrome/BrandMark.js";
27
+ import { DynamicFooter as A } from "./chrome/DynamicFooter.js";
28
+ import { PanelTabs as j } from "./chrome/PanelTabs.js";
29
+ import { PanelContainer as M } from "./chrome/PanelContainer.js";
30
+ import { StatusBar as N } from "./chrome/StatusBar.js";
31
+ import { PluginRoutes as P } from "./chrome/PluginRoutes.js";
32
+ import { PluginSettingsPage as F } from "./chrome/PluginSettingsPage.js";
33
+ import { PluginToolbar as I } from "./chrome/PluginToolbar.js";
34
+ import { PluginWidgetGrid as L } from "./chrome/PluginWidgetGrid.js";
35
+ import { PluginContextMenuTarget as R } from "./chrome/PluginContextMenuTarget.js";
36
+ import { ThemePreferences as z } from "./chrome/ThemePreferences.js";
37
+ export { w as AccountSwitcher, t as AppShellLayout, T as AutoBreadcrumbs, k as BrandMark, f as Breadcrumbs, d as CommandPalette, y as ContextSwitcher, o as DEFAULT_FOOTER_COLUMNS, s as DEFAULT_SOCIAL_LINKS, A as DynamicFooter, c as Footer, i as FooterBar, b as GeographySwitcher, u as GlobalSearch, r as HeaderBar, S as LanguagePickerSheet, v as LanguageSwitcher, p as NavLink, x as NotificationCenter, n as PageHeader, M as PanelContainer, j as PanelTabs, R as PluginContextMenuTarget, a as PluginFooterStrip, P as PluginRoutes, F as PluginSettingsPage, I as PluginToolbar, L as PluginWidgetGrid, C as ProductPickerSheet, O as ProductSideNav, _ as ProductSwitcher, g as ProfileSwitcher, e as ShortcutHelpDialog, l as SideNavigation, h as Sidebar, N as StatusBar, m as Tabs, z as ThemePreferences, E as registerBreadcrumbName, D as unregisterBreadcrumbName };
@@ -51,6 +51,19 @@ export declare const PRODUCT_URLS: {
51
51
  readonly manufacturedops: "https://app.manufacturedops.com/";
52
52
  readonly proserviceworld: "https://app.proserviceworld.com/";
53
53
  readonly intelwatchtower: "https://app.intelwatchtower.com/";
54
+ readonly govcitizenhub: "https://app.govcitizenhub.com/";
55
+ readonly brainyrich: "https://app.brainyrich.com/";
56
+ readonly buildmyiq: "https://app.buildmyiq.com/";
57
+ readonly collabkin: "https://app.collabkin.com/";
58
+ readonly comradecircle: "https://app.comradecircle.com/";
59
+ readonly cosmicintersection: "https://app.cosmicintersection.com/";
60
+ readonly ecoimpacthub: "https://app.ecoimpacthub.com/";
61
+ readonly mybodyshield: "https://app.mybodyshield.com/";
62
+ readonly planmagnet: "https://app.planmagnet.com/";
63
+ readonly semanticfed: "https://app.semanticfed.com/";
64
+ readonly technospam: "https://app.technospam.com/";
65
+ readonly theculturepost: "https://app.theculturepost.com/";
66
+ readonly theglobalfuel: "https://app.theglobalfuel.com/";
54
67
  };
55
68
  };
56
69
  export declare const PRODUCTS: ProductConfig[];
@@ -1 +1 @@
1
- {"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/shared/config/products.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCf,CAAC;AAEX,eAAO,MAAM,QAAQ,EAAE,aAAa,EA0MnC,CAAC;AAOF,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB;;QA7Q7B,MAAM;UACJ,MAAM;UACN,MAAM;WACL,MAAM;kBACC,MAAM;IACpB;;;;;OAKG;iBACU,OAAO;IAoQrB"}
1
+ {"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/shared/config/products.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDf,CAAC;AAEX,eAAO,MAAM,QAAQ,EAAE,aAAa,EAkTnC,CAAC;AAOF,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB;;QAlY7B,MAAM;UACJ,MAAM;UACN,MAAM;WACL,MAAM;kBACC,MAAM;IACpB;;;;;OAKG;iBACU,OAAO;IAyXrB"}
@@ -32,7 +32,20 @@ var e = {
32
32
  movethewheels: "https://app.movethewheels.com/",
33
33
  manufacturedops: "https://app.manufacturedops.com/",
34
34
  proserviceworld: "https://app.proserviceworld.com/",
35
- intelwatchtower: "https://app.intelwatchtower.com/"
35
+ intelwatchtower: "https://app.intelwatchtower.com/",
36
+ govcitizenhub: "https://app.govcitizenhub.com/",
37
+ brainyrich: "https://app.brainyrich.com/",
38
+ buildmyiq: "https://app.buildmyiq.com/",
39
+ collabkin: "https://app.collabkin.com/",
40
+ comradecircle: "https://app.comradecircle.com/",
41
+ cosmicintersection: "https://app.cosmicintersection.com/",
42
+ ecoimpacthub: "https://app.ecoimpacthub.com/",
43
+ mybodyshield: "https://app.mybodyshield.com/",
44
+ planmagnet: "https://app.planmagnet.com/",
45
+ semanticfed: "https://app.semanticfed.com/",
46
+ technospam: "https://app.technospam.com/",
47
+ theculturepost: "https://app.theculturepost.com/",
48
+ theglobalfuel: "https://app.theglobalfuel.com/"
36
49
  }
37
50
  }, t = [
38
51
  {
@@ -232,6 +245,110 @@ var e = {
232
245
  color: "#0369a1",
233
246
  description: "Military & intelligence platform",
234
247
  comingSoon: !0
248
+ },
249
+ {
250
+ id: "govcitizenhub",
251
+ name: "GovCitizenHub",
252
+ icon: "GC",
253
+ color: "#e34003",
254
+ description: "Government & citizen operations platform",
255
+ comingSoon: !0
256
+ },
257
+ {
258
+ id: "brainyrich",
259
+ name: "BrainyRich",
260
+ icon: "BR",
261
+ color: "#059669",
262
+ description: "Wealth management platform",
263
+ comingSoon: !0
264
+ },
265
+ {
266
+ id: "buildmyiq",
267
+ name: "BuildMyIQ",
268
+ icon: "BI",
269
+ color: "#6366f1",
270
+ description: "AI-native learning platform",
271
+ comingSoon: !0
272
+ },
273
+ {
274
+ id: "collabkin",
275
+ name: "CollabKin",
276
+ icon: "CK",
277
+ color: "#f59e0b",
278
+ description: "Private family & ancestry",
279
+ comingSoon: !0
280
+ },
281
+ {
282
+ id: "comradecircle",
283
+ name: "ComradeCircle",
284
+ icon: "CC",
285
+ color: "#0d9488",
286
+ description: "Community engagement platform",
287
+ comingSoon: !0
288
+ },
289
+ {
290
+ id: "cosmicintersection",
291
+ name: "CosmicIntersection",
292
+ icon: "CI",
293
+ color: "#7c3aed",
294
+ description: "Space & science data platform",
295
+ comingSoon: !0
296
+ },
297
+ {
298
+ id: "ecoimpacthub",
299
+ name: "EcoImpactHub",
300
+ icon: "EI",
301
+ color: "#16a34a",
302
+ description: "Environment, sustainability & conservation",
303
+ comingSoon: !0
304
+ },
305
+ {
306
+ id: "mybodyshield",
307
+ name: "MyBodyShield",
308
+ icon: "MB",
309
+ color: "#2563eb",
310
+ description: "Complete health & fitness platform",
311
+ comingSoon: !0
312
+ },
313
+ {
314
+ id: "planmagnet",
315
+ name: "PlanMagnet",
316
+ icon: "PM",
317
+ color: "#3b82f6",
318
+ description: "Product & project management",
319
+ comingSoon: !0
320
+ },
321
+ {
322
+ id: "semanticfed",
323
+ name: "SemanticFed",
324
+ icon: "SF",
325
+ color: "#0891b2",
326
+ description: "Data federation platform",
327
+ comingSoon: !0
328
+ },
329
+ {
330
+ id: "technospam",
331
+ name: "TechnoSpam",
332
+ icon: "TS",
333
+ color: "#8b5cf6",
334
+ description: "Learn technology by doing",
335
+ comingSoon: !0
336
+ },
337
+ {
338
+ id: "theculturepost",
339
+ name: "TheCulturePost",
340
+ icon: "CP",
341
+ color: "#db2777",
342
+ description: "Sourced cultural storytelling",
343
+ comingSoon: !0
344
+ },
345
+ {
346
+ id: "theglobalfuel",
347
+ name: "TheGlobalFuel",
348
+ icon: "TF",
349
+ color: "#f59e0b",
350
+ description: "Energy, minerals & resources platform",
351
+ comingSoon: !0
235
352
  }
236
353
  ];
237
354
  function n() {
@@ -12,6 +12,8 @@ export interface Product {
12
12
  url: string;
13
13
  icon: string;
14
14
  color: string;
15
+ /** Real product logo (the app's `/icons/icon.svg`), used by the switcher. */
16
+ logoUrl?: string;
15
17
  /** When true, render as disabled with a "Coming soon" badge (non-GA product). */
16
18
  comingSoon?: boolean;
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useProducts.d.ts","sourceRoot":"","sources":["../../../../src/shared/hooks/shell/useProducts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA8DH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAiDD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAwD3E"}
1
+ {"version":3,"file":"useProducts.d.ts","sourceRoot":"","sources":["../../../../src/shared/hooks/shell/useProducts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA8DH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA6DD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAyD3E"}
@@ -50,19 +50,23 @@ function m(e, t) {
50
50
  function h(e, t) {
51
51
  return t?.color && typeof t.color == "string" ? t.color : f[e] || p;
52
52
  }
53
- function g() {
53
+ function g(e) {
54
+ if (e) return `${e.replace(/\/+$/, "")}/icons/icon.svg`;
55
+ }
56
+ function _() {
54
57
  return e.map((e) => ({
55
58
  id: e.id,
56
59
  name: e.name,
57
60
  url: t(e.id),
58
61
  icon: e.icon,
59
62
  color: e.color,
63
+ logoUrl: g(t(e.id)),
60
64
  comingSoon: e.comingSoon
61
65
  }));
62
66
  }
63
- function _(e) {
64
- let o = n("global"), [s, c] = a(g()), [f, p] = a(e?.autoFetch !== !1), [_, v] = a(null), y = r(async () => {
65
- p(!0), v(null);
67
+ function v(e) {
68
+ let o = n("global"), [s, c] = a(_()), [f, p] = a(e?.autoFetch !== !1), [v, y] = a(null), b = r(async () => {
69
+ p(!0), y(null);
66
70
  try {
67
71
  let e = ((await o.query({
68
72
  query: u,
@@ -77,11 +81,12 @@ function _(e) {
77
81
  url: e.appUrl || t(e.slug),
78
82
  icon: m(e.name, e.slug),
79
83
  color: h(e.slug, e.metadata),
84
+ logoUrl: e.logoUrl || g(e.appUrl || t(e.slug)),
80
85
  comingSoon: l(e.slug, e.status, e.appUrl)
81
86
  }));
82
- e.sort((e, t) => e.name.localeCompare(t.name)), c(e.length > 0 ? e : g());
87
+ e.sort((e, t) => e.name.localeCompare(t.name)), c(e.length > 0 ? e : _());
83
88
  } catch (e) {
84
- v(e instanceof Error ? e.message : "Failed to fetch products"), c(g());
89
+ y(e instanceof Error ? e.message : "Failed to fetch products"), c(_());
85
90
  } finally {
86
91
  p(!1);
87
92
  }
@@ -91,13 +96,13 @@ function _(e) {
91
96
  p(!1);
92
97
  return;
93
98
  }
94
- y();
99
+ b();
95
100
  }, []), {
96
101
  products: s,
97
102
  isLoading: f,
98
- error: _,
99
- refetch: y
103
+ error: v,
104
+ refetch: b
100
105
  };
101
106
  }
102
107
  //#endregion
103
- export { _ as useProducts };
108
+ export { v as useProducts };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.719.2",
3
+ "version": "2026.719.4",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "imports": {