fine-modal-react 1.0.3 → 1.0.5
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 +67 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,36 +12,61 @@ pnpm add fine-modal-react
|
|
|
12
12
|
|
|
13
13
|
Peer deps: `react` and `react-dom` (19.x).
|
|
14
14
|
|
|
15
|
+
## Quickstart (checklist)
|
|
16
|
+
|
|
17
|
+
1) Install the package.
|
|
18
|
+
2) Define your modal with `FineModal.define`.
|
|
19
|
+
3) Aggregate modals in `modals.ts` and augment `Register` for typed `open`.
|
|
20
|
+
4) Choose mounting strategy:
|
|
21
|
+
- Global host: create `ModalHost = FineModal.createHost({ modals })` near root.
|
|
22
|
+
- Local: render the modal component where you need it.
|
|
23
|
+
5) Call `open` (typed both ways):
|
|
24
|
+
- `FineModal.open('ModalId', props?)` uses registered ids/props/result from `modals`.
|
|
25
|
+
- `SomeModal.open(props?)` uses the component’s props/result.
|
|
26
|
+
Both resolve to the `onConfirm` value, or `null` on `onCancel/close`.
|
|
27
|
+
|
|
15
28
|
## Define a modal (shared for both strategies)
|
|
16
29
|
|
|
30
|
+
`ConfirmInviteModal.tsx`
|
|
31
|
+
|
|
17
32
|
```tsx
|
|
18
33
|
import { FineModal } from 'fine-modal-react'
|
|
19
34
|
|
|
35
|
+
interface ConfirmInviteModalProps {
|
|
36
|
+
initialProps: { email: string }
|
|
37
|
+
onConfirm: (value: 'sent') => void
|
|
38
|
+
onCancel: () => void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const ConfirmInvite = ({
|
|
42
|
+
initialProps,
|
|
43
|
+
onConfirm,
|
|
44
|
+
onCancel,
|
|
45
|
+
}: ConfirmInviteModalProps) => (
|
|
46
|
+
<section>
|
|
47
|
+
<p>Send an invite to {initialProps.email}?</p>
|
|
48
|
+
<div>
|
|
49
|
+
<button type="button" onClick={() => onConfirm('sent')}>Send</button>
|
|
50
|
+
<button type="button" onClick={onCancel}>Cancel</button>
|
|
51
|
+
</div>
|
|
52
|
+
</section>
|
|
53
|
+
)
|
|
54
|
+
|
|
20
55
|
export const ConfirmInviteModal = FineModal.define({
|
|
21
56
|
id: 'ConfirmInviteModal',
|
|
22
|
-
component:
|
|
23
|
-
initialProps: { email: string }
|
|
24
|
-
onConfirm: (value: 'sent') => void
|
|
25
|
-
onCancel: () => void
|
|
26
|
-
}) => (
|
|
27
|
-
<section>
|
|
28
|
-
<p>Send an invite to {initialProps.email}?</p>
|
|
29
|
-
<div>
|
|
30
|
-
<button type="button" onClick={() => onConfirm('sent')}>Send</button>
|
|
31
|
-
<button type="button" onClick={onCancel}>Cancel</button>
|
|
32
|
-
</div>
|
|
33
|
-
</section>
|
|
34
|
-
),
|
|
57
|
+
component: ConfirmInvite,
|
|
35
58
|
})
|
|
36
|
-
|
|
37
|
-
export const modals = [ConfirmInviteModal] as const
|
|
38
59
|
```
|
|
39
60
|
|
|
40
|
-
|
|
61
|
+
`modals.ts`
|
|
41
62
|
|
|
42
63
|
```ts
|
|
43
|
-
import
|
|
64
|
+
import { ConfirmInviteModal } from './ConfirmInviteModal'
|
|
65
|
+
|
|
66
|
+
// Collect all modals in one place for the host and typed open()
|
|
67
|
+
export const modals = [ConfirmInviteModal] as const
|
|
44
68
|
|
|
69
|
+
// Module augmentation kept here for convenience; required for typed open()
|
|
45
70
|
declare module 'fine-modal-react' {
|
|
46
71
|
interface Register {
|
|
47
72
|
readonly modals?: typeof modals
|
|
@@ -91,6 +116,29 @@ export function App() {
|
|
|
91
116
|
}
|
|
92
117
|
```
|
|
93
118
|
|
|
119
|
+
## Type safety (global & local)
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
// Global host: ids/props/result inferred from registered modals
|
|
123
|
+
const result = await FineModal.open('ConfirmInviteModal', { email: 'team@org.com' })
|
|
124
|
+
// ^? result is "sent" | null
|
|
125
|
+
|
|
126
|
+
// TS error: missing required prop "email"
|
|
127
|
+
FineModal.open('ConfirmInviteModal')
|
|
128
|
+
|
|
129
|
+
// TS error: unknown modal id
|
|
130
|
+
FineModal.open('UnknownModal')
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// Local modal: props/result inferred from component definition
|
|
135
|
+
const result = await ConfirmInviteModal.open({ email: 'new.user@org.com' })
|
|
136
|
+
// ^? result is "sent" | null
|
|
137
|
+
|
|
138
|
+
// TS error: email must be a string
|
|
139
|
+
ConfirmInviteModal.open({ email: 42 })
|
|
140
|
+
```
|
|
141
|
+
|
|
94
142
|
## Option B: Local modal component (colocated scope)
|
|
95
143
|
|
|
96
144
|
Render the modal component where you need it; open it via its static API. This avoids a global host if you only need the modal in one subtree.
|
|
@@ -119,5 +167,6 @@ export function App() {
|
|
|
119
167
|
|
|
120
168
|
- `onConfirm(value)` resolves the promise returned by `open` with `value`.
|
|
121
169
|
- `onCancel()` resolves the promise with `null` and closes the modal.
|
|
122
|
-
- If your modal needs initial props, add an `initialProps` field to the component props; `open` will require/accept that shape.
|
|
170
|
+
- If your modal needs initial props, add an `initialProps` field to the component props; `open` will require/accept that shape. If not needed, omit `initialProps` and `open()` will take no args.
|
|
123
171
|
- `FineModal.open` automatically closes an existing modal with the same id before opening a new one.
|
|
172
|
+
- Keep the module augmentation file (`modals.ts` in the example) included in `tsconfig` so TypeScript picks up the `Register` interface extension.
|