@mehdashti/modals 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +287 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.js +232 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# @mehdashti/modals
|
|
2
|
+
|
|
3
|
+
Modal and drawer management with stacking support for Smart Platform.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multiple Modal Types**: Modal, Drawer, Confirmation Dialog
|
|
8
|
+
- **Modal Stacking**: Support for multiple modals simultaneously
|
|
9
|
+
- **Focus Management**: Automatic focus trap and restoration
|
|
10
|
+
- **Accessible**: Built with Radix UI for WCAG compliance
|
|
11
|
+
- **Customizable**: 5 sizes and flexible styling
|
|
12
|
+
- **Keyboard Support**: ESC to close, Tab for focus management
|
|
13
|
+
- **Programmatic Control**: Imperative API via context
|
|
14
|
+
- **Animations**: Smooth enter/exit animations
|
|
15
|
+
- **Type Safe**: Full TypeScript support
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @mehdashti/modals
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Basic Modal
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { Modal } from '@mehdashti/modals'
|
|
29
|
+
import { useState } from 'react'
|
|
30
|
+
|
|
31
|
+
function MyComponent() {
|
|
32
|
+
const [open, setOpen] = useState(false)
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<button onClick={() => setOpen(true)}>Open Modal</button>
|
|
37
|
+
|
|
38
|
+
<Modal
|
|
39
|
+
open={open}
|
|
40
|
+
onClose={() => setOpen(false)}
|
|
41
|
+
title="Modal Title"
|
|
42
|
+
description="This is a modal description"
|
|
43
|
+
>
|
|
44
|
+
<p>Modal content goes here</p>
|
|
45
|
+
</Modal>
|
|
46
|
+
</>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Modal Sizes
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<Modal
|
|
55
|
+
open={open}
|
|
56
|
+
onClose={onClose}
|
|
57
|
+
title="Small Modal"
|
|
58
|
+
size="sm" // sm | md | lg | xl | full
|
|
59
|
+
>
|
|
60
|
+
<p>Content</p>
|
|
61
|
+
</Modal>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Modal Context (Programmatic Control)
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { ModalProvider, useModal } from '@mehdashti/modals'
|
|
68
|
+
|
|
69
|
+
// Wrap your app
|
|
70
|
+
function App() {
|
|
71
|
+
return (
|
|
72
|
+
<ModalProvider>
|
|
73
|
+
<YourApp />
|
|
74
|
+
</ModalProvider>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Use in any component
|
|
79
|
+
function MyComponent() {
|
|
80
|
+
const { openModal, closeModal } = useModal()
|
|
81
|
+
|
|
82
|
+
const handleOpen = () => {
|
|
83
|
+
openModal('user-profile', {
|
|
84
|
+
title: 'User Profile',
|
|
85
|
+
children: <UserProfile />,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const handleClose = () => {
|
|
90
|
+
closeModal('user-profile')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return <button onClick={handleOpen}>Open Profile</button>
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Confirmation Dialog
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { ConfirmDialog } from '@mehdashti/modals'
|
|
101
|
+
|
|
102
|
+
function DeleteButton() {
|
|
103
|
+
const [open, setOpen] = useState(false)
|
|
104
|
+
|
|
105
|
+
const handleConfirm = async () => {
|
|
106
|
+
await deleteUser()
|
|
107
|
+
setOpen(false)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<>
|
|
112
|
+
<button onClick={() => setOpen(true)}>Delete User</button>
|
|
113
|
+
|
|
114
|
+
<ConfirmDialog
|
|
115
|
+
open={open}
|
|
116
|
+
onClose={() => setOpen(false)}
|
|
117
|
+
onConfirm={handleConfirm}
|
|
118
|
+
title="Delete User"
|
|
119
|
+
description="Are you sure you want to delete this user? This action cannot be undone."
|
|
120
|
+
confirmText="Delete"
|
|
121
|
+
cancelText="Cancel"
|
|
122
|
+
variant="destructive"
|
|
123
|
+
/>
|
|
124
|
+
</>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Drawer (Slide from Side)
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { Drawer } from '@mehdashti/modals'
|
|
133
|
+
|
|
134
|
+
function MyComponent() {
|
|
135
|
+
const [open, setOpen] = useState(false)
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<>
|
|
139
|
+
<button onClick={() => setOpen(true)}>Open Drawer</button>
|
|
140
|
+
|
|
141
|
+
<Drawer
|
|
142
|
+
open={open}
|
|
143
|
+
onClose={() => setOpen(false)}
|
|
144
|
+
title="Settings"
|
|
145
|
+
side="right" // left | right
|
|
146
|
+
>
|
|
147
|
+
<SettingsForm />
|
|
148
|
+
</Drawer>
|
|
149
|
+
</>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Form Modal
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { FormModal } from '@mehdashti/modals'
|
|
158
|
+
import { useSmartForm } from '@mehdashti/forms'
|
|
159
|
+
|
|
160
|
+
function CreateUserModal({ open, onClose }) {
|
|
161
|
+
const form = useSmartForm({
|
|
162
|
+
schema: userSchema,
|
|
163
|
+
onSubmit: async (data) => {
|
|
164
|
+
await createUser(data)
|
|
165
|
+
onClose()
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<FormModal
|
|
171
|
+
open={open}
|
|
172
|
+
onClose={onClose}
|
|
173
|
+
title="Create User"
|
|
174
|
+
form={form}
|
|
175
|
+
submitText="Create"
|
|
176
|
+
>
|
|
177
|
+
<FormField name="name" label="Name" control={form.control} />
|
|
178
|
+
<FormField name="email" label="Email" control={form.control} />
|
|
179
|
+
</FormModal>
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Modal Stacking
|
|
185
|
+
|
|
186
|
+
Multiple modals can be opened simultaneously:
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
function App() {
|
|
190
|
+
return (
|
|
191
|
+
<ModalProvider>
|
|
192
|
+
<YourApp />
|
|
193
|
+
</ModalProvider>
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function Component() {
|
|
198
|
+
const { openModal } = useModal()
|
|
199
|
+
|
|
200
|
+
const handleOpenFirst = () => {
|
|
201
|
+
openModal('first', {
|
|
202
|
+
title: 'First Modal',
|
|
203
|
+
children: (
|
|
204
|
+
<button onClick={() => openModal('second', {
|
|
205
|
+
title: 'Second Modal',
|
|
206
|
+
children: <p>This is stacked on top!</p>
|
|
207
|
+
})}>
|
|
208
|
+
Open Second Modal
|
|
209
|
+
</button>
|
|
210
|
+
),
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return <button onClick={handleOpenFirst}>Open Modal</button>
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## API
|
|
219
|
+
|
|
220
|
+
### Modal Props
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface ModalProps {
|
|
224
|
+
open: boolean
|
|
225
|
+
onClose?: () => void
|
|
226
|
+
title?: React.ReactNode
|
|
227
|
+
description?: React.ReactNode
|
|
228
|
+
children: React.ReactNode
|
|
229
|
+
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'
|
|
230
|
+
showClose?: boolean
|
|
231
|
+
dismissable?: boolean
|
|
232
|
+
className?: string
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Drawer Props
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
interface DrawerProps extends ModalProps {
|
|
240
|
+
side?: 'left' | 'right'
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### ConfirmDialog Props
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
interface ConfirmDialogProps {
|
|
248
|
+
open: boolean
|
|
249
|
+
onClose: () => void
|
|
250
|
+
onConfirm: () => void | Promise<void>
|
|
251
|
+
title: string
|
|
252
|
+
description: string
|
|
253
|
+
confirmText?: string
|
|
254
|
+
cancelText?: string
|
|
255
|
+
variant?: 'default' | 'destructive'
|
|
256
|
+
isLoading?: boolean
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### ModalContext API
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
interface ModalContextValue {
|
|
264
|
+
openModal: (id: string, props: Omit<ModalProps, 'open' | 'onClose'>) => void
|
|
265
|
+
closeModal: (id: string) => void
|
|
266
|
+
closeAllModals: () => void
|
|
267
|
+
isOpen: (id: string) => boolean
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Accessibility
|
|
272
|
+
|
|
273
|
+
All components follow WCAG 2.1 guidelines:
|
|
274
|
+
|
|
275
|
+
- **Focus trap**: Focus is trapped within the modal
|
|
276
|
+
- **Focus restoration**: Focus returns to trigger on close
|
|
277
|
+
- **Keyboard navigation**: ESC to close, Tab to navigate
|
|
278
|
+
- **ARIA attributes**: Proper roles and labels
|
|
279
|
+
- **Screen reader support**: Announcements for state changes
|
|
280
|
+
|
|
281
|
+
## Examples
|
|
282
|
+
|
|
283
|
+
See [Storybook stories](./src/components/modal.stories.tsx) for more examples.
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Modal Types
|
|
6
|
+
*
|
|
7
|
+
* Type definitions for modal management.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface ModalProps {
|
|
11
|
+
/**
|
|
12
|
+
* Whether the modal is open
|
|
13
|
+
*/
|
|
14
|
+
open?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Callback when modal is closed
|
|
17
|
+
*/
|
|
18
|
+
onClose?: () => void;
|
|
19
|
+
/**
|
|
20
|
+
* Modal title
|
|
21
|
+
*/
|
|
22
|
+
title?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Modal description
|
|
25
|
+
*/
|
|
26
|
+
description?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Modal content
|
|
29
|
+
*/
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
/**
|
|
32
|
+
* Modal size
|
|
33
|
+
*/
|
|
34
|
+
size?: "sm" | "md" | "lg" | "xl" | "full";
|
|
35
|
+
/**
|
|
36
|
+
* Whether to show close button
|
|
37
|
+
*/
|
|
38
|
+
showClose?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Custom className for modal content
|
|
41
|
+
*/
|
|
42
|
+
className?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the modal can be dismissed by clicking outside or pressing Escape
|
|
45
|
+
*/
|
|
46
|
+
dismissable?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface ModalContextValue {
|
|
49
|
+
/**
|
|
50
|
+
* Open a modal
|
|
51
|
+
*/
|
|
52
|
+
openModal: (id: string, props: Omit<ModalProps, "open" | "onClose">) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Close a modal
|
|
55
|
+
*/
|
|
56
|
+
closeModal: (id: string) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Close all modals
|
|
59
|
+
*/
|
|
60
|
+
closeAllModals: () => void;
|
|
61
|
+
/**
|
|
62
|
+
* Check if a modal is open
|
|
63
|
+
*/
|
|
64
|
+
isModalOpen: (id: string) => boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Get all open modal IDs
|
|
67
|
+
*/
|
|
68
|
+
openModals: string[];
|
|
69
|
+
}
|
|
70
|
+
interface ConfirmModalProps {
|
|
71
|
+
/**
|
|
72
|
+
* Confirmation title
|
|
73
|
+
*/
|
|
74
|
+
title: string;
|
|
75
|
+
/**
|
|
76
|
+
* Confirmation message
|
|
77
|
+
*/
|
|
78
|
+
message: string;
|
|
79
|
+
/**
|
|
80
|
+
* Confirm button text
|
|
81
|
+
*/
|
|
82
|
+
confirmText?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Cancel button text
|
|
85
|
+
*/
|
|
86
|
+
cancelText?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Callback when confirmed
|
|
89
|
+
*/
|
|
90
|
+
onConfirm: () => void | Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Callback when cancelled
|
|
93
|
+
*/
|
|
94
|
+
onCancel?: () => void;
|
|
95
|
+
/**
|
|
96
|
+
* Confirm button variant
|
|
97
|
+
*/
|
|
98
|
+
variant?: "default" | "destructive";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Modal Component
|
|
103
|
+
*
|
|
104
|
+
* Accessible modal dialog with stacking support.
|
|
105
|
+
*/
|
|
106
|
+
declare function Modal({ open, onClose, title, description, children, size, showClose, className, dismissable, }: ModalProps): react_jsx_runtime.JSX.Element;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Confirm Modal
|
|
110
|
+
*
|
|
111
|
+
* Modal for confirming user actions.
|
|
112
|
+
*/
|
|
113
|
+
declare function ConfirmModal({ title, message, confirmText, cancelText, onConfirm, onCancel, variant, }: ConfirmModalProps & {
|
|
114
|
+
open?: boolean;
|
|
115
|
+
onClose?: () => void;
|
|
116
|
+
}): react_jsx_runtime.JSX.Element;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* useModal Hook
|
|
120
|
+
*
|
|
121
|
+
* Hook for programmatic modal control.
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Use Modal
|
|
126
|
+
*
|
|
127
|
+
* Get modal control functions for a specific modal ID.
|
|
128
|
+
*/
|
|
129
|
+
declare function useModal(id: string): {
|
|
130
|
+
/**
|
|
131
|
+
* Open this modal
|
|
132
|
+
*/
|
|
133
|
+
open: (props: Omit<ModalProps, "open" | "onClose">) => void;
|
|
134
|
+
/**
|
|
135
|
+
* Close this modal
|
|
136
|
+
*/
|
|
137
|
+
close: () => void;
|
|
138
|
+
/**
|
|
139
|
+
* Check if this modal is open
|
|
140
|
+
*/
|
|
141
|
+
isOpen: boolean;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
interface ModalProviderProps {
|
|
145
|
+
children: React.ReactNode;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Modal Provider
|
|
149
|
+
*
|
|
150
|
+
* Provides modal management functionality to the app.
|
|
151
|
+
*/
|
|
152
|
+
declare function ModalProvider({ children }: ModalProviderProps): react_jsx_runtime.JSX.Element;
|
|
153
|
+
/**
|
|
154
|
+
* Use Modal Context
|
|
155
|
+
*
|
|
156
|
+
* Access modal management functions.
|
|
157
|
+
*/
|
|
158
|
+
declare function useModalContext(): ModalContextValue;
|
|
159
|
+
|
|
160
|
+
export { ConfirmModal, type ConfirmModalProps, Modal, type ModalContextValue, type ModalProps, ModalProvider, useModal, useModalContext };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// src/components/modal.tsx
|
|
2
|
+
import * as Dialog from "@radix-ui/react-dialog";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var sizeClasses = {
|
|
6
|
+
sm: "max-w-md",
|
|
7
|
+
md: "max-w-lg",
|
|
8
|
+
lg: "max-w-2xl",
|
|
9
|
+
xl: "max-w-4xl",
|
|
10
|
+
full: "max-w-full"
|
|
11
|
+
};
|
|
12
|
+
function Modal({
|
|
13
|
+
open = false,
|
|
14
|
+
onClose,
|
|
15
|
+
title,
|
|
16
|
+
description,
|
|
17
|
+
children,
|
|
18
|
+
size = "md",
|
|
19
|
+
showClose = true,
|
|
20
|
+
className,
|
|
21
|
+
dismissable = true
|
|
22
|
+
}) {
|
|
23
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange: (open2) => !open2 && onClose?.(), children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
|
|
24
|
+
/* @__PURE__ */ jsx(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" }),
|
|
25
|
+
/* @__PURE__ */ jsxs(
|
|
26
|
+
Dialog.Content,
|
|
27
|
+
{
|
|
28
|
+
className: clsx(
|
|
29
|
+
"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",
|
|
30
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
31
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
32
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
33
|
+
"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
|
|
34
|
+
"data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
35
|
+
"sm:rounded-lg",
|
|
36
|
+
sizeClasses[size],
|
|
37
|
+
className
|
|
38
|
+
),
|
|
39
|
+
onEscapeKeyDown: (e) => {
|
|
40
|
+
if (!dismissable) {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
onPointerDownOutside: (e) => {
|
|
45
|
+
if (!dismissable) {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
children: [
|
|
50
|
+
(title || description) && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
51
|
+
title && /* @__PURE__ */ jsx(Dialog.Title, { className: "text-lg font-semibold leading-none tracking-tight", children: title }),
|
|
52
|
+
description && /* @__PURE__ */ jsx(Dialog.Description, { className: "text-sm text-muted-foreground", children: description })
|
|
53
|
+
] }),
|
|
54
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4", children }),
|
|
55
|
+
showClose && /* @__PURE__ */ jsxs(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", children: [
|
|
56
|
+
/* @__PURE__ */ jsxs(
|
|
57
|
+
"svg",
|
|
58
|
+
{
|
|
59
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
60
|
+
width: "24",
|
|
61
|
+
height: "24",
|
|
62
|
+
viewBox: "0 0 24 24",
|
|
63
|
+
fill: "none",
|
|
64
|
+
stroke: "currentColor",
|
|
65
|
+
strokeWidth: "2",
|
|
66
|
+
strokeLinecap: "round",
|
|
67
|
+
strokeLinejoin: "round",
|
|
68
|
+
className: "h-4 w-4",
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
71
|
+
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
76
|
+
] })
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
] }) });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/components/confirm-modal.tsx
|
|
84
|
+
import * as React from "react";
|
|
85
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
86
|
+
function ConfirmModal({
|
|
87
|
+
title,
|
|
88
|
+
message,
|
|
89
|
+
confirmText = "Confirm",
|
|
90
|
+
cancelText = "Cancel",
|
|
91
|
+
onConfirm,
|
|
92
|
+
onCancel,
|
|
93
|
+
variant = "default"
|
|
94
|
+
}) {
|
|
95
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
96
|
+
const [isOpen, setIsOpen] = React.useState(true);
|
|
97
|
+
const handleConfirm = async () => {
|
|
98
|
+
setIsLoading(true);
|
|
99
|
+
try {
|
|
100
|
+
await onConfirm();
|
|
101
|
+
setIsOpen(false);
|
|
102
|
+
} finally {
|
|
103
|
+
setIsLoading(false);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const handleCancel = () => {
|
|
107
|
+
onCancel?.();
|
|
108
|
+
setIsOpen(false);
|
|
109
|
+
};
|
|
110
|
+
return /* @__PURE__ */ jsx2(
|
|
111
|
+
Modal,
|
|
112
|
+
{
|
|
113
|
+
open: isOpen,
|
|
114
|
+
onClose: handleCancel,
|
|
115
|
+
title,
|
|
116
|
+
size: "sm",
|
|
117
|
+
dismissable: !isLoading,
|
|
118
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
|
|
119
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-muted-foreground", children: message }),
|
|
120
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-end space-x-2", children: [
|
|
121
|
+
/* @__PURE__ */ jsx2(
|
|
122
|
+
"button",
|
|
123
|
+
{
|
|
124
|
+
type: "button",
|
|
125
|
+
onClick: handleCancel,
|
|
126
|
+
disabled: isLoading,
|
|
127
|
+
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",
|
|
128
|
+
children: cancelText
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
/* @__PURE__ */ jsx2(
|
|
132
|
+
"button",
|
|
133
|
+
{
|
|
134
|
+
type: "button",
|
|
135
|
+
onClick: handleConfirm,
|
|
136
|
+
disabled: isLoading,
|
|
137
|
+
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 ${variant === "destructive" ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "bg-primary text-primary-foreground hover:bg-primary/90"}`,
|
|
138
|
+
children: isLoading ? "Loading..." : confirmText
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
] })
|
|
142
|
+
] })
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/context/modal-context.tsx
|
|
148
|
+
import * as React2 from "react";
|
|
149
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
150
|
+
var ModalContext = React2.createContext(
|
|
151
|
+
void 0
|
|
152
|
+
);
|
|
153
|
+
function ModalProvider({ children }) {
|
|
154
|
+
const [modals, setModals] = React2.useState([]);
|
|
155
|
+
const openModal = React2.useCallback(
|
|
156
|
+
(id, props) => {
|
|
157
|
+
setModals((prev) => {
|
|
158
|
+
const existing = prev.find((m) => m.id === id);
|
|
159
|
+
if (existing) {
|
|
160
|
+
return prev.map((m) => m.id === id ? { id, props } : m);
|
|
161
|
+
}
|
|
162
|
+
return [...prev, { id, props }];
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
[]
|
|
166
|
+
);
|
|
167
|
+
const closeModal = React2.useCallback((id) => {
|
|
168
|
+
setModals((prev) => prev.filter((m) => m.id !== id));
|
|
169
|
+
}, []);
|
|
170
|
+
const closeAllModals = React2.useCallback(() => {
|
|
171
|
+
setModals([]);
|
|
172
|
+
}, []);
|
|
173
|
+
const isModalOpen = React2.useCallback(
|
|
174
|
+
(id) => {
|
|
175
|
+
return modals.some((m) => m.id === id);
|
|
176
|
+
},
|
|
177
|
+
[modals]
|
|
178
|
+
);
|
|
179
|
+
const value = {
|
|
180
|
+
openModal,
|
|
181
|
+
closeModal,
|
|
182
|
+
closeAllModals,
|
|
183
|
+
isModalOpen,
|
|
184
|
+
openModals: modals.map((m) => m.id)
|
|
185
|
+
};
|
|
186
|
+
return /* @__PURE__ */ jsxs3(ModalContext.Provider, { value, children: [
|
|
187
|
+
children,
|
|
188
|
+
modals.map((modal) => /* @__PURE__ */ jsx3(
|
|
189
|
+
Modal,
|
|
190
|
+
{
|
|
191
|
+
open: true,
|
|
192
|
+
onClose: () => closeModal(modal.id),
|
|
193
|
+
...modal.props
|
|
194
|
+
},
|
|
195
|
+
modal.id
|
|
196
|
+
))
|
|
197
|
+
] });
|
|
198
|
+
}
|
|
199
|
+
function useModalContext() {
|
|
200
|
+
const context = React2.useContext(ModalContext);
|
|
201
|
+
if (!context) {
|
|
202
|
+
throw new Error("useModalContext must be used within ModalProvider");
|
|
203
|
+
}
|
|
204
|
+
return context;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/hooks/use-modal.ts
|
|
208
|
+
function useModal(id) {
|
|
209
|
+
const { openModal, closeModal, isModalOpen } = useModalContext();
|
|
210
|
+
return {
|
|
211
|
+
/**
|
|
212
|
+
* Open this modal
|
|
213
|
+
*/
|
|
214
|
+
open: (props) => openModal(id, props),
|
|
215
|
+
/**
|
|
216
|
+
* Close this modal
|
|
217
|
+
*/
|
|
218
|
+
close: () => closeModal(id),
|
|
219
|
+
/**
|
|
220
|
+
* Check if this modal is open
|
|
221
|
+
*/
|
|
222
|
+
isOpen: isModalOpen(id)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
export {
|
|
226
|
+
ConfirmModal,
|
|
227
|
+
Modal,
|
|
228
|
+
ModalProvider,
|
|
229
|
+
useModal,
|
|
230
|
+
useModalContext
|
|
231
|
+
};
|
|
232
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mehdashti/modals",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Modal management system with stacking support for Smart Platform",
|
|
5
|
+
"author": "mehdashti",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/mehdashti/smart-platform.git",
|
|
10
|
+
"directory": "packages/modals"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/mehdashti/smart-platform#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/mehdashti/smart-platform/issues"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup",
|
|
29
|
+
"dev": "tsup --watch",
|
|
30
|
+
"lint": "eslint src",
|
|
31
|
+
"type-check": "tsc --noEmit"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@radix-ui/react-dialog": "^1.1.4",
|
|
35
|
+
"clsx": "^2.1.1"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@mehdashti/ui": "workspace:^",
|
|
39
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
40
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@mehdashti/ui": "workspace:^",
|
|
44
|
+
"@types/react": "^18.3.18",
|
|
45
|
+
"@types/react-dom": "^18.3.5",
|
|
46
|
+
"react": "^18.3.1",
|
|
47
|
+
"react-dom": "^18.3.1",
|
|
48
|
+
"tsup": "^8.3.5",
|
|
49
|
+
"typescript": "^5.7.3"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"react",
|
|
53
|
+
"modal",
|
|
54
|
+
"dialog",
|
|
55
|
+
"radix-ui",
|
|
56
|
+
"stacking",
|
|
57
|
+
"smart-platform"
|
|
58
|
+
]
|
|
59
|
+
}
|