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 +36 -24
- package/dist/{chunk-UIFTQDYM.js → chunk-YWH2VIAD.js} +177 -64
- package/dist/chunk-YWH2VIAD.js.map +1 -0
- package/dist/index.cjs +1258 -303
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -17
- package/dist/index.d.ts +59 -17
- package/dist/index.js +1052 -206
- package/dist/index.js.map +1 -1
- package/dist/{modal-CS9SuYSC.d.cts → modal-B2lmASXk.d.cts} +3 -4
- package/dist/{modal-CS9SuYSC.d.ts → modal-B2lmASXk.d.ts} +3 -4
- package/dist/modal.cjs +175 -63
- package/dist/modal.cjs.map +1 -1
- package/dist/modal.d.cts +2 -2
- package/dist/modal.d.ts +2 -2
- package/dist/modal.js +1 -1
- package/package.json +5 -10
- package/dist/chunk-UIFTQDYM.js.map +0 -1
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-
|
|
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-
|
|
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(
|
|
26
|
+
export default function ExamplePage() {
|
|
25
27
|
return (
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
>
|
|
54
|
-
|
|
55
|
-
</
|
|
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
|
|
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,
|
|
126
|
-
- a mocked `
|
|
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
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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.
|
|
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.
|
|
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:
|
|
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 (!
|
|
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,
|
|
323
|
+
}, [closeOnEscape, isOpen, onClose, shouldDisableDismiss]);
|
|
251
324
|
if (!isOpen) {
|
|
252
325
|
return null;
|
|
253
326
|
}
|
|
254
|
-
const resolvedHeader = headerContent != null ? headerContent : /* @__PURE__ */
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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(
|
|
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 ? {
|
|
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 ? {
|
|
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 (!
|
|
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:
|
|
369
|
-
padding: "
|
|
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(
|
|
374
|
-
|
|
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:
|
|
384
|
-
width:
|
|
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:
|
|
484
|
+
onClick: shouldDisableDismiss ? void 0 : onClose,
|
|
402
485
|
style: {
|
|
403
|
-
height:
|
|
404
|
-
width:
|
|
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:
|
|
492
|
+
cursor: shouldDisableDismiss ? "not-allowed" : "pointer",
|
|
410
493
|
fontSize: 20,
|
|
411
494
|
fontWeight: 700,
|
|
412
|
-
opacity:
|
|
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__ */
|
|
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:
|
|
441
|
-
padding: "
|
|
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-
|
|
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":"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","names":["_a"]}
|