@t8/react-store 1.2.4 → 1.2.5

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/dist/index.cjs ADDED
@@ -0,0 +1,60 @@
1
+ let __t8_store = require("@t8/store");
2
+ let react = require("react");
3
+
4
+ //#region src/useStore.ts
5
+ /**
6
+ * Returns the state value of `store` passed as the parameter and
7
+ * a function to update the store state value.
8
+ *
9
+ * @example
10
+ * ```js
11
+ * let [value, setValue] = useStore(store);
12
+ * ```
13
+ *
14
+ * The optional second parameter `shouldUpdate` controls whether
15
+ * the component using this hook should be updated in response to
16
+ * the store updates, which is set to `true` by default.
17
+ *
18
+ * `shouldUpdate` can be set to `false` to prevent subscription
19
+ * to the store updates. Use case: if the component only requires
20
+ * the store state setter but not the store state value, the
21
+ * component may not need to respond to the store updates at all:
22
+ *
23
+ * @example
24
+ * ```js
25
+ * let [, setValue] = useStore(store, false);
26
+ * ```
27
+ *
28
+ * `shouldUpdate` can also be a function `(nextState, prevState) => boolean`
29
+ * to make the component respond only to specific store state changes,
30
+ * when this function returns `true`.
31
+ */
32
+ function useStore(store, shouldUpdate = true) {
33
+ if (!(0, __t8_store.isStore)(store)) throw new Error("'store' is not an instance of Store");
34
+ let [, setRevision] = (0, react.useState)(-1);
35
+ let state = store.getState();
36
+ let setState = (0, react.useMemo)(() => store.setState.bind(store), [store]);
37
+ let initialStoreRevision = (0, react.useRef)(store.revision);
38
+ (0, react.useEffect)(() => {
39
+ if ((0, __t8_store.isPersistentStore)(store)) store.syncOnce();
40
+ if (!shouldUpdate) return;
41
+ let unsubscribe = store.onUpdate((nextState, prevState) => {
42
+ if (typeof shouldUpdate !== "function" || shouldUpdate(nextState, prevState)) setRevision(Math.random());
43
+ });
44
+ if (store.revision !== initialStoreRevision.current) setRevision(Math.random());
45
+ return () => {
46
+ unsubscribe();
47
+ initialStoreRevision.current = store.revision;
48
+ };
49
+ }, [store, shouldUpdate]);
50
+ return [state, setState];
51
+ }
52
+
53
+ //#endregion
54
+ exports.useStore = useStore;
55
+ Object.keys(__t8_store).forEach(function (k) {
56
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
57
+ enumerable: true,
58
+ get: function () { return __t8_store[k]; }
59
+ });
60
+ });
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import type { Store } from "@t8/store";
1
+ import { Store } from "@t8/store";
2
+ export * from "@t8/store";
2
3
 
3
- export type SetStoreState<T> = Store<T>["setState"];
4
- export type ShouldUpdateCallback<T> = (nextState: T, prevState: T) => boolean;
5
- export type ShouldUpdate<T> = boolean | ShouldUpdateCallback<T>;
4
+ type SetStoreState<T> = Store<T>["setState"];
5
+ type ShouldUpdateCallback<T> = (nextState: T, prevState: T) => boolean;
6
+ type ShouldUpdate<T> = boolean | ShouldUpdateCallback<T>;
6
7
  /**
7
8
  * Returns the state value of `store` passed as the parameter and
8
9
  * a function to update the store state value.
@@ -30,10 +31,6 @@ export type ShouldUpdate<T> = boolean | ShouldUpdateCallback<T>;
30
31
  * to make the component respond only to specific store state changes,
31
32
  * when this function returns `true`.
32
33
  */
33
- export declare function useStore<T>(store: Store<T>, shouldUpdate?: ShouldUpdate<T>): [
34
- T,
35
- SetStoreState<T>
36
- ];
37
- export * from "@t8/store";
34
+ declare function useStore<T>(store: Store<T>, shouldUpdate?: ShouldUpdate<T>): [T, SetStoreState<T>];
38
35
 
39
- export {};
36
+ export { SetStoreState, ShouldUpdate, ShouldUpdateCallback, useStore };
package/dist/index.mjs ADDED
@@ -0,0 +1,56 @@
1
+ import { isPersistentStore, isStore } from "@t8/store";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
+
4
+ export * from "@t8/store"
5
+
6
+ //#region src/useStore.ts
7
+ /**
8
+ * Returns the state value of `store` passed as the parameter and
9
+ * a function to update the store state value.
10
+ *
11
+ * @example
12
+ * ```js
13
+ * let [value, setValue] = useStore(store);
14
+ * ```
15
+ *
16
+ * The optional second parameter `shouldUpdate` controls whether
17
+ * the component using this hook should be updated in response to
18
+ * the store updates, which is set to `true` by default.
19
+ *
20
+ * `shouldUpdate` can be set to `false` to prevent subscription
21
+ * to the store updates. Use case: if the component only requires
22
+ * the store state setter but not the store state value, the
23
+ * component may not need to respond to the store updates at all:
24
+ *
25
+ * @example
26
+ * ```js
27
+ * let [, setValue] = useStore(store, false);
28
+ * ```
29
+ *
30
+ * `shouldUpdate` can also be a function `(nextState, prevState) => boolean`
31
+ * to make the component respond only to specific store state changes,
32
+ * when this function returns `true`.
33
+ */
34
+ function useStore(store, shouldUpdate = true) {
35
+ if (!isStore(store)) throw new Error("'store' is not an instance of Store");
36
+ let [, setRevision] = useState(-1);
37
+ let state = store.getState();
38
+ let setState = useMemo(() => store.setState.bind(store), [store]);
39
+ let initialStoreRevision = useRef(store.revision);
40
+ useEffect(() => {
41
+ if (isPersistentStore(store)) store.syncOnce();
42
+ if (!shouldUpdate) return;
43
+ let unsubscribe = store.onUpdate((nextState, prevState) => {
44
+ if (typeof shouldUpdate !== "function" || shouldUpdate(nextState, prevState)) setRevision(Math.random());
45
+ });
46
+ if (store.revision !== initialStoreRevision.current) setRevision(Math.random());
47
+ return () => {
48
+ unsubscribe();
49
+ initialStoreRevision.current = store.revision;
50
+ };
51
+ }, [store, shouldUpdate]);
52
+ return [state, setState];
53
+ }
54
+
55
+ //#endregion
56
+ export { useStore };
package/package.json CHANGED
@@ -1,16 +1,15 @@
1
1
  {
2
2
  "name": "@t8/react-store",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "Small React app state management lib aligned with React's state pattern, condensed to the essentials",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
7
8
  "type": "module",
8
9
  "scripts": {
9
- "clean": "node -e \"require('node:fs').rmSync('dist', { force: true, recursive: true });\"",
10
- "compile": "npx esbuild index.ts --bundle --outdir=dist --platform=neutral --external:react",
11
10
  "demo": "npx @t8/serve 3000 * tests/counter -b src/index.tsx",
12
- "preversion": "npx npm-run-all clean shape compile test",
13
- "shape": "npx codeshape --typecheck --emit-types",
11
+ "preversion": "npx npm-run-all shape test",
12
+ "shape": "npx codeshape",
14
13
  "test": "npx playwright test --project=chromium",
15
14
  "tic-tac-toe": "npx @t8/serve 3000 * tests/tic-tac-toe -b src/index.tsx"
16
15
  },
@@ -33,7 +32,7 @@
33
32
  },
34
33
  "devDependencies": {
35
34
  "@playwright/test": "^1.56.0",
36
- "@t8/serve": "^0.1.36",
35
+ "@t8/serve": "^0.1.37",
37
36
  "@types/node": "^24.5.2",
38
37
  "@types/react": "^19.2.7",
39
38
  "@types/react-dom": "^19.2.3",
@@ -41,6 +40,6 @@
41
40
  "react-dom": "^19.2.1"
42
41
  },
43
42
  "dependencies": {
44
- "@t8/store": "^1.3.5"
43
+ "@t8/store": "^1.3.7"
45
44
  }
46
45
  }
package/dist/index.js DELETED
@@ -1,152 +0,0 @@
1
- // node_modules/@t8/store/src/isStore.ts
2
- function isStore(x) {
3
- return x !== null && typeof x === "object" && "onUpdate" in x && typeof x.onUpdate === "function" && "getState" in x && typeof x.getState === "function" && "setState" in x && typeof x.setState === "function";
4
- }
5
-
6
- // node_modules/@t8/store/src/isPersistentStore.ts
7
- function isPersistentStore(x) {
8
- return isStore(x) && "sync" in x;
9
- }
10
-
11
- // node_modules/@t8/store/src/Store.ts
12
- var Store = class {
13
- state;
14
- callbacks = /* @__PURE__ */ new Set();
15
- revision = -1;
16
- constructor(data) {
17
- this.state = data;
18
- }
19
- onUpdate(callback) {
20
- this.callbacks.add(callback);
21
- return () => {
22
- this.callbacks.delete(callback);
23
- };
24
- }
25
- getState() {
26
- return this.state;
27
- }
28
- setState(update) {
29
- let prevState = this.state;
30
- let nextState = update instanceof Function ? update(this.state) : update;
31
- this.state = nextState;
32
- this.revision = Math.random();
33
- for (let callback of this.callbacks) callback(nextState, prevState);
34
- }
35
- };
36
-
37
- // node_modules/@t8/store/src/PersistentStore.ts
38
- function getStorage(session = false) {
39
- if (typeof window === "undefined") return;
40
- return session ? sessionStorage : localStorage;
41
- }
42
- var PersistentStore = class extends Store {
43
- storageKey;
44
- options;
45
- synced = false;
46
- /**
47
- * Creates an instance of the container for data persistent across page
48
- * reloads.
49
- *
50
- * The store data is saved to and restored from the given `storageKey`
51
- * either of `localStorage` (by default) or `sessionStorage` (if `options.session`
52
- * is set to `true`). Interaction with the browser storage is skipped in
53
- * non-browser environments.
54
- *
55
- * @example
56
- * ```js
57
- * let counterStore = new PersistentStore(0, "counter");
58
- * ```
59
- *
60
- * The way data gets saved to and restored from a browser storage entry
61
- * (including filtering out certain data or otherwise rearranging the
62
- * saved data) can be overridden by setting `options.serialize` and
63
- * `options.deserialize`. By default, they are `JSON.stringify()` and
64
- * `JSON.parse()`.
65
- */
66
- constructor(data, storageKey, options) {
67
- super(data);
68
- this.storageKey = storageKey;
69
- this.options = {
70
- session: false,
71
- serialize: (data2) => JSON.stringify(data2),
72
- deserialize: (content) => JSON.parse(content),
73
- ...options
74
- };
75
- this.onUpdate(() => {
76
- if (this.synced) this.save();
77
- });
78
- }
79
- /**
80
- * Saves the store state value to the browser storage.
81
- */
82
- save() {
83
- let storage = getStorage(this.options?.session);
84
- let serialize = this.options?.serialize;
85
- if (this.synced && storage && typeof serialize === "function") {
86
- try {
87
- storage.setItem(this.storageKey, serialize(this.state));
88
- } catch {
89
- }
90
- }
91
- }
92
- /**
93
- * Signals the store to read the state value from the browser storage.
94
- */
95
- sync() {
96
- let storage = getStorage(this.options?.session);
97
- let deserialize = this.options?.deserialize;
98
- let serializedState = null;
99
- if (storage && typeof deserialize === "function") {
100
- try {
101
- serializedState = storage.getItem(this.storageKey);
102
- if (serializedState !== null)
103
- this.setState(deserialize(serializedState, this.state));
104
- } catch {
105
- }
106
- }
107
- if (!this.synced) {
108
- this.synced = true;
109
- if (serializedState === null) this.save();
110
- }
111
- }
112
- /**
113
- * Signals the store to read the state value from the browser storage once,
114
- * disregarding subsequest `syncOnce()` calls.
115
- */
116
- syncOnce() {
117
- if (!this.synced) this.sync();
118
- }
119
- };
120
-
121
- // src/useStore.ts
122
- import { useEffect, useMemo, useRef, useState } from "react";
123
- function useStore(store, shouldUpdate = true) {
124
- if (!isStore(store))
125
- throw new Error("'store' is not an instance of Store");
126
- let [, setRevision] = useState(-1);
127
- let state = store.getState();
128
- let setState = useMemo(() => store.setState.bind(store), [store]);
129
- let initialStoreRevision = useRef(store.revision);
130
- useEffect(() => {
131
- if (isPersistentStore(store)) store.syncOnce();
132
- if (!shouldUpdate) return;
133
- let unsubscribe = store.onUpdate((nextState, prevState) => {
134
- if (typeof shouldUpdate !== "function" || shouldUpdate(nextState, prevState))
135
- setRevision(Math.random());
136
- });
137
- if (store.revision !== initialStoreRevision.current)
138
- setRevision(Math.random());
139
- return () => {
140
- unsubscribe();
141
- initialStoreRevision.current = store.revision;
142
- };
143
- }, [store, shouldUpdate]);
144
- return [state, setState];
145
- }
146
- export {
147
- PersistentStore,
148
- Store,
149
- isPersistentStore,
150
- isStore,
151
- useStore
152
- };
@@ -1,4 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "include": ["./index.ts", "./src"]
4
- }