@t8/react-pending 1.0.28 → 1.0.29

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,118 @@
1
+ let react = require("react");
2
+ let __t8_react_store = require("@t8/react-store");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+
5
+ //#region src/PendingStateContext.ts
6
+ const PendingStateContext = (0, react.createContext)(/* @__PURE__ */ new Map());
7
+
8
+ //#endregion
9
+ //#region src/PendingStateProvider.tsx
10
+ const PendingStateProvider = ({ value, children }) => {
11
+ let defaultValueRef = (0, react.useRef)(null);
12
+ let resolvedValue = (0, react.useMemo)(() => {
13
+ if (value instanceof Map) return value;
14
+ if (typeof value === "object" && value !== null) return new Map(Object.entries(value).map(([key, state]) => [key, new __t8_react_store.Store(state)]));
15
+ if (defaultValueRef.current === null) defaultValueRef.current = /* @__PURE__ */ new Map();
16
+ return defaultValueRef.current;
17
+ }, [value]);
18
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PendingStateContext.Provider, {
19
+ value: resolvedValue,
20
+ children
21
+ });
22
+ };
23
+
24
+ //#endregion
25
+ //#region src/usePendingState.ts
26
+ function createState(initialized = false, complete = false, error) {
27
+ return {
28
+ initialized,
29
+ complete,
30
+ error,
31
+ time: Date.now()
32
+ };
33
+ }
34
+ /**
35
+ * Returns an instance of an action's state and the functions to update it.
36
+ *
37
+ * @param store - A unique store key or a store. Providing a store
38
+ * key or a shared store allows to share the state across multiple
39
+ * components.
40
+ *
41
+ * @returns `[state, withState, setState]`, where
42
+ * - `state` is the current value of the action's state;
43
+ * - `withState(action, options?)` reads and tracks the `actions`'s state
44
+ * which is exposed as `state` listed above;
45
+ * - `setState(update)` can replace the current `state` value directly with
46
+ * an another state value.
47
+ */
48
+ function usePendingState(store) {
49
+ let storeMap = (0, react.useContext)(PendingStateContext);
50
+ let storeRef = (0, react.useRef)(null);
51
+ let [storeItemInited, setStoreItemInited] = (0, react.useState)(false);
52
+ let [state, setState] = (0, __t8_react_store.useStore)((0, react.useMemo)(() => {
53
+ if ((0, __t8_react_store.isStore)(store)) return store;
54
+ if (typeof store === "string") {
55
+ let storeItem = storeMap.get(store);
56
+ if (!storeItem) {
57
+ storeItem = new __t8_react_store.Store(createState());
58
+ storeMap.set(store, storeItem);
59
+ if (!storeItemInited) setStoreItemInited(true);
60
+ }
61
+ return storeItem;
62
+ }
63
+ if (!storeRef.current) storeRef.current = new __t8_react_store.Store(createState());
64
+ return storeRef.current;
65
+ }, [
66
+ store,
67
+ storeMap,
68
+ storeItemInited
69
+ ]));
70
+ return [
71
+ state,
72
+ (0, react.useCallback)((value, options) => {
73
+ if (value instanceof Promise) {
74
+ let delayedPending = null;
75
+ if (!options?.silent) {
76
+ let delay = options?.delay;
77
+ if (delay === void 0) setState((prevState) => ({
78
+ ...prevState,
79
+ ...createState(true, false)
80
+ }));
81
+ else delayedPending = setTimeout(() => {
82
+ setState((prevState) => ({
83
+ ...prevState,
84
+ ...createState(true, false)
85
+ }));
86
+ delayedPending = null;
87
+ }, delay);
88
+ }
89
+ return value.then((resolvedValue) => {
90
+ if (delayedPending !== null) clearTimeout(delayedPending);
91
+ setState((prevState) => ({
92
+ ...prevState,
93
+ ...createState(true, true)
94
+ }));
95
+ return resolvedValue;
96
+ }).catch((error) => {
97
+ if (delayedPending !== null) clearTimeout(delayedPending);
98
+ setState((prevState) => ({
99
+ ...prevState,
100
+ ...createState(true, true, error)
101
+ }));
102
+ if (options?.throws) throw error;
103
+ });
104
+ }
105
+ setState((prevState) => ({
106
+ ...prevState,
107
+ ...createState(true, true)
108
+ }));
109
+ return value;
110
+ }, [setState]),
111
+ setState
112
+ ];
113
+ }
114
+
115
+ //#endregion
116
+ exports.PendingStateContext = PendingStateContext;
117
+ exports.PendingStateProvider = PendingStateProvider;
118
+ exports.usePendingState = usePendingState;
package/dist/index.d.ts CHANGED
@@ -1,19 +1,27 @@
1
- import type { SetStoreState, Store } from "@t8/react-store";
2
- import type { ReactNode } from "react";
1
+ import * as react0 from "react";
2
+ import { ReactNode } from "react";
3
+ import { SetStoreState, Store } from "@t8/react-store";
4
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
5
 
4
- export type PendingState = {
6
+ type PendingState = {
5
7
  initialized?: boolean | undefined;
6
8
  complete?: boolean | undefined;
7
9
  time?: number | undefined;
8
10
  error?: unknown;
9
11
  };
10
- export declare const PendingStateContext: import("react").Context<Map<string, Store<PendingState>>>;
11
- export type PendingStateProviderProps = {
12
+
13
+ declare const PendingStateContext: react0.Context<Map<string, Store<PendingState>>>;
14
+
15
+ type PendingStateProviderProps = {
12
16
  value?: Record<string, PendingState> | Map<string, Store<PendingState>> | null | undefined;
13
17
  children?: ReactNode;
14
18
  };
15
- export declare const PendingStateProvider: ({ value, children, }: PendingStateProviderProps) => import("react/jsx-runtime").JSX.Element;
16
- export type WithStateOptions = {
19
+ declare const PendingStateProvider: ({
20
+ value,
21
+ children
22
+ }: PendingStateProviderProps) => react_jsx_runtime0.JSX.Element;
23
+
24
+ type WithStateOptions = {
17
25
  /**
18
26
  * Whether to track the action state silently (e.g. with a background
19
27
  * action or an optimistic update).
@@ -50,10 +58,6 @@ export type WithStateOptions = {
50
58
  * - `setState(update)` can replace the current `state` value directly with
51
59
  * an another state value.
52
60
  */
53
- export declare function usePendingState(store?: string | Store<PendingState> | null): [
54
- PendingState,
55
- <T>(value: T) => T,
56
- SetStoreState<PendingState>
57
- ];
61
+ declare function usePendingState(store?: string | Store<PendingState> | null): [PendingState, <T>(value: T) => T, SetStoreState<PendingState>];
58
62
 
59
- export {};
63
+ export { PendingState, PendingStateContext, PendingStateProvider, PendingStateProviderProps, WithStateOptions, usePendingState };
package/dist/index.mjs ADDED
@@ -0,0 +1,116 @@
1
+ import { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
2
+ import { Store, isStore, useStore } from "@t8/react-store";
3
+ import { jsx } from "react/jsx-runtime";
4
+
5
+ //#region src/PendingStateContext.ts
6
+ const PendingStateContext = createContext(/* @__PURE__ */ new Map());
7
+
8
+ //#endregion
9
+ //#region src/PendingStateProvider.tsx
10
+ const PendingStateProvider = ({ value, children }) => {
11
+ let defaultValueRef = useRef(null);
12
+ let resolvedValue = useMemo(() => {
13
+ if (value instanceof Map) return value;
14
+ if (typeof value === "object" && value !== null) return new Map(Object.entries(value).map(([key, state]) => [key, new Store(state)]));
15
+ if (defaultValueRef.current === null) defaultValueRef.current = /* @__PURE__ */ new Map();
16
+ return defaultValueRef.current;
17
+ }, [value]);
18
+ return /* @__PURE__ */ jsx(PendingStateContext.Provider, {
19
+ value: resolvedValue,
20
+ children
21
+ });
22
+ };
23
+
24
+ //#endregion
25
+ //#region src/usePendingState.ts
26
+ function createState(initialized = false, complete = false, error) {
27
+ return {
28
+ initialized,
29
+ complete,
30
+ error,
31
+ time: Date.now()
32
+ };
33
+ }
34
+ /**
35
+ * Returns an instance of an action's state and the functions to update it.
36
+ *
37
+ * @param store - A unique store key or a store. Providing a store
38
+ * key or a shared store allows to share the state across multiple
39
+ * components.
40
+ *
41
+ * @returns `[state, withState, setState]`, where
42
+ * - `state` is the current value of the action's state;
43
+ * - `withState(action, options?)` reads and tracks the `actions`'s state
44
+ * which is exposed as `state` listed above;
45
+ * - `setState(update)` can replace the current `state` value directly with
46
+ * an another state value.
47
+ */
48
+ function usePendingState(store) {
49
+ let storeMap = useContext(PendingStateContext);
50
+ let storeRef = useRef(null);
51
+ let [storeItemInited, setStoreItemInited] = useState(false);
52
+ let [state, setState] = useStore(useMemo(() => {
53
+ if (isStore(store)) return store;
54
+ if (typeof store === "string") {
55
+ let storeItem = storeMap.get(store);
56
+ if (!storeItem) {
57
+ storeItem = new Store(createState());
58
+ storeMap.set(store, storeItem);
59
+ if (!storeItemInited) setStoreItemInited(true);
60
+ }
61
+ return storeItem;
62
+ }
63
+ if (!storeRef.current) storeRef.current = new Store(createState());
64
+ return storeRef.current;
65
+ }, [
66
+ store,
67
+ storeMap,
68
+ storeItemInited
69
+ ]));
70
+ return [
71
+ state,
72
+ useCallback((value, options) => {
73
+ if (value instanceof Promise) {
74
+ let delayedPending = null;
75
+ if (!options?.silent) {
76
+ let delay = options?.delay;
77
+ if (delay === void 0) setState((prevState) => ({
78
+ ...prevState,
79
+ ...createState(true, false)
80
+ }));
81
+ else delayedPending = setTimeout(() => {
82
+ setState((prevState) => ({
83
+ ...prevState,
84
+ ...createState(true, false)
85
+ }));
86
+ delayedPending = null;
87
+ }, delay);
88
+ }
89
+ return value.then((resolvedValue) => {
90
+ if (delayedPending !== null) clearTimeout(delayedPending);
91
+ setState((prevState) => ({
92
+ ...prevState,
93
+ ...createState(true, true)
94
+ }));
95
+ return resolvedValue;
96
+ }).catch((error) => {
97
+ if (delayedPending !== null) clearTimeout(delayedPending);
98
+ setState((prevState) => ({
99
+ ...prevState,
100
+ ...createState(true, true, error)
101
+ }));
102
+ if (options?.throws) throw error;
103
+ });
104
+ }
105
+ setState((prevState) => ({
106
+ ...prevState,
107
+ ...createState(true, true)
108
+ }));
109
+ return value;
110
+ }, [setState]),
111
+ setState
112
+ ];
113
+ }
114
+
115
+ //#endregion
116
+ export { PendingStateContext, PendingStateProvider, usePendingState };
package/package.json CHANGED
@@ -1,16 +1,15 @@
1
1
  {
2
2
  "name": "@t8/react-pending",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "description": "Concise async action state tracking for React apps",
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/async_status -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
  },
16
15
  "author": "axtk",
@@ -30,13 +29,13 @@
30
29
  },
31
30
  "devDependencies": {
32
31
  "@playwright/test": "^1.56.0",
33
- "@t8/serve": "^0.1.36",
32
+ "@t8/serve": "^0.1.37",
34
33
  "@types/node": "^24.10.2",
35
34
  "@types/react": "^19.2.7",
36
35
  "@types/react-dom": "^19.2.3",
37
36
  "react-dom": "^19.2.1"
38
37
  },
39
38
  "dependencies": {
40
- "@t8/react-store": "^1.2.4"
39
+ "@t8/react-store": "^1.2.5"
41
40
  }
42
41
  }
package/dist/index.js DELETED
@@ -1,169 +0,0 @@
1
- // src/PendingStateContext.ts
2
- import { createContext } from "react";
3
- var PendingStateContext = createContext(
4
- /* @__PURE__ */ new Map()
5
- );
6
-
7
- // node_modules/@t8/store/src/isStore.ts
8
- function isStore(x) {
9
- 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";
10
- }
11
-
12
- // node_modules/@t8/store/src/isPersistentStore.ts
13
- function isPersistentStore(x) {
14
- return isStore(x) && "sync" in x;
15
- }
16
-
17
- // node_modules/@t8/store/src/Store.ts
18
- var Store = class {
19
- state;
20
- callbacks = /* @__PURE__ */ new Set();
21
- revision = -1;
22
- constructor(data) {
23
- this.state = data;
24
- }
25
- onUpdate(callback) {
26
- this.callbacks.add(callback);
27
- return () => {
28
- this.callbacks.delete(callback);
29
- };
30
- }
31
- getState() {
32
- return this.state;
33
- }
34
- setState(update) {
35
- let prevState = this.state;
36
- let nextState = update instanceof Function ? update(this.state) : update;
37
- this.state = nextState;
38
- this.revision = Math.random();
39
- for (let callback of this.callbacks) callback(nextState, prevState);
40
- }
41
- };
42
-
43
- // node_modules/@t8/react-store/src/useStore.ts
44
- import { useEffect, useMemo, useRef, useState } from "react";
45
- function useStore(store, shouldUpdate = true) {
46
- if (!isStore(store))
47
- throw new Error("'store' is not an instance of Store");
48
- let [, setRevision] = useState(-1);
49
- let state = store.getState();
50
- let setState = useMemo(() => store.setState.bind(store), [store]);
51
- let initialStoreRevision = useRef(store.revision);
52
- useEffect(() => {
53
- if (isPersistentStore(store)) store.syncOnce();
54
- if (!shouldUpdate) return;
55
- let unsubscribe = store.onUpdate((nextState, prevState) => {
56
- if (typeof shouldUpdate !== "function" || shouldUpdate(nextState, prevState))
57
- setRevision(Math.random());
58
- });
59
- if (store.revision !== initialStoreRevision.current)
60
- setRevision(Math.random());
61
- return () => {
62
- unsubscribe();
63
- initialStoreRevision.current = store.revision;
64
- };
65
- }, [store, shouldUpdate]);
66
- return [state, setState];
67
- }
68
-
69
- // src/PendingStateProvider.tsx
70
- import { useMemo as useMemo2, useRef as useRef2 } from "react";
71
- import { jsx } from "react/jsx-runtime";
72
- var PendingStateProvider = ({
73
- value,
74
- children
75
- }) => {
76
- let defaultValueRef = useRef2(null);
77
- let resolvedValue = useMemo2(() => {
78
- if (value instanceof Map) return value;
79
- if (typeof value === "object" && value !== null)
80
- return new Map(
81
- Object.entries(value).map(([key, state]) => [key, new Store(state)])
82
- );
83
- if (defaultValueRef.current === null)
84
- defaultValueRef.current = /* @__PURE__ */ new Map();
85
- return defaultValueRef.current;
86
- }, [value]);
87
- return /* @__PURE__ */ jsx(PendingStateContext.Provider, { value: resolvedValue, children });
88
- };
89
-
90
- // src/usePendingState.ts
91
- import { useCallback, useContext, useMemo as useMemo3, useRef as useRef3, useState as useState2 } from "react";
92
- function createState(initialized = false, complete = false, error) {
93
- return {
94
- initialized,
95
- complete,
96
- error,
97
- time: Date.now()
98
- };
99
- }
100
- function usePendingState(store) {
101
- let storeMap = useContext(PendingStateContext);
102
- let storeRef = useRef3(null);
103
- let [storeItemInited, setStoreItemInited] = useState2(false);
104
- let resolvedStore = useMemo3(() => {
105
- if (isStore(store)) return store;
106
- if (typeof store === "string") {
107
- let storeItem = storeMap.get(store);
108
- if (!storeItem) {
109
- storeItem = new Store(createState());
110
- storeMap.set(store, storeItem);
111
- if (!storeItemInited) setStoreItemInited(true);
112
- }
113
- return storeItem;
114
- }
115
- if (!storeRef.current) storeRef.current = new Store(createState());
116
- return storeRef.current;
117
- }, [store, storeMap, storeItemInited]);
118
- let [state, setState] = useStore(resolvedStore);
119
- let withState = useCallback(
120
- (value, options) => {
121
- if (value instanceof Promise) {
122
- let delayedPending = null;
123
- if (!options?.silent) {
124
- let delay = options?.delay;
125
- if (delay === void 0)
126
- setState((prevState) => ({
127
- ...prevState,
128
- ...createState(true, false)
129
- }));
130
- else
131
- delayedPending = setTimeout(() => {
132
- setState((prevState) => ({
133
- ...prevState,
134
- ...createState(true, false)
135
- }));
136
- delayedPending = null;
137
- }, delay);
138
- }
139
- return value.then((resolvedValue) => {
140
- if (delayedPending !== null) clearTimeout(delayedPending);
141
- setState((prevState) => ({
142
- ...prevState,
143
- ...createState(true, true)
144
- }));
145
- return resolvedValue;
146
- }).catch((error) => {
147
- if (delayedPending !== null) clearTimeout(delayedPending);
148
- setState((prevState) => ({
149
- ...prevState,
150
- ...createState(true, true, error)
151
- }));
152
- if (options?.throws) throw error;
153
- });
154
- }
155
- setState((prevState) => ({
156
- ...prevState,
157
- ...createState(true, true)
158
- }));
159
- return value;
160
- },
161
- [setState]
162
- );
163
- return [state, withState, setState];
164
- }
165
- export {
166
- PendingStateContext,
167
- PendingStateProvider,
168
- usePendingState
169
- };