modalio 0.9.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 +157 -0
- package/dist/index.cjs +912 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +618 -0
- package/dist/index.d.ts +618 -0
- package/dist/index.js +874 -0
- package/dist/index.js.map +1 -0
- package/package.json +76 -0
- package/src/adapters.ts +567 -0
- package/src/api.ts +418 -0
- package/src/context.tsx +206 -0
- package/src/core.ts +226 -0
- package/src/hoc.tsx +114 -0
- package/src/hooks.ts +250 -0
- package/src/index.ts +81 -0
- package/src/modal-manager.ts +136 -0
- package/src/types.ts +243 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { JSXElementConstructor, ReactNode, Dispatch, ComponentType, Ref } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Internal key for modal configuration stored in data */
|
|
5
|
+
declare const MODAL_CONFIG_KEY: "__modalConfig";
|
|
6
|
+
/** Internal modal configuration shape */
|
|
7
|
+
interface InternalModalConfig {
|
|
8
|
+
disableClose?: boolean;
|
|
9
|
+
keepMounted?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* State for a single modal instance
|
|
13
|
+
*/
|
|
14
|
+
interface ModalState {
|
|
15
|
+
modalId: string;
|
|
16
|
+
data?: Record<string, unknown>;
|
|
17
|
+
isOpen?: boolean;
|
|
18
|
+
delayOpen?: boolean;
|
|
19
|
+
keepMounted?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Global modal store - maps modal IDs to their state
|
|
23
|
+
*/
|
|
24
|
+
interface ModalStore {
|
|
25
|
+
[key: string]: ModalState | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Modal lifecycle state
|
|
29
|
+
*/
|
|
30
|
+
type ModalLifecycleState = "open" | "closing" | "closed";
|
|
31
|
+
type ModalActionType = "show" | "hide" | "remove" | "set-flags";
|
|
32
|
+
interface ModalAction {
|
|
33
|
+
type: `modalio/${ModalActionType}`;
|
|
34
|
+
payload: {
|
|
35
|
+
modalId: string;
|
|
36
|
+
data?: Record<string, unknown>;
|
|
37
|
+
flags?: Record<string, unknown>;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Deferred promise with exposed resolve/reject handlers
|
|
42
|
+
*/
|
|
43
|
+
interface DeferredPromise<T = unknown> {
|
|
44
|
+
resolve: (value: T) => void;
|
|
45
|
+
reject: (reason: unknown) => void;
|
|
46
|
+
promise: Promise<T>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read-only state of a modal instance
|
|
50
|
+
*/
|
|
51
|
+
interface ModalReadState<TData = Record<string, unknown>> {
|
|
52
|
+
/** The modal's unique identifier */
|
|
53
|
+
readonly modalId: string;
|
|
54
|
+
/** Data passed to the modal via open() */
|
|
55
|
+
readonly data: TData | undefined;
|
|
56
|
+
/** Whether the modal is currently open */
|
|
57
|
+
readonly isOpen: boolean;
|
|
58
|
+
/** Whether to keep the modal mounted after closing */
|
|
59
|
+
readonly keepMounted: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Methods for controlling a modal
|
|
63
|
+
*/
|
|
64
|
+
interface ModalControls<TData = Record<string, unknown>> {
|
|
65
|
+
/** Open the modal with optional data */
|
|
66
|
+
open: (data?: TData) => Promise<unknown>;
|
|
67
|
+
/** Close the modal and resolve with a result */
|
|
68
|
+
close: (result?: unknown) => void;
|
|
69
|
+
/** Dismiss the modal (close without result, resolves undefined) */
|
|
70
|
+
dismiss: () => void;
|
|
71
|
+
/** Remove the modal from the DOM immediately */
|
|
72
|
+
remove: () => void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Internal methods for animation lifecycle (used by adapters)
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
interface ModalAnimationHandlers {
|
|
79
|
+
/** Called when closing animation completes */
|
|
80
|
+
onAnimationEnd: () => void;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Complete modal handler returned by useModal hook
|
|
84
|
+
* Combines state, controls, and animation handlers
|
|
85
|
+
*/
|
|
86
|
+
interface ModalHandler<TData = Record<string, unknown>> extends ModalReadState<TData>, ModalControls<TData>, ModalAnimationHandlers {
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Props injected into HOC-wrapped modal components
|
|
90
|
+
* Note: Uses `modalId` instead of `id` to avoid conflicts with common props
|
|
91
|
+
*/
|
|
92
|
+
interface ModalHocProps {
|
|
93
|
+
modalId: string;
|
|
94
|
+
defaultOpen?: boolean;
|
|
95
|
+
keepMounted?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Extract props from a component type, excluding HOC props
|
|
99
|
+
*/
|
|
100
|
+
type ModalProps<T> = T extends JSXElementConstructor<infer P> ? Omit<P, keyof ModalHocProps> : Record<string, unknown>;
|
|
101
|
+
/**
|
|
102
|
+
* Props for the ModalProvider component
|
|
103
|
+
*/
|
|
104
|
+
interface ModalProviderProps {
|
|
105
|
+
children?: ReactNode;
|
|
106
|
+
/** Optional external dispatch for state management integration */
|
|
107
|
+
dispatch?: Dispatch<ModalAction>;
|
|
108
|
+
/** Optional external modal store */
|
|
109
|
+
modals?: ModalStore;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Modal reference for programmatic control
|
|
113
|
+
* Provides lifecycle promises and control methods
|
|
114
|
+
*/
|
|
115
|
+
interface ModalRef<TResult = unknown, TData = unknown> {
|
|
116
|
+
/** Unique identifier for this modal instance */
|
|
117
|
+
readonly modalId: string;
|
|
118
|
+
/** Data passed to the modal */
|
|
119
|
+
readonly data: TData | undefined;
|
|
120
|
+
/** Whether the user is allowed to close the modal (via escape/outside click) */
|
|
121
|
+
disableClose: boolean;
|
|
122
|
+
/** Close the modal with an optional result */
|
|
123
|
+
close: (result?: TResult) => void;
|
|
124
|
+
/** Promise that resolves when the modal opening animation completes */
|
|
125
|
+
afterOpened: () => Promise<void>;
|
|
126
|
+
/** Promise that resolves with the result when the modal closing animation completes */
|
|
127
|
+
afterClosed: () => Promise<TResult | undefined>;
|
|
128
|
+
/** Promise that resolves when the modal starts closing (before animation) */
|
|
129
|
+
beforeClosed: () => Promise<TResult | undefined>;
|
|
130
|
+
/** Update the data passed to the modal */
|
|
131
|
+
updateData: (data: Partial<TData>) => void;
|
|
132
|
+
/** Get the current lifecycle state of the modal */
|
|
133
|
+
getState: () => ModalLifecycleState;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Configuration for opening a modal
|
|
137
|
+
*/
|
|
138
|
+
interface ModalConfig<TData = unknown> {
|
|
139
|
+
/** Data to pass to the modal component */
|
|
140
|
+
readonly data?: TData;
|
|
141
|
+
/** Keep the modal mounted in DOM after closing (for animation performance) */
|
|
142
|
+
readonly keepMounted?: boolean;
|
|
143
|
+
/** Custom ID for the modal (auto-generated if not provided) */
|
|
144
|
+
readonly modalId?: string;
|
|
145
|
+
/** Whether clicking outside/escape closes the modal */
|
|
146
|
+
readonly disableClose?: boolean;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Props for Radix UI Dialog root component
|
|
150
|
+
*/
|
|
151
|
+
interface RadixDialogProps {
|
|
152
|
+
open: boolean;
|
|
153
|
+
onOpenChange: (open: boolean) => void;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Props for Radix UI Dialog content component
|
|
157
|
+
*/
|
|
158
|
+
interface RadixDialogContentProps {
|
|
159
|
+
onAnimationEndCapture: () => void;
|
|
160
|
+
onEscapeKeyDown: (e?: Event) => void;
|
|
161
|
+
onPointerDownOutside: (e?: Event) => void;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Combined props for Shadcn Dialog
|
|
165
|
+
*/
|
|
166
|
+
interface ShadcnDialogProps extends RadixDialogProps {
|
|
167
|
+
onClose: () => void;
|
|
168
|
+
onAnimationEndCapture: () => void;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Options for adapter behavior
|
|
173
|
+
*/
|
|
174
|
+
interface AdapterOptions {
|
|
175
|
+
/** Prevent closing via escape key or clicking outside */
|
|
176
|
+
disableClose?: boolean;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Adapter for Radix UI Dialog root component
|
|
180
|
+
*/
|
|
181
|
+
declare const radixUiDialog: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogProps;
|
|
182
|
+
/**
|
|
183
|
+
* Adapter for Radix UI Dialog.Content component
|
|
184
|
+
*/
|
|
185
|
+
declare const radixUiDialogContent: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogContentProps;
|
|
186
|
+
/**
|
|
187
|
+
* Adapter for Radix UI AlertDialog root component
|
|
188
|
+
*/
|
|
189
|
+
declare const radixUiAlertDialog: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogProps;
|
|
190
|
+
/**
|
|
191
|
+
* Adapter for Radix UI AlertDialog.Content component
|
|
192
|
+
*/
|
|
193
|
+
declare const radixUiAlertDialogContent: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogContentProps;
|
|
194
|
+
/**
|
|
195
|
+
* Adapter for Shadcn UI Dialog
|
|
196
|
+
*/
|
|
197
|
+
declare const shadcnUiDialog: (modal: ModalHandler, options?: AdapterOptions) => ShadcnDialogProps;
|
|
198
|
+
/**
|
|
199
|
+
* Adapter for Shadcn UI DialogContent
|
|
200
|
+
*/
|
|
201
|
+
declare const shadcnUiDialogContent: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogContentProps;
|
|
202
|
+
/**
|
|
203
|
+
* Adapter for Shadcn UI AlertDialog
|
|
204
|
+
*/
|
|
205
|
+
declare const shadcnUiAlertDialog: (modal: ModalHandler, options?: AdapterOptions) => ShadcnDialogProps;
|
|
206
|
+
/**
|
|
207
|
+
* Adapter for Shadcn UI AlertDialogContent
|
|
208
|
+
*/
|
|
209
|
+
declare const shadcnUiAlertDialogContent: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogContentProps;
|
|
210
|
+
/**
|
|
211
|
+
* Adapter for Shadcn UI Sheet
|
|
212
|
+
*/
|
|
213
|
+
declare const shadcnUiSheet: (modal: ModalHandler, options?: AdapterOptions) => ShadcnDialogProps;
|
|
214
|
+
/**
|
|
215
|
+
* Adapter for Shadcn UI SheetContent
|
|
216
|
+
*/
|
|
217
|
+
declare const shadcnUiSheetContent: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogContentProps;
|
|
218
|
+
/**
|
|
219
|
+
* Adapter for Shadcn UI Popover
|
|
220
|
+
*/
|
|
221
|
+
declare const shadcnUiPopover: (modal: ModalHandler, options?: AdapterOptions) => {
|
|
222
|
+
open: boolean;
|
|
223
|
+
onOpenChange: (open: boolean) => void;
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Props returned by Shadcn UI Drawer adapters
|
|
227
|
+
*/
|
|
228
|
+
interface ShadcnUiDrawerRootProps {
|
|
229
|
+
open: boolean;
|
|
230
|
+
onOpenChange: (open: boolean) => void;
|
|
231
|
+
dismissible?: boolean;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Props for Shadcn UI DrawerContent component
|
|
235
|
+
*/
|
|
236
|
+
interface ShadcnUiDrawerContentProps {
|
|
237
|
+
onAnimationEnd: () => void;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Adapter for Shadcn UI Drawer
|
|
241
|
+
*/
|
|
242
|
+
declare const shadcnUiDrawer: (modal: ModalHandler, options?: AdapterOptions) => ShadcnUiDrawerRootProps;
|
|
243
|
+
/**
|
|
244
|
+
* Adapter for Shadcn UI DrawerContent component
|
|
245
|
+
*/
|
|
246
|
+
declare const shadcnUiDrawerContent: (modal: ModalHandler) => ShadcnUiDrawerContentProps;
|
|
247
|
+
/**
|
|
248
|
+
* Adapter for Radix UI Sheet root component
|
|
249
|
+
*/
|
|
250
|
+
declare const radixUiSheet: (modal: ModalHandler, options?: AdapterOptions) => {
|
|
251
|
+
open: boolean;
|
|
252
|
+
onOpenChange: (open: boolean) => void;
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Adapter for Radix UI Sheet.Content component
|
|
256
|
+
*/
|
|
257
|
+
declare const radixUiSheetContent: (modal: ModalHandler, options?: AdapterOptions) => RadixDialogContentProps;
|
|
258
|
+
/**
|
|
259
|
+
* Adapter for Radix UI Popover
|
|
260
|
+
*/
|
|
261
|
+
declare const radixUiPopover: (modal: ModalHandler, options?: AdapterOptions) => {
|
|
262
|
+
open: boolean;
|
|
263
|
+
onOpenChange: (open: boolean) => void;
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Props returned by Base UI dialog adapters
|
|
267
|
+
*/
|
|
268
|
+
interface BaseUiDialogRootProps {
|
|
269
|
+
open: boolean;
|
|
270
|
+
onOpenChange: (open: boolean) => void;
|
|
271
|
+
dismissible?: boolean;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Props for Base UI Dialog.Portal component
|
|
275
|
+
*/
|
|
276
|
+
interface BaseUiDialogPortalProps {
|
|
277
|
+
keepMounted?: boolean;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Props for Base UI Dialog.Popup component
|
|
281
|
+
*/
|
|
282
|
+
interface BaseUiDialogPopupProps {
|
|
283
|
+
onAnimationEnd: () => void;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Adapter for Base UI Dialog.Root component
|
|
287
|
+
*/
|
|
288
|
+
declare const baseUiDialog: (modal: ModalHandler, options?: AdapterOptions) => BaseUiDialogRootProps;
|
|
289
|
+
/**
|
|
290
|
+
* Adapter for Base UI Dialog.Portal component
|
|
291
|
+
*/
|
|
292
|
+
declare const baseUiDialogPortal: (modal: ModalHandler) => BaseUiDialogPortalProps;
|
|
293
|
+
/**
|
|
294
|
+
* Adapter for Base UI Dialog.Popup component
|
|
295
|
+
*/
|
|
296
|
+
declare const baseUiDialogPopup: (modal: ModalHandler) => BaseUiDialogPopupProps;
|
|
297
|
+
/**
|
|
298
|
+
* Adapter for Base UI AlertDialog root component
|
|
299
|
+
*/
|
|
300
|
+
declare const baseUiAlertDialog: (modal: ModalHandler, options?: AdapterOptions) => BaseUiDialogRootProps;
|
|
301
|
+
/**
|
|
302
|
+
* Adapter for Base UI AlertDialog.Portal component
|
|
303
|
+
*/
|
|
304
|
+
declare const baseUiAlertDialogPortal: (modal: ModalHandler) => BaseUiDialogPortalProps;
|
|
305
|
+
/**
|
|
306
|
+
* Adapter for Base UI AlertDialog.Popup component
|
|
307
|
+
*/
|
|
308
|
+
declare const baseUiAlertDialogPopup: (modal: ModalHandler) => BaseUiDialogPopupProps;
|
|
309
|
+
/**
|
|
310
|
+
* Props returned by Base UI popover adapters
|
|
311
|
+
*/
|
|
312
|
+
interface BaseUiPopoverRootProps {
|
|
313
|
+
open: boolean;
|
|
314
|
+
onOpenChange: (open: boolean) => void;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Props for Base UI Popover.Portal component
|
|
318
|
+
*/
|
|
319
|
+
interface BaseUiPopoverPortalProps {
|
|
320
|
+
keepMounted?: boolean;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Props for Base UI Popover.Popup component
|
|
324
|
+
*/
|
|
325
|
+
interface BaseUiPopoverPopupProps {
|
|
326
|
+
onAnimationEnd: () => void;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Adapter for Base UI Popover.Root component
|
|
330
|
+
*/
|
|
331
|
+
declare const baseUiPopover: (modal: ModalHandler, options?: AdapterOptions) => BaseUiPopoverRootProps;
|
|
332
|
+
/**
|
|
333
|
+
* Adapter for Base UI Popover.Portal component
|
|
334
|
+
*/
|
|
335
|
+
declare const baseUiPopoverPortal: (modal: ModalHandler) => BaseUiPopoverPortalProps;
|
|
336
|
+
/**
|
|
337
|
+
* Adapter for Base UI Popover.Popup component
|
|
338
|
+
*/
|
|
339
|
+
declare const baseUiPopoverPopup: (modal: ModalHandler) => BaseUiPopoverPopupProps;
|
|
340
|
+
/**
|
|
341
|
+
* Adapter for Base UI Sheet root component
|
|
342
|
+
*/
|
|
343
|
+
declare const baseUiSheet: (modal: ModalHandler, options?: AdapterOptions) => BaseUiDialogRootProps;
|
|
344
|
+
/**
|
|
345
|
+
* Adapter for Base UI Sheet.Portal component
|
|
346
|
+
*/
|
|
347
|
+
declare const baseUiSheetPortal: (modal: ModalHandler) => BaseUiDialogPortalProps;
|
|
348
|
+
/**
|
|
349
|
+
* Adapter for Base UI Sheet.Popup component
|
|
350
|
+
*/
|
|
351
|
+
declare const baseUiSheetPopup: (modal: ModalHandler) => BaseUiDialogPopupProps;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Context for the modal store
|
|
355
|
+
*/
|
|
356
|
+
declare const ModalContext: react.Context<ModalStore>;
|
|
357
|
+
/**
|
|
358
|
+
* Context for the current modal ID (used in HOC-wrapped components)
|
|
359
|
+
*/
|
|
360
|
+
declare const ModalIdContext: react.Context<string | null>;
|
|
361
|
+
/**
|
|
362
|
+
* Modal Provider - wrap your app with this to enable modal management
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```tsx
|
|
366
|
+
* // Basic usage
|
|
367
|
+
* <ModalProvider>
|
|
368
|
+
* <App />
|
|
369
|
+
* </ModalProvider>
|
|
370
|
+
*
|
|
371
|
+
* // With external state management (Redux, etc.)
|
|
372
|
+
* <ModalProvider dispatch={dispatch} modals={modals}>
|
|
373
|
+
* <App />
|
|
374
|
+
* </ModalProvider>
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
declare function ModalProvider({ children, dispatch: givenDispatch, modals: givenModals, }: ModalProviderProps): ReactNode;
|
|
378
|
+
/**
|
|
379
|
+
* Declarative modal definition component
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* <ModalDef id="my-modal" component={MyModal} />
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
declare function ModalDef({ id, component, }: {
|
|
387
|
+
id: string;
|
|
388
|
+
component: ComponentType<any>;
|
|
389
|
+
}): ReactNode;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get the modal ID from a string or component
|
|
393
|
+
*/
|
|
394
|
+
declare const getModalId: (modal: string | ComponentType<Record<string, unknown>>) => string;
|
|
395
|
+
/**
|
|
396
|
+
* Reducer for modal state management
|
|
397
|
+
*/
|
|
398
|
+
declare const reducer: (state: ModalStore, action: ModalAction) => ModalStore;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Hook to control a modal from within the modal component or from anywhere.
|
|
402
|
+
* Returns an enhanced handler with state and control methods.
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```tsx
|
|
406
|
+
* // Inside a modal component (uses context)
|
|
407
|
+
* const modal = useModal();
|
|
408
|
+
*
|
|
409
|
+
* return (
|
|
410
|
+
* <Dialog open={modal.open} onOpenChange={(open) => !open && modal.dismiss()}>
|
|
411
|
+
* <DialogContent onAnimationEnd={modal.onAnimationEnd}>
|
|
412
|
+
* <Button onClick={() => modal.close(result)}>Save</Button>
|
|
413
|
+
* <Button onClick={modal.dismiss}>Cancel</Button>
|
|
414
|
+
* </DialogContent>
|
|
415
|
+
* </Dialog>
|
|
416
|
+
* );
|
|
417
|
+
*
|
|
418
|
+
* // With a specific modal component
|
|
419
|
+
* const modal = useModal(MyModal);
|
|
420
|
+
* modal.open({ userId: '123' });
|
|
421
|
+
*
|
|
422
|
+
* // With a string ID
|
|
423
|
+
* const modal = useModal('my-modal');
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
declare function useModal(modal?: string, data?: Record<string, unknown>): ModalHandler;
|
|
427
|
+
declare function useModal<TProps extends Record<string, unknown>, P extends Partial<ModalProps<React.ComponentType<TProps & ModalHocProps>>>>(modal: React.ComponentType<TProps & ModalHocProps>, data?: P): ModalHandler<TProps>;
|
|
428
|
+
/**
|
|
429
|
+
* Hook to get typed data passed to a modal
|
|
430
|
+
* Must be used inside a modal component (within ModalIdContext)
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* ```tsx
|
|
434
|
+
* interface MyModalData {
|
|
435
|
+
* userId: string;
|
|
436
|
+
* userName: string;
|
|
437
|
+
* }
|
|
438
|
+
*
|
|
439
|
+
* const MyModal = createModal(() => {
|
|
440
|
+
* const data = useModalData<MyModalData>();
|
|
441
|
+
* const modal = useModal();
|
|
442
|
+
*
|
|
443
|
+
* return (
|
|
444
|
+
* <Dialog open={modal.open}>
|
|
445
|
+
* <DialogContent>
|
|
446
|
+
* <p>User: {data?.userName}</p>
|
|
447
|
+
* </DialogContent>
|
|
448
|
+
* </Dialog>
|
|
449
|
+
* );
|
|
450
|
+
* });
|
|
451
|
+
*
|
|
452
|
+
* // Usage:
|
|
453
|
+
* open(MyModal, { data: { userId: '123', userName: 'John' } });
|
|
454
|
+
* ```
|
|
455
|
+
*/
|
|
456
|
+
declare function useModalData<TData = Record<string, unknown>>(): TData | undefined;
|
|
457
|
+
/**
|
|
458
|
+
* Hook to get the modal config options (disableClose, keepMounted, etc.)
|
|
459
|
+
* Must be used inside a modal component
|
|
460
|
+
*/
|
|
461
|
+
declare function useModalConfig(): InternalModalConfig;
|
|
462
|
+
|
|
463
|
+
/** Props for components that accept a ref (React 19+ style) */
|
|
464
|
+
interface RefProp<T> {
|
|
465
|
+
ref?: Ref<T>;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Close a modal and return a promise that resolves when the animation completes
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```tsx
|
|
473
|
+
* await closeModal(MyModal);
|
|
474
|
+
* await closeModal('my-modal');
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
declare function closeModal<TResult = unknown>(modal: string | React.ComponentType<any>): Promise<TResult>;
|
|
478
|
+
/**
|
|
479
|
+
* Open a modal and return a ModalRef for controlling it
|
|
480
|
+
*
|
|
481
|
+
* @example
|
|
482
|
+
* ```tsx
|
|
483
|
+
* // Open a modal with typed data
|
|
484
|
+
* const modalRef = openModal<{ confirmed: boolean }, { userId: string }>(
|
|
485
|
+
* ConfirmModal,
|
|
486
|
+
* { data: { userId: '123' } }
|
|
487
|
+
* );
|
|
488
|
+
*
|
|
489
|
+
* // Wait for it to close
|
|
490
|
+
* const result = await modalRef.afterClosed();
|
|
491
|
+
* if (result?.confirmed) {
|
|
492
|
+
* // User confirmed
|
|
493
|
+
* }
|
|
494
|
+
*
|
|
495
|
+
* // Or close it programmatically
|
|
496
|
+
* modalRef.close({ confirmed: false });
|
|
497
|
+
*
|
|
498
|
+
* // Check lifecycle state
|
|
499
|
+
* if (modalRef.getState() === 'open') {
|
|
500
|
+
* modalRef.close();
|
|
501
|
+
* }
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
504
|
+
declare function openModal<TResult = unknown, TData = Record<string, unknown>, TProps extends Record<string, unknown> = Record<string, unknown>>(modal: React.ComponentType<TProps & ModalHocProps>, config?: ModalConfig<TData>): ModalRef<TResult, TData>;
|
|
505
|
+
declare function openModal<TResult = unknown, TData = Record<string, unknown>>(modal: string, config?: ModalConfig<TData>): ModalRef<TResult, TData>;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* ModalManager namespace - the primary API for managing modals.
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* ```tsx
|
|
512
|
+
* import { ModalManager } from "modalio";
|
|
513
|
+
*
|
|
514
|
+
* // Create a modal
|
|
515
|
+
* const MyModal = ModalManager.create<{ message: string }>(({ message }) => {
|
|
516
|
+
* const modal = useModal();
|
|
517
|
+
* return (
|
|
518
|
+
* <Dialog {...radixDialog(modal)}>
|
|
519
|
+
* <DialogContent {...radixDialogContent(modal)}>
|
|
520
|
+
* <p>{message}</p>
|
|
521
|
+
* <button onClick={() => modal.close(true)}>Confirm</button>
|
|
522
|
+
* </DialogContent>
|
|
523
|
+
* </Dialog>
|
|
524
|
+
* );
|
|
525
|
+
* });
|
|
526
|
+
*
|
|
527
|
+
* // Open it
|
|
528
|
+
* const result = await ModalManager.open(MyModal, {
|
|
529
|
+
* data: { message: "Hello!" }
|
|
530
|
+
* }).afterClosed();
|
|
531
|
+
*
|
|
532
|
+
* // Close it
|
|
533
|
+
* ModalManager.close(MyModal);
|
|
534
|
+
*
|
|
535
|
+
* // Close all modals
|
|
536
|
+
* ModalManager.closeAll();
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
declare const ModalManager: {
|
|
540
|
+
/**
|
|
541
|
+
* Create a modal component with lifecycle management.
|
|
542
|
+
* Wraps your component with automatic registration and state handling.
|
|
543
|
+
*/
|
|
544
|
+
readonly create: <TProps extends Record<string, unknown> = Record<string, unknown>, TRef = unknown>(Comp: react.ComponentType<TProps & RefProp<TRef>>) => react.ComponentType<TProps & ModalHocProps & RefProp<TRef>>;
|
|
545
|
+
/**
|
|
546
|
+
* Open a modal and return a ModalRef for controlling it.
|
|
547
|
+
* @returns ModalRef with afterOpened(), afterClosed(), beforeClosed() promises
|
|
548
|
+
*/
|
|
549
|
+
readonly open: typeof openModal;
|
|
550
|
+
/**
|
|
551
|
+
* Close a specific modal by component or ID.
|
|
552
|
+
* @returns Promise that resolves when the close animation completes
|
|
553
|
+
*/
|
|
554
|
+
readonly close: typeof closeModal;
|
|
555
|
+
/**
|
|
556
|
+
* Close all open modals.
|
|
557
|
+
* @returns Promise that resolves when all close animations complete
|
|
558
|
+
*/
|
|
559
|
+
readonly closeAll: () => Promise<void>;
|
|
560
|
+
/**
|
|
561
|
+
* Remove a modal from the DOM completely.
|
|
562
|
+
*/
|
|
563
|
+
readonly remove: (modal: string | React.ComponentType<Record<string, unknown>>) => void;
|
|
564
|
+
/**
|
|
565
|
+
* Check if any modals are currently open.
|
|
566
|
+
*/
|
|
567
|
+
readonly hasOpen: () => boolean;
|
|
568
|
+
/**
|
|
569
|
+
* Get array of currently open modal IDs.
|
|
570
|
+
*/
|
|
571
|
+
readonly getOpen: () => string[];
|
|
572
|
+
/**
|
|
573
|
+
* Register a modal component with an ID for later use.
|
|
574
|
+
*/
|
|
575
|
+
readonly register: (id: string, comp: react.ComponentType<any>, props?: Record<string, unknown>) => void;
|
|
576
|
+
/**
|
|
577
|
+
* Unregister a previously registered modal.
|
|
578
|
+
*/
|
|
579
|
+
readonly unregister: (id: string) => void;
|
|
580
|
+
/**
|
|
581
|
+
* Clean up all internal state for a specific modal.
|
|
582
|
+
*/
|
|
583
|
+
readonly cleanup: (modalId: string) => void;
|
|
584
|
+
/**
|
|
585
|
+
* Clean up all modal state (useful for testing).
|
|
586
|
+
*/
|
|
587
|
+
readonly cleanupAll: () => void;
|
|
588
|
+
/**
|
|
589
|
+
* Context provider for modal management.
|
|
590
|
+
* Must wrap your application.
|
|
591
|
+
*
|
|
592
|
+
* @example
|
|
593
|
+
* ```tsx
|
|
594
|
+
* function App() {
|
|
595
|
+
* return (
|
|
596
|
+
* <ModalManager.Provider>
|
|
597
|
+
* <YourApp />
|
|
598
|
+
* </ModalManager.Provider>
|
|
599
|
+
* );
|
|
600
|
+
* }
|
|
601
|
+
* ```
|
|
602
|
+
*/
|
|
603
|
+
readonly Provider: typeof ModalProvider;
|
|
604
|
+
/**
|
|
605
|
+
* Declaratively define a modal in JSX.
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```tsx
|
|
609
|
+
* <ModalManager.Def component={MyModal} id="my-modal" />
|
|
610
|
+
*
|
|
611
|
+
* // Later: open by ID
|
|
612
|
+
* ModalManager.open("my-modal");
|
|
613
|
+
* ```
|
|
614
|
+
*/
|
|
615
|
+
readonly Def: typeof ModalDef;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
export { type AdapterOptions, type BaseUiDialogPopupProps, type BaseUiDialogPortalProps, type BaseUiDialogRootProps, type BaseUiPopoverPopupProps, type BaseUiPopoverPortalProps, type BaseUiPopoverRootProps, type DeferredPromise, type InternalModalConfig, MODAL_CONFIG_KEY, type ModalAction, type ModalActionType, type ModalAnimationHandlers, type ModalConfig, ModalContext, type ModalControls, type ModalHandler, type ModalHocProps, ModalIdContext, type ModalLifecycleState, ModalManager, type ModalProps, type ModalProviderProps, type ModalReadState, type ModalRef, type ModalState, type ModalStore, type RadixDialogContentProps, type RadixDialogProps, type ShadcnDialogProps, type ShadcnUiDrawerContentProps, type ShadcnUiDrawerRootProps, baseUiAlertDialog, baseUiAlertDialogPopup, baseUiAlertDialogPortal, baseUiDialog, baseUiDialogPopup, baseUiDialogPortal, baseUiPopover, baseUiPopoverPopup, baseUiPopoverPortal, baseUiSheet, baseUiSheetPopup, baseUiSheetPortal, getModalId, radixUiAlertDialog, radixUiAlertDialogContent, radixUiDialog, radixUiDialogContent, radixUiPopover, radixUiSheet, radixUiSheetContent, reducer, shadcnUiAlertDialog, shadcnUiAlertDialogContent, shadcnUiDialog, shadcnUiDialogContent, shadcnUiDrawer, shadcnUiDrawerContent, shadcnUiPopover, shadcnUiSheet, shadcnUiSheetContent, useModal, useModalConfig, useModalData };
|