valtio-define 1.3.3 → 1.4.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 +7 -2
- package/dist/index.mjs +152 -1
- package/dist/plugins/index.mjs +4 -1
- package/dist/plugins/persist/index.mjs +58 -1
- package/dist/plugins/persist/types.d.mts +2 -2
- package/dist/plugins/persist/types.mjs +1 -1
- package/dist/plugins/signal/index.mjs +15 -1
- package/dist/plugins/signal/jsx-dev-runtime.mjs +3 -1
- package/dist/plugins/signal/jsx-runtime.mjs +3 -1
- package/dist/plugins/signal/types.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,7 +124,7 @@ Save and restore your store state using the `persist` plugin.
|
|
|
124
124
|
|
|
125
125
|
### Manual Hydration (SSR Friendly)
|
|
126
126
|
|
|
127
|
-
To avoid hydration mismatches during Server-Side Rendering, disable automatic hydration and
|
|
127
|
+
To avoid hydration mismatches during Server-Side Rendering, disable automatic hydration and rehydrate it in a `useEffect`.
|
|
128
128
|
|
|
129
129
|
```tsx
|
|
130
130
|
// Register with hydrate disabled
|
|
@@ -132,7 +132,7 @@ store.use(persist({ hydrate: false }))
|
|
|
132
132
|
|
|
133
133
|
// In your Client Entry / App Root
|
|
134
134
|
useEffect(() => {
|
|
135
|
-
store.$persist.
|
|
135
|
+
store.$persist.rehydrate()
|
|
136
136
|
}, [])
|
|
137
137
|
```
|
|
138
138
|
|
|
@@ -224,6 +224,11 @@ valtio.use(myPlugin())
|
|
|
224
224
|
// Local
|
|
225
225
|
const store = defineStore({ /* ... */ })
|
|
226
226
|
store.use(myPlugin())
|
|
227
|
+
|
|
228
|
+
// Local options
|
|
229
|
+
const store = defineStore({
|
|
230
|
+
use: [myPlugin()],
|
|
231
|
+
})
|
|
227
232
|
```
|
|
228
233
|
|
|
229
234
|
### Creating a Custom Plugin
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1,152 @@
|
|
|
1
|
-
import{proxy
|
|
1
|
+
import { proxy, useSnapshot } from "valtio";
|
|
2
|
+
import { batch } from "valtio-reactive";
|
|
3
|
+
import { subscribeKey } from "valtio/utils";
|
|
4
|
+
import { proxy as proxy$1, ref, subscribe as subscribe$1 } from "valtio/vanilla";
|
|
5
|
+
|
|
6
|
+
//#region src/plugin.ts
|
|
7
|
+
const plugins = proxy([]);
|
|
8
|
+
function use(plugin) {
|
|
9
|
+
plugins.push(plugin);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/define.ts
|
|
14
|
+
/**
|
|
15
|
+
* @description Define a store
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const store = defineStore({
|
|
19
|
+
* state: () => ({ count: 0 }),
|
|
20
|
+
* actions: {
|
|
21
|
+
* increment() {
|
|
22
|
+
* this.count++
|
|
23
|
+
* },
|
|
24
|
+
* },
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* store.increment()
|
|
28
|
+
* console.log(store.$state.count) // 1
|
|
29
|
+
*
|
|
30
|
+
* function Component() {
|
|
31
|
+
* const store = useStore(store)
|
|
32
|
+
* return (
|
|
33
|
+
* <div>
|
|
34
|
+
* <button onClick={store.increment}>Increment</button>
|
|
35
|
+
* <div>{store.count}</div>
|
|
36
|
+
* </div>
|
|
37
|
+
* )
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
function defineStore(options) {
|
|
43
|
+
const state = typeof options.state === "function" ? options.state() : options.state;
|
|
44
|
+
const getters = options.getters || {};
|
|
45
|
+
const actions = options.actions || {};
|
|
46
|
+
const $state = proxy$1(state);
|
|
47
|
+
const $actions = {};
|
|
48
|
+
const $getters = proxy$1({});
|
|
49
|
+
const $plugins = /* @__PURE__ */ new WeakSet();
|
|
50
|
+
let unsub;
|
|
51
|
+
for (const key of Object.keys(getters)) {
|
|
52
|
+
defineProperty($state, key, getters[key].bind($state), { enumerable: false });
|
|
53
|
+
defineProperty($getters, key, () => $state[key]);
|
|
54
|
+
}
|
|
55
|
+
for (const key of Object.keys(actions)) {
|
|
56
|
+
$actions[key] = ref(actions[key].bind($state));
|
|
57
|
+
defineProperty($state, key, () => $actions[key], { enumerable: false });
|
|
58
|
+
}
|
|
59
|
+
function $subscribe(listener) {
|
|
60
|
+
return subscribe$1($state, (ops) => listener($state, ops));
|
|
61
|
+
}
|
|
62
|
+
function $subscribeKey(key, listener) {
|
|
63
|
+
return subscribeKey($state, key, (value) => listener(value), true);
|
|
64
|
+
}
|
|
65
|
+
function $patch(patch) {
|
|
66
|
+
typeof patch === "function" ? batch(() => patch($state)) : Object.assign($state, patch);
|
|
67
|
+
}
|
|
68
|
+
function $dispose() {
|
|
69
|
+
unsub?.();
|
|
70
|
+
}
|
|
71
|
+
function use(plugin) {
|
|
72
|
+
apply(plugin);
|
|
73
|
+
}
|
|
74
|
+
const base = {
|
|
75
|
+
$subscribe,
|
|
76
|
+
$subscribeKey,
|
|
77
|
+
$patch,
|
|
78
|
+
$state,
|
|
79
|
+
$actions,
|
|
80
|
+
$getters,
|
|
81
|
+
$dispose,
|
|
82
|
+
use
|
|
83
|
+
};
|
|
84
|
+
const store = new Proxy(base, {
|
|
85
|
+
get(target, prop) {
|
|
86
|
+
if (prop in $actions) return $actions[prop];
|
|
87
|
+
if (prop in target) return target[prop];
|
|
88
|
+
return $state[prop];
|
|
89
|
+
},
|
|
90
|
+
has(target, prop) {
|
|
91
|
+
return prop in target || prop in $actions || prop in $state;
|
|
92
|
+
},
|
|
93
|
+
set(target, prop, value) {
|
|
94
|
+
prop in $state ? $state[prop] = value : target[prop] = value;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
function apply(plugin) {
|
|
99
|
+
if ($plugins.has(plugin)) return;
|
|
100
|
+
$plugins.add(plugin);
|
|
101
|
+
plugin({
|
|
102
|
+
store,
|
|
103
|
+
options
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
for (const plugin of plugins) apply(plugin);
|
|
107
|
+
unsub = subscribe$1(plugins, () => {
|
|
108
|
+
for (const plugin of plugins) apply(plugin);
|
|
109
|
+
});
|
|
110
|
+
return store;
|
|
111
|
+
}
|
|
112
|
+
function defineProperty(target, prop, getter, descriptor) {
|
|
113
|
+
Object.defineProperty(target, prop, {
|
|
114
|
+
get: getter,
|
|
115
|
+
enumerable: true,
|
|
116
|
+
...descriptor
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/hooks.ts
|
|
122
|
+
function useStore(store, options) {
|
|
123
|
+
return useSnapshot(store.$state, options);
|
|
124
|
+
}
|
|
125
|
+
function useGetters(store, options) {
|
|
126
|
+
return useSnapshot(store.$getters, options);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/utils.ts
|
|
131
|
+
function storeToState(store, key, options) {
|
|
132
|
+
const state = useStore(store, options);
|
|
133
|
+
function set(value) {
|
|
134
|
+
if (typeof value === "function") store.$patch((state) => {
|
|
135
|
+
state[key] = value(state[key]);
|
|
136
|
+
});
|
|
137
|
+
else store.$patch((state) => {
|
|
138
|
+
state[key] = value;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return [state[key], set];
|
|
142
|
+
}
|
|
143
|
+
function storeToStates(store, options) {
|
|
144
|
+
return Object.fromEntries(Object.keys(store.$state).map((key) => [key, storeToState(store, key, options)]));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//#endregion
|
|
148
|
+
//#region src/index.ts
|
|
149
|
+
const defaultExport = { use };
|
|
150
|
+
|
|
151
|
+
//#endregion
|
|
152
|
+
export { defaultExport as default, defineStore, plugins, storeToState, storeToStates, use, useGetters, useStore };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1 +1,58 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { subscribe } from "valtio";
|
|
2
|
+
import { get, set } from "@hairy/utils";
|
|
3
|
+
import { destr } from "destr";
|
|
4
|
+
import { generateStructureId } from "structure-id";
|
|
5
|
+
|
|
6
|
+
//#region src/plugins/persist/index.ts
|
|
7
|
+
function persist({ hydrate = true } = {}) {
|
|
8
|
+
return (context) => {
|
|
9
|
+
const { persist, getters } = context.options;
|
|
10
|
+
const { $state } = context.store;
|
|
11
|
+
context.store.$persist?.dehydrate?.();
|
|
12
|
+
if (!persist) return;
|
|
13
|
+
const getterKeys = new Set(Object.keys(getters || {}));
|
|
14
|
+
const options = persist === true ? {} : persist;
|
|
15
|
+
const key = options.key || generateStructureId($state);
|
|
16
|
+
const storage = options.storage ?? (typeof localStorage !== "undefined" ? localStorage : void 0);
|
|
17
|
+
if (!storage?.getItem || !storage?.setItem) return;
|
|
18
|
+
const meta = context.store.$persist?.meta ?? {
|
|
19
|
+
mounted: false,
|
|
20
|
+
hydrated: false
|
|
21
|
+
};
|
|
22
|
+
function initialize(value) {
|
|
23
|
+
const data = destr(value);
|
|
24
|
+
if (data && typeof data === "object") {
|
|
25
|
+
for (const key of Object.keys(data)) getterKeys.has(key) && delete data[key];
|
|
26
|
+
Object.assign($state, data);
|
|
27
|
+
}
|
|
28
|
+
meta.hydrated = true;
|
|
29
|
+
}
|
|
30
|
+
function rehydrate() {
|
|
31
|
+
meta.mounted = true;
|
|
32
|
+
const value = storage.getItem(key);
|
|
33
|
+
value instanceof Promise ? value.then(initialize) : initialize(value);
|
|
34
|
+
}
|
|
35
|
+
function dehydrate() {
|
|
36
|
+
meta.unsubscribe?.();
|
|
37
|
+
meta.unsubscribe = void 0;
|
|
38
|
+
}
|
|
39
|
+
function watch() {
|
|
40
|
+
dehydrate();
|
|
41
|
+
meta.unsubscribe = subscribe($state, () => {
|
|
42
|
+
if (!meta.hydrated) return;
|
|
43
|
+
const statePaths = (options.paths || Object.keys($state)).filter((p) => !getterKeys.has(p)).reduce((acc, p) => set(acc, p, get($state, p)), {});
|
|
44
|
+
storage.setItem(key, JSON.stringify(statePaths));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
context.store.$persist = {
|
|
48
|
+
rehydrate,
|
|
49
|
+
dehydrate,
|
|
50
|
+
meta
|
|
51
|
+
};
|
|
52
|
+
hydrate && !meta.mounted && rehydrate();
|
|
53
|
+
watch();
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { persist };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{};
|
|
1
|
+
export { };
|
|
@@ -1 +1,15 @@
|
|
|
1
|
-
import{$
|
|
1
|
+
import { $ } from "valtio-signal";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/signal/index.ts
|
|
4
|
+
function signal() {
|
|
5
|
+
return (context) => {
|
|
6
|
+
function $signal(fn) {
|
|
7
|
+
const attached = $(context.store.$state);
|
|
8
|
+
return fn ? fn(attached) : attached;
|
|
9
|
+
}
|
|
10
|
+
context.store.$signal = $signal;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { signal };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{};
|
|
1
|
+
export { };
|
package/package.json
CHANGED