@isograph/react-disposable-state 0.5.0 → 0.5.1

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.
Files changed (69) hide show
  1. package/.turbo/turbo-compile-libs.log +9 -2
  2. package/dist/CacheItem.d.mts +63 -0
  3. package/dist/CacheItem.d.mts.map +1 -0
  4. package/dist/CacheItem.d.ts +33 -29
  5. package/dist/CacheItem.d.ts.map +1 -1
  6. package/dist/CacheItem.js +191 -266
  7. package/dist/CacheItem.mjs +193 -0
  8. package/dist/CacheItem.mjs.map +1 -0
  9. package/dist/ParentCache.d.mts +45 -0
  10. package/dist/ParentCache.d.mts.map +1 -0
  11. package/dist/ParentCache.d.ts +27 -22
  12. package/dist/ParentCache.d.ts.map +1 -1
  13. package/dist/ParentCache.js +69 -85
  14. package/dist/ParentCache.mjs +73 -0
  15. package/dist/ParentCache.mjs.map +1 -0
  16. package/dist/_virtual/rolldown_runtime.js +25 -0
  17. package/dist/index.d.mts +9 -0
  18. package/dist/index.d.ts +9 -9
  19. package/dist/index.js +24 -24
  20. package/dist/index.mjs +11 -0
  21. package/dist/useCachedResponsivePrecommitValue.d.mts +43 -0
  22. package/dist/useCachedResponsivePrecommitValue.d.mts.map +1 -0
  23. package/dist/useCachedResponsivePrecommitValue.d.ts +9 -4
  24. package/dist/useCachedResponsivePrecommitValue.d.ts.map +1 -1
  25. package/dist/useCachedResponsivePrecommitValue.js +55 -90
  26. package/dist/useCachedResponsivePrecommitValue.mjs +57 -0
  27. package/dist/useCachedResponsivePrecommitValue.mjs.map +1 -0
  28. package/dist/useDisposableState.d.mts +13 -0
  29. package/dist/useDisposableState.d.mts.map +1 -0
  30. package/dist/useDisposableState.d.ts +10 -7
  31. package/dist/useDisposableState.d.ts.map +1 -1
  32. package/dist/useDisposableState.js +36 -69
  33. package/dist/useDisposableState.mjs +37 -0
  34. package/dist/useDisposableState.mjs.map +1 -0
  35. package/dist/useHasCommittedRef.d.mts +11 -0
  36. package/dist/useHasCommittedRef.d.mts.map +1 -0
  37. package/dist/useHasCommittedRef.d.ts +7 -2
  38. package/dist/useHasCommittedRef.d.ts.map +1 -1
  39. package/dist/useHasCommittedRef.js +15 -11
  40. package/dist/useHasCommittedRef.mjs +17 -0
  41. package/dist/useHasCommittedRef.mjs.map +1 -0
  42. package/dist/useLazyDisposableState.d.mts +20 -0
  43. package/dist/useLazyDisposableState.d.mts.map +1 -0
  44. package/dist/useLazyDisposableState.d.ts +9 -4
  45. package/dist/useLazyDisposableState.d.ts.map +1 -1
  46. package/dist/useLazyDisposableState.js +32 -39
  47. package/dist/useLazyDisposableState.mjs +34 -0
  48. package/dist/useLazyDisposableState.mjs.map +1 -0
  49. package/dist/useUpdatableDisposableState.d.mts +43 -0
  50. package/dist/useUpdatableDisposableState.d.mts.map +1 -0
  51. package/dist/useUpdatableDisposableState.d.ts +10 -7
  52. package/dist/useUpdatableDisposableState.d.ts.map +1 -1
  53. package/dist/useUpdatableDisposableState.js +73 -89
  54. package/dist/useUpdatableDisposableState.mjs +74 -0
  55. package/dist/useUpdatableDisposableState.mjs.map +1 -0
  56. package/package.json +14 -6
  57. package/src/CacheItem.test.ts +4 -7
  58. package/src/CacheItem.ts +16 -11
  59. package/src/ParentCache.test.ts +5 -5
  60. package/src/ParentCache.ts +5 -4
  61. package/src/useCachedResponsivePrecommitValue.test.tsx +15 -14
  62. package/src/useCachedResponsivePrecommitValue.ts +4 -4
  63. package/src/useDisposableState.ts +21 -16
  64. package/src/useHasCommittedRef.ts +1 -1
  65. package/src/useLazyDisposableState.test.tsx +2 -2
  66. package/src/useLazyDisposableState.ts +1 -1
  67. package/src/useUpdatableDisposableState.test.tsx +19 -5
  68. package/src/useUpdatableDisposableState.ts +1 -1
  69. package/dist/index.d.ts.map +0 -1
@@ -1,6 +1,11 @@
1
- import { MutableRefObject } from 'react';
1
+ import { MutableRefObject } from "react";
2
+
3
+ //#region src/useHasCommittedRef.d.ts
4
+
2
5
  /**
3
6
  * Returns true if the component has committed, false otherwise.
4
7
  */
5
- export declare function useHasCommittedRef(): MutableRefObject<boolean>;
8
+ declare function useHasCommittedRef(): MutableRefObject<boolean>;
9
+ //#endregion
10
+ export { useHasCommittedRef };
6
11
  //# sourceMappingURL=useHasCommittedRef.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHasCommittedRef.d.ts","sourceRoot":"","sources":["../src/useHasCommittedRef.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,OAAO,CAAC;AAE5D;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAM9D"}
1
+ {"version":3,"file":"useHasCommittedRef.d.ts","names":[],"sources":["../src/useHasCommittedRef.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;iBAAgB,kBAAA,CAAA,GAAsB"}
@@ -1,14 +1,18 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useHasCommittedRef = useHasCommittedRef;
4
- const react_1 = require("react");
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.js');
2
+ let react = require("react");
3
+ react = require_rolldown_runtime.__toESM(react);
4
+
5
+ //#region src/useHasCommittedRef.ts
5
6
  /**
6
- * Returns true if the component has committed, false otherwise.
7
- */
7
+ * Returns true if the component has committed, false otherwise.
8
+ */
8
9
  function useHasCommittedRef() {
9
- const hasCommittedRef = (0, react_1.useRef)(false);
10
- (0, react_1.useEffect)(() => {
11
- hasCommittedRef.current = true;
12
- }, []);
13
- return hasCommittedRef;
10
+ const hasCommittedRef = (0, react.useRef)(false);
11
+ (0, react.useEffect)(() => {
12
+ hasCommittedRef.current = true;
13
+ }, []);
14
+ return hasCommittedRef;
14
15
  }
16
+
17
+ //#endregion
18
+ exports.useHasCommittedRef = useHasCommittedRef;
@@ -0,0 +1,17 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ //#region src/useHasCommittedRef.ts
4
+ /**
5
+ * Returns true if the component has committed, false otherwise.
6
+ */
7
+ function useHasCommittedRef() {
8
+ const hasCommittedRef = useRef(false);
9
+ useEffect(() => {
10
+ hasCommittedRef.current = true;
11
+ }, []);
12
+ return hasCommittedRef;
13
+ }
14
+
15
+ //#endregion
16
+ export { useHasCommittedRef };
17
+ //# sourceMappingURL=useHasCommittedRef.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHasCommittedRef.mjs","names":[],"sources":["../src/useHasCommittedRef.ts"],"sourcesContent":["import { type MutableRefObject, useEffect, useRef } from 'react';\n\n/**\n * Returns true if the component has committed, false otherwise.\n */\nexport function useHasCommittedRef(): MutableRefObject<boolean> {\n const hasCommittedRef = useRef(false);\n useEffect(() => {\n hasCommittedRef.current = true;\n }, []);\n return hasCommittedRef;\n}\n"],"mappings":";;;;;;AAKA,SAAgB,qBAAgD;CAC9D,MAAM,kBAAkB,OAAO,MAAM;AACrC,iBAAgB;AACd,kBAAgB,UAAU;IACzB,EAAE,CAAC;AACN,QAAO"}
@@ -0,0 +1,20 @@
1
+ import { ParentCache } from "./ParentCache.mjs";
2
+ import { UnassignedState } from "./useUpdatableDisposableState.mjs";
3
+
4
+ //#region src/useLazyDisposableState.d.ts
5
+
6
+ /**
7
+ * useLazyDisposableState<T>
8
+ * - Takes a mutable parent cache and a factory function
9
+ * - Returns { state: T }
10
+ *
11
+ * This lazily loads the disposable item using useCachedResponsivePrecommitValue, then
12
+ * (on commit) sets it in state. The item continues to be returned after
13
+ * commit and is disposed when the hook unmounts.
14
+ */
15
+ declare function useLazyDisposableState<T>(parentCache: ParentCache<Exclude<T, UnassignedState>>): {
16
+ state: T;
17
+ };
18
+ //#endregion
19
+ export { useLazyDisposableState };
20
+ //# sourceMappingURL=useLazyDisposableState.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLazyDisposableState.d.mts","names":[],"sources":["../src/useLazyDisposableState.ts"],"sourcesContent":[],"mappings":";;;;;;;AAiBA;;;;;;;iBAAgB,uCACD,YAAY,QAAQ,GAAG;SAE7B"}
@@ -1,5 +1,8 @@
1
- import { ParentCache } from './ParentCache';
2
- import { type UnassignedState } from './useUpdatableDisposableState';
1
+ import { ParentCache } from "./ParentCache.js";
2
+ import { UnassignedState } from "./useUpdatableDisposableState.js";
3
+
4
+ //#region src/useLazyDisposableState.d.ts
5
+
3
6
  /**
4
7
  * useLazyDisposableState<T>
5
8
  * - Takes a mutable parent cache and a factory function
@@ -9,7 +12,9 @@ import { type UnassignedState } from './useUpdatableDisposableState';
9
12
  * (on commit) sets it in state. The item continues to be returned after
10
13
  * commit and is disposed when the hook unmounts.
11
14
  */
12
- export declare function useLazyDisposableState<T>(parentCache: ParentCache<Exclude<T, UnassignedState>>): {
13
- state: T;
15
+ declare function useLazyDisposableState<T>(parentCache: ParentCache<Exclude<T, UnassignedState>>): {
16
+ state: T;
14
17
  };
18
+ //#endregion
19
+ export { useLazyDisposableState };
15
20
  //# sourceMappingURL=useLazyDisposableState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useLazyDisposableState.d.ts","sourceRoot":"","sources":["../src/useLazyDisposableState.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,GACpD;IACD,KAAK,EAAE,CAAC,CAAC;CACV,CAoCA"}
1
+ {"version":3,"file":"useLazyDisposableState.d.ts","names":[],"sources":["../src/useLazyDisposableState.ts"],"sourcesContent":[],"mappings":";;;;;;;AAiBA;;;;;;;iBAAgB,uCACD,YAAY,QAAQ,GAAG;SAE7B"}
@@ -1,42 +1,35 @@
1
- 'use strict';
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useLazyDisposableState = useLazyDisposableState;
4
- const react_1 = require("react");
5
- const useCachedResponsivePrecommitValue_1 = require("./useCachedResponsivePrecommitValue");
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.js');
2
+ const require_useCachedResponsivePrecommitValue = require('./useCachedResponsivePrecommitValue.js');
3
+ let react = require("react");
4
+ react = require_rolldown_runtime.__toESM(react);
5
+
6
+ //#region src/useLazyDisposableState.ts
6
7
  /**
7
- * useLazyDisposableState<T>
8
- * - Takes a mutable parent cache and a factory function
9
- * - Returns { state: T }
10
- *
11
- * This lazily loads the disposable item using useCachedResponsivePrecommitValue, then
12
- * (on commit) sets it in state. The item continues to be returned after
13
- * commit and is disposed when the hook unmounts.
14
- */
8
+ * useLazyDisposableState<T>
9
+ * - Takes a mutable parent cache and a factory function
10
+ * - Returns { state: T }
11
+ *
12
+ * This lazily loads the disposable item using useCachedResponsivePrecommitValue, then
13
+ * (on commit) sets it in state. The item continues to be returned after
14
+ * commit and is disposed when the hook unmounts.
15
+ */
15
16
  function useLazyDisposableState(parentCache) {
16
- var _a, _b;
17
- const itemCleanupPairRef = (0, react_1.useRef)(null);
18
- const preCommitItem = (0, useCachedResponsivePrecommitValue_1.useCachedResponsivePrecommitValue)(parentCache, (pair) => {
19
- var _a;
20
- (_a = itemCleanupPairRef.current) === null || _a === void 0 ? void 0 : _a[1]();
21
- itemCleanupPairRef.current = pair;
22
- });
23
- (0, react_1.useEffect)(() => {
24
- return () => {
25
- var _a;
26
- const cleanupFn = (_a = itemCleanupPairRef.current) === null || _a === void 0 ? void 0 : _a[1];
27
- // TODO confirm useEffect is called in order.
28
- if (cleanupFn == null) {
29
- throw new Error('cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.');
30
- }
31
- return cleanupFn();
32
- };
33
- }, []);
34
- const returnedItem = (_a = preCommitItem === null || preCommitItem === void 0 ? void 0 : preCommitItem.state) !== null && _a !== void 0 ? _a : (_b = itemCleanupPairRef.current) === null || _b === void 0 ? void 0 : _b[0];
35
- if (returnedItem != null) {
36
- return { state: returnedItem };
37
- }
38
- // Safety: This can't happen. For renders before the initial commit, preCommitItem
39
- // is non-null. During the initial commit, we assign itemCleanupPairRef.current,
40
- // so during subsequent renders, itemCleanupPairRef.current is non-null.
41
- throw new Error('returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.');
17
+ const itemCleanupPairRef = (0, react.useRef)(null);
18
+ const preCommitItem = require_useCachedResponsivePrecommitValue.useCachedResponsivePrecommitValue(parentCache, (pair) => {
19
+ itemCleanupPairRef.current?.[1]();
20
+ itemCleanupPairRef.current = pair;
21
+ });
22
+ (0, react.useEffect)(() => {
23
+ return () => {
24
+ const cleanupFn = itemCleanupPairRef.current?.[1];
25
+ if (cleanupFn == null) throw new Error("cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.");
26
+ return cleanupFn();
27
+ };
28
+ }, []);
29
+ const returnedItem = preCommitItem?.state ?? itemCleanupPairRef.current?.[0];
30
+ if (returnedItem != null) return { state: returnedItem };
31
+ throw new Error("returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.");
42
32
  }
33
+
34
+ //#endregion
35
+ exports.useLazyDisposableState = useLazyDisposableState;
@@ -0,0 +1,34 @@
1
+ import { useCachedResponsivePrecommitValue } from "./useCachedResponsivePrecommitValue.mjs";
2
+ import { useEffect, useRef } from "react";
3
+
4
+ //#region src/useLazyDisposableState.ts
5
+ /**
6
+ * useLazyDisposableState<T>
7
+ * - Takes a mutable parent cache and a factory function
8
+ * - Returns { state: T }
9
+ *
10
+ * This lazily loads the disposable item using useCachedResponsivePrecommitValue, then
11
+ * (on commit) sets it in state. The item continues to be returned after
12
+ * commit and is disposed when the hook unmounts.
13
+ */
14
+ function useLazyDisposableState(parentCache) {
15
+ const itemCleanupPairRef = useRef(null);
16
+ const preCommitItem = useCachedResponsivePrecommitValue(parentCache, (pair) => {
17
+ itemCleanupPairRef.current?.[1]();
18
+ itemCleanupPairRef.current = pair;
19
+ });
20
+ useEffect(() => {
21
+ return () => {
22
+ const cleanupFn = itemCleanupPairRef.current?.[1];
23
+ if (cleanupFn == null) throw new Error("cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.");
24
+ return cleanupFn();
25
+ };
26
+ }, []);
27
+ const returnedItem = preCommitItem?.state ?? itemCleanupPairRef.current?.[0];
28
+ if (returnedItem != null) return { state: returnedItem };
29
+ throw new Error("returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.");
30
+ }
31
+
32
+ //#endregion
33
+ export { useLazyDisposableState };
34
+ //# sourceMappingURL=useLazyDisposableState.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLazyDisposableState.mjs","names":[],"sources":["../src/useLazyDisposableState.ts"],"sourcesContent":["'use strict';\n\nimport type { ItemCleanupPair } from '@isograph/isograph-disposable-types';\nimport { useEffect, useRef } from 'react';\nimport type { ParentCache } from './ParentCache';\nimport { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';\nimport { type UnassignedState } from './useUpdatableDisposableState';\n\n/**\n * useLazyDisposableState<T>\n * - Takes a mutable parent cache and a factory function\n * - Returns { state: T }\n *\n * This lazily loads the disposable item using useCachedResponsivePrecommitValue, then\n * (on commit) sets it in state. The item continues to be returned after\n * commit and is disposed when the hook unmounts.\n */\nexport function useLazyDisposableState<T>(\n parentCache: ParentCache<Exclude<T, UnassignedState>>,\n): {\n state: T;\n} {\n const itemCleanupPairRef = useRef<ItemCleanupPair<T> | null>(null);\n\n const preCommitItem = useCachedResponsivePrecommitValue(\n parentCache,\n (pair) => {\n itemCleanupPairRef.current?.[1]();\n itemCleanupPairRef.current = pair;\n },\n );\n\n useEffect(() => {\n return () => {\n const cleanupFn = itemCleanupPairRef.current?.[1];\n // TODO confirm useEffect is called in order.\n if (cleanupFn == null) {\n throw new Error(\n 'cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.',\n );\n }\n return cleanupFn();\n };\n }, []);\n\n const returnedItem = preCommitItem?.state ?? itemCleanupPairRef.current?.[0];\n\n if (returnedItem != null) {\n return { state: returnedItem };\n }\n\n // Safety: This can't happen. For renders before the initial commit, preCommitItem\n // is non-null. During the initial commit, we assign itemCleanupPairRef.current,\n // so during subsequent renders, itemCleanupPairRef.current is non-null.\n throw new Error(\n 'returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.',\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,uBACd,aAGA;CACA,MAAM,qBAAqB,OAAkC,KAAK;CAElE,MAAM,gBAAgB,kCACpB,cACC,SAAS;AACR,qBAAmB,UAAU,IAAI;AACjC,qBAAmB,UAAU;GAEhC;AAED,iBAAgB;AACd,eAAa;GACX,MAAM,YAAY,mBAAmB,UAAU;AAE/C,OAAI,aAAa,KACf,OAAM,IAAI,MACR,+EACD;AAEH,UAAO,WAAW;;IAEnB,EAAE,CAAC;CAEN,MAAM,eAAe,eAAe,SAAS,mBAAmB,UAAU;AAE1E,KAAI,gBAAgB,KAClB,QAAO,EAAE,OAAO,cAAc;AAMhC,OAAM,IAAI,MACR,sFACD"}
@@ -0,0 +1,43 @@
1
+ import { ItemCleanupPair } from "@isograph/disposable-types";
2
+
3
+ //#region src/useUpdatableDisposableState.d.ts
4
+ declare const UNASSIGNED_STATE: unique symbol;
5
+ type UnassignedState = typeof UNASSIGNED_STATE;
6
+ type UseUpdatableDisposableStateReturnValue<T> = {
7
+ state: T | UnassignedState;
8
+ setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;
9
+ };
10
+ /**
11
+ * useUpdatableDisposableState
12
+ * - Returns a { state, setItem } object.
13
+ * - setItem accepts an ItemCleanupPair<T>, and throws if called before commit.
14
+ * - setItem sets the T in state and adds it to a set.
15
+ * - React's behavior is that when the hook commits, whatever item is currently
16
+ * returned from the useState hook is the oldest item which will ever be returned
17
+ * from that useState hook. (More newly created ones can later be returned with
18
+ * concurrent mode.)
19
+ * - When this hook commits, all items up to, but not including, the item currently
20
+ * returned from the useState hook are disposed and removed from the set.
21
+ *
22
+ * Calling setState before the hook commits:
23
+ * - Calling setState before the hook commits is disallowed because until the hook
24
+ * commits, React will not schedule any unmount callbacks, meaning that if this
25
+ * hook never commits, any disposable items passed to setState will never be
26
+ * disposed.
27
+ * - We also cannot store them in some cache, because multiple components can share
28
+ * the same cache location (for example, if they are loading the same query from
29
+ * multiple components), so updating the cache with the disposable item will cause
30
+ * both components to show the updated data, which is almost certainly a bug.
31
+ * - Note that calling setState before commit is probably an anti-pattern! Consider
32
+ * not doing it.
33
+ * - If you must, the workaround is to lazily load the disposable item with
34
+ * useDisposableState or useLazyDisposableState, and update the cache location
35
+ * instead of calling setState before commit. One can update the cache location
36
+ * by calling setState on some parent component that has already mounted, and
37
+ * therefore passing in different props.
38
+ * - This may only work in concurrent mode, though.
39
+ */
40
+ declare function useUpdatableDisposableState<T = never>(): UseUpdatableDisposableStateReturnValue<T>;
41
+ //#endregion
42
+ export { UNASSIGNED_STATE, UnassignedState, useUpdatableDisposableState };
43
+ //# sourceMappingURL=useUpdatableDisposableState.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUpdatableDisposableState.d.mts","names":[],"sources":["../src/useUpdatableDisposableState.ts"],"sourcesContent":[],"mappings":";;;cAIa;KACD,eAAA,UAAyB;AADrC,KAGK,sCAHkD,CAAA,CAAA,CAAA,GAAA;EAC3C,KAAA,EAGH,CAHG,GAGC,eAHc;EAEtB,QAAA,EAAA,CAAA,IAAA,EAEc,eAFd,CAE8B,OAF9B,CAEsC,CAFA,EAEG,eAFH,CAAA,CAAA,EAAA,GAAA,IAAA;CAClC;;;;;;;AAoDT;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,0CAEX,uCAAuC"}
@@ -1,9 +1,11 @@
1
- import { ItemCleanupPair } from '@isograph/disposable-types';
2
- export declare const UNASSIGNED_STATE: unique symbol;
3
- export type UnassignedState = typeof UNASSIGNED_STATE;
1
+ import { ItemCleanupPair } from "@isograph/disposable-types";
2
+
3
+ //#region src/useUpdatableDisposableState.d.ts
4
+ declare const UNASSIGNED_STATE: unique symbol;
5
+ type UnassignedState = typeof UNASSIGNED_STATE;
4
6
  type UseUpdatableDisposableStateReturnValue<T> = {
5
- state: T | UnassignedState;
6
- setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;
7
+ state: T | UnassignedState;
8
+ setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;
7
9
  };
8
10
  /**
9
11
  * useUpdatableDisposableState
@@ -35,6 +37,7 @@ type UseUpdatableDisposableStateReturnValue<T> = {
35
37
  * therefore passing in different props.
36
38
  * - This may only work in concurrent mode, though.
37
39
  */
38
- export declare function useUpdatableDisposableState<T = never>(): UseUpdatableDisposableStateReturnValue<T>;
39
- export {};
40
+ declare function useUpdatableDisposableState<T = never>(): UseUpdatableDisposableStateReturnValue<T>;
41
+ //#endregion
42
+ export { UNASSIGNED_STATE, UnassignedState, useUpdatableDisposableState };
40
43
  //# sourceMappingURL=useUpdatableDisposableState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useUpdatableDisposableState.d.ts","sourceRoot":"","sources":["../src/useUpdatableDisposableState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAI7D,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAiB,CAAC;AACxD,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC;AAEtD,KAAK,sCAAsC,CAAC,CAAC,IAAI;IAC/C,KAAK,EAAE,CAAC,GAAG,eAAe,CAAC;IAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,KAAK,IAAI,CAAC;CACxE,CAAC;AAoBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,2BAA2B,CACzC,CAAC,GAAG,KAAK,KACN,sCAAsC,CAAC,CAAC,CAAC,CA0D7C"}
1
+ {"version":3,"file":"useUpdatableDisposableState.d.ts","names":[],"sources":["../src/useUpdatableDisposableState.ts"],"sourcesContent":[],"mappings":";;;cAIa;KACD,eAAA,UAAyB;AADrC,KAGK,sCAHkD,CAAA,CAAA,CAAA,GAAA;EAC3C,KAAA,EAGH,CAHG,GAGC,eAHc;EAEtB,QAAA,EAAA,CAAA,IAAA,EAEc,eAFd,CAE8B,OAF9B,CAEsC,CAFA,EAEG,eAFH,CAAA,CAAA,EAAA,GAAA,IAAA;CAClC;;;;;;;AAoDT;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,0CAEX,uCAAuC"}
@@ -1,92 +1,76 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UNASSIGNED_STATE = void 0;
4
- exports.useUpdatableDisposableState = useUpdatableDisposableState;
5
- const react_1 = require("react");
6
- const useHasCommittedRef_1 = require("./useHasCommittedRef");
7
- exports.UNASSIGNED_STATE = Symbol();
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.js');
2
+ const require_useHasCommittedRef = require('./useHasCommittedRef.js');
3
+ let react = require("react");
4
+ react = require_rolldown_runtime.__toESM(react);
5
+
6
+ //#region src/useUpdatableDisposableState.ts
7
+ const UNASSIGNED_STATE = Symbol();
8
8
  /**
9
- * useUpdatableDisposableState
10
- * - Returns a { state, setItem } object.
11
- * - setItem accepts an ItemCleanupPair<T>, and throws if called before commit.
12
- * - setItem sets the T in state and adds it to a set.
13
- * - React's behavior is that when the hook commits, whatever item is currently
14
- * returned from the useState hook is the oldest item which will ever be returned
15
- * from that useState hook. (More newly created ones can later be returned with
16
- * concurrent mode.)
17
- * - When this hook commits, all items up to, but not including, the item currently
18
- * returned from the useState hook are disposed and removed from the set.
19
- *
20
- * Calling setState before the hook commits:
21
- * - Calling setState before the hook commits is disallowed because until the hook
22
- * commits, React will not schedule any unmount callbacks, meaning that if this
23
- * hook never commits, any disposable items passed to setState will never be
24
- * disposed.
25
- * - We also cannot store them in some cache, because multiple components can share
26
- * the same cache location (for example, if they are loading the same query from
27
- * multiple components), so updating the cache with the disposable item will cause
28
- * both components to show the updated data, which is almost certainly a bug.
29
- * - Note that calling setState before commit is probably an anti-pattern! Consider
30
- * not doing it.
31
- * - If you must, the workaround is to lazily load the disposable item with
32
- * useDisposableState or useLazyDisposableState, and update the cache location
33
- * instead of calling setState before commit. One can update the cache location
34
- * by calling setState on some parent component that has already mounted, and
35
- * therefore passing in different props.
36
- * - This may only work in concurrent mode, though.
37
- */
9
+ * useUpdatableDisposableState
10
+ * - Returns a { state, setItem } object.
11
+ * - setItem accepts an ItemCleanupPair<T>, and throws if called before commit.
12
+ * - setItem sets the T in state and adds it to a set.
13
+ * - React's behavior is that when the hook commits, whatever item is currently
14
+ * returned from the useState hook is the oldest item which will ever be returned
15
+ * from that useState hook. (More newly created ones can later be returned with
16
+ * concurrent mode.)
17
+ * - When this hook commits, all items up to, but not including, the item currently
18
+ * returned from the useState hook are disposed and removed from the set.
19
+ *
20
+ * Calling setState before the hook commits:
21
+ * - Calling setState before the hook commits is disallowed because until the hook
22
+ * commits, React will not schedule any unmount callbacks, meaning that if this
23
+ * hook never commits, any disposable items passed to setState will never be
24
+ * disposed.
25
+ * - We also cannot store them in some cache, because multiple components can share
26
+ * the same cache location (for example, if they are loading the same query from
27
+ * multiple components), so updating the cache with the disposable item will cause
28
+ * both components to show the updated data, which is almost certainly a bug.
29
+ * - Note that calling setState before commit is probably an anti-pattern! Consider
30
+ * not doing it.
31
+ * - If you must, the workaround is to lazily load the disposable item with
32
+ * useDisposableState or useLazyDisposableState, and update the cache location
33
+ * instead of calling setState before commit. One can update the cache location
34
+ * by calling setState on some parent component that has already mounted, and
35
+ * therefore passing in different props.
36
+ * - This may only work in concurrent mode, though.
37
+ */
38
38
  function useUpdatableDisposableState() {
39
- const hasCommittedRef = (0, useHasCommittedRef_1.useHasCommittedRef)();
40
- const undisposedICIs = (0, react_1.useRef)(new Set());
41
- const setStateCountRef = (0, react_1.useRef)(0);
42
- const [stateICI, setStateICI] = (0, react_1.useState)(exports.UNASSIGNED_STATE);
43
- const setStateAfterCommit = (0, react_1.useCallback)((itemCleanupPair) => {
44
- if (!hasCommittedRef.current) {
45
- throw new Error('Calling setState before the component has committed is unsafe and disallowed.');
46
- }
47
- const ici = {
48
- item: itemCleanupPair[0],
49
- cleanup: itemCleanupPair[1],
50
- index: setStateCountRef.current,
51
- };
52
- setStateCountRef.current++;
53
- undisposedICIs.current.add(ici);
54
- setStateICI(ici);
55
- }, [setStateICI]);
56
- (0, react_1.useEffect)(function cleanupUnreachableItems() {
57
- const indexInState = stateICI !== exports.UNASSIGNED_STATE ? stateICI.index : 0;
58
- if (indexInState === 0) {
59
- return;
60
- }
61
- for (const undisposedICI of undisposedICIs.current) {
62
- if (undisposedICI.index === indexInState) {
63
- break;
64
- }
65
- undisposedICIs.current.delete(undisposedICI);
66
- undisposedICI.cleanup();
67
- }
68
- });
69
- (0, react_1.useEffect)(() => {
70
- return function disposeAllRemainingItems() {
71
- for (const undisposedICI of undisposedICIs.current) {
72
- undisposedICI.cleanup();
73
- }
74
- };
75
- }, []);
76
- return {
77
- setState: setStateAfterCommit,
78
- state: stateICI !== exports.UNASSIGNED_STATE ? stateICI.item : exports.UNASSIGNED_STATE,
79
- };
80
- }
81
- // @ts-ignore
82
- function tsTests() {
83
- const a = useUpdatableDisposableState();
84
- // @ts-expect-error
85
- a.setState([exports.UNASSIGNED_STATE, () => { }]);
86
- // @ts-expect-error
87
- a.setState(['asdf', () => { }]);
88
- const b = useUpdatableDisposableState();
89
- // @ts-expect-error
90
- b.setState([exports.UNASSIGNED_STATE, () => { }]);
91
- b.setState(['asdf', () => { }]);
39
+ const hasCommittedRef = require_useHasCommittedRef.useHasCommittedRef();
40
+ const undisposedICIs = (0, react.useRef)(/* @__PURE__ */ new Set());
41
+ const setStateCountRef = (0, react.useRef)(0);
42
+ const [stateICI, setStateICI] = (0, react.useState)(UNASSIGNED_STATE);
43
+ const setStateAfterCommit = (0, react.useCallback)((itemCleanupPair) => {
44
+ if (!hasCommittedRef.current) throw new Error("Calling setState before the component has committed is unsafe and disallowed.");
45
+ const ici = {
46
+ item: itemCleanupPair[0],
47
+ cleanup: itemCleanupPair[1],
48
+ index: setStateCountRef.current
49
+ };
50
+ setStateCountRef.current++;
51
+ undisposedICIs.current.add(ici);
52
+ setStateICI(ici);
53
+ }, [setStateICI]);
54
+ (0, react.useEffect)(function cleanupUnreachableItems() {
55
+ const indexInState = stateICI !== UNASSIGNED_STATE ? stateICI.index : 0;
56
+ if (indexInState === 0) return;
57
+ for (const undisposedICI of undisposedICIs.current) {
58
+ if (undisposedICI.index === indexInState) break;
59
+ undisposedICIs.current.delete(undisposedICI);
60
+ undisposedICI.cleanup();
61
+ }
62
+ });
63
+ (0, react.useEffect)(() => {
64
+ return function disposeAllRemainingItems() {
65
+ for (const undisposedICI of undisposedICIs.current) undisposedICI.cleanup();
66
+ };
67
+ }, []);
68
+ return {
69
+ setState: setStateAfterCommit,
70
+ state: stateICI !== UNASSIGNED_STATE ? stateICI.item : UNASSIGNED_STATE
71
+ };
92
72
  }
73
+
74
+ //#endregion
75
+ exports.UNASSIGNED_STATE = UNASSIGNED_STATE;
76
+ exports.useUpdatableDisposableState = useUpdatableDisposableState;
@@ -0,0 +1,74 @@
1
+ import { useHasCommittedRef } from "./useHasCommittedRef.mjs";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+
4
+ //#region src/useUpdatableDisposableState.ts
5
+ const UNASSIGNED_STATE = Symbol();
6
+ /**
7
+ * useUpdatableDisposableState
8
+ * - Returns a { state, setItem } object.
9
+ * - setItem accepts an ItemCleanupPair<T>, and throws if called before commit.
10
+ * - setItem sets the T in state and adds it to a set.
11
+ * - React's behavior is that when the hook commits, whatever item is currently
12
+ * returned from the useState hook is the oldest item which will ever be returned
13
+ * from that useState hook. (More newly created ones can later be returned with
14
+ * concurrent mode.)
15
+ * - When this hook commits, all items up to, but not including, the item currently
16
+ * returned from the useState hook are disposed and removed from the set.
17
+ *
18
+ * Calling setState before the hook commits:
19
+ * - Calling setState before the hook commits is disallowed because until the hook
20
+ * commits, React will not schedule any unmount callbacks, meaning that if this
21
+ * hook never commits, any disposable items passed to setState will never be
22
+ * disposed.
23
+ * - We also cannot store them in some cache, because multiple components can share
24
+ * the same cache location (for example, if they are loading the same query from
25
+ * multiple components), so updating the cache with the disposable item will cause
26
+ * both components to show the updated data, which is almost certainly a bug.
27
+ * - Note that calling setState before commit is probably an anti-pattern! Consider
28
+ * not doing it.
29
+ * - If you must, the workaround is to lazily load the disposable item with
30
+ * useDisposableState or useLazyDisposableState, and update the cache location
31
+ * instead of calling setState before commit. One can update the cache location
32
+ * by calling setState on some parent component that has already mounted, and
33
+ * therefore passing in different props.
34
+ * - This may only work in concurrent mode, though.
35
+ */
36
+ function useUpdatableDisposableState() {
37
+ const hasCommittedRef = useHasCommittedRef();
38
+ const undisposedICIs = useRef(/* @__PURE__ */ new Set());
39
+ const setStateCountRef = useRef(0);
40
+ const [stateICI, setStateICI] = useState(UNASSIGNED_STATE);
41
+ const setStateAfterCommit = useCallback((itemCleanupPair) => {
42
+ if (!hasCommittedRef.current) throw new Error("Calling setState before the component has committed is unsafe and disallowed.");
43
+ const ici = {
44
+ item: itemCleanupPair[0],
45
+ cleanup: itemCleanupPair[1],
46
+ index: setStateCountRef.current
47
+ };
48
+ setStateCountRef.current++;
49
+ undisposedICIs.current.add(ici);
50
+ setStateICI(ici);
51
+ }, [setStateICI]);
52
+ useEffect(function cleanupUnreachableItems() {
53
+ const indexInState = stateICI !== UNASSIGNED_STATE ? stateICI.index : 0;
54
+ if (indexInState === 0) return;
55
+ for (const undisposedICI of undisposedICIs.current) {
56
+ if (undisposedICI.index === indexInState) break;
57
+ undisposedICIs.current.delete(undisposedICI);
58
+ undisposedICI.cleanup();
59
+ }
60
+ });
61
+ useEffect(() => {
62
+ return function disposeAllRemainingItems() {
63
+ for (const undisposedICI of undisposedICIs.current) undisposedICI.cleanup();
64
+ };
65
+ }, []);
66
+ return {
67
+ setState: setStateAfterCommit,
68
+ state: stateICI !== UNASSIGNED_STATE ? stateICI.item : UNASSIGNED_STATE
69
+ };
70
+ }
71
+
72
+ //#endregion
73
+ export { UNASSIGNED_STATE, useUpdatableDisposableState };
74
+ //# sourceMappingURL=useUpdatableDisposableState.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUpdatableDisposableState.mjs","names":["UNASSIGNED_STATE: unique symbol","ici: ICI<T>"],"sources":["../src/useUpdatableDisposableState.ts"],"sourcesContent":["import type { ItemCleanupPair } from '@isograph/disposable-types';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useHasCommittedRef } from './useHasCommittedRef';\n\nexport const UNASSIGNED_STATE: unique symbol = Symbol();\nexport type UnassignedState = typeof UNASSIGNED_STATE;\n\ntype UseUpdatableDisposableStateReturnValue<T> = {\n state: T | UnassignedState;\n setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;\n};\n\n/**\n * ICI stands for ItemCleanupIndex. Use a short name because it shows up a lot.\n *\n * Like an ItemCleanupPair<T>, but with an additional index and as a struct\n * for readability.\n *\n * Interally, we must keep track of the index of the state change. The disposable\n * items that are set in state are not guaranteed to be distinct according to ===,\n * as in `setState([1, dispose1]); setState([1, dispose2])`. Following this, we\n * would expect dispose1 to be called on commit. If state items were compared for\n * ===, then dispose1 would not be called in such a situation.\n *\n * Note that this comes at a runtime cost, and we may want to expose APIs that do\n * not incur this runtime cost, for example in cases where every disposable item is\n * distinguishable via ===.\n */\ntype ICI<T> = { item: T; cleanup: () => void; index: number };\n\n/**\n * useUpdatableDisposableState\n * - Returns a { state, setItem } object.\n * - setItem accepts an ItemCleanupPair<T>, and throws if called before commit.\n * - setItem sets the T in state and adds it to a set.\n * - React's behavior is that when the hook commits, whatever item is currently\n * returned from the useState hook is the oldest item which will ever be returned\n * from that useState hook. (More newly created ones can later be returned with\n * concurrent mode.)\n * - When this hook commits, all items up to, but not including, the item currently\n * returned from the useState hook are disposed and removed from the set.\n *\n * Calling setState before the hook commits:\n * - Calling setState before the hook commits is disallowed because until the hook\n * commits, React will not schedule any unmount callbacks, meaning that if this\n * hook never commits, any disposable items passed to setState will never be\n * disposed.\n * - We also cannot store them in some cache, because multiple components can share\n * the same cache location (for example, if they are loading the same query from\n * multiple components), so updating the cache with the disposable item will cause\n * both components to show the updated data, which is almost certainly a bug.\n * - Note that calling setState before commit is probably an anti-pattern! Consider\n * not doing it.\n * - If you must, the workaround is to lazily load the disposable item with\n * useDisposableState or useLazyDisposableState, and update the cache location\n * instead of calling setState before commit. One can update the cache location\n * by calling setState on some parent component that has already mounted, and\n * therefore passing in different props.\n * - This may only work in concurrent mode, though.\n */\nexport function useUpdatableDisposableState<\n T = never,\n>(): UseUpdatableDisposableStateReturnValue<T> {\n const hasCommittedRef = useHasCommittedRef();\n\n const undisposedICIs = useRef(new Set<ICI<T>>());\n const setStateCountRef = useRef(0);\n\n const [stateICI, setStateICI] = useState<ICI<T> | UnassignedState>(\n UNASSIGNED_STATE,\n );\n\n const setStateAfterCommit = useCallback(\n (itemCleanupPair: ItemCleanupPair<T>) => {\n if (!hasCommittedRef.current) {\n throw new Error(\n 'Calling setState before the component has committed is unsafe and disallowed.',\n );\n }\n\n const ici: ICI<T> = {\n item: itemCleanupPair[0],\n cleanup: itemCleanupPair[1],\n index: setStateCountRef.current,\n };\n setStateCountRef.current++;\n undisposedICIs.current.add(ici);\n setStateICI(ici);\n },\n [setStateICI],\n );\n\n useEffect(function cleanupUnreachableItems() {\n const indexInState = stateICI !== UNASSIGNED_STATE ? stateICI.index : 0;\n\n if (indexInState === 0) {\n return;\n }\n\n for (const undisposedICI of undisposedICIs.current) {\n if (undisposedICI.index === indexInState) {\n break;\n }\n undisposedICIs.current.delete(undisposedICI);\n undisposedICI.cleanup();\n }\n });\n\n useEffect(() => {\n return function disposeAllRemainingItems() {\n for (const undisposedICI of undisposedICIs.current) {\n undisposedICI.cleanup();\n }\n };\n }, []);\n\n return {\n setState: setStateAfterCommit,\n state: stateICI !== UNASSIGNED_STATE ? stateICI.item : UNASSIGNED_STATE,\n };\n}\n\n// @ts-ignore\nfunction tsTests() {\n const a = useUpdatableDisposableState();\n // @ts-expect-error\n a.setState([UNASSIGNED_STATE, () => {}]);\n // @ts-expect-error\n a.setState(['asdf', () => {}]);\n const b = useUpdatableDisposableState<string | UnassignedState>();\n // @ts-expect-error\n b.setState([UNASSIGNED_STATE, () => {}]);\n b.setState(['asdf', () => {}]);\n}\n"],"mappings":";;;;AAIA,MAAaA,mBAAkC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDvD,SAAgB,8BAE+B;CAC7C,MAAM,kBAAkB,oBAAoB;CAE5C,MAAM,iBAAiB,uBAAO,IAAI,KAAa,CAAC;CAChD,MAAM,mBAAmB,OAAO,EAAE;CAElC,MAAM,CAAC,UAAU,eAAe,SAC9B,iBACD;CAED,MAAM,sBAAsB,aACzB,oBAAwC;AACvC,MAAI,CAAC,gBAAgB,QACnB,OAAM,IAAI,MACR,gFACD;EAGH,MAAMC,MAAc;GAClB,MAAM,gBAAgB;GACtB,SAAS,gBAAgB;GACzB,OAAO,iBAAiB;GACzB;AACD,mBAAiB;AACjB,iBAAe,QAAQ,IAAI,IAAI;AAC/B,cAAY,IAAI;IAElB,CAAC,YAAY,CACd;AAED,WAAU,SAAS,0BAA0B;EAC3C,MAAM,eAAe,aAAa,mBAAmB,SAAS,QAAQ;AAEtE,MAAI,iBAAiB,EACnB;AAGF,OAAK,MAAM,iBAAiB,eAAe,SAAS;AAClD,OAAI,cAAc,UAAU,aAC1B;AAEF,kBAAe,QAAQ,OAAO,cAAc;AAC5C,iBAAc,SAAS;;GAEzB;AAEF,iBAAgB;AACd,SAAO,SAAS,2BAA2B;AACzC,QAAK,MAAM,iBAAiB,eAAe,QACzC,eAAc,SAAS;;IAG1B,EAAE,CAAC;AAEN,QAAO;EACL,UAAU;EACV,OAAO,aAAa,mBAAmB,SAAS,OAAO;EACxD"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@isograph/react-disposable-state",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Primitives for managing disposable state in React",
5
5
  "homepage": "https://isograph.dev",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
8
  "author": "Isograph Labs",
9
9
  "license": "MIT",
10
10
  "dependencies": {
11
- "@isograph/disposable-types": "0.5.0"
11
+ "@isograph/disposable-types": "0.5.1"
12
12
  },
13
13
  "peerDependencies": {
14
14
  "react": "^18.0.0 || ^19.0.0"
@@ -24,9 +24,17 @@
24
24
  "directory": "libs/isograph-react-disposable-state"
25
25
  },
26
26
  "sideEffects": false,
27
+ "module": "./dist/index.mjs",
28
+ "exports": {
29
+ ".": {
30
+ "import": "./dist/index.mjs",
31
+ "require": "./dist/index.js"
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
27
35
  "scripts": {
28
- "compile-libs": "rimraf dist && tsc -p tsconfig.pkg.json",
29
- "compile-watch": "tsc -p tsconfig.pkg.json --watch",
36
+ "compile-libs": "tsdown",
37
+ "watch-libs": "tsdown --watch",
30
38
  "test": "vitest run",
31
39
  "test-watch": "vitest watch",
32
40
  "coverage": "vitest run --coverage",