smartsell-ui-kit 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,29 +5,33 @@
5
5
  It is designed for tenant developers who should not need to know how the core app is implemented.
6
6
  The package stays on the public contract surface:
7
7
 
8
- - theme-aware components powered by `smartsell-sales-sdk`
8
+ - theme-aware components powered by `smartsell-theme`
9
9
  - inline-style primitives that do not depend on private app CSS files
10
10
  - a composable modal helper with predictable slot ids for `header`, `body`, and `footer`
11
11
 
12
12
  ## Installation
13
13
 
14
14
  ```bash
15
- npm install react smartsell-sales-sdk smartsell-ui-kit
15
+ npm install react smartsell-theme smartsell-ui-kit
16
16
  ```
17
17
 
18
+ If you want to connect `ComposableModal` to SmartSell slot overrides, install `smartsell-sales-sdk` as well.
19
+
18
20
  ## Basic button and card
19
21
 
20
22
  ```tsx
23
+ import { ThemeProvider } from 'smartsell-theme';
21
24
  import { Button, Card } from 'smartsell-ui-kit';
22
- import type { ModulePageProps } from 'smartsell-sales-sdk';
23
25
 
24
- export default function ExamplePage({ sdk }: ModulePageProps) {
26
+ export default function ExamplePage() {
25
27
  return (
26
- <Card sdk={sdk} title="Example" eyebrow="UI kit">
27
- <Button sdk={sdk} onClick={() => sdk.navigation.goBack()}>
28
- Go back
29
- </Button>
30
- </Card>
28
+ <ThemeProvider>
29
+ <Card title="Example" eyebrow="UI kit">
30
+ <Button onClick={() => window.history.back()}>
31
+ Go back
32
+ </Button>
33
+ </Card>
34
+ </ThemeProvider>
31
35
  );
32
36
  }
33
37
  ```
@@ -37,22 +41,30 @@ export default function ExamplePage({ sdk }: ModulePageProps) {
37
41
  Use `ComposableModal` when you want the page to keep modal state while tenants customize visual sections independently.
38
42
 
39
43
  ```tsx
44
+ import { SlotRenderer, type ModulePageProps, type SlotComponentProps } from 'smartsell-sales-sdk';
40
45
  import { ComposableModal, createModalSlotIds } from 'smartsell-ui-kit';
41
46
 
42
47
  const slotIds = createModalSlotIds('order-review');
43
48
 
44
- <ComposableModal
45
- sdk={sdk}
46
- isOpen={isOpen}
47
- onClose={() => setIsOpen(false)}
48
- onConfirm={submitOrder}
49
- title="Order review"
50
- description="Validate the order before sending it."
51
- slotBaseId="order-review"
52
- payload={{ orderNumber: 'SO-1001', total: 421.9 }}
53
- >
54
- <div>Default modal body</div>
55
- </ComposableModal>
49
+ export default function ExamplePage({ sdk }: ModulePageProps) {
50
+ return (
51
+ <ComposableModal
52
+ isOpen={isOpen}
53
+ onClose={() => setIsOpen(false)}
54
+ onConfirm={submitOrder}
55
+ title="Order review"
56
+ slotBaseId="order-review"
57
+ renderSlot={({ id, context, children }) => (
58
+ <SlotRenderer id={id} sdk={sdk} context={context}>
59
+ {children}
60
+ </SlotRenderer>
61
+ )}
62
+ payload={{ orderNumber: 'SO-1001', total: 421.9 }}
63
+ >
64
+ <div>Default modal body</div>
65
+ </ComposableModal>
66
+ );
67
+ }
56
68
  ```
57
69
 
58
70
  Slot ids generated by `createModalSlotIds('order-review')`:
@@ -82,7 +94,7 @@ type OrderPayload = {
82
94
 
83
95
  function CustomFooter({ sdk, context }: SlotComponentProps<ModalSlotContext<OrderPayload>>) {
84
96
  return (
85
- <Button sdk={sdk} onClick={() => context?.confirm?.()}>
97
+ <Button onClick={() => context?.confirm?.()}>
86
98
  Send order {context?.payload?.orderNumber}
87
99
  </Button>
88
100
  );
@@ -122,8 +134,8 @@ npm publish
122
134
  The repository now includes a local Storybook workspace so you can inspect and interact with components before publishing the package.
123
135
 
124
136
  - grouped sidebar navigation for buttons, surfaces, forms, and modals
125
- - live Controls for component props such as size, tone, labels, states, and modal behaviors
126
- - a mocked `SmartSellSDK` so theme-aware components render without depending on the main app runtime
137
+ - live Controls for component props such as size, variants, labels, states, and modal behaviors
138
+ - a mocked `ThemeProvider` so components render with the same theme contract used in host apps
127
139
 
128
140
  Run it directly with npm:
129
141
 
@@ -1,5 +1,17 @@
1
1
  // src/components/Modal.tsx
2
2
  import { useEffect, useMemo, useState } from "react";
3
+
4
+ // src/color.ts
5
+ function withAlpha(hex, alpha) {
6
+ const normalized = hex.replace("#", "").trim();
7
+ const value = normalized.length === 3 ? normalized.split("").map((char) => char + char).join("") : normalized;
8
+ const red = Number.parseInt(value.slice(0, 2), 16);
9
+ const green = Number.parseInt(value.slice(2, 4), 16);
10
+ const blue = Number.parseInt(value.slice(4, 6), 16);
11
+ return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
12
+ }
13
+
14
+ // src/components/Modal.tsx
3
15
  import { jsx, jsxs } from "react/jsx-runtime";
4
16
  var defaultThemeColors = {
5
17
  background: "#f8fafc",
@@ -13,13 +25,16 @@ var defaultThemeColors = {
13
25
  negative: "#dc2626",
14
26
  warning: "#d97706"
15
27
  };
16
- var withAlpha = (hex, alpha) => {
17
- const normalized = hex.replace("#", "").trim();
18
- const value = normalized.length === 3 ? normalized.split("").map((char) => char + char).join("") : normalized;
19
- const red = Number.parseInt(value.slice(0, 2), 16);
20
- const green = Number.parseInt(value.slice(2, 4), 16);
21
- const blue = Number.parseInt(value.slice(4, 6), 16);
22
- return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
28
+ var srOnlyStyle = {
29
+ position: "absolute",
30
+ width: 1,
31
+ height: 1,
32
+ padding: 0,
33
+ margin: -1,
34
+ overflow: "hidden",
35
+ clip: "rect(0, 0, 0, 0)",
36
+ whiteSpace: "nowrap",
37
+ border: 0
23
38
  };
24
39
  var isUiKitThemeTokens = (theme) => {
25
40
  return Boolean(theme && typeof theme === "object" && "theme" in theme);
@@ -137,11 +152,12 @@ function ModalActionButton({
137
152
  alignItems: "center",
138
153
  justifyContent: "center",
139
154
  borderRadius: "0.4rem",
140
- padding: appearance === "link" ? 0 : "1.3rem",
155
+ padding: appearance === "link" ? 0 : "0.9rem 1.15rem",
141
156
  boxSizing: "border-box",
142
157
  cursor: disabled ? "not-allowed" : "pointer",
143
158
  fontWeight: 700,
144
- fontSize: "1.3rem",
159
+ fontSize: "1.05rem",
160
+ lineHeight: 1.2,
145
161
  margin: 0,
146
162
  textAlign: "center",
147
163
  transition: "0.5s",
@@ -177,7 +193,7 @@ function ModalActionButton({
177
193
  display: "flex",
178
194
  alignItems: "center",
179
195
  justifyContent: "center",
180
- margin: "0 5px",
196
+ margin: 0,
181
197
  marginBottom: (_b = style == null ? void 0 : style.marginBottom) != null ? _b : 0,
182
198
  ...style
183
199
  },
@@ -194,12 +210,68 @@ function ModalActionButton({
194
210
  }
195
211
  );
196
212
  }
213
+ function ModalBusyIndicator({
214
+ theme
215
+ }) {
216
+ return /* @__PURE__ */ jsxs(
217
+ "div",
218
+ {
219
+ "aria-live": "polite",
220
+ role: "status",
221
+ style: {
222
+ position: "relative",
223
+ display: "inline-flex",
224
+ alignItems: "center",
225
+ justifyContent: "center",
226
+ width: 56,
227
+ height: 56,
228
+ borderRadius: 999,
229
+ backgroundColor: withAlpha(theme.colors.surface, 0.88),
230
+ boxShadow: `0 18px 36px ${withAlpha(theme.colors.onSurface, 0.08)}`
231
+ },
232
+ children: [
233
+ /* @__PURE__ */ jsx("span", { style: srOnlyStyle, children: "Loading" }),
234
+ /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", width: "32", height: "32", viewBox: "0 0 40 40", fill: "none", children: [
235
+ /* @__PURE__ */ jsx(
236
+ "circle",
237
+ {
238
+ cx: "20",
239
+ cy: "20",
240
+ r: "16",
241
+ stroke: withAlpha(theme.colors.onSurface, 0.12),
242
+ strokeWidth: "4"
243
+ }
244
+ ),
245
+ /* @__PURE__ */ jsx(
246
+ "path",
247
+ {
248
+ d: "M20 4C28.837 4 36 11.163 36 20",
249
+ stroke: theme.colors.primary,
250
+ strokeWidth: "4",
251
+ strokeLinecap: "round",
252
+ children: /* @__PURE__ */ jsx(
253
+ "animateTransform",
254
+ {
255
+ attributeName: "transform",
256
+ type: "rotate",
257
+ from: "0 20 20",
258
+ to: "360 20 20",
259
+ dur: "0.75s",
260
+ repeatCount: "indefinite"
261
+ }
262
+ )
263
+ }
264
+ )
265
+ ] })
266
+ ]
267
+ }
268
+ );
269
+ }
197
270
  function UnifiedModal({
198
271
  isOpen,
199
272
  onClose,
200
273
  children,
201
274
  title,
202
- description,
203
275
  headerContent,
204
276
  footer,
205
277
  confirmAction,
@@ -222,6 +294,7 @@ function UnifiedModal({
222
294
  const modalTheme = useMemo(() => resolveTheme(theme), [theme]);
223
295
  const [isMaximized, setIsMaximized] = useState(maximized != null ? maximized : false);
224
296
  const titleId = useMemo(() => createTitleId(title), [title]);
297
+ const shouldDisableDismiss = disableDismiss || isBusy;
225
298
  useEffect(() => {
226
299
  if (typeof maximized === "boolean") {
227
300
  setIsMaximized(maximized);
@@ -238,7 +311,7 @@ function UnifiedModal({
238
311
  const previousOverflow = document.body.style.overflow;
239
312
  document.body.style.overflow = "hidden";
240
313
  const handleKeyDown = (event) => {
241
- if (!disableDismiss && closeOnEscape && event.key === "Escape") {
314
+ if (!shouldDisableDismiss && closeOnEscape && event.key === "Escape") {
242
315
  onClose();
243
316
  }
244
317
  };
@@ -247,53 +320,54 @@ function UnifiedModal({
247
320
  document.body.style.overflow = previousOverflow;
248
321
  window.removeEventListener("keydown", handleKeyDown);
249
322
  };
250
- }, [closeOnEscape, disableDismiss, isOpen, onClose]);
323
+ }, [closeOnEscape, isOpen, onClose, shouldDisableDismiss]);
251
324
  if (!isOpen) {
252
325
  return null;
253
326
  }
254
- const resolvedHeader = headerContent != null ? headerContent : /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
255
- title ? /* @__PURE__ */ jsx(
256
- "h2",
257
- {
258
- id: titleId,
259
- style: {
260
- margin: 0,
261
- color: modalTheme.colors.onSurface,
262
- fontSize: 30,
263
- fontWeight: 800,
264
- lineHeight: 1.1
265
- },
266
- children: title
267
- }
268
- ) : null,
269
- description ? /* @__PURE__ */ jsx(
270
- "p",
271
- {
272
- style: {
273
- margin: 0,
274
- color: modalTheme.mutedText,
275
- fontSize: 15,
276
- lineHeight: 1.6
277
- },
278
- children: description
279
- }
280
- ) : null
281
- ] });
327
+ const resolvedHeader = headerContent != null ? headerContent : title ? /* @__PURE__ */ jsx(
328
+ "h2",
329
+ {
330
+ id: titleId,
331
+ style: {
332
+ margin: 0,
333
+ color: modalTheme.colors.onSurface,
334
+ fontSize: 30,
335
+ fontWeight: 800,
336
+ lineHeight: 1.1
337
+ },
338
+ children: title
339
+ }
340
+ ) : null;
282
341
  let footerContent = footer;
283
342
  if (footerContent === void 0) {
284
343
  if (closeAction && !closeAction.hidden) {
285
- footerContent = /* @__PURE__ */ jsx(ModalActionButton, { action: closeAction, theme: modalTheme });
344
+ footerContent = /* @__PURE__ */ jsx(
345
+ ModalActionButton,
346
+ {
347
+ action: { ...closeAction, disabled: closeAction.disabled || isBusy },
348
+ theme: modalTheme
349
+ }
350
+ );
286
351
  } else {
287
352
  const resolvedActions = [
288
- cancelAction ? { ...cancelAction, appearance: (_a = cancelAction.appearance) != null ? _a : "text" } : void 0,
353
+ cancelAction ? {
354
+ ...cancelAction,
355
+ appearance: (_a = cancelAction.appearance) != null ? _a : "text",
356
+ disabled: cancelAction.disabled || isBusy
357
+ } : void 0,
289
358
  ...(extraActions != null ? extraActions : []).map((action) => {
290
359
  var _a2;
291
360
  return {
292
361
  ...action,
293
- appearance: (_a2 = action.appearance) != null ? _a2 : "contained"
362
+ appearance: (_a2 = action.appearance) != null ? _a2 : "contained",
363
+ disabled: action.disabled || isBusy
294
364
  };
295
365
  }),
296
- confirmAction ? { ...confirmAction, appearance: (_b = confirmAction.appearance) != null ? _b : "contained" } : void 0
366
+ confirmAction ? {
367
+ ...confirmAction,
368
+ appearance: (_b = confirmAction.appearance) != null ? _b : "contained",
369
+ disabled: confirmAction.disabled || isBusy
370
+ } : void 0
297
371
  ].reduce((items, action) => {
298
372
  if (!action || action.hidden) {
299
373
  return items;
@@ -317,10 +391,11 @@ function UnifiedModal({
317
391
  {
318
392
  "aria-label": headerContent ? typeof title === "string" ? title : "Dialog" : void 0,
319
393
  "aria-labelledby": headerContent ? void 0 : title ? titleId : void 0,
394
+ "aria-busy": isBusy,
320
395
  "aria-modal": "true",
321
396
  role: "dialog",
322
397
  onMouseDown: (event) => {
323
- if (!disableDismiss && closeOnBackdrop && event.target === event.currentTarget) {
398
+ if (!shouldDisableDismiss && closeOnBackdrop && event.target === event.currentTarget) {
324
399
  onClose();
325
400
  }
326
401
  },
@@ -338,7 +413,6 @@ function UnifiedModal({
338
413
  children: /* @__PURE__ */ jsxs(
339
414
  "div",
340
415
  {
341
- id: isBusy ? "ldg1" : void 0,
342
416
  style: {
343
417
  position: "relative",
344
418
  display: "flex",
@@ -354,7 +428,6 @@ function UnifiedModal({
354
428
  boxShadow: `0 34px 80px ${withAlpha("#020617", 0.28)}`,
355
429
  color: modalTheme.colors.onSurface,
356
430
  overflow: "hidden",
357
- opacity: isBusy ? 0.5 : 1,
358
431
  ...contentStyle
359
432
  },
360
433
  children: [
@@ -365,13 +438,23 @@ function UnifiedModal({
365
438
  display: "flex",
366
439
  alignItems: "flex-start",
367
440
  justifyContent: "space-between",
368
- gap: 16,
369
- padding: "24px 24px 16px",
441
+ gap: 12,
442
+ padding: "18px 20px 12px",
370
443
  borderBottom: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`
371
444
  },
372
445
  children: [
373
- /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: resolvedHeader }),
374
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
446
+ /* @__PURE__ */ jsx(
447
+ "div",
448
+ {
449
+ style: {
450
+ flex: 1,
451
+ opacity: isBusy ? 0.38 : 1,
452
+ transition: "opacity 180ms ease"
453
+ },
454
+ children: resolvedHeader
455
+ }
456
+ ),
457
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
375
458
  !hideExpandButton ? /* @__PURE__ */ jsx(
376
459
  "button",
377
460
  {
@@ -380,8 +463,8 @@ function UnifiedModal({
380
463
  type: "button",
381
464
  onClick: () => setIsMaximized((current) => !current),
382
465
  style: {
383
- height: 42,
384
- width: 42,
466
+ height: 40,
467
+ width: 40,
385
468
  borderRadius: 999,
386
469
  border: `1px solid ${modalTheme.borderSoft}`,
387
470
  backgroundColor: "transparent",
@@ -398,18 +481,18 @@ function UnifiedModal({
398
481
  {
399
482
  "aria-label": "Close modal",
400
483
  type: "button",
401
- onClick: disableDismiss ? void 0 : onClose,
484
+ onClick: shouldDisableDismiss ? void 0 : onClose,
402
485
  style: {
403
- height: 42,
404
- width: 42,
486
+ height: 40,
487
+ width: 40,
405
488
  borderRadius: 999,
406
489
  border: `1px solid ${modalTheme.borderSoft}`,
407
490
  backgroundColor: "transparent",
408
491
  color: modalTheme.colors.onSurface,
409
- cursor: disableDismiss ? "not-allowed" : "pointer",
492
+ cursor: shouldDisableDismiss ? "not-allowed" : "pointer",
410
493
  fontSize: 20,
411
494
  fontWeight: 700,
412
- opacity: disableDismiss ? 0.5 : 1
495
+ opacity: shouldDisableDismiss ? 0.5 : 1
413
496
  },
414
497
  children: "\xD7"
415
498
  }
@@ -418,17 +501,46 @@ function UnifiedModal({
418
501
  ]
419
502
  }
420
503
  ),
421
- /* @__PURE__ */ jsx(
504
+ /* @__PURE__ */ jsxs(
422
505
  "div",
423
506
  {
424
507
  style: {
425
508
  flex: 1,
426
509
  minHeight: 0,
510
+ position: "relative",
427
511
  overflow: "auto",
428
512
  padding: 24,
429
513
  ...bodyStyle
430
514
  },
431
- children
515
+ children: [
516
+ /* @__PURE__ */ jsx(
517
+ "div",
518
+ {
519
+ style: {
520
+ opacity: isBusy ? 0.38 : 1,
521
+ filter: isBusy ? "saturate(0.8)" : "none",
522
+ pointerEvents: isBusy ? "none" : "auto",
523
+ transition: "opacity 180ms ease, filter 180ms ease"
524
+ },
525
+ children
526
+ }
527
+ ),
528
+ isBusy ? /* @__PURE__ */ jsx(
529
+ "div",
530
+ {
531
+ style: {
532
+ position: "absolute",
533
+ inset: 0,
534
+ display: "flex",
535
+ alignItems: "center",
536
+ justifyContent: "center",
537
+ backgroundColor: withAlpha(modalTheme.colors.surface, 0.58),
538
+ backdropFilter: "blur(2px)"
539
+ },
540
+ children: /* @__PURE__ */ jsx(ModalBusyIndicator, { theme: modalTheme })
541
+ }
542
+ ) : null
543
+ ]
432
544
  }
433
545
  ),
434
546
  shouldRenderFooter ? /* @__PURE__ */ jsx(
@@ -437,8 +549,8 @@ function UnifiedModal({
437
549
  style: {
438
550
  display: "flex",
439
551
  justifyContent: "flex-end",
440
- gap: 12,
441
- padding: "16px 24px 24px",
552
+ gap: 10,
553
+ padding: "12px 20px 16px",
442
554
  borderTop: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`
443
555
  },
444
556
  children: footerContent
@@ -455,6 +567,7 @@ function Modal(props) {
455
567
  }
456
568
 
457
569
  export {
570
+ withAlpha,
458
571
  Modal
459
572
  };
460
- //# sourceMappingURL=chunk-UIFTQDYM.js.map
573
+ //# sourceMappingURL=chunk-YWH2VIAD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Modal.tsx","../src/color.ts"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\n\nimport { withAlpha } from '../color';\nimport type { UiKitThemeTokens } from '../theme';\n\ntype ModalActionAppearance = 'text' | 'outlined' | 'contained' | 'link';\n\ntype ModalThemeColors = {\n background: string;\n surface: string;\n onSurface: string;\n onBackground: string;\n primary: string;\n onPrimary: string;\n secondary: string;\n onSecondary: string;\n negative: string;\n warning: string;\n};\n\nexport interface ModalTheme {\n colors?: Partial<ModalThemeColors>;\n}\n\nexport type ModalThemeSource = ModalTheme | UiKitThemeTokens;\n\nexport interface ModalAction {\n label: ReactNode;\n onClick: () => void;\n appearance?: ModalActionAppearance;\n style?: CSSProperties;\n disabled?: boolean;\n hidden?: boolean;\n}\n\ninterface BaseModalProps {\n children?: ReactNode;\n theme?: ModalThemeSource;\n}\n\nexport interface ModalProps extends BaseModalProps {\n isOpen: boolean;\n onClose: () => void;\n title?: ReactNode;\n headerContent?: ReactNode;\n footer?: ReactNode;\n confirmAction?: ModalAction;\n cancelAction?: ModalAction;\n closeAction?: ModalAction;\n extraActions?: ModalAction[];\n maxWidth?: number | string;\n closeOnBackdrop?: boolean;\n closeOnEscape?: boolean;\n hideCloseButton?: boolean;\n hideExpandButton?: boolean;\n disableDismiss?: boolean;\n maximized?: boolean;\n contentStyle?: CSSProperties;\n bodyStyle?: CSSProperties;\n isBusy?: boolean;\n}\n\nexport interface LegacyModalAction {\n name: string;\n onClick: () => void;\n type?: ModalActionAppearance;\n style?: CSSProperties;\n disable?: boolean;\n}\n\nexport interface LegacyModalCompatProps extends BaseModalProps {\n title: ReactNode;\n showModal: boolean;\n closeModal: () => void;\n action?: () => void;\n actionNameBtn?: string | undefined;\n hideActionButton?: boolean;\n cancelButton?: () => void;\n disableActionBtn?: boolean;\n isLoading?: boolean;\n onlyCloseButton?: boolean;\n hideCloseIcon?: boolean;\n style?: CSSProperties;\n bodyStyle?: CSSProperties;\n additionalActions?: LegacyModalAction[];\n maximized?: boolean;\n}\n\nexport type LegacyModalProps = LegacyModalCompatProps;\nexport type StandardModalProps = ModalProps;\n\ntype ModalInputProps = ModalProps | LegacyModalCompatProps;\n\nconst defaultThemeColors: ModalThemeColors = {\n background: '#f8fafc',\n surface: '#ffffff',\n onSurface: '#0f172a',\n onBackground: '#0f172a',\n primary: '#0f766e',\n onPrimary: '#ffffff',\n secondary: '#1d4ed8',\n onSecondary: '#ffffff',\n negative: '#dc2626',\n warning: '#d97706',\n};\n\nconst srOnlyStyle: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\nconst isUiKitThemeTokens = (theme?: ModalThemeSource): theme is UiKitThemeTokens => {\n return Boolean(theme && typeof theme === 'object' && 'theme' in theme);\n};\n\nconst resolveTheme = (theme?: ModalThemeSource) => {\n const colorOverrides = isUiKitThemeTokens(theme)\n ? theme.theme.colors\n : (theme?.colors ?? {});\n\n const colors: ModalThemeColors = {\n ...defaultThemeColors,\n ...colorOverrides,\n };\n\n return {\n colors,\n borderSoft: isUiKitThemeTokens(theme)\n ? theme.borderSoft\n : withAlpha(colors.onSurface, 0.1),\n borderStrong: isUiKitThemeTokens(theme)\n ? theme.borderStrong\n : withAlpha(colors.onSurface, 0.16),\n surfaceMuted: isUiKitThemeTokens(theme)\n ? theme.surfaceMuted\n : withAlpha(colors.onSurface, 0.04),\n surfaceRaised: isUiKitThemeTokens(theme)\n ? theme.surfaceRaised\n : withAlpha(colors.surface, 0.94),\n overlay: isUiKitThemeTokens(theme)\n ? theme.overlay\n : withAlpha('#030712', 0.62),\n mutedText: isUiKitThemeTokens(theme)\n ? theme.mutedText\n : withAlpha(colors.onSurface, 0.72),\n };\n};\n\nconst normalizeWidth = (maxWidth?: number | string): string | number => {\n if (typeof maxWidth === 'number') {\n return `${maxWidth}px`;\n }\n\n return maxWidth ?? '720px';\n};\n\nconst isLikelyMobileViewport = (): boolean => {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return false;\n }\n\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n );\n};\n\nconst createTitleId = (title?: ReactNode): string => {\n if (typeof title === 'string' || typeof title === 'number') {\n const normalized = String(title)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n\n return `smartsell-modal-${normalized || 'dialog'}`;\n }\n\n return 'smartsell-modal-dialog';\n};\n\nconst isLegacyModalProps = (props: ModalInputProps): props is LegacyModalCompatProps => {\n return 'showModal' in props;\n};\n\nconst normalizeLegacyAction = (\n action: LegacyModalAction,\n fallbackDisabled = false,\n): ModalAction => {\n return {\n label: action.name,\n onClick: action.onClick,\n appearance: action.type ?? 'contained',\n style: action.style ?? { maxWidth: '150px' },\n disabled: action.disable ?? fallbackDisabled,\n };\n};\n\nconst normalizeModalProps = (props: ModalInputProps): ModalProps => {\n if (!isLegacyModalProps(props)) {\n return props;\n }\n\n const isBusy = Boolean(props.isLoading);\n const disableAction = Boolean(props.disableActionBtn || props.isLoading);\n\n return {\n isOpen: props.showModal,\n onClose: props.closeModal,\n title: props.title,\n children: props.children,\n theme: props.theme,\n maximized: props.maximized,\n contentStyle: props.style,\n bodyStyle: props.bodyStyle,\n hideCloseButton: props.hideCloseIcon,\n disableDismiss: isBusy,\n closeOnBackdrop: false,\n closeOnEscape: false,\n isBusy,\n closeAction: props.onlyCloseButton\n ? {\n label: 'Close',\n onClick: props.closeModal,\n appearance: 'contained',\n disabled: isBusy,\n }\n : undefined,\n cancelAction: props.onlyCloseButton || !props.cancelButton\n ? undefined\n : {\n label: 'Cancel',\n onClick: props.cancelButton,\n appearance: 'text',\n style: { maxWidth: '100px' },\n },\n confirmAction: props.onlyCloseButton || props.hideActionButton || !props.action\n ? undefined\n : {\n label: props.actionNameBtn ?? 'Save',\n onClick: props.action,\n appearance: 'contained',\n style: { maxWidth: '100px' },\n disabled: disableAction,\n },\n extraActions: props.onlyCloseButton\n ? undefined\n : props.additionalActions?.map((action) => normalizeLegacyAction(action, disableAction)),\n };\n};\n\nfunction ModalActionButton({\n action,\n theme,\n}: {\n action: ModalAction;\n theme: ReturnType<typeof resolveTheme>;\n}) {\n const { colors } = theme;\n const {\n label,\n onClick,\n appearance = 'contained',\n disabled = false,\n style,\n } = action;\n\n const buttonStyle: CSSProperties = {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '0.4rem',\n padding: appearance === 'link' ? 0 : '0.9rem 1.15rem',\n boxSizing: 'border-box',\n cursor: disabled ? 'not-allowed' : 'pointer',\n fontWeight: 700,\n fontSize: '1.05rem',\n lineHeight: 1.2,\n margin: 0,\n textAlign: 'center',\n transition: '0.5s',\n opacity: disabled ? 0.5 : 1,\n filter: disabled ? 'saturate(0)' : undefined,\n };\n\n if (appearance === 'text') {\n buttonStyle.background = 'none';\n buttonStyle.border = '1px solid transparent';\n buttonStyle.color = colors.primary;\n buttonStyle.boxShadow = 'none';\n } else if (appearance === 'link') {\n buttonStyle.background = 'none';\n buttonStyle.border = 'none';\n buttonStyle.color = colors.primary;\n buttonStyle.boxShadow = 'none';\n } else if (appearance === 'outlined') {\n buttonStyle.background = 'none';\n buttonStyle.border = `2px solid ${colors.primary}`;\n buttonStyle.color = colors.primary;\n buttonStyle.boxShadow = `0 14px 28px ${withAlpha(colors.onSurface, 0.08)}`;\n } else {\n buttonStyle.background = colors.primary;\n buttonStyle.border = '1px solid transparent';\n buttonStyle.color = colors.onPrimary;\n buttonStyle.boxShadow = `0 14px 28px ${withAlpha(colors.primary, 0.22)}`;\n }\n\n return (\n <div\n style={{\n width: style?.width ?? (style?.maxWidth ? '100%' : 'max-content'),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: 0,\n marginBottom: style?.marginBottom ?? 0,\n ...style,\n }}\n >\n <button\n type=\"button\"\n onClick={disabled ? undefined : onClick}\n disabled={disabled}\n style={buttonStyle}\n >\n {label}\n </button>\n </div>\n );\n}\n\nfunction ModalBusyIndicator({\n theme,\n}: {\n theme: ReturnType<typeof resolveTheme>;\n}) {\n return (\n <div\n aria-live=\"polite\"\n role=\"status\"\n style={{\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 56,\n height: 56,\n borderRadius: 999,\n backgroundColor: withAlpha(theme.colors.surface, 0.88),\n boxShadow: `0 18px 36px ${withAlpha(theme.colors.onSurface, 0.08)}`,\n }}\n >\n <span style={srOnlyStyle}>Loading</span>\n <svg aria-hidden=\"true\" width=\"32\" height=\"32\" viewBox=\"0 0 40 40\" fill=\"none\">\n <circle\n cx=\"20\"\n cy=\"20\"\n r=\"16\"\n stroke={withAlpha(theme.colors.onSurface, 0.12)}\n strokeWidth=\"4\"\n />\n <path\n d=\"M20 4C28.837 4 36 11.163 36 20\"\n stroke={theme.colors.primary}\n strokeWidth=\"4\"\n strokeLinecap=\"round\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 20 20\"\n to=\"360 20 20\"\n dur=\"0.75s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </svg>\n </div>\n );\n}\n\nfunction UnifiedModal({\n isOpen,\n onClose,\n children,\n title,\n headerContent,\n footer,\n confirmAction,\n cancelAction,\n closeAction,\n extraActions,\n maxWidth,\n closeOnBackdrop = true,\n closeOnEscape = true,\n hideCloseButton = false,\n hideExpandButton = false,\n disableDismiss = false,\n maximized,\n contentStyle,\n bodyStyle,\n isBusy = false,\n theme,\n}: ModalProps) {\n const modalTheme = useMemo(() => resolveTheme(theme), [theme]);\n const [isMaximized, setIsMaximized] = useState<boolean>(maximized ?? false);\n const titleId = useMemo(() => createTitleId(title), [title]);\n const shouldDisableDismiss = disableDismiss || isBusy;\n\n useEffect(() => {\n if (typeof maximized === 'boolean') {\n setIsMaximized(maximized);\n return;\n }\n\n if (isLikelyMobileViewport()) {\n setIsMaximized(true);\n }\n }, [maximized]);\n\n useEffect(() => {\n if (!isOpen || typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!shouldDisableDismiss && closeOnEscape && event.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.body.style.overflow = previousOverflow;\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [closeOnEscape, isOpen, onClose, shouldDisableDismiss]);\n\n if (!isOpen) {\n return null;\n }\n\n const resolvedHeader = headerContent ?? (title ? (\n <h2\n id={titleId}\n style={{\n margin: 0,\n color: modalTheme.colors.onSurface,\n fontSize: 30,\n fontWeight: 800,\n lineHeight: 1.1,\n }}\n >\n {title}\n </h2>\n ) : null);\n\n let footerContent = footer;\n\n if (footerContent === undefined) {\n if (closeAction && !closeAction.hidden) {\n footerContent = (\n <ModalActionButton\n action={{ ...closeAction, disabled: closeAction.disabled || isBusy }}\n theme={modalTheme}\n />\n );\n } else {\n const resolvedActions = [\n cancelAction\n ? {\n ...cancelAction,\n appearance: cancelAction.appearance ?? 'text',\n disabled: cancelAction.disabled || isBusy,\n }\n : undefined,\n ...(extraActions ?? []).map((action) => ({\n ...action,\n appearance: action.appearance ?? 'contained',\n disabled: action.disabled || isBusy,\n })),\n confirmAction\n ? {\n ...confirmAction,\n appearance: confirmAction.appearance ?? 'contained',\n disabled: confirmAction.disabled || isBusy,\n }\n : undefined,\n ].reduce<ModalAction[]>((items, action) => {\n if (!action || action.hidden) {\n return items;\n }\n\n items.push(action);\n return items;\n }, []);\n\n footerContent = resolvedActions.length > 0\n ? resolvedActions.map((action, index) => (\n <ModalActionButton\n key={`modal-action-${index}`}\n action={action}\n theme={modalTheme}\n />\n ))\n : undefined;\n }\n }\n\n const shouldRenderFooter = footerContent !== undefined && footerContent !== null && footerContent !== false;\n\n return (\n <div\n aria-label={headerContent ? (typeof title === 'string' ? title : 'Dialog') : undefined}\n aria-labelledby={headerContent ? undefined : title ? titleId : undefined}\n aria-busy={isBusy}\n aria-modal=\"true\"\n role=\"dialog\"\n onMouseDown={(event) => {\n if (!shouldDisableDismiss && closeOnBackdrop && event.target === event.currentTarget) {\n onClose();\n }\n }}\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 70,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: isMaximized ? 0 : 16,\n backgroundColor: modalTheme.overlay,\n backdropFilter: 'blur(8px)',\n }}\n >\n <div\n style={{\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n width: isMaximized ? '100vw' : 'min(100%, 100%)',\n maxWidth: isMaximized ? '100vw' : normalizeWidth(maxWidth),\n height: isMaximized ? '100vh' : undefined,\n maxHeight: isMaximized ? '100vh' : 'calc(100vh - 32px)',\n minWidth: isMaximized ? '100vw' : 300,\n borderRadius: isMaximized ? 0 : 30,\n border: `1px solid ${modalTheme.borderSoft}`,\n background: `linear-gradient(180deg, ${modalTheme.surfaceRaised}, ${modalTheme.colors.surface})`,\n boxShadow: `0 34px 80px ${withAlpha('#020617', 0.28)}`,\n color: modalTheme.colors.onSurface,\n overflow: 'hidden',\n ...contentStyle,\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 12,\n padding: '18px 20px 12px',\n borderBottom: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`,\n }}\n >\n <div\n style={{\n flex: 1,\n opacity: isBusy ? 0.38 : 1,\n transition: 'opacity 180ms ease',\n }}\n >\n {resolvedHeader}\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {!hideExpandButton ? (\n <button\n aria-label={isMaximized ? 'Minimize modal' : 'Maximize modal'}\n title={isMaximized ? 'Minimize' : 'Maximize'}\n type=\"button\"\n onClick={() => setIsMaximized((current) => !current)}\n style={{\n height: 40,\n width: 40,\n borderRadius: 999,\n border: `1px solid ${modalTheme.borderSoft}`,\n backgroundColor: 'transparent',\n color: modalTheme.colors.onSurface,\n cursor: 'pointer',\n fontSize: 18,\n fontWeight: 700,\n }}\n >\n {isMaximized ? '▢' : '□'}\n </button>\n ) : null}\n {!hideCloseButton ? (\n <button\n aria-label=\"Close modal\"\n type=\"button\"\n onClick={shouldDisableDismiss ? undefined : onClose}\n style={{\n height: 40,\n width: 40,\n borderRadius: 999,\n border: `1px solid ${modalTheme.borderSoft}`,\n backgroundColor: 'transparent',\n color: modalTheme.colors.onSurface,\n cursor: shouldDisableDismiss ? 'not-allowed' : 'pointer',\n fontSize: 20,\n fontWeight: 700,\n opacity: shouldDisableDismiss ? 0.5 : 1,\n }}\n >\n ×\n </button>\n ) : null}\n </div>\n </div>\n\n <div\n style={{\n flex: 1,\n minHeight: 0,\n position: 'relative',\n overflow: 'auto',\n padding: 24,\n ...bodyStyle,\n }}\n >\n <div\n style={{\n opacity: isBusy ? 0.38 : 1,\n filter: isBusy ? 'saturate(0.8)' : 'none',\n pointerEvents: isBusy ? 'none' : 'auto',\n transition: 'opacity 180ms ease, filter 180ms ease',\n }}\n >\n {children}\n </div>\n {isBusy ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: withAlpha(modalTheme.colors.surface, 0.58),\n backdropFilter: 'blur(2px)',\n }}\n >\n <ModalBusyIndicator theme={modalTheme} />\n </div>\n ) : null}\n </div>\n\n {shouldRenderFooter ? (\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 10,\n padding: '12px 20px 16px',\n borderTop: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`,\n }}\n >\n {footerContent}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport function Modal(props: ModalInputProps) {\n return <UnifiedModal {...normalizeModalProps(props)} />;\n}\n","export function withAlpha(hex: string, alpha: number): string {\n const normalized = hex.replace('#', '').trim();\n const value = normalized.length === 3\n ? normalized.split('').map((char) => char + char).join('')\n : normalized;\n\n const red = Number.parseInt(value.slice(0, 2), 16);\n const green = Number.parseInt(value.slice(2, 4), 16);\n const blue = Number.parseInt(value.slice(4, 6), 16);\n\n return `rgba(${red}, ${green}, ${blue}, ${alpha})`;\n}"],"mappings":";AAAA,SAAS,WAAW,SAAS,gBAAgB;;;ACAtC,SAAS,UAAU,KAAa,OAAuB;AAC5D,QAAM,aAAa,IAAI,QAAQ,KAAK,EAAE,EAAE,KAAK;AAC7C,QAAM,QAAQ,WAAW,WAAW,IAChC,WAAW,MAAM,EAAE,EAAE,IAAI,CAAC,SAAS,OAAO,IAAI,EAAE,KAAK,EAAE,IACvD;AAEJ,QAAM,MAAM,OAAO,SAAS,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE;AACjD,QAAM,QAAQ,OAAO,SAAS,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE;AACnD,QAAM,OAAO,OAAO,SAAS,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE;AAElD,SAAO,QAAQ,GAAG,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK;AACjD;;;AD2TM,cAkCA,YAlCA;AAxON,IAAM,qBAAuC;AAAA,EAC3C,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,cAAc;AAAA,EACd,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAU;AAAA,EACV,SAAS;AACX;AAEA,IAAM,cAA6B;AAAA,EACjC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AACV;AAEA,IAAM,qBAAqB,CAAC,UAAwD;AAClF,SAAO,QAAQ,SAAS,OAAO,UAAU,YAAY,WAAW,KAAK;AACvE;AAEA,IAAM,eAAe,CAAC,UAA6B;AA3HnD;AA4HE,QAAM,iBAAiB,mBAAmB,KAAK,IAC3C,MAAM,MAAM,UACX,oCAAO,WAAP,YAAiB,CAAC;AAEvB,QAAM,SAA2B;AAAA,IAC/B,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAY,mBAAmB,KAAK,IAChC,MAAM,aACN,UAAU,OAAO,WAAW,GAAG;AAAA,IACnC,cAAc,mBAAmB,KAAK,IAClC,MAAM,eACN,UAAU,OAAO,WAAW,IAAI;AAAA,IACpC,cAAc,mBAAmB,KAAK,IAClC,MAAM,eACN,UAAU,OAAO,WAAW,IAAI;AAAA,IACpC,eAAe,mBAAmB,KAAK,IACnC,MAAM,gBACN,UAAU,OAAO,SAAS,IAAI;AAAA,IAClC,SAAS,mBAAmB,KAAK,IAC7B,MAAM,UACN,UAAU,WAAW,IAAI;AAAA,IAC7B,WAAW,mBAAmB,KAAK,IAC/B,MAAM,YACN,UAAU,OAAO,WAAW,IAAI;AAAA,EACtC;AACF;AAEA,IAAM,iBAAiB,CAAC,aAAgD;AACtE,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO,GAAG,QAAQ;AAAA,EACpB;AAEA,SAAO,8BAAY;AACrB;AAEA,IAAM,yBAAyB,MAAe;AAC5C,MAAI,OAAO,WAAW,eAAe,OAAO,cAAc,aAAa;AACrE,WAAO;AAAA,EACT;AAEA,SAAO,iEAAiE;AAAA,IACtE,UAAU;AAAA,EACZ;AACF;AAEA,IAAM,gBAAgB,CAAC,UAA8B;AACnD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,UAAM,aAAa,OAAO,KAAK,EAC5B,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAEzB,WAAO,mBAAmB,cAAc,QAAQ;AAAA,EAClD;AAEA,SAAO;AACT;AAEA,IAAM,qBAAqB,CAAC,UAA4D;AACtF,SAAO,eAAe;AACxB;AAEA,IAAM,wBAAwB,CAC5B,QACA,mBAAmB,UACH;AAlMlB;AAmME,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd,SAAS,OAAO;AAAA,IAChB,aAAY,YAAO,SAAP,YAAe;AAAA,IAC3B,QAAO,YAAO,UAAP,YAAgB,EAAE,UAAU,QAAQ;AAAA,IAC3C,WAAU,YAAO,YAAP,YAAkB;AAAA,EAC9B;AACF;AAEA,IAAM,sBAAsB,CAAC,UAAuC;AA5MpE;AA6ME,MAAI,CAAC,mBAAmB,KAAK,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,QAAQ,MAAM,SAAS;AACtC,QAAM,gBAAgB,QAAQ,MAAM,oBAAoB,MAAM,SAAS;AAEvE,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,WAAW,MAAM;AAAA,IACjB,cAAc,MAAM;AAAA,IACpB,WAAW,MAAM;AAAA,IACjB,iBAAiB,MAAM;AAAA,IACvB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf;AAAA,IACA,aAAa,MAAM,kBACf;AAAA,MACE,OAAO;AAAA,MACP,SAAS,MAAM;AAAA,MACf,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ,IACA;AAAA,IACJ,cAAc,MAAM,mBAAmB,CAAC,MAAM,eAC1C,SACA;AAAA,MACE,OAAO;AAAA,MACP,SAAS,MAAM;AAAA,MACf,YAAY;AAAA,MACZ,OAAO,EAAE,UAAU,QAAQ;AAAA,IAC7B;AAAA,IACJ,eAAe,MAAM,mBAAmB,MAAM,oBAAoB,CAAC,MAAM,SACrE,SACA;AAAA,MACE,QAAO,WAAM,kBAAN,YAAuB;AAAA,MAC9B,SAAS,MAAM;AAAA,MACf,YAAY;AAAA,MACZ,OAAO,EAAE,UAAU,QAAQ;AAAA,MAC3B,UAAU;AAAA,IACZ;AAAA,IACJ,cAAc,MAAM,kBAChB,UACA,WAAM,sBAAN,mBAAyB,IAAI,CAAC,WAAW,sBAAsB,QAAQ,aAAa;AAAA,EAC1F;AACF;AAEA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAGG;AAvQH;AAwQE,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,WAAW;AAAA,IACX;AAAA,EACF,IAAI;AAEJ,QAAM,cAA6B;AAAA,IACjC,OAAO;AAAA,IACP,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,SAAS,eAAe,SAAS,IAAI;AAAA,IACrC,WAAW;AAAA,IACX,QAAQ,WAAW,gBAAgB;AAAA,IACnC,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS,WAAW,MAAM;AAAA,IAC1B,QAAQ,WAAW,gBAAgB;AAAA,EACrC;AAEA,MAAI,eAAe,QAAQ;AACzB,gBAAY,aAAa;AACzB,gBAAY,SAAS;AACrB,gBAAY,QAAQ,OAAO;AAC3B,gBAAY,YAAY;AAAA,EAC1B,WAAW,eAAe,QAAQ;AAChC,gBAAY,aAAa;AACzB,gBAAY,SAAS;AACrB,gBAAY,QAAQ,OAAO;AAC3B,gBAAY,YAAY;AAAA,EAC1B,WAAW,eAAe,YAAY;AACpC,gBAAY,aAAa;AACzB,gBAAY,SAAS,aAAa,OAAO,OAAO;AAChD,gBAAY,QAAQ,OAAO;AAC3B,gBAAY,YAAY,eAAe,UAAU,OAAO,WAAW,IAAI,CAAC;AAAA,EAC1E,OAAO;AACL,gBAAY,aAAa,OAAO;AAChC,gBAAY,SAAS;AACrB,gBAAY,QAAQ,OAAO;AAC3B,gBAAY,YAAY,eAAe,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,EACxE;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,QAAO,oCAAO,UAAP,aAAiB,+BAAO,YAAW,SAAS;AAAA,QACnD,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,eAAc,oCAAO,iBAAP,YAAuB;AAAA,QACrC,GAAG;AAAA,MACL;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,WAAW,SAAY;AAAA,UAChC;AAAA,UACA,OAAO;AAAA,UAEN;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AACF,GAEG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,MAAK;AAAA,MACL,OAAO;AAAA,QACL,UAAU;AAAA,QACV,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,iBAAiB,UAAU,MAAM,OAAO,SAAS,IAAI;AAAA,QACrD,WAAW,eAAe,UAAU,MAAM,OAAO,WAAW,IAAI,CAAC;AAAA,MACnE;AAAA,MAEA;AAAA,4BAAC,UAAK,OAAO,aAAa,qBAAO;AAAA,QACjC,qBAAC,SAAI,eAAY,QAAO,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QACtE;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,IAAG;AAAA,cACH,GAAE;AAAA,cACF,QAAQ,UAAU,MAAM,OAAO,WAAW,IAAI;AAAA,cAC9C,aAAY;AAAA;AAAA,UACd;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,GAAE;AAAA,cACF,QAAQ,MAAM,OAAO;AAAA,cACrB,aAAY;AAAA,cACZ,eAAc;AAAA,cAEd;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAc;AAAA,kBACd,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,IAAG;AAAA,kBACH,KAAI;AAAA,kBACJ,aAAY;AAAA;AAAA,cACd;AAAA;AAAA,UACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AACF,GAAe;AA1Zf;AA2ZE,QAAM,aAAa,QAAQ,MAAM,aAAa,KAAK,GAAG,CAAC,KAAK,CAAC;AAC7D,QAAM,CAAC,aAAa,cAAc,IAAI,SAAkB,gCAAa,KAAK;AAC1E,QAAM,UAAU,QAAQ,MAAM,cAAc,KAAK,GAAG,CAAC,KAAK,CAAC;AAC3D,QAAM,uBAAuB,kBAAkB;AAE/C,YAAU,MAAM;AACd,QAAI,OAAO,cAAc,WAAW;AAClC,qBAAe,SAAS;AACxB;AAAA,IACF;AAEA,QAAI,uBAAuB,GAAG;AAC5B,qBAAe,IAAI;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AAC/E;AAAA,IACF;AAEA,UAAM,mBAAmB,SAAS,KAAK,MAAM;AAC7C,aAAS,KAAK,MAAM,WAAW;AAE/B,UAAM,gBAAgB,CAAC,UAAyB;AAC9C,UAAI,CAAC,wBAAwB,iBAAiB,MAAM,QAAQ,UAAU;AACpE,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,aAAa;AAEhD,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAC/B,aAAO,oBAAoB,WAAW,aAAa;AAAA,IACrD;AAAA,EACF,GAAG,CAAC,eAAe,QAAQ,SAAS,oBAAoB,CAAC;AAEzD,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,wCAAkB,QACvC;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,WAAW,OAAO;AAAA,QACzB,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,MAEC;AAAA;AAAA,EACH,IACE;AAEJ,MAAI,gBAAgB;AAEpB,MAAI,kBAAkB,QAAW;AAC/B,QAAI,eAAe,CAAC,YAAY,QAAQ;AACtC,sBACE;AAAA,QAAC;AAAA;AAAA,UACC,QAAQ,EAAE,GAAG,aAAa,UAAU,YAAY,YAAY,OAAO;AAAA,UACnE,OAAO;AAAA;AAAA,MACT;AAAA,IAEJ,OAAO;AACL,YAAM,kBAAkB;AAAA,QACtB,eACI;AAAA,UACE,GAAG;AAAA,UACH,aAAY,kBAAa,eAAb,YAA2B;AAAA,UACvC,UAAU,aAAa,YAAY;AAAA,QACrC,IACA;AAAA,QACJ,IAAI,sCAAgB,CAAC,GAAG,IAAI,CAAC,WAAQ;AAve7C,cAAAA;AAueiD;AAAA,YACvC,GAAG;AAAA,YACH,aAAYA,MAAA,OAAO,eAAP,OAAAA,MAAqB;AAAA,YACjC,UAAU,OAAO,YAAY;AAAA,UAC/B;AAAA,SAAE;AAAA,QACF,gBACI;AAAA,UACE,GAAG;AAAA,UACH,aAAY,mBAAc,eAAd,YAA4B;AAAA,UACxC,UAAU,cAAc,YAAY;AAAA,QACtC,IACA;AAAA,MACN,EAAE,OAAsB,CAAC,OAAO,WAAW;AACzC,YAAI,CAAC,UAAU,OAAO,QAAQ;AAC5B,iBAAO;AAAA,QACT;AAEA,cAAM,KAAK,MAAM;AACjB,eAAO;AAAA,MACT,GAAG,CAAC,CAAC;AAEL,sBAAgB,gBAAgB,SAAS,IACrC,gBAAgB,IAAI,CAAC,QAAQ,UAC3B;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,OAAO;AAAA;AAAA,QAFF,gBAAgB,KAAK;AAAA,MAG5B,CACD,IACD;AAAA,IACN;AAAA,EACF;AAEA,QAAM,qBAAqB,kBAAkB,UAAa,kBAAkB,QAAQ,kBAAkB;AAEtG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAY,gBAAiB,OAAO,UAAU,WAAW,QAAQ,WAAY;AAAA,MAC7E,mBAAiB,gBAAgB,SAAY,QAAQ,UAAU;AAAA,MAC/D,aAAW;AAAA,MACX,cAAW;AAAA,MACX,MAAK;AAAA,MACL,aAAa,CAAC,UAAU;AACtB,YAAI,CAAC,wBAAwB,mBAAmB,MAAM,WAAW,MAAM,eAAe;AACpF,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS,cAAc,IAAI;AAAA,QAC3B,iBAAiB,WAAW;AAAA,QAC5B,gBAAgB;AAAA,MAClB;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,SAAS;AAAA,YACT,eAAe;AAAA,YACf,OAAO,cAAc,UAAU;AAAA,YAC/B,UAAU,cAAc,UAAU,eAAe,QAAQ;AAAA,YACzD,QAAQ,cAAc,UAAU;AAAA,YAChC,WAAW,cAAc,UAAU;AAAA,YACnC,UAAU,cAAc,UAAU;AAAA,YAClC,cAAc,cAAc,IAAI;AAAA,YAChC,QAAQ,aAAa,WAAW,UAAU;AAAA,YAC1C,YAAY,2BAA2B,WAAW,aAAa,KAAK,WAAW,OAAO,OAAO;AAAA,YAC7F,WAAW,eAAe,UAAU,WAAW,IAAI,CAAC;AAAA,YACpD,OAAO,WAAW,OAAO;AAAA,YACzB,UAAU;AAAA,YACV,GAAG;AAAA,UACL;AAAA,UAEA;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,SAAS;AAAA,kBACT,YAAY;AAAA,kBACZ,gBAAgB;AAAA,kBAChB,KAAK;AAAA,kBACL,SAAS;AAAA,kBACT,cAAc,aAAa,UAAU,WAAW,OAAO,WAAW,IAAI,CAAC;AAAA,gBACzE;AAAA,gBAEA;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,MAAM;AAAA,wBACN,SAAS,SAAS,OAAO;AAAA,wBACzB,YAAY;AAAA,sBACd;AAAA,sBAEC;AAAA;AAAA,kBACH;AAAA,kBACA,qBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GACzD;AAAA,qBAAC,mBACA;AAAA,sBAAC;AAAA;AAAA,wBACC,cAAY,cAAc,mBAAmB;AAAA,wBAC7C,OAAO,cAAc,aAAa;AAAA,wBAClC,MAAK;AAAA,wBACL,SAAS,MAAM,eAAe,CAAC,YAAY,CAAC,OAAO;AAAA,wBACnD,OAAO;AAAA,0BACL,QAAQ;AAAA,0BACR,OAAO;AAAA,0BACP,cAAc;AAAA,0BACd,QAAQ,aAAa,WAAW,UAAU;AAAA,0BAC1C,iBAAiB;AAAA,0BACjB,OAAO,WAAW,OAAO;AAAA,0BACzB,QAAQ;AAAA,0BACR,UAAU;AAAA,0BACV,YAAY;AAAA,wBACd;AAAA,wBAEC,wBAAc,WAAM;AAAA;AAAA,oBACvB,IACE;AAAA,oBACH,CAAC,kBACA;AAAA,sBAAC;AAAA;AAAA,wBACC,cAAW;AAAA,wBACX,MAAK;AAAA,wBACL,SAAS,uBAAuB,SAAY;AAAA,wBAC5C,OAAO;AAAA,0BACL,QAAQ;AAAA,0BACR,OAAO;AAAA,0BACP,cAAc;AAAA,0BACd,QAAQ,aAAa,WAAW,UAAU;AAAA,0BAC1C,iBAAiB;AAAA,0BACjB,OAAO,WAAW,OAAO;AAAA,0BACzB,QAAQ,uBAAuB,gBAAgB;AAAA,0BAC/C,UAAU;AAAA,0BACV,YAAY;AAAA,0BACZ,SAAS,uBAAuB,MAAM;AAAA,wBACxC;AAAA,wBACD;AAAA;AAAA,oBAED,IACE;AAAA,qBACN;AAAA;AAAA;AAAA,YACF;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,MAAM;AAAA,kBACN,WAAW;AAAA,kBACX,UAAU;AAAA,kBACV,UAAU;AAAA,kBACV,SAAS;AAAA,kBACT,GAAG;AAAA,gBACL;AAAA,gBAEA;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,SAAS,SAAS,OAAO;AAAA,wBACzB,QAAQ,SAAS,kBAAkB;AAAA,wBACnC,eAAe,SAAS,SAAS;AAAA,wBACjC,YAAY;AAAA,sBACd;AAAA,sBAEC;AAAA;AAAA,kBACH;AAAA,kBACC,SACC;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,OAAO;AAAA,wBACP,SAAS;AAAA,wBACT,YAAY;AAAA,wBACZ,gBAAgB;AAAA,wBAChB,iBAAiB,UAAU,WAAW,OAAO,SAAS,IAAI;AAAA,wBAC1D,gBAAgB;AAAA,sBAClB;AAAA,sBAEA,8BAAC,sBAAmB,OAAO,YAAY;AAAA;AAAA,kBACzC,IACE;AAAA;AAAA;AAAA,YACN;AAAA,YAEC,qBACC;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,SAAS;AAAA,kBACT,gBAAgB;AAAA,kBAChB,KAAK;AAAA,kBACL,SAAS;AAAA,kBACT,WAAW,aAAa,UAAU,WAAW,OAAO,WAAW,IAAI,CAAC;AAAA,gBACtE;AAAA,gBAEC;AAAA;AAAA,YACH,IACE;AAAA;AAAA;AAAA,MACN;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,MAAM,OAAwB;AAC5C,SAAO,oBAAC,gBAAc,GAAG,oBAAoB,KAAK,GAAG;AACvD;","names":["_a"]}