@burdenoff/microfe-adaptercloud 2026.706.2 → 2026.706.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.
Files changed (40) hide show
  1. package/dist/adaptercloud/AdapterCloudRoot.js +52 -44
  2. package/dist/adaptercloud/AdapterCloudRoot.js.map +1 -1
  3. package/dist/adaptercloud/AdapterCloudRoutes.js +18 -14
  4. package/dist/adaptercloud/AdapterCloudRoutes.js.map +1 -1
  5. package/dist/adaptercloud/components/ConfirmDialog.js.map +1 -1
  6. package/dist/adaptercloud/components/viz/BarChart.js +32 -0
  7. package/dist/adaptercloud/components/viz/BarChart.js.map +1 -0
  8. package/dist/adaptercloud/components/viz/Sparkline.js +50 -0
  9. package/dist/adaptercloud/components/viz/Sparkline.js.map +1 -0
  10. package/dist/adaptercloud/components/viz/StackedBar.js +1 -0
  11. package/dist/adaptercloud/components/viz/TopologyGraph.js +96 -0
  12. package/dist/adaptercloud/components/viz/TopologyGraph.js.map +1 -0
  13. package/dist/adaptercloud/components/viz/index.js +4 -0
  14. package/dist/adaptercloud/hooks/useAdapterCloudApi.js +22 -4
  15. package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -1
  16. package/dist/adaptercloud/pages/OverviewPage.js.map +1 -1
  17. package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js +176 -123
  18. package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js.map +1 -1
  19. package/dist/adaptercloud/pages/adapters/AdapterFormPage.js +261 -179
  20. package/dist/adaptercloud/pages/adapters/AdapterFormPage.js.map +1 -1
  21. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js.map +1 -1
  22. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js +158 -94
  23. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js.map +1 -1
  24. package/dist/adaptercloud/pages/costs/CostsPage.js +160 -111
  25. package/dist/adaptercloud/pages/costs/CostsPage.js.map +1 -1
  26. package/dist/adaptercloud/pages/drift/DriftListPage.js +163 -84
  27. package/dist/adaptercloud/pages/drift/DriftListPage.js.map +1 -1
  28. package/dist/adaptercloud/pages/policies/PoliciesListPage.js +177 -96
  29. package/dist/adaptercloud/pages/policies/PoliciesListPage.js.map +1 -1
  30. package/dist/adaptercloud/pages/resources/ResourceDetailPage.js +145 -131
  31. package/dist/adaptercloud/pages/resources/ResourceDetailPage.js.map +1 -1
  32. package/dist/adaptercloud/pages/resources/ResourcesListPage.js +10 -1
  33. package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -1
  34. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js +226 -165
  35. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js.map +1 -1
  36. package/dist/adaptercloud/pages/topology/TopologyPage.js +397 -0
  37. package/dist/adaptercloud/pages/topology/TopologyPage.js.map +1 -0
  38. package/dist/adaptercloud/pages/violations/ViolationsListPage.js +184 -131
  39. package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -1
  40. package/package.json +1 -1
@@ -4,11 +4,11 @@ import { AdapterCloudRoutes as n } from "./AdapterCloudRoutes.js";
4
4
  import { useCallback as r, useEffect as i } from "react";
5
5
  import { MutationCache as a, QueryClient as o, QueryClientProvider as s } from "@tanstack/react-query";
6
6
  import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
- import { Activity as l, Boxes as u, Cable as d, DollarSign as f, GitCompareArrows as p, LayoutDashboard as m, ScrollText as h, Server as g, ShieldAlert as _ } from "lucide-react";
8
- import { jsx as v } from "react/jsx-runtime";
9
- import { FeatureFlagProvider as y } from "@burdenoff/fe-libs/shared/feature-flags";
7
+ import { Activity as l, Boxes as u, Cable as d, DollarSign as f, GitCompareArrows as p, LayoutDashboard as m, ScrollText as h, Server as g, ShieldAlert as _, Waypoints as v } from "lucide-react";
8
+ import { jsx as y } from "react/jsx-runtime";
9
+ import { FeatureFlagProvider as b } from "@burdenoff/fe-libs/shared/feature-flags";
10
10
  //#region src/adaptercloud/AdapterCloudRoot.tsx
11
- var b = new o({
11
+ var x = new o({
12
12
  mutationCache: new a({ onError: (e) => {
13
13
  t.error("Something went wrong", e instanceof Error ? e.message : "Please try again.");
14
14
  } }),
@@ -16,112 +16,120 @@ var b = new o({
16
16
  staleTime: 300 * 1e3,
17
17
  retry: 1
18
18
  } }
19
- }), x = (t) => {
20
- let { registerNavItems: a, registerFooterItems: o, basePath: x = "/" } = t, { t: S } = c(), C = r((e, t) => {
21
- let n = S(e);
19
+ }), S = (t) => {
20
+ let { registerNavItems: a, registerFooterItems: o, basePath: S = "/" } = t, { t: C } = c(), w = r((e, t) => {
21
+ let n = C(e);
22
22
  return n === e ? t : n;
23
- }, [S]), w = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
23
+ }, [C]), T = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
24
24
  return i(() => {
25
25
  if (a) return a([
26
26
  {
27
27
  id: "adaptercloud-overview",
28
- label: C("adaptercloud.nav.overview", "Overview"),
29
- path: w(x, ""),
30
- icon: /* @__PURE__ */ v(m, { size: 20 }),
28
+ label: w("adaptercloud.nav.overview", "Overview"),
29
+ path: T(S, ""),
30
+ icon: /* @__PURE__ */ y(m, { size: 20 }),
31
31
  order: 1,
32
32
  group: "main"
33
33
  },
34
34
  {
35
35
  id: "adaptercloud-adapters",
36
- label: C("adaptercloud.nav.adapters", "Adapters"),
37
- path: w(x, "adapters"),
38
- icon: /* @__PURE__ */ v(u, { size: 20 }),
36
+ label: w("adaptercloud.nav.adapters", "Adapters"),
37
+ path: T(S, "adapters"),
38
+ icon: /* @__PURE__ */ y(u, { size: 20 }),
39
39
  order: 10,
40
40
  group: "fabric"
41
41
  },
42
42
  {
43
43
  id: "adaptercloud-connections",
44
- label: C("adaptercloud.nav.connections", "Connections"),
45
- path: w(x, "connections"),
46
- icon: /* @__PURE__ */ v(d, { size: 20 }),
44
+ label: w("adaptercloud.nav.connections", "Connections"),
45
+ path: T(S, "connections"),
46
+ icon: /* @__PURE__ */ y(d, { size: 20 }),
47
47
  order: 11,
48
48
  group: "fabric"
49
49
  },
50
50
  {
51
51
  id: "adaptercloud-resources",
52
- label: C("adaptercloud.nav.resources", "Resources"),
53
- path: w(x, "resources"),
54
- icon: /* @__PURE__ */ v(g, { size: 20 }),
52
+ label: w("adaptercloud.nav.resources", "Resources"),
53
+ path: T(S, "resources"),
54
+ icon: /* @__PURE__ */ y(g, { size: 20 }),
55
55
  order: 12,
56
56
  group: "fabric"
57
57
  },
58
+ {
59
+ id: "adaptercloud-topology",
60
+ label: w("adaptercloud.nav.topology", "Topology"),
61
+ path: T(S, "topology"),
62
+ icon: /* @__PURE__ */ y(v, { size: 20 }),
63
+ order: 13,
64
+ group: "fabric"
65
+ },
58
66
  {
59
67
  id: "adaptercloud-policies",
60
- label: C("adaptercloud.nav.policies", "Policies"),
61
- path: w(x, "policies"),
62
- icon: /* @__PURE__ */ v(h, { size: 20 }),
68
+ label: w("adaptercloud.nav.policies", "Policies"),
69
+ path: T(S, "policies"),
70
+ icon: /* @__PURE__ */ y(h, { size: 20 }),
63
71
  order: 20,
64
72
  group: "governance"
65
73
  },
66
74
  {
67
75
  id: "adaptercloud-violations",
68
- label: C("adaptercloud.nav.violations", "Violations"),
69
- path: w(x, "violations"),
70
- icon: /* @__PURE__ */ v(_, { size: 20 }),
76
+ label: w("adaptercloud.nav.violations", "Violations"),
77
+ path: T(S, "violations"),
78
+ icon: /* @__PURE__ */ y(_, { size: 20 }),
71
79
  order: 21,
72
80
  group: "governance"
73
81
  },
74
82
  {
75
83
  id: "adaptercloud-drift",
76
- label: C("adaptercloud.nav.drift", "Drift"),
77
- path: w(x, "drift"),
78
- icon: /* @__PURE__ */ v(p, { size: 20 }),
84
+ label: w("adaptercloud.nav.drift", "Drift"),
85
+ path: T(S, "drift"),
86
+ icon: /* @__PURE__ */ y(p, { size: 20 }),
79
87
  order: 22,
80
88
  group: "governance"
81
89
  },
82
90
  {
83
91
  id: "adaptercloud-sync-runs",
84
- label: C("adaptercloud.nav.syncRuns", "Sync Runs"),
85
- path: w(x, "sync-runs"),
86
- icon: /* @__PURE__ */ v(l, { size: 20 }),
92
+ label: w("adaptercloud.nav.syncRuns", "Sync Runs"),
93
+ path: T(S, "sync-runs"),
94
+ icon: /* @__PURE__ */ y(l, { size: 20 }),
87
95
  order: 30,
88
96
  group: "operations"
89
97
  },
90
98
  {
91
99
  id: "adaptercloud-costs",
92
- label: C("adaptercloud.nav.finops", "FinOps"),
93
- path: w(x, "costs"),
94
- icon: /* @__PURE__ */ v(f, { size: 20 }),
100
+ label: w("adaptercloud.nav.finops", "FinOps"),
101
+ path: T(S, "costs"),
102
+ icon: /* @__PURE__ */ y(f, { size: 20 }),
95
103
  order: 31,
96
104
  group: "operations"
97
105
  }
98
106
  ]);
99
107
  }, [
100
108
  a,
101
- x,
102
- C
109
+ S,
110
+ w
103
111
  ]), i(() => {
104
112
  if (o) return o([{
105
113
  id: "adaptercloud-status",
106
- label: C("adaptercloud.footer.ready", "AdapterCloud Ready"),
114
+ label: w("adaptercloud.footer.ready", "AdapterCloud Ready"),
107
115
  type: "status",
108
116
  order: 10,
109
117
  section: "left"
110
118
  }]);
111
- }, [o, C]), /* @__PURE__ */ v(s, {
112
- client: b,
113
- children: /* @__PURE__ */ v(y, {
119
+ }, [o, w]), /* @__PURE__ */ y(s, {
120
+ client: x,
121
+ children: /* @__PURE__ */ y(b, {
114
122
  workspaceId: null,
115
123
  gateway: "global",
116
124
  defaultEnabled: !0,
117
- children: /* @__PURE__ */ v(e, {
125
+ children: /* @__PURE__ */ y(e, {
118
126
  ...t,
119
- children: /* @__PURE__ */ v(n, {})
127
+ children: /* @__PURE__ */ y(n, {})
120
128
  })
121
129
  })
122
130
  });
123
131
  };
124
132
  //#endregion
125
- export { x as AdapterCloudRoot };
133
+ export { S as AdapterCloudRoot };
126
134
 
127
135
  //# sourceMappingURL=AdapterCloudRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdapterCloudRoot.js","names":[],"sources":["../../src/adaptercloud/AdapterCloudRoot.tsx"],"sourcesContent":["/**\n * AdapterCloud Root Component\n * @module adaptercloud\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect } from 'react';\nimport { MutationCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n LayoutDashboard,\n Boxes,\n Cable,\n Server,\n ScrollText,\n ShieldAlert,\n GitCompareArrows,\n Activity,\n DollarSign,\n} from 'lucide-react';\nimport { AdapterCloudProvider } from './context/AdapterCloudContext';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { AdapterCloudRoutes } from './AdapterCloudRoutes';\nimport { notify } from './lib/toast';\nimport type { AdapterCloudRootProps, NavItem } from './types';\n\n// Create a query client for this microfrontend. A shared MutationCache surfaces\n// every failed write as a toast, so no mutation can fail silently with only\n// inline error state (the <Toaster> is owned by the host app shell).\nconst queryClient = new QueryClient({\n mutationCache: new MutationCache({\n onError: (error) => {\n notify.error(\n 'Something went wrong',\n error instanceof Error ? error.message : 'Please try again.'\n );\n },\n }),\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n },\n },\n});\n\nexport const AdapterCloudRoot: FC<AdapterCloudRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n // Helper to join paths correctly\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with shell on mount\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n // Overview\n {\n id: 'adaptercloud-overview',\n label: t('adaptercloud.nav.overview', 'Overview'),\n path: joinPath(basePath, ''),\n icon: <LayoutDashboard size={20} />,\n order: 1,\n group: 'main',\n },\n\n // Fabric\n {\n id: 'adaptercloud-adapters',\n label: t('adaptercloud.nav.adapters', 'Adapters'),\n path: joinPath(basePath, 'adapters'),\n icon: <Boxes size={20} />,\n order: 10,\n group: 'fabric',\n },\n {\n id: 'adaptercloud-connections',\n label: t('adaptercloud.nav.connections', 'Connections'),\n path: joinPath(basePath, 'connections'),\n icon: <Cable size={20} />,\n order: 11,\n group: 'fabric',\n },\n {\n id: 'adaptercloud-resources',\n label: t('adaptercloud.nav.resources', 'Resources'),\n path: joinPath(basePath, 'resources'),\n icon: <Server size={20} />,\n order: 12,\n group: 'fabric',\n },\n\n // Governance\n {\n id: 'adaptercloud-policies',\n label: t('adaptercloud.nav.policies', 'Policies'),\n path: joinPath(basePath, 'policies'),\n icon: <ScrollText size={20} />,\n order: 20,\n group: 'governance',\n },\n {\n id: 'adaptercloud-violations',\n label: t('adaptercloud.nav.violations', 'Violations'),\n path: joinPath(basePath, 'violations'),\n icon: <ShieldAlert size={20} />,\n order: 21,\n group: 'governance',\n },\n {\n id: 'adaptercloud-drift',\n label: t('adaptercloud.nav.drift', 'Drift'),\n path: joinPath(basePath, 'drift'),\n icon: <GitCompareArrows size={20} />,\n order: 22,\n group: 'governance',\n },\n\n // Operations\n {\n id: 'adaptercloud-sync-runs',\n label: t('adaptercloud.nav.syncRuns', 'Sync Runs'),\n path: joinPath(basePath, 'sync-runs'),\n icon: <Activity size={20} />,\n order: 30,\n group: 'operations',\n },\n {\n id: 'adaptercloud-costs',\n label: t('adaptercloud.nav.finops', 'FinOps'),\n path: joinPath(basePath, 'costs'),\n icon: <DollarSign size={20} />,\n order: 31,\n group: 'operations',\n },\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath, t]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'adaptercloud-status',\n label: t('adaptercloud.footer.ready', 'AdapterCloud Ready'),\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, t]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <AdapterCloudProvider {...props}>\n <AdapterCloudRoutes />\n </AdapterCloudProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdapterCloudRoot.js","names":[],"sources":["../../src/adaptercloud/AdapterCloudRoot.tsx"],"sourcesContent":["/**\n * AdapterCloud Root Component\n * @module adaptercloud\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect } from 'react';\nimport { MutationCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n LayoutDashboard,\n Boxes,\n Cable,\n Server,\n Waypoints,\n ScrollText,\n ShieldAlert,\n GitCompareArrows,\n Activity,\n DollarSign,\n} from 'lucide-react';\nimport { AdapterCloudProvider } from './context/AdapterCloudContext';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { AdapterCloudRoutes } from './AdapterCloudRoutes';\nimport { notify } from './lib/toast';\nimport type { AdapterCloudRootProps, NavItem } from './types';\n\n// Create a query client for this microfrontend. A shared MutationCache surfaces\n// every failed write as a toast, so no mutation can fail silently with only\n// inline error state (the <Toaster> is owned by the host app shell).\nconst queryClient = new QueryClient({\n mutationCache: new MutationCache({\n onError: (error) => {\n notify.error(\n 'Something went wrong',\n error instanceof Error ? error.message : 'Please try again.'\n );\n },\n }),\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n },\n },\n});\n\nexport const AdapterCloudRoot: FC<AdapterCloudRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n // Helper to join paths correctly\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with shell on mount\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n // Overview\n {\n id: 'adaptercloud-overview',\n label: t('adaptercloud.nav.overview', 'Overview'),\n path: joinPath(basePath, ''),\n icon: <LayoutDashboard size={20} />,\n order: 1,\n group: 'main',\n },\n\n // Fabric\n {\n id: 'adaptercloud-adapters',\n label: t('adaptercloud.nav.adapters', 'Adapters'),\n path: joinPath(basePath, 'adapters'),\n icon: <Boxes size={20} />,\n order: 10,\n group: 'fabric',\n },\n {\n id: 'adaptercloud-connections',\n label: t('adaptercloud.nav.connections', 'Connections'),\n path: joinPath(basePath, 'connections'),\n icon: <Cable size={20} />,\n order: 11,\n group: 'fabric',\n },\n {\n id: 'adaptercloud-resources',\n label: t('adaptercloud.nav.resources', 'Resources'),\n path: joinPath(basePath, 'resources'),\n icon: <Server size={20} />,\n order: 12,\n group: 'fabric',\n },\n {\n id: 'adaptercloud-topology',\n label: t('adaptercloud.nav.topology', 'Topology'),\n path: joinPath(basePath, 'topology'),\n icon: <Waypoints size={20} />,\n order: 13,\n group: 'fabric',\n },\n\n // Governance\n {\n id: 'adaptercloud-policies',\n label: t('adaptercloud.nav.policies', 'Policies'),\n path: joinPath(basePath, 'policies'),\n icon: <ScrollText size={20} />,\n order: 20,\n group: 'governance',\n },\n {\n id: 'adaptercloud-violations',\n label: t('adaptercloud.nav.violations', 'Violations'),\n path: joinPath(basePath, 'violations'),\n icon: <ShieldAlert size={20} />,\n order: 21,\n group: 'governance',\n },\n {\n id: 'adaptercloud-drift',\n label: t('adaptercloud.nav.drift', 'Drift'),\n path: joinPath(basePath, 'drift'),\n icon: <GitCompareArrows size={20} />,\n order: 22,\n group: 'governance',\n },\n\n // Operations\n {\n id: 'adaptercloud-sync-runs',\n label: t('adaptercloud.nav.syncRuns', 'Sync Runs'),\n path: joinPath(basePath, 'sync-runs'),\n icon: <Activity size={20} />,\n order: 30,\n group: 'operations',\n },\n {\n id: 'adaptercloud-costs',\n label: t('adaptercloud.nav.finops', 'FinOps'),\n path: joinPath(basePath, 'costs'),\n icon: <DollarSign size={20} />,\n order: 31,\n group: 'operations',\n },\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath, t]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'adaptercloud-status',\n label: t('adaptercloud.footer.ready', 'AdapterCloud Ready'),\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, t]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <AdapterCloudProvider {...props}>\n <AdapterCloudRoutes />\n </AdapterCloudProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n"],"mappings":"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"}
@@ -4,15 +4,15 @@ import { Suspense as n, lazy as r } from "react";
4
4
  import { Navigate as i, Route as a, Routes as o, useLocation as s } from "react-router-dom";
5
5
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
6
  //#region src/adaptercloud/AdapterCloudRoutes.tsx
7
- var u = r(() => import("./pages/adapters/AdaptersListPage.js").then((e) => ({ default: e.AdaptersListPage }))), d = r(() => import("./pages/adapters/AdapterDetailPage.js").then((e) => ({ default: e.AdapterDetailPage }))), f = r(() => import("./pages/adapters/AdapterFormPage.js").then((e) => ({ default: e.AdapterFormPage }))), p = r(() => import("./pages/connections/ConnectionsListPage.js").then((e) => ({ default: e.ConnectionsListPage }))), m = r(() => import("./pages/connections/ConnectionDetailPage.js").then((e) => ({ default: e.ConnectionDetailPage }))), h = r(() => import("./pages/connections/ConnectionFormPage.js").then((e) => ({ default: e.ConnectionFormPage }))), g = r(() => import("./pages/resources/ResourcesListPage.js").then((e) => ({ default: e.ResourcesListPage }))), _ = r(() => import("./pages/resources/ResourceDetailPage.js").then((e) => ({ default: e.ResourceDetailPage }))), v = r(() => import("./pages/policies/PoliciesListPage.js").then((e) => ({ default: e.PoliciesListPage }))), y = r(() => import("./pages/policies/PolicyDetailPage.js").then((e) => ({ default: e.PolicyDetailPage }))), b = r(() => import("./pages/policies/PolicyFormPage.js").then((e) => ({ default: e.PolicyFormPage }))), x = r(() => import("./pages/violations/ViolationsListPage.js").then((e) => ({ default: e.ViolationsListPage }))), S = r(() => import("./pages/drift/DriftListPage.js").then((e) => ({ default: e.DriftListPage }))), C = r(() => import("./pages/sync-runs/SyncRunsListPage.js").then((e) => ({ default: e.SyncRunsListPage }))), w = r(() => import("./pages/costs/CostsPage.js").then((e) => ({ default: e.CostsPage }))), T = () => /* @__PURE__ */ c("div", {
7
+ var u = r(() => import("./pages/adapters/AdaptersListPage.js").then((e) => ({ default: e.AdaptersListPage }))), d = r(() => import("./pages/adapters/AdapterDetailPage.js").then((e) => ({ default: e.AdapterDetailPage }))), f = r(() => import("./pages/adapters/AdapterFormPage.js").then((e) => ({ default: e.AdapterFormPage }))), p = r(() => import("./pages/connections/ConnectionsListPage.js").then((e) => ({ default: e.ConnectionsListPage }))), m = r(() => import("./pages/connections/ConnectionDetailPage.js").then((e) => ({ default: e.ConnectionDetailPage }))), h = r(() => import("./pages/connections/ConnectionFormPage.js").then((e) => ({ default: e.ConnectionFormPage }))), g = r(() => import("./pages/resources/ResourcesListPage.js").then((e) => ({ default: e.ResourcesListPage }))), _ = r(() => import("./pages/resources/ResourceDetailPage.js").then((e) => ({ default: e.ResourceDetailPage }))), v = r(() => import("./pages/topology/TopologyPage.js").then((e) => ({ default: e.TopologyPage }))), y = r(() => import("./pages/policies/PoliciesListPage.js").then((e) => ({ default: e.PoliciesListPage }))), b = r(() => import("./pages/policies/PolicyDetailPage.js").then((e) => ({ default: e.PolicyDetailPage }))), x = r(() => import("./pages/policies/PolicyFormPage.js").then((e) => ({ default: e.PolicyFormPage }))), S = r(() => import("./pages/violations/ViolationsListPage.js").then((e) => ({ default: e.ViolationsListPage }))), C = r(() => import("./pages/drift/DriftListPage.js").then((e) => ({ default: e.DriftListPage }))), w = r(() => import("./pages/sync-runs/SyncRunsListPage.js").then((e) => ({ default: e.SyncRunsListPage }))), T = r(() => import("./pages/costs/CostsPage.js").then((e) => ({ default: e.CostsPage }))), E = () => /* @__PURE__ */ c("div", {
8
8
  className: "flex min-h-[400px] items-center justify-center",
9
9
  children: /* @__PURE__ */ c("div", { className: "h-8 w-8 animate-spin rounded-full border-b-2 border-accent-blue" })
10
- }), E = () => {
11
- let { basePath: r, isStandalone: E } = e(), D = s(), O = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
12
- return O && !E && !(D.pathname === O || D.pathname.startsWith(O + "/")) ? null : /* @__PURE__ */ c("div", {
10
+ }), D = () => {
11
+ let { basePath: r, isStandalone: D } = e(), O = s(), k = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
12
+ return k && !D && !(O.pathname === k || O.pathname.startsWith(k + "/")) ? null : /* @__PURE__ */ c("div", {
13
13
  className: "flex min-h-full flex-col",
14
14
  children: /* @__PURE__ */ c(n, {
15
- fallback: /* @__PURE__ */ c(T, {}),
15
+ fallback: /* @__PURE__ */ c(E, {}),
16
16
  children: /* @__PURE__ */ l(o, { children: [
17
17
  /* @__PURE__ */ c(a, {
18
18
  index: !0,
@@ -59,36 +59,40 @@ var u = r(() => import("./pages/adapters/AdaptersListPage.js").then((e) => ({ de
59
59
  element: /* @__PURE__ */ c(_, {})
60
60
  }),
61
61
  /* @__PURE__ */ c(a, {
62
- path: "policies",
62
+ path: "topology",
63
63
  element: /* @__PURE__ */ c(v, {})
64
64
  }),
65
+ /* @__PURE__ */ c(a, {
66
+ path: "policies",
67
+ element: /* @__PURE__ */ c(y, {})
68
+ }),
65
69
  /* @__PURE__ */ c(a, {
66
70
  path: "policies/new",
67
- element: /* @__PURE__ */ c(b, {})
71
+ element: /* @__PURE__ */ c(x, {})
68
72
  }),
69
73
  /* @__PURE__ */ c(a, {
70
74
  path: "policies/:id",
71
- element: /* @__PURE__ */ c(y, {})
75
+ element: /* @__PURE__ */ c(b, {})
72
76
  }),
73
77
  /* @__PURE__ */ c(a, {
74
78
  path: "policies/:id/edit",
75
- element: /* @__PURE__ */ c(b, {})
79
+ element: /* @__PURE__ */ c(x, {})
76
80
  }),
77
81
  /* @__PURE__ */ c(a, {
78
82
  path: "violations",
79
- element: /* @__PURE__ */ c(x, {})
83
+ element: /* @__PURE__ */ c(S, {})
80
84
  }),
81
85
  /* @__PURE__ */ c(a, {
82
86
  path: "drift",
83
- element: /* @__PURE__ */ c(S, {})
87
+ element: /* @__PURE__ */ c(C, {})
84
88
  }),
85
89
  /* @__PURE__ */ c(a, {
86
90
  path: "sync-runs",
87
- element: /* @__PURE__ */ c(C, {})
91
+ element: /* @__PURE__ */ c(w, {})
88
92
  }),
89
93
  /* @__PURE__ */ c(a, {
90
94
  path: "costs",
91
- element: /* @__PURE__ */ c(w, {})
95
+ element: /* @__PURE__ */ c(T, {})
92
96
  }),
93
97
  /* @__PURE__ */ c(a, {
94
98
  path: "*",
@@ -102,6 +106,6 @@ var u = r(() => import("./pages/adapters/AdaptersListPage.js").then((e) => ({ de
102
106
  });
103
107
  };
104
108
  //#endregion
105
- export { E as AdapterCloudRoutes };
109
+ export { D as AdapterCloudRoutes };
106
110
 
107
111
  //# sourceMappingURL=AdapterCloudRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdapterCloudRoutes.js","names":[],"sources":["../../src/adaptercloud/AdapterCloudRoutes.tsx"],"sourcesContent":["/**\n * AdapterCloud Routes\n * @module adaptercloud\n *\n * Domain routing for the AdapterCloud (InfraVerse) control plane: an overview\n * landing page plus fabric (adapters / connections / resources), governance\n * (policies / violations / drift) and operations (sync runs / FinOps).\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router-dom';\nimport { useAdapterCloud } from './context/AdapterCloudContext';\n\n// Eager — overview landing page\nimport { OverviewPage } from './pages/OverviewPage';\n\n// Fabric — adapters\nconst AdaptersListPage = lazy(() =>\n import('./pages/adapters/AdaptersListPage').then((m) => ({ default: m.AdaptersListPage }))\n);\nconst AdapterDetailPage = lazy(() =>\n import('./pages/adapters/AdapterDetailPage').then((m) => ({ default: m.AdapterDetailPage }))\n);\nconst AdapterFormPage = lazy(() =>\n import('./pages/adapters/AdapterFormPage').then((m) => ({ default: m.AdapterFormPage }))\n);\n\n// Fabric — connections\nconst ConnectionsListPage = lazy(() =>\n import('./pages/connections/ConnectionsListPage').then((m) => ({\n default: m.ConnectionsListPage,\n }))\n);\nconst ConnectionDetailPage = lazy(() =>\n import('./pages/connections/ConnectionDetailPage').then((m) => ({\n default: m.ConnectionDetailPage,\n }))\n);\nconst ConnectionFormPage = lazy(() =>\n import('./pages/connections/ConnectionFormPage').then((m) => ({\n default: m.ConnectionFormPage,\n }))\n);\n\n// Fabric — resources\nconst ResourcesListPage = lazy(() =>\n import('./pages/resources/ResourcesListPage').then((m) => ({ default: m.ResourcesListPage }))\n);\nconst ResourceDetailPage = lazy(() =>\n import('./pages/resources/ResourceDetailPage').then((m) => ({ default: m.ResourceDetailPage }))\n);\n\n// Governance — policies\nconst PoliciesListPage = lazy(() =>\n import('./pages/policies/PoliciesListPage').then((m) => ({ default: m.PoliciesListPage }))\n);\nconst PolicyDetailPage = lazy(() =>\n import('./pages/policies/PolicyDetailPage').then((m) => ({ default: m.PolicyDetailPage }))\n);\nconst PolicyFormPage = lazy(() =>\n import('./pages/policies/PolicyFormPage').then((m) => ({ default: m.PolicyFormPage }))\n);\n\n// Governance — violations & drift\nconst ViolationsListPage = lazy(() =>\n import('./pages/violations/ViolationsListPage').then((m) => ({ default: m.ViolationsListPage }))\n);\nconst DriftListPage = lazy(() =>\n import('./pages/drift/DriftListPage').then((m) => ({ default: m.DriftListPage }))\n);\n\n// Operations — sync runs & costs\nconst SyncRunsListPage = lazy(() =>\n import('./pages/sync-runs/SyncRunsListPage').then((m) => ({ default: m.SyncRunsListPage }))\n);\nconst CostsPage = lazy(() =>\n import('./pages/costs/CostsPage').then((m) => ({ default: m.CostsPage }))\n);\n\n// Loading fallback component\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-b-2 border-accent-blue\" />\n </div>\n);\n\nexport const AdapterCloudRoutes: FC = () => {\n const { basePath, isStandalone } = useAdapterCloud();\n const location = useLocation();\n\n // Normalize base path\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: Only render if path matches basePath (when integrated)\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n\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 — eager loaded */}\n <Route index element={<OverviewPage />} />\n\n {/* Adapters */}\n <Route path=\"adapters\" element={<AdaptersListPage />} />\n <Route path=\"adapters/new\" element={<AdapterFormPage />} />\n <Route path=\"adapters/:id\" element={<AdapterDetailPage />} />\n <Route path=\"adapters/:id/edit\" element={<AdapterFormPage />} />\n\n {/* Connections */}\n <Route path=\"connections\" element={<ConnectionsListPage />} />\n <Route path=\"connections/new\" element={<ConnectionFormPage />} />\n <Route path=\"connections/:id\" element={<ConnectionDetailPage />} />\n <Route path=\"connections/:id/edit\" element={<ConnectionFormPage />} />\n\n {/* Resources */}\n <Route path=\"resources\" element={<ResourcesListPage />} />\n <Route path=\"resources/:id\" element={<ResourceDetailPage />} />\n\n {/* Policies */}\n <Route path=\"policies\" element={<PoliciesListPage />} />\n <Route path=\"policies/new\" element={<PolicyFormPage />} />\n <Route path=\"policies/:id\" element={<PolicyDetailPage />} />\n <Route path=\"policies/:id/edit\" element={<PolicyFormPage />} />\n\n {/* Governance */}\n <Route path=\"violations\" element={<ViolationsListPage />} />\n <Route path=\"drift\" element={<DriftListPage />} />\n\n {/* Operations */}\n <Route path=\"sync-runs\" element={<SyncRunsListPage />} />\n <Route path=\"costs\" element={<CostsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdapterCloudRoutes.js","names":[],"sources":["../../src/adaptercloud/AdapterCloudRoutes.tsx"],"sourcesContent":["/**\n * AdapterCloud Routes\n * @module adaptercloud\n *\n * Domain routing for the AdapterCloud (InfraVerse) control plane: an overview\n * landing page plus fabric (adapters / connections / resources), governance\n * (policies / violations / drift) and operations (sync runs / FinOps).\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router-dom';\nimport { useAdapterCloud } from './context/AdapterCloudContext';\n\n// Eager — overview landing page\nimport { OverviewPage } from './pages/OverviewPage';\n\n// Fabric — adapters\nconst AdaptersListPage = lazy(() =>\n import('./pages/adapters/AdaptersListPage').then((m) => ({ default: m.AdaptersListPage }))\n);\nconst AdapterDetailPage = lazy(() =>\n import('./pages/adapters/AdapterDetailPage').then((m) => ({ default: m.AdapterDetailPage }))\n);\nconst AdapterFormPage = lazy(() =>\n import('./pages/adapters/AdapterFormPage').then((m) => ({ default: m.AdapterFormPage }))\n);\n\n// Fabric — connections\nconst ConnectionsListPage = lazy(() =>\n import('./pages/connections/ConnectionsListPage').then((m) => ({\n default: m.ConnectionsListPage,\n }))\n);\nconst ConnectionDetailPage = lazy(() =>\n import('./pages/connections/ConnectionDetailPage').then((m) => ({\n default: m.ConnectionDetailPage,\n }))\n);\nconst ConnectionFormPage = lazy(() =>\n import('./pages/connections/ConnectionFormPage').then((m) => ({\n default: m.ConnectionFormPage,\n }))\n);\n\n// Fabric — resources\nconst ResourcesListPage = lazy(() =>\n import('./pages/resources/ResourcesListPage').then((m) => ({ default: m.ResourcesListPage }))\n);\nconst ResourceDetailPage = lazy(() =>\n import('./pages/resources/ResourceDetailPage').then((m) => ({ default: m.ResourceDetailPage }))\n);\n\n// Fabric — estate topology (dependency graph)\nconst TopologyPage = lazy(() =>\n import('./pages/topology/TopologyPage').then((m) => ({ default: m.TopologyPage }))\n);\n\n// Governance — policies\nconst PoliciesListPage = lazy(() =>\n import('./pages/policies/PoliciesListPage').then((m) => ({ default: m.PoliciesListPage }))\n);\nconst PolicyDetailPage = lazy(() =>\n import('./pages/policies/PolicyDetailPage').then((m) => ({ default: m.PolicyDetailPage }))\n);\nconst PolicyFormPage = lazy(() =>\n import('./pages/policies/PolicyFormPage').then((m) => ({ default: m.PolicyFormPage }))\n);\n\n// Governance — violations & drift\nconst ViolationsListPage = lazy(() =>\n import('./pages/violations/ViolationsListPage').then((m) => ({ default: m.ViolationsListPage }))\n);\nconst DriftListPage = lazy(() =>\n import('./pages/drift/DriftListPage').then((m) => ({ default: m.DriftListPage }))\n);\n\n// Operations — sync runs & costs\nconst SyncRunsListPage = lazy(() =>\n import('./pages/sync-runs/SyncRunsListPage').then((m) => ({ default: m.SyncRunsListPage }))\n);\nconst CostsPage = lazy(() =>\n import('./pages/costs/CostsPage').then((m) => ({ default: m.CostsPage }))\n);\n\n// Loading fallback component\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-b-2 border-accent-blue\" />\n </div>\n);\n\nexport const AdapterCloudRoutes: FC = () => {\n const { basePath, isStandalone } = useAdapterCloud();\n const location = useLocation();\n\n // Normalize base path\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: Only render if path matches basePath (when integrated)\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n\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 — eager loaded */}\n <Route index element={<OverviewPage />} />\n\n {/* Adapters */}\n <Route path=\"adapters\" element={<AdaptersListPage />} />\n <Route path=\"adapters/new\" element={<AdapterFormPage />} />\n <Route path=\"adapters/:id\" element={<AdapterDetailPage />} />\n <Route path=\"adapters/:id/edit\" element={<AdapterFormPage />} />\n\n {/* Connections */}\n <Route path=\"connections\" element={<ConnectionsListPage />} />\n <Route path=\"connections/new\" element={<ConnectionFormPage />} />\n <Route path=\"connections/:id\" element={<ConnectionDetailPage />} />\n <Route path=\"connections/:id/edit\" element={<ConnectionFormPage />} />\n\n {/* Resources */}\n <Route path=\"resources\" element={<ResourcesListPage />} />\n <Route path=\"resources/:id\" element={<ResourceDetailPage />} />\n\n {/* Fabric — estate topology graph */}\n <Route path=\"topology\" element={<TopologyPage />} />\n\n {/* Policies */}\n <Route path=\"policies\" element={<PoliciesListPage />} />\n <Route path=\"policies/new\" element={<PolicyFormPage />} />\n <Route path=\"policies/:id\" element={<PolicyDetailPage />} />\n <Route path=\"policies/:id/edit\" element={<PolicyFormPage />} />\n\n {/* Governance */}\n <Route path=\"violations\" element={<ViolationsListPage />} />\n <Route path=\"drift\" element={<DriftListPage />} />\n\n {/* Operations */}\n <Route path=\"sync-runs\" element={<SyncRunsListPage />} />\n <Route path=\"costs\" element={<CostsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/adaptercloud/components/ConfirmDialog.tsx"],"sourcesContent":["/**\n * ConfirmDialog Component\n * @module adaptercloud/components\n *\n * A consistent \"Are you sure?\" confirmation gate for destructive or\n * consequential actions (archive, disable, remediate, cancel). Built on the\n * shared fe-libs `ResponsiveDialog` primitive so it adapts to mobile as a sheet\n * and desktop as a modal. Cancel dismisses; Confirm invokes `onConfirm` and can\n * show a pending spinner while the mutation is in flight.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\n\ninterface ConfirmDialogProps {\n /** Controls visibility. */\n open: boolean;\n /** Called with `false` when the dialog should close (Cancel / overlay / esc). */\n onOpenChange: (open: boolean) => void;\n /** Dialog heading, e.g. \"Archive adapter?\". */\n title: string;\n /** Supporting body copy explaining the consequence. */\n description?: ReactNode;\n /** Confirm button label. Defaults to \"Confirm\". */\n confirmLabel: string;\n /** Cancel button label. Defaults to \"Cancel\". */\n cancelLabel: string;\n /** Invoked when the user confirms. */\n onConfirm: () => void;\n /** When true the confirm button spins and both buttons disable. */\n isPending?: boolean;\n /**\n * Visual tone of the confirm button. `danger` for destructive actions\n * (archive/disable/cancel), `primary` for neutral consequential ones.\n */\n tone?: 'danger' | 'primary';\n}\n\nexport const ConfirmDialog: FC<ConfirmDialogProps> = ({\n open,\n onOpenChange,\n title,\n description,\n confirmLabel,\n cancelLabel,\n onConfirm,\n isPending = false,\n tone = 'danger',\n}) => {\n const confirmClass =\n tone === 'danger'\n ? 'inline-flex items-center justify-center gap-2 rounded-lg bg-action-danger-bg px-4 py-2 text-sm font-medium text-action-danger-text transition-colors hover:bg-action-danger-bg-hover disabled:opacity-50'\n : 'inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50';\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onOpenChange(false);\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{title}</ResponsiveDialogTitle>\n {description && (\n <ResponsiveDialogDescription>{description}</ResponsiveDialogDescription>\n )}\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n disabled={isPending}\n onClick={() => onOpenChange(false)}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n {cancelLabel}\n </button>\n <button type=\"button\" disabled={isPending} onClick={onConfirm} className={confirmClass}>\n {isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {confirmLabel}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n};\n"],"mappings":";;;;AA8CA,IAAa,KAAyC,EACpD,SACA,iBACA,UACA,gBACA,iBACA,gBACA,cACA,eAAY,IACZ,UAAO,eAQL,kBAAC,GAAD;CACQ;CACN,eAAe,MAAS;AACtB,EAAK,KAAM,EAAa,GAAM;;WAGhC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAwB,GAA8B,CAAA,EACrD,KACC,kBAAC,GAAD,EAAA,UAA8B,GAA0C,CAAA,CAEnD,EAAA,CAAA,EACzB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,UAAD;EACE,MAAK;EACL,UAAU;EACV,eAAe,EAAa,GAAM;EAClC,WAAU;YAET;EACM,CAAA,EACT,kBAAC,UAAD;EAAQ,MAAK;EAAS,UAAU;EAAW,SAAS;EAAW,WA3BrE,MAAS,WACL,6MACA;YAyBE,CACG,KAAa,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,EACzD,EACM;IACc,EAAA,CAAA,CACD,EAAA,CAAA;CACT,CAAA"}
1
+ {"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/adaptercloud/components/ConfirmDialog.tsx"],"sourcesContent":["/**\n * ConfirmDialog Component\n * @module adaptercloud/components\n *\n * A consistent \"Are you sure?\" confirmation gate for destructive or\n * consequential actions (archive, disable, remediate, cancel). Built on the\n * shared fe-libs `ResponsiveDialog` primitive so it adapts to mobile as a sheet\n * and desktop as a modal. Cancel dismisses; Confirm invokes `onConfirm` and can\n * show a pending spinner while the mutation is in flight.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\n\ninterface ConfirmDialogProps {\n /** Controls visibility. */\n open: boolean;\n /** Called with `false` when the dialog should close (Cancel / overlay / esc). */\n onOpenChange: (open: boolean) => void;\n /** Dialog heading, e.g. \"Archive adapter?\". */\n title: string;\n /** Supporting body copy explaining the consequence. */\n description?: ReactNode;\n /** Confirm button label. Defaults to \"Confirm\". */\n confirmLabel: string;\n /** Cancel button label. Defaults to \"Cancel\". */\n cancelLabel: string;\n /** Invoked when the user confirms. */\n onConfirm: () => void;\n /** When true the confirm button spins and both buttons disable. */\n isPending?: boolean;\n /**\n * Visual tone of the confirm button. `danger` for destructive actions\n * (archive/disable/cancel), `primary` for neutral consequential ones.\n */\n tone?: 'danger' | 'primary';\n}\n\nexport const ConfirmDialog: FC<ConfirmDialogProps> = ({\n open,\n onOpenChange,\n title,\n description,\n confirmLabel,\n cancelLabel,\n onConfirm,\n isPending = false,\n tone = 'danger',\n}) => {\n const confirmClass =\n tone === 'danger'\n ? 'inline-flex items-center justify-center gap-2 rounded-lg bg-action-danger-bg px-4 py-2 text-sm font-medium text-action-danger-text transition-colors hover:bg-action-danger-bg-hover disabled:opacity-50'\n : 'inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50';\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onOpenChange(false);\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{title}</ResponsiveDialogTitle>\n {description && <ResponsiveDialogDescription>{description}</ResponsiveDialogDescription>}\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n disabled={isPending}\n onClick={() => onOpenChange(false)}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n {cancelLabel}\n </button>\n <button type=\"button\" disabled={isPending} onClick={onConfirm} className={confirmClass}>\n {isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {confirmLabel}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n};\n"],"mappings":";;;;AA8CA,IAAa,KAAyC,EACpD,SACA,iBACA,UACA,gBACA,iBACA,gBACA,cACA,eAAY,IACZ,UAAO,eAQL,kBAAC,GAAD;CACQ;CACN,eAAe,MAAS;AACtB,EAAK,KAAM,EAAa,GAAM;;WAGhC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAwB,GAA8B,CAAA,EACrD,KAAe,kBAAC,GAAD,EAAA,UAA8B,GAA0C,CAAA,CACjE,EAAA,CAAA,EACzB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,UAAD;EACE,MAAK;EACL,UAAU;EACV,eAAe,EAAa,GAAM;EAClC,WAAU;YAET;EACM,CAAA,EACT,kBAAC,UAAD;EAAQ,MAAK;EAAS,UAAU;EAAW,SAAS;EAAW,WAzBrE,MAAS,WACL,6MACA;YAuBE,CACG,KAAa,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,EACzD,EACM;IACc,EAAA,CAAA,CACD,EAAA,CAAA;CACT,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
+ //#region src/adaptercloud/components/viz/BarChart.tsx
3
+ var n = ({ data: n, barClassName: r = "bg-accent-blue", labelWidthClassName: i = "w-20 sm:w-24" }) => {
4
+ let a = Math.max(...n.map((e) => e.value), 1);
5
+ return /* @__PURE__ */ e("ul", {
6
+ className: "space-y-2.5",
7
+ children: n.map((n) => /* @__PURE__ */ t("li", {
8
+ className: "flex items-center gap-3",
9
+ children: [
10
+ /* @__PURE__ */ e("span", {
11
+ className: `${i} shrink-0 truncate text-xs text-text-secondary`,
12
+ children: n.label
13
+ }),
14
+ /* @__PURE__ */ e("div", {
15
+ className: "h-2.5 flex-1 overflow-hidden rounded-full bg-bg-sunken",
16
+ children: /* @__PURE__ */ e("div", {
17
+ className: `h-full rounded-full ${r} transition-[width] duration-500`,
18
+ style: { width: `${Math.max(2, n.value / a * 100)}%` }
19
+ })
20
+ }),
21
+ /* @__PURE__ */ e("span", {
22
+ className: "shrink-0 text-xs font-semibold tabular-nums text-text-primary",
23
+ children: n.display
24
+ })
25
+ ]
26
+ }, n.key))
27
+ });
28
+ };
29
+ //#endregion
30
+ export { n as BarChart };
31
+
32
+ //# sourceMappingURL=BarChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BarChart.js","names":[],"sources":["../../../../src/adaptercloud/components/viz/BarChart.tsx"],"sourcesContent":["/**\n * BarChart — a compact horizontal bar list (label · bar · value). Tokenized,\n * responsive, no raw colors. Used for breakdowns like cost-by-service.\n */\nimport type { FC } from 'react';\n\nexport interface BarDatum {\n key: string;\n label: string;\n value: number;\n /** Preformatted value shown on the right (e.g. \"$22,400\"). */\n display: string;\n}\n\ninterface BarChartProps {\n data: BarDatum[];\n /** Semantic-token fill class for the bar (default accent-blue). */\n barClassName?: string;\n labelWidthClassName?: string;\n}\n\nexport const BarChart: FC<BarChartProps> = ({\n data,\n barClassName = 'bg-accent-blue',\n labelWidthClassName = 'w-20 sm:w-24',\n}) => {\n const max = Math.max(...data.map((d) => d.value), 1);\n\n return (\n <ul className=\"space-y-2.5\">\n {data.map((d) => (\n <li key={d.key} className=\"flex items-center gap-3\">\n <span className={`${labelWidthClassName} shrink-0 truncate text-xs text-text-secondary`}>\n {d.label}\n </span>\n <div className=\"h-2.5 flex-1 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className={`h-full rounded-full ${barClassName} transition-[width] duration-500`}\n style={{ width: `${Math.max(2, (d.value / max) * 100)}%` }}\n />\n </div>\n <span className=\"shrink-0 text-xs font-semibold tabular-nums text-text-primary\">\n {d.display}\n </span>\n </li>\n ))}\n </ul>\n );\n};\n"],"mappings":";;AAqBA,IAAa,KAA+B,EAC1C,SACA,kBAAe,kBACf,yBAAsB,qBAClB;CACJ,IAAM,IAAM,KAAK,IAAI,GAAG,EAAK,KAAK,MAAM,EAAE,MAAM,EAAE,EAAE;AAEpD,QACE,kBAAC,MAAD;EAAI,WAAU;YACX,EAAK,KAAK,MACT,kBAAC,MAAD;GAAgB,WAAU;aAA1B;IACE,kBAAC,QAAD;KAAM,WAAW,GAAG,EAAoB;eACrC,EAAE;KACE,CAAA;IACP,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MACE,WAAW,uBAAuB,EAAa;MAC/C,OAAO,EAAE,OAAO,GAAG,KAAK,IAAI,GAAI,EAAE,QAAQ,IAAO,IAAI,CAAC,IAAI;MAC1D,CAAA;KACE,CAAA;IACN,kBAAC,QAAD;KAAM,WAAU;eACb,EAAE;KACE,CAAA;IACJ;KAbI,EAAE,IAaN,CACL;EACC,CAAA"}
@@ -0,0 +1,50 @@
1
+ import { useId as e } from "react";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ //#region src/adaptercloud/components/viz/Sparkline.tsx
4
+ var r = ({ points: r, className: i = "text-accent-blue h-10 w-full", ariaLabel: a }) => {
5
+ let o = e();
6
+ if (r.length < 2) return null;
7
+ let s = Math.max(...r), c = Math.min(...r), l = s - c || 1, u = 120 / (r.length - 1), d = r.map((e, t) => [t * u, 40 - (e - c) / l * 36 - 2]).map(([e, t], n) => `${n === 0 ? "M" : "L"}${e.toFixed(1)},${t.toFixed(1)}`).join(" "), f = `${d} L120,40 L0,40 Z`;
8
+ return /* @__PURE__ */ n("svg", {
9
+ viewBox: "0 0 120 40",
10
+ className: i,
11
+ preserveAspectRatio: "none",
12
+ role: "img",
13
+ "aria-label": a ?? "trend",
14
+ children: [
15
+ /* @__PURE__ */ t("defs", { children: /* @__PURE__ */ n("linearGradient", {
16
+ id: o,
17
+ x1: "0",
18
+ y1: "0",
19
+ x2: "0",
20
+ y2: "1",
21
+ children: [/* @__PURE__ */ t("stop", {
22
+ offset: "0%",
23
+ stopColor: "currentColor",
24
+ stopOpacity: "0.3"
25
+ }), /* @__PURE__ */ t("stop", {
26
+ offset: "100%",
27
+ stopColor: "currentColor",
28
+ stopOpacity: "0"
29
+ })]
30
+ }) }),
31
+ /* @__PURE__ */ t("path", {
32
+ d: f,
33
+ fill: `url(#${o})`
34
+ }),
35
+ /* @__PURE__ */ t("path", {
36
+ d,
37
+ fill: "none",
38
+ stroke: "currentColor",
39
+ strokeWidth: "1.75",
40
+ strokeLinecap: "round",
41
+ strokeLinejoin: "round",
42
+ vectorEffect: "non-scaling-stroke"
43
+ })
44
+ ]
45
+ });
46
+ };
47
+ //#endregion
48
+ export { r as Sparkline };
49
+
50
+ //# sourceMappingURL=Sparkline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sparkline.js","names":[],"sources":["../../../../src/adaptercloud/components/viz/Sparkline.tsx"],"sourcesContent":["/**\n * Sparkline — a tiny tokenized SVG area/line trend (e.g. monthly cost trend).\n * Uses currentColor + a unique gradient id so multiple sparklines coexist.\n */\nimport { useId, type FC } from 'react';\n\ninterface SparklineProps {\n points: number[];\n /** Wrapper class controls size + color (via text-*). Default accent-blue, full width, 40px tall. */\n className?: string;\n ariaLabel?: string;\n}\n\nexport const Sparkline: FC<SparklineProps> = ({\n points,\n className = 'text-accent-blue h-10 w-full',\n ariaLabel,\n}) => {\n const gradientId = useId();\n if (points.length < 2) return null;\n\n const w = 120;\n const h = 40;\n const max = Math.max(...points);\n const min = Math.min(...points);\n const range = max - min || 1;\n const step = w / (points.length - 1);\n const coords = points.map((p, i) => [i * step, h - ((p - min) / range) * (h - 4) - 2]);\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${w},${h} L0,${h} Z`;\n\n return (\n <svg\n viewBox={`0 0 ${w} ${h}`}\n className={className}\n preserveAspectRatio=\"none\"\n role=\"img\"\n aria-label={ariaLabel ?? 'trend'}\n >\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"currentColor\" stopOpacity=\"0.3\" />\n <stop offset=\"100%\" stopColor=\"currentColor\" stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={area} fill={`url(#${gradientId})`} />\n <path\n d={line}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n );\n};\n"],"mappings":";;;AAaA,IAAa,KAAiC,EAC5C,WACA,eAAY,gCACZ,mBACI;CACJ,IAAM,IAAa,GAAO;AAC1B,KAAI,EAAO,SAAS,EAAG,QAAO;CAE9B,IAEM,IAAM,KAAK,IAAI,GAAG,EAAO,EACzB,IAAM,KAAK,IAAI,GAAG,EAAO,EACzB,IAAQ,IAAM,KAAO,GACrB,IAAO,OAAK,EAAO,SAAS,IAE5B,IADS,EAAO,KAAK,GAAG,MAAM,CAAC,IAAI,GAAM,MAAM,IAAI,KAAO,IAAU,KAAS,EAAE,CAAC,CAEnF,KAAK,CAAC,GAAG,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,CAC3E,KAAK,IAAI,EACN,IAAO,GAAG,EAAK;AAErB,QACE,kBAAC,OAAD;EACE,SAAS;EACE;EACX,qBAAoB;EACpB,MAAK;EACL,cAAY,KAAa;YAL3B;GAOE,kBAAC,QAAD,EAAA,UACE,kBAAC,kBAAD;IAAgB,IAAI;IAAY,IAAG;IAAI,IAAG;IAAI,IAAG;IAAI,IAAG;cAAxD,CACE,kBAAC,QAAD;KAAM,QAAO;KAAK,WAAU;KAAe,aAAY;KAAQ,CAAA,EAC/D,kBAAC,QAAD;KAAM,QAAO;KAAO,WAAU;KAAe,aAAY;KAAM,CAAA,CAChD;OACZ,CAAA;GACP,kBAAC,QAAD;IAAM,GAAG;IAAM,MAAM,QAAQ,EAAW;IAAM,CAAA;GAC9C,kBAAC,QAAD;IACK;IACH,MAAK;IACL,QAAO;IACP,aAAY;IACZ,eAAc;IACd,gBAAe;IACf,cAAa;IACb,CAAA;GACE"}
@@ -0,0 +1 @@
1
+ import "react/jsx-runtime";
@@ -0,0 +1,96 @@
1
+ import { useMemo as e } from "react";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ //#region src/adaptercloud/components/viz/TopologyGraph.tsx
4
+ var r = 168, i = 44, a = 120, o = 26, s = 28, c = ({ nodes: c, edges: l, selectedId: u, onSelect: d }) => {
5
+ let { positioned: f, width: p, height: m, edgePaths: h } = e(() => {
6
+ let e = /* @__PURE__ */ new Map();
7
+ for (let t of c) {
8
+ let n = e.get(t.group) ?? [];
9
+ n.push(t), e.set(t.group, n);
10
+ }
11
+ let t = [...e.keys()], n = Math.max(1, ...[...e.values()].map((e) => e.length)), u = /* @__PURE__ */ new Map();
12
+ t.forEach((t, c) => {
13
+ let l = e.get(t), d = l.length * i + (l.length - 1) * o, f = s + (n * i + (n - 1) * o - d) / 2;
14
+ l.forEach((e, t) => {
15
+ u.set(e.id, {
16
+ x: s + c * (r + a),
17
+ y: f + t * (i + o),
18
+ node: e
19
+ });
20
+ });
21
+ });
22
+ let d = s * 2 + t.length * r + Math.max(0, t.length - 1) * a, f = s * 2 + n * i + Math.max(0, n - 1) * o, p = l.map((e) => {
23
+ let t = u.get(e.from), n = u.get(e.to);
24
+ if (!t || !n) return null;
25
+ let a = t.x + r, o = t.y + i / 2, s = n.x, c = n.y + i / 2, l = (a + s) / 2, d = `M${a},${o} C${l},${o} ${l},${c} ${s},${c}`;
26
+ return {
27
+ ...e,
28
+ d
29
+ };
30
+ }).filter(Boolean);
31
+ return {
32
+ positioned: [...u.values()],
33
+ width: d,
34
+ height: f,
35
+ edgePaths: p
36
+ };
37
+ }, [c, l]), g = e(() => u ? new Set(h.filter((e) => e.from === u || e.to === u).map((e) => e.id)) : /* @__PURE__ */ new Set(), [u, h]), _ = (e) => e === "DRIFTED" ? "border-status-warning-text/60" : e === "ORPHANED" || e === "DELETED" ? "border-status-error-text/60" : "border-border-strong";
38
+ return /* @__PURE__ */ t("div", {
39
+ className: "relative w-full overflow-auto rounded-xl border border-border-subtle bg-bg-sunken/40",
40
+ children: /* @__PURE__ */ n("div", {
41
+ className: "relative",
42
+ style: {
43
+ width: p,
44
+ height: m,
45
+ minWidth: "100%"
46
+ },
47
+ children: [/* @__PURE__ */ t("svg", {
48
+ className: "absolute inset-0 h-full w-full",
49
+ width: p,
50
+ height: m,
51
+ "aria-hidden": !0,
52
+ children: h.map((e) => {
53
+ let n = g.has(e.id), r = e.drifted ? "stroke-status-warning-text" : n ? "stroke-accent-blue" : "stroke-border-strong";
54
+ return /* @__PURE__ */ t("path", {
55
+ d: e.d,
56
+ fill: "none",
57
+ className: r,
58
+ strokeWidth: n ? 2 : 1.25,
59
+ strokeOpacity: u && !n && !e.drifted ? .35 : .9
60
+ }, e.id);
61
+ })
62
+ }), f.map(({ x: e, y: a, node: o }) => {
63
+ let s = o.id === u;
64
+ return /* @__PURE__ */ n("button", {
65
+ type: "button",
66
+ onClick: () => d?.(o.id),
67
+ style: {
68
+ left: e,
69
+ top: a,
70
+ width: r,
71
+ height: i
72
+ },
73
+ className: `absolute flex items-center gap-2 rounded-lg border bg-bg-surface/90 px-3 text-left backdrop-blur transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${s ? "border-accent-blue ring-2 ring-accent-blue/40" : _(o.state)}`,
74
+ title: o.type ? `${o.label} · ${o.type}` : o.label,
75
+ children: [/* @__PURE__ */ t("span", {
76
+ className: `h-2 w-2 shrink-0 rounded-full ${o.state === "DRIFTED" ? "bg-status-warning-text" : o.state === "ORPHANED" || o.state === "DELETED" ? "bg-status-error-text" : "bg-status-success-text"}`,
77
+ "aria-hidden": !0
78
+ }), /* @__PURE__ */ n("span", {
79
+ className: "min-w-0 flex-1",
80
+ children: [/* @__PURE__ */ t("span", {
81
+ className: "block truncate text-sm font-medium text-text-primary",
82
+ children: o.label
83
+ }), o.type && /* @__PURE__ */ t("span", {
84
+ className: "block truncate font-mono text-[10px] text-text-secondary",
85
+ children: o.type
86
+ })]
87
+ })]
88
+ }, o.id);
89
+ })]
90
+ })
91
+ });
92
+ };
93
+ //#endregion
94
+ export { c as TopologyGraph };
95
+
96
+ //# sourceMappingURL=TopologyGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TopologyGraph.js","names":[],"sources":["../../../../src/adaptercloud/components/viz/TopologyGraph.tsx"],"sourcesContent":["/**\n * TopologyGraph — a tokenized, dependency graph of the estate. Deterministic\n * layered layout: nodes are grouped into columns by `group` (class of system),\n * stacked within the column; edges are drawn as SVG bezier curves between node\n * centres. Clicking a node highlights its incident edges and selects it (the\n * parent renders an inspector). No external graph lib — pure SVG + tokens.\n *\n * Data is REAL: the parent feeds nodes from `adaListResources` and edges from\n * `adaListTopologyEdges`.\n */\nimport { useMemo, type FC } from 'react';\n\nexport interface TopologyNode {\n id: string;\n label: string;\n /** Column grouping label, e.g. \"Public Cloud\", \"Kubernetes\", \"Edge / IoT\". */\n group: string;\n type?: string;\n /** Resource state — drives the node accent (DRIFTED → warning, ORPHANED → error, else default). */\n state?: string;\n}\n\nexport interface TopologyEdge {\n id: string;\n from: string;\n to: string;\n kind?: string;\n /** Optional: mark an edge as drifted to render it amber. */\n drifted?: boolean;\n}\n\nconst NODE_W = 168;\nconst NODE_H = 44;\nconst COL_GAP = 120;\nconst ROW_GAP = 26;\nconst PAD = 28;\n\ninterface TopologyGraphProps {\n nodes: TopologyNode[];\n edges: TopologyEdge[];\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n}\n\nexport const TopologyGraph: FC<TopologyGraphProps> = ({ nodes, edges, selectedId, onSelect }) => {\n const { positioned, width, height, edgePaths } = useMemo(() => {\n // group → ordered nodes\n const groups = new Map<string, TopologyNode[]>();\n for (const n of nodes) {\n const g = groups.get(n.group) ?? [];\n g.push(n);\n groups.set(n.group, g);\n }\n const groupNames = [...groups.keys()];\n const maxCol = Math.max(1, ...[...groups.values()].map((g) => g.length));\n\n const pos = new Map<string, { x: number; y: number; node: TopologyNode }>();\n groupNames.forEach((name, ci) => {\n const colNodes = groups.get(name)!;\n const colHeight = colNodes.length * NODE_H + (colNodes.length - 1) * ROW_GAP;\n const fullHeight = maxCol * NODE_H + (maxCol - 1) * ROW_GAP;\n const yStart = PAD + (fullHeight - colHeight) / 2;\n colNodes.forEach((node, ri) => {\n pos.set(node.id, {\n x: PAD + ci * (NODE_W + COL_GAP),\n y: yStart + ri * (NODE_H + ROW_GAP),\n node,\n });\n });\n });\n\n const w = PAD * 2 + groupNames.length * NODE_W + Math.max(0, groupNames.length - 1) * COL_GAP;\n const h = PAD * 2 + maxCol * NODE_H + Math.max(0, maxCol - 1) * ROW_GAP;\n\n const paths = edges\n .map((e) => {\n const a = pos.get(e.from);\n const b = pos.get(e.to);\n if (!a || !b) return null;\n const x1 = a.x + NODE_W;\n const y1 = a.y + NODE_H / 2;\n const x2 = b.x;\n const y2 = b.y + NODE_H / 2;\n const mx = (x1 + x2) / 2;\n const d = `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`;\n return { ...e, d };\n })\n .filter(Boolean) as (TopologyEdge & { d: string })[];\n\n return { positioned: [...pos.values()], width: w, height: h, edgePaths: paths };\n }, [nodes, edges]);\n\n const incident = useMemo(() => {\n if (!selectedId) return new Set<string>();\n return new Set(\n edgePaths.filter((e) => e.from === selectedId || e.to === selectedId).map((e) => e.id)\n );\n }, [selectedId, edgePaths]);\n\n const stateAccent = (state?: string) =>\n state === 'DRIFTED'\n ? 'border-status-warning-text/60'\n : state === 'ORPHANED' || state === 'DELETED'\n ? 'border-status-error-text/60'\n : 'border-border-strong';\n\n return (\n <div className=\"relative w-full overflow-auto rounded-xl border border-border-subtle bg-bg-sunken/40\">\n <div className=\"relative\" style={{ width, height, minWidth: '100%' }}>\n <svg className=\"absolute inset-0 h-full w-full\" width={width} height={height} aria-hidden>\n {edgePaths.map((e) => {\n const active = incident.has(e.id);\n const cls = e.drifted\n ? 'stroke-status-warning-text'\n : active\n ? 'stroke-accent-blue'\n : 'stroke-border-strong';\n return (\n <path\n key={e.id}\n d={e.d}\n fill=\"none\"\n className={cls}\n strokeWidth={active ? 2 : 1.25}\n strokeOpacity={selectedId && !active && !e.drifted ? 0.35 : 0.9}\n />\n );\n })}\n </svg>\n\n {positioned.map(({ x, y, node }) => {\n const selected = node.id === selectedId;\n return (\n <button\n key={node.id}\n type=\"button\"\n onClick={() => onSelect?.(node.id)}\n style={{ left: x, top: y, width: NODE_W, height: NODE_H }}\n className={`absolute flex items-center gap-2 rounded-lg border bg-bg-surface/90 px-3 text-left backdrop-blur transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${\n selected ? 'border-accent-blue ring-2 ring-accent-blue/40' : stateAccent(node.state)\n }`}\n title={node.type ? `${node.label} · ${node.type}` : node.label}\n >\n <span\n className={`h-2 w-2 shrink-0 rounded-full ${\n node.state === 'DRIFTED'\n ? 'bg-status-warning-text'\n : node.state === 'ORPHANED' || node.state === 'DELETED'\n ? 'bg-status-error-text'\n : 'bg-status-success-text'\n }`}\n aria-hidden\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-medium text-text-primary\">\n {node.label}\n </span>\n {node.type && (\n <span className=\"block truncate font-mono text-[10px] text-text-secondary\">\n {node.type}\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import "./StackedBar.js";
2
+ import "./BarChart.js";
3
+ import "./Sparkline.js";
4
+ import "./TopologyGraph.js";