@burdenoff/fe-libs 2026.1021.14 → 2026.1022.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.
Files changed (50) hide show
  1. package/dist/admin-overview/AdminOverviewActionsContext.d.ts +11 -0
  2. package/dist/admin-overview/AdminOverviewActionsContext.js +17 -0
  3. package/dist/admin-overview/AdminOverviewPage.d.ts +4 -0
  4. package/dist/admin-overview/AdminOverviewPage.js +524 -0
  5. package/dist/admin-overview/buildHierarchyGraph.d.ts +36 -0
  6. package/dist/admin-overview/buildHierarchyGraph.js +172 -0
  7. package/dist/admin-overview/index.d.ts +10 -0
  8. package/dist/admin-overview/nodes/OrganizationNode.d.ts +9 -0
  9. package/dist/admin-overview/nodes/OrganizationNode.js +85 -0
  10. package/dist/admin-overview/nodes/ProjectNode.d.ts +9 -0
  11. package/dist/admin-overview/nodes/ProjectNode.js +69 -0
  12. package/dist/admin-overview/nodes/TenantNode.d.ts +9 -0
  13. package/dist/admin-overview/nodes/TenantNode.js +78 -0
  14. package/dist/admin-overview/nodes/WorkspaceNode.d.ts +9 -0
  15. package/dist/admin-overview/nodes/WorkspaceNode.js +136 -0
  16. package/dist/admin-overview/nodes/nodeStyles.d.ts +7 -0
  17. package/dist/admin-overview/nodes/nodeStyles.js +10 -0
  18. package/dist/admin-overview/operations.d.ts +45 -0
  19. package/dist/admin-overview/operations.js +42 -0
  20. package/dist/admin-overview.d.ts +2 -0
  21. package/dist/admin-overview.js +3 -0
  22. package/dist/chrome/GlobalSearch.js +9 -9
  23. package/dist/chrome/HeaderThemeSwitcher.js +7 -7
  24. package/dist/chrome.js +44 -44
  25. package/dist/platform-pages/AcceptShareRoute.d.ts +33 -0
  26. package/dist/platform-pages/AcceptShareRoute.js +72 -0
  27. package/dist/platform-pages/AffiliatesPage.d.ts +16 -0
  28. package/dist/platform-pages/AffiliatesPage.js +583 -0
  29. package/dist/platform-pages/AppearanceSettingsPage.d.ts +14 -0
  30. package/dist/platform-pages/AppearanceSettingsPage.js +14 -0
  31. package/dist/platform-pages/index.d.ts +20 -0
  32. package/dist/platform-pages.d.ts +2 -0
  33. package/dist/platform-pages.js +4 -0
  34. package/dist/shared/config/shellRoutes.js +7 -0
  35. package/dist/shared/feature-flags/FeatureFlagProvider.d.ts +10 -0
  36. package/dist/shared/feature-flags/FeatureFlagProvider.js +4 -1
  37. package/dist/shared/feature-flags/index.d.ts +2 -2
  38. package/dist/shared/feature-flags/useFeatureFlag.d.ts +26 -1
  39. package/dist/shared/feature-flags/useFeatureFlag.js +25 -12
  40. package/dist/shared/hooks/shell/useGlobalSearch.d.ts +11 -2
  41. package/dist/shared/hooks/shell/useGlobalSearch.js +54 -23
  42. package/dist/shared/hooks/usePushDeviceRegistration.js +1 -1
  43. package/dist/shared/providers/AppShellProvider.js +6 -6
  44. package/dist/shared-feature-flags.js +4 -4
  45. package/dist/shared-hooks.js +25 -25
  46. package/dist/shared-native.js +15 -15
  47. package/dist/shared-providers-shell.js +12 -12
  48. package/dist/shared.js +94 -94
  49. package/dist/shell-native/push-optin.js +4 -4
  50. package/package.json +16 -3
@@ -0,0 +1,172 @@
1
+ import { MarkerType as e } from "@xyflow/react";
2
+ //#region src/admin-overview/buildHierarchyGraph.ts
3
+ var t = 260, n = 260, r = 220, i = 240, a = 60, o = 140, s = 60, c = -260, l = 0, u = 260, d = 520, f = 120, p = "__ungrouped__";
4
+ function m(e) {
5
+ let { organizations: m, workspaces: _, tenants: v, projectsByWorkspace: y, loadingProjectsFor: b, selectedId: x } = e, S = /* @__PURE__ */ new Map();
6
+ for (let e of _) {
7
+ let t = e.organizationId ?? p, n = S.get(t);
8
+ n ? n.push(e) : S.set(t, [e]);
9
+ }
10
+ let C = S.has(p) ? [...m, {
11
+ id: p,
12
+ name: "Unassigned Workspaces",
13
+ slug: null,
14
+ tenantId: null
15
+ }] : m;
16
+ function w(e) {
17
+ let t = y[e.id];
18
+ return !t || t.length === 0 ? n : Math.max(n, r);
19
+ }
20
+ function T(e) {
21
+ let n = S.get(e) ?? [];
22
+ if (n.length === 0) return t;
23
+ let r = n.reduce((e, t) => e + w(t), 0) + a * (n.length - 1);
24
+ return Math.max(t, r);
25
+ }
26
+ let E = /* @__PURE__ */ new Set(), D = /* @__PURE__ */ new Set();
27
+ if (x) {
28
+ let [e, t] = x.split(":");
29
+ if (E.add(x), e === "org") (S.get(t) ?? []).forEach((e) => {
30
+ E.add(h("ws", e.id)), D.add(`e-org-ws-${t}-${e.id}`), (y[e.id] ?? []).forEach((t) => {
31
+ E.add(h("proj", t.id)), D.add(`e-ws-proj-${e.id}-${t.id}`);
32
+ });
33
+ });
34
+ else if (e === "ws") {
35
+ let e = _.find((e) => e.id === t);
36
+ e && (e.organizationId && (E.add(h("org", e.organizationId)), D.add(`e-org-ws-${e.organizationId}-${e.id}`)), e.tenantId && (E.add(h("tenant", e.tenantId)), D.add(`e-tenant-ws-${e.tenantId}-${e.id}`)), (y[e.id] ?? []).forEach((t) => {
37
+ E.add(h("proj", t.id)), D.add(`e-ws-proj-${e.id}-${t.id}`);
38
+ }));
39
+ } else if (e === "tenant") for (let e of _) e.tenantId === t && (E.add(h("ws", e.id)), D.add(`e-tenant-ws-${t}-${e.id}`));
40
+ else if (e === "proj") {
41
+ let e = Object.values(y).flat().find((e) => !!e && e.id === t);
42
+ e && (E.add(h("ws", e.workspaceId)), D.add(`e-ws-proj-${e.workspaceId}-${e.id}`));
43
+ }
44
+ }
45
+ let O = [], k = [], A = 0;
46
+ C.forEach((e) => {
47
+ let i = T(e.id), s = A + i / 2, c = e.id === p;
48
+ if (!c) {
49
+ let n = s - t / 2;
50
+ O.push({
51
+ id: h("org", e.id),
52
+ type: "organization",
53
+ position: {
54
+ x: n,
55
+ y: l
56
+ },
57
+ data: {
58
+ kind: "organization",
59
+ entity: e,
60
+ workspaceCount: (S.get(e.id) ?? []).length,
61
+ isHighlighted: E.has(h("org", e.id))
62
+ }
63
+ });
64
+ }
65
+ let m = S.get(e.id) ?? [], _ = s - (m.reduce((e, t) => e + w(t), 0) + a * Math.max(0, m.length - 1)) / 2;
66
+ m.forEach((t) => {
67
+ let i = w(t), o = _ + i / 2, s = o - n / 2, l = y[t.id], p = E.has(h("ws", t.id));
68
+ if (O.push({
69
+ id: h("ws", t.id),
70
+ type: "workspace",
71
+ position: {
72
+ x: s,
73
+ y: u
74
+ },
75
+ data: {
76
+ kind: "workspace",
77
+ entity: t,
78
+ projectCount: l ? l.length : null,
79
+ projectsLoading: b.has(t.id),
80
+ isHighlighted: p
81
+ }
82
+ }), c || k.push(g({
83
+ id: `e-org-ws-${e.id}-${t.id}`,
84
+ source: h("org", e.id),
85
+ target: h("ws", t.id),
86
+ highlighted: D.has(`e-org-ws-${e.id}-${t.id}`),
87
+ variant: "solid"
88
+ })), l && l.length > 0) {
89
+ let e = o - r / 2;
90
+ l.forEach((n, r) => {
91
+ O.push({
92
+ id: h("proj", n.id),
93
+ type: "project",
94
+ position: {
95
+ x: e,
96
+ y: d + r * f
97
+ },
98
+ data: {
99
+ kind: "project",
100
+ entity: n,
101
+ isHighlighted: E.has(h("proj", n.id))
102
+ }
103
+ }), k.push(g({
104
+ id: `e-ws-proj-${t.id}-${n.id}`,
105
+ source: h("ws", t.id),
106
+ target: h("proj", n.id),
107
+ highlighted: D.has(`e-ws-proj-${t.id}-${n.id}`),
108
+ variant: "solid"
109
+ }));
110
+ });
111
+ }
112
+ _ += i + a;
113
+ }), A += i + o;
114
+ });
115
+ let j = Math.max(0, A - o), M = v.length > 0 ? v.length * i + s * Math.max(0, v.length - 1) : 0, N = j > 0 ? j / 2 - M / 2 : -M / 2;
116
+ return v.forEach((e, t) => {
117
+ let n = _.filter((t) => t.tenantId === e.id);
118
+ O.push({
119
+ id: h("tenant", e.id),
120
+ type: "tenant",
121
+ position: {
122
+ x: N + t * 300,
123
+ y: c
124
+ },
125
+ data: {
126
+ kind: "tenant",
127
+ entity: e,
128
+ workspaceCount: n.length,
129
+ isHighlighted: E.has(h("tenant", e.id))
130
+ }
131
+ }), n.forEach((t) => {
132
+ k.push(g({
133
+ id: `e-tenant-ws-${e.id}-${t.id}`,
134
+ source: h("tenant", e.id),
135
+ target: h("ws", t.id),
136
+ highlighted: D.has(`e-tenant-ws-${e.id}-${t.id}`),
137
+ variant: "dashed"
138
+ }));
139
+ });
140
+ }), {
141
+ nodes: O,
142
+ edges: k
143
+ };
144
+ }
145
+ function h(e, t) {
146
+ return `${e}:${t}`;
147
+ }
148
+ function g(t) {
149
+ let { id: n, source: r, target: i, highlighted: a, variant: o } = t, s = a ? "var(--color-action-primary-bg)" : "var(--color-border-default)";
150
+ return {
151
+ id: n,
152
+ source: r,
153
+ target: i,
154
+ type: "smoothstep",
155
+ animated: a,
156
+ style: {
157
+ stroke: s,
158
+ strokeWidth: a ? 2.5 : 1.5,
159
+ strokeDasharray: o === "dashed" ? "5 5" : void 0,
160
+ opacity: a ? 1 : o === "dashed" ? .7 : .9,
161
+ transition: "stroke 150ms ease, stroke-width 150ms ease, opacity 150ms ease"
162
+ },
163
+ markerEnd: {
164
+ type: e.ArrowClosed,
165
+ color: s,
166
+ width: 18,
167
+ height: 18
168
+ }
169
+ };
170
+ }
171
+ //#endregion
172
+ export { m as buildHierarchyGraph };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @burdenoff/fe-libs/admin-overview
3
+ *
4
+ * The account hierarchy graph (Organization → Workspace → Project, with Tenant
5
+ * chips) that app shells mount at `/admin/overview`, inside
6
+ * `<GatewayRoute gateway="global">`. It renders with React Flow, so the shell
7
+ * must install the optional `@xyflow/react` peer.
8
+ */
9
+ export { AdminOverviewPage, type AdminOverviewPageProps } from './AdminOverviewPage';
10
+ export { buildHierarchyGraph, type HierarchyNodeData } from './buildHierarchyGraph';
@@ -0,0 +1,9 @@
1
+ import { NodeProps } from '@xyflow/react';
2
+ import { HierarchyNodeData } from '../buildHierarchyGraph';
3
+ type Props = NodeProps & {
4
+ data: Extract<HierarchyNodeData, {
5
+ kind: 'organization';
6
+ }>;
7
+ };
8
+ export declare function OrganizationNode({ data }: Props): import('react/jsx-runtime').JSX.Element;
9
+ export {};
@@ -0,0 +1,85 @@
1
+ import { useShellNavigate as e } from "../../shared/utils/appHelpers.js";
2
+ import "../../shared-utils.js";
3
+ import { MANAGE_BUTTON_CLASS as t, NODE_CARD_CLASS_BASE as n, nodeBorderColor as r, nodeBoxShadow as i } from "./nodeStyles.js";
4
+ import { Building as a, Settings as o } from "lucide-react";
5
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
6
+ import { Handle as l, Position as u } from "@xyflow/react";
7
+ //#region src/admin-overview/nodes/OrganizationNode.tsx
8
+ function d({ data: d }) {
9
+ let f = e(), { entity: p, workspaceCount: m, isHighlighted: h } = d;
10
+ return /* @__PURE__ */ c("div", {
11
+ className: `${n} min-w-[240px]`,
12
+ style: {
13
+ background: "var(--color-bg-surface)",
14
+ borderColor: r(h),
15
+ color: "var(--color-text-primary)",
16
+ boxShadow: i(h)
17
+ },
18
+ "data-testid": `admin-overview-org-${p.id}`,
19
+ children: [
20
+ /* @__PURE__ */ s(l, {
21
+ type: "source",
22
+ position: u.Bottom,
23
+ style: {
24
+ background: "var(--color-action-primary-bg)",
25
+ width: 8,
26
+ height: 8
27
+ }
28
+ }),
29
+ /* @__PURE__ */ c("div", {
30
+ className: "flex items-center justify-between px-3 py-2 border-b",
31
+ style: { borderColor: "var(--color-border-default)" },
32
+ children: [/* @__PURE__ */ c("div", {
33
+ className: "flex items-center gap-2",
34
+ children: [/* @__PURE__ */ s(a, {
35
+ size: 16,
36
+ style: { color: "var(--color-action-primary-bg)" }
37
+ }), /* @__PURE__ */ s("span", {
38
+ className: "text-[11px] font-semibold uppercase tracking-wide",
39
+ style: { color: "var(--color-text-secondary)" },
40
+ children: "Organization"
41
+ })]
42
+ }), /* @__PURE__ */ s("button", {
43
+ type: "button",
44
+ onClick: (e) => {
45
+ e.stopPropagation(), f(`/organizations/${p.id}`);
46
+ },
47
+ className: t,
48
+ style: { color: "var(--color-action-primary-bg)" },
49
+ title: "Manage organization",
50
+ "aria-label": `Manage organization ${p.name}`,
51
+ children: /* @__PURE__ */ s(o, { size: 14 })
52
+ })]
53
+ }),
54
+ /* @__PURE__ */ c("div", {
55
+ className: "px-3 py-2",
56
+ children: [
57
+ /* @__PURE__ */ s("div", {
58
+ className: "font-semibold text-sm truncate",
59
+ title: p.name,
60
+ children: p.name
61
+ }),
62
+ p.slug ? /* @__PURE__ */ s("div", {
63
+ className: "text-xs truncate",
64
+ style: { color: "var(--color-text-secondary)" },
65
+ children: p.slug
66
+ }) : null,
67
+ /* @__PURE__ */ c("div", {
68
+ className: "text-xs mt-1 inline-flex items-center gap-1 px-1.5 py-0.5 rounded",
69
+ style: {
70
+ background: "var(--color-bg-subtle, transparent)",
71
+ color: "var(--color-text-secondary)"
72
+ },
73
+ children: [
74
+ m,
75
+ " workspace",
76
+ m === 1 ? "" : "s"
77
+ ]
78
+ })
79
+ ]
80
+ })
81
+ ]
82
+ });
83
+ }
84
+ //#endregion
85
+ export { d as OrganizationNode };
@@ -0,0 +1,9 @@
1
+ import { NodeProps } from '@xyflow/react';
2
+ import { HierarchyNodeData } from '../buildHierarchyGraph';
3
+ type Props = NodeProps & {
4
+ data: Extract<HierarchyNodeData, {
5
+ kind: 'project';
6
+ }>;
7
+ };
8
+ export declare function ProjectNode({ data }: Props): import('react/jsx-runtime').JSX.Element;
9
+ export {};
@@ -0,0 +1,69 @@
1
+ import { useShellNavigate as e } from "../../shared/utils/appHelpers.js";
2
+ import "../../shared-utils.js";
3
+ import { MANAGE_BUTTON_CLASS as t, NODE_CARD_CLASS_BASE as n, nodeBorderColor as r, nodeBoxShadow as i } from "./nodeStyles.js";
4
+ import { Package as a, Settings as o } from "lucide-react";
5
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
6
+ import { Handle as l, Position as u } from "@xyflow/react";
7
+ //#region src/admin-overview/nodes/ProjectNode.tsx
8
+ function d({ data: d }) {
9
+ let f = e(), { entity: p, isHighlighted: m } = d;
10
+ return /* @__PURE__ */ c("div", {
11
+ className: `${n} min-w-[200px]`,
12
+ style: {
13
+ background: "var(--color-bg-surface)",
14
+ borderColor: r(m),
15
+ color: "var(--color-text-primary)",
16
+ boxShadow: i(m)
17
+ },
18
+ "data-testid": `admin-overview-project-${p.id}`,
19
+ children: [/* @__PURE__ */ s(l, {
20
+ type: "target",
21
+ position: u.Top,
22
+ style: {
23
+ background: "var(--color-action-primary-bg)",
24
+ width: 8,
25
+ height: 8
26
+ }
27
+ }), /* @__PURE__ */ c("div", {
28
+ className: "flex items-center justify-between px-3 py-2",
29
+ children: [/* @__PURE__ */ c("div", {
30
+ className: "flex items-center gap-2 min-w-0",
31
+ children: [/* @__PURE__ */ s(a, {
32
+ size: 14,
33
+ style: { color: "var(--color-action-primary-bg)" }
34
+ }), /* @__PURE__ */ c("div", {
35
+ className: "min-w-0",
36
+ children: [
37
+ /* @__PURE__ */ s("div", {
38
+ className: "text-[10px] font-semibold uppercase tracking-wide",
39
+ style: { color: "var(--color-text-secondary)" },
40
+ children: "Project"
41
+ }),
42
+ /* @__PURE__ */ s("div", {
43
+ className: "text-sm font-medium truncate",
44
+ title: p.name,
45
+ children: p.name
46
+ }),
47
+ p.key ? /* @__PURE__ */ c("div", {
48
+ className: "text-[11px] truncate",
49
+ style: { color: "var(--color-text-secondary)" },
50
+ children: [p.key, p.archived ? " · archived" : ""]
51
+ }) : null
52
+ ]
53
+ })]
54
+ }), /* @__PURE__ */ s("button", {
55
+ type: "button",
56
+ onClick: (e) => {
57
+ e.stopPropagation(), f(`/workspaces/${p.workspaceId}/projects`);
58
+ },
59
+ className: t,
60
+ style: { color: "var(--color-action-primary-bg)" },
61
+ title: "Manage project",
62
+ "aria-label": `Manage project ${p.name}`,
63
+ children: /* @__PURE__ */ s(o, { size: 12 })
64
+ })]
65
+ })]
66
+ });
67
+ }
68
+ //#endregion
69
+ export { d as ProjectNode };
@@ -0,0 +1,9 @@
1
+ import { NodeProps } from '@xyflow/react';
2
+ import { HierarchyNodeData } from '../buildHierarchyGraph';
3
+ type Props = NodeProps & {
4
+ data: Extract<HierarchyNodeData, {
5
+ kind: 'tenant';
6
+ }>;
7
+ };
8
+ export declare function TenantNode({ data }: Props): import('react/jsx-runtime').JSX.Element;
9
+ export {};
@@ -0,0 +1,78 @@
1
+ import { useShellNavigate as e } from "../../shared/utils/appHelpers.js";
2
+ import "../../shared-utils.js";
3
+ import { MANAGE_BUTTON_CLASS as t, NODE_CARD_CLASS_BASE as n, nodeBorderColor as r, nodeBoxShadow as i } from "./nodeStyles.js";
4
+ import { Building2 as a, Settings as o } from "lucide-react";
5
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
6
+ import { Handle as l, Position as u } from "@xyflow/react";
7
+ //#region src/admin-overview/nodes/TenantNode.tsx
8
+ function d({ data: d }) {
9
+ let f = e(), { entity: p, workspaceCount: m, isHighlighted: h } = d;
10
+ return /* @__PURE__ */ c("div", {
11
+ className: `${n} min-w-[220px]`,
12
+ style: {
13
+ background: "var(--color-bg-subtle, var(--color-bg-surface))",
14
+ borderColor: r(h),
15
+ borderStyle: "dashed",
16
+ color: "var(--color-text-primary)",
17
+ boxShadow: i(h)
18
+ },
19
+ "data-testid": `admin-overview-tenant-${p.id}`,
20
+ children: [/* @__PURE__ */ s(l, {
21
+ type: "source",
22
+ position: u.Bottom,
23
+ style: {
24
+ background: "var(--color-action-primary-bg)",
25
+ width: 8,
26
+ height: 8
27
+ }
28
+ }), /* @__PURE__ */ c("div", {
29
+ className: "flex items-center justify-between px-3 py-2",
30
+ children: [/* @__PURE__ */ c("div", {
31
+ className: "flex items-center gap-2 min-w-0",
32
+ children: [/* @__PURE__ */ s(a, {
33
+ size: 14,
34
+ style: { color: "var(--color-action-primary-bg)" }
35
+ }), /* @__PURE__ */ c("div", {
36
+ className: "min-w-0",
37
+ children: [
38
+ /* @__PURE__ */ s("div", {
39
+ className: "text-[10px] font-semibold uppercase tracking-wide",
40
+ style: { color: "var(--color-text-secondary)" },
41
+ children: "Tenant"
42
+ }),
43
+ /* @__PURE__ */ s("div", {
44
+ className: "text-sm font-medium truncate",
45
+ title: p.name,
46
+ children: p.name
47
+ }),
48
+ /* @__PURE__ */ c("div", {
49
+ className: "text-[11px] mt-0.5 flex items-center gap-1.5",
50
+ style: { color: "var(--color-text-secondary)" },
51
+ children: [
52
+ /* @__PURE__ */ s("span", {
53
+ className: "px-1 py-0.5 rounded text-[9px] font-medium uppercase tracking-wide",
54
+ style: { border: "1px solid var(--color-border-default)" },
55
+ children: p.type ?? "shared"
56
+ }),
57
+ /* @__PURE__ */ s("span", { children: "·" }),
58
+ /* @__PURE__ */ c("span", { children: [m, " ws"] })
59
+ ]
60
+ })
61
+ ]
62
+ })]
63
+ }), /* @__PURE__ */ s("button", {
64
+ type: "button",
65
+ onClick: (e) => {
66
+ e.stopPropagation(), f(`/organizations?tenantId=${p.id}`);
67
+ },
68
+ className: t,
69
+ style: { color: "var(--color-action-primary-bg)" },
70
+ title: "View tenant organizations",
71
+ "aria-label": `View organizations for tenant ${p.name}`,
72
+ children: /* @__PURE__ */ s(o, { size: 14 })
73
+ })]
74
+ })]
75
+ });
76
+ }
77
+ //#endregion
78
+ export { d as TenantNode };
@@ -0,0 +1,9 @@
1
+ import { NodeProps } from '@xyflow/react';
2
+ import { HierarchyNodeData } from '../buildHierarchyGraph';
3
+ type Props = NodeProps & {
4
+ data: Extract<HierarchyNodeData, {
5
+ kind: 'workspace';
6
+ }>;
7
+ };
8
+ export declare function WorkspaceNode({ data }: Props): import('react/jsx-runtime').JSX.Element;
9
+ export {};
@@ -0,0 +1,136 @@
1
+ import { useAdminOverviewActions as e } from "../AdminOverviewActionsContext.js";
2
+ import { MANAGE_BUTTON_CLASS as t, NODE_CARD_CLASS_BASE as n, nodeBorderColor as r, nodeBoxShadow as i } from "./nodeStyles.js";
3
+ import { LayoutGrid as a, Loader2 as o, Package as s, Settings as c } from "lucide-react";
4
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
5
+ import { Handle as d, Position as f } from "@xyflow/react";
6
+ //#region src/admin-overview/nodes/WorkspaceNode.tsx
7
+ function p(e) {
8
+ if (!e) return "var(--color-text-secondary)";
9
+ let t = e.toLowerCase();
10
+ return t === "active" ? "var(--color-status-success-text)" : t === "suspended" || t === "inactive" ? "var(--color-status-warning-text)" : "var(--color-text-secondary)";
11
+ }
12
+ function m({ data: m }) {
13
+ let { onLoadProjects: h, onManageWorkspace: g } = e(), { entity: _, projectCount: v, projectsLoading: y, isHighlighted: b } = m;
14
+ return /* @__PURE__ */ u("div", {
15
+ className: `${n} min-w-[240px]`,
16
+ style: {
17
+ background: "var(--color-bg-surface)",
18
+ borderColor: r(b),
19
+ color: "var(--color-text-primary)",
20
+ boxShadow: i(b)
21
+ },
22
+ "data-testid": `admin-overview-workspace-${_.id}`,
23
+ children: [
24
+ /* @__PURE__ */ l(d, {
25
+ type: "target",
26
+ position: f.Top,
27
+ style: {
28
+ background: "var(--color-action-primary-bg)",
29
+ width: 8,
30
+ height: 8
31
+ }
32
+ }),
33
+ /* @__PURE__ */ l(d, {
34
+ type: "source",
35
+ position: f.Bottom,
36
+ style: {
37
+ background: "var(--color-action-primary-bg)",
38
+ width: 8,
39
+ height: 8
40
+ }
41
+ }),
42
+ /* @__PURE__ */ u("div", {
43
+ className: "flex items-center justify-between px-3 py-2 border-b",
44
+ style: { borderColor: "var(--color-border-default)" },
45
+ children: [/* @__PURE__ */ u("div", {
46
+ className: "flex items-center gap-2",
47
+ children: [/* @__PURE__ */ l(a, {
48
+ size: 16,
49
+ style: { color: "var(--color-action-primary-bg)" }
50
+ }), /* @__PURE__ */ l("span", {
51
+ className: "text-[11px] font-semibold uppercase tracking-wide",
52
+ style: { color: "var(--color-text-secondary)" },
53
+ children: "Workspace"
54
+ })]
55
+ }), /* @__PURE__ */ l("button", {
56
+ type: "button",
57
+ onClick: (e) => {
58
+ e.stopPropagation(), g(_.id);
59
+ },
60
+ className: t,
61
+ style: { color: "var(--color-action-primary-bg)" },
62
+ title: "Manage workspace",
63
+ "aria-label": `Manage workspace ${_.name}`,
64
+ children: /* @__PURE__ */ l(c, { size: 14 })
65
+ })]
66
+ }),
67
+ /* @__PURE__ */ u("div", {
68
+ className: "px-3 py-2",
69
+ children: [
70
+ /* @__PURE__ */ l("div", {
71
+ className: "font-semibold text-sm truncate",
72
+ title: _.name,
73
+ children: _.name
74
+ }),
75
+ /* @__PURE__ */ u("div", {
76
+ className: "text-xs flex items-center gap-2 mt-1",
77
+ style: { color: "var(--color-text-secondary)" },
78
+ children: [
79
+ _.type ? /* @__PURE__ */ l("span", {
80
+ className: "px-1.5 py-0.5 rounded text-[10px] font-medium uppercase tracking-wide",
81
+ style: {
82
+ background: "var(--color-bg-subtle, transparent)",
83
+ border: "1px solid var(--color-border-default)"
84
+ },
85
+ children: _.type
86
+ }) : null,
87
+ _.status ? /* @__PURE__ */ u("span", {
88
+ className: "flex items-center gap-1",
89
+ style: { color: p(_.status) },
90
+ children: [/* @__PURE__ */ l("span", {
91
+ className: "inline-block size-1.5 rounded-full",
92
+ style: { background: p(_.status) }
93
+ }), _.status]
94
+ }) : null,
95
+ typeof _.memberCount == "number" ? /* @__PURE__ */ u("span", { children: [
96
+ "· ",
97
+ _.memberCount,
98
+ " members"
99
+ ] }) : null
100
+ ]
101
+ }),
102
+ /* @__PURE__ */ u("div", {
103
+ className: "mt-2 flex items-center justify-between gap-2 pt-2 border-t",
104
+ style: { borderColor: "var(--color-border-default)" },
105
+ children: [/* @__PURE__ */ u("div", {
106
+ className: "flex items-center gap-1 text-xs",
107
+ style: { color: "var(--color-text-secondary)" },
108
+ children: [/* @__PURE__ */ l(s, { size: 12 }), /* @__PURE__ */ l("span", { children: v === null ? "Projects not loaded" : `${v} project${v === 1 ? "" : "s"}` })]
109
+ }), /* @__PURE__ */ l("button", {
110
+ type: "button",
111
+ onClick: (e) => {
112
+ e.stopPropagation(), h(_.id);
113
+ },
114
+ disabled: y,
115
+ className: "text-xs px-2 py-1 rounded-md border cursor-pointer transition-all duration-150 disabled:opacity-50 disabled:cursor-not-allowed hover:bg-[color:var(--color-action-primary-bg)]/10",
116
+ style: {
117
+ borderColor: "var(--color-action-primary-bg)",
118
+ color: "var(--color-action-primary-bg)"
119
+ },
120
+ title: "Load projects for this workspace",
121
+ children: y ? /* @__PURE__ */ u("span", {
122
+ className: "flex items-center gap-1",
123
+ children: [/* @__PURE__ */ l(o, {
124
+ size: 12,
125
+ className: "animate-spin"
126
+ }), "Loading"]
127
+ }) : v === null ? "Load projects" : "Reload"
128
+ })]
129
+ })
130
+ ]
131
+ })
132
+ ]
133
+ });
134
+ }
135
+ //#endregion
136
+ export { m as WorkspaceNode };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared style helpers for Admin Overview custom nodes.
3
+ */
4
+ export declare const MANAGE_BUTTON_CLASS: string;
5
+ export declare const NODE_CARD_CLASS_BASE: string;
6
+ export declare function nodeBorderColor(highlighted: boolean): string;
7
+ export declare function nodeBoxShadow(highlighted: boolean): string | undefined;
@@ -0,0 +1,10 @@
1
+ //#region src/admin-overview/nodes/nodeStyles.ts
2
+ var e = "p-1.5 rounded-md cursor-pointer transition-all duration-150 hover:bg-[color:var(--color-action-primary-bg)]/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--color-action-primary-bg)]/40", t = "rounded-xl border shadow-sm transition-all duration-150 hover:shadow-md";
3
+ function n(e) {
4
+ return e ? "var(--color-action-primary-bg)" : "var(--color-border-default)";
5
+ }
6
+ function r(e) {
7
+ return e ? "0 0 0 2px var(--color-action-primary-bg), var(--shadow-elevation-2)" : void 0;
8
+ }
9
+ //#endregion
10
+ export { e as MANAGE_BUTTON_CLASS, t as NODE_CARD_CLASS_BASE, n as nodeBorderColor, r as nodeBoxShadow };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * GraphQL operations for the Admin Overview page.
3
+ *
4
+ * Global gateway operations (orgs / workspaces / tenants) are executed via
5
+ * Apollo `useQuery` under <GatewayRoute gateway="global">.
6
+ *
7
+ * The project query targets the WORKSPACE gateway and is executed via a raw
8
+ * fetch (workspace-scoped token is issued on demand) — see AdminOverviewPage.
9
+ */
10
+ export declare const GET_ADMIN_OVERVIEW_CONTEXT: import('graphql').DocumentNode;
11
+ /**
12
+ * Raw GraphQL document string for the workspace-gateway project fetch.
13
+ * Kept as a string (not gql) because we execute it via `fetch`, not Apollo.
14
+ */
15
+ export declare const GET_MY_PROJECTS_DOC = "\n query AdminOverviewGetMyProjects($pagination: PaginationInput) {\n myProjects(pagination: $pagination) {\n items {\n id\n name\n key\n workspaceId\n status\n archived\n }\n total\n hasMore\n }\n }\n";
16
+ export interface OrganizationSummary {
17
+ id: string;
18
+ name: string;
19
+ slug: string | null;
20
+ tenantId: string | null;
21
+ }
22
+ export interface WorkspaceSummary {
23
+ id: string;
24
+ name: string;
25
+ type: string | null;
26
+ status: string | null;
27
+ tenantId: string | null;
28
+ organizationId: string | null;
29
+ memberCount: number | null;
30
+ }
31
+ export interface TenantSummary {
32
+ id: string;
33
+ name: string;
34
+ slug: string | null;
35
+ status: string | null;
36
+ type: string | null;
37
+ }
38
+ export interface ProjectSummary {
39
+ id: string;
40
+ name: string;
41
+ key: string | null;
42
+ workspaceId: string;
43
+ status: string | null;
44
+ archived: boolean | null;
45
+ }