@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.
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/cjs/index.cjs +32 -0
- package/dist/cjs/index.native.js +35 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/useClickOutside.cjs +52 -0
- package/dist/cjs/useClickOutside.native.js +63 -0
- package/dist/cjs/useClickOutside.native.js.map +1 -0
- package/dist/cjs/useDebouncePrepend.cjs +66 -0
- package/dist/cjs/useDebouncePrepend.native.js +70 -0
- package/dist/cjs/useDebouncePrepend.native.js.map +1 -0
- package/dist/cjs/useDeepMemoizedObject.cjs +207 -0
- package/dist/cjs/useDeepMemoizedObject.native.js +258 -0
- package/dist/cjs/useDeepMemoizedObject.native.js.map +1 -0
- package/dist/cjs/useDeepMemoizedObject.test.cjs +321 -0
- package/dist/cjs/useDeepMemoizedObject.test.native.js +324 -0
- package/dist/cjs/useDeepMemoizedObject.test.native.js.map +1 -0
- package/dist/cjs/useDeferredBoolean.cjs +39 -0
- package/dist/cjs/useDeferredBoolean.native.js +42 -0
- package/dist/cjs/useDeferredBoolean.native.js.map +1 -0
- package/dist/cjs/useEffectOnceGlobally.cjs +45 -0
- package/dist/cjs/useEffectOnceGlobally.native.js +50 -0
- package/dist/cjs/useEffectOnceGlobally.native.js.map +1 -0
- package/dist/cjs/useEvent.cjs +33 -0
- package/dist/cjs/useEvent.native.js +41 -0
- package/dist/cjs/useEvent.native.js.map +1 -0
- package/dist/cjs/useIsMounted.cjs +35 -0
- package/dist/cjs/useIsMounted.native.js +38 -0
- package/dist/cjs/useIsMounted.native.js.map +1 -0
- package/dist/cjs/useLastValue.cjs +31 -0
- package/dist/cjs/useLastValue.native.js +34 -0
- package/dist/cjs/useLastValue.native.js.map +1 -0
- package/dist/cjs/useLastValueIf.cjs +38 -0
- package/dist/cjs/useLastValueIf.native.js +42 -0
- package/dist/cjs/useLastValueIf.native.js.map +1 -0
- package/dist/cjs/useMemoStable.cjs +35 -0
- package/dist/cjs/useMemoStable.native.js +39 -0
- package/dist/cjs/useMemoStable.native.js.map +1 -0
- package/dist/cjs/useMemoizedObjectList.cjs +64 -0
- package/dist/cjs/useMemoizedObjectList.native.js +86 -0
- package/dist/cjs/useMemoizedObjectList.native.js.map +1 -0
- package/dist/cjs/useThrottle.cjs +52 -0
- package/dist/cjs/useThrottle.native.js +59 -0
- package/dist/cjs/useThrottle.native.js.map +1 -0
- package/dist/cjs/useWarnIfDepsChange.cjs +65 -0
- package/dist/cjs/useWarnIfDepsChange.native.js +68 -0
- package/dist/cjs/useWarnIfDepsChange.native.js.map +1 -0
- package/dist/cjs/useWarnIfMemoChangesOften.cjs +43 -0
- package/dist/cjs/useWarnIfMemoChangesOften.native.js +48 -0
- package/dist/cjs/useWarnIfMemoChangesOften.native.js.map +1 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index.mjs +14 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/index.native.js +14 -0
- package/dist/esm/index.native.js.map +1 -0
- package/dist/esm/useClickOutside.mjs +27 -0
- package/dist/esm/useClickOutside.mjs.map +1 -0
- package/dist/esm/useClickOutside.native.js +35 -0
- package/dist/esm/useClickOutside.native.js.map +1 -0
- package/dist/esm/useDebouncePrepend.mjs +41 -0
- package/dist/esm/useDebouncePrepend.mjs.map +1 -0
- package/dist/esm/useDebouncePrepend.native.js +42 -0
- package/dist/esm/useDebouncePrepend.native.js.map +1 -0
- package/dist/esm/useDeepMemoizedObject.mjs +180 -0
- package/dist/esm/useDeepMemoizedObject.mjs.map +1 -0
- package/dist/esm/useDeepMemoizedObject.native.js +228 -0
- package/dist/esm/useDeepMemoizedObject.native.js.map +1 -0
- package/dist/esm/useDeepMemoizedObject.test.mjs +322 -0
- package/dist/esm/useDeepMemoizedObject.test.mjs.map +1 -0
- package/dist/esm/useDeepMemoizedObject.test.native.js +322 -0
- package/dist/esm/useDeepMemoizedObject.test.native.js.map +1 -0
- package/dist/esm/useDeferredBoolean.mjs +14 -0
- package/dist/esm/useDeferredBoolean.mjs.map +1 -0
- package/dist/esm/useDeferredBoolean.native.js +14 -0
- package/dist/esm/useDeferredBoolean.native.js.map +1 -0
- package/dist/esm/useEffectOnceGlobally.mjs +20 -0
- package/dist/esm/useEffectOnceGlobally.mjs.map +1 -0
- package/dist/esm/useEffectOnceGlobally.native.js +22 -0
- package/dist/esm/useEffectOnceGlobally.native.js.map +1 -0
- package/dist/esm/useEvent.mjs +8 -0
- package/dist/esm/useEvent.mjs.map +1 -0
- package/dist/esm/useEvent.native.js +13 -0
- package/dist/esm/useEvent.native.js.map +1 -0
- package/dist/esm/useIsMounted.mjs +10 -0
- package/dist/esm/useIsMounted.mjs.map +1 -0
- package/dist/esm/useIsMounted.native.js +10 -0
- package/dist/esm/useIsMounted.native.js.map +1 -0
- package/dist/esm/useLastValue.mjs +6 -0
- package/dist/esm/useLastValue.mjs.map +1 -0
- package/dist/esm/useLastValue.native.js +6 -0
- package/dist/esm/useLastValue.native.js.map +1 -0
- package/dist/esm/useLastValueIf.mjs +13 -0
- package/dist/esm/useLastValueIf.mjs.map +1 -0
- package/dist/esm/useLastValueIf.native.js +14 -0
- package/dist/esm/useLastValueIf.native.js.map +1 -0
- package/dist/esm/useMemoStable.mjs +10 -0
- package/dist/esm/useMemoStable.mjs.map +1 -0
- package/dist/esm/useMemoStable.native.js +11 -0
- package/dist/esm/useMemoStable.native.js.map +1 -0
- package/dist/esm/useMemoizedObjectList.mjs +39 -0
- package/dist/esm/useMemoizedObjectList.mjs.map +1 -0
- package/dist/esm/useMemoizedObjectList.native.js +58 -0
- package/dist/esm/useMemoizedObjectList.native.js.map +1 -0
- package/dist/esm/useThrottle.mjs +27 -0
- package/dist/esm/useThrottle.mjs.map +1 -0
- package/dist/esm/useThrottle.native.js +31 -0
- package/dist/esm/useThrottle.native.js.map +1 -0
- package/dist/esm/useWarnIfDepsChange.mjs +40 -0
- package/dist/esm/useWarnIfDepsChange.mjs.map +1 -0
- package/dist/esm/useWarnIfDepsChange.native.js +40 -0
- package/dist/esm/useWarnIfDepsChange.native.js.map +1 -0
- package/dist/esm/useWarnIfMemoChangesOften.mjs +18 -0
- package/dist/esm/useWarnIfMemoChangesOften.mjs.map +1 -0
- package/dist/esm/useWarnIfMemoChangesOften.native.js +20 -0
- package/dist/esm/useWarnIfMemoChangesOften.native.js.map +1 -0
- package/package.json +59 -0
- package/src/index.ts +13 -0
- package/src/useClickOutside.ts +34 -0
- package/src/useDebouncePrepend.ts +63 -0
- package/src/useDeepMemoizedObject.test.ts +344 -0
- package/src/useDeepMemoizedObject.ts +231 -0
- package/src/useDeferredBoolean.tsx +15 -0
- package/src/useEffectOnceGlobally.ts +41 -0
- package/src/useEvent.ts +7 -0
- package/src/useIsMounted.ts +11 -0
- package/src/useLastValue.ts +5 -0
- package/src/useLastValueIf.ts +15 -0
- package/src/useMemoStable.ts +25 -0
- package/src/useMemoizedObjectList.ts +74 -0
- package/src/useThrottle.ts +36 -0
- package/src/useWarnIfDepsChange.ts +61 -0
- 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
|
+
}
|