overkit 0.0.2 → 0.0.3

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 +314 -314
  2. package/package.json +75 -75
package/README.md CHANGED
@@ -1,314 +1,314 @@
1
- # Overkit
2
-
3
- Simplified overlay management system for React and Next.js. Uses Zustand for state management and allows creating modals, drawers, sheets, and more with ease.
4
-
5
- ## Features
6
-
7
- - **Centralized State**: State management with Zustand
8
- - **Simple Triggers**: Open overlays with a single click
9
- - **Portals**: Flexible rendering with tunnel-rat
10
- - **TypeScript**: Complete and safe typing
11
- - **Dynamic Configuration**: Props based on store state
12
- - **Built-in Hooks**: Access state from any component
13
-
14
- ## Installation
15
-
16
- ```bash
17
- npm install overkit
18
- # or
19
- yarn add overkit
20
- # or
21
- pnpm add overkit
22
- ```
23
-
24
- ## Dependencies
25
-
26
- ```bash
27
- npm install zustand @radix-ui/react-slot tunnel-rat
28
- ```
29
-
30
- ## Basic Usage
31
-
32
- ### 1. Create a Registry
33
-
34
- First, create a base component that will serve as the overlay (Modal, Drawer, Sheet, etc.):
35
-
36
- ```tsx
37
- // components/modal.tsx
38
- import { registry, type RegistryComponentProps } from "overkit";
39
-
40
- const Modal = ({
41
- open,
42
- onOpenChange,
43
- title,
44
- description,
45
- children,
46
- }: RegistryComponentProps) => {
47
- if (!open) return null;
48
-
49
- return (
50
- <div className="modal-backdrop" onClick={() => onOpenChange?.(false)}>
51
- <div className="modal-content">
52
- <h2>{title}</h2>
53
- <p>{description}</p>
54
- {children}
55
- </div>
56
- </div>
57
- );
58
- };
59
-
60
- export const ModalRegistry = registry({
61
- name: "modal",
62
- render: Modal,
63
- });
64
- ```
65
-
66
- ### 2. Configure Overkit
67
-
68
- ```tsx
69
- // overlays.tsx
70
- import { Overkit } from "overkit";
71
- import { ModalRegistry } from "./modal";
72
-
73
- const o = new Overkit(["userModal", "confirmDialog"] as const)
74
- .with(ModalRegistry)
75
- .build();
76
-
77
- // Create simple overlay
78
- const userDialog = o.create("userModal", "modal").configure({
79
- title: "User Profile",
80
- description: "Manage your profile information",
81
- });
82
-
83
- // Create overlay with extended state
84
- const confirmDialog = o
85
- .create("confirmDialog", "modal")
86
- .extend<{ message: string }>(() => ({
87
- message: "",
88
- }))
89
- .configure({
90
- title: "Confirm Action",
91
- description: "Are you sure?",
92
- });
93
-
94
- // Export components
95
- export const UserModalTrigger = userDialog.trigger;
96
- export const UserModalView = userDialog.view;
97
-
98
- export const ConfirmTrigger = confirmDialog.trigger;
99
- export const ConfirmView = confirmDialog.view;
100
- export const useOverkitStore = o.useOverkitStore;
101
- ```
102
-
103
- ### 3. Use in Your App
104
-
105
- ```tsx
106
- // page.tsx
107
- import { UserModalTrigger, UserModalView } from "./overlays";
108
-
109
- export default function Page() {
110
- return (
111
- <div>
112
- <UserModalTrigger>
113
- <button>Open User Modal</button>
114
- </UserModalTrigger>
115
-
116
- <UserModalView />
117
- </div>
118
- );
119
- }
120
- ```
121
-
122
- ## API
123
-
124
- ### `Overkit`
125
-
126
- The main class for creating and managing overlays.
127
-
128
- ```tsx
129
- const o = new Overkit(["key1", "key2"] as const).with(RegistryItem).build();
130
- ```
131
-
132
- ### `.create(key, registryName)`
133
-
134
- Creates a new overlay.
135
-
136
- ```tsx
137
- const dialog = o.create("myDialog", "modal");
138
- ```
139
-
140
- ### `.extend<State>(storeCreator)`
141
-
142
- Extends the overlay state with additional properties.
143
-
144
- ```tsx
145
- const dialog = o
146
- .create("myDialog", "modal")
147
- .extend<{ count: number }>((set) => ({
148
- count: 0,
149
- increment: () => set((state) => ({ count: state.count + 1 })),
150
- }));
151
- ```
152
-
153
- ### `.configure(options)`
154
-
155
- Configures the overlay properties. You can use static values or functions that receive the store:
156
-
157
- ```tsx
158
- const dialog = o
159
- .create("productDialog", "modal")
160
- .extend<{ mode: "create" | "edit" }>((set) => ({
161
- mode: "create",
162
- setMode: (mode) => set({ mode }),
163
- }))
164
- .configure({
165
- // Static values
166
- title: "Product",
167
-
168
- // Functions with store access
169
- title: (store) =>
170
- store?.mode === "create" ? "Create Product" : "Edit Product",
171
- description: (store) =>
172
- store?.mode === "create"
173
- ? "Create a new product"
174
- : "Edit existing product",
175
- className: (store) =>
176
- store?.mode === "create" ? "mode-create" : "mode-edit",
177
- });
178
- ```
179
-
180
- ### `trigger`
181
-
182
- Component to open the overlay.
183
-
184
- ```tsx
185
- <Trigger>
186
- <button>Open</button>
187
- </Trigger>
188
-
189
- // With initial store values
190
- <Trigger count={100}>
191
- <button>Open with 100</button>
192
- </Trigger>
193
-
194
- // With componentProps for the view
195
- <Trigger componentProps={{ items: ["a", "b", "c"] }}>
196
- <button>Open with Items</button>
197
- </Trigger>
198
- ```
199
-
200
- ### `view`
201
-
202
- Component that renders the overlay content.
203
-
204
- ```tsx
205
- // Basic
206
- const View = dialog.view(() => <div>Content</div>);
207
-
208
- // With props
209
- const View = dialog.view<{ items: string[] }>(({ items }) => (
210
- <ul>
211
- {items.map((item) => (
212
- <li key={item}>{item}</li>
213
- ))}
214
- </ul>
215
- ));
216
-
217
- // With close function
218
- const View = dialog.view(({ close }) => (
219
- <div>
220
- <button onClick={close}>Close</button>
221
- </div>
222
- ));
223
-
224
- // With useInnerContext (requires .extend())
225
- const View = dialog.view(({ useInnerContext }) => {
226
- const count = useInnerContext((state) => state.count);
227
- const increment = useInnerContext((state) => state.increment);
228
-
229
- return (
230
- <div>
231
- <p>Count: {count}</p>
232
- <button onClick={increment}>Increment</button>
233
- </div>
234
- );
235
- });
236
- ```
237
-
238
- ### `useOverkitStore`
239
-
240
- Hook to access the global state of all overlays.
241
-
242
- ```tsx
243
- const isOpen = useOverkitStore((state) => state.states.myDialog);
244
- const setOpen = useOverkitStore((state) => state.setMyDialog);
245
-
246
- // Open/close programmatically
247
- setOpen(true);
248
- setOpen(false);
249
- ```
250
-
251
- ## Advanced Examples
252
-
253
- ### Product Sheet (Create/Edit)
254
-
255
- ```tsx
256
- const productSheet = o
257
- .create("productSheet", "Sheet")
258
- .extend<ProductState>((set) => ({
259
- mode: "create",
260
- setMode: (mode) => set({ mode }),
261
- }))
262
- .configure({
263
- title: (store) => {
264
- return store?.mode === "create" ? "Create a Product" : "Edit Product";
265
- },
266
- description: (store) => {
267
- return store?.mode === "create"
268
- ? "Fill in the details of the product you want to create"
269
- : "Fill in the details of the product you want to edit";
270
- },
271
- className: "!max-w-none w-3/8",
272
- });
273
- ```
274
-
275
- ### Counter with Extended State
276
-
277
- ```tsx
278
- const counterDialog = o
279
- .create("counter", "modal")
280
- .extend<{ count: number }>((set) => ({
281
- count: 0,
282
- }))
283
- .configure({
284
- title: "Counter Dialog",
285
- });
286
-
287
- // Open with initial value
288
- <counterDialog.trigger count={100}>
289
- <button>Open with 100</button>
290
- </counterDialog.trigger>;
291
-
292
- // Use in the view
293
- const CounterView = counterDialog.view(({ useInnerContext }) => {
294
- const count = useInnerContext((state) => state.count);
295
- return <div>Count: {count}</div>;
296
- });
297
- ```
298
-
299
- ## TypeScript
300
-
301
- Overkit is fully typed. When creating overlays, types are automatically inferred:
302
-
303
- ```tsx
304
- // Keys are validated at compile time
305
- const o = new Overkit(["dialog1", "dialog2"] as const);
306
-
307
- // TypeScript knows only "dialog1" and "dialog2" are valid
308
- o.create("dialog1", "modal"); // ✅
309
- o.create("dialog3", "modal"); // ❌ Type error
310
- ```
311
-
312
- ## License
313
-
314
- MIT
1
+ # Overkit
2
+
3
+ Simplified overlay management system for React and Next.js. Uses Zustand for state management and allows creating modals, drawers, sheets, and more with ease.
4
+
5
+ ## Features
6
+
7
+ - **Centralized State**: State management with Zustand
8
+ - **Simple Triggers**: Open overlays with a single click
9
+ - **Portals**: Flexible rendering with tunnel-rat
10
+ - **TypeScript**: Complete and safe typing
11
+ - **Dynamic Configuration**: Props based on store state
12
+ - **Built-in Hooks**: Access state from any component
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install overkit
18
+ # or
19
+ yarn add overkit
20
+ # or
21
+ pnpm add overkit
22
+ ```
23
+
24
+ ## Dependencies
25
+
26
+ ```bash
27
+ npm install zustand @radix-ui/react-slot tunnel-rat
28
+ ```
29
+
30
+ ## Basic Usage
31
+
32
+ ### 1. Create a Registry
33
+
34
+ First, create a base component that will serve as the overlay (Modal, Drawer, Sheet, etc.):
35
+
36
+ ```tsx
37
+ // components/modal.tsx
38
+ import { registry, type RegistryComponentProps } from "overkit";
39
+
40
+ const Modal = ({
41
+ open,
42
+ onOpenChange,
43
+ title,
44
+ description,
45
+ children,
46
+ }: RegistryComponentProps) => {
47
+ if (!open) return null;
48
+
49
+ return (
50
+ <div className="modal-backdrop" onClick={() => onOpenChange?.(false)}>
51
+ <div className="modal-content">
52
+ <h2>{title}</h2>
53
+ <p>{description}</p>
54
+ {children}
55
+ </div>
56
+ </div>
57
+ );
58
+ };
59
+
60
+ export const ModalRegistry = registry({
61
+ name: "modal",
62
+ render: Modal,
63
+ });
64
+ ```
65
+
66
+ ### 2. Configure Overkit
67
+
68
+ ```tsx
69
+ // overlays.tsx
70
+ import { Overkit } from "overkit";
71
+ import { ModalRegistry } from "./modal";
72
+
73
+ const o = new Overkit(["userModal", "confirmDialog"] as const)
74
+ .with(ModalRegistry)
75
+ .build();
76
+
77
+ // Create simple overlay
78
+ const userDialog = o.create("userModal", "modal").configure({
79
+ title: "User Profile",
80
+ description: "Manage your profile information",
81
+ });
82
+
83
+ // Create overlay with extended state
84
+ const confirmDialog = o
85
+ .create("confirmDialog", "modal")
86
+ .extend<{ message: string }>(() => ({
87
+ message: "",
88
+ }))
89
+ .configure({
90
+ title: "Confirm Action",
91
+ description: "Are you sure?",
92
+ });
93
+
94
+ // Export components
95
+ export const UserModalTrigger = userDialog.trigger;
96
+ export const UserModalView = userDialog.view;
97
+
98
+ export const ConfirmTrigger = confirmDialog.trigger;
99
+ export const ConfirmView = confirmDialog.view;
100
+ export const useOverkitStore = o.useOverkitStore;
101
+ ```
102
+
103
+ ### 3. Use in Your App
104
+
105
+ ```tsx
106
+ // page.tsx
107
+ import { UserModalTrigger, UserModalView } from "./overlays";
108
+
109
+ export default function Page() {
110
+ return (
111
+ <div>
112
+ <UserModalTrigger>
113
+ <button>Open User Modal</button>
114
+ </UserModalTrigger>
115
+
116
+ <UserModalView />
117
+ </div>
118
+ );
119
+ }
120
+ ```
121
+
122
+ ## API
123
+
124
+ ### `Overkit`
125
+
126
+ The main class for creating and managing overlays.
127
+
128
+ ```tsx
129
+ const o = new Overkit(["key1", "key2"] as const).with(RegistryItem).build();
130
+ ```
131
+
132
+ ### `.create(key, registryName)`
133
+
134
+ Creates a new overlay.
135
+
136
+ ```tsx
137
+ const dialog = o.create("myDialog", "modal");
138
+ ```
139
+
140
+ ### `.extend<State>(storeCreator)`
141
+
142
+ Extends the overlay state with additional properties.
143
+
144
+ ```tsx
145
+ const dialog = o
146
+ .create("myDialog", "modal")
147
+ .extend<{ count: number }>((set) => ({
148
+ count: 0,
149
+ increment: () => set((state) => ({ count: state.count + 1 })),
150
+ }));
151
+ ```
152
+
153
+ ### `.configure(options)`
154
+
155
+ Configures the overlay properties. You can use static values or functions that receive the store:
156
+
157
+ ```tsx
158
+ const dialog = o
159
+ .create("productDialog", "modal")
160
+ .extend<{ mode: "create" | "edit" }>((set) => ({
161
+ mode: "create",
162
+ setMode: (mode) => set({ mode }),
163
+ }))
164
+ .configure({
165
+ // Static values
166
+ title: "Product",
167
+
168
+ // Functions with store access
169
+ title: (store) =>
170
+ store?.mode === "create" ? "Create Product" : "Edit Product",
171
+ description: (store) =>
172
+ store?.mode === "create"
173
+ ? "Create a new product"
174
+ : "Edit existing product",
175
+ className: (store) =>
176
+ store?.mode === "create" ? "mode-create" : "mode-edit",
177
+ });
178
+ ```
179
+
180
+ ### `trigger`
181
+
182
+ Component to open the overlay.
183
+
184
+ ```tsx
185
+ <Trigger>
186
+ <button>Open</button>
187
+ </Trigger>
188
+
189
+ // With initial store values
190
+ <Trigger count={100}>
191
+ <button>Open with 100</button>
192
+ </Trigger>
193
+
194
+ // With componentProps for the view
195
+ <Trigger componentProps={{ items: ["a", "b", "c"] }}>
196
+ <button>Open with Items</button>
197
+ </Trigger>
198
+ ```
199
+
200
+ ### `view`
201
+
202
+ Component that renders the overlay content.
203
+
204
+ ```tsx
205
+ // Basic
206
+ const View = dialog.view(() => <div>Content</div>);
207
+
208
+ // With props
209
+ const View = dialog.view<{ items: string[] }>(({ items }) => (
210
+ <ul>
211
+ {items.map((item) => (
212
+ <li key={item}>{item}</li>
213
+ ))}
214
+ </ul>
215
+ ));
216
+
217
+ // With close function
218
+ const View = dialog.view(({ close }) => (
219
+ <div>
220
+ <button onClick={close}>Close</button>
221
+ </div>
222
+ ));
223
+
224
+ // With useInnerContext (requires .extend())
225
+ const View = dialog.view(({ useInnerContext }) => {
226
+ const count = useInnerContext((state) => state.count);
227
+ const increment = useInnerContext((state) => state.increment);
228
+
229
+ return (
230
+ <div>
231
+ <p>Count: {count}</p>
232
+ <button onClick={increment}>Increment</button>
233
+ </div>
234
+ );
235
+ });
236
+ ```
237
+
238
+ ### `useOverkitStore`
239
+
240
+ Hook to access the global state of all overlays.
241
+
242
+ ```tsx
243
+ const isOpen = useOverkitStore((state) => state.states.myDialog);
244
+ const setOpen = useOverkitStore((state) => state.setMyDialog);
245
+
246
+ // Open/close programmatically
247
+ setOpen(true);
248
+ setOpen(false);
249
+ ```
250
+
251
+ ## Advanced Examples
252
+
253
+ ### Product Sheet (Create/Edit)
254
+
255
+ ```tsx
256
+ const productSheet = o
257
+ .create("productSheet", "Sheet")
258
+ .extend<ProductState>((set) => ({
259
+ mode: "create",
260
+ setMode: (mode) => set({ mode }),
261
+ }))
262
+ .configure({
263
+ title: (store) => {
264
+ return store?.mode === "create" ? "Create a Product" : "Edit Product";
265
+ },
266
+ description: (store) => {
267
+ return store?.mode === "create"
268
+ ? "Fill in the details of the product you want to create"
269
+ : "Fill in the details of the product you want to edit";
270
+ },
271
+ className: "!max-w-none w-3/8",
272
+ });
273
+ ```
274
+
275
+ ### Counter with Extended State
276
+
277
+ ```tsx
278
+ const counterDialog = o
279
+ .create("counter", "modal")
280
+ .extend<{ count: number }>((set) => ({
281
+ count: 0,
282
+ }))
283
+ .configure({
284
+ title: "Counter Dialog",
285
+ });
286
+
287
+ // Open with initial value
288
+ <counterDialog.trigger count={100}>
289
+ <button>Open with 100</button>
290
+ </counterDialog.trigger>;
291
+
292
+ // Use in the view
293
+ const CounterView = counterDialog.view(({ useInnerContext }) => {
294
+ const count = useInnerContext((state) => state.count);
295
+ return <div>Count: {count}</div>;
296
+ });
297
+ ```
298
+
299
+ ## TypeScript
300
+
301
+ Overkit is fully typed. When creating overlays, types are automatically inferred:
302
+
303
+ ```tsx
304
+ // Keys are validated at compile time
305
+ const o = new Overkit(["dialog1", "dialog2"] as const);
306
+
307
+ // TypeScript knows only "dialog1" and "dialog2" are valid
308
+ o.create("dialog1", "modal"); // ✅
309
+ o.create("dialog3", "modal"); // ❌ Type error
310
+ ```
311
+
312
+ ## License
313
+
314
+ MIT
package/package.json CHANGED
@@ -1,75 +1,75 @@
1
- {
2
- "name": "overkit",
3
- "version": "0.0.2",
4
- "description": "Simplified overlay management system for React",
5
- "type": "module",
6
- "main": "./dist/index.mjs",
7
- "module": "./dist/index.mjs",
8
- "types": "./dist/index.d.mts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.mts",
12
- "import": "./dist/index.mjs",
13
- "require": "./dist/index.mjs"
14
- }
15
- },
16
- "files": [
17
- "dist",
18
- "README.md"
19
- ],
20
- "scripts": {
21
- "build": "tsdown",
22
- "test": "vitest",
23
- "test:ui": "vitest --ui",
24
- "test:run": "vitest run"
25
- },
26
- "keywords": [
27
- "react",
28
- "reactjs",
29
- "overlay",
30
- "modal",
31
- "dialog",
32
- "drawer",
33
- "sheet",
34
- "portal",
35
- "zustand",
36
- "state-management",
37
- "typescript"
38
- ],
39
- "author": {
40
- "name": "Jean Caiza",
41
- "email": "jeanmcm@hotmail.com",
42
- "url": "https://github.com/jfortez"
43
- },
44
- "license": "MIT",
45
- "repository": {
46
- "type": "git",
47
- "url": "https://github.com/jfortez/overkit.git",
48
- "directory": "lib/overkit"
49
- },
50
- "bugs": {
51
- "url": "https://github.com/jfortez/overkit/issues"
52
- },
53
- "homepage": "https://github.com/jfortez/overkit#readme",
54
- "devDependencies": {
55
- "@testing-library/jest-dom": "^6.9.1",
56
- "@testing-library/react": "^16.0.0",
57
- "@types/bun": "latest",
58
- "@types/react": "^19.0.0",
59
- "@types/react-dom": "^19.0.0",
60
- "@vitejs/plugin-react": "^4.3.0",
61
- "jsdom": "^25.0.0",
62
- "tsdown": "^0.20.3",
63
- "typescript": "^5.0.0",
64
- "vitest": "^2.1.0"
65
- },
66
- "peerDependencies": {
67
- "react": ">=18.0.0",
68
- "react-dom": ">=18.0.0"
69
- },
70
- "dependencies": {
71
- "zustand": "^5.0.0",
72
- "@radix-ui/react-slot": "^1.1.0",
73
- "tunnel-rat": "^0.1.0"
74
- }
75
- }
1
+ {
2
+ "name": "overkit",
3
+ "version": "0.0.3",
4
+ "description": "Simplified overlay management system for React",
5
+ "type": "module",
6
+ "main": "./dist/index.mjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.mts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.mts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.mjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsdown",
22
+ "test": "vitest",
23
+ "test:ui": "vitest --ui",
24
+ "test:run": "vitest run"
25
+ },
26
+ "keywords": [
27
+ "react",
28
+ "reactjs",
29
+ "overlay",
30
+ "modal",
31
+ "dialog",
32
+ "drawer",
33
+ "sheet",
34
+ "portal",
35
+ "zustand",
36
+ "state-management",
37
+ "typescript"
38
+ ],
39
+ "author": {
40
+ "name": "Jean Caiza",
41
+ "email": "jeanmcm@hotmail.com",
42
+ "url": "https://github.com/jfortez"
43
+ },
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/jfortez/overkit.git",
48
+ "directory": "lib/overkit"
49
+ },
50
+ "bugs": {
51
+ "url": "https://github.com/jfortez/overkit/issues"
52
+ },
53
+ "homepage": "https://github.com/jfortez/overkit#readme",
54
+ "devDependencies": {
55
+ "@testing-library/jest-dom": "^6.9.1",
56
+ "@testing-library/react": "^16.0.0",
57
+ "@types/bun": "latest",
58
+ "@types/react": "^19.0.0",
59
+ "@types/react-dom": "^19.0.0",
60
+ "@vitejs/plugin-react": "^4.3.0",
61
+ "jsdom": "^25.0.0",
62
+ "tsdown": "^0.20.3",
63
+ "typescript": "^5.0.0",
64
+ "vitest": "^2.1.0"
65
+ },
66
+ "peerDependencies": {
67
+ "react": ">=18.0.0",
68
+ "react-dom": ">=18.0.0"
69
+ },
70
+ "dependencies": {
71
+ "zustand": "^5.0.0",
72
+ "@radix-ui/react-slot": "^1.1.0",
73
+ "tunnel-rat": "^0.1.0"
74
+ }
75
+ }