@lcashe/react-modal-controller 1.0.0 → 1.0.1

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.
Files changed (2) hide show
  1. package/README.md +93 -8
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # react-modal-controller
2
2
 
3
- Tiny and type-safe modal controller for React and Next.js.
3
+ Tiny and type-safe modal controller for React.
4
+
5
+ Works with React, Next.js and other React-based frameworks.
4
6
 
5
7
  - No global modal registry
6
- - No reducers
8
+ - No reducers or external state managers
7
9
  - No boilerplate
8
- - Full TypeScript inference
10
+ - Automatic TypeScript prop inference
9
11
 
10
12
  ---
11
13
 
@@ -17,9 +19,11 @@ Tiny and type-safe modal controller for React and Next.js.
17
19
  - [Important](#important)
18
20
  - [Simple Example](#simple-example)
19
21
  - [Modal With Props](#modal-with-props)
22
+ - [TypeScript Inference](#typescript-inference)
20
23
  - [Dynamic Initial Props](#dynamic-initial-props)
21
24
  - [Auto Close Example](#auto-close-example)
22
25
  - [Multiple Modals](#multiple-modals)
26
+ - [Multiple Same Modals](#multiple-same-modals)
23
27
  - [API](#api)
24
28
 
25
29
  ---
@@ -50,17 +54,66 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
50
54
  );
51
55
  ```
52
56
 
57
+ `ModalScope` stores and renders all active modals internally.
58
+
59
+ Every modal opened through `useModalController`
60
+ will automatically appear inside the nearest `ModalScope`.
61
+
53
62
  ---
54
63
 
55
64
  # Next.js Setup
56
65
 
66
+ ## App Router
67
+
68
+ `app/providers.tsx`
69
+
70
+ ```tsx
71
+ 'use client';
72
+
73
+ import { PropsWithChildren } from 'react';
74
+
75
+ import { ModalScope } from '@lcashe/react-modal-controller';
76
+
77
+ export const Providers = ({ children }: PropsWithChildren) => {
78
+ return <ModalScope>{children}</ModalScope>;
79
+ };
80
+ ```
81
+
57
82
  `app/layout.tsx`
58
83
 
59
84
  ```tsx
85
+ import { Providers } from './providers';
86
+
87
+ export default function RootLayout({
88
+ children,
89
+ }: {
90
+ children: React.ReactNode;
91
+ }) {
92
+ return (
93
+ <html lang="en">
94
+ <body>
95
+ <Providers>{children}</Providers>
96
+ </body>
97
+ </html>
98
+ );
99
+ }
100
+ ```
101
+
102
+ ## Pages Router
103
+
104
+ `pages/_app.tsx`
105
+
106
+ ```tsx
107
+ import type { AppProps } from 'next/app';
108
+
60
109
  import { ModalScope } from '@lcashe/react-modal-controller';
61
110
 
62
- export default function Page() {
63
- return <ModalScope>// PAGE CONTENT</ModalScope>;
111
+ export default function App({ Component, pageProps }: AppProps) {
112
+ return (
113
+ <ModalScope>
114
+ <Component {...pageProps} />
115
+ </ModalScope>
116
+ );
64
117
  }
65
118
  ```
66
119
 
@@ -91,6 +144,8 @@ type ModalProps = {
91
144
  };
92
145
  ```
93
146
 
147
+ These props are injected automatically by the controller.
148
+
94
149
  ---
95
150
 
96
151
  # Simple Example
@@ -100,7 +155,6 @@ type ModalProps = {
100
155
  ```tsx
101
156
  'use client';
102
157
 
103
-
104
158
  type ModalProps = {
105
159
  opened: boolean;
106
160
  onClose: VoidFunction;
@@ -185,7 +239,7 @@ export const Component = () => {
185
239
  <button
186
240
  onClick={() =>
187
241
  modal.open({
188
- title: 'Another title', // optional
242
+ title: 'Another title',
189
243
  })
190
244
  }
191
245
  >
@@ -195,6 +249,20 @@ export const Component = () => {
195
249
  };
196
250
  ```
197
251
 
252
+ `initialProps` are merged with props passed into `open()`.
253
+
254
+ ```tsx
255
+ const modal = useModalController(Modal, {
256
+ title: 'Default title',
257
+ });
258
+
259
+ modal.open({
260
+ title: 'Another title',
261
+ });
262
+ ```
263
+
264
+ The second object overrides the first one.
265
+
198
266
  ---
199
267
 
200
268
  # TypeScript Inference
@@ -223,6 +291,16 @@ const modal = useModalController(Modal, {
223
291
 
224
292
  When `title` changes, the next `open()` call will use the latest value.
225
293
 
294
+ This makes it safe to use reactive values:
295
+
296
+ ```tsx
297
+ const modal = useModalController(Modal, {
298
+ title: currentTitle,
299
+ });
300
+ ```
301
+
302
+ The controller always keeps the latest values internally.
303
+
226
304
  ---
227
305
 
228
306
  # Auto Close Example
@@ -282,9 +360,12 @@ const secondModal = useModalController(Modal);
282
360
 
283
361
  ...
284
362
 
285
- secondModal.open() // <-- will open only the second modal
363
+ secondModal.open(); // opens only the second modal
286
364
  ```
287
365
 
366
+ Modals are mounted globally inside `ModalScope`,
367
+ but every controller manages its own isolated modal state.
368
+
288
369
  ---
289
370
 
290
371
  # API
@@ -301,6 +382,8 @@ Returns:
301
382
  }
302
383
  ```
303
384
 
385
+ ---
386
+
304
387
  ## `open(props?)`
305
388
 
306
389
  Open modal with optional props.
@@ -333,6 +416,8 @@ Remove modal from the store completely.
333
416
  modal.remove();
334
417
  ```
335
418
 
419
+ Usually useful when you want to completely destroy modal state manually.
420
+
336
421
  ---
337
422
 
338
423
  # License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lcashe/react-modal-controller",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Tiny type-safe modal controller for React with inferred props and no registry.",
5
5
  "license": "MIT",
6
6
  "type": "module",