@burdenoff/microfe-adaptercloud 2026.706.2 → 2026.706.3

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
@@ -1,133 +1,139 @@
1
1
  import { useAdapterCloud as e } from "../../context/AdapterCloudContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { adapterKindLabels as n, authMethodLabels as r } from "../../utils/domain.js";
4
- import { StatusBadge as i } from "../../components/StatusBadge.js";
5
- import { DataState as a } from "../../components/DataState.js";
6
- import { useAdapter as o, useArchiveAdapter as s } from "../../hooks/useAdapterCloudApi.js";
7
- import { formatDate as c } from "../../utils/formatters.js";
8
- import { ConfirmDialog as l } from "../../components/ConfirmDialog.js";
9
- import { useCallback as u, useState as d } from "react";
10
- import { useI18n as f } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
- import { Archive as p, ArrowLeft as m, Cable as h, Pencil as g } from "lucide-react";
12
- import { useParams as _ } from "react-router-dom";
13
- import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
14
- import { GlassCard as x } from "@burdenoff/fe-libs/ui";
3
+ import { adapterKindLabels as n } from "../../utils/domain.js";
4
+ import { StatusBadge as r } from "../../components/StatusBadge.js";
5
+ import { DataState as i } from "../../components/DataState.js";
6
+ import { useAdapter as a, useArchiveAdapter as o } from "../../hooks/useAdapterCloudApi.js";
7
+ import { formatDate as s } from "../../utils/formatters.js";
8
+ import { ConfirmDialog as c } from "../../components/ConfirmDialog.js";
9
+ import { useCallback as l, useState as u } from "react";
10
+ import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
+ import { Archive as f, ArrowLeft as p, Cable as m, Check as h, Copy as g, Pencil as _ } from "lucide-react";
12
+ import { useParams as v } from "react-router-dom";
13
+ import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
14
+ import { GlassCard as S } from "@burdenoff/fe-libs/ui";
15
15
  //#region src/adaptercloud/pages/adapters/AdapterDetailPage.tsx
16
- function S() {
17
- let { id: S } = _(), { navigateTo: C } = e(), { t: w } = f(), T = u((e, t) => {
18
- let n = w(e);
16
+ function C() {
17
+ let { id: C } = v(), { navigateTo: w } = e(), { t: T } = d(), E = l((e, t) => {
18
+ let n = T(e);
19
19
  return n === e ? t : n;
20
- }, [w]), E = o(S), D = s(), O = E.data, [k, A] = d(!1), j = u(() => {
21
- S && D.mutate(S, { onSuccess: () => {
22
- A(!1), C("/adapters");
20
+ }, [T]), D = a(C), O = o(), k = D.data, [A, j] = u(!1), [M, N] = u(!1), P = l(() => {
21
+ if (k?.configSchema == null) return;
22
+ let e = JSON.stringify(k.configSchema, null, 2);
23
+ navigator.clipboard?.writeText(e).then(() => {
24
+ N(!0), setTimeout(() => N(!1), 1500);
25
+ }).catch(() => {});
26
+ }, [k?.configSchema]), F = l(() => {
27
+ C && O.mutate(C, { onSuccess: () => {
28
+ j(!1), w("/adapters");
23
29
  } });
24
30
  }, [
25
- D,
26
- S,
27
- C
31
+ O,
32
+ C,
33
+ w
28
34
  ]);
29
- return /* @__PURE__ */ b(t, {
30
- title: O?.name ?? T("adaptercloud.adapters.detailTitle", "Adapter"),
31
- description: O?.slug,
32
- actions: /* @__PURE__ */ b("div", {
35
+ return /* @__PURE__ */ x(t, {
36
+ title: k?.name ?? E("adaptercloud.adapters.detailTitle", "Adapter"),
37
+ description: k?.slug,
38
+ actions: /* @__PURE__ */ x("div", {
33
39
  className: "flex items-center gap-2",
34
- children: [/* @__PURE__ */ b("button", {
40
+ children: [/* @__PURE__ */ x("button", {
35
41
  type: "button",
36
- onClick: () => C("/adapters"),
42
+ onClick: () => w("/adapters"),
37
43
  className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent",
38
- children: [/* @__PURE__ */ y(m, { className: "h-4 w-4" }), T("adaptercloud.common.back", "Back")]
39
- }), O && /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ b("button", {
44
+ children: [/* @__PURE__ */ b(p, { className: "h-4 w-4" }), E("adaptercloud.common.back", "Back")]
45
+ }), k && /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ x("button", {
40
46
  type: "button",
41
- onClick: () => C(`/adapters/${O.id}/edit`),
47
+ onClick: () => w(`/adapters/${k.id}/edit`),
42
48
  className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent",
43
- children: [/* @__PURE__ */ y(g, { className: "h-4 w-4" }), T("adaptercloud.common.edit", "Edit")]
44
- }), O.status !== "ARCHIVED" && /* @__PURE__ */ b("button", {
49
+ children: [/* @__PURE__ */ b(_, { className: "h-4 w-4" }), E("adaptercloud.common.edit", "Edit")]
50
+ }), k.status !== "ARCHIVED" && /* @__PURE__ */ x("button", {
45
51
  type: "button",
46
- onClick: () => A(!0),
47
- disabled: D.isPending,
52
+ onClick: () => j(!0),
53
+ disabled: O.isPending,
48
54
  className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50",
49
- children: [/* @__PURE__ */ y(p, { className: "h-4 w-4" }), T("adaptercloud.common.archive", "Archive")]
55
+ children: [/* @__PURE__ */ b(f, { className: "h-4 w-4" }), E("adaptercloud.common.archive", "Archive")]
50
56
  })] })]
51
57
  }),
52
- children: [/* @__PURE__ */ y(a, {
53
- isLoading: E.isLoading,
54
- isError: E.isError,
55
- isEmpty: !E.isLoading && !O,
56
- error: E.error,
57
- onRetry: () => void E.refetch(),
58
- emptyTitle: T("adaptercloud.adapters.notFound", "Adapter not found"),
59
- emptyDescription: T("adaptercloud.adapters.notFoundDescription", "This adapter does not exist or belongs to another workspace."),
60
- children: O && /* @__PURE__ */ b("div", {
58
+ children: [/* @__PURE__ */ b(i, {
59
+ isLoading: D.isLoading,
60
+ isError: D.isError,
61
+ isEmpty: !D.isLoading && !k,
62
+ error: D.error,
63
+ onRetry: () => void D.refetch(),
64
+ emptyTitle: E("adaptercloud.adapters.notFound", "Adapter not found"),
65
+ emptyDescription: E("adaptercloud.adapters.notFoundDescription", "This adapter does not exist or belongs to another workspace."),
66
+ children: k && /* @__PURE__ */ x("div", {
61
67
  className: "space-y-6",
62
68
  children: [
63
- /* @__PURE__ */ b(x, {
69
+ /* @__PURE__ */ x(S, {
64
70
  className: "p-6",
65
71
  children: [
66
- /* @__PURE__ */ b("div", {
72
+ /* @__PURE__ */ x("div", {
67
73
  className: "mb-4 flex items-center gap-3",
68
74
  children: [
69
- /* @__PURE__ */ y(i, { status: O.status }),
70
- /* @__PURE__ */ y("span", {
75
+ /* @__PURE__ */ b(r, { status: k.status }),
76
+ /* @__PURE__ */ b("span", {
71
77
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
72
- children: n[O.kind]
78
+ children: n[k.kind]
73
79
  }),
74
- /* @__PURE__ */ b("span", {
80
+ /* @__PURE__ */ x("span", {
75
81
  className: "text-xs text-text-secondary",
76
- children: ["v", O.version]
82
+ children: ["v", k.version]
77
83
  })
78
84
  ]
79
85
  }),
80
- O.description && /* @__PURE__ */ y("p", {
86
+ k.description && /* @__PURE__ */ b("p", {
81
87
  className: "mb-4 text-sm text-text-secondary",
82
- children: O.description
88
+ children: k.description
83
89
  }),
84
- /* @__PURE__ */ b("dl", {
90
+ /* @__PURE__ */ x("dl", {
85
91
  className: "grid grid-cols-2 gap-4 text-sm sm:grid-cols-3",
86
92
  children: [
87
- /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("dt", {
93
+ /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
88
94
  className: "text-text-secondary",
89
- children: T("adaptercloud.adapters.vendor", "Vendor")
90
- }), /* @__PURE__ */ y("dd", {
95
+ children: E("adaptercloud.adapters.vendor", "Vendor")
96
+ }), /* @__PURE__ */ b("dd", {
91
97
  className: "mt-0.5 font-medium text-text-primary",
92
- children: O.vendor ?? "—"
98
+ children: k.vendor ?? "—"
93
99
  })] }),
94
- /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("dt", {
100
+ /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
95
101
  className: "text-text-secondary",
96
- children: T("adaptercloud.common.created", "Created")
97
- }), /* @__PURE__ */ y("dd", {
102
+ children: E("adaptercloud.common.created", "Created")
103
+ }), /* @__PURE__ */ b("dd", {
98
104
  className: "mt-0.5 font-medium text-text-primary",
99
- children: c(O.createdAt)
105
+ children: s(k.createdAt)
100
106
  })] }),
101
- /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("dt", {
107
+ /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
102
108
  className: "text-text-secondary",
103
- children: T("adaptercloud.common.updated", "Updated")
104
- }), /* @__PURE__ */ y("dd", {
109
+ children: E("adaptercloud.common.updated", "Updated")
110
+ }), /* @__PURE__ */ b("dd", {
105
111
  className: "mt-0.5 font-medium text-text-primary",
106
- children: c(O.updatedAt)
112
+ children: s(k.updatedAt)
107
113
  })] })
108
114
  ]
109
115
  }),
110
- O.capabilities.length > 0 && /* @__PURE__ */ b("div", {
116
+ k.capabilities.length > 0 && /* @__PURE__ */ x("div", {
111
117
  className: "mt-5",
112
- children: [/* @__PURE__ */ y("h3", {
118
+ children: [/* @__PURE__ */ b("h3", {
113
119
  className: "mb-2 text-sm font-semibold text-text-primary",
114
- children: T("adaptercloud.adapters.capabilities", "Capabilities")
115
- }), /* @__PURE__ */ y("div", {
120
+ children: E("adaptercloud.adapters.capabilities", "Capabilities")
121
+ }), /* @__PURE__ */ b("div", {
116
122
  className: "flex flex-wrap gap-1.5",
117
- children: O.capabilities.map((e) => /* @__PURE__ */ y("span", {
123
+ children: k.capabilities.map((e) => /* @__PURE__ */ b("span", {
118
124
  className: "inline-flex items-center rounded-full bg-accent-blue-subtle px-2.5 py-0.5 text-xs text-accent-blue",
119
125
  children: e
120
126
  }, e))
121
127
  })]
122
128
  }),
123
- O.tags.length > 0 && /* @__PURE__ */ b("div", {
129
+ k.tags.length > 0 && /* @__PURE__ */ x("div", {
124
130
  className: "mt-4",
125
- children: [/* @__PURE__ */ y("h3", {
131
+ children: [/* @__PURE__ */ b("h3", {
126
132
  className: "mb-2 text-sm font-semibold text-text-primary",
127
- children: T("adaptercloud.common.tags", "Tags")
128
- }), /* @__PURE__ */ y("div", {
133
+ children: E("adaptercloud.common.tags", "Tags")
134
+ }), /* @__PURE__ */ b("div", {
129
135
  className: "flex flex-wrap gap-1.5",
130
- children: O.tags.map((e) => /* @__PURE__ */ y("span", {
136
+ children: k.tags.map((e) => /* @__PURE__ */ b("span", {
131
137
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
132
138
  children: e
133
139
  }, e))
@@ -135,66 +141,113 @@ function S() {
135
141
  })
136
142
  ]
137
143
  }),
138
- O.configSchema != null && /* @__PURE__ */ b(x, {
144
+ k.configSchema != null && /* @__PURE__ */ x(S, {
139
145
  className: "p-6",
140
- children: [/* @__PURE__ */ y("h3", {
141
- className: "mb-3 text-sm font-semibold text-text-primary",
142
- children: T("adaptercloud.adapters.configSchema", "Config Schema")
143
- }), /* @__PURE__ */ y("pre", {
146
+ children: [/* @__PURE__ */ x("div", {
147
+ className: "mb-3 flex items-center justify-between gap-3",
148
+ children: [/* @__PURE__ */ b("h3", {
149
+ className: "text-sm font-semibold text-text-primary",
150
+ children: E("adaptercloud.adapters.configSchema", "Config Schema")
151
+ }), /* @__PURE__ */ b("button", {
152
+ type: "button",
153
+ onClick: P,
154
+ "aria-label": E("adaptercloud.common.copy", "Copy"),
155
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-subtle bg-bg-surface px-2.5 py-1 text-xs font-medium text-text-secondary transition-colors hover:bg-accent hover:text-text-primary",
156
+ children: M ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(h, { className: "h-3.5 w-3.5 text-status-success-text" }), E("adaptercloud.common.copied", "Copied")] }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(g, { className: "h-3.5 w-3.5" }), E("adaptercloud.common.copy", "Copy")] })
157
+ })]
158
+ }), /* @__PURE__ */ b("pre", {
144
159
  className: "overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary",
145
- children: JSON.stringify(O.configSchema, null, 2)
160
+ children: JSON.stringify(k.configSchema, null, 2)
146
161
  })]
147
162
  }),
148
- /* @__PURE__ */ b("section", { children: [/* @__PURE__ */ y("h3", {
163
+ /* @__PURE__ */ x("section", { children: [/* @__PURE__ */ b("h3", {
149
164
  className: "mb-3 text-base font-semibold text-text-primary",
150
- children: T("adaptercloud.adapters.connections", "Connections")
151
- }), O.connections && O.connections.length > 0 ? /* @__PURE__ */ y("div", {
152
- className: "divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface",
153
- children: O.connections.map((e) => /* @__PURE__ */ b("button", {
154
- type: "button",
155
- onClick: () => C(`/connections/${e.id}`),
156
- className: "flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50",
157
- children: [
158
- /* @__PURE__ */ y(h, { className: "h-4 w-4 shrink-0 text-text-secondary" }),
159
- /* @__PURE__ */ b("div", {
160
- className: "min-w-0 flex-1",
161
- children: [/* @__PURE__ */ y("p", {
162
- className: "truncate text-sm font-medium text-text-primary",
163
- children: e.name
164
- }), /* @__PURE__ */ b("p", {
165
- className: "mt-0.5 text-xs text-text-secondary",
166
- children: [
167
- r[e.authMethod],
168
- " · ",
169
- e.resourceCount,
170
- " ",
171
- T("adaptercloud.adapters.resourcesLower", "resources")
172
- ]
173
- })]
174
- }),
175
- /* @__PURE__ */ y(i, { status: e.status })
176
- ]
177
- }, e.id))
178
- }) : /* @__PURE__ */ y("p", {
165
+ children: E("adaptercloud.adapters.connections", "Connections")
166
+ }), k.connections && k.connections.length > 0 ? /* @__PURE__ */ b("div", {
167
+ className: "overflow-x-auto rounded-xl border border-border-subtle bg-bg-surface",
168
+ children: /* @__PURE__ */ x("table", {
169
+ className: "w-full min-w-[32rem] text-sm",
170
+ children: [/* @__PURE__ */ b("thead", { children: /* @__PURE__ */ x("tr", {
171
+ className: "border-b border-border-subtle text-left text-xs uppercase tracking-wide text-text-secondary",
172
+ children: [
173
+ /* @__PURE__ */ b("th", {
174
+ scope: "col",
175
+ className: "px-4 py-2.5 font-medium",
176
+ children: E("adaptercloud.adapters.connName", "Name")
177
+ }),
178
+ /* @__PURE__ */ b("th", {
179
+ scope: "col",
180
+ className: "px-4 py-2.5 font-medium",
181
+ children: E("adaptercloud.resources.region", "Region")
182
+ }),
183
+ /* @__PURE__ */ b("th", {
184
+ scope: "col",
185
+ className: "px-4 py-2.5 font-medium",
186
+ children: E("adaptercloud.adapters.status", "Status")
187
+ }),
188
+ /* @__PURE__ */ b("th", {
189
+ scope: "col",
190
+ className: "px-4 py-2.5 text-right font-medium",
191
+ children: E("adaptercloud.adapters.resources", "Resources")
192
+ })
193
+ ]
194
+ }) }), /* @__PURE__ */ b("tbody", {
195
+ className: "divide-y divide-border",
196
+ children: k.connections.map((e) => /* @__PURE__ */ x("tr", {
197
+ role: "link",
198
+ tabIndex: 0,
199
+ onClick: () => w(`/connections/${e.id}`),
200
+ onKeyDown: (t) => {
201
+ (t.key === "Enter" || t.key === " ") && (t.preventDefault(), w(`/connections/${e.id}`));
202
+ },
203
+ className: "cursor-pointer transition-colors hover:bg-accent/50 focus:bg-accent/50 focus:outline-none",
204
+ children: [
205
+ /* @__PURE__ */ b("td", {
206
+ className: "px-4 py-3",
207
+ children: /* @__PURE__ */ x("span", {
208
+ className: "flex items-center gap-2",
209
+ children: [/* @__PURE__ */ b(m, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ b("span", {
210
+ className: "truncate font-medium text-text-primary",
211
+ children: e.name
212
+ })]
213
+ })
214
+ }),
215
+ /* @__PURE__ */ b("td", {
216
+ className: "px-4 py-3 text-text-secondary",
217
+ children: e.region ?? "—"
218
+ }),
219
+ /* @__PURE__ */ b("td", {
220
+ className: "px-4 py-3",
221
+ children: /* @__PURE__ */ b(r, { status: e.status })
222
+ }),
223
+ /* @__PURE__ */ b("td", {
224
+ className: "px-4 py-3 text-right tabular-nums text-text-secondary",
225
+ children: e.resourceCount
226
+ })
227
+ ]
228
+ }, e.id))
229
+ })]
230
+ })
231
+ }) : /* @__PURE__ */ b("p", {
179
232
  className: "rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary",
180
- children: T("adaptercloud.adapters.noConnections", "No connections use this adapter yet.")
233
+ children: E("adaptercloud.adapters.noConnections", "No connections use this adapter yet.")
181
234
  })] })
182
235
  ]
183
236
  })
184
- }), /* @__PURE__ */ y(l, {
185
- open: k,
186
- onOpenChange: A,
187
- title: T("adaptercloud.adapters.archiveTitle", "Archive this adapter?"),
188
- description: T("adaptercloud.adapters.archivePrompt", "The adapter will be archived and hidden from the catalog. Existing connections keep working, but no new connections can select it."),
189
- confirmLabel: T("adaptercloud.common.archive", "Archive"),
190
- cancelLabel: T("adaptercloud.common.cancel", "Cancel"),
191
- onConfirm: j,
192
- isPending: D.isPending,
237
+ }), /* @__PURE__ */ b(c, {
238
+ open: A,
239
+ onOpenChange: j,
240
+ title: E("adaptercloud.adapters.archiveTitle", "Archive this adapter?"),
241
+ description: E("adaptercloud.adapters.archivePrompt", "The adapter will be archived and hidden from the catalog. Existing connections keep working, but no new connections can select it."),
242
+ confirmLabel: E("adaptercloud.common.archive", "Archive"),
243
+ cancelLabel: E("adaptercloud.common.cancel", "Cancel"),
244
+ onConfirm: F,
245
+ isPending: O.isPending,
193
246
  tone: "danger"
194
247
  })]
195
248
  });
196
249
  }
197
250
  //#endregion
198
- export { S as AdapterDetailPage };
251
+ export { C as AdapterDetailPage };
199
252
 
200
253
  //# sourceMappingURL=AdapterDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdapterDetailPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/adapters/AdapterDetailPage.tsx"],"sourcesContent":["/**\n * Adapter Detail Page\n * @module adaptercloud/pages/adapters\n *\n * Full view of one adapter (`adaAdapter`) — metadata, capabilities, config\n * schema and its connections. Supports archiving via `adaArchiveAdapter`.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Archive, Cable, Pencil } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { ConfirmDialog } from '../../components/ConfirmDialog';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useAdapter, useArchiveAdapter } from '../../hooks/useAdapterCloudApi';\nimport { adapterKindLabels, authMethodLabels } from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\n\nexport function AdapterDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useAdapterCloud();\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 const query = useAdapter(id);\n const archive = useArchiveAdapter();\n const adapter = query.data;\n\n const [confirmArchiveOpen, setConfirmArchiveOpen] = useState(false);\n\n const handleArchive = useCallback(() => {\n if (!id) return;\n archive.mutate(id, {\n onSuccess: () => {\n setConfirmArchiveOpen(false);\n navigateTo('/adapters');\n },\n });\n }, [archive, id, navigateTo]);\n\n return (\n <PageLayout\n title={adapter?.name ?? t('adaptercloud.adapters.detailTitle', 'Adapter')}\n description={adapter?.slug}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/adapters')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.back', 'Back')}\n </button>\n {adapter && (\n <>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/adapters/${adapter.id}/edit`)}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <Pencil className=\"h-4 w-4\" />\n {t('adaptercloud.common.edit', 'Edit')}\n </button>\n {adapter.status !== 'ARCHIVED' && (\n <button\n type=\"button\"\n onClick={() => setConfirmArchiveOpen(true)}\n disabled={archive.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Archive className=\"h-4 w-4\" />\n {t('adaptercloud.common.archive', 'Archive')}\n </button>\n )}\n </>\n )}\n </div>\n }\n >\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={!query.isLoading && !adapter}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.adapters.notFound', 'Adapter not found')}\n emptyDescription={t(\n 'adaptercloud.adapters.notFoundDescription',\n 'This adapter does not exist or belongs to another workspace.'\n )}\n >\n {adapter && (\n <div className=\"space-y-6\">\n {/* Metadata */}\n <GlassCard className=\"p-6\">\n <div className=\"mb-4 flex items-center gap-3\">\n <StatusBadge status={adapter.status} />\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n {adapterKindLabels[adapter.kind]}\n </span>\n <span className=\"text-xs text-text-secondary\">v{adapter.version}</span>\n </div>\n\n {adapter.description && (\n <p className=\"mb-4 text-sm text-text-secondary\">{adapter.description}</p>\n )}\n\n <dl className=\"grid grid-cols-2 gap-4 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.adapters.vendor', 'Vendor')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">{adapter.vendor ?? '—'}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.common.created', 'Created')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDate(adapter.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDate(adapter.updatedAt)}\n </dd>\n </div>\n </dl>\n\n {adapter.capabilities.length > 0 && (\n <div className=\"mt-5\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.adapters.capabilities', 'Capabilities')}\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {adapter.capabilities.map((cap) => (\n <span\n key={cap}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2.5 py-0.5 text-xs text-accent-blue\"\n >\n {cap}\n </span>\n ))}\n </div>\n </div>\n )}\n\n {adapter.tags.length > 0 && (\n <div className=\"mt-4\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.common.tags', 'Tags')}\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {adapter.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n )}\n </GlassCard>\n\n {/* Config schema */}\n {adapter.configSchema != null && (\n <GlassCard className=\"p-6\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.adapters.configSchema', 'Config Schema')}\n </h3>\n <pre className=\"overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary\">\n {JSON.stringify(adapter.configSchema, null, 2)}\n </pre>\n </GlassCard>\n )}\n\n {/* Connections */}\n <section>\n <h3 className=\"mb-3 text-base font-semibold text-text-primary\">\n {t('adaptercloud.adapters.connections', 'Connections')}\n </h3>\n {adapter.connections && adapter.connections.length > 0 ? (\n <div className=\"divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface\">\n {adapter.connections.map((conn) => (\n <button\n key={conn.id}\n type=\"button\"\n onClick={() => navigateTo(`/connections/${conn.id}`)}\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50\"\n >\n <Cable className=\"h-4 w-4 shrink-0 text-text-secondary\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {conn.name}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {authMethodLabels[conn.authMethod]} · {conn.resourceCount}{' '}\n {t('adaptercloud.adapters.resourcesLower', 'resources')}\n </p>\n </div>\n <StatusBadge status={conn.status} />\n </button>\n ))}\n </div>\n ) : (\n <p className=\"rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {t('adaptercloud.adapters.noConnections', 'No connections use this adapter yet.')}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n\n <ConfirmDialog\n open={confirmArchiveOpen}\n onOpenChange={setConfirmArchiveOpen}\n title={t('adaptercloud.adapters.archiveTitle', 'Archive this adapter?')}\n description={t(\n 'adaptercloud.adapters.archivePrompt',\n 'The adapter will be archived and hidden from the catalog. Existing connections keep working, but no new connections can select it.'\n )}\n confirmLabel={t('adaptercloud.common.archive', 'Archive')}\n cancelLabel={t('adaptercloud.common.cancel', 'Cancel')}\n onConfirm={handleArchive}\n isPending={archive.isPending}\n tone=\"danger\"\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdapterDetailPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/adapters/AdapterDetailPage.tsx"],"sourcesContent":["/**\n * Adapter Detail Page\n * @module adaptercloud/pages/adapters\n *\n * Full view of one adapter (`adaAdapter`) — metadata, capabilities, config\n * schema and its connections. Supports archiving via `adaArchiveAdapter`.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Archive, Cable, Check, Copy, Pencil } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { ConfirmDialog } from '../../components/ConfirmDialog';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useAdapter, useArchiveAdapter } from '../../hooks/useAdapterCloudApi';\nimport { adapterKindLabels } from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\n\nexport function AdapterDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useAdapterCloud();\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 const query = useAdapter(id);\n const archive = useArchiveAdapter();\n const adapter = query.data;\n\n const [confirmArchiveOpen, setConfirmArchiveOpen] = useState(false);\n const [copied, setCopied] = useState(false);\n\n const handleCopyConfig = useCallback(() => {\n if (adapter?.configSchema == null) return;\n const text = JSON.stringify(adapter.configSchema, null, 2);\n void navigator.clipboard\n ?.writeText(text)\n .then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n })\n .catch(() => {\n /* clipboard unavailable — no-op */\n });\n }, [adapter?.configSchema]);\n\n const handleArchive = useCallback(() => {\n if (!id) return;\n archive.mutate(id, {\n onSuccess: () => {\n setConfirmArchiveOpen(false);\n navigateTo('/adapters');\n },\n });\n }, [archive, id, navigateTo]);\n\n return (\n <PageLayout\n title={adapter?.name ?? t('adaptercloud.adapters.detailTitle', 'Adapter')}\n description={adapter?.slug}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/adapters')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.back', 'Back')}\n </button>\n {adapter && (\n <>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/adapters/${adapter.id}/edit`)}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <Pencil className=\"h-4 w-4\" />\n {t('adaptercloud.common.edit', 'Edit')}\n </button>\n {adapter.status !== 'ARCHIVED' && (\n <button\n type=\"button\"\n onClick={() => setConfirmArchiveOpen(true)}\n disabled={archive.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Archive className=\"h-4 w-4\" />\n {t('adaptercloud.common.archive', 'Archive')}\n </button>\n )}\n </>\n )}\n </div>\n }\n >\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={!query.isLoading && !adapter}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.adapters.notFound', 'Adapter not found')}\n emptyDescription={t(\n 'adaptercloud.adapters.notFoundDescription',\n 'This adapter does not exist or belongs to another workspace.'\n )}\n >\n {adapter && (\n <div className=\"space-y-6\">\n {/* Metadata */}\n <GlassCard className=\"p-6\">\n <div className=\"mb-4 flex items-center gap-3\">\n <StatusBadge status={adapter.status} />\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n {adapterKindLabels[adapter.kind]}\n </span>\n <span className=\"text-xs text-text-secondary\">v{adapter.version}</span>\n </div>\n\n {adapter.description && (\n <p className=\"mb-4 text-sm text-text-secondary\">{adapter.description}</p>\n )}\n\n <dl className=\"grid grid-cols-2 gap-4 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.adapters.vendor', 'Vendor')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">{adapter.vendor ?? '—'}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.common.created', 'Created')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDate(adapter.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDate(adapter.updatedAt)}\n </dd>\n </div>\n </dl>\n\n {adapter.capabilities.length > 0 && (\n <div className=\"mt-5\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.adapters.capabilities', 'Capabilities')}\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {adapter.capabilities.map((cap) => (\n <span\n key={cap}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2.5 py-0.5 text-xs text-accent-blue\"\n >\n {cap}\n </span>\n ))}\n </div>\n </div>\n )}\n\n {adapter.tags.length > 0 && (\n <div className=\"mt-4\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.common.tags', 'Tags')}\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {adapter.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n )}\n </GlassCard>\n\n {/* Config schema */}\n {adapter.configSchema != null && (\n <GlassCard className=\"p-6\">\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t('adaptercloud.adapters.configSchema', 'Config Schema')}\n </h3>\n <button\n type=\"button\"\n onClick={handleCopyConfig}\n aria-label={t('adaptercloud.common.copy', 'Copy')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle bg-bg-surface px-2.5 py-1 text-xs font-medium text-text-secondary transition-colors hover:bg-accent hover:text-text-primary\"\n >\n {copied ? (\n <>\n <Check className=\"h-3.5 w-3.5 text-status-success-text\" />\n {t('adaptercloud.common.copied', 'Copied')}\n </>\n ) : (\n <>\n <Copy className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.common.copy', 'Copy')}\n </>\n )}\n </button>\n </div>\n <pre className=\"overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary\">\n {JSON.stringify(adapter.configSchema, null, 2)}\n </pre>\n </GlassCard>\n )}\n\n {/* Connections */}\n <section>\n <h3 className=\"mb-3 text-base font-semibold text-text-primary\">\n {t('adaptercloud.adapters.connections', 'Connections')}\n </h3>\n {adapter.connections && adapter.connections.length > 0 ? (\n <div className=\"overflow-x-auto rounded-xl border border-border-subtle bg-bg-surface\">\n <table className=\"w-full min-w-[32rem] text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle text-left text-xs uppercase tracking-wide text-text-secondary\">\n <th scope=\"col\" className=\"px-4 py-2.5 font-medium\">\n {t('adaptercloud.adapters.connName', 'Name')}\n </th>\n <th scope=\"col\" className=\"px-4 py-2.5 font-medium\">\n {t('adaptercloud.resources.region', 'Region')}\n </th>\n <th scope=\"col\" className=\"px-4 py-2.5 font-medium\">\n {t('adaptercloud.adapters.status', 'Status')}\n </th>\n <th scope=\"col\" className=\"px-4 py-2.5 text-right font-medium\">\n {t('adaptercloud.adapters.resources', 'Resources')}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {adapter.connections.map((conn) => (\n <tr\n key={conn.id}\n role=\"link\"\n tabIndex={0}\n onClick={() => navigateTo(`/connections/${conn.id}`)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n navigateTo(`/connections/${conn.id}`);\n }\n }}\n className=\"cursor-pointer transition-colors hover:bg-accent/50 focus:bg-accent/50 focus:outline-none\"\n >\n <td className=\"px-4 py-3\">\n <span className=\"flex items-center gap-2\">\n <Cable className=\"h-4 w-4 shrink-0 text-text-secondary\" />\n <span className=\"truncate font-medium text-text-primary\">\n {conn.name}\n </span>\n </span>\n </td>\n <td className=\"px-4 py-3 text-text-secondary\">{conn.region ?? '—'}</td>\n <td className=\"px-4 py-3\">\n <StatusBadge status={conn.status} />\n </td>\n <td className=\"px-4 py-3 text-right tabular-nums text-text-secondary\">\n {conn.resourceCount}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <p className=\"rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {t('adaptercloud.adapters.noConnections', 'No connections use this adapter yet.')}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n\n <ConfirmDialog\n open={confirmArchiveOpen}\n onOpenChange={setConfirmArchiveOpen}\n title={t('adaptercloud.adapters.archiveTitle', 'Archive this adapter?')}\n description={t(\n 'adaptercloud.adapters.archivePrompt',\n 'The adapter will be archived and hidden from the catalog. Existing connections keep working, but no new connections can select it.'\n )}\n confirmLabel={t('adaptercloud.common.archive', 'Archive')}\n cancelLabel={t('adaptercloud.common.cancel', 'Cancel')}\n onConfirm={handleArchive}\n isPending={archive.isPending}\n tone=\"danger\"\n />\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsBA,SAAgB,IAAoB;CAClC,IAAM,EAAE,UAAO,GAA2B,EACpC,EAAE,kBAAe,GAAiB,EAClC,EAAE,GAAG,MAAc,GAAS,EAC5B,IAAI,GACP,GAAa,MAA6B;EACzC,IAAM,IAAQ,EAAU,EAAI;AAC5B,SAAO,MAAU,IAAM,IAAW;IAEpC,CAAC,EAAU,CACZ,EAEK,IAAQ,EAAW,EAAG,EACtB,IAAU,GAAmB,EAC7B,IAAU,EAAM,MAEhB,CAAC,GAAoB,KAAyB,EAAS,GAAM,EAC7D,CAAC,GAAQ,KAAa,EAAS,GAAM,EAErC,IAAmB,QAAkB;AACzC,MAAI,GAAS,gBAAgB,KAAM;EACnC,IAAM,IAAO,KAAK,UAAU,EAAQ,cAAc,MAAM,EAAE;AACrD,YAAU,WACX,UAAU,EAAK,CAChB,WAAW;AAEV,GADA,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,KAAK;IACxC,CACD,YAAY,GAEX;IACH,CAAC,GAAS,aAAa,CAAC,EAErB,IAAgB,QAAkB;AACjC,OACL,EAAQ,OAAO,GAAI,EACjB,iBAAiB;AAEf,GADA,EAAsB,GAAM,EAC5B,EAAW,YAAY;KAE1B,CAAC;IACD;EAAC;EAAS;EAAI;EAAW,CAAC;AAE7B,QACE,kBAAC,GAAD;EACE,OAAO,GAAS,QAAQ,EAAE,qCAAqC,UAAU;EACzE,aAAa,GAAS;EACtB,SACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,YAAY;IACtC,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAChC,EAAE,4BAA4B,OAAO,CAC/B;OACR,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,aAAa,EAAQ,GAAG,OAAO;IACzD,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAC7B,EAAE,4BAA4B,OAAO,CAC/B;OACR,EAAQ,WAAW,cAClB,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAsB,GAAK;IAC1C,UAAU,EAAQ;IAClB,WAAU;cAJZ,CAME,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA,EAC9B,EAAE,+BAA+B,UAAU,CACrC;MAEV,EAAA,CAAA,CAED;;YApCV,CAuCE,kBAAC,GAAD;GACE,WAAW,EAAM;GACjB,SAAS,EAAM;GACf,SAAS,CAAC,EAAM,aAAa,CAAC;GAC9B,OAAO,EAAM;GACb,eAAe,KAAK,EAAM,SAAS;GACnC,YAAY,EAAE,kCAAkC,oBAAoB;GACpE,kBAAkB,EAChB,6CACA,+DACD;aAEA,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,GAAD;MAAW,WAAU;gBAArB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,GAAD,EAAa,QAAQ,EAAQ,QAAU,CAAA;SACvC,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAkB,EAAQ;UACtB,CAAA;SACP,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CAA8C,KAAE,EAAQ,QAAe;;SACnE;;OAEL,EAAQ,eACP,kBAAC,KAAD;QAAG,WAAU;kBAAoC,EAAQ;QAAgB,CAAA;OAG3E,kBAAC,MAAD;QAAI,WAAU;kBAAd;SACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAE,gCAAgC,SAAS;UACzC,CAAA,EACL,kBAAC,MAAD;UAAI,WAAU;oBAAwC,EAAQ,UAAU;UAAS,CAAA,CAC7E,EAAA,CAAA;SACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAE,+BAA+B,UAAU;UACzC,CAAA,EACL,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAW,EAAQ,UAAU;UAC3B,CAAA,CACD,EAAA,CAAA;SACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAE,+BAA+B,UAAU;UACzC,CAAA,EACL,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAW,EAAQ,UAAU;UAC3B,CAAA,CACD,EAAA,CAAA;SACH;;OAEJ,EAAQ,aAAa,SAAS,KAC7B,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,sCAAsC,eAAe;SACrD,CAAA,EACL,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAQ,aAAa,KAAK,MACzB,kBAAC,QAAD;UAEE,WAAU;oBAET;UACI,EAJA,EAIA,CACP;SACE,CAAA,CACF;;OAGP,EAAQ,KAAK,SAAS,KACrB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,4BAA4B,OAAO;SACnC,CAAA,EACL,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAQ,KAAK,KAAK,MACjB,kBAAC,QAAD;UAEE,WAAU;oBAET;UACI,EAJA,EAIA,CACP;SACE,CAAA,CACF;;OAEE;;KAGX,EAAQ,gBAAgB,QACvB,kBAAC,GAAD;MAAW,WAAU;gBAArB,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,sCAAsC,gBAAgB;QACtD,CAAA,EACL,kBAAC,UAAD;QACE,MAAK;QACL,SAAS;QACT,cAAY,EAAE,4BAA4B,OAAO;QACjD,WAAU;kBAET,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAO,WAAU,wCAAyC,CAAA,EACzD,EAAE,8BAA8B,SAAS,CACzC,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA,EAC/B,EAAE,4BAA4B,OAAO,CACrC,EAAA,CAAA;QAEE,CAAA,CACL;UACN,kBAAC,OAAD;OAAK,WAAU;iBACZ,KAAK,UAAU,EAAQ,cAAc,MAAM,EAAE;OAC1C,CAAA,CACI;;KAId,kBAAC,WAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAE,qCAAqC,cAAc;MACnD,CAAA,EACJ,EAAQ,eAAe,EAAQ,YAAY,SAAS,IACnD,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;QAAI,WAAU;kBAAd;SACE,kBAAC,MAAD;UAAI,OAAM;UAAM,WAAU;oBACvB,EAAE,kCAAkC,OAAO;UACzC,CAAA;SACL,kBAAC,MAAD;UAAI,OAAM;UAAM,WAAU;oBACvB,EAAE,iCAAiC,SAAS;UAC1C,CAAA;SACL,kBAAC,MAAD;UAAI,OAAM;UAAM,WAAU;oBACvB,EAAE,gCAAgC,SAAS;UACzC,CAAA;SACL,kBAAC,MAAD;UAAI,OAAM;UAAM,WAAU;oBACvB,EAAE,mCAAmC,YAAY;UAC/C,CAAA;SACF;WACC,CAAA,EACR,kBAAC,SAAD;QAAO,WAAU;kBACd,EAAQ,YAAY,KAAK,MACxB,kBAAC,MAAD;SAEE,MAAK;SACL,UAAU;SACV,eAAe,EAAW,gBAAgB,EAAK,KAAK;SACpD,YAAY,MAAM;AAChB,WAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,gBAAgB,EAClB,EAAW,gBAAgB,EAAK,KAAK;;SAGzC,WAAU;mBAXZ;UAaE,kBAAC,MAAD;WAAI,WAAU;qBACZ,kBAAC,QAAD;YAAM,WAAU;sBAAhB,CACE,kBAAC,GAAD,EAAO,WAAU,wCAAyC,CAAA,EAC1D,kBAAC,QAAD;aAAM,WAAU;uBACb,EAAK;aACD,CAAA,CACF;;WACJ,CAAA;UACL,kBAAC,MAAD;WAAI,WAAU;qBAAiC,EAAK,UAAU;WAAS,CAAA;UACvE,kBAAC,MAAD;WAAI,WAAU;qBACZ,kBAAC,GAAD,EAAa,QAAQ,EAAK,QAAU,CAAA;WACjC,CAAA;UACL,kBAAC,MAAD;WAAI,WAAU;qBACX,EAAK;WACH,CAAA;UACF;WA3BE,EAAK,GA2BP,CACL;QACI,CAAA,CACF;;MACJ,CAAA,GAEN,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAE,uCAAuC,uCAAuC;MAC/E,CAAA,CAEE,EAAA,CAAA;KACN;;GAEE,CAAA,EAEZ,kBAAC,GAAD;GACE,MAAM;GACN,cAAc;GACd,OAAO,EAAE,sCAAsC,wBAAwB;GACvE,aAAa,EACX,uCACA,qIACD;GACD,cAAc,EAAE,+BAA+B,UAAU;GACzD,aAAa,EAAE,8BAA8B,SAAS;GACtD,WAAW;GACX,WAAW,EAAQ;GACnB,MAAK;GACL,CAAA,CACS"}