@burdenoff/microfe-subscriberbot 2026.731.1 → 2026.827.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/subscriberbot/SubscriberBotRoutes.js +1 -1
- package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
- package/dist/subscriberbot/components/viz.js +51 -27
- package/dist/subscriberbot/components/viz.js.map +1 -1
- package/dist/subscriberbot/context/SubscriberBotContext.js +1 -1
- package/dist/subscriberbot/context/SubscriberBotContext.js.map +1 -1
- package/dist/subscriberbot/hooks/index.d.ts +1 -1
- package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
- package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts +12 -1
- package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -1
- package/dist/subscriberbot/hooks/useSubscriberBotApi.js +82 -56
- package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
- package/dist/subscriberbot/pages/AssetVaultPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/AssetVaultPage.js +134 -78
- package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -1
- package/dist/subscriberbot/pages/InvoicesPage.d.ts +3 -2
- package/dist/subscriberbot/pages/InvoicesPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/InvoicesPage.js +43 -31
- package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts +3 -1
- package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentDetailPage.js +195 -159
- package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.d.ts +4 -2
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +368 -266
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
- package/dist/subscriberbot/types/index.d.ts +37 -0
- package/dist/subscriberbot/types/index.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useSubscriberBot as e } from "./context/SubscriberBotContext.js";
|
|
2
2
|
import { DashboardPage as t } from "./pages/DashboardPage.js";
|
|
3
3
|
import { Suspense as n, lazy as r } from "react";
|
|
4
|
-
import { Navigate as i, Route as a, Routes as o, useLocation as s } from "react-router
|
|
4
|
+
import { Navigate as i, Route as a, Routes as o, useLocation as s } from "react-router";
|
|
5
5
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
6
|
import { Spinner as u } from "@burdenoff/fe-libs/ui";
|
|
7
7
|
//#region src/subscriberbot/SubscriberBotRoutes.tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriberBotRoutes.js","names":[],"sources":["../../src/subscriberbot/SubscriberBotRoutes.tsx"],"sourcesContent":["/**\n * SubscriberBot Routes\n * @module subscriberbot\n *\n * Domain routes for the Subscriber Bot product. The dashboard is eager-loaded\n * (primary landing); all other pages are lazy-loaded.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router
|
|
1
|
+
{"version":3,"file":"SubscriberBotRoutes.js","names":[],"sources":["../../src/subscriberbot/SubscriberBotRoutes.tsx"],"sourcesContent":["/**\n * SubscriberBot Routes\n * @module subscriberbot\n *\n * Domain routes for the Subscriber Bot product. The dashboard is eager-loaded\n * (primary landing); all other pages are lazy-loaded.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useSubscriberBot } from './context/SubscriberBotContext';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/DashboardPage';\n\n// Relationships\nconst RelationshipsListPage = lazy(() =>\n import('./pages/relationships/RelationshipsListPage').then((m) => ({\n default: m.RelationshipsListPage,\n }))\n);\nconst RelationshipNewPage = lazy(() =>\n import('./pages/relationships/RelationshipNewPage').then((m) => ({\n default: m.RelationshipNewPage,\n }))\n);\nconst RelationshipDetailPage = lazy(() =>\n import('./pages/relationships/RelationshipDetailPage').then((m) => ({\n default: m.RelationshipDetailPage,\n }))\n);\n\n// Providers\nconst ProvidersListPage = lazy(() =>\n import('./pages/providers/ProvidersListPage').then((m) => ({ default: m.ProvidersListPage }))\n);\nconst ProviderNewPage = lazy(() =>\n import('./pages/providers/ProviderNewPage').then((m) => ({ default: m.ProviderNewPage }))\n);\nconst ProviderDetailPage = lazy(() =>\n import('./pages/providers/ProviderDetailPage').then((m) => ({ default: m.ProviderDetailPage }))\n);\n\n// Inbox / Invoices / Workflows\nconst InboxPage = lazy(() => import('./pages/InboxPage').then((m) => ({ default: m.InboxPage })));\nconst InvoicesPage = lazy(() =>\n import('./pages/InvoicesPage').then((m) => ({ default: m.InvoicesPage }))\n);\nconst WorkflowsPage = lazy(() =>\n import('./pages/WorkflowsPage').then((m) => ({ default: m.WorkflowsPage }))\n);\n\n// Agents\nconst AgentsListPage = lazy(() =>\n import('./pages/agents/AgentsListPage').then((m) => ({ default: m.AgentsListPage }))\n);\nconst AgentNewPage = lazy(() =>\n import('./pages/agents/AgentNewPage').then((m) => ({ default: m.AgentNewPage }))\n);\nconst AgentDetailPage = lazy(() =>\n import('./pages/agents/AgentDetailPage').then((m) => ({ default: m.AgentDetailPage }))\n);\n\n// Insights + Asset Vault (aggregated real data)\nconst InsightsPage = lazy(() =>\n import('./pages/InsightsPage').then((m) => ({ default: m.InsightsPage }))\n);\nconst AssetVaultPage = lazy(() =>\n import('./pages/AssetVaultPage').then((m) => ({ default: m.AssetVaultPage }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const SubscriberBotRoutes: FC = () => {\n const { basePath, isStandalone } = useSubscriberBot();\n const location = useLocation();\n\n // Normalize base path\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Overview / dashboard */}\n <Route index element={<DashboardPage />} />\n\n {/* Relationships (the core domain) */}\n <Route path=\"relationships\" element={<RelationshipsListPage />} />\n <Route path=\"relationships/new\" element={<RelationshipNewPage />} />\n <Route path=\"relationships/:id\" element={<RelationshipDetailPage />} />\n\n {/* Providers (registry) */}\n <Route path=\"providers\" element={<ProvidersListPage />} />\n <Route path=\"providers/new\" element={<ProviderNewPage />} />\n <Route path=\"providers/:id\" element={<ProviderDetailPage />} />\n\n {/* Universal Inbox */}\n <Route path=\"inbox\" element={<InboxPage />} />\n\n {/* Invoices */}\n <Route path=\"invoices\" element={<InvoicesPage />} />\n\n {/* Insights (spend analytics + renewal forecast) */}\n <Route path=\"insights\" element={<InsightsPage />} />\n\n {/* Digital Asset Vault */}\n <Route path=\"vault\" element={<AssetVaultPage />} />\n\n {/* AI Agents */}\n <Route path=\"agents\" element={<AgentsListPage />} />\n <Route path=\"agents/new\" element={<AgentNewPage />} />\n <Route path=\"agents/:id\" element={<AgentDetailPage />} />\n\n {/* Workflows */}\n <Route path=\"workflows\" element={<WorkflowsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -10,8 +10,8 @@ var r = [
|
|
|
10
10
|
"var(--color-chart-6)",
|
|
11
11
|
"var(--color-chart-7)",
|
|
12
12
|
"var(--color-chart-8)"
|
|
13
|
-
], i = "var(--color-chart-
|
|
14
|
-
let d = r.reduce((e, t) => e + Math.max(0, t.value), 0), f = (i -
|
|
13
|
+
], i = "var(--color-chart-positive)", a = "var(--color-chart-negative)", o = "var(--color-chart-grid)", s = "var(--color-status-warning-text)", c = "var(--color-status-success-text)", l = (e, t) => t ?? r[e % r.length], u = ({ data: r, size: i = 160, thickness: a = 18, centerLabel: s, centerSub: c, className: u }) => {
|
|
14
|
+
let d = r.reduce((e, t) => e + Math.max(0, t.value), 0), f = (i - a) / 2, p = 2 * Math.PI * f, m = i / 2, h = 0, g = r.map((e) => `${e.label}: ${e.value}`).join(", ");
|
|
15
15
|
return /* @__PURE__ */ n("div", {
|
|
16
16
|
className: e("relative inline-flex items-center justify-center", u),
|
|
17
17
|
children: [/* @__PURE__ */ n("svg", {
|
|
@@ -26,8 +26,8 @@ var r = [
|
|
|
26
26
|
cy: m,
|
|
27
27
|
r: f,
|
|
28
28
|
fill: "none",
|
|
29
|
-
stroke:
|
|
30
|
-
strokeWidth:
|
|
29
|
+
stroke: o,
|
|
30
|
+
strokeWidth: a,
|
|
31
31
|
opacity: .4
|
|
32
32
|
}), d > 0 && r.map((e, n) => {
|
|
33
33
|
let r = Math.max(0, e.value) / d * p, i = /* @__PURE__ */ t("circle", {
|
|
@@ -35,8 +35,8 @@ var r = [
|
|
|
35
35
|
cy: m,
|
|
36
36
|
r: f,
|
|
37
37
|
fill: "none",
|
|
38
|
-
stroke:
|
|
39
|
-
strokeWidth:
|
|
38
|
+
stroke: l(n, e.color),
|
|
39
|
+
strokeWidth: a,
|
|
40
40
|
strokeDasharray: `${r} ${p - r}`,
|
|
41
41
|
strokeDashoffset: -h,
|
|
42
42
|
strokeLinecap: "butt",
|
|
@@ -44,25 +44,25 @@ var r = [
|
|
|
44
44
|
}, n);
|
|
45
45
|
return h += r, i;
|
|
46
46
|
})]
|
|
47
|
-
}), (s ||
|
|
47
|
+
}), (s || c) && /* @__PURE__ */ n("div", {
|
|
48
48
|
className: "absolute inset-0 flex flex-col items-center justify-center text-center",
|
|
49
49
|
children: [s && /* @__PURE__ */ t("span", {
|
|
50
50
|
className: "text-xl font-bold text-text-primary tabular-nums leading-none",
|
|
51
51
|
children: s
|
|
52
|
-
}),
|
|
52
|
+
}), c && /* @__PURE__ */ t("span", {
|
|
53
53
|
className: "mt-1 text-xs text-text-secondary",
|
|
54
|
-
children:
|
|
54
|
+
children: c
|
|
55
55
|
})]
|
|
56
56
|
})]
|
|
57
57
|
});
|
|
58
|
-
},
|
|
58
|
+
}, d = ({ data: r, valueFormat: i, className: a }) => /* @__PURE__ */ t("ul", {
|
|
59
59
|
className: e("space-y-2", a),
|
|
60
60
|
children: r.map((e, r) => /* @__PURE__ */ n("li", {
|
|
61
61
|
className: "flex items-center gap-2 text-sm",
|
|
62
62
|
children: [
|
|
63
63
|
/* @__PURE__ */ t("span", {
|
|
64
64
|
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
65
|
-
style: { backgroundColor:
|
|
65
|
+
style: { backgroundColor: l(r, e.color) },
|
|
66
66
|
"aria-hidden": !0
|
|
67
67
|
}),
|
|
68
68
|
/* @__PURE__ */ t("span", {
|
|
@@ -75,10 +75,10 @@ var r = [
|
|
|
75
75
|
})
|
|
76
76
|
]
|
|
77
77
|
}, r))
|
|
78
|
-
}),
|
|
78
|
+
}), f = ({ data: r, valueFormat: i, className: a }) => {
|
|
79
79
|
let s = Math.max(1, ...r.map((e) => e.value));
|
|
80
80
|
return /* @__PURE__ */ t("ul", {
|
|
81
|
-
className: e("space-y-3",
|
|
81
|
+
className: e("space-y-3", a),
|
|
82
82
|
role: "img",
|
|
83
83
|
"aria-label": "Bar chart",
|
|
84
84
|
children: r.map((e, r) => /* @__PURE__ */ n("li", { children: [/* @__PURE__ */ n("div", {
|
|
@@ -92,18 +92,42 @@ var r = [
|
|
|
92
92
|
})]
|
|
93
93
|
}), /* @__PURE__ */ t("div", {
|
|
94
94
|
className: "mt-1.5 h-2 w-full overflow-hidden rounded-full",
|
|
95
|
-
style: { backgroundColor:
|
|
95
|
+
style: { backgroundColor: o },
|
|
96
96
|
children: /* @__PURE__ */ t("div", {
|
|
97
97
|
className: "h-full rounded-full transition-all",
|
|
98
98
|
style: {
|
|
99
99
|
width: `${e.value / s * 100}%`,
|
|
100
|
-
backgroundColor:
|
|
100
|
+
backgroundColor: l(r, e.color)
|
|
101
101
|
}
|
|
102
102
|
})
|
|
103
103
|
})] }, r))
|
|
104
104
|
});
|
|
105
|
-
},
|
|
106
|
-
|
|
105
|
+
}, p = ({ points: r, width: o = 220, height: s = 56, positive: c = !0, className: l }) => {
|
|
106
|
+
if (r.length < 2) return null;
|
|
107
|
+
let u = Math.max(...r), d = Math.min(...r), f = u - d || 1, p = c ? i : a, m = o / (r.length - 1), h = r.map((e, t) => [t * m, s - (e - d) / f * (s - 8) - 4]).map(([e, t], n) => `${n === 0 ? "M" : "L"}${e.toFixed(1)},${t.toFixed(1)}`).join(" "), g = `${h} L${o},${s} L0,${s} Z`;
|
|
108
|
+
return /* @__PURE__ */ n("svg", {
|
|
109
|
+
width: o,
|
|
110
|
+
height: s,
|
|
111
|
+
viewBox: `0 0 ${o} ${s}`,
|
|
112
|
+
role: "img",
|
|
113
|
+
"aria-label": "Trend sparkline",
|
|
114
|
+
className: e("max-w-full", l),
|
|
115
|
+
preserveAspectRatio: "none",
|
|
116
|
+
children: [/* @__PURE__ */ t("path", {
|
|
117
|
+
d: g,
|
|
118
|
+
fill: p,
|
|
119
|
+
opacity: .12
|
|
120
|
+
}), /* @__PURE__ */ t("path", {
|
|
121
|
+
d: h,
|
|
122
|
+
fill: "none",
|
|
123
|
+
stroke: p,
|
|
124
|
+
strokeWidth: 2,
|
|
125
|
+
strokeLinejoin: "round",
|
|
126
|
+
strokeLinecap: "round"
|
|
127
|
+
})]
|
|
128
|
+
});
|
|
129
|
+
}, m = ({ value: r, max: i = 100, size: l = 120, label: u, className: d }) => {
|
|
130
|
+
let f = Math.max(0, Math.min(1, r / i)), p = l / 2 - 10, m = l / 2, h = Math.PI * p, g = f >= .66 ? c : f >= .33 ? s : a;
|
|
107
131
|
return /* @__PURE__ */ n("div", {
|
|
108
132
|
className: e("inline-flex flex-col items-center", d),
|
|
109
133
|
children: [/* @__PURE__ */ n("svg", {
|
|
@@ -116,7 +140,7 @@ var r = [
|
|
|
116
140
|
children: [/* @__PURE__ */ t("path", {
|
|
117
141
|
d: `M10 ${m} A ${p} ${p} 0 0 1 ${l - 10} ${m}`,
|
|
118
142
|
fill: "none",
|
|
119
|
-
stroke:
|
|
143
|
+
stroke: o,
|
|
120
144
|
strokeWidth: 10,
|
|
121
145
|
strokeLinecap: "round"
|
|
122
146
|
}), /* @__PURE__ */ t("path", {
|
|
@@ -138,12 +162,12 @@ var r = [
|
|
|
138
162
|
})]
|
|
139
163
|
})]
|
|
140
164
|
});
|
|
141
|
-
},
|
|
165
|
+
}, h = {
|
|
142
166
|
default: "var(--color-accent-indigo)",
|
|
143
|
-
positive:
|
|
144
|
-
warning:
|
|
167
|
+
positive: c,
|
|
168
|
+
warning: s,
|
|
145
169
|
muted: "var(--color-text-secondary)"
|
|
146
|
-
},
|
|
170
|
+
}, g = ({ items: r, className: i }) => /* @__PURE__ */ n("ol", {
|
|
147
171
|
className: e("relative space-y-5 pl-6", i),
|
|
148
172
|
children: [/* @__PURE__ */ t("span", {
|
|
149
173
|
className: "absolute left-[7px] top-1 bottom-1 w-px bg-border-subtle",
|
|
@@ -153,7 +177,7 @@ var r = [
|
|
|
153
177
|
children: [
|
|
154
178
|
/* @__PURE__ */ t("span", {
|
|
155
179
|
className: "absolute -left-[22px] top-1 h-3 w-3 rounded-full ring-4 ring-bg-surface",
|
|
156
|
-
style: { backgroundColor:
|
|
180
|
+
style: { backgroundColor: h[e.tone ?? "default"] },
|
|
157
181
|
"aria-hidden": !0
|
|
158
182
|
}),
|
|
159
183
|
/* @__PURE__ */ n("div", {
|
|
@@ -172,11 +196,11 @@ var r = [
|
|
|
172
196
|
})
|
|
173
197
|
]
|
|
174
198
|
}, r))]
|
|
175
|
-
}),
|
|
176
|
-
let u = Math.max(0, Math.min(1, r ? n / r : 0)), d =
|
|
199
|
+
}), _ = ({ value: n, max: r = 100, tone: i = "accent", className: l }) => {
|
|
200
|
+
let u = Math.max(0, Math.min(1, r ? n / r : 0)), d = i === "positive" ? c : i === "warning" ? s : i === "negative" ? a : "var(--color-accent-indigo)";
|
|
177
201
|
return /* @__PURE__ */ t("div", {
|
|
178
202
|
className: e("h-2 w-full overflow-hidden rounded-full", l),
|
|
179
|
-
style: { backgroundColor:
|
|
203
|
+
style: { backgroundColor: o },
|
|
180
204
|
role: "progressbar",
|
|
181
205
|
"aria-valuenow": Math.round(u * 100),
|
|
182
206
|
"aria-valuemin": 0,
|
|
@@ -191,6 +215,6 @@ var r = [
|
|
|
191
215
|
});
|
|
192
216
|
};
|
|
193
217
|
//#endregion
|
|
194
|
-
export {
|
|
218
|
+
export { f as BarList, r as CHART_COLORS, u as Donut, m as Gauge, d as Legend, _ as MiniProgress, p as Sparkline, g as Timeline };
|
|
195
219
|
|
|
196
220
|
//# sourceMappingURL=viz.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viz.js","names":[],"sources":["../../../src/subscriberbot/components/viz.tsx"],"sourcesContent":["/**\n * Tokenized, responsive SVG visualization primitives.\n * @module subscriberbot/components/viz\n *\n * Every color is a fe-libs semantic CSS variable (never a raw hex), so charts\n * theme automatically in light/dark and per-product themes. All charts scale to\n * their container (SVG viewBox) and carry an accessible role/label.\n */\nimport type { FC, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\n\n/** Categorical palette — fe-libs chart tokens. */\nexport const CHART_COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n 'var(--color-chart-6)',\n 'var(--color-chart-7)',\n 'var(--color-chart-8)',\n] as const;\n\nconst POSITIVE = 'var(--color-chart-positive)';\nconst NEGATIVE = 'var(--color-chart-negative)';\nconst GRID = 'var(--color-chart-grid)';\nconst WARN = 'var(--color-status-warning-text)';\nconst SUCCESS = 'var(--color-status-success-text)';\n\nexport interface Segment {\n label: string;\n value: number;\n color?: string;\n}\n\nconst colorAt = (i: number, override?: string) => override ?? CHART_COLORS[i % CHART_COLORS.length];\n\n// ---------------------------------------------------------------------------\n// Donut — proportional ring with an optional center label.\n// ---------------------------------------------------------------------------\nexport const Donut: FC<{\n data: Segment[];\n size?: number;\n thickness?: number;\n centerLabel?: string;\n centerSub?: string;\n className?: string;\n}> = ({ data, size = 160, thickness = 18, centerLabel, centerSub, className }) => {\n const total = data.reduce((s, d) => s + Math.max(0, d.value), 0);\n const r = (size - thickness) / 2;\n const c = 2 * Math.PI * r;\n const cx = size / 2;\n let offset = 0;\n const label = data.map((d) => `${d.label}: ${d.value}`).join(', ');\n\n return (\n <div className={cn('relative inline-flex items-center justify-center', className)}>\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n role=\"img\"\n aria-label={`Donut chart. ${label}`}\n className=\"max-w-full\"\n >\n <circle\n cx={cx}\n cy={cx}\n r={r}\n fill=\"none\"\n stroke={GRID}\n strokeWidth={thickness}\n opacity={0.4}\n />\n {total > 0 &&\n data.map((d, i) => {\n const frac = Math.max(0, d.value) / total;\n const len = frac * c;\n const seg = (\n <circle\n key={i}\n cx={cx}\n cy={cx}\n r={r}\n fill=\"none\"\n stroke={colorAt(i, d.color)}\n strokeWidth={thickness}\n strokeDasharray={`${len} ${c - len}`}\n strokeDashoffset={-offset}\n strokeLinecap=\"butt\"\n transform={`rotate(-90 ${cx} ${cx})`}\n />\n );\n offset += len;\n return seg;\n })}\n </svg>\n {(centerLabel || centerSub) && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center text-center\">\n {centerLabel && (\n <span className=\"text-xl font-bold text-text-primary tabular-nums leading-none\">\n {centerLabel}\n </span>\n )}\n {centerSub && <span className=\"mt-1 text-xs text-text-secondary\">{centerSub}</span>}\n </div>\n )}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Legend — pairs with Donut / charts.\n// ---------------------------------------------------------------------------\nexport const Legend: FC<{\n data: Segment[];\n valueFormat?: (n: number) => string;\n className?: string;\n}> = ({ data, valueFormat, className }) => (\n <ul className={cn('space-y-2', className)}>\n {data.map((d, i) => (\n <li key={i} className=\"flex items-center gap-2 text-sm\">\n <span\n className=\"h-2.5 w-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: colorAt(i, d.color) }}\n aria-hidden\n />\n <span className=\"flex-1 truncate text-text-secondary\">{d.label}</span>\n <span className=\"font-medium text-text-primary tabular-nums\">\n {valueFormat ? valueFormat(d.value) : d.value}\n </span>\n </li>\n ))}\n </ul>\n);\n\n// ---------------------------------------------------------------------------\n// BarList — horizontal labelled bars (e.g. spend by category).\n// ---------------------------------------------------------------------------\nexport const BarList: FC<{\n data: Segment[];\n valueFormat?: (n: number) => string;\n className?: string;\n}> = ({ data, valueFormat, className }) => {\n const max = Math.max(1, ...data.map((d) => d.value));\n return (\n <ul className={cn('space-y-3', className)} role=\"img\" aria-label=\"Bar chart\">\n {data.map((d, i) => (\n <li key={i}>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"truncate text-text-secondary\">{d.label}</span>\n <span className=\"font-medium text-text-primary tabular-nums\">\n {valueFormat ? valueFormat(d.value) : d.value}\n </span>\n </div>\n <div\n className=\"mt-1.5 h-2 w-full overflow-hidden rounded-full\"\n style={{ backgroundColor: GRID }}\n >\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${(d.value / max) * 100}%`, backgroundColor: colorAt(i, d.color) }}\n />\n </div>\n </li>\n ))}\n </ul>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Sparkline / area — small trend line.\n// ---------------------------------------------------------------------------\nexport const Sparkline: FC<{\n points: number[];\n width?: number;\n height?: number;\n positive?: boolean;\n className?: string;\n}> = ({ points, width = 220, height = 56, positive = true, className }) => {\n if (points.length < 2) return null;\n const max = Math.max(...points);\n const min = Math.min(...points);\n const span = max - min || 1;\n const stroke = positive ? POSITIVE : NEGATIVE;\n const step = width / (points.length - 1);\n const coords = points.map((p, i) => [i * step, height - ((p - min) / span) * (height - 8) - 4]);\n const line = coords\n .map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`)\n .join(' ');\n const area = `${line} L${width},${height} L0,${height} Z`;\n return (\n <svg\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label=\"Trend sparkline\"\n className={cn('max-w-full', className)}\n preserveAspectRatio=\"none\"\n >\n <path d={area} fill={stroke} opacity={0.12} />\n <path\n d={line}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={2}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Gauge — 0..max semicircle (e.g. health score).\n// ---------------------------------------------------------------------------\nexport const Gauge: FC<{\n value: number;\n max?: number;\n size?: number;\n label?: string;\n className?: string;\n}> = ({ value, max = 100, size = 120, label, className }) => {\n const pct = Math.max(0, Math.min(1, value / max));\n const r = size / 2 - 10;\n const cy = size / 2;\n const circ = Math.PI * r; // half circle\n const tone = pct >= 0.66 ? SUCCESS : pct >= 0.33 ? WARN : NEGATIVE;\n return (\n <div className={cn('inline-flex flex-col items-center', className)}>\n <svg\n width={size}\n height={size / 2 + 8}\n viewBox={`0 0 ${size} ${size / 2 + 8}`}\n role=\"img\"\n aria-label={`Gauge: ${Math.round(pct * 100)} percent`}\n className=\"max-w-full\"\n >\n <path\n d={`M10 ${cy} A ${r} ${r} 0 0 1 ${size - 10} ${cy}`}\n fill=\"none\"\n stroke={GRID}\n strokeWidth={10}\n strokeLinecap=\"round\"\n />\n <path\n d={`M10 ${cy} A ${r} ${r} 0 0 1 ${size - 10} ${cy}`}\n fill=\"none\"\n stroke={tone}\n strokeWidth={10}\n strokeLinecap=\"round\"\n strokeDasharray={`${pct * circ} ${circ}`}\n />\n </svg>\n <div className=\"-mt-4 text-center\">\n <span className=\"text-lg font-bold text-text-primary tabular-nums\">\n {Math.round(value)}\n </span>\n {label && <p className=\"text-xs text-text-secondary\">{label}</p>}\n </div>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Timeline — vertical events with a connector rail (e.g. renewals).\n// ---------------------------------------------------------------------------\nexport interface TimelineItem {\n title: string;\n sub?: string;\n meta?: ReactNode;\n tone?: 'default' | 'positive' | 'warning' | 'muted';\n}\nconst dotTone: Record<NonNullable<TimelineItem['tone']>, string> = {\n default: 'var(--color-accent-indigo)',\n positive: SUCCESS,\n warning: WARN,\n muted: 'var(--color-text-secondary)',\n};\nexport const Timeline: FC<{ items: TimelineItem[]; className?: string }> = ({\n items,\n className,\n}) => (\n <ol className={cn('relative space-y-5 pl-6', className)}>\n <span className=\"absolute left-[7px] top-1 bottom-1 w-px bg-border-subtle\" aria-hidden />\n {items.map((it, i) => (\n <li key={i} className=\"relative\">\n <span\n className=\"absolute -left-[22px] top-1 h-3 w-3 rounded-full ring-4 ring-bg-surface\"\n style={{ backgroundColor: dotTone[it.tone ?? 'default'] }}\n aria-hidden\n />\n <div className=\"flex items-baseline justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">{it.title}</p>\n {it.meta && <span className=\"text-sm tabular-nums text-text-primary\">{it.meta}</span>}\n </div>\n {it.sub && <p className=\"text-xs text-text-secondary\">{it.sub}</p>}\n </li>\n ))}\n </ol>\n);\n\n// ---------------------------------------------------------------------------\n// MiniProgress — inline utilization bar (e.g. seats used).\n// ---------------------------------------------------------------------------\nexport const MiniProgress: FC<{\n value: number;\n max?: number;\n tone?: 'accent' | 'positive' | 'warning' | 'negative';\n className?: string;\n}> = ({ value, max = 100, tone = 'accent', className }) => {\n const pct = Math.max(0, Math.min(1, max ? value / max : 0));\n const color =\n tone === 'positive'\n ? SUCCESS\n : tone === 'warning'\n ? WARN\n : tone === 'negative'\n ? NEGATIVE\n : 'var(--color-accent-indigo)';\n return (\n <div\n className={cn('h-2 w-full overflow-hidden rounded-full', className)}\n style={{ backgroundColor: GRID }}\n role=\"progressbar\"\n aria-valuenow={Math.round(pct * 100)}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${pct * 100}%`, backgroundColor: color }}\n />\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"viz.js","names":[],"sources":["../../../src/subscriberbot/components/viz.tsx"],"sourcesContent":["/**\n * Tokenized, responsive SVG visualization primitives.\n * @module subscriberbot/components/viz\n *\n * Every color is a fe-libs semantic CSS variable (never a raw hex), so charts\n * theme automatically in light/dark and per-product themes. All charts scale to\n * their container (SVG viewBox) and carry an accessible role/label.\n */\nimport type { FC, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\n\n/** Categorical palette — fe-libs chart tokens. */\nexport const CHART_COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n 'var(--color-chart-6)',\n 'var(--color-chart-7)',\n 'var(--color-chart-8)',\n] as const;\n\nconst POSITIVE = 'var(--color-chart-positive)';\nconst NEGATIVE = 'var(--color-chart-negative)';\nconst GRID = 'var(--color-chart-grid)';\nconst WARN = 'var(--color-status-warning-text)';\nconst SUCCESS = 'var(--color-status-success-text)';\n\nexport interface Segment {\n label: string;\n value: number;\n color?: string;\n}\n\nconst colorAt = (i: number, override?: string) => override ?? CHART_COLORS[i % CHART_COLORS.length];\n\n// ---------------------------------------------------------------------------\n// Donut — proportional ring with an optional center label.\n// ---------------------------------------------------------------------------\nexport const Donut: FC<{\n data: Segment[];\n size?: number;\n thickness?: number;\n centerLabel?: string;\n centerSub?: string;\n className?: string;\n}> = ({ data, size = 160, thickness = 18, centerLabel, centerSub, className }) => {\n const total = data.reduce((s, d) => s + Math.max(0, d.value), 0);\n const r = (size - thickness) / 2;\n const c = 2 * Math.PI * r;\n const cx = size / 2;\n let offset = 0;\n const label = data.map((d) => `${d.label}: ${d.value}`).join(', ');\n\n return (\n <div className={cn('relative inline-flex items-center justify-center', className)}>\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n role=\"img\"\n aria-label={`Donut chart. ${label}`}\n className=\"max-w-full\"\n >\n <circle\n cx={cx}\n cy={cx}\n r={r}\n fill=\"none\"\n stroke={GRID}\n strokeWidth={thickness}\n opacity={0.4}\n />\n {total > 0 &&\n data.map((d, i) => {\n const frac = Math.max(0, d.value) / total;\n const len = frac * c;\n const seg = (\n <circle\n key={i}\n cx={cx}\n cy={cx}\n r={r}\n fill=\"none\"\n stroke={colorAt(i, d.color)}\n strokeWidth={thickness}\n strokeDasharray={`${len} ${c - len}`}\n strokeDashoffset={-offset}\n strokeLinecap=\"butt\"\n transform={`rotate(-90 ${cx} ${cx})`}\n />\n );\n offset += len;\n return seg;\n })}\n </svg>\n {(centerLabel || centerSub) && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center text-center\">\n {centerLabel && (\n <span className=\"text-xl font-bold text-text-primary tabular-nums leading-none\">\n {centerLabel}\n </span>\n )}\n {centerSub && <span className=\"mt-1 text-xs text-text-secondary\">{centerSub}</span>}\n </div>\n )}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Legend — pairs with Donut / charts.\n// ---------------------------------------------------------------------------\nexport const Legend: FC<{\n data: Segment[];\n valueFormat?: (n: number) => string;\n className?: string;\n}> = ({ data, valueFormat, className }) => (\n <ul className={cn('space-y-2', className)}>\n {data.map((d, i) => (\n <li key={i} className=\"flex items-center gap-2 text-sm\">\n <span\n className=\"h-2.5 w-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: colorAt(i, d.color) }}\n aria-hidden\n />\n <span className=\"flex-1 truncate text-text-secondary\">{d.label}</span>\n <span className=\"font-medium text-text-primary tabular-nums\">\n {valueFormat ? valueFormat(d.value) : d.value}\n </span>\n </li>\n ))}\n </ul>\n);\n\n// ---------------------------------------------------------------------------\n// BarList — horizontal labelled bars (e.g. spend by category).\n// ---------------------------------------------------------------------------\nexport const BarList: FC<{\n data: Segment[];\n valueFormat?: (n: number) => string;\n className?: string;\n}> = ({ data, valueFormat, className }) => {\n const max = Math.max(1, ...data.map((d) => d.value));\n return (\n <ul className={cn('space-y-3', className)} role=\"img\" aria-label=\"Bar chart\">\n {data.map((d, i) => (\n <li key={i}>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"truncate text-text-secondary\">{d.label}</span>\n <span className=\"font-medium text-text-primary tabular-nums\">\n {valueFormat ? valueFormat(d.value) : d.value}\n </span>\n </div>\n <div\n className=\"mt-1.5 h-2 w-full overflow-hidden rounded-full\"\n style={{ backgroundColor: GRID }}\n >\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${(d.value / max) * 100}%`, backgroundColor: colorAt(i, d.color) }}\n />\n </div>\n </li>\n ))}\n </ul>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Sparkline / area — small trend line.\n// ---------------------------------------------------------------------------\nexport const Sparkline: FC<{\n points: number[];\n width?: number;\n height?: number;\n positive?: boolean;\n className?: string;\n}> = ({ points, width = 220, height = 56, positive = true, className }) => {\n if (points.length < 2) return null;\n const max = Math.max(...points);\n const min = Math.min(...points);\n const span = max - min || 1;\n const stroke = positive ? POSITIVE : NEGATIVE;\n const step = width / (points.length - 1);\n const coords = points.map((p, i) => [i * step, height - ((p - min) / span) * (height - 8) - 4]);\n const line = coords\n .map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`)\n .join(' ');\n const area = `${line} L${width},${height} L0,${height} Z`;\n return (\n <svg\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label=\"Trend sparkline\"\n className={cn('max-w-full', className)}\n preserveAspectRatio=\"none\"\n >\n <path d={area} fill={stroke} opacity={0.12} />\n <path\n d={line}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={2}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Gauge — 0..max semicircle (e.g. health score).\n// ---------------------------------------------------------------------------\nexport const Gauge: FC<{\n value: number;\n max?: number;\n size?: number;\n label?: string;\n className?: string;\n}> = ({ value, max = 100, size = 120, label, className }) => {\n const pct = Math.max(0, Math.min(1, value / max));\n const r = size / 2 - 10;\n const cy = size / 2;\n const circ = Math.PI * r; // half circle\n const tone = pct >= 0.66 ? SUCCESS : pct >= 0.33 ? WARN : NEGATIVE;\n return (\n <div className={cn('inline-flex flex-col items-center', className)}>\n <svg\n width={size}\n height={size / 2 + 8}\n viewBox={`0 0 ${size} ${size / 2 + 8}`}\n role=\"img\"\n aria-label={`Gauge: ${Math.round(pct * 100)} percent`}\n className=\"max-w-full\"\n >\n <path\n d={`M10 ${cy} A ${r} ${r} 0 0 1 ${size - 10} ${cy}`}\n fill=\"none\"\n stroke={GRID}\n strokeWidth={10}\n strokeLinecap=\"round\"\n />\n <path\n d={`M10 ${cy} A ${r} ${r} 0 0 1 ${size - 10} ${cy}`}\n fill=\"none\"\n stroke={tone}\n strokeWidth={10}\n strokeLinecap=\"round\"\n strokeDasharray={`${pct * circ} ${circ}`}\n />\n </svg>\n <div className=\"-mt-4 text-center\">\n <span className=\"text-lg font-bold text-text-primary tabular-nums\">\n {Math.round(value)}\n </span>\n {label && <p className=\"text-xs text-text-secondary\">{label}</p>}\n </div>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Timeline — vertical events with a connector rail (e.g. renewals).\n// ---------------------------------------------------------------------------\nexport interface TimelineItem {\n title: string;\n sub?: string;\n meta?: ReactNode;\n tone?: 'default' | 'positive' | 'warning' | 'muted';\n}\nconst dotTone: Record<NonNullable<TimelineItem['tone']>, string> = {\n default: 'var(--color-accent-indigo)',\n positive: SUCCESS,\n warning: WARN,\n muted: 'var(--color-text-secondary)',\n};\nexport const Timeline: FC<{ items: TimelineItem[]; className?: string }> = ({\n items,\n className,\n}) => (\n <ol className={cn('relative space-y-5 pl-6', className)}>\n <span className=\"absolute left-[7px] top-1 bottom-1 w-px bg-border-subtle\" aria-hidden />\n {items.map((it, i) => (\n <li key={i} className=\"relative\">\n <span\n className=\"absolute -left-[22px] top-1 h-3 w-3 rounded-full ring-4 ring-bg-surface\"\n style={{ backgroundColor: dotTone[it.tone ?? 'default'] }}\n aria-hidden\n />\n <div className=\"flex items-baseline justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">{it.title}</p>\n {it.meta && <span className=\"text-sm tabular-nums text-text-primary\">{it.meta}</span>}\n </div>\n {it.sub && <p className=\"text-xs text-text-secondary\">{it.sub}</p>}\n </li>\n ))}\n </ol>\n);\n\n// ---------------------------------------------------------------------------\n// MiniProgress — inline utilization bar (e.g. seats used).\n// ---------------------------------------------------------------------------\nexport const MiniProgress: FC<{\n value: number;\n max?: number;\n tone?: 'accent' | 'positive' | 'warning' | 'negative';\n className?: string;\n}> = ({ value, max = 100, tone = 'accent', className }) => {\n const pct = Math.max(0, Math.min(1, max ? value / max : 0));\n const color =\n tone === 'positive'\n ? SUCCESS\n : tone === 'warning'\n ? WARN\n : tone === 'negative'\n ? NEGATIVE\n : 'var(--color-accent-indigo)';\n return (\n <div\n className={cn('h-2 w-full overflow-hidden rounded-full', className)}\n style={{ backgroundColor: GRID }}\n role=\"progressbar\"\n aria-valuenow={Math.round(pct * 100)}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${pct * 100}%`, backgroundColor: color }}\n />\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { joinPath as e } from "../utils/navigation.js";
|
|
2
2
|
import { createContext as t, useCallback as n, useContext as r, useMemo as i } from "react";
|
|
3
|
-
import { MemoryRouter as a, useNavigate as o } from "react-router
|
|
3
|
+
import { MemoryRouter as a, useNavigate as o } from "react-router";
|
|
4
4
|
import { jsx as s } from "react/jsx-runtime";
|
|
5
5
|
//#region src/subscriberbot/context/SubscriberBotContext.tsx
|
|
6
6
|
var c = t(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriberBotContext.js","names":[],"sources":["../../../src/subscriberbot/context/SubscriberBotContext.tsx"],"sourcesContent":["/**\n * SubscriberBot Context Provider\n * @module subscriberbot/context\n */\n\nimport type { FC, PropsWithChildren } from 'react';\nimport { createContext, useContext, useMemo, useCallback } from 'react';\nimport { MemoryRouter, useNavigate as useRouterNavigate } from 'react-router
|
|
1
|
+
{"version":3,"file":"SubscriberBotContext.js","names":[],"sources":["../../../src/subscriberbot/context/SubscriberBotContext.tsx"],"sourcesContent":["/**\n * SubscriberBot Context Provider\n * @module subscriberbot/context\n */\n\nimport type { FC, PropsWithChildren } from 'react';\nimport { createContext, useContext, useMemo, useCallback } from 'react';\nimport { MemoryRouter, useNavigate as useRouterNavigate } from 'react-router';\nimport type { SubscriberBotRootProps } from '../types';\nimport { joinPath } from '../utils/navigation';\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface SubscriberBotContextValue extends Omit<\n SubscriberBotRootProps,\n 'registerNavItems' | 'registerFooterItems' | 'navigate'\n> {\n isStandalone: boolean;\n /** Shell's navigate function (only available in integrated mode) */\n navigate?: (path: string) => void;\n /** Navigate to a path relative to basePath */\n navigateTo: (relativePath: string) => void;\n /** Get the full path for a relative path */\n getPath: (relativePath: string) => string;\n}\n\nconst SubscriberBotContext = createContext<SubscriberBotContextValue | null>(null);\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useSubscriberBot(): SubscriberBotContextValue {\n const context = useContext(SubscriberBotContext);\n if (!context) {\n throw new Error('useSubscriberBot must be used within a SubscriberBotProvider');\n }\n return context;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\ntype ProviderProps = Omit<SubscriberBotRootProps, 'registerNavItems' | 'registerFooterItems'> & {\n isStandalone: boolean;\n};\n\n/** Provider for standalone mode (has access to MemoryRouter) */\nconst StandaloneProviderInner: FC<PropsWithChildren<ProviderProps>> = ({\n children,\n basePath,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n}) => {\n const routerNavigate = useRouterNavigate();\n const effectiveBasePath = basePath || '/';\n\n const getPath = useCallback(\n (relativePath: string) => joinPath(effectiveBasePath, relativePath),\n [effectiveBasePath]\n );\n\n const navigateTo = useCallback(\n (relativePath: string) => {\n const fullPath = joinPath(effectiveBasePath, relativePath);\n routerNavigate(fullPath);\n },\n [effectiveBasePath, routerNavigate]\n );\n\n const contextValue = useMemo<SubscriberBotContextValue>(\n () => ({\n basePath: effectiveBasePath,\n navigate: undefined,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n isStandalone: true,\n navigateTo,\n getPath,\n }),\n [\n effectiveBasePath,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n navigateTo,\n getPath,\n ]\n );\n\n return (\n <SubscriberBotContext.Provider value={contextValue}>{children}</SubscriberBotContext.Provider>\n );\n};\n\n/** Provider for integrated mode (shell provides navigate) */\nconst IntegratedProviderInner: FC<\n PropsWithChildren<ProviderProps & { navigate: (path: string) => void }>\n> = ({\n children,\n basePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n}) => {\n const effectiveBasePath = basePath || '/';\n\n const getPath = useCallback(\n (relativePath: string) => joinPath(effectiveBasePath, relativePath),\n [effectiveBasePath]\n );\n\n const navigateTo = useCallback(\n (relativePath: string) => {\n const fullPath = joinPath(effectiveBasePath, relativePath);\n navigate(fullPath);\n },\n [effectiveBasePath, navigate]\n );\n\n const contextValue = useMemo<SubscriberBotContextValue>(\n () => ({\n basePath: effectiveBasePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n isStandalone: false,\n navigateTo,\n getPath,\n }),\n [\n effectiveBasePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n navigateTo,\n getPath,\n ]\n );\n\n return (\n <SubscriberBotContext.Provider value={contextValue}>{children}</SubscriberBotContext.Provider>\n );\n};\n\nexport const SubscriberBotProvider: FC<PropsWithChildren<SubscriberBotRootProps>> = (props) => {\n const { children, navigate } = props;\n // Standalone mode: no navigate function provided (MFE manages its own router)\n // Integrated mode: navigate function provided by shell (shell provides router)\n const isStandalone = !navigate;\n\n // Standalone mode: wrap in MemoryRouter\n if (isStandalone) {\n return (\n <MemoryRouter>\n <StandaloneProviderInner {...props} isStandalone={true}>\n {children}\n </StandaloneProviderInner>\n </MemoryRouter>\n );\n }\n\n // Integrated mode: shell provides router\n return (\n <IntegratedProviderInner {...props} navigate={navigate} isStandalone={false}>\n {children}\n </IntegratedProviderInner>\n );\n};\n"],"mappings":";;;;;AA4BA,IAAM,IAAuB,EAAgD,KAAK;AAMlF,SAAgB,IAA8C;CAC5D,IAAM,IAAU,EAAW,EAAqB;AAChD,KAAI,CAAC,EACH,OAAU,MAAM,+DAA+D;AAEjF,QAAO;;AAYT,IAAM,KAAiE,EACrE,aACA,aACA,gBACA,aACA,gBACA,kBACA,mBACI;CACJ,IAAM,IAAiB,GAAmB,EACpC,IAAoB,KAAY,KAEhC,IAAU,GACb,MAAyB,EAAS,GAAmB,EAAa,EACnE,CAAC,EAAkB,CACpB,EAEK,IAAa,GAChB,MAAyB;AAExB,IADiB,EAAS,GAAmB,EAAa,CAClC;IAE1B,CAAC,GAAmB,EAAe,CACpC,EAEK,IAAe,SACZ;EACL,UAAU;EACV,UAAU,KAAA;EACV;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QACE,kBAAC,EAAqB,UAAtB;EAA+B,OAAO;EAAe;EAAyC,CAAA;GAK5F,KAED,EACH,aACA,aACA,aACA,gBACA,aACA,gBACA,kBACA,mBACI;CACJ,IAAM,IAAoB,KAAY,KAEhC,IAAU,GACb,MAAyB,EAAS,GAAmB,EAAa,EACnE,CAAC,EAAkB,CACpB,EAEK,IAAa,GAChB,MAAyB;AAExB,IADiB,EAAS,GAAmB,EAAa,CACxC;IAEpB,CAAC,GAAmB,EAAS,CAC9B,EAEK,IAAe,SACZ;EACL,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QACE,kBAAC,EAAqB,UAAtB;EAA+B,OAAO;EAAe;EAAyC,CAAA;GAIrF,KAAwE,MAAU;CAC7F,IAAM,EAAE,aAAU,gBAAa;AAiB/B,QAdsB,IAepB,kBAAC,GAAD;EAAyB,GAAI;EAAiB;EAAU,cAAc;EACnE;EACuB,CAAA,GAZxB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EAAyB,GAAI;EAAO,cAAc;EAC/C;EACuB,CAAA,EACb,CAAA"}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* SubscriberBot hooks barrel
|
|
3
3
|
* @module subscriberbot/hooks
|
|
4
4
|
*/
|
|
5
|
-
export { useRelationships, useRelationship, useCreateRelationship, useUpdateRelationship, useTransitionRelationship, useCancelRelationship, useRenewalEvents, useEntitlements, useCreateEntitlement, useAssets, useCreateAsset, useUploadFile, useFileDownloadUrl, useProviders, useProvider, useCreateProvider, useUpdateProvider, useArchiveProvider, usePlans, useCreatePlan, useInboxMessages, useMarkMessageRead, useIngestMessage, useInvoices, useMarkInvoicePaid, useCreateInvoice, usePaymentInstruments, useCreatePaymentInstrument, useRemovePaymentInstrument, useChannels, useCreateChannel, useVerifyChannel, useAgents, useAgent, useCreateAgent, useSetAgentStatus, useCreatePolicy, useWorkflows, useCreateWorkflow, useActivateWorkflow, useAdapterSubmissions, useApproveAdapter, useRejectAdapter, useMarketplaceReports, useModerateListing, } from './useSubscriberBotApi';
|
|
5
|
+
export { useRelationships, useRelationship, useCreateRelationship, useUpdateRelationship, useTransitionRelationship, useCancelRelationship, useRenewalEvents, useEntitlements, useCreateEntitlement, useAssets, useCreateAsset, useUploadFile, useFileDownloadUrl, useProviders, useProvider, useCreateProvider, useUpdateProvider, useArchiveProvider, usePlans, useCreatePlan, useBenchmarkDataPoints, useInboxMessages, useMarkMessageRead, useIngestMessage, useInvoices, useMarkInvoicePaid, useCreateInvoice, usePaymentInstruments, useCreatePaymentInstrument, useRemovePaymentInstrument, useChannels, useCreateChannel, useVerifyChannel, useAgents, useAgent, useCreateAgent, useSetAgentStatus, useCreatePolicy, useWorkflows, useCreateWorkflow, useActivateWorkflow, useAdapterSubmissions, useApproveAdapter, useRejectAdapter, useMarketplaceReports, useModerateListing, } from './useSubscriberBotApi';
|
|
6
6
|
export type { RelationshipListFilters, ProviderListFilters, InboxListFilters, InvoiceListFilters, AgentListFilters, AdapterSubmissionListFilters, MarketplaceReportListFilters, } from './useSubscriberBotApi';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,EACb,kBAAkB,EAElB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,EACb,kBAAkB,EAElB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,sBAAsB,EAEtB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEhB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EAEnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PaginationInput, SubAdapterSubmission, SubAgentKind, SubAgentStatus, SubAiAgent, SubAsset, SubCommunicationChannel, SubConnection, SubCreateAgentInput, SubCreateAssetInput, SubCreateChannelInput, SubCreateEntitlementInput, SubCreateInvoiceInput, SubCreatePaymentInstrumentInput, SubCreatePlanInput, SubCreatePolicyInput, SubCreateProviderInput, SubCreateRelationshipInput, SubCreateWorkflowInput, SubEntitlement, SubInboxMessage, SubIngestMessageInput, SubInvoice, SubInvoiceStatus, SubMarketplaceReport, SubMessageCategory, SubModerationAction, SubPaymentInstrument, SubPlan, SubPolicy, SubProvider, SubProviderCategory, SubProviderStatus, SubRelationship, SubRelationshipKind, SubRelationshipStatus, SubRenewalEvent, SubReportStatus, SubSubmissionStatus, SubUpdateProviderInput, SubUpdateRelationshipInput, SubWorkflow, SubWorkflowStatus } from '../types';
|
|
1
|
+
import { PaginationInput, SubAdapterSubmission, SubAgentKind, SubAgentStatus, SubAiAgent, SubAsset, SubBenchmarkDataPoint, SubCommunicationChannel, SubConnection, SubCreateAgentInput, SubCreateAssetInput, SubCreateChannelInput, SubCreateEntitlementInput, SubCreateInvoiceInput, SubCreatePaymentInstrumentInput, SubCreatePlanInput, SubCreatePolicyInput, SubCreateProviderInput, SubCreateRelationshipInput, SubCreateWorkflowInput, SubEntitlement, SubInboxMessage, SubIngestMessageInput, SubInvoice, SubInvoiceStatus, SubMarketplaceReport, SubMessageCategory, SubModerationAction, SubPaymentInstrument, SubPlan, SubPolicy, SubProvider, SubProviderCategory, SubProviderStatus, SubRelationship, SubRelationshipKind, SubRelationshipStatus, SubRenewalEvent, SubReportStatus, SubSubmissionStatus, SubUpdateProviderInput, SubUpdateRelationshipInput, SubWorkflow, SubWorkflowStatus } from '../types';
|
|
2
2
|
|
|
3
3
|
export interface RelationshipListFilters {
|
|
4
4
|
kind?: SubRelationshipKind;
|
|
@@ -62,6 +62,17 @@ export declare const useUpdateProvider: () => import('@tanstack/react-query').Us
|
|
|
62
62
|
export declare const useArchiveProvider: () => import('@tanstack/react-query').UseMutationResult<boolean, Error, string, unknown>;
|
|
63
63
|
export declare const usePlans: (providerId: string | undefined) => import('@tanstack/react-query').UseQueryResult<NoInfer<SubPlan[]>, Error>;
|
|
64
64
|
export declare const useCreatePlan: () => import('@tanstack/react-query').UseMutationResult<SubPlan, Error, SubCreatePlanInput, unknown>;
|
|
65
|
+
/**
|
|
66
|
+
* Observed price points for one provider, newest first from the server.
|
|
67
|
+
*
|
|
68
|
+
* Backs the provider "Price history" card. The benchmark dataset is read
|
|
69
|
+
* GLOBALLY (`@rbac(..., public: true)` on the svc) — it is the same for every
|
|
70
|
+
* workspace — so nothing here is workspace scoped. Matching is by
|
|
71
|
+
* `providerSlug`, which is an exact match server-side; `providerName` is a
|
|
72
|
+
* fuzzy `contains` match and would risk attributing another vendor's prices to
|
|
73
|
+
* this provider, so the query stays disabled until a slug exists.
|
|
74
|
+
*/
|
|
75
|
+
export declare const useBenchmarkDataPoints: (providerSlug: string | null | undefined) => import('@tanstack/react-query').UseQueryResult<NoInfer<SubBenchmarkDataPoint[]>, Error>;
|
|
65
76
|
export interface InboxListFilters {
|
|
66
77
|
category?: SubMessageCategory;
|
|
67
78
|
channelId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSubscriberBotApi.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/useSubscriberBotApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,QAAQ,EACR,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,+BAA+B,EAC/B,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,WAAW,EACX,iBAAiB,EAClB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"useSubscriberBotApi.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/useSubscriberBotApi.ts"],"names":[],"mappings":"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"}
|