smartsell-ui-kit 0.0.4 → 0.0.6

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
@@ -115,4 +115,27 @@ export default manifest;
115
115
  npm run typecheck
116
116
  npm run build
117
117
  npm publish
118
- ```
118
+ ```
119
+
120
+ ## Component preview workspace
121
+
122
+ The repository now includes a local Storybook workspace so you can inspect and interact with components before publishing the package.
123
+
124
+ - 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
127
+
128
+ Run it directly with npm:
129
+
130
+ ```bash
131
+ npm install
132
+ npm run storybook
133
+ ```
134
+
135
+ Run it in a container with hot reload:
136
+
137
+ ```bash
138
+ docker compose up --build
139
+ ```
140
+
141
+ The Storybook workspace is development-only. It is not part of the published package because `package.json` only ships `dist`, `README.md`, and `LICENSE`.
@@ -0,0 +1,460 @@
1
+ // src/components/Modal.tsx
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ var defaultThemeColors = {
5
+ background: "#f8fafc",
6
+ surface: "#ffffff",
7
+ onSurface: "#0f172a",
8
+ onBackground: "#0f172a",
9
+ primary: "#0f766e",
10
+ onPrimary: "#ffffff",
11
+ secondary: "#1d4ed8",
12
+ onSecondary: "#ffffff",
13
+ negative: "#dc2626",
14
+ warning: "#d97706"
15
+ };
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})`;
23
+ };
24
+ var isUiKitThemeTokens = (theme) => {
25
+ return Boolean(theme && typeof theme === "object" && "theme" in theme);
26
+ };
27
+ var resolveTheme = (theme) => {
28
+ var _a;
29
+ const colorOverrides = isUiKitThemeTokens(theme) ? theme.theme.colors : (_a = theme == null ? void 0 : theme.colors) != null ? _a : {};
30
+ const colors = {
31
+ ...defaultThemeColors,
32
+ ...colorOverrides
33
+ };
34
+ return {
35
+ colors,
36
+ borderSoft: isUiKitThemeTokens(theme) ? theme.borderSoft : withAlpha(colors.onSurface, 0.1),
37
+ borderStrong: isUiKitThemeTokens(theme) ? theme.borderStrong : withAlpha(colors.onSurface, 0.16),
38
+ surfaceMuted: isUiKitThemeTokens(theme) ? theme.surfaceMuted : withAlpha(colors.onSurface, 0.04),
39
+ surfaceRaised: isUiKitThemeTokens(theme) ? theme.surfaceRaised : withAlpha(colors.surface, 0.94),
40
+ overlay: isUiKitThemeTokens(theme) ? theme.overlay : withAlpha("#030712", 0.62),
41
+ mutedText: isUiKitThemeTokens(theme) ? theme.mutedText : withAlpha(colors.onSurface, 0.72)
42
+ };
43
+ };
44
+ var normalizeWidth = (maxWidth) => {
45
+ if (typeof maxWidth === "number") {
46
+ return `${maxWidth}px`;
47
+ }
48
+ return maxWidth != null ? maxWidth : "720px";
49
+ };
50
+ var isLikelyMobileViewport = () => {
51
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
52
+ return false;
53
+ }
54
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
55
+ navigator.userAgent
56
+ );
57
+ };
58
+ var createTitleId = (title) => {
59
+ if (typeof title === "string" || typeof title === "number") {
60
+ const normalized = String(title).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
61
+ return `smartsell-modal-${normalized || "dialog"}`;
62
+ }
63
+ return "smartsell-modal-dialog";
64
+ };
65
+ var isLegacyModalProps = (props) => {
66
+ return "showModal" in props;
67
+ };
68
+ var normalizeLegacyAction = (action, fallbackDisabled = false) => {
69
+ var _a, _b, _c;
70
+ return {
71
+ label: action.name,
72
+ onClick: action.onClick,
73
+ appearance: (_a = action.type) != null ? _a : "contained",
74
+ style: (_b = action.style) != null ? _b : { maxWidth: "150px" },
75
+ disabled: (_c = action.disable) != null ? _c : fallbackDisabled
76
+ };
77
+ };
78
+ var normalizeModalProps = (props) => {
79
+ var _a, _b;
80
+ if (!isLegacyModalProps(props)) {
81
+ return props;
82
+ }
83
+ const isBusy = Boolean(props.isLoading);
84
+ const disableAction = Boolean(props.disableActionBtn || props.isLoading);
85
+ return {
86
+ isOpen: props.showModal,
87
+ onClose: props.closeModal,
88
+ title: props.title,
89
+ children: props.children,
90
+ theme: props.theme,
91
+ maximized: props.maximized,
92
+ contentStyle: props.style,
93
+ bodyStyle: props.bodyStyle,
94
+ hideCloseButton: props.hideCloseIcon,
95
+ disableDismiss: isBusy,
96
+ closeOnBackdrop: false,
97
+ closeOnEscape: false,
98
+ isBusy,
99
+ closeAction: props.onlyCloseButton ? {
100
+ label: "Close",
101
+ onClick: props.closeModal,
102
+ appearance: "contained",
103
+ disabled: isBusy
104
+ } : void 0,
105
+ cancelAction: props.onlyCloseButton || !props.cancelButton ? void 0 : {
106
+ label: "Cancel",
107
+ onClick: props.cancelButton,
108
+ appearance: "text",
109
+ style: { maxWidth: "100px" }
110
+ },
111
+ confirmAction: props.onlyCloseButton || props.hideActionButton || !props.action ? void 0 : {
112
+ label: (_a = props.actionNameBtn) != null ? _a : "Save",
113
+ onClick: props.action,
114
+ appearance: "contained",
115
+ style: { maxWidth: "100px" },
116
+ disabled: disableAction
117
+ },
118
+ extraActions: props.onlyCloseButton ? void 0 : (_b = props.additionalActions) == null ? void 0 : _b.map((action) => normalizeLegacyAction(action, disableAction))
119
+ };
120
+ };
121
+ function ModalActionButton({
122
+ action,
123
+ theme
124
+ }) {
125
+ var _a, _b;
126
+ const { colors } = theme;
127
+ const {
128
+ label,
129
+ onClick,
130
+ appearance = "contained",
131
+ disabled = false,
132
+ style
133
+ } = action;
134
+ const buttonStyle = {
135
+ width: "100%",
136
+ display: "flex",
137
+ alignItems: "center",
138
+ justifyContent: "center",
139
+ borderRadius: "0.4rem",
140
+ padding: appearance === "link" ? 0 : "1.3rem",
141
+ boxSizing: "border-box",
142
+ cursor: disabled ? "not-allowed" : "pointer",
143
+ fontWeight: 700,
144
+ fontSize: "1.3rem",
145
+ margin: 0,
146
+ textAlign: "center",
147
+ transition: "0.5s",
148
+ opacity: disabled ? 0.5 : 1,
149
+ filter: disabled ? "saturate(0)" : void 0
150
+ };
151
+ if (appearance === "text") {
152
+ buttonStyle.background = "none";
153
+ buttonStyle.border = "1px solid transparent";
154
+ buttonStyle.color = colors.primary;
155
+ buttonStyle.boxShadow = "none";
156
+ } else if (appearance === "link") {
157
+ buttonStyle.background = "none";
158
+ buttonStyle.border = "none";
159
+ buttonStyle.color = colors.primary;
160
+ buttonStyle.boxShadow = "none";
161
+ } else if (appearance === "outlined") {
162
+ buttonStyle.background = "none";
163
+ buttonStyle.border = `2px solid ${colors.primary}`;
164
+ buttonStyle.color = colors.primary;
165
+ buttonStyle.boxShadow = `0 14px 28px ${withAlpha(colors.onSurface, 0.08)}`;
166
+ } else {
167
+ buttonStyle.background = colors.primary;
168
+ buttonStyle.border = "1px solid transparent";
169
+ buttonStyle.color = colors.onPrimary;
170
+ buttonStyle.boxShadow = `0 14px 28px ${withAlpha(colors.primary, 0.22)}`;
171
+ }
172
+ return /* @__PURE__ */ jsx(
173
+ "div",
174
+ {
175
+ style: {
176
+ width: (_a = style == null ? void 0 : style.width) != null ? _a : (style == null ? void 0 : style.maxWidth) ? "100%" : "max-content",
177
+ display: "flex",
178
+ alignItems: "center",
179
+ justifyContent: "center",
180
+ margin: "0 5px",
181
+ marginBottom: (_b = style == null ? void 0 : style.marginBottom) != null ? _b : 0,
182
+ ...style
183
+ },
184
+ children: /* @__PURE__ */ jsx(
185
+ "button",
186
+ {
187
+ type: "button",
188
+ onClick: disabled ? void 0 : onClick,
189
+ disabled,
190
+ style: buttonStyle,
191
+ children: label
192
+ }
193
+ )
194
+ }
195
+ );
196
+ }
197
+ function UnifiedModal({
198
+ isOpen,
199
+ onClose,
200
+ children,
201
+ title,
202
+ description,
203
+ headerContent,
204
+ footer,
205
+ confirmAction,
206
+ cancelAction,
207
+ closeAction,
208
+ extraActions,
209
+ maxWidth,
210
+ closeOnBackdrop = true,
211
+ closeOnEscape = true,
212
+ hideCloseButton = false,
213
+ hideExpandButton = false,
214
+ disableDismiss = false,
215
+ maximized,
216
+ contentStyle,
217
+ bodyStyle,
218
+ isBusy = false,
219
+ theme
220
+ }) {
221
+ var _a, _b;
222
+ const modalTheme = useMemo(() => resolveTheme(theme), [theme]);
223
+ const [isMaximized, setIsMaximized] = useState(maximized != null ? maximized : false);
224
+ const titleId = useMemo(() => createTitleId(title), [title]);
225
+ useEffect(() => {
226
+ if (typeof maximized === "boolean") {
227
+ setIsMaximized(maximized);
228
+ return;
229
+ }
230
+ if (isLikelyMobileViewport()) {
231
+ setIsMaximized(true);
232
+ }
233
+ }, [maximized]);
234
+ useEffect(() => {
235
+ if (!isOpen || typeof window === "undefined" || typeof document === "undefined") {
236
+ return;
237
+ }
238
+ const previousOverflow = document.body.style.overflow;
239
+ document.body.style.overflow = "hidden";
240
+ const handleKeyDown = (event) => {
241
+ if (!disableDismiss && closeOnEscape && event.key === "Escape") {
242
+ onClose();
243
+ }
244
+ };
245
+ window.addEventListener("keydown", handleKeyDown);
246
+ return () => {
247
+ document.body.style.overflow = previousOverflow;
248
+ window.removeEventListener("keydown", handleKeyDown);
249
+ };
250
+ }, [closeOnEscape, disableDismiss, isOpen, onClose]);
251
+ if (!isOpen) {
252
+ return null;
253
+ }
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
+ ] });
282
+ let footerContent = footer;
283
+ if (footerContent === void 0) {
284
+ if (closeAction && !closeAction.hidden) {
285
+ footerContent = /* @__PURE__ */ jsx(ModalActionButton, { action: closeAction, theme: modalTheme });
286
+ } else {
287
+ const resolvedActions = [
288
+ cancelAction ? { ...cancelAction, appearance: (_a = cancelAction.appearance) != null ? _a : "text" } : void 0,
289
+ ...(extraActions != null ? extraActions : []).map((action) => {
290
+ var _a2;
291
+ return {
292
+ ...action,
293
+ appearance: (_a2 = action.appearance) != null ? _a2 : "contained"
294
+ };
295
+ }),
296
+ confirmAction ? { ...confirmAction, appearance: (_b = confirmAction.appearance) != null ? _b : "contained" } : void 0
297
+ ].reduce((items, action) => {
298
+ if (!action || action.hidden) {
299
+ return items;
300
+ }
301
+ items.push(action);
302
+ return items;
303
+ }, []);
304
+ footerContent = resolvedActions.length > 0 ? resolvedActions.map((action, index) => /* @__PURE__ */ jsx(
305
+ ModalActionButton,
306
+ {
307
+ action,
308
+ theme: modalTheme
309
+ },
310
+ `modal-action-${index}`
311
+ )) : void 0;
312
+ }
313
+ }
314
+ const shouldRenderFooter = footerContent !== void 0 && footerContent !== null && footerContent !== false;
315
+ return /* @__PURE__ */ jsx(
316
+ "div",
317
+ {
318
+ "aria-label": headerContent ? typeof title === "string" ? title : "Dialog" : void 0,
319
+ "aria-labelledby": headerContent ? void 0 : title ? titleId : void 0,
320
+ "aria-modal": "true",
321
+ role: "dialog",
322
+ onMouseDown: (event) => {
323
+ if (!disableDismiss && closeOnBackdrop && event.target === event.currentTarget) {
324
+ onClose();
325
+ }
326
+ },
327
+ style: {
328
+ position: "fixed",
329
+ inset: 0,
330
+ zIndex: 70,
331
+ display: "flex",
332
+ alignItems: "center",
333
+ justifyContent: "center",
334
+ padding: isMaximized ? 0 : 16,
335
+ backgroundColor: modalTheme.overlay,
336
+ backdropFilter: "blur(8px)"
337
+ },
338
+ children: /* @__PURE__ */ jsxs(
339
+ "div",
340
+ {
341
+ id: isBusy ? "ldg1" : void 0,
342
+ style: {
343
+ position: "relative",
344
+ display: "flex",
345
+ flexDirection: "column",
346
+ width: isMaximized ? "100vw" : "min(100%, 100%)",
347
+ maxWidth: isMaximized ? "100vw" : normalizeWidth(maxWidth),
348
+ height: isMaximized ? "100vh" : void 0,
349
+ maxHeight: isMaximized ? "100vh" : "calc(100vh - 32px)",
350
+ minWidth: isMaximized ? "100vw" : 300,
351
+ borderRadius: isMaximized ? 0 : 30,
352
+ border: `1px solid ${modalTheme.borderSoft}`,
353
+ background: `linear-gradient(180deg, ${modalTheme.surfaceRaised}, ${modalTheme.colors.surface})`,
354
+ boxShadow: `0 34px 80px ${withAlpha("#020617", 0.28)}`,
355
+ color: modalTheme.colors.onSurface,
356
+ overflow: "hidden",
357
+ opacity: isBusy ? 0.5 : 1,
358
+ ...contentStyle
359
+ },
360
+ children: [
361
+ /* @__PURE__ */ jsxs(
362
+ "div",
363
+ {
364
+ style: {
365
+ display: "flex",
366
+ alignItems: "flex-start",
367
+ justifyContent: "space-between",
368
+ gap: 16,
369
+ padding: "24px 24px 16px",
370
+ borderBottom: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`
371
+ },
372
+ children: [
373
+ /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: resolvedHeader }),
374
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
375
+ !hideExpandButton ? /* @__PURE__ */ jsx(
376
+ "button",
377
+ {
378
+ "aria-label": isMaximized ? "Minimize modal" : "Maximize modal",
379
+ title: isMaximized ? "Minimize" : "Maximize",
380
+ type: "button",
381
+ onClick: () => setIsMaximized((current) => !current),
382
+ style: {
383
+ height: 42,
384
+ width: 42,
385
+ borderRadius: 999,
386
+ border: `1px solid ${modalTheme.borderSoft}`,
387
+ backgroundColor: "transparent",
388
+ color: modalTheme.colors.onSurface,
389
+ cursor: "pointer",
390
+ fontSize: 18,
391
+ fontWeight: 700
392
+ },
393
+ children: isMaximized ? "\u25A2" : "\u25A1"
394
+ }
395
+ ) : null,
396
+ !hideCloseButton ? /* @__PURE__ */ jsx(
397
+ "button",
398
+ {
399
+ "aria-label": "Close modal",
400
+ type: "button",
401
+ onClick: disableDismiss ? void 0 : onClose,
402
+ style: {
403
+ height: 42,
404
+ width: 42,
405
+ borderRadius: 999,
406
+ border: `1px solid ${modalTheme.borderSoft}`,
407
+ backgroundColor: "transparent",
408
+ color: modalTheme.colors.onSurface,
409
+ cursor: disableDismiss ? "not-allowed" : "pointer",
410
+ fontSize: 20,
411
+ fontWeight: 700,
412
+ opacity: disableDismiss ? 0.5 : 1
413
+ },
414
+ children: "\xD7"
415
+ }
416
+ ) : null
417
+ ] })
418
+ ]
419
+ }
420
+ ),
421
+ /* @__PURE__ */ jsx(
422
+ "div",
423
+ {
424
+ style: {
425
+ flex: 1,
426
+ minHeight: 0,
427
+ overflow: "auto",
428
+ padding: 24,
429
+ ...bodyStyle
430
+ },
431
+ children
432
+ }
433
+ ),
434
+ shouldRenderFooter ? /* @__PURE__ */ jsx(
435
+ "div",
436
+ {
437
+ style: {
438
+ display: "flex",
439
+ justifyContent: "flex-end",
440
+ gap: 12,
441
+ padding: "16px 24px 24px",
442
+ borderTop: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`
443
+ },
444
+ children: footerContent
445
+ }
446
+ ) : null
447
+ ]
448
+ }
449
+ )
450
+ }
451
+ );
452
+ }
453
+ function Modal(props) {
454
+ return /* @__PURE__ */ jsx(UnifiedModal, { ...normalizeModalProps(props) });
455
+ }
456
+
457
+ export {
458
+ Modal
459
+ };
460
+ //# sourceMappingURL=chunk-UIFTQDYM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Modal.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\n\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 description?: 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 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};\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 : '1.3rem',\n boxSizing: 'border-box',\n cursor: disabled ? 'not-allowed' : 'pointer',\n fontWeight: 700,\n fontSize: '1.3rem',\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 5px',\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 UnifiedModal({\n isOpen,\n onClose,\n children,\n title,\n description,\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\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 (!disableDismiss && 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, disableDismiss, isOpen, onClose]);\n\n if (!isOpen) {\n return null;\n }\n\n const resolvedHeader = headerContent ?? (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {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 {description ? (\n <p\n style={{\n margin: 0,\n color: modalTheme.mutedText,\n fontSize: 15,\n lineHeight: 1.6,\n }}\n >\n {description}\n </p>\n ) : null}\n </div>\n );\n\n let footerContent = footer;\n\n if (footerContent === undefined) {\n if (closeAction && !closeAction.hidden) {\n footerContent = <ModalActionButton action={closeAction} theme={modalTheme} />;\n } else {\n const resolvedActions = [\n cancelAction\n ? { ...cancelAction, appearance: cancelAction.appearance ?? 'text' }\n : undefined,\n ...(extraActions ?? []).map((action) => ({\n ...action,\n appearance: action.appearance ?? 'contained',\n })),\n confirmAction\n ? { ...confirmAction, appearance: confirmAction.appearance ?? 'contained' }\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-modal=\"true\"\n role=\"dialog\"\n onMouseDown={(event) => {\n if (!disableDismiss && 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 id={isBusy ? 'ldg1' : undefined}\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 opacity: isBusy ? 0.5 : 1,\n ...contentStyle,\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 16,\n padding: '24px 24px 16px',\n borderBottom: `1px solid ${withAlpha(modalTheme.colors.onSurface, 0.06)}`,\n }}\n >\n <div style={{ flex: 1 }}>{resolvedHeader}</div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>\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: 42,\n width: 42,\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={disableDismiss ? undefined : onClose}\n style={{\n height: 42,\n width: 42,\n borderRadius: 999,\n border: `1px solid ${modalTheme.borderSoft}`,\n backgroundColor: 'transparent',\n color: modalTheme.colors.onSurface,\n cursor: disableDismiss ? 'not-allowed' : 'pointer',\n fontSize: 20,\n fontWeight: 700,\n opacity: disableDismiss ? 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 overflow: 'auto',\n padding: 24,\n ...bodyStyle,\n }}\n >\n {children}\n </div>\n\n {shouldRenderFooter ? (\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 12,\n padding: '16px 24px 24px',\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"],"mappings":"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","names":["_a"]}