@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 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 jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
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__ */ jsxs3(ModalContext.Provider, { value, children: [
272
+ return /* @__PURE__ */ jsxs4(ModalContext.Provider, { value, children: [
187
273
  children,
188
- modals.map((modal) => /* @__PURE__ */ jsx3(
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":";AAOA,YAAY,YAAY;AACxB,SAAS,YAAY;AA8Bb,cAyBI,YAzBJ;AA3BR,IAAM,cAAc;AAAA,EAClB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AACR;AAOO,SAAS,MAAM;AAAA,EACpB,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ;AAAA,EACA,cAAc;AAChB,GAAe;AACb,SACE,oBAAQ,aAAP,EAAY,MAAY,cAAc,CAACA,UAAS,CAACA,SAAQ,UAAU,GAClE,+BAAQ,eAAP,EACC;AAAA,wBAAQ,gBAAP,EAAe,WAAU,qJAAoJ;AAAA,IAC9K;AAAA,MAAQ;AAAA,MAAP;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,YAAY,IAAI;AAAA,UAChB;AAAA,QACF;AAAA,QACA,iBAAiB,CAAC,MAAM;AACtB,cAAI,CAAC,aAAa;AAChB,cAAE,eAAe;AAAA,UACnB;AAAA,QACF;AAAA,QACA,sBAAsB,CAAC,MAAM;AAC3B,cAAI,CAAC,aAAa;AAChB,cAAE,eAAe;AAAA,UACnB;AAAA,QACF;AAAA,QAEE;AAAA,oBAAS,gBACT,qBAAC,SAAI,WAAU,aACZ;AAAA,qBACC,oBAAQ,cAAP,EAAa,WAAU,qDACrB,iBACH;AAAA,YAED,eACC,oBAAQ,oBAAP,EAAmB,WAAU,iCAC3B,uBACH;AAAA,aAEJ;AAAA,UAGF,oBAAC,SAAI,WAAU,QAAQ,UAAS;AAAA,UAE/B,aACC,qBAAQ,cAAP,EAAa,WAAU,iRACtB;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,OAAM;AAAA,gBACN,QAAO;AAAA,gBACP,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,aAAY;AAAA,gBACZ,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,WAAU;AAAA,gBAEV;AAAA,sCAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK;AAAA,kBACpC,oBAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA;AAAA;AAAA,YACtC;AAAA,YACA,oBAAC,UAAK,WAAU,WAAU,mBAAK;AAAA,aACjC;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF,GACF;AAEJ;;;ACjGA,YAAY,WAAW;AA6Cf,gBAAAC,MAEA,QAAAC,aAFA;AApCD,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,UAAU;AACZ,GAAiE;AAC/D,QAAM,CAAC,WAAW,YAAY,IAAU,eAAS,KAAK;AACtD,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,IAAI;AAE/C,QAAM,gBAAgB,YAAY;AAChC,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,UAAU;AAChB,gBAAU,KAAK;AAAA,IACjB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,eAAe,MAAM;AACzB,eAAW;AACX,cAAU,KAAK;AAAA,EACjB;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA,MAAK;AAAA,MACL,aAAa,CAAC;AAAA,MAEd,0BAAAC,MAAC,SAAI,WAAU,aACb;AAAA,wBAAAD,KAAC,OAAE,WAAU,iCAAiC,mBAAQ;AAAA,QAEtD,gBAAAC,MAAC,SAAI,WAAU,8BACb;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAU;AAAA,cAET;AAAA;AAAA,UACH;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAW,uRACT,YAAY,gBACR,uEACA,wDACN;AAAA,cAEC,sBAAY,eAAe;AAAA;AAAA,UAC9B;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;;;ACxEA,YAAYE,YAAW;AAgEnB,SAGI,OAAAC,MAHJ,QAAAC,aAAA;AA5DJ,IAAM,eAAqB;AAAA,EACzB;AACF;AAgBO,SAAS,cAAc,EAAE,SAAS,GAAuB;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAAuB,CAAC,CAAC;AAE3D,QAAM,YAAkB;AAAA,IACtB,CAAC,IAAY,UAAgD;AAC3D,gBAAU,CAAC,SAAS;AAElB,cAAM,WAAW,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC7C,YAAI,UAAU;AACZ,iBAAO,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,EAAE,IAAI,MAAM,IAAI,CAAE;AAAA,QAC1D;AAEA,eAAO,CAAC,GAAG,MAAM,EAAE,IAAI,MAAM,CAAC;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,aAAmB,mBAAY,CAAC,OAAe;AACnD,cAAU,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,EACrD,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAuB,mBAAY,MAAM;AAC7C,cAAU,CAAC,CAAC;AAAA,EACd,GAAG,CAAC,CAAC;AAEL,QAAM,cAAoB;AAAA,IACxB,CAAC,OAAe;AACd,aAAO,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,IACvC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,QAA2B;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,EACpC;AAEA,SACE,gBAAAA,MAAC,aAAa,UAAb,EAAsB,OACpB;AAAA;AAAA,IACA,OAAO,IAAI,CAAC,UACX,gBAAAD;AAAA,MAAC;AAAA;AAAA,QAEC,MAAM;AAAA,QACN,SAAS,MAAM,WAAW,MAAM,EAAE;AAAA,QACjC,GAAG,MAAM;AAAA;AAAA,MAHL,MAAM;AAAA,IAIb,CACD;AAAA,KACH;AAEJ;AAOO,SAAS,kBAAqC;AACnD,QAAM,UAAgB,kBAAW,YAAY;AAE7C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,SAAO;AACT;;;ACnFO,SAAS,SAAS,IAAY;AACnC,QAAM,EAAE,WAAW,YAAY,YAAY,IAAI,gBAAgB;AAE/D,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,MAAM,CAAC,UACL,UAAU,IAAI,KAAK;AAAA;AAAA;AAAA;AAAA,IAKrB,OAAO,MAAM,WAAW,EAAE;AAAA;AAAA;AAAA;AAAA,IAK1B,QAAQ,YAAY,EAAE;AAAA,EACxB;AACF;","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.1.0",
4
- "description": "Modal management system with stacking support for Smart Platform",
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
  }