zustand-kit 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 +299 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.esm.js +1 -0
- package/package.json +63 -0
- package/types/index.d.ts +124 -0
package/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# zustand-kit
|
|
2
|
+
|
|
3
|
+
[English](./README_EN.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
一个基于 Zustand 构建的轻量级、灵活的 React 状态管理库。
|
|
6
|
+
|
|
7
|
+
## ✨ 特性
|
|
8
|
+
|
|
9
|
+
- 🚀 **简单易用** - 最小化的 API 设计,易于上手
|
|
10
|
+
- 🎯 **类型安全** - 完整的 TypeScript 支持
|
|
11
|
+
- 💾 **持久化** - 内置 localStorage/sessionStorage 支持
|
|
12
|
+
- ⚡ **高性能** - 基于 Zustand,性能卓越
|
|
13
|
+
- 🔄 **灵活更新** - 支持对象部分更新和函数式更新
|
|
14
|
+
- 🎨 **选择器支持** - 细粒度订阅,避免不必要的重渲染
|
|
15
|
+
- 🌐 **非 React 环境支持** - 提供独立的 API 用于非组件场景
|
|
16
|
+
|
|
17
|
+
## 📦 安装
|
|
18
|
+
|
|
19
|
+
yarn add zustand-x zustand
|
|
20
|
+
```bash
|
|
21
|
+
npm install zustand-kit zustand
|
|
22
|
+
# 或
|
|
23
|
+
yarn add zustand-kit zustand
|
|
24
|
+
# 或
|
|
25
|
+
pnpm add zustand-kit zustand
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 🎯 快速开始
|
|
29
|
+
|
|
30
|
+
### 基础用法
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { useGlobalState } from 'zustand-kit';
|
|
34
|
+
|
|
35
|
+
function Counter() {
|
|
36
|
+
const [count, setCount, resetCount] = useGlobalState('counter', 0);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div>
|
|
40
|
+
<p>Count: {count}</p>
|
|
41
|
+
<button onClick={() => setCount(count + 1)}>增加</button>
|
|
42
|
+
<button onClick={() => setCount(prev => prev - 1)}>减少</button>
|
|
43
|
+
<button onClick={resetCount}>重置</button>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 对象状态(支持部分更新)
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { useGlobalState } from 'zustand-x';
|
|
53
|
+
|
|
54
|
+
function UserProfile() {
|
|
55
|
+
const [user, setUser, resetUser] = useGlobalState('user', {
|
|
56
|
+
name: 'John',
|
|
57
|
+
email: 'john@example.com',
|
|
58
|
+
age: 30
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div>
|
|
63
|
+
<p>名称: {user.name}</p>
|
|
64
|
+
<p>邮箱: {user.email}</p>
|
|
65
|
+
{/* 部分更新 - 只更新 name,其他字段保持不变 */}
|
|
66
|
+
<button onClick={() => setUser({ name: 'Jane' })}>
|
|
67
|
+
更改名称
|
|
68
|
+
</button>
|
|
69
|
+
<button onClick={resetUser}>重置</button>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 持久化状态
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { useGlobalState } from 'zustand-x';
|
|
79
|
+
|
|
80
|
+
function Settings() {
|
|
81
|
+
// 使用 localStorage 持久化
|
|
82
|
+
const [settings, setSettings] = useGlobalState(
|
|
83
|
+
'settings',
|
|
84
|
+
{ theme: 'dark', lang: 'zh-CN' },
|
|
85
|
+
{ storage: 'localStorage' }
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// 使用 sessionStorage 持久化
|
|
89
|
+
const [tempData, setTempData] = useGlobalState(
|
|
90
|
+
'temp',
|
|
91
|
+
{ foo: 'bar' },
|
|
92
|
+
{
|
|
93
|
+
storage: 'sessionStorage',
|
|
94
|
+
storageKey: 'my-app' // 自定义存储键前缀
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<div>
|
|
100
|
+
<p>主题: {settings.theme}</p>
|
|
101
|
+
<button onClick={() => setSettings({ theme: 'light' })}>
|
|
102
|
+
切换主题
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 选择器模式(性能优化)
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import { useGlobalSelector } from 'zustand-x';
|
|
113
|
+
|
|
114
|
+
function UserName() {
|
|
115
|
+
// 仅订阅 user.name,其他字段变化不会触发重渲染
|
|
116
|
+
const userName = useGlobalSelector('user', (state) => state.name);
|
|
117
|
+
|
|
118
|
+
return <p>用户名: {userName}</p>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function UserEmail() {
|
|
122
|
+
// 仅订阅 user.email
|
|
123
|
+
const userEmail = useGlobalSelector('user', (state) => state.email);
|
|
124
|
+
|
|
125
|
+
return <p>邮箱: {userEmail}</p>;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 仅获取 Setter(不订阅状态)
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { useGlobalSetter } from 'zustand-x';
|
|
133
|
+
|
|
134
|
+
function IncrementButton() {
|
|
135
|
+
// 只获取 setter,不订阅状态变化(不会重渲染)
|
|
136
|
+
const setCount = useGlobalSetter<number>('counter');
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<button onClick={() => setCount(prev => prev + 1)}>
|
|
140
|
+
增加
|
|
141
|
+
</button>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 🔧 非 React 环境使用
|
|
147
|
+
|
|
148
|
+
zustand-x 提供了独立的 API,可以在非 React 组件中使用:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import {
|
|
152
|
+
getGlobalState,
|
|
153
|
+
setGlobalState,
|
|
154
|
+
subscribeGlobalState,
|
|
155
|
+
resetGlobalState
|
|
156
|
+
} from 'zustand-x';
|
|
157
|
+
|
|
158
|
+
// 获取状态
|
|
159
|
+
const count = getGlobalState<number>('counter');
|
|
160
|
+
|
|
161
|
+
// 设置状态
|
|
162
|
+
setGlobalState('counter', 5);
|
|
163
|
+
setGlobalState('counter', prev => prev + 1);
|
|
164
|
+
|
|
165
|
+
// 订阅状态变化
|
|
166
|
+
const unsubscribe = subscribeGlobalState('counter', (newValue, prevValue) => {
|
|
167
|
+
console.log(`Counter 从 ${prevValue} 变为 ${newValue}`);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// 取消订阅
|
|
171
|
+
unsubscribe();
|
|
172
|
+
|
|
173
|
+
// 重置状态
|
|
174
|
+
resetGlobalState('counter');
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## 📖 API 参考
|
|
178
|
+
|
|
179
|
+
### `useGlobalState<T>(key, initialState, options?)`
|
|
180
|
+
|
|
181
|
+
创建或连接到全局状态。
|
|
182
|
+
|
|
183
|
+
**参数:**
|
|
184
|
+
- `key: string` - 状态的唯一标识符
|
|
185
|
+
- `initialState: T` - 初始状态值
|
|
186
|
+
- `options?: UseGlobalStateOptions` - 可选配置
|
|
187
|
+
- `storage?: 'localStorage' | 'sessionStorage' | 'none'` - 持久化类型(默认 'none')
|
|
188
|
+
- `storageKey?: string` - 存储键前缀(默认 'global-state')
|
|
189
|
+
|
|
190
|
+
**返回:** `[state, setState, resetState]`
|
|
191
|
+
|
|
192
|
+
### `useGlobalSelector<T, R>(key, selector)`
|
|
193
|
+
|
|
194
|
+
使用选择器订阅状态的特定部分。
|
|
195
|
+
|
|
196
|
+
**参数:**
|
|
197
|
+
- `key: string` - 状态键
|
|
198
|
+
- `selector: (state: T) => R` - 选择器函数
|
|
199
|
+
|
|
200
|
+
**返回:** 选择的值
|
|
201
|
+
|
|
202
|
+
### `useGlobalSetter<T>(key)`
|
|
203
|
+
|
|
204
|
+
仅获取 setter 函数,不订阅状态变化。
|
|
205
|
+
|
|
206
|
+
**参数:**
|
|
207
|
+
- `key: string` - 状态键
|
|
208
|
+
|
|
209
|
+
**返回:** setter 函数
|
|
210
|
+
|
|
211
|
+
### `getGlobalState<T>(key)`
|
|
212
|
+
|
|
213
|
+
获取全局状态值(非 React 环境)。
|
|
214
|
+
|
|
215
|
+
### `setGlobalState<T>(key, value)`
|
|
216
|
+
|
|
217
|
+
设置全局状态值(非 React 环境)。
|
|
218
|
+
|
|
219
|
+
### `subscribeGlobalState<T>(key, callback)`
|
|
220
|
+
|
|
221
|
+
订阅全局状态变化(非 React 环境)。返回取消订阅函数。
|
|
222
|
+
|
|
223
|
+
### `resetGlobalState(key)`
|
|
224
|
+
|
|
225
|
+
重置全局状态为初始值(非 React 环境)。
|
|
226
|
+
|
|
227
|
+
## 🎨 TypeScript 支持
|
|
228
|
+
|
|
229
|
+
zustand-x 使用 TypeScript 编写,提供完整的类型推断:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// 自动推断类型
|
|
233
|
+
const [count, setCount] = useGlobalState('counter', 0);
|
|
234
|
+
// count: number
|
|
235
|
+
// setCount: (value: number | ((prev: number) => number)) => void
|
|
236
|
+
|
|
237
|
+
// 对象状态支持部分更新
|
|
238
|
+
const [user, setUser] = useGlobalState('user', {
|
|
239
|
+
name: 'John',
|
|
240
|
+
age: 30
|
|
241
|
+
});
|
|
242
|
+
// user: { name: string; age: number }
|
|
243
|
+
// setUser: (value: Partial<{name: string; age: number}> | ((prev) => ...)) => void
|
|
244
|
+
|
|
245
|
+
// 显式类型声明
|
|
246
|
+
interface User {
|
|
247
|
+
name: string;
|
|
248
|
+
email: string;
|
|
249
|
+
}
|
|
250
|
+
const [user, setUser] = useGlobalState<User>('user', {
|
|
251
|
+
name: 'John',
|
|
252
|
+
email: 'john@example.com'
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## 🤝 对比其他方案
|
|
257
|
+
|
|
258
|
+
| 特性 | zustand-x | Zustand | Redux | Context API |
|
|
259
|
+
|------|-----------|---------|-------|-------------|
|
|
260
|
+
| 学习曲线 | ⭐️ 简单 | ⭐️⭐️ 较简单 | ⭐️⭐️⭐️ 复杂 | ⭐️⭐️ 中等 |
|
|
261
|
+
| 包体积 | 极小 | 小 | 大 | 无 |
|
|
262
|
+
| 性能 | 优秀 | 优秀 | 优秀 | 较差 |
|
|
263
|
+
| TypeScript | ✅ 完整 | ✅ 完整 | ✅ 完整 | ⚠️ 基础 |
|
|
264
|
+
| 持久化 | ✅ 内置 | ✅ 中间件 | 需要插件 | ❌ |
|
|
265
|
+
| 选择器 | ✅ | ✅ | ✅ | ❌ |
|
|
266
|
+
| 易用性 | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️ | ⭐️⭐️⭐️ |
|
|
267
|
+
|
|
268
|
+
## 🧪 测试
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# 运行测试
|
|
272
|
+
npm test
|
|
273
|
+
|
|
274
|
+
# 监听模式运行测试
|
|
275
|
+
npm run test:watch
|
|
276
|
+
|
|
277
|
+
# 生成覆盖率报告
|
|
278
|
+
npm run test:coverage
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
测试覆盖率:93%+ (语句、分支、函数覆盖率)
|
|
282
|
+
|
|
283
|
+
## 📄 许可证
|
|
284
|
+
|
|
285
|
+
MIT
|
|
286
|
+
|
|
287
|
+
## 🔗 链接
|
|
288
|
+
|
|
289
|
+
- [GitHub](https://github.com/leonwgc/zustand-x)
|
|
290
|
+
- [Issues](https://github.com/leonwgc/zustand-x/issues)
|
|
291
|
+
- [Zustand](https://github.com/pmndrs/zustand)
|
|
292
|
+
|
|
293
|
+
## 👨💻 作者
|
|
294
|
+
|
|
295
|
+
leon.wang
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
如果这个项目对你有帮助,欢迎给个 ⭐️!
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var V=Object.defineProperty;var d=Object.getOwnPropertySymbols;var x=Object.prototype.hasOwnProperty,A=Object.prototype.propertyIsEnumerable;var g=(t,e,o)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o,T=(t,e)=>{for(var o in e||(e={}))x.call(e,o)&&g(t,o,e[o]);if(d)for(var o of d(e))A.call(e,o)&&g(t,o,e[o]);return t};var _zustand = require('zustand');var _middleware = require('zustand/middleware');var _react = require('react');var r=new Map;function _(){r.clear()}function B(t,e,o){let{storage:a="none",storageKey:i="global-state"}=o||{};if(!r.has(t)){let u=typeof e=="object"&&e!==null&&!Array.isArray(e),v=s=>({value:e,setValue:l=>{s(typeof l=="function"?p=>({value:l(p.value)}):u&&typeof l=="object"&&l!==null?p=>({value:T(T({},p.value),l)}):{value:l})},reset:()=>s({value:e})}),S;if(a!=="none"){let s=a==="localStorage"?localStorage:sessionStorage;S=_zustand.create.call(void 0, )(_middleware.persist.call(void 0, v,{name:`${i}-${t}`,storage:_middleware.createJSONStorage.call(void 0, ()=>s)}))}else S=_zustand.create.call(void 0, v);r.set(t,S)}let n=r.get(t),w=n(u=>u.value),b=_react.useMemo.call(void 0, ()=>n.getState().setValue,[n]),G=_react.useMemo.call(void 0, ()=>n.getState().reset,[n]);return[w,b,G]}function $(t,e){let o=r.get(t);if(!o)throw new Error(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return o(a=>e(a.value))}function I(t){let e=r.get(t);if(!e)throw new Error(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return _react.useMemo.call(void 0, ()=>e.getState().setValue,[e])}function z(t){let e=r.get(t);return e==null?void 0:e.getState().value}function P(t,e){let o=r.get(t);if(!o){process.env.NODE_ENV!=="production"&&console.warn(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return}o.getState().setValue(e)}function j(t,e){let o=r.get(t);if(!o)return process.env.NODE_ENV!=="production"&&console.warn(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`),()=>{};let a=o.getState().value;return o.subscribe(i=>{let n=i.value;n!==a&&(e(n,a),a=n)})}function C(t){let e=r.get(t);if(!e){process.env.NODE_ENV!=="production"&&console.warn(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return}e.getState().reset()}var D=B;exports.__clearAllStates__ = _; exports.default = D; exports.getGlobalState = z; exports.resetGlobalState = C; exports.setGlobalState = P; exports.subscribeGlobalState = j; exports.useGlobalSelector = $; exports.useGlobalSetter = I; exports.useGlobalState = B;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var V=Object.defineProperty;var d=Object.getOwnPropertySymbols;var x=Object.prototype.hasOwnProperty,A=Object.prototype.propertyIsEnumerable;var g=(t,e,o)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o,T=(t,e)=>{for(var o in e||(e={}))x.call(e,o)&&g(t,o,e[o]);if(d)for(var o of d(e))A.call(e,o)&&g(t,o,e[o]);return t};import{create as f}from"zustand";import{persist as h,createJSONStorage as U}from"zustand/middleware";import{useMemo as c}from"react";var r=new Map;function _(){r.clear()}function B(t,e,o){let{storage:a="none",storageKey:i="global-state"}=o||{};if(!r.has(t)){let u=typeof e=="object"&&e!==null&&!Array.isArray(e),v=s=>({value:e,setValue:l=>{s(typeof l=="function"?p=>({value:l(p.value)}):u&&typeof l=="object"&&l!==null?p=>({value:T(T({},p.value),l)}):{value:l})},reset:()=>s({value:e})}),S;if(a!=="none"){let s=a==="localStorage"?localStorage:sessionStorage;S=f()(h(v,{name:`${i}-${t}`,storage:U(()=>s)}))}else S=f(v);r.set(t,S)}let n=r.get(t),w=n(u=>u.value),b=c(()=>n.getState().setValue,[n]),G=c(()=>n.getState().reset,[n]);return[w,b,G]}function $(t,e){let o=r.get(t);if(!o)throw new Error(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return o(a=>e(a.value))}function I(t){let e=r.get(t);if(!e)throw new Error(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return c(()=>e.getState().setValue,[e])}function z(t){let e=r.get(t);return e==null?void 0:e.getState().value}function P(t,e){let o=r.get(t);if(!o){process.env.NODE_ENV!=="production"&&console.warn(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return}o.getState().setValue(e)}function j(t,e){let o=r.get(t);if(!o)return process.env.NODE_ENV!=="production"&&console.warn(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`),()=>{};let a=o.getState().value;return o.subscribe(i=>{let n=i.value;n!==a&&(e(n,a),a=n)})}function C(t){let e=r.get(t);if(!e){process.env.NODE_ENV!=="production"&&console.warn(`Global state with key "${t}" not found. Initialize it with useGlobalState first.`);return}e.getState().reset()}var D=B;export{_ as __clearAllStates__,D as default,z as getGlobalState,C as resetGlobalState,P as setGlobalState,j as subscribeGlobalState,$ as useGlobalSelector,I as useGlobalSetter,B as useGlobalState};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zustand-kit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "⚡️ A minimalist React global state management library based on Zustand with persistence, TypeScript and fine-grained subscriptions",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"zustand",
|
|
7
|
+
"react",
|
|
8
|
+
"state-management",
|
|
9
|
+
"hooks"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"repository": "https://github.com/leonwgc/zustand-kit",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/leonwgc/zustand-kit/issues"
|
|
15
|
+
},
|
|
16
|
+
"main": "dist/index.cjs.js",
|
|
17
|
+
"module": "dist/index.esm.js",
|
|
18
|
+
"typings": "types/index.d.ts",
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup && tsc",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"prepublishOnly": "npm run build",
|
|
26
|
+
"publish--patch": "./publish.sh patch",
|
|
27
|
+
"publish--minor": "./publish.sh minor",
|
|
28
|
+
"publish--major": "./publish.sh major"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": "^18.0.0",
|
|
32
|
+
"react-dom": "^18.0.0",
|
|
33
|
+
"zustand": "^5.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@testing-library/react": "^14.3.1",
|
|
37
|
+
"@types/node": "^25.0.3",
|
|
38
|
+
"@types/react": "^18.0.0",
|
|
39
|
+
"@types/react-dom": "^18.0.10",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
|
41
|
+
"@typescript-eslint/parser": "^5.6.0",
|
|
42
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
43
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
44
|
+
"antd": "^6.1.4",
|
|
45
|
+
"eslint": "^8.34.0",
|
|
46
|
+
"eslint-plugin-react": "^7.19.0",
|
|
47
|
+
"eslint-plugin-react-hooks": "^2.5.0",
|
|
48
|
+
"jsdom": "^23.2.0",
|
|
49
|
+
"packrs": "^1.0.1",
|
|
50
|
+
"prettier": "^2.2.1",
|
|
51
|
+
"react": "^18.2.0",
|
|
52
|
+
"react-dom": "^18.2.0",
|
|
53
|
+
"tsup": "^8.3.6",
|
|
54
|
+
"typescript": "^5.7.3",
|
|
55
|
+
"vitest": "^1.6.1",
|
|
56
|
+
"yargs": "^15.3.1",
|
|
57
|
+
"zustand": "^5.0.9"
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"dist",
|
|
61
|
+
"types"
|
|
62
|
+
]
|
|
63
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file src/index.tsx
|
|
3
|
+
* @author leon.wang
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Clear all global states (for testing purposes)
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function __clearAllStates__(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Storage type for persistence
|
|
12
|
+
*/
|
|
13
|
+
export type StorageType = 'localStorage' | 'sessionStorage' | 'none';
|
|
14
|
+
/**
|
|
15
|
+
* Options for useGlobalState
|
|
16
|
+
*/
|
|
17
|
+
export interface UseGlobalStateOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Enable persistence and specify storage type
|
|
20
|
+
* @default 'none'
|
|
21
|
+
*/
|
|
22
|
+
storage?: StorageType;
|
|
23
|
+
/**
|
|
24
|
+
* Custom storage key prefix
|
|
25
|
+
* @default 'global-state'
|
|
26
|
+
*/
|
|
27
|
+
storageKey?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Universal global state hook - supports both simple values and objects
|
|
31
|
+
* Performance optimized with selector pattern
|
|
32
|
+
*
|
|
33
|
+
* @param key - Unique key for the state
|
|
34
|
+
* @param initialState - Initial state (any type)
|
|
35
|
+
* @param options - Configuration options including persistence
|
|
36
|
+
* @returns [state, setState, resetState]
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Simple value (number, string, boolean)
|
|
40
|
+
* const [count, setCount, resetCount] = useGlobalState('counter', 0);
|
|
41
|
+
* setCount(5);
|
|
42
|
+
* setCount(prev => prev + 1);
|
|
43
|
+
*
|
|
44
|
+
* // Object state - supports partial updates
|
|
45
|
+
* const [user, setUser, resetUser] = useGlobalState('user', {
|
|
46
|
+
* name: 'John',
|
|
47
|
+
* email: 'john@example.com',
|
|
48
|
+
* });
|
|
49
|
+
* setUser({ name: 'Jane' }); // Partial update
|
|
50
|
+
*
|
|
51
|
+
* // With localStorage persistence
|
|
52
|
+
* const [settings, setSettings] = useGlobalState('settings', { theme: 'dark' }, {
|
|
53
|
+
* storage: 'localStorage'
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // With sessionStorage persistence
|
|
57
|
+
* const [tempData, setTempData] = useGlobalState('temp', { foo: 'bar' }, {
|
|
58
|
+
* storage: 'sessionStorage',
|
|
59
|
+
* storageKey: 'my-app'
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // For non-React usage, see: getGlobalState, setGlobalState, subscribeGlobalState, resetGlobalState
|
|
63
|
+
*/
|
|
64
|
+
export declare function useGlobalState<T>(key: string, initialState: T, options?: UseGlobalStateOptions): [
|
|
65
|
+
T,
|
|
66
|
+
(value: T extends Record<string, unknown> ? Partial<T> | ((prev: T) => T) : T | ((prev: T) => T)) => void,
|
|
67
|
+
() => void
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Advanced hook with custom selector for fine-grained subscriptions
|
|
71
|
+
* Only re-renders when selected value changes
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // Only subscribe to user name, not the whole user object
|
|
75
|
+
* const userName = useGlobalSelector('user', (state) => state.name);
|
|
76
|
+
*
|
|
77
|
+
* // Multiple values
|
|
78
|
+
* const { name, email } = useGlobalSelector(
|
|
79
|
+
* 'user',
|
|
80
|
+
* (state) => ({ name: state.name, email: state.email })
|
|
81
|
+
* );
|
|
82
|
+
*/
|
|
83
|
+
export declare function useGlobalSelector<T, R>(key: string, selector: (state: T) => R): R;
|
|
84
|
+
/**
|
|
85
|
+
* Hook to get setter function only (doesn't subscribe to state changes)
|
|
86
|
+
* Useful when you only need to update state without reading it
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* const setCount = useGlobalSetter<number>('counter');
|
|
90
|
+
* setCount(5);
|
|
91
|
+
* setCount(prev => prev + 1);
|
|
92
|
+
*/
|
|
93
|
+
export declare function useGlobalSetter<T>(key: string): (value: T extends Record<string, unknown> ? Partial<T> | ((prev: T) => T) : T | ((prev: T) => T)) => void;
|
|
94
|
+
/**
|
|
95
|
+
* Get global state value (for non-React usage)
|
|
96
|
+
* @example
|
|
97
|
+
* const count = getGlobalState<number>('counter');
|
|
98
|
+
*/
|
|
99
|
+
export declare function getGlobalState<T>(key: string): T | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* Set global state value (for non-React usage)
|
|
102
|
+
* @example
|
|
103
|
+
* setGlobalState('counter', 5);
|
|
104
|
+
* setGlobalState('counter', prev => prev + 1);
|
|
105
|
+
* setGlobalState('user', { name: 'Jane' }); // Partial update for objects
|
|
106
|
+
*/
|
|
107
|
+
export declare function setGlobalState<T>(key: string, value: T extends Record<string, unknown> ? Partial<T> | ((prev: T) => T) : T | ((prev: T) => T)): void;
|
|
108
|
+
/**
|
|
109
|
+
* Subscribe to global state changes (for non-React usage)
|
|
110
|
+
* Returns unsubscribe function
|
|
111
|
+
* @example
|
|
112
|
+
* const unsubscribe = subscribeGlobalState('counter', (newValue, prevValue) => {
|
|
113
|
+
* console.log('Counter changed from', prevValue, 'to', newValue);
|
|
114
|
+
* });
|
|
115
|
+
* // Later: unsubscribe();
|
|
116
|
+
*/
|
|
117
|
+
export declare function subscribeGlobalState<T>(key: string, callback: (newValue: T, prevValue: T) => void): () => void;
|
|
118
|
+
/**
|
|
119
|
+
* Reset global state to initial value (for non-React usage)
|
|
120
|
+
* @example
|
|
121
|
+
* resetGlobalState('counter');
|
|
122
|
+
*/
|
|
123
|
+
export declare function resetGlobalState(key: string): void;
|
|
124
|
+
export default useGlobalState;
|