zustic 1.0.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 +439 -0
- package/dist/index.d.mts +36 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +66 -0
- package/dist/index.mjs +44 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
# Zustic
|
|
2
|
+
|
|
3
|
+
A lightweight, minimal state management library for React using `useSyncExternalStore`. Perfect for managing global state in React, React Native, and Next.js applications.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/zustic)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://bundlephobia.com/package/zustic)
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
✨ **Lightweight** - Minimal footprint with zero dependencies (except React)
|
|
12
|
+
⚡ **Simple API** - Intuitive and easy to learn state management
|
|
13
|
+
🎣 **React Hooks** - Use hooks to access state in your components
|
|
14
|
+
📱 **Multi-Platform** - Works with React, React Native, and Next.js
|
|
15
|
+
🔄 **Reactive Updates** - Automatic re-renders on state changes
|
|
16
|
+
💾 **TypeScript Support** - Full TypeScript support with type safety
|
|
17
|
+
🚀 **Production Ready** - Optimized for performance and reliability
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install zustic
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
or with yarn:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add zustic
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
or with pnpm:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add zustic
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { create } from 'zustic';
|
|
43
|
+
|
|
44
|
+
type CounterStore = {
|
|
45
|
+
count: number;
|
|
46
|
+
inc: () => void;
|
|
47
|
+
dec: () => void;
|
|
48
|
+
reset: () => void;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const useCounter = create<CounterStore>((set) => ({
|
|
52
|
+
count: 0,
|
|
53
|
+
inc: () => set((state) => ({ count: state.count + 1 })),
|
|
54
|
+
dec: () => set((state) => ({ count: state.count - 1 })),
|
|
55
|
+
reset: () => set({ count: 0 }),
|
|
56
|
+
}));
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Using in React Components
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { useCounter } from './store';
|
|
63
|
+
|
|
64
|
+
function Counter() {
|
|
65
|
+
const { count, inc, dec, reset } = useCounter();
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div>
|
|
69
|
+
<p>Count: {count}</p>
|
|
70
|
+
<button onClick={inc}>Increment</button>
|
|
71
|
+
<button onClick={dec}>Decrement</button>
|
|
72
|
+
<button onClick={reset}>Reset</button>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default Counter;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### `create<T>(initializer)`
|
|
83
|
+
|
|
84
|
+
Creates a new store with the given state and actions.
|
|
85
|
+
|
|
86
|
+
#### Parameters
|
|
87
|
+
|
|
88
|
+
- **initializer** `(set: (partial: Partial<T> | ((state: T) => Partial<T>)) => void) => T`
|
|
89
|
+
- A function that receives the `set` function and returns the initial state object
|
|
90
|
+
- The `set` function accepts either a partial state object or a function that takes the current state and returns a partial state object
|
|
91
|
+
|
|
92
|
+
#### Returns
|
|
93
|
+
|
|
94
|
+
A React hook function that provides access to the store state.
|
|
95
|
+
|
|
96
|
+
#### Type Parameters
|
|
97
|
+
|
|
98
|
+
- **T** `extends object` - The shape of your store state
|
|
99
|
+
|
|
100
|
+
## Advanced Examples
|
|
101
|
+
|
|
102
|
+
### 1. Combining Multiple Stores
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { create } from 'zustic';
|
|
106
|
+
|
|
107
|
+
// User store
|
|
108
|
+
export const useUserStore = create<UserStore>((set) => ({
|
|
109
|
+
user: null,
|
|
110
|
+
setUser: (user) => set({ user }),
|
|
111
|
+
clearUser: () => set({ user: null }),
|
|
112
|
+
}));
|
|
113
|
+
|
|
114
|
+
// Todos store
|
|
115
|
+
export const useTodosStore = create<TodosStore>((set) => ({
|
|
116
|
+
todos: [],
|
|
117
|
+
addTodo: (todo) => set((state) => ({
|
|
118
|
+
todos: [...state.todos, todo]
|
|
119
|
+
})),
|
|
120
|
+
removeTodo: (id) => set((state) => ({
|
|
121
|
+
todos: state.todos.filter(t => t.id !== id)
|
|
122
|
+
})),
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
// Use both in a component
|
|
126
|
+
function App() {
|
|
127
|
+
const user = useUserStore();
|
|
128
|
+
const todos = useTodosStore();
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<>
|
|
132
|
+
<User />
|
|
133
|
+
<TodoList />
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. Complex State Updates
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
const useShopStore = create<ShopStore>((set) => ({
|
|
143
|
+
items: [],
|
|
144
|
+
cart: [],
|
|
145
|
+
total: 0,
|
|
146
|
+
|
|
147
|
+
addToCart: (item) => set((state) => ({
|
|
148
|
+
cart: [...state.cart, item],
|
|
149
|
+
total: state.total + item.price,
|
|
150
|
+
})),
|
|
151
|
+
|
|
152
|
+
removeFromCart: (itemId) => set((state) => ({
|
|
153
|
+
cart: state.cart.filter(item => item.id !== itemId),
|
|
154
|
+
total: state.total - state.cart.find(item => item.id === itemId)?.price || 0,
|
|
155
|
+
})),
|
|
156
|
+
|
|
157
|
+
clearCart: () => set({
|
|
158
|
+
cart: [],
|
|
159
|
+
total: 0,
|
|
160
|
+
}),
|
|
161
|
+
}));
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 3. Computed Values
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const useStatsStore = create<StatsStore>((set) => ({
|
|
168
|
+
scores: [],
|
|
169
|
+
|
|
170
|
+
addScore: (score) => set((state) => ({
|
|
171
|
+
scores: [...state.scores, score],
|
|
172
|
+
})),
|
|
173
|
+
|
|
174
|
+
// You can compute values directly in the component
|
|
175
|
+
// or create selector functions
|
|
176
|
+
getAverage: (state) => {
|
|
177
|
+
if (state.scores.length === 0) return 0;
|
|
178
|
+
return state.scores.reduce((a, b) => a + b, 0) / state.scores.length;
|
|
179
|
+
},
|
|
180
|
+
}));
|
|
181
|
+
|
|
182
|
+
function Stats() {
|
|
183
|
+
const { scores, addScore, getAverage } = useStatsStore();
|
|
184
|
+
const average = getAverage(useStatsStore());
|
|
185
|
+
|
|
186
|
+
return <div>Average: {average}</div>;
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 4. Next.js Usage
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// store/counterStore.ts
|
|
194
|
+
import { create } from 'zustic';
|
|
195
|
+
|
|
196
|
+
export const useCounterStore = create<CounterStore>((set) => ({
|
|
197
|
+
count: 0,
|
|
198
|
+
increment: () => set((state) => ({ count: state.count + 1 })),
|
|
199
|
+
decrement: () => set((state) => ({ count: state.count - 1 })),
|
|
200
|
+
}));
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// app/page.tsx
|
|
205
|
+
'use client';
|
|
206
|
+
|
|
207
|
+
import { useCounterStore } from '@/store/counterStore';
|
|
208
|
+
|
|
209
|
+
export default function Home() {
|
|
210
|
+
const { count, increment, decrement } = useCounterStore();
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<main>
|
|
214
|
+
<h1>Count: {count}</h1>
|
|
215
|
+
<button onClick={increment}>+</button>
|
|
216
|
+
<button onClick={decrement}>-</button>
|
|
217
|
+
</main>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 5. React Native Usage
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { create } from 'zustic';
|
|
226
|
+
import { View, Text, TouchableOpacity } from 'react-native';
|
|
227
|
+
|
|
228
|
+
const useThemeStore = create<ThemeStore>((set) => ({
|
|
229
|
+
isDark: false,
|
|
230
|
+
toggleTheme: () => set((state) => ({ isDark: !state.isDark })),
|
|
231
|
+
}));
|
|
232
|
+
|
|
233
|
+
function App() {
|
|
234
|
+
const { isDark, toggleTheme } = useThemeStore();
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
<View style={{ backgroundColor: isDark ? '#000' : '#fff' }}>
|
|
238
|
+
<Text>{isDark ? 'Dark Mode' : 'Light Mode'}</Text>
|
|
239
|
+
<TouchableOpacity onPress={toggleTheme}>
|
|
240
|
+
<Text>Toggle Theme</Text>
|
|
241
|
+
</TouchableOpacity>
|
|
242
|
+
</View>
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Best Practices
|
|
248
|
+
|
|
249
|
+
### 1. **Organize Stores**
|
|
250
|
+
Keep your stores organized in a dedicated directory:
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
src/
|
|
254
|
+
├── stores/
|
|
255
|
+
│ ├── counterStore.ts
|
|
256
|
+
│ ├── userStore.ts
|
|
257
|
+
│ └── index.ts
|
|
258
|
+
└── components/
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 2. **Type Your Store**
|
|
262
|
+
Always define proper TypeScript types for better type safety:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
interface CounterState {
|
|
266
|
+
count: number;
|
|
267
|
+
inc: () => void;
|
|
268
|
+
dec: () => void;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export const useCounter = create<CounterState>((set) => ({
|
|
272
|
+
count: 0,
|
|
273
|
+
inc: () => set((state) => ({ count: state.count + 1 })),
|
|
274
|
+
dec: () => set((state) => ({ count: state.count - 1 })),
|
|
275
|
+
}));
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### 3. **Keep State Flat**
|
|
279
|
+
Try to keep your state structure as flat as possible for better performance:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// ❌ Avoid deeply nested structures
|
|
283
|
+
const state = { user: { profile: { settings: { theme: 'dark' } } } };
|
|
284
|
+
|
|
285
|
+
// ✅ Prefer flat structures
|
|
286
|
+
const state = { userTheme: 'dark' };
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 4. **Use Immutable Updates**
|
|
290
|
+
Always return new objects instead of mutating state:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// ❌ Bad - mutating state
|
|
294
|
+
set((state) => {
|
|
295
|
+
state.items.push(newItem);
|
|
296
|
+
return state;
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// ✅ Good - immutable updates
|
|
300
|
+
set((state) => ({
|
|
301
|
+
items: [...state.items, newItem],
|
|
302
|
+
}));
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Performance Tips
|
|
306
|
+
|
|
307
|
+
1. **Minimize Subscriptions** - Only subscribe to the parts of the state you need
|
|
308
|
+
2. **Use Memoization** - Memoize components that depend on store state
|
|
309
|
+
3. **Avoid Large Objects** - Split large stores into multiple smaller ones
|
|
310
|
+
4. **Batch Updates** - Group related state updates together
|
|
311
|
+
|
|
312
|
+
## Browser Support
|
|
313
|
+
|
|
314
|
+
Zustic works in all modern browsers that support ES6 and React 16.8+.
|
|
315
|
+
|
|
316
|
+
- Chrome/Edge (latest)
|
|
317
|
+
- Firefox (latest)
|
|
318
|
+
- Safari (latest)
|
|
319
|
+
- Mobile browsers supporting React Native
|
|
320
|
+
|
|
321
|
+
## Comparison
|
|
322
|
+
|
|
323
|
+
| Feature | Zustic | Zustand | Redux | Context API |
|
|
324
|
+
|---------|--------|---------|-------|-------------|
|
|
325
|
+
| Bundle Size | ~500B | ~2KB | ~7KB | - |
|
|
326
|
+
| Learning Curve | Very Easy | Easy | Hard | Medium |
|
|
327
|
+
| Boilerplate | Minimal | Minimal | Lots | Medium |
|
|
328
|
+
| DevTools | No | Yes | Yes | No |
|
|
329
|
+
| Middleware | No | Yes | Yes | No |
|
|
330
|
+
| TypeScript | ✅ | ✅ | ✅ | ✅ |
|
|
331
|
+
|
|
332
|
+
## Troubleshooting
|
|
333
|
+
|
|
334
|
+
### State not updating?
|
|
335
|
+
Make sure you're using the `set` function correctly. Always return a new object:
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// ❌ Wrong
|
|
339
|
+
set({ count: state.count + 1 }); // state is undefined here
|
|
340
|
+
|
|
341
|
+
// ✅ Correct
|
|
342
|
+
set((state) => ({ count: state.count + 1 }));
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Component not re-rendering?
|
|
346
|
+
Ensure you're using the hook at the top level of your component:
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// ❌ Bad
|
|
350
|
+
if (condition) {
|
|
351
|
+
const state = useStore();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ✅ Good
|
|
355
|
+
const state = useStore();
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Migration Guide
|
|
359
|
+
|
|
360
|
+
### From Context API
|
|
361
|
+
|
|
362
|
+
Before:
|
|
363
|
+
```typescript
|
|
364
|
+
const CounterContext = createContext();
|
|
365
|
+
|
|
366
|
+
export function CounterProvider({ children }) {
|
|
367
|
+
const [count, setCount] = useState(0);
|
|
368
|
+
|
|
369
|
+
return (
|
|
370
|
+
<CounterContext.Provider value={{ count, setCount }}>
|
|
371
|
+
{children}
|
|
372
|
+
</CounterContext.Provider>
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function useCounter() {
|
|
377
|
+
return useContext(CounterContext);
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
After:
|
|
382
|
+
```typescript
|
|
383
|
+
export const useCounter = create((set) => ({
|
|
384
|
+
count: 0,
|
|
385
|
+
setCount: (count) => set({ count }),
|
|
386
|
+
}));
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### From Redux
|
|
390
|
+
|
|
391
|
+
Before:
|
|
392
|
+
```typescript
|
|
393
|
+
const counterSlice = createSlice({
|
|
394
|
+
name: 'counter',
|
|
395
|
+
initialState: { count: 0 },
|
|
396
|
+
reducers: {
|
|
397
|
+
increment: (state) => { state.count += 1; },
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
export const { increment } = counterSlice.actions;
|
|
402
|
+
export default useSelector((state) => state.counter);
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
After:
|
|
406
|
+
```typescript
|
|
407
|
+
export const useCounter = create((set) => ({
|
|
408
|
+
count: 0,
|
|
409
|
+
increment: () => set((state) => ({ count: state.count + 1 })),
|
|
410
|
+
}));
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Contributing
|
|
414
|
+
|
|
415
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
416
|
+
|
|
417
|
+
## License
|
|
418
|
+
|
|
419
|
+
ISC © 2024 [Rejaul Karim](https://github.com/DeveloperRejaul)
|
|
420
|
+
|
|
421
|
+
## Support
|
|
422
|
+
|
|
423
|
+
- 📖 [Documentation](https://github.com/DeveloperRejaul/zustic)
|
|
424
|
+
- 🐛 [Bug Reports](https://github.com/DeveloperRejaul/zustic/issues)
|
|
425
|
+
- 💬 [Discussions](https://github.com/DeveloperRejaul/zustic/discussions)
|
|
426
|
+
|
|
427
|
+
## Related Projects
|
|
428
|
+
|
|
429
|
+
- [Zustand](https://github.com/pmndrs/zustand) - A small, fast and scalable bearbones state-management solution
|
|
430
|
+
- [Jotai](https://github.com/pmndrs/jotai) - Primitive and flexible state management for React
|
|
431
|
+
- [Recoil](https://recoiljs.org/) - A state management library for React
|
|
432
|
+
|
|
433
|
+
## Changelog
|
|
434
|
+
|
|
435
|
+
### v1.0.0 (2026)
|
|
436
|
+
- Initial release
|
|
437
|
+
- Basic state management with `create` function
|
|
438
|
+
- TypeScript support
|
|
439
|
+
- React, React Native, and Next.js compatibility
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a store with state and actions.
|
|
3
|
+
*
|
|
4
|
+
* Example usage:
|
|
5
|
+
* ```ts
|
|
6
|
+
* type CreateType = {
|
|
7
|
+
* count: number;
|
|
8
|
+
* inc: () => void;
|
|
9
|
+
* dec: () => void;
|
|
10
|
+
* }
|
|
11
|
+
*
|
|
12
|
+
* export const useCounter = create<CreateType>((set) => ({
|
|
13
|
+
* count: 1,
|
|
14
|
+
* inc: () => set((state) => ({ count: state.count + 1 })),
|
|
15
|
+
* dec: () => set((state) => ({ count: state.count - 1 })),
|
|
16
|
+
* })));
|
|
17
|
+
*
|
|
18
|
+
* // In a React component:
|
|
19
|
+
* const Counter = () => {
|
|
20
|
+
* const { count, inc, dec } = useCounter();
|
|
21
|
+
* return (
|
|
22
|
+
* <>
|
|
23
|
+
* <Text>{count}</Text>
|
|
24
|
+
* <Button title="+" onPress={inc} />
|
|
25
|
+
* <Button title="-" onPress={dec} />
|
|
26
|
+
* </>
|
|
27
|
+
* );
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param initializer Function that receives `set` and returns the initial state object.
|
|
32
|
+
* @returns A hook that provides access to the store state and actions.
|
|
33
|
+
*/
|
|
34
|
+
declare function create<T extends object>(initializer: (set: (partial: Partial<T> | ((state: T) => Partial<T>)) => void) => T): () => T;
|
|
35
|
+
|
|
36
|
+
export { create };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a store with state and actions.
|
|
3
|
+
*
|
|
4
|
+
* Example usage:
|
|
5
|
+
* ```ts
|
|
6
|
+
* type CreateType = {
|
|
7
|
+
* count: number;
|
|
8
|
+
* inc: () => void;
|
|
9
|
+
* dec: () => void;
|
|
10
|
+
* }
|
|
11
|
+
*
|
|
12
|
+
* export const useCounter = create<CreateType>((set) => ({
|
|
13
|
+
* count: 1,
|
|
14
|
+
* inc: () => set((state) => ({ count: state.count + 1 })),
|
|
15
|
+
* dec: () => set((state) => ({ count: state.count - 1 })),
|
|
16
|
+
* })));
|
|
17
|
+
*
|
|
18
|
+
* // In a React component:
|
|
19
|
+
* const Counter = () => {
|
|
20
|
+
* const { count, inc, dec } = useCounter();
|
|
21
|
+
* return (
|
|
22
|
+
* <>
|
|
23
|
+
* <Text>{count}</Text>
|
|
24
|
+
* <Button title="+" onPress={inc} />
|
|
25
|
+
* <Button title="-" onPress={dec} />
|
|
26
|
+
* </>
|
|
27
|
+
* );
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param initializer Function that receives `set` and returns the initial state object.
|
|
32
|
+
* @returns A hook that provides access to the store state and actions.
|
|
33
|
+
*/
|
|
34
|
+
declare function create<T extends object>(initializer: (set: (partial: Partial<T> | ((state: T) => Partial<T>)) => void) => T): () => T;
|
|
35
|
+
|
|
36
|
+
export { create };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __export = (target, all) => {
|
|
22
|
+
for (var name in all)
|
|
23
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
24
|
+
};
|
|
25
|
+
var __copyProps = (to, from, except, desc) => {
|
|
26
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
27
|
+
for (let key of __getOwnPropNames(from))
|
|
28
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
29
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
30
|
+
}
|
|
31
|
+
return to;
|
|
32
|
+
};
|
|
33
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
34
|
+
|
|
35
|
+
// src/index.ts
|
|
36
|
+
var index_exports = {};
|
|
37
|
+
__export(index_exports, {
|
|
38
|
+
create: () => create
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
var import_react = require("react");
|
|
42
|
+
function create(initializer) {
|
|
43
|
+
let state;
|
|
44
|
+
let listeners = [];
|
|
45
|
+
const setState = (partial) => {
|
|
46
|
+
const partialState = typeof partial === "function" ? partial(state) : partial;
|
|
47
|
+
state = __spreadValues(__spreadValues({}, state), partialState);
|
|
48
|
+
listeners.forEach((l) => l());
|
|
49
|
+
};
|
|
50
|
+
state = initializer(setState);
|
|
51
|
+
const subscribe = (listener) => {
|
|
52
|
+
listeners.push(listener);
|
|
53
|
+
return () => {
|
|
54
|
+
listeners = listeners.filter((l) => l !== listener);
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
const getSnapshot = () => state;
|
|
58
|
+
return function useStore() {
|
|
59
|
+
const snapshot = (0, import_react.useSyncExternalStore)(subscribe, getSnapshot);
|
|
60
|
+
return snapshot;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
create
|
|
66
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __spreadValues = (a, b) => {
|
|
8
|
+
for (var prop in b || (b = {}))
|
|
9
|
+
if (__hasOwnProp.call(b, prop))
|
|
10
|
+
__defNormalProp(a, prop, b[prop]);
|
|
11
|
+
if (__getOwnPropSymbols)
|
|
12
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
13
|
+
if (__propIsEnum.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
}
|
|
16
|
+
return a;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// src/index.ts
|
|
20
|
+
import { useSyncExternalStore } from "react";
|
|
21
|
+
function create(initializer) {
|
|
22
|
+
let state;
|
|
23
|
+
let listeners = [];
|
|
24
|
+
const setState = (partial) => {
|
|
25
|
+
const partialState = typeof partial === "function" ? partial(state) : partial;
|
|
26
|
+
state = __spreadValues(__spreadValues({}, state), partialState);
|
|
27
|
+
listeners.forEach((l) => l());
|
|
28
|
+
};
|
|
29
|
+
state = initializer(setState);
|
|
30
|
+
const subscribe = (listener) => {
|
|
31
|
+
listeners.push(listener);
|
|
32
|
+
return () => {
|
|
33
|
+
listeners = listeners.filter((l) => l !== listener);
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
const getSnapshot = () => state;
|
|
37
|
+
return function useStore() {
|
|
38
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot);
|
|
39
|
+
return snapshot;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
create
|
|
44
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zustic",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A fast, minimal state management solution for React ecosystems. Works seamlessly with React, Next.js, and React Native, offering predictable state updates with a tiny footprint.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean --external react",
|
|
10
|
+
"start:cjs": "node dist/cjs/index.js",
|
|
11
|
+
"start:esm": "node dist/esm/index.js",
|
|
12
|
+
"start": "ts-node src/index.ts",
|
|
13
|
+
"test": "npm run build && npm link"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"require": "./dist/index.js",
|
|
18
|
+
"import": "./dist/index.mjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"directories": {
|
|
22
|
+
"dist": "dist"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/DeveloperRejaul/zustic.git"
|
|
27
|
+
},
|
|
28
|
+
"author": "Rejaul Karim",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/DeveloperRejaul/zustic/issues"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"javascript",
|
|
35
|
+
"zustic",
|
|
36
|
+
"react",
|
|
37
|
+
"react-native",
|
|
38
|
+
"nextjs",
|
|
39
|
+
"state"
|
|
40
|
+
],
|
|
41
|
+
"homepage": "https://github.com/DeveloperRejaul/zustic#readme",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist/**/*",
|
|
44
|
+
"README.md"
|
|
45
|
+
],
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"registry": "https://registry.npmjs.org/",
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "^19.1.16",
|
|
52
|
+
"react": "^19.1.1",
|
|
53
|
+
"@types/node": "^22.7.4",
|
|
54
|
+
"ts-node": "^10.9.2",
|
|
55
|
+
"tslib": "^2.7.0",
|
|
56
|
+
"tsup": "^8.3.0",
|
|
57
|
+
"typescript": "^5.6.2"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"react": "*"
|
|
61
|
+
},
|
|
62
|
+
"sideEffects": false
|
|
63
|
+
}
|