@o/hooks 0.16.19

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 (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/cjs/index.cjs +32 -0
  4. package/dist/cjs/index.native.js +35 -0
  5. package/dist/cjs/index.native.js.map +1 -0
  6. package/dist/cjs/useClickOutside.cjs +52 -0
  7. package/dist/cjs/useClickOutside.native.js +63 -0
  8. package/dist/cjs/useClickOutside.native.js.map +1 -0
  9. package/dist/cjs/useDebouncePrepend.cjs +66 -0
  10. package/dist/cjs/useDebouncePrepend.native.js +70 -0
  11. package/dist/cjs/useDebouncePrepend.native.js.map +1 -0
  12. package/dist/cjs/useDeepMemoizedObject.cjs +207 -0
  13. package/dist/cjs/useDeepMemoizedObject.native.js +258 -0
  14. package/dist/cjs/useDeepMemoizedObject.native.js.map +1 -0
  15. package/dist/cjs/useDeepMemoizedObject.test.cjs +321 -0
  16. package/dist/cjs/useDeepMemoizedObject.test.native.js +324 -0
  17. package/dist/cjs/useDeepMemoizedObject.test.native.js.map +1 -0
  18. package/dist/cjs/useDeferredBoolean.cjs +39 -0
  19. package/dist/cjs/useDeferredBoolean.native.js +42 -0
  20. package/dist/cjs/useDeferredBoolean.native.js.map +1 -0
  21. package/dist/cjs/useEffectOnceGlobally.cjs +45 -0
  22. package/dist/cjs/useEffectOnceGlobally.native.js +50 -0
  23. package/dist/cjs/useEffectOnceGlobally.native.js.map +1 -0
  24. package/dist/cjs/useEvent.cjs +33 -0
  25. package/dist/cjs/useEvent.native.js +41 -0
  26. package/dist/cjs/useEvent.native.js.map +1 -0
  27. package/dist/cjs/useIsMounted.cjs +35 -0
  28. package/dist/cjs/useIsMounted.native.js +38 -0
  29. package/dist/cjs/useIsMounted.native.js.map +1 -0
  30. package/dist/cjs/useLastValue.cjs +31 -0
  31. package/dist/cjs/useLastValue.native.js +34 -0
  32. package/dist/cjs/useLastValue.native.js.map +1 -0
  33. package/dist/cjs/useLastValueIf.cjs +38 -0
  34. package/dist/cjs/useLastValueIf.native.js +42 -0
  35. package/dist/cjs/useLastValueIf.native.js.map +1 -0
  36. package/dist/cjs/useMemoStable.cjs +35 -0
  37. package/dist/cjs/useMemoStable.native.js +39 -0
  38. package/dist/cjs/useMemoStable.native.js.map +1 -0
  39. package/dist/cjs/useMemoizedObjectList.cjs +64 -0
  40. package/dist/cjs/useMemoizedObjectList.native.js +86 -0
  41. package/dist/cjs/useMemoizedObjectList.native.js.map +1 -0
  42. package/dist/cjs/useThrottle.cjs +52 -0
  43. package/dist/cjs/useThrottle.native.js +59 -0
  44. package/dist/cjs/useThrottle.native.js.map +1 -0
  45. package/dist/cjs/useWarnIfDepsChange.cjs +65 -0
  46. package/dist/cjs/useWarnIfDepsChange.native.js +68 -0
  47. package/dist/cjs/useWarnIfDepsChange.native.js.map +1 -0
  48. package/dist/cjs/useWarnIfMemoChangesOften.cjs +43 -0
  49. package/dist/cjs/useWarnIfMemoChangesOften.native.js +48 -0
  50. package/dist/cjs/useWarnIfMemoChangesOften.native.js.map +1 -0
  51. package/dist/esm/index.js +14 -0
  52. package/dist/esm/index.js.map +1 -0
  53. package/dist/esm/index.mjs +14 -0
  54. package/dist/esm/index.mjs.map +1 -0
  55. package/dist/esm/index.native.js +14 -0
  56. package/dist/esm/index.native.js.map +1 -0
  57. package/dist/esm/useClickOutside.mjs +27 -0
  58. package/dist/esm/useClickOutside.mjs.map +1 -0
  59. package/dist/esm/useClickOutside.native.js +35 -0
  60. package/dist/esm/useClickOutside.native.js.map +1 -0
  61. package/dist/esm/useDebouncePrepend.mjs +41 -0
  62. package/dist/esm/useDebouncePrepend.mjs.map +1 -0
  63. package/dist/esm/useDebouncePrepend.native.js +42 -0
  64. package/dist/esm/useDebouncePrepend.native.js.map +1 -0
  65. package/dist/esm/useDeepMemoizedObject.mjs +180 -0
  66. package/dist/esm/useDeepMemoizedObject.mjs.map +1 -0
  67. package/dist/esm/useDeepMemoizedObject.native.js +228 -0
  68. package/dist/esm/useDeepMemoizedObject.native.js.map +1 -0
  69. package/dist/esm/useDeepMemoizedObject.test.mjs +322 -0
  70. package/dist/esm/useDeepMemoizedObject.test.mjs.map +1 -0
  71. package/dist/esm/useDeepMemoizedObject.test.native.js +322 -0
  72. package/dist/esm/useDeepMemoizedObject.test.native.js.map +1 -0
  73. package/dist/esm/useDeferredBoolean.mjs +14 -0
  74. package/dist/esm/useDeferredBoolean.mjs.map +1 -0
  75. package/dist/esm/useDeferredBoolean.native.js +14 -0
  76. package/dist/esm/useDeferredBoolean.native.js.map +1 -0
  77. package/dist/esm/useEffectOnceGlobally.mjs +20 -0
  78. package/dist/esm/useEffectOnceGlobally.mjs.map +1 -0
  79. package/dist/esm/useEffectOnceGlobally.native.js +22 -0
  80. package/dist/esm/useEffectOnceGlobally.native.js.map +1 -0
  81. package/dist/esm/useEvent.mjs +8 -0
  82. package/dist/esm/useEvent.mjs.map +1 -0
  83. package/dist/esm/useEvent.native.js +13 -0
  84. package/dist/esm/useEvent.native.js.map +1 -0
  85. package/dist/esm/useIsMounted.mjs +10 -0
  86. package/dist/esm/useIsMounted.mjs.map +1 -0
  87. package/dist/esm/useIsMounted.native.js +10 -0
  88. package/dist/esm/useIsMounted.native.js.map +1 -0
  89. package/dist/esm/useLastValue.mjs +6 -0
  90. package/dist/esm/useLastValue.mjs.map +1 -0
  91. package/dist/esm/useLastValue.native.js +6 -0
  92. package/dist/esm/useLastValue.native.js.map +1 -0
  93. package/dist/esm/useLastValueIf.mjs +13 -0
  94. package/dist/esm/useLastValueIf.mjs.map +1 -0
  95. package/dist/esm/useLastValueIf.native.js +14 -0
  96. package/dist/esm/useLastValueIf.native.js.map +1 -0
  97. package/dist/esm/useMemoStable.mjs +10 -0
  98. package/dist/esm/useMemoStable.mjs.map +1 -0
  99. package/dist/esm/useMemoStable.native.js +11 -0
  100. package/dist/esm/useMemoStable.native.js.map +1 -0
  101. package/dist/esm/useMemoizedObjectList.mjs +39 -0
  102. package/dist/esm/useMemoizedObjectList.mjs.map +1 -0
  103. package/dist/esm/useMemoizedObjectList.native.js +58 -0
  104. package/dist/esm/useMemoizedObjectList.native.js.map +1 -0
  105. package/dist/esm/useThrottle.mjs +27 -0
  106. package/dist/esm/useThrottle.mjs.map +1 -0
  107. package/dist/esm/useThrottle.native.js +31 -0
  108. package/dist/esm/useThrottle.native.js.map +1 -0
  109. package/dist/esm/useWarnIfDepsChange.mjs +40 -0
  110. package/dist/esm/useWarnIfDepsChange.mjs.map +1 -0
  111. package/dist/esm/useWarnIfDepsChange.native.js +40 -0
  112. package/dist/esm/useWarnIfDepsChange.native.js.map +1 -0
  113. package/dist/esm/useWarnIfMemoChangesOften.mjs +18 -0
  114. package/dist/esm/useWarnIfMemoChangesOften.mjs.map +1 -0
  115. package/dist/esm/useWarnIfMemoChangesOften.native.js +20 -0
  116. package/dist/esm/useWarnIfMemoChangesOften.native.js.map +1 -0
  117. package/package.json +59 -0
  118. package/src/index.ts +13 -0
  119. package/src/useClickOutside.ts +34 -0
  120. package/src/useDebouncePrepend.ts +63 -0
  121. package/src/useDeepMemoizedObject.test.ts +344 -0
  122. package/src/useDeepMemoizedObject.ts +231 -0
  123. package/src/useDeferredBoolean.tsx +15 -0
  124. package/src/useEffectOnceGlobally.ts +41 -0
  125. package/src/useEvent.ts +7 -0
  126. package/src/useIsMounted.ts +11 -0
  127. package/src/useLastValue.ts +5 -0
  128. package/src/useLastValueIf.ts +15 -0
  129. package/src/useMemoStable.ts +25 -0
  130. package/src/useMemoizedObjectList.ts +74 -0
  131. package/src/useThrottle.ts +36 -0
  132. package/src/useWarnIfDepsChange.ts +61 -0
  133. package/src/useWarnIfMemoChangesOften.ts +24 -0
@@ -0,0 +1,58 @@
1
+ import { isEqualDeepLite } from "@o/helpers";
2
+ import { useEffect, useMemo, useRef } from "react";
3
+ function useMemoizedObjectList(list, identityKey) {
4
+ var memoizedItems = useRef({});
5
+ var memoizedList = useRef(list);
6
+ var val = useMemo(function () {
7
+ var res = list;
8
+ var didFindChange = false;
9
+ var next = [];
10
+ var lastItems = memoizedItems.current;
11
+ if (list.length !== memoizedList.current.length) {
12
+ didFindChange = true;
13
+ }
14
+ var _iteratorNormalCompletion = true,
15
+ _didIteratorError = false,
16
+ _iteratorError = void 0;
17
+ try {
18
+ for (var _iterator = list[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
19
+ var item_ = _step.value;
20
+ var item = item_;
21
+ var id = item[identityKey];
22
+ var last = lastItems[id];
23
+ if (!last || !isEqualDeepLite(last, item)) {
24
+ didFindChange = true;
25
+ lastItems[id] = item;
26
+ next.push(item);
27
+ } else {
28
+ next.push(last);
29
+ }
30
+ }
31
+ } catch (err) {
32
+ _didIteratorError = true;
33
+ _iteratorError = err;
34
+ } finally {
35
+ try {
36
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
37
+ _iterator.return();
38
+ }
39
+ } finally {
40
+ if (_didIteratorError) {
41
+ throw _iteratorError;
42
+ }
43
+ }
44
+ }
45
+ if (didFindChange) {
46
+ res = next;
47
+ } else {
48
+ res = memoizedList.current;
49
+ }
50
+ return res;
51
+ }, [identityKey, list]);
52
+ useEffect(function () {
53
+ memoizedList.current = val;
54
+ }, [val]);
55
+ return val;
56
+ }
57
+ export { useMemoizedObjectList };
58
+ //# sourceMappingURL=useMemoizedObjectList.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isEqualDeepLite","useEffect","useMemo","useRef","useMemoizedObjectList","list","identityKey","memoizedItems","memoizedList","val","res","didFindChange","next","lastItems","current","length","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_iterator","Symbol","iterator","_step","done","item_","value","item","id","last","push","err","return"],"sources":["../../src/useMemoizedObjectList.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,eAAA,QAAuB;AAChC,SAASC,SAAA,EAAWC,OAAA,EAASC,MAAA,QAAc;AAapC,SAASC,sBAIdC,IAAA,EAAaC,WAAA,EAA6B;EAC1C,IAAAC,aAAM,GAAAJ,MAAgB,GAA4B,CAAC;EACnD,IAAAK,YAAM,GAAAL,MAAe,CAAAE,IAAc;EAEnC,IAAAI,GAAM,GAAAP,OAAM,aAAc;IACxB,IAAIQ,GAAA,GAAML,IAAA;IACV,IAAIM,aAAA,GAAgB;IACpB,IAAAC,IAAM,KAAe;IACrB,IAAAC,SAAM,GAAAN,aAAY,CAAAO,OAAc;IAGhC,IAAIT,IAAA,CAAKU,MAAA,KAAWP,YAAA,CAAaM,OAAA,CAAQC,MAAA,EAAQ;MAC/CJ,aAAA,GAAgB;IAClB;IAEA,IAAAK,yBAA0B;MAAAC,iBAAA;MAAAC,cAAA;IACxB;MACA,SAAMC,SAAU,GAAAd,IAAA,CAAAe,MAAW,CAAAC,QAAA,KAAAC,KAAA,IAAAN,yBAAA,IAAAM,KAAA,GAAAH,SAAA,CAAAP,IAAA,IAAAW,IAAA,GAAAP,yBAAA;QAC3B,IAAMQ,KAAA,GAAOF,KAAA,CAAAG,KAAY;QAGzB,IAAKC,IAAA,GAAQF,KAAC;QACZ,IAAAG,EAAA,GAAAD,IAAA,CAAApB,WAAgB;QAWhB,IAAAsB,IAAA,GAAUf,SAAM,CAAAc,EAAA;QAChB,KAAKC,IAAA,IAAK,CAAI5B,eAAA,CAAA4B,IAAA,EAAAF,IAAA;UAChBf,aAAO;UACLE,SAAU,CAAAc,EAAI,IAAAD,IAAA;UAChBd,IAAA,CAAAiB,IAAA,CAAAH,IAAA;QACF;UAGId,IAAA,CAAAiB,IAAA,CAAAD,IAAe;QACjB;MACF;IACE,SAAME,GAAA;MACRb,iBAAA;MAEAC,cAAO,GAAAY,GAAA;IACT,CAAG,SAAC;MAEJ;QACE,KAAAd,yBAAuB,IAAAG,SAAA,CAAAY,MAAA;UACjBZ,SAAA,CAAAY,MAAA;QAER;MACF","ignoreList":[]}
@@ -0,0 +1,27 @@
1
+ import { useRef } from "react";
2
+ import { useEvent } from "./useEvent.mjs";
3
+ const useThrottle = (fn, delay = 100) => {
4
+ const lastCallTime = useRef(0);
5
+ const timeoutRef = useRef(null);
6
+ const stableFn = useEvent(fn);
7
+ const throttledFn = useEvent((...args) => {
8
+ const now = Date.now();
9
+ const timeSinceLastCall = now - lastCallTime.current;
10
+ if (timeSinceLastCall >= delay) {
11
+ lastCallTime.current = now;
12
+ stableFn(...args);
13
+ } else {
14
+ if (timeoutRef.current) {
15
+ clearTimeout(timeoutRef.current);
16
+ }
17
+ timeoutRef.current = setTimeout(() => {
18
+ lastCallTime.current = Date.now();
19
+ stableFn(...args);
20
+ timeoutRef.current = null;
21
+ }, delay - timeSinceLastCall);
22
+ }
23
+ });
24
+ return throttledFn;
25
+ };
26
+ export { useThrottle };
27
+ //# sourceMappingURL=useThrottle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useRef","useEvent","useThrottle","fn","delay","lastCallTime","timeoutRef","stableFn","throttledFn","args","now","Date","timeSinceLastCall","current","clearTimeout","setTimeout"],"sources":["../../src/useThrottle.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAA,QAAc;AAEvB,SAASC,QAAA,QAAgB;AAIlB,MAAMC,WAAA,GAAcA,CAAoCC,EAAA,EAAOC,KAAA,GAAQ,QAAW;EACvF,MAAMC,YAAA,GAAeL,MAAA,CAAe,CAAC;EACrC,MAAMM,UAAA,GAAaN,MAAA,CAAqB,IAAI;EAE5C,MAAMO,QAAA,GAAWN,QAAA,CAASE,EAAE;EAE5B,MAAMK,WAAA,GAAcP,QAAA,CAAS,IAAIQ,IAAA,KAAwB;IACvD,MAAMC,GAAA,GAAMC,IAAA,CAAKD,GAAA,CAAI;IACrB,MAAME,iBAAA,GAAoBF,GAAA,GAAML,YAAA,CAAaQ,OAAA;IAE7C,IAAID,iBAAA,IAAqBR,KAAA,EAAO;MAE9BC,YAAA,CAAaQ,OAAA,GAAUH,GAAA;MACvBH,QAAA,CAAS,GAAGE,IAAI;IAClB,OAAO;MAEL,IAAIH,UAAA,CAAWO,OAAA,EAAS;QACtBC,YAAA,CAAaR,UAAA,CAAWO,OAAO;MACjC;MAEAP,UAAA,CAAWO,OAAA,GAAUE,UAAA,CAAW,MAAM;QACpCV,YAAA,CAAaQ,OAAA,GAAUF,IAAA,CAAKD,GAAA,CAAI;QAChCH,QAAA,CAAS,GAAGE,IAAI;QAChBH,UAAA,CAAWO,OAAA,GAAU;MACvB,GAAGT,KAAA,GAAQQ,iBAAiB;IAC9B;EACF,CAAC;EAED,OAAOJ,WAAA;AACT","ignoreList":[]}
@@ -0,0 +1,31 @@
1
+ import { useRef } from "react";
2
+ import { useEvent } from "./useEvent.native.js";
3
+ var useThrottle = function useThrottle2(fn) {
4
+ var delay = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 100;
5
+ var lastCallTime = useRef(0);
6
+ var timeoutRef = useRef(null);
7
+ var stableFn = useEvent(fn);
8
+ var throttledFn = useEvent(function () {
9
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
10
+ args[_key] = arguments[_key];
11
+ }
12
+ var now = Date.now();
13
+ var timeSinceLastCall = now - lastCallTime.current;
14
+ if (timeSinceLastCall >= delay) {
15
+ lastCallTime.current = now;
16
+ stableFn(...args);
17
+ } else {
18
+ if (timeoutRef.current) {
19
+ clearTimeout(timeoutRef.current);
20
+ }
21
+ timeoutRef.current = setTimeout(function () {
22
+ lastCallTime.current = Date.now();
23
+ stableFn(...args);
24
+ timeoutRef.current = null;
25
+ }, delay - timeSinceLastCall);
26
+ }
27
+ });
28
+ return throttledFn;
29
+ };
30
+ export { useThrottle };
31
+ //# sourceMappingURL=useThrottle.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useRef","useEvent","useThrottle","useThrottle2","fn","delay","arguments","length","lastCallTime","timeoutRef","stableFn","throttledFn","_len","args","Array","_key","now","Date","timeSinceLastCall","current","clearTimeout","setTimeout"],"sources":["../../src/useThrottle.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAA,QAAc;AAEvB,SAASC,QAAA,QAAgB;AAIlB,IAAAC,WAAM,YAAyDC,YAAQA,CAAAC,EAAW;EACvF,IAAAC,KAAM,GAAAC,SAAe,CAAAC,MAAe,GAAC,KAAAD,SAAA,iBAAAA,SAAA;EACrC,IAAAE,YAAM,GAAaR,MAAA,CAAqB;EAExC,IAAAS,UAAM,GAAWT,MAAA,KAAW;EAE5B,IAAAU,QAAM,GAAAT,QAAc,CAAAG,EAAA;EAClB,IAAAO,WAAY,GAAAV,QAAS;IACrB,SAAMW,IAAA,GAAAN,SAAA,CAAoBC,MAAM,EAAAM,IAAA,OAAaC,KAAA,CAAAF,IAAA,GAAAG,IAAA,MAAAA,IAAA,GAAAH,IAAA,EAAAG,IAAA;MAE7CF,IAAI,CAAAE,IAAA,IAAAT,SAAA,CAAqBS,IAAA;IAEvB;IACA,IAAAC,GAAA,GAAAC,IAAY,CAAAD,GAAI;IAClB,IAAAE,iBAAO,GAAAF,GAAA,GAAAR,YAAA,CAAAW,OAAA;IAEL,IAAAD,iBAAe,IAAAb,KAAS;MACtBG,YAAA,CAAAW,OAAa,GAAAH,GAAW;MAC1BN,QAAA,IAAAG,IAAA;IAEA;MACE,IAAAJ,UAAA,CAAaU,OAAA;QACbC,YAAY,CAAAX,UAAI,CAAAU,OAAA;MAChB;MACFV,UAAG,CAAQU,OAAA,GAAAE,UAAiB;QAC9Bb,YAAA,CAAAW,OAAA,GAAAF,IAAA,CAAAD,GAAA;QACDN,QAAA,IAAAG,IAAA;QAEDJ,UAAO,CAAAU,OAAA;MACT,GAAAd,KAAA,GAAAa,iBAAA","ignoreList":[]}
@@ -0,0 +1,40 @@
1
+ import { getCurrentComponentStack } from "@o/helpers";
2
+ import { useEffect, useId, useRef } from "react";
3
+ function useWarnIfDepsChange(deps, options) {
4
+ const {
5
+ maxChanges = 0,
6
+ name,
7
+ ignoreIndexBefore = 0
8
+ } = options;
9
+ const changeCountRef = useRef(0);
10
+ const prevDepsRef = useRef(void 0);
11
+ const id = useId();
12
+ useEffect(() => {
13
+ if (process.env.NODE_ENV === "development") {
14
+ if (prevDepsRef.current !== void 0) {
15
+ const changedDeps = [];
16
+ const compareDeps = ignoreIndexBefore ? deps.slice(ignoreIndexBefore) : deps;
17
+ compareDeps.forEach((dep, indexIn) => {
18
+ const index = indexIn + ignoreIndexBefore;
19
+ if (prevDepsRef.current && prevDepsRef.current[index] !== dep) {
20
+ changedDeps.push({
21
+ index,
22
+ prev: prevDepsRef.current[index],
23
+ next: dep
24
+ });
25
+ }
26
+ });
27
+ if (changedDeps.length > 0) {
28
+ changeCountRef.current++;
29
+ if (changeCountRef.current > maxChanges) {
30
+ console.info(`\u{1F504} useWarnIfDepsChange "${name}" is changing too often! Changed ${changeCountRef.current} times (max: ${maxChanges})`, changedDeps, `
31
+ id (${id}) at:`, getCurrentComponentStack("short"));
32
+ }
33
+ }
34
+ }
35
+ prevDepsRef.current = deps;
36
+ }
37
+ });
38
+ }
39
+ export { useWarnIfDepsChange };
40
+ //# sourceMappingURL=useWarnIfDepsChange.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getCurrentComponentStack","useEffect","useId","useRef","useWarnIfDepsChange","deps","options","maxChanges","name","ignoreIndexBefore","changeCountRef","prevDepsRef","id","process","env","NODE_ENV","current","changedDeps","compareDeps","slice","forEach","dep","indexIn","index","push","prev","next","length","console","info"],"sources":["../../src/useWarnIfDepsChange.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,wBAAA,QAAgC;AACzC,SAASC,SAAA,EAAWC,KAAA,EAAOC,MAAA,QAAc;AAQlC,SAASC,oBACdC,IAAA,EACAC,OAAA,EACM;EACN,MAAM;IAAEC,UAAA,GAAa;IAAGC,IAAA;IAAMC,iBAAA,GAAoB;EAAE,IAAIH,OAAA;EAExD,MAAMI,cAAA,GAAiBP,MAAA,CAAO,CAAC;EAC/B,MAAMQ,WAAA,GAAcR,MAAA,CAAsB,MAAS;EACnD,MAAMS,EAAA,GAAKV,KAAA,CAAM;EAEjBD,SAAA,CAAU,MAAM;IACd,IAAIY,OAAA,CAAQC,GAAA,CAAIC,QAAA,KAAa,eAAe;MAC1C,IAAIJ,WAAA,CAAYK,OAAA,KAAY,QAAW;QACrC,MAAMC,WAAA,GAID,EAAC;QAEN,MAAMC,WAAA,GAAcT,iBAAA,GAAoBJ,IAAA,CAAKc,KAAA,CAAMV,iBAAiB,IAAIJ,IAAA;QAExEa,WAAA,CAAYE,OAAA,CAAQ,CAACC,GAAA,EAAKC,OAAA,KAAY;UACpC,MAAMC,KAAA,GAAQD,OAAA,GAAUb,iBAAA;UAExB,IAAIE,WAAA,CAAYK,OAAA,IAAWL,WAAA,CAAYK,OAAA,CAAQO,KAAK,MAAMF,GAAA,EAAK;YAC7DJ,WAAA,CAAYO,IAAA,CAAK;cACfD,KAAA;cACAE,IAAA,EAAMd,WAAA,CAAYK,OAAA,CAAQO,KAAK;cAC/BG,IAAA,EAAML;YACR,CAAC;UACH;QACF,CAAC;QAED,IAAIJ,WAAA,CAAYU,MAAA,GAAS,GAAG;UAC1BjB,cAAA,CAAeM,OAAA;UAEf,IAAIN,cAAA,CAAeM,OAAA,GAAUT,UAAA,EAAY;YAEvCqB,OAAA,CAAQC,IAAA,CACN,kCAA2BrB,IAAI,oCAAoCE,cAAA,CAAeM,OAAO,gBAAgBT,UAAU,KACnHU,WAAA,EACA;AAAA,OAAUL,EAAE,SACZZ,wBAAA,CAAyB,OAAO,CAClC;UACF;QACF;MACF;MAEAW,WAAA,CAAYK,OAAA,GAAUX,IAAA;IACxB;EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,40 @@
1
+ import { getCurrentComponentStack } from "@o/helpers";
2
+ import { useEffect, useId, useRef } from "react";
3
+ function useWarnIfDepsChange(deps, options) {
4
+ var {
5
+ maxChanges = 0,
6
+ name,
7
+ ignoreIndexBefore = 0
8
+ } = options;
9
+ var changeCountRef = useRef(0);
10
+ var prevDepsRef = useRef(void 0);
11
+ var id = useId();
12
+ useEffect(function () {
13
+ if (process.env.NODE_ENV === "development") {
14
+ if (prevDepsRef.current !== void 0) {
15
+ var changedDeps = [];
16
+ var compareDeps = ignoreIndexBefore ? deps.slice(ignoreIndexBefore) : deps;
17
+ compareDeps.forEach(function (dep, indexIn) {
18
+ var index = indexIn + ignoreIndexBefore;
19
+ if (prevDepsRef.current && prevDepsRef.current[index] !== dep) {
20
+ changedDeps.push({
21
+ index,
22
+ prev: prevDepsRef.current[index],
23
+ next: dep
24
+ });
25
+ }
26
+ });
27
+ if (changedDeps.length > 0) {
28
+ changeCountRef.current++;
29
+ if (changeCountRef.current > maxChanges) {
30
+ console.info(`\u{1F504} useWarnIfDepsChange "${name}" is changing too often! Changed ${changeCountRef.current} times (max: ${maxChanges})`, changedDeps, `
31
+ id (${id}) at:`, getCurrentComponentStack("short"));
32
+ }
33
+ }
34
+ }
35
+ prevDepsRef.current = deps;
36
+ }
37
+ });
38
+ }
39
+ export { useWarnIfDepsChange };
40
+ //# sourceMappingURL=useWarnIfDepsChange.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getCurrentComponentStack","useEffect","useId","useRef","useWarnIfDepsChange","deps","options","maxChanges","name","ignoreIndexBefore","changeCountRef","prevDepsRef","id","process","env","NODE_ENV","current","changedDeps","compareDeps","slice","forEach","dep","indexIn","index","push","prev","next","length","console","info"],"sources":["../../src/useWarnIfDepsChange.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,wBAAA,QAAgC;AACzC,SAASC,SAAA,EAAWC,KAAA,EAAOC,MAAA,QAAc;AAQlC,SAASC,oBACdC,IAAA,EACAC,OAAA,EACM;EACN;IAAMC,UAAE;IAAaC,IAAG;IAAAC,iBAAM;EAAoB,IAAEH,OAAI;EAExD,IAAAI,cAAM,GAAAP,MAAiB,GAAO;EAC9B,IAAAQ,WAAM,GAAAR,MAAc,MAAsB;EAC1C,IAAAS,EAAM,GAAAV,KAAK;EAEXD,SAAA,CAAU,YAAM;IACd,IAAIY,OAAA,CAAQC,GAAA,CAAIC,QAAA,KAAa,eAAe;MAC1C,IAAIJ,WAAA,CAAYK,OAAA,KAAY,QAAW;QACrC,IAAAC,WAAM,KAID;QAEL,IAAAC,WAAM,GAAAT,iBAAc,GAAAJ,IAAoB,CAAAc,KAAK,CAAAV,iBAAM,IAAiBJ,IAAI;QAExEa,WAAA,CAAYE,OAAA,CAAQ,UAAMC,GAAA,EAAAC,OAAY;UACpC,IAAAC,KAAM,GAAAD,OAAQ,GAAAb,iBAAU;UAExB,IAAIE,WAAA,CAAYK,OAAA,IAAWL,WAAA,CAAYK,OAAA,CAAQO,KAAK,MAAMF,GAAA,EAAK;YAC7DJ,WAAA,CAAYO,IAAA,CAAK;cACfD,KAAA;cACAE,IAAA,EAAMd,WAAA,CAAYK,OAAA,CAAQO,KAAK;cAC/BG,IAAA,EAAML;YACR,CAAC;UACH;QACF,CAAC;QAED,IAAIJ,WAAA,CAAYU,MAAA,GAAS,GAAG;UAC1BjB,cAAA,CAAeM,OAAA;UAEf,IAAIN,cAAA,CAAeM,OAAA,GAAUT,UAAA,EAAY;YAEvCqB,OAAA,CAAQC,IAAA,mCAAArB,IAAA,oCAAAE,cAAA,CAAAM,OAAA,gBAAAT,UAAA,KAAAU,WAAA;AAAA,OAAAL,EAAA,OACN,EAAAZ,wBAAA,QAA2B,EAAI;UAAoF;QACnH;MACA;MAAYW,WACZ,CAAAK,OAAA,GAAAX,IAAA;IAAgC;EAClC;AACF;AACF,SAGFD,mBAAY","ignoreList":[]}
@@ -0,0 +1,18 @@
1
+ import { emptyFn } from "@o/helpers";
2
+ import { useEffect, useRef } from "react";
3
+ const useWarnIfMemoChangesOften = process.env.NODE_ENV === "production" ? emptyFn : (value, threshold = 5, name) => {
4
+ const countRef = useRef(0);
5
+ const prevValueRef = useRef(value);
6
+ useEffect(() => {
7
+ if (prevValueRef.current !== value) {
8
+ countRef.current++;
9
+ prevValueRef.current = value;
10
+ if (countRef.current > threshold) {
11
+ const warningName = name || "Memoized value";
12
+ console.warn(`\u{1F504} ${warningName} is changing too often! Changed ${countRef.current} times (threshold: ${threshold})`);
13
+ }
14
+ }
15
+ }, [value, threshold, name]);
16
+ };
17
+ export { useWarnIfMemoChangesOften };
18
+ //# sourceMappingURL=useWarnIfMemoChangesOften.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["emptyFn","useEffect","useRef","useWarnIfMemoChangesOften","process","env","NODE_ENV","value","threshold","name","countRef","prevValueRef","current","warningName","console","warn"],"sources":["../../src/useWarnIfMemoChangesOften.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAA,QAAe;AACxB,SAASC,SAAA,EAAWC,MAAA,QAAc;AAE3B,MAAMC,yBAAA,GACXC,OAAA,CAAQC,GAAA,CAAIC,QAAA,KAAa,eACpBN,OAAA,GACD,CAAIO,KAAA,EAAUC,SAAA,GAAY,GAAGC,IAAA,KAAkB;EAC7C,MAAMC,QAAA,GAAWR,MAAA,CAAO,CAAC;EACzB,MAAMS,YAAA,GAAeT,MAAA,CAAUK,KAAK;EAEpCN,SAAA,CAAU,MAAM;IACd,IAAIU,YAAA,CAAaC,OAAA,KAAYL,KAAA,EAAO;MAClCG,QAAA,CAASE,OAAA;MACTD,YAAA,CAAaC,OAAA,GAAUL,KAAA;MAEvB,IAAIG,QAAA,CAASE,OAAA,GAAUJ,SAAA,EAAW;QAChC,MAAMK,WAAA,GAAcJ,IAAA,IAAQ;QAC5BK,OAAA,CAAQC,IAAA,CACN,aAAMF,WAAW,mCAAmCH,QAAA,CAASE,OAAO,sBAAsBJ,SAAS,GACrG;MACF;IACF;EACF,GAAG,CAACD,KAAA,EAAOC,SAAA,EAAWC,IAAI,CAAC;AAC7B","ignoreList":[]}
@@ -0,0 +1,20 @@
1
+ import { emptyFn } from "@o/helpers";
2
+ import { useEffect, useRef } from "react";
3
+ var useWarnIfMemoChangesOften = process.env.NODE_ENV === "production" ? emptyFn : function (value) {
4
+ var threshold = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 5,
5
+ name = arguments.length > 2 ? arguments[2] : void 0;
6
+ var countRef = useRef(0);
7
+ var prevValueRef = useRef(value);
8
+ useEffect(function () {
9
+ if (prevValueRef.current !== value) {
10
+ countRef.current++;
11
+ prevValueRef.current = value;
12
+ if (countRef.current > threshold) {
13
+ var warningName = name || "Memoized value";
14
+ console.warn(`\u{1F504} ${warningName} is changing too often! Changed ${countRef.current} times (threshold: ${threshold})`);
15
+ }
16
+ }
17
+ }, [value, threshold, name]);
18
+ };
19
+ export { useWarnIfMemoChangesOften };
20
+ //# sourceMappingURL=useWarnIfMemoChangesOften.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["emptyFn","useEffect","useRef","useWarnIfMemoChangesOften","process","env","NODE_ENV","value","threshold","arguments","length","name","countRef","prevValueRef","current","warningName","console","warn"],"sources":["../../src/useWarnIfMemoChangesOften.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAA,QAAe;AACxB,SAASC,SAAA,EAAWC,MAAA,QAAc;AAE3B,IAAAC,yBAAM,GAAAC,OACX,CAAAC,GAAQ,CAAAC,QAAI,iBAAa,GAAAN,OACpB,aACGO,KAAU;EACZ,IAAAC,SAAM,GAAAC,SAAmB,CAAAC,MAAA,QAAAD,SAAA,iBAAAA,SAAA;IAAAE,IAAA,GAAAF,SAAA,CAAAC,MAAA,OAAAD,SAAA;EACzB,IAAAG,QAAM,GAAAV,MAAe;EAErB,IAAAW,YAAgB,GAAAX,MAAA,CAAAK,KAAA;EACdN,SAAI,aAAa;IACf,IAAAY,YAAS,CAAAC,OAAA,KAAAP,KAAA;MACTK,QAAA,CAAAE,OAAa;MAEbD,YAAI,CAASC,OAAA,GAAUP,KAAA;MACrB,IAAAK,QAAM,CAAAE,OAAA,GAAcN,SAAQ;QAC5B,IAAAO,WAAQ,GAAAJ,IAAA;QAAAK,OACN,CAAAC,IAAA,cAAiBF,WAAA,mCAA4CH,QAAO,CAAAE,OAAA,sBAA+BN,SAAA;MAAA;IACrG;EACF,GACF,CACFD,KAAI,EACNC,SAAA,E","ignoreList":[]}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@o/hooks",
3
+ "version": "0.16.19",
4
+ "sideEffects": false,
5
+ "source": "src/index.ts",
6
+ "type": "module",
7
+ "main": "dist/cjs",
8
+ "module": "dist/esm",
9
+ "types": "./src/index.ts",
10
+ "files": [
11
+ "src",
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "tamagui-build --skip-types",
16
+ "watch": "tamagui-build --skip-types --watch",
17
+ "typecheck": "tko run typecheck",
18
+ "lint": "oxlint src",
19
+ "lint:fix": "oxfmt src && oxlint --fix --fix-suggestions src",
20
+ "clean": "tamagui-build clean",
21
+ "clean:build": "tamagui-build clean:build"
22
+ },
23
+ "exports": {
24
+ "./package.json": "./package.json",
25
+ ".": {
26
+ "react-native": "./dist/esm/index.native.js",
27
+ "types": "./src/index.ts",
28
+ "import": "./dist/esm/index.mjs",
29
+ "require": "./dist/cjs/index.cjs",
30
+ "default": "./dist/cjs/index.native.js"
31
+ }
32
+ },
33
+ "dependencies": {
34
+ "@o/helpers": "0.16.19"
35
+ },
36
+ "peerDependencies": {
37
+ "react": "*",
38
+ "react-native": "*"
39
+ },
40
+ "peerDependenciesMeta": {
41
+ "react-native": {
42
+ "optional": true
43
+ }
44
+ },
45
+ "devDependencies": {
46
+ "@tamagui/build": "2.3.1",
47
+ "react": "*",
48
+ "react-native": "*"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/natew/orez.git",
56
+ "directory": "packages/hooks"
57
+ },
58
+ "optionalDependencies": null
59
+ }
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export * from './useClickOutside'
2
+ export * from './useDebouncePrepend'
3
+ export * from './useDeepMemoizedObject'
4
+ export * from './useDeferredBoolean'
5
+ export * from './useEffectOnceGlobally'
6
+ export * from './useIsMounted'
7
+ export * from './useLastValue'
8
+ export * from './useLastValueIf'
9
+ export * from './useMemoizedObjectList'
10
+ export * from './useMemoStable'
11
+ export * from './useThrottle'
12
+ export * from './useWarnIfDepsChange'
13
+ export * from './useWarnIfMemoChangesOften'
@@ -0,0 +1,34 @@
1
+ import { IS_WEB } from '@o/helpers'
2
+ import { useEffect } from 'react'
3
+
4
+ type UseClickOutsideProps = {
5
+ ref: React.RefObject<HTMLElement | null>
6
+ active: boolean
7
+ onClickOutside?: () => void
8
+ }
9
+
10
+ export const useClickOutside = ({
11
+ ref,
12
+ active,
13
+ onClickOutside,
14
+ }: UseClickOutsideProps) => {
15
+ useEffect(() => {
16
+ if (!IS_WEB) return
17
+ if (!active) return
18
+ if (!onClickOutside) return
19
+
20
+ const handleClickOutside = (e: MouseEvent) => {
21
+ const node = ref.current as HTMLElement
22
+ if (!node) return
23
+ if (!(e.target instanceof HTMLElement)) return
24
+ if (!node.contains(e.target)) {
25
+ onClickOutside()
26
+ }
27
+ }
28
+
29
+ document.addEventListener('click', handleClickOutside)
30
+ return () => {
31
+ document.removeEventListener('click', handleClickOutside)
32
+ }
33
+ }, [ref, active, onClickOutside])
34
+ }
@@ -0,0 +1,63 @@
1
+ import { debounce } from '@o/helpers'
2
+ import { useCallback, useEffect, useMemo, useState } from 'react'
3
+
4
+ export function useDebouncePrepend<T extends readonly { id: any }[]>(
5
+ list: T,
6
+ delay: number
7
+ ): T {
8
+ const [current, setCurrent] = useState(list)
9
+ const [previous, setPrevious] = useState(list)
10
+ const [pendingUpdate, setPendingUpdate] = useState<T | null>(null)
11
+
12
+ const debouncedUpdate = useMemo(() => {
13
+ return debounce((newList: T) => {
14
+ setCurrent(newList)
15
+ setPendingUpdate(null)
16
+ }, delay)
17
+ }, [delay])
18
+
19
+ const updateState = useCallback(
20
+ (newList: T) => {
21
+ setCurrent((prevCurrent) => {
22
+ // If there's a pending update, use the most recent list
23
+ const currentList = pendingUpdate || prevCurrent
24
+
25
+ // Check if we're prepending by comparing with the actual previous state
26
+ const isPrepending =
27
+ newList.length > previous.length && newList[0]?.id !== previous[0]?.id
28
+
29
+ if (isPrepending) {
30
+ // Cancel any existing debounced update
31
+ debouncedUpdate.cancel()
32
+ setPendingUpdate(newList)
33
+ debouncedUpdate(newList)
34
+ return currentList // Keep current state until debounced update fires
35
+ }
36
+
37
+ // Immediate update for non-prepending changes
38
+ debouncedUpdate.cancel()
39
+ setPendingUpdate(null)
40
+ return newList
41
+ })
42
+ },
43
+ [previous, pendingUpdate, debouncedUpdate]
44
+ )
45
+
46
+ useEffect(() => {
47
+ if (list === previous) {
48
+ return
49
+ }
50
+
51
+ // Update previous state
52
+ setPrevious(list)
53
+
54
+ // Update current state with concurrent safety
55
+ updateState(list)
56
+
57
+ return () => {
58
+ debouncedUpdate.cancel()
59
+ }
60
+ }, [list, previous, updateState, debouncedUpdate])
61
+
62
+ return current
63
+ }