@mehdashti/modals 0.1.0 → 0.2.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/dist/index.d.ts +97 -1
- package/dist/index.js +255 -4
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,58 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
|
+
interface DrawerProps {
|
|
5
|
+
/**
|
|
6
|
+
* Whether the drawer is open
|
|
7
|
+
*/
|
|
8
|
+
open?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Callback when drawer should close
|
|
11
|
+
*/
|
|
12
|
+
onClose?: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Drawer title
|
|
15
|
+
*/
|
|
16
|
+
title?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Drawer description (for accessibility)
|
|
19
|
+
*/
|
|
20
|
+
description?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Drawer content
|
|
23
|
+
*/
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* Side to slide from
|
|
27
|
+
*/
|
|
28
|
+
side?: "left" | "right" | "top" | "bottom";
|
|
29
|
+
/**
|
|
30
|
+
* Drawer size
|
|
31
|
+
*/
|
|
32
|
+
size?: "sm" | "md" | "lg" | "xl" | "full";
|
|
33
|
+
/**
|
|
34
|
+
* Show close button
|
|
35
|
+
*/
|
|
36
|
+
showClose?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Allow dismissing by clicking outside or pressing Escape
|
|
39
|
+
*/
|
|
40
|
+
dismissable?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Custom className
|
|
43
|
+
*/
|
|
44
|
+
className?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Header content (overrides title)
|
|
47
|
+
*/
|
|
48
|
+
header?: React.ReactNode;
|
|
49
|
+
/**
|
|
50
|
+
* Footer content
|
|
51
|
+
*/
|
|
52
|
+
footer?: React.ReactNode;
|
|
53
|
+
}
|
|
54
|
+
declare function Drawer({ open, onClose, title, description, children, side, size, showClose, dismissable, className, header, footer, }: DrawerProps): react_jsx_runtime.JSX.Element;
|
|
55
|
+
|
|
4
56
|
/**
|
|
5
57
|
* Modal Types
|
|
6
58
|
*
|
|
@@ -141,6 +193,50 @@ declare function useModal(id: string): {
|
|
|
141
193
|
isOpen: boolean;
|
|
142
194
|
};
|
|
143
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Global Modal Utilities Hook
|
|
198
|
+
*
|
|
199
|
+
* Provides convenient methods for common modal patterns:
|
|
200
|
+
* - confirm(): Confirmation dialogs
|
|
201
|
+
* - alert(): Alert dialogs
|
|
202
|
+
* - prompt(): Input dialogs
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
interface ConfirmOptions {
|
|
206
|
+
title: string;
|
|
207
|
+
message: string;
|
|
208
|
+
confirmText?: string;
|
|
209
|
+
cancelText?: string;
|
|
210
|
+
variant?: "default" | "destructive";
|
|
211
|
+
}
|
|
212
|
+
interface AlertOptions {
|
|
213
|
+
title: string;
|
|
214
|
+
message: string;
|
|
215
|
+
okText?: string;
|
|
216
|
+
}
|
|
217
|
+
interface PromptOptions {
|
|
218
|
+
title: string;
|
|
219
|
+
message?: string;
|
|
220
|
+
placeholder?: string;
|
|
221
|
+
defaultValue?: string;
|
|
222
|
+
confirmText?: string;
|
|
223
|
+
cancelText?: string;
|
|
224
|
+
validate?: (value: string) => boolean | string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Hook providing global modal utilities
|
|
228
|
+
*/
|
|
229
|
+
declare function useModals(): {
|
|
230
|
+
openModal: (id: string, props: Omit<ModalProps, "open" | "onClose">) => void;
|
|
231
|
+
closeModal: (id: string) => void;
|
|
232
|
+
closeAllModals: () => void;
|
|
233
|
+
isModalOpen: (id: string) => boolean;
|
|
234
|
+
openModals: string[];
|
|
235
|
+
confirm: (options: ConfirmOptions) => Promise<boolean>;
|
|
236
|
+
alert: (options: AlertOptions) => Promise<void>;
|
|
237
|
+
prompt: (options: PromptOptions) => Promise<string | null>;
|
|
238
|
+
};
|
|
239
|
+
|
|
144
240
|
interface ModalProviderProps {
|
|
145
241
|
children: React.ReactNode;
|
|
146
242
|
}
|
|
@@ -157,4 +253,4 @@ declare function ModalProvider({ children }: ModalProviderProps): react_jsx_runt
|
|
|
157
253
|
*/
|
|
158
254
|
declare function useModalContext(): ModalContextValue;
|
|
159
255
|
|
|
160
|
-
export { ConfirmModal, type ConfirmModalProps, Modal, type ModalContextValue, type ModalProps, ModalProvider, useModal, useModalContext };
|
|
256
|
+
export { type AlertOptions, ConfirmModal, type ConfirmModalProps, type ConfirmOptions, Drawer, type DrawerProps, Modal, type ModalContextValue, type ModalProps, ModalProvider, type PromptOptions, useModal, useModalContext, useModals };
|
package/dist/index.js
CHANGED
|
@@ -144,9 +144,95 @@ function ConfirmModal({
|
|
|
144
144
|
);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
// src/components/drawer.tsx
|
|
148
|
+
import * as Dialog2 from "@radix-ui/react-dialog";
|
|
149
|
+
import { clsx as clsx2 } from "clsx";
|
|
150
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
151
|
+
var sizeClasses2 = {
|
|
152
|
+
sm: "max-w-sm",
|
|
153
|
+
md: "max-w-md",
|
|
154
|
+
lg: "max-w-lg",
|
|
155
|
+
xl: "max-w-xl",
|
|
156
|
+
full: "max-w-full"
|
|
157
|
+
};
|
|
158
|
+
var sideClasses = {
|
|
159
|
+
left: "left-0 top-0 h-full animate-slide-in-from-left",
|
|
160
|
+
right: "right-0 top-0 h-full animate-slide-in-from-right",
|
|
161
|
+
top: "top-0 left-0 w-full animate-slide-in-from-top",
|
|
162
|
+
bottom: "bottom-0 left-0 w-full animate-slide-in-from-bottom"
|
|
163
|
+
};
|
|
164
|
+
function Drawer({
|
|
165
|
+
open = false,
|
|
166
|
+
onClose,
|
|
167
|
+
title,
|
|
168
|
+
description,
|
|
169
|
+
children,
|
|
170
|
+
side = "right",
|
|
171
|
+
size = "md",
|
|
172
|
+
showClose = true,
|
|
173
|
+
dismissable = true,
|
|
174
|
+
className,
|
|
175
|
+
header,
|
|
176
|
+
footer
|
|
177
|
+
}) {
|
|
178
|
+
return /* @__PURE__ */ jsx3(Dialog2.Root, { open, onOpenChange: (open2) => !open2 && onClose?.(), children: /* @__PURE__ */ jsxs3(Dialog2.Portal, { children: [
|
|
179
|
+
/* @__PURE__ */ jsx3(Dialog2.Overlay, { className: "fixed inset-0 bg-black/50 backdrop-blur-sm z-50 animate-fade-in" }),
|
|
180
|
+
/* @__PURE__ */ jsxs3(
|
|
181
|
+
Dialog2.Content,
|
|
182
|
+
{
|
|
183
|
+
className: clsx2(
|
|
184
|
+
"fixed z-50 bg-white dark:bg-gray-900 shadow-xl",
|
|
185
|
+
"flex flex-col",
|
|
186
|
+
sideClasses[side],
|
|
187
|
+
(side === "left" || side === "right") && sizeClasses2[size],
|
|
188
|
+
(side === "top" || side === "bottom") && "h-auto",
|
|
189
|
+
className
|
|
190
|
+
),
|
|
191
|
+
onEscapeKeyDown: (e) => !dismissable && e.preventDefault(),
|
|
192
|
+
onPointerDownOutside: (e) => !dismissable && e.preventDefault(),
|
|
193
|
+
children: [
|
|
194
|
+
(header || title || description) && /* @__PURE__ */ jsx3("div", { className: "flex-shrink-0 border-b border-gray-200 dark:border-gray-800 p-6", children: header ? header : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
195
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between", children: [
|
|
196
|
+
title && /* @__PURE__ */ jsx3(Dialog2.Title, { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: title }),
|
|
197
|
+
showClose && /* @__PURE__ */ jsx3(
|
|
198
|
+
Dialog2.Close,
|
|
199
|
+
{
|
|
200
|
+
className: "rounded-md p-1 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors",
|
|
201
|
+
"aria-label": "Close",
|
|
202
|
+
children: /* @__PURE__ */ jsx3(
|
|
203
|
+
"svg",
|
|
204
|
+
{
|
|
205
|
+
className: "h-5 w-5 text-gray-500",
|
|
206
|
+
fill: "none",
|
|
207
|
+
viewBox: "0 0 24 24",
|
|
208
|
+
stroke: "currentColor",
|
|
209
|
+
children: /* @__PURE__ */ jsx3(
|
|
210
|
+
"path",
|
|
211
|
+
{
|
|
212
|
+
strokeLinecap: "round",
|
|
213
|
+
strokeLinejoin: "round",
|
|
214
|
+
strokeWidth: 2,
|
|
215
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
] }),
|
|
223
|
+
description && /* @__PURE__ */ jsx3(Dialog2.Description, { className: "mt-2 text-sm text-gray-600 dark:text-gray-400", children: description })
|
|
224
|
+
] }) }),
|
|
225
|
+
/* @__PURE__ */ jsx3("div", { className: "flex-1 overflow-y-auto p-6", children }),
|
|
226
|
+
footer && /* @__PURE__ */ jsx3("div", { className: "flex-shrink-0 border-t border-gray-200 dark:border-gray-800 p-6", children: footer })
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
] }) });
|
|
231
|
+
}
|
|
232
|
+
|
|
147
233
|
// src/context/modal-context.tsx
|
|
148
234
|
import * as React2 from "react";
|
|
149
|
-
import { jsx as
|
|
235
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
150
236
|
var ModalContext = React2.createContext(
|
|
151
237
|
void 0
|
|
152
238
|
);
|
|
@@ -183,9 +269,9 @@ function ModalProvider({ children }) {
|
|
|
183
269
|
isModalOpen,
|
|
184
270
|
openModals: modals.map((m) => m.id)
|
|
185
271
|
};
|
|
186
|
-
return /* @__PURE__ */
|
|
272
|
+
return /* @__PURE__ */ jsxs4(ModalContext.Provider, { value, children: [
|
|
187
273
|
children,
|
|
188
|
-
modals.map((modal) => /* @__PURE__ */
|
|
274
|
+
modals.map((modal) => /* @__PURE__ */ jsx4(
|
|
189
275
|
Modal,
|
|
190
276
|
{
|
|
191
277
|
open: true,
|
|
@@ -222,11 +308,176 @@ function useModal(id) {
|
|
|
222
308
|
isOpen: isModalOpen(id)
|
|
223
309
|
};
|
|
224
310
|
}
|
|
311
|
+
|
|
312
|
+
// src/hooks/use-modals.tsx
|
|
313
|
+
import * as React3 from "react";
|
|
314
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
315
|
+
function useModals() {
|
|
316
|
+
const context = useModalContext();
|
|
317
|
+
const confirm = React3.useCallback(
|
|
318
|
+
(options) => {
|
|
319
|
+
return new Promise((resolve) => {
|
|
320
|
+
const modalId = `confirm-${Date.now()}`;
|
|
321
|
+
const handleConfirm = () => {
|
|
322
|
+
context.closeModal(modalId);
|
|
323
|
+
resolve(true);
|
|
324
|
+
};
|
|
325
|
+
const handleCancel = () => {
|
|
326
|
+
context.closeModal(modalId);
|
|
327
|
+
resolve(false);
|
|
328
|
+
};
|
|
329
|
+
context.openModal(modalId, {
|
|
330
|
+
title: options.title,
|
|
331
|
+
size: "sm",
|
|
332
|
+
dismissable: true,
|
|
333
|
+
showClose: false,
|
|
334
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
|
|
335
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: options.message }),
|
|
336
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex justify-end gap-2", children: [
|
|
337
|
+
/* @__PURE__ */ jsx5(
|
|
338
|
+
"button",
|
|
339
|
+
{
|
|
340
|
+
onClick: handleCancel,
|
|
341
|
+
className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-700",
|
|
342
|
+
children: options.cancelText || "Cancel"
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
/* @__PURE__ */ jsx5(
|
|
346
|
+
"button",
|
|
347
|
+
{
|
|
348
|
+
onClick: handleConfirm,
|
|
349
|
+
className: `px-4 py-2 text-sm font-medium text-white rounded-md ${options.variant === "destructive" ? "bg-red-600 hover:bg-red-700" : "bg-blue-600 hover:bg-blue-700"}`,
|
|
350
|
+
children: options.confirmText || "Confirm"
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
] })
|
|
354
|
+
] })
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
},
|
|
358
|
+
[context]
|
|
359
|
+
);
|
|
360
|
+
const alert = React3.useCallback(
|
|
361
|
+
(options) => {
|
|
362
|
+
return new Promise((resolve) => {
|
|
363
|
+
const modalId = `alert-${Date.now()}`;
|
|
364
|
+
const handleOk = () => {
|
|
365
|
+
context.closeModal(modalId);
|
|
366
|
+
resolve();
|
|
367
|
+
};
|
|
368
|
+
context.openModal(modalId, {
|
|
369
|
+
title: options.title,
|
|
370
|
+
size: "sm",
|
|
371
|
+
dismissable: true,
|
|
372
|
+
showClose: false,
|
|
373
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
|
|
374
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: options.message }),
|
|
375
|
+
/* @__PURE__ */ jsx5("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx5(
|
|
376
|
+
"button",
|
|
377
|
+
{
|
|
378
|
+
onClick: handleOk,
|
|
379
|
+
className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700",
|
|
380
|
+
children: options.okText || "OK"
|
|
381
|
+
}
|
|
382
|
+
) })
|
|
383
|
+
] })
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
[context]
|
|
388
|
+
);
|
|
389
|
+
const prompt = React3.useCallback(
|
|
390
|
+
(options) => {
|
|
391
|
+
return new Promise((resolve) => {
|
|
392
|
+
const modalId = `prompt-${Date.now()}`;
|
|
393
|
+
let inputValue = options.defaultValue || "";
|
|
394
|
+
let errorMessage = "";
|
|
395
|
+
const PromptContent = () => {
|
|
396
|
+
const [value, setValue] = React3.useState(inputValue);
|
|
397
|
+
const [error, setError] = React3.useState("");
|
|
398
|
+
const handleConfirm = () => {
|
|
399
|
+
if (options.validate) {
|
|
400
|
+
const validation = options.validate(value);
|
|
401
|
+
if (validation === false || typeof validation === "string") {
|
|
402
|
+
setError(typeof validation === "string" ? validation : "Invalid input");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
context.closeModal(modalId);
|
|
407
|
+
resolve(value);
|
|
408
|
+
};
|
|
409
|
+
const handleCancel = () => {
|
|
410
|
+
context.closeModal(modalId);
|
|
411
|
+
resolve(null);
|
|
412
|
+
};
|
|
413
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
|
|
414
|
+
options.message && /* @__PURE__ */ jsx5("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: options.message }),
|
|
415
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
416
|
+
/* @__PURE__ */ jsx5(
|
|
417
|
+
"input",
|
|
418
|
+
{
|
|
419
|
+
type: "text",
|
|
420
|
+
value,
|
|
421
|
+
onChange: (e) => {
|
|
422
|
+
setValue(e.target.value);
|
|
423
|
+
setError("");
|
|
424
|
+
},
|
|
425
|
+
onKeyDown: (e) => {
|
|
426
|
+
if (e.key === "Enter") handleConfirm();
|
|
427
|
+
if (e.key === "Escape") handleCancel();
|
|
428
|
+
},
|
|
429
|
+
placeholder: options.placeholder,
|
|
430
|
+
autoFocus: true,
|
|
431
|
+
className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white"
|
|
432
|
+
}
|
|
433
|
+
),
|
|
434
|
+
error && /* @__PURE__ */ jsx5("p", { className: "mt-1 text-xs text-red-600 dark:text-red-400", children: error })
|
|
435
|
+
] }),
|
|
436
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex justify-end gap-2", children: [
|
|
437
|
+
/* @__PURE__ */ jsx5(
|
|
438
|
+
"button",
|
|
439
|
+
{
|
|
440
|
+
onClick: handleCancel,
|
|
441
|
+
className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-700",
|
|
442
|
+
children: options.cancelText || "Cancel"
|
|
443
|
+
}
|
|
444
|
+
),
|
|
445
|
+
/* @__PURE__ */ jsx5(
|
|
446
|
+
"button",
|
|
447
|
+
{
|
|
448
|
+
onClick: handleConfirm,
|
|
449
|
+
className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700",
|
|
450
|
+
children: options.confirmText || "OK"
|
|
451
|
+
}
|
|
452
|
+
)
|
|
453
|
+
] })
|
|
454
|
+
] });
|
|
455
|
+
};
|
|
456
|
+
context.openModal(modalId, {
|
|
457
|
+
title: options.title,
|
|
458
|
+
size: "sm",
|
|
459
|
+
dismissable: true,
|
|
460
|
+
showClose: false,
|
|
461
|
+
children: /* @__PURE__ */ jsx5(PromptContent, {})
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
},
|
|
465
|
+
[context]
|
|
466
|
+
);
|
|
467
|
+
return {
|
|
468
|
+
confirm,
|
|
469
|
+
alert,
|
|
470
|
+
prompt,
|
|
471
|
+
...context
|
|
472
|
+
};
|
|
473
|
+
}
|
|
225
474
|
export {
|
|
226
475
|
ConfirmModal,
|
|
476
|
+
Drawer,
|
|
227
477
|
Modal,
|
|
228
478
|
ModalProvider,
|
|
229
479
|
useModal,
|
|
230
|
-
useModalContext
|
|
480
|
+
useModalContext,
|
|
481
|
+
useModals
|
|
231
482
|
};
|
|
232
483
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/modal.tsx","../src/components/confirm-modal.tsx","../src/context/modal-context.tsx","../src/hooks/use-modal.ts"],"sourcesContent":["/**\n * Modal Component\n *\n * Modal dialog with Radix UI.\n */\n\nimport * as React from \"react\";\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { clsx } from \"clsx\";\nimport type { ModalProps } from \"../types/index.js\";\n\nconst sizeClasses = {\n sm: \"max-w-md\",\n md: \"max-w-lg\",\n lg: \"max-w-2xl\",\n xl: \"max-w-4xl\",\n full: \"max-w-full\",\n};\n\n/**\n * Modal Component\n *\n * Accessible modal dialog with stacking support.\n */\nexport function Modal({\n open = false,\n onClose,\n title,\n description,\n children,\n size = \"md\",\n showClose = true,\n className,\n dismissable = true,\n}: ModalProps) {\n return (\n <Dialog.Root open={open} onOpenChange={(open) => !open && onClose?.()}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <Dialog.Content\n className={clsx(\n \"fixed left-[50%] top-[50%] z-50 w-full translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]\",\n \"data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]\",\n \"sm:rounded-lg\",\n sizeClasses[size],\n className\n )}\n onEscapeKeyDown={(e) => {\n if (!dismissable) {\n e.preventDefault();\n }\n }}\n onPointerDownOutside={(e) => {\n if (!dismissable) {\n e.preventDefault();\n }\n }}\n >\n {(title || description) && (\n <div className=\"space-y-2\">\n {title && (\n <Dialog.Title className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </Dialog.Title>\n )}\n {description && (\n <Dialog.Description className=\"text-sm text-muted-foreground\">\n {description}\n </Dialog.Description>\n )}\n </div>\n )}\n\n <div className=\"mt-4\">{children}</div>\n\n {showClose && (\n <Dialog.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </Dialog.Close>\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","/**\n * Confirm Modal Component\n *\n * Confirmation dialog with confirm/cancel actions.\n */\n\nimport * as React from \"react\";\nimport { Modal } from \"./modal.js\";\nimport type { ConfirmModalProps } from \"../types/index.js\";\n\n/**\n * Confirm Modal\n *\n * Modal for confirming user actions.\n */\nexport function ConfirmModal({\n title,\n message,\n confirmText = \"Confirm\",\n cancelText = \"Cancel\",\n onConfirm,\n onCancel,\n variant = \"default\",\n}: ConfirmModalProps & { open?: boolean; onClose?: () => void }) {\n const [isLoading, setIsLoading] = React.useState(false);\n const [isOpen, setIsOpen] = React.useState(true);\n\n const handleConfirm = async () => {\n setIsLoading(true);\n try {\n await onConfirm();\n setIsOpen(false);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleCancel = () => {\n onCancel?.();\n setIsOpen(false);\n };\n\n return (\n <Modal\n open={isOpen}\n onClose={handleCancel}\n title={title}\n size=\"sm\"\n dismissable={!isLoading}\n >\n <div className=\"space-y-4\">\n <p className=\"text-sm text-muted-foreground\">{message}</p>\n\n <div className=\"flex justify-end space-x-2\">\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={isLoading}\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2\"\n >\n {cancelText}\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={isLoading}\n className={`inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2 ${\n variant === \"destructive\"\n ? \"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\"\n }`}\n >\n {isLoading ? \"Loading...\" : confirmText}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","/**\n * Modal Context\n *\n * Context for managing multiple modals with stacking support.\n */\n\nimport * as React from \"react\";\nimport type { ModalContextValue, ModalProps } from \"../types/index.js\";\nimport { Modal } from \"../components/modal.js\";\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\ninterface ModalState {\n id: string;\n props: Omit<ModalProps, \"open\" | \"onClose\">;\n}\n\nexport interface ModalProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Modal Provider\n *\n * Provides modal management functionality to the app.\n */\nexport function ModalProvider({ children }: ModalProviderProps) {\n const [modals, setModals] = React.useState<ModalState[]>([]);\n\n const openModal = React.useCallback(\n (id: string, props: Omit<ModalProps, \"open\" | \"onClose\">) => {\n setModals((prev) => {\n // If modal already exists, update it\n const existing = prev.find((m) => m.id === id);\n if (existing) {\n return prev.map((m) => (m.id === id ? { id, props } : m));\n }\n // Otherwise add new modal\n return [...prev, { id, props }];\n });\n },\n []\n );\n\n const closeModal = React.useCallback((id: string) => {\n setModals((prev) => prev.filter((m) => m.id !== id));\n }, []);\n\n const closeAllModals = React.useCallback(() => {\n setModals([]);\n }, []);\n\n const isModalOpen = React.useCallback(\n (id: string) => {\n return modals.some((m) => m.id === id);\n },\n [modals]\n );\n\n const value: ModalContextValue = {\n openModal,\n closeModal,\n closeAllModals,\n isModalOpen,\n openModals: modals.map((m) => m.id),\n };\n\n return (\n <ModalContext.Provider value={value}>\n {children}\n {modals.map((modal) => (\n <Modal\n key={modal.id}\n open={true}\n onClose={() => closeModal(modal.id)}\n {...modal.props}\n />\n ))}\n </ModalContext.Provider>\n );\n}\n\n/**\n * Use Modal Context\n *\n * Access modal management functions.\n */\nexport function useModalContext(): ModalContextValue {\n const context = React.useContext(ModalContext);\n\n if (!context) {\n throw new Error(\"useModalContext must be used within ModalProvider\");\n }\n\n return context;\n}\n","/**\n * useModal Hook\n *\n * Hook for programmatic modal control.\n */\n\nimport { useModalContext } from \"../context/modal-context.js\";\nimport type { ModalProps } from \"../types/index.js\";\n\n/**\n * Use Modal\n *\n * Get modal control functions for a specific modal ID.\n */\nexport function useModal(id: string) {\n const { openModal, closeModal, isModalOpen } = useModalContext();\n\n return {\n /**\n * Open this modal\n */\n open: (props: Omit<ModalProps, \"open\" | \"onClose\">) =>\n openModal(id, props),\n\n /**\n * Close this modal\n */\n close: () => closeModal(id),\n\n /**\n * Check if this modal is open\n */\n isOpen: isModalOpen(id),\n };\n}\n"],"mappings":"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","names":["open","jsx","jsxs","React","jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/modal.tsx","../src/components/confirm-modal.tsx","../src/components/drawer.tsx","../src/context/modal-context.tsx","../src/hooks/use-modal.ts","../src/hooks/use-modals.tsx"],"sourcesContent":["/**\n * Modal Component\n *\n * Modal dialog with Radix UI.\n */\n\nimport * as React from \"react\";\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { clsx } from \"clsx\";\nimport type { ModalProps } from \"../types/index.js\";\n\nconst sizeClasses = {\n sm: \"max-w-md\",\n md: \"max-w-lg\",\n lg: \"max-w-2xl\",\n xl: \"max-w-4xl\",\n full: \"max-w-full\",\n};\n\n/**\n * Modal Component\n *\n * Accessible modal dialog with stacking support.\n */\nexport function Modal({\n open = false,\n onClose,\n title,\n description,\n children,\n size = \"md\",\n showClose = true,\n className,\n dismissable = true,\n}: ModalProps) {\n return (\n <Dialog.Root open={open} onOpenChange={(open) => !open && onClose?.()}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <Dialog.Content\n className={clsx(\n \"fixed left-[50%] top-[50%] z-50 w-full translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]\",\n \"data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]\",\n \"sm:rounded-lg\",\n sizeClasses[size],\n className\n )}\n onEscapeKeyDown={(e) => {\n if (!dismissable) {\n e.preventDefault();\n }\n }}\n onPointerDownOutside={(e) => {\n if (!dismissable) {\n e.preventDefault();\n }\n }}\n >\n {(title || description) && (\n <div className=\"space-y-2\">\n {title && (\n <Dialog.Title className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </Dialog.Title>\n )}\n {description && (\n <Dialog.Description className=\"text-sm text-muted-foreground\">\n {description}\n </Dialog.Description>\n )}\n </div>\n )}\n\n <div className=\"mt-4\">{children}</div>\n\n {showClose && (\n <Dialog.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </Dialog.Close>\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","/**\n * Confirm Modal Component\n *\n * Confirmation dialog with confirm/cancel actions.\n */\n\nimport * as React from \"react\";\nimport { Modal } from \"./modal.js\";\nimport type { ConfirmModalProps } from \"../types/index.js\";\n\n/**\n * Confirm Modal\n *\n * Modal for confirming user actions.\n */\nexport function ConfirmModal({\n title,\n message,\n confirmText = \"Confirm\",\n cancelText = \"Cancel\",\n onConfirm,\n onCancel,\n variant = \"default\",\n}: ConfirmModalProps & { open?: boolean; onClose?: () => void }) {\n const [isLoading, setIsLoading] = React.useState(false);\n const [isOpen, setIsOpen] = React.useState(true);\n\n const handleConfirm = async () => {\n setIsLoading(true);\n try {\n await onConfirm();\n setIsOpen(false);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleCancel = () => {\n onCancel?.();\n setIsOpen(false);\n };\n\n return (\n <Modal\n open={isOpen}\n onClose={handleCancel}\n title={title}\n size=\"sm\"\n dismissable={!isLoading}\n >\n <div className=\"space-y-4\">\n <p className=\"text-sm text-muted-foreground\">{message}</p>\n\n <div className=\"flex justify-end space-x-2\">\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={isLoading}\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2\"\n >\n {cancelText}\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={isLoading}\n className={`inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2 ${\n variant === \"destructive\"\n ? \"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\"\n }`}\n >\n {isLoading ? \"Loading...\" : confirmText}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","/**\n * Drawer Component\n *\n * Side panel that slides in from left, right, top, or bottom.\n * Built on Radix UI Dialog for accessibility.\n */\n\nimport * as React from \"react\";\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { clsx } from \"clsx\";\n\nexport interface DrawerProps {\n /**\n * Whether the drawer is open\n */\n open?: boolean;\n\n /**\n * Callback when drawer should close\n */\n onClose?: () => void;\n\n /**\n * Drawer title\n */\n title?: string;\n\n /**\n * Drawer description (for accessibility)\n */\n description?: string;\n\n /**\n * Drawer content\n */\n children: React.ReactNode;\n\n /**\n * Side to slide from\n */\n side?: \"left\" | \"right\" | \"top\" | \"bottom\";\n\n /**\n * Drawer size\n */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n\n /**\n * Show close button\n */\n showClose?: boolean;\n\n /**\n * Allow dismissing by clicking outside or pressing Escape\n */\n dismissable?: boolean;\n\n /**\n * Custom className\n */\n className?: string;\n\n /**\n * Header content (overrides title)\n */\n header?: React.ReactNode;\n\n /**\n * Footer content\n */\n footer?: React.ReactNode;\n}\n\nconst sizeClasses = {\n sm: \"max-w-sm\",\n md: \"max-w-md\",\n lg: \"max-w-lg\",\n xl: \"max-w-xl\",\n full: \"max-w-full\",\n};\n\nconst sideClasses = {\n left: \"left-0 top-0 h-full animate-slide-in-from-left\",\n right: \"right-0 top-0 h-full animate-slide-in-from-right\",\n top: \"top-0 left-0 w-full animate-slide-in-from-top\",\n bottom: \"bottom-0 left-0 w-full animate-slide-in-from-bottom\",\n};\n\nexport function Drawer({\n open = false,\n onClose,\n title,\n description,\n children,\n side = \"right\",\n size = \"md\",\n showClose = true,\n dismissable = true,\n className,\n header,\n footer,\n}: DrawerProps) {\n return (\n <Dialog.Root open={open} onOpenChange={(open) => !open && onClose?.()}>\n <Dialog.Portal>\n {/* Overlay */}\n <Dialog.Overlay className=\"fixed inset-0 bg-black/50 backdrop-blur-sm z-50 animate-fade-in\" />\n\n {/* Drawer Content */}\n <Dialog.Content\n className={clsx(\n \"fixed z-50 bg-white dark:bg-gray-900 shadow-xl\",\n \"flex flex-col\",\n sideClasses[side],\n (side === \"left\" || side === \"right\") && sizeClasses[size],\n (side === \"top\" || side === \"bottom\") && \"h-auto\",\n className\n )}\n onEscapeKeyDown={(e) => !dismissable && e.preventDefault()}\n onPointerDownOutside={(e) => !dismissable && e.preventDefault()}\n >\n {/* Header */}\n {(header || title || description) && (\n <div className=\"flex-shrink-0 border-b border-gray-200 dark:border-gray-800 p-6\">\n {header ? (\n header\n ) : (\n <>\n <div className=\"flex items-start justify-between\">\n {title && (\n <Dialog.Title className=\"text-lg font-semibold text-gray-900 dark:text-gray-100\">\n {title}\n </Dialog.Title>\n )}\n {showClose && (\n <Dialog.Close\n className=\"rounded-md p-1 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\"\n aria-label=\"Close\"\n >\n <svg\n className=\"h-5 w-5 text-gray-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </Dialog.Close>\n )}\n </div>\n {description && (\n <Dialog.Description className=\"mt-2 text-sm text-gray-600 dark:text-gray-400\">\n {description}\n </Dialog.Description>\n )}\n </>\n )}\n </div>\n )}\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto p-6\">{children}</div>\n\n {/* Footer */}\n {footer && (\n <div className=\"flex-shrink-0 border-t border-gray-200 dark:border-gray-800 p-6\">\n {footer}\n </div>\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","/**\n * Modal Context\n *\n * Context for managing multiple modals with stacking support.\n */\n\nimport * as React from \"react\";\nimport type { ModalContextValue, ModalProps } from \"../types/index.js\";\nimport { Modal } from \"../components/modal.js\";\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\ninterface ModalState {\n id: string;\n props: Omit<ModalProps, \"open\" | \"onClose\">;\n}\n\nexport interface ModalProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Modal Provider\n *\n * Provides modal management functionality to the app.\n */\nexport function ModalProvider({ children }: ModalProviderProps) {\n const [modals, setModals] = React.useState<ModalState[]>([]);\n\n const openModal = React.useCallback(\n (id: string, props: Omit<ModalProps, \"open\" | \"onClose\">) => {\n setModals((prev) => {\n // If modal already exists, update it\n const existing = prev.find((m) => m.id === id);\n if (existing) {\n return prev.map((m) => (m.id === id ? { id, props } : m));\n }\n // Otherwise add new modal\n return [...prev, { id, props }];\n });\n },\n []\n );\n\n const closeModal = React.useCallback((id: string) => {\n setModals((prev) => prev.filter((m) => m.id !== id));\n }, []);\n\n const closeAllModals = React.useCallback(() => {\n setModals([]);\n }, []);\n\n const isModalOpen = React.useCallback(\n (id: string) => {\n return modals.some((m) => m.id === id);\n },\n [modals]\n );\n\n const value: ModalContextValue = {\n openModal,\n closeModal,\n closeAllModals,\n isModalOpen,\n openModals: modals.map((m) => m.id),\n };\n\n return (\n <ModalContext.Provider value={value}>\n {children}\n {modals.map((modal) => (\n <Modal\n key={modal.id}\n open={true}\n onClose={() => closeModal(modal.id)}\n {...modal.props}\n />\n ))}\n </ModalContext.Provider>\n );\n}\n\n/**\n * Use Modal Context\n *\n * Access modal management functions.\n */\nexport function useModalContext(): ModalContextValue {\n const context = React.useContext(ModalContext);\n\n if (!context) {\n throw new Error(\"useModalContext must be used within ModalProvider\");\n }\n\n return context;\n}\n","/**\n * useModal Hook\n *\n * Hook for programmatic modal control.\n */\n\nimport { useModalContext } from \"../context/modal-context.js\";\nimport type { ModalProps } from \"../types/index.js\";\n\n/**\n * Use Modal\n *\n * Get modal control functions for a specific modal ID.\n */\nexport function useModal(id: string) {\n const { openModal, closeModal, isModalOpen } = useModalContext();\n\n return {\n /**\n * Open this modal\n */\n open: (props: Omit<ModalProps, \"open\" | \"onClose\">) =>\n openModal(id, props),\n\n /**\n * Close this modal\n */\n close: () => closeModal(id),\n\n /**\n * Check if this modal is open\n */\n isOpen: isModalOpen(id),\n };\n}\n","/**\n * Global Modal Utilities Hook\n *\n * Provides convenient methods for common modal patterns:\n * - confirm(): Confirmation dialogs\n * - alert(): Alert dialogs\n * - prompt(): Input dialogs\n */\n\nimport * as React from \"react\";\nimport { useModalContext } from \"../context/index.js\";\nimport type { ModalProps } from \"../types/index.js\";\n\nexport interface ConfirmOptions {\n title: string;\n message: string;\n confirmText?: string;\n cancelText?: string;\n variant?: \"default\" | \"destructive\";\n}\n\nexport interface AlertOptions {\n title: string;\n message: string;\n okText?: string;\n}\n\nexport interface PromptOptions {\n title: string;\n message?: string;\n placeholder?: string;\n defaultValue?: string;\n confirmText?: string;\n cancelText?: string;\n validate?: (value: string) => boolean | string;\n}\n\n/**\n * Hook providing global modal utilities\n */\nexport function useModals() {\n const context = useModalContext();\n\n /**\n * Show confirmation dialog\n * @returns Promise that resolves to true if confirmed, false if cancelled\n */\n const confirm = React.useCallback(\n (options: ConfirmOptions): Promise<boolean> => {\n return new Promise((resolve) => {\n const modalId = `confirm-${Date.now()}`;\n\n const handleConfirm = () => {\n context.closeModal(modalId);\n resolve(true);\n };\n\n const handleCancel = () => {\n context.closeModal(modalId);\n resolve(false);\n };\n\n context.openModal(modalId, {\n title: options.title,\n size: \"sm\",\n dismissable: true,\n showClose: false,\n children: (\n <div className=\"space-y-4\">\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n {options.message}\n </p>\n <div className=\"flex justify-end gap-2\">\n <button\n onClick={handleCancel}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-700\"\n >\n {options.cancelText || \"Cancel\"}\n </button>\n <button\n onClick={handleConfirm}\n className={`px-4 py-2 text-sm font-medium text-white rounded-md ${\n options.variant === \"destructive\"\n ? \"bg-red-600 hover:bg-red-700\"\n : \"bg-blue-600 hover:bg-blue-700\"\n }`}\n >\n {options.confirmText || \"Confirm\"}\n </button>\n </div>\n </div>\n ),\n });\n });\n },\n [context]\n );\n\n /**\n * Show alert dialog\n * @returns Promise that resolves when dismissed\n */\n const alert = React.useCallback(\n (options: AlertOptions): Promise<void> => {\n return new Promise((resolve) => {\n const modalId = `alert-${Date.now()}`;\n\n const handleOk = () => {\n context.closeModal(modalId);\n resolve();\n };\n\n context.openModal(modalId, {\n title: options.title,\n size: \"sm\",\n dismissable: true,\n showClose: false,\n children: (\n <div className=\"space-y-4\">\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n {options.message}\n </p>\n <div className=\"flex justify-end\">\n <button\n onClick={handleOk}\n className=\"px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700\"\n >\n {options.okText || \"OK\"}\n </button>\n </div>\n </div>\n ),\n });\n });\n },\n [context]\n );\n\n /**\n * Show prompt dialog\n * @returns Promise that resolves to the input value if confirmed, null if cancelled\n */\n const prompt = React.useCallback(\n (options: PromptOptions): Promise<string | null> => {\n return new Promise((resolve) => {\n const modalId = `prompt-${Date.now()}`;\n let inputValue = options.defaultValue || \"\";\n let errorMessage = \"\";\n\n const PromptContent = () => {\n const [value, setValue] = React.useState(inputValue);\n const [error, setError] = React.useState(\"\");\n\n const handleConfirm = () => {\n if (options.validate) {\n const validation = options.validate(value);\n if (validation === false || typeof validation === \"string\") {\n setError(typeof validation === \"string\" ? validation : \"Invalid input\");\n return;\n }\n }\n context.closeModal(modalId);\n resolve(value);\n };\n\n const handleCancel = () => {\n context.closeModal(modalId);\n resolve(null);\n };\n\n return (\n <div className=\"space-y-4\">\n {options.message && (\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n {options.message}\n </p>\n )}\n <div>\n <input\n type=\"text\"\n value={value}\n onChange={(e) => {\n setValue(e.target.value);\n setError(\"\");\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleConfirm();\n if (e.key === \"Escape\") handleCancel();\n }}\n placeholder={options.placeholder}\n autoFocus\n className=\"w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white\"\n />\n {error && (\n <p className=\"mt-1 text-xs text-red-600 dark:text-red-400\">\n {error}\n </p>\n )}\n </div>\n <div className=\"flex justify-end gap-2\">\n <button\n onClick={handleCancel}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-700\"\n >\n {options.cancelText || \"Cancel\"}\n </button>\n <button\n onClick={handleConfirm}\n className=\"px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700\"\n >\n {options.confirmText || \"OK\"}\n </button>\n </div>\n </div>\n );\n };\n\n context.openModal(modalId, {\n title: options.title,\n size: \"sm\",\n dismissable: true,\n showClose: false,\n children: <PromptContent />,\n });\n });\n },\n [context]\n );\n\n return {\n confirm,\n alert,\n prompt,\n ...context,\n };\n}\n"],"mappings":"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","names":["open","jsx","jsxs","Dialog","clsx","jsx","jsxs","sizeClasses","open","React","jsx","jsxs","React","jsx","jsxs"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mehdashti/modals",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Enterprise-grade modal and drawer management with global utilities for Smart Platform",
|
|
5
5
|
"author": "mehdashti",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -52,8 +52,12 @@
|
|
|
52
52
|
"react",
|
|
53
53
|
"modal",
|
|
54
54
|
"dialog",
|
|
55
|
+
"drawer",
|
|
55
56
|
"radix-ui",
|
|
56
57
|
"stacking",
|
|
58
|
+
"confirm",
|
|
59
|
+
"alert",
|
|
60
|
+
"prompt",
|
|
57
61
|
"smart-platform"
|
|
58
62
|
]
|
|
59
63
|
}
|