@burdenoff/microfe-bigconsole 2026.731.6 → 2026.731.7

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.
@@ -0,0 +1,308 @@
1
+ import e from "../../../hooks/useDashboardEmbedPolicy.js";
2
+ import { useEffect as t, useMemo as n, useState as r } from "react";
3
+ import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
4
+ //#region src/bigconsole/components/dashboard/ShareDialog/EmbedTab.tsx
5
+ function s(e) {
6
+ let t = e.trim();
7
+ if (!t) return null;
8
+ try {
9
+ let e = new URL(t);
10
+ return e.protocol !== "https:" || e.pathname !== "" && e.pathname !== "/" || e.search || e.hash ? null : e.origin;
11
+ } catch {
12
+ return null;
13
+ }
14
+ }
15
+ function c({ dashboardId: c, colors: l }) {
16
+ let { policy: u, secret: d, loading: f, error: p, fetchPolicy: m, publishToWeb: h, setAllowedOrigins: g, rotateKey: _, unpublish: v } = e(), [y, b] = r(""), [x, S] = r([]), [C, w] = r(!1), [T, E] = r(!1), [D, O] = r(null);
17
+ t(() => {
18
+ c && m(c);
19
+ }, [c, m]);
20
+ let k = u?.status === "ACTIVE", A = k ? u?.allowedParentOrigins ?? [] : x, j = n(() => d?.iframeSnippet ? d.iframeSnippet : null, [d]), M = () => {
21
+ O(null);
22
+ let e = s(y);
23
+ if (!e) {
24
+ O("Enter a valid https origin, e.g. https://example.com");
25
+ return;
26
+ }
27
+ if (A.includes(e)) {
28
+ b("");
29
+ return;
30
+ }
31
+ k && u ? g(u.id, [...A, e]) : S((t) => [...t, e]), b("");
32
+ }, N = (e) => {
33
+ k && u ? g(u.id, A.filter((t) => t !== e)) : S((t) => t.filter((t) => t !== e));
34
+ }, P = async () => {
35
+ if (O(null), x.length === 0) {
36
+ O("Add at least one allowed website domain before publishing.");
37
+ return;
38
+ }
39
+ if (!C) {
40
+ O("Please confirm this dashboard is safe to be public.");
41
+ return;
42
+ }
43
+ await h(c, x, !0);
44
+ }, F = async (e) => {
45
+ try {
46
+ await navigator.clipboard.writeText(e), E(!0), setTimeout(() => E(!1), 1500);
47
+ } catch {
48
+ O("Could not copy — select and copy manually.");
49
+ }
50
+ }, I = {
51
+ padding: "8px 14px",
52
+ borderRadius: "8px",
53
+ border: "none",
54
+ background: l.actionPrimaryBg,
55
+ color: "#fff",
56
+ fontSize: "13px",
57
+ fontWeight: 600,
58
+ cursor: "pointer"
59
+ }, L = {
60
+ padding: "8px 14px",
61
+ borderRadius: "8px",
62
+ border: `1px solid ${l.borderDefault}`,
63
+ background: "transparent",
64
+ color: l.textPrimary,
65
+ fontSize: "13px",
66
+ cursor: "pointer"
67
+ }, R = {
68
+ flex: 1,
69
+ padding: "8px 10px",
70
+ borderRadius: "8px",
71
+ border: `1px solid ${l.borderDefault}`,
72
+ background: l.bgSecondary,
73
+ color: l.textPrimary,
74
+ fontSize: "13px"
75
+ };
76
+ return /* @__PURE__ */ o("div", {
77
+ style: { padding: "20px 24px" },
78
+ children: [
79
+ /* @__PURE__ */ o("div", {
80
+ style: {
81
+ display: "flex",
82
+ alignItems: "center",
83
+ justifyContent: "space-between",
84
+ padding: "12px 14px",
85
+ borderRadius: "10px",
86
+ background: l.bgSecondary,
87
+ marginBottom: "16px"
88
+ },
89
+ children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("div", {
90
+ style: {
91
+ fontSize: "14px",
92
+ fontWeight: 600,
93
+ color: l.textPrimary
94
+ },
95
+ children: "Publish to the web"
96
+ }), /* @__PURE__ */ a("div", {
97
+ style: {
98
+ fontSize: "12px",
99
+ color: l.textSecondary,
100
+ marginTop: "2px"
101
+ },
102
+ children: k ? "This dashboard is live. Anyone with the link on an allowed website sees its live data." : "Embed this dashboard on your website. Viewers see live data — no login required."
103
+ })] }), /* @__PURE__ */ a("span", {
104
+ style: {
105
+ fontSize: "11px",
106
+ fontWeight: 700,
107
+ padding: "3px 8px",
108
+ borderRadius: "999px",
109
+ color: "#fff",
110
+ background: k ? l.statusSuccessBg : l.textTertiary
111
+ },
112
+ children: k ? "PUBLISHED" : "PRIVATE"
113
+ })]
114
+ }),
115
+ /* @__PURE__ */ o("div", {
116
+ style: { marginBottom: "16px" },
117
+ children: [
118
+ /* @__PURE__ */ a("div", {
119
+ style: {
120
+ fontSize: "12px",
121
+ fontWeight: 600,
122
+ color: l.textSecondary,
123
+ marginBottom: "6px"
124
+ },
125
+ children: "Allowed website domains"
126
+ }),
127
+ /* @__PURE__ */ o("div", {
128
+ style: {
129
+ display: "flex",
130
+ gap: "8px",
131
+ marginBottom: "8px"
132
+ },
133
+ children: [/* @__PURE__ */ a("input", {
134
+ style: R,
135
+ placeholder: "https://yoursite.com",
136
+ value: y,
137
+ onChange: (e) => b(e.target.value),
138
+ onKeyDown: (e) => {
139
+ e.key === "Enter" && M();
140
+ }
141
+ }), /* @__PURE__ */ a("button", {
142
+ style: L,
143
+ onClick: M,
144
+ type: "button",
145
+ children: "Add"
146
+ })]
147
+ }),
148
+ A.length === 0 ? /* @__PURE__ */ a("div", {
149
+ style: {
150
+ fontSize: "12px",
151
+ color: l.textTertiary
152
+ },
153
+ children: "No domains yet. Only listed https domains may frame this dashboard."
154
+ }) : /* @__PURE__ */ a("div", {
155
+ style: {
156
+ display: "flex",
157
+ flexDirection: "column",
158
+ gap: "6px"
159
+ },
160
+ children: A.map((e) => /* @__PURE__ */ o("div", {
161
+ style: {
162
+ display: "flex",
163
+ alignItems: "center",
164
+ justifyContent: "space-between",
165
+ padding: "6px 10px",
166
+ borderRadius: "8px",
167
+ background: l.bgTertiary
168
+ },
169
+ children: [/* @__PURE__ */ a("span", {
170
+ style: {
171
+ fontSize: "13px",
172
+ color: l.textPrimary
173
+ },
174
+ children: e
175
+ }), /* @__PURE__ */ a("button", {
176
+ style: {
177
+ ...L,
178
+ padding: "2px 8px",
179
+ color: l.statusErrorText
180
+ },
181
+ onClick: () => N(e),
182
+ type: "button",
183
+ children: "Remove"
184
+ })]
185
+ }, e))
186
+ })
187
+ ]
188
+ }),
189
+ !k && /* @__PURE__ */ o("div", {
190
+ style: { marginBottom: "8px" },
191
+ children: [/* @__PURE__ */ o("label", {
192
+ style: {
193
+ display: "flex",
194
+ gap: "8px",
195
+ alignItems: "flex-start",
196
+ marginBottom: "12px"
197
+ },
198
+ children: [/* @__PURE__ */ a("input", {
199
+ type: "checkbox",
200
+ checked: C,
201
+ onChange: (e) => w(e.target.checked)
202
+ }), /* @__PURE__ */ a("span", {
203
+ style: {
204
+ fontSize: "12px",
205
+ color: l.textSecondary
206
+ },
207
+ children: "I understand this makes the dashboard's live data visible to anyone with the link, and I confirm it is safe to be public."
208
+ })]
209
+ }), /* @__PURE__ */ a("button", {
210
+ style: I,
211
+ onClick: P,
212
+ disabled: f,
213
+ type: "button",
214
+ children: f ? "Publishing…" : "Publish to web"
215
+ })]
216
+ }),
217
+ k && /* @__PURE__ */ o(i, { children: [j ? /* @__PURE__ */ o("div", {
218
+ style: { marginBottom: "16px" },
219
+ children: [
220
+ /* @__PURE__ */ a("div", {
221
+ style: {
222
+ fontSize: "12px",
223
+ fontWeight: 600,
224
+ color: l.textSecondary,
225
+ marginBottom: "6px"
226
+ },
227
+ children: "Embed snippet"
228
+ }),
229
+ /* @__PURE__ */ a("textarea", {
230
+ readOnly: !0,
231
+ value: j,
232
+ style: {
233
+ width: "100%",
234
+ minHeight: "96px",
235
+ padding: "10px",
236
+ borderRadius: "8px",
237
+ border: `1px solid ${l.borderDefault}`,
238
+ background: l.bgSecondary,
239
+ color: l.textPrimary,
240
+ fontFamily: "monospace",
241
+ fontSize: "12px",
242
+ resize: "vertical"
243
+ }
244
+ }),
245
+ /* @__PURE__ */ a("button", {
246
+ style: {
247
+ ...L,
248
+ marginTop: "8px"
249
+ },
250
+ onClick: () => F(j),
251
+ type: "button",
252
+ children: T ? "Copied ✓" : "Copy snippet"
253
+ })
254
+ ]
255
+ }) : /* @__PURE__ */ o("div", {
256
+ style: {
257
+ fontSize: "12px",
258
+ color: l.textSecondary,
259
+ background: l.bgSecondary,
260
+ borderRadius: "8px",
261
+ padding: "10px 12px",
262
+ marginBottom: "16px"
263
+ },
264
+ children: [
265
+ "The embed link is already active. For security the snippet (which contains the secret key) is only shown once at publish time — use ",
266
+ /* @__PURE__ */ a("strong", { children: "Rotate link" }),
267
+ " to generate a fresh snippet."
268
+ ]
269
+ }), /* @__PURE__ */ o("div", {
270
+ style: {
271
+ display: "flex",
272
+ gap: "8px"
273
+ },
274
+ children: [/* @__PURE__ */ a("button", {
275
+ style: L,
276
+ onClick: () => u && _(u.id),
277
+ disabled: f,
278
+ type: "button",
279
+ children: "Rotate link"
280
+ }), /* @__PURE__ */ a("button", {
281
+ style: {
282
+ ...L,
283
+ color: l.statusErrorText,
284
+ borderColor: l.statusErrorText
285
+ },
286
+ onClick: () => {
287
+ u && window.confirm("Unpublish this dashboard? The embed will stop working immediately for anyone using the link.") && v(u.id);
288
+ },
289
+ disabled: f,
290
+ type: "button",
291
+ children: "Unpublish"
292
+ })]
293
+ })] }),
294
+ (D || p) && /* @__PURE__ */ a("div", {
295
+ style: {
296
+ marginTop: "12px",
297
+ fontSize: "12px",
298
+ color: l.statusErrorText
299
+ },
300
+ children: D ?? p?.message
301
+ })
302
+ ]
303
+ });
304
+ }
305
+ //#endregion
306
+ export { c as default };
307
+
308
+ //# sourceMappingURL=EmbedTab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmbedTab.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/ShareDialog/EmbedTab.tsx"],"sourcesContent":["/**\n * EmbedTab — \"Publish to web\" section of the dashboard Share dialog.\n *\n * Owner-facing UI to publish a dashboard as an anonymous-link embed serving LIVE\n * data, manage the allowed parent domains, copy the iframe snippet, rotate the\n * link key, and unpublish. Backed by {@link useDashboardEmbedPolicy}; all\n * mutations are gateway-enforced by `@rbac(manage_embed)` (owner-only).\n *\n * Self-contained (inline styles driven by the dialog's `colors`) so it slots into\n * the existing hand-styled ShareDialog without a broader refactor.\n */\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { useDashboardEmbedPolicy } from '../../../hooks/useDashboardEmbedPolicy';\n\ninterface DialogColors {\n bgPrimary: string;\n bgSecondary: string;\n bgTertiary: string;\n textPrimary: string;\n textSecondary: string;\n textTertiary: string;\n borderDefault: string;\n actionPrimaryBg: string;\n actionPrimaryBgHover: string;\n statusSuccessBg: string;\n statusErrorText: string;\n}\n\nexport interface EmbedTabProps {\n dashboardId: string;\n colors: DialogColors;\n}\n\n/** Validate an exact https origin (matches the backend allowlist rules). */\nfunction normalizeOrigin(raw: string): string | null {\n const trimmed = raw.trim();\n if (!trimmed) return null;\n try {\n const url = new URL(trimmed);\n if (url.protocol !== 'https:') return null;\n if ((url.pathname !== '' && url.pathname !== '/') || url.search || url.hash) return null;\n return url.origin;\n } catch {\n return null;\n }\n}\n\nexport function EmbedTab({ dashboardId, colors }: EmbedTabProps) {\n const { policy, secret, loading, error, fetchPolicy, publishToWeb, setAllowedOrigins, rotateKey, unpublish } =\n useDashboardEmbedPolicy();\n\n const [domainInput, setDomainInput] = useState('');\n const [pendingDomains, setPendingDomains] = useState<string[]>([]);\n const [attested, setAttested] = useState(false);\n const [copied, setCopied] = useState(false);\n const [localError, setLocalError] = useState<string | null>(null);\n\n useEffect(() => {\n if (dashboardId) fetchPolicy(dashboardId);\n }, [dashboardId, fetchPolicy]);\n\n const isPublished = policy?.status === 'ACTIVE';\n const domains = isPublished ? (policy?.allowedParentOrigins ?? []) : pendingDomains;\n\n // The copyable iframe snippet: from the one-time secret if present (fresh\n // publish/rotate), else reconstructed from the locator for an already-published\n // policy (the fragment key is only available in the one-time secret).\n const iframeSnippet = useMemo(() => {\n if (secret?.iframeSnippet) return secret.iframeSnippet;\n return null;\n }, [secret]);\n\n const addDomain = () => {\n setLocalError(null);\n const origin = normalizeOrigin(domainInput);\n if (!origin) {\n setLocalError('Enter a valid https origin, e.g. https://example.com');\n return;\n }\n if (domains.includes(origin)) {\n setDomainInput('');\n return;\n }\n if (isPublished && policy) {\n void setAllowedOrigins(policy.id, [...domains, origin]);\n } else {\n setPendingDomains((prev) => [...prev, origin]);\n }\n setDomainInput('');\n };\n\n const removeDomain = (origin: string) => {\n if (isPublished && policy) {\n void setAllowedOrigins(\n policy.id,\n domains.filter((d) => d !== origin)\n );\n } else {\n setPendingDomains((prev) => prev.filter((d) => d !== origin));\n }\n };\n\n const handlePublish = async () => {\n setLocalError(null);\n if (pendingDomains.length === 0) {\n setLocalError('Add at least one allowed website domain before publishing.');\n return;\n }\n if (!attested) {\n setLocalError('Please confirm this dashboard is safe to be public.');\n return;\n }\n await publishToWeb(dashboardId, pendingDomains, true);\n };\n\n const handleCopy = async (text: string) => {\n try {\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n } catch {\n setLocalError('Could not copy — select and copy manually.');\n }\n };\n\n const primaryBtn: React.CSSProperties = {\n padding: '8px 14px',\n borderRadius: '8px',\n border: 'none',\n background: colors.actionPrimaryBg,\n color: '#fff',\n fontSize: '13px',\n fontWeight: 600,\n cursor: 'pointer',\n };\n const ghostBtn: React.CSSProperties = {\n padding: '8px 14px',\n borderRadius: '8px',\n border: `1px solid ${colors.borderDefault}`,\n background: 'transparent',\n color: colors.textPrimary,\n fontSize: '13px',\n cursor: 'pointer',\n };\n const inputStyle: React.CSSProperties = {\n flex: 1,\n padding: '8px 10px',\n borderRadius: '8px',\n border: `1px solid ${colors.borderDefault}`,\n background: colors.bgSecondary,\n color: colors.textPrimary,\n fontSize: '13px',\n };\n\n return (\n <div style={{ padding: '20px 24px' }}>\n {/* Status banner */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '12px 14px',\n borderRadius: '10px',\n background: colors.bgSecondary,\n marginBottom: '16px',\n }}\n >\n <div>\n <div style={{ fontSize: '14px', fontWeight: 600, color: colors.textPrimary }}>Publish to the web</div>\n <div style={{ fontSize: '12px', color: colors.textSecondary, marginTop: '2px' }}>\n {isPublished\n ? 'This dashboard is live. Anyone with the link on an allowed website sees its live data.'\n : 'Embed this dashboard on your website. Viewers see live data — no login required.'}\n </div>\n </div>\n <span\n style={{\n fontSize: '11px',\n fontWeight: 700,\n padding: '3px 8px',\n borderRadius: '999px',\n color: '#fff',\n background: isPublished ? colors.statusSuccessBg : colors.textTertiary,\n }}\n >\n {isPublished ? 'PUBLISHED' : 'PRIVATE'}\n </span>\n </div>\n\n {/* Allowed domains */}\n <div style={{ marginBottom: '16px' }}>\n <div style={{ fontSize: '12px', fontWeight: 600, color: colors.textSecondary, marginBottom: '6px' }}>\n Allowed website domains\n </div>\n <div style={{ display: 'flex', gap: '8px', marginBottom: '8px' }}>\n <input\n style={inputStyle}\n placeholder=\"https://yoursite.com\"\n value={domainInput}\n onChange={(e) => setDomainInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') addDomain();\n }}\n />\n <button style={ghostBtn} onClick={addDomain} type=\"button\">\n Add\n </button>\n </div>\n {domains.length === 0 ? (\n <div style={{ fontSize: '12px', color: colors.textTertiary }}>\n No domains yet. Only listed https domains may frame this dashboard.\n </div>\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\n {domains.map((d) => (\n <div\n key={d}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '6px 10px',\n borderRadius: '8px',\n background: colors.bgTertiary,\n }}\n >\n <span style={{ fontSize: '13px', color: colors.textPrimary }}>{d}</span>\n <button\n style={{ ...ghostBtn, padding: '2px 8px', color: colors.statusErrorText }}\n onClick={() => removeDomain(d)}\n type=\"button\"\n >\n Remove\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Publish CTA (unpublished) */}\n {!isPublished && (\n <div style={{ marginBottom: '8px' }}>\n <label style={{ display: 'flex', gap: '8px', alignItems: 'flex-start', marginBottom: '12px' }}>\n <input type=\"checkbox\" checked={attested} onChange={(e) => setAttested(e.target.checked)} />\n <span style={{ fontSize: '12px', color: colors.textSecondary }}>\n I understand this makes the dashboard&apos;s live data visible to anyone with the link, and I confirm it\n is safe to be public.\n </span>\n </label>\n <button style={primaryBtn} onClick={handlePublish} disabled={loading} type=\"button\">\n {loading ? 'Publishing…' : 'Publish to web'}\n </button>\n </div>\n )}\n\n {/* Embed snippet + management (published) */}\n {isPublished && (\n <>\n {iframeSnippet ? (\n <div style={{ marginBottom: '16px' }}>\n <div style={{ fontSize: '12px', fontWeight: 600, color: colors.textSecondary, marginBottom: '6px' }}>\n Embed snippet\n </div>\n <textarea\n readOnly\n value={iframeSnippet}\n style={{\n width: '100%',\n minHeight: '96px',\n padding: '10px',\n borderRadius: '8px',\n border: `1px solid ${colors.borderDefault}`,\n background: colors.bgSecondary,\n color: colors.textPrimary,\n fontFamily: 'monospace',\n fontSize: '12px',\n resize: 'vertical',\n }}\n />\n <button style={{ ...ghostBtn, marginTop: '8px' }} onClick={() => handleCopy(iframeSnippet)} type=\"button\">\n {copied ? 'Copied ✓' : 'Copy snippet'}\n </button>\n </div>\n ) : (\n <div\n style={{\n fontSize: '12px',\n color: colors.textSecondary,\n background: colors.bgSecondary,\n borderRadius: '8px',\n padding: '10px 12px',\n marginBottom: '16px',\n }}\n >\n The embed link is already active. For security the snippet (which contains the secret key) is only shown\n once at publish time — use <strong>Rotate link</strong> to generate a fresh snippet.\n </div>\n )}\n\n <div style={{ display: 'flex', gap: '8px' }}>\n <button style={ghostBtn} onClick={() => policy && rotateKey(policy.id)} disabled={loading} type=\"button\">\n Rotate link\n </button>\n <button\n style={{ ...ghostBtn, color: colors.statusErrorText, borderColor: colors.statusErrorText }}\n onClick={() => {\n if (\n policy &&\n window.confirm(\n 'Unpublish this dashboard? The embed will stop working immediately for anyone using the link.'\n )\n ) {\n void unpublish(policy.id);\n }\n }}\n disabled={loading}\n type=\"button\"\n >\n Unpublish\n </button>\n </div>\n </>\n )}\n\n {(localError || error) && (\n <div style={{ marginTop: '12px', fontSize: '12px', color: colors.statusErrorText }}>\n {localError ?? error?.message}\n </div>\n )}\n </div>\n );\n}\n\nexport default EmbedTab;\n"],"mappings":";;;;AAmCA,SAAS,EAAgB,GAA4B;CACnD,IAAM,IAAU,EAAI,MAAM;AAC1B,KAAI,CAAC,EAAS,QAAO;AACrB,KAAI;EACF,IAAM,IAAM,IAAI,IAAI,EAAQ;AAG5B,SAFI,EAAI,aAAa,YAChB,EAAI,aAAa,MAAM,EAAI,aAAa,OAAQ,EAAI,UAAU,EAAI,OAAa,OAC7E,EAAI;SACL;AACN,SAAO;;;AAIX,SAAgB,EAAS,EAAE,gBAAa,aAAyB;CAC/D,IAAM,EAAE,WAAQ,WAAQ,YAAS,UAAO,gBAAa,iBAAc,sBAAmB,cAAW,iBAC/F,GAAyB,EAErB,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAgB,KAAqB,EAAmB,EAAE,CAAC,EAC5D,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAY,KAAiB,EAAwB,KAAK;AAEjE,SAAgB;AACd,EAAI,KAAa,EAAY,EAAY;IACxC,CAAC,GAAa,EAAY,CAAC;CAE9B,IAAM,IAAc,GAAQ,WAAW,UACjC,IAAU,IAAe,GAAQ,wBAAwB,EAAE,GAAI,GAK/D,IAAgB,QAChB,GAAQ,gBAAsB,EAAO,gBAClC,MACN,CAAC,EAAO,CAAC,EAEN,UAAkB;AACtB,IAAc,KAAK;EACnB,IAAM,IAAS,EAAgB,EAAY;AAC3C,MAAI,CAAC,GAAQ;AACX,KAAc,uDAAuD;AACrE;;AAEF,MAAI,EAAQ,SAAS,EAAO,EAAE;AAC5B,KAAe,GAAG;AAClB;;AAOF,EALI,KAAe,IACZ,EAAkB,EAAO,IAAI,CAAC,GAAG,GAAS,EAAO,CAAC,GAEvD,GAAmB,MAAS,CAAC,GAAG,GAAM,EAAO,CAAC,EAEhD,EAAe,GAAG;IAGd,KAAgB,MAAmB;AACvC,EAAI,KAAe,IACZ,EACH,EAAO,IACP,EAAQ,QAAQ,MAAM,MAAM,EAAO,CACpC,GAED,GAAmB,MAAS,EAAK,QAAQ,MAAM,MAAM,EAAO,CAAC;IAI3D,IAAgB,YAAY;AAEhC,MADA,EAAc,KAAK,EACf,EAAe,WAAW,GAAG;AAC/B,KAAc,6DAA6D;AAC3E;;AAEF,MAAI,CAAC,GAAU;AACb,KAAc,sDAAsD;AACpE;;AAEF,QAAM,EAAa,GAAa,GAAgB,GAAK;IAGjD,IAAa,OAAO,MAAiB;AACzC,MAAI;AAGF,GAFA,MAAM,UAAU,UAAU,UAAU,EAAK,EACzC,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,KAAK;UAClC;AACN,KAAc,6CAA6C;;IAIzD,IAAkC;EACtC,SAAS;EACT,cAAc;EACd,QAAQ;EACR,YAAY,EAAO;EACnB,OAAO;EACP,UAAU;EACV,YAAY;EACZ,QAAQ;EACT,EACK,IAAgC;EACpC,SAAS;EACT,cAAc;EACd,QAAQ,aAAa,EAAO;EAC5B,YAAY;EACZ,OAAO,EAAO;EACd,UAAU;EACV,QAAQ;EACT,EACK,IAAkC;EACtC,MAAM;EACN,SAAS;EACT,cAAc;EACd,QAAQ,aAAa,EAAO;EAC5B,YAAY,EAAO;EACnB,OAAO,EAAO;EACd,UAAU;EACX;AAED,QACE,kBAAC,OAAD;EAAK,OAAO,EAAE,SAAS,aAAa;YAApC;GAEE,kBAAC,OAAD;IACE,OAAO;KACL,SAAS;KACT,YAAY;KACZ,gBAAgB;KAChB,SAAS;KACT,cAAc;KACd,YAAY,EAAO;KACnB,cAAc;KACf;cATH,CAWE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;KAAK,OAAO;MAAE,UAAU;MAAQ,YAAY;MAAK,OAAO,EAAO;MAAa;eAAE;KAAwB,CAAA,EACtG,kBAAC,OAAD;KAAK,OAAO;MAAE,UAAU;MAAQ,OAAO,EAAO;MAAe,WAAW;MAAO;eAC5E,IACG,2FACA;KACA,CAAA,CACF,EAAA,CAAA,EACN,kBAAC,QAAD;KACE,OAAO;MACL,UAAU;MACV,YAAY;MACZ,SAAS;MACT,cAAc;MACd,OAAO;MACP,YAAY,IAAc,EAAO,kBAAkB,EAAO;MAC3D;eAEA,IAAc,cAAc;KACxB,CAAA,CACH;;GAGN,kBAAC,OAAD;IAAK,OAAO,EAAE,cAAc,QAAQ;cAApC;KACE,kBAAC,OAAD;MAAK,OAAO;OAAE,UAAU;OAAQ,YAAY;OAAK,OAAO,EAAO;OAAe,cAAc;OAAO;gBAAE;MAE/F,CAAA;KACN,kBAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,KAAK;OAAO,cAAc;OAAO;gBAAhE,CACE,kBAAC,SAAD;OACE,OAAO;OACP,aAAY;OACZ,OAAO;OACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;OAC/C,YAAY,MAAM;AAChB,QAAI,EAAE,QAAQ,WAAS,GAAW;;OAEpC,CAAA,EACF,kBAAC,UAAD;OAAQ,OAAO;OAAU,SAAS;OAAW,MAAK;iBAAS;OAElD,CAAA,CACL;;KACL,EAAQ,WAAW,IAClB,kBAAC,OAAD;MAAK,OAAO;OAAE,UAAU;OAAQ,OAAO,EAAO;OAAc;gBAAE;MAExD,CAAA,GAEN,kBAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,eAAe;OAAU,KAAK;OAAO;gBACjE,EAAQ,KAAK,MACZ,kBAAC,OAAD;OAEE,OAAO;QACL,SAAS;QACT,YAAY;QACZ,gBAAgB;QAChB,SAAS;QACT,cAAc;QACd,YAAY,EAAO;QACpB;iBATH,CAWE,kBAAC,QAAD;QAAM,OAAO;SAAE,UAAU;SAAQ,OAAO,EAAO;SAAa;kBAAG;QAAS,CAAA,EACxE,kBAAC,UAAD;QACE,OAAO;SAAE,GAAG;SAAU,SAAS;SAAW,OAAO,EAAO;SAAiB;QACzE,eAAe,EAAa,EAAE;QAC9B,MAAK;kBACN;QAEQ,CAAA,CACL;SAlBC,EAkBD,CACN;MACE,CAAA;KAEJ;;GAGL,CAAC,KACA,kBAAC,OAAD;IAAK,OAAO,EAAE,cAAc,OAAO;cAAnC,CACE,kBAAC,SAAD;KAAO,OAAO;MAAE,SAAS;MAAQ,KAAK;MAAO,YAAY;MAAc,cAAc;MAAQ;eAA7F,CACE,kBAAC,SAAD;MAAO,MAAK;MAAW,SAAS;MAAU,WAAW,MAAM,EAAY,EAAE,OAAO,QAAQ;MAAI,CAAA,EAC5F,kBAAC,QAAD;MAAM,OAAO;OAAE,UAAU;OAAQ,OAAO,EAAO;OAAe;gBAAE;MAGzD,CAAA,CACD;QACR,kBAAC,UAAD;KAAQ,OAAO;KAAY,SAAS;KAAe,UAAU;KAAS,MAAK;eACxE,IAAU,gBAAgB;KACpB,CAAA,CACL;;GAIP,KACC,kBAAA,GAAA,EAAA,UAAA,CACG,IACC,kBAAC,OAAD;IAAK,OAAO,EAAE,cAAc,QAAQ;cAApC;KACE,kBAAC,OAAD;MAAK,OAAO;OAAE,UAAU;OAAQ,YAAY;OAAK,OAAO,EAAO;OAAe,cAAc;OAAO;gBAAE;MAE/F,CAAA;KACN,kBAAC,YAAD;MACE,UAAA;MACA,OAAO;MACP,OAAO;OACL,OAAO;OACP,WAAW;OACX,SAAS;OACT,cAAc;OACd,QAAQ,aAAa,EAAO;OAC5B,YAAY,EAAO;OACnB,OAAO,EAAO;OACd,YAAY;OACZ,UAAU;OACV,QAAQ;OACT;MACD,CAAA;KACF,kBAAC,UAAD;MAAQ,OAAO;OAAE,GAAG;OAAU,WAAW;OAAO;MAAE,eAAe,EAAW,EAAc;MAAE,MAAK;gBAC9F,IAAS,aAAa;MAChB,CAAA;KACL;QAEN,kBAAC,OAAD;IACE,OAAO;KACL,UAAU;KACV,OAAO,EAAO;KACd,YAAY,EAAO;KACnB,cAAc;KACd,SAAS;KACT,cAAc;KACf;cARH;KASC;KAE4B,kBAAC,UAAD,EAAA,UAAQ,eAAoB,CAAA;;KACnD;OAGR,kBAAC,OAAD;IAAK,OAAO;KAAE,SAAS;KAAQ,KAAK;KAAO;cAA3C,CACE,kBAAC,UAAD;KAAQ,OAAO;KAAU,eAAe,KAAU,EAAU,EAAO,GAAG;KAAE,UAAU;KAAS,MAAK;eAAS;KAEhG,CAAA,EACT,kBAAC,UAAD;KACE,OAAO;MAAE,GAAG;MAAU,OAAO,EAAO;MAAiB,aAAa,EAAO;MAAiB;KAC1F,eAAe;AACb,MACE,KACA,OAAO,QACL,+FACD,IAEI,EAAU,EAAO,GAAG;;KAG7B,UAAU;KACV,MAAK;eACN;KAEQ,CAAA,CACL;MACL,EAAA,CAAA;IAGH,KAAc,MACd,kBAAC,OAAD;IAAK,OAAO;KAAE,WAAW;KAAQ,UAAU;KAAQ,OAAO,EAAO;KAAiB;cAC/E,KAAc,GAAO;IAClB,CAAA;GAEJ"}