@koine/react 2.0.0-beta.80 → 2.0.0-beta.83

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 (63) hide show
  1. package/FaviconTags.cjs.js +10 -3
  2. package/FaviconTags.esm.js +10 -3
  3. package/Meta.cjs.js +10 -3
  4. package/Meta.esm.js +10 -3
  5. package/NoJs.cjs.js +1 -5
  6. package/NoJs.esm.js +1 -5
  7. package/calendar.cjs.js +97 -534
  8. package/calendar.esm.js +97 -534
  9. package/classed.cjs.js +42 -39
  10. package/classed.esm.js +42 -39
  11. package/createUseMediaQueryWidth.cjs.js +15 -34
  12. package/createUseMediaQueryWidth.d.ts +1 -1
  13. package/createUseMediaQueryWidth.esm.js +15 -34
  14. package/extendComponent.cjs.js +5 -7
  15. package/extendComponent.d.ts +1 -1
  16. package/extendComponent.esm.js +5 -7
  17. package/forms/antispam.d.ts +1 -1
  18. package/forms.cjs.js +27 -27
  19. package/forms.esm.js +27 -27
  20. package/mergeRefs.cjs.js +1 -12
  21. package/mergeRefs.d.ts +1 -1
  22. package/mergeRefs.esm.js +1 -12
  23. package/package.json +3 -3
  24. package/useAsyncFn.cjs.js +4 -23
  25. package/useAsyncFn.esm.js +4 -23
  26. package/useFirstMountState.cjs.js +3 -8
  27. package/useFirstMountState.esm.js +3 -8
  28. package/useFixedOffset.cjs.js +12 -37
  29. package/useFixedOffset.esm.js +13 -38
  30. package/useFocus.cjs.js +3 -7
  31. package/useFocus.esm.js +3 -7
  32. package/useInterval.cjs.js +6 -17
  33. package/useInterval.esm.js +6 -17
  34. package/useIsomorphicLayoutEffect.cjs.js +3 -1
  35. package/useIsomorphicLayoutEffect.esm.js +3 -1
  36. package/useKeyUp.cjs.js +6 -13
  37. package/useKeyUp.esm.js +6 -13
  38. package/useMeasure.cjs.js +33 -115
  39. package/useMeasure.esm.js +33 -115
  40. package/useMountedState.cjs.js +3 -11
  41. package/useMountedState.esm.js +3 -11
  42. package/useNavigateAway.cjs.js +47 -22
  43. package/useNavigateAway.esm.js +47 -22
  44. package/usePrevious.cjs.js +1 -7
  45. package/usePrevious.esm.js +1 -7
  46. package/usePreviousRef.cjs.js +1 -7
  47. package/usePreviousRef.esm.js +1 -7
  48. package/useScrollPosition.cjs.js +7 -53
  49. package/useScrollPosition.esm.js +7 -53
  50. package/useScrollThreshold.cjs.js +4 -22
  51. package/useScrollThreshold.esm.js +4 -22
  52. package/useScrollTo.cjs.js +3 -16
  53. package/useScrollTo.esm.js +3 -16
  54. package/useSmoothScroll.cjs.js +6 -27
  55. package/useSmoothScroll.esm.js +6 -27
  56. package/useSpinDelay.cjs.js +12 -34
  57. package/useSpinDelay.esm.js +12 -34
  58. package/useTraceUpdate.cjs.js +4 -15
  59. package/useTraceUpdate.esm.js +4 -15
  60. package/useUpdateEffect.cjs.js +4 -8
  61. package/useUpdateEffect.esm.js +4 -8
  62. package/useWindowSize.cjs.js +9 -17
  63. package/useWindowSize.esm.js +9 -17
@@ -4,14 +4,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
6
 
7
- let useFirstMountState = () => {
8
- const isFirst = react.useRef(true);
9
- if (isFirst.current) {
10
- isFirst.current = false;
11
- return true;
12
- }
13
- return isFirst.current;
14
- };
7
+ /**
8
+ * @borrows [streamich/react-use](https://github.com/streamich/react-use/blob/master/src/useFirstMountState.ts)
9
+ */let useFirstMountState=()=>{let r=react.useRef(!0);return r.current?(r.current=!1,!0):r.current};
15
10
 
16
11
  exports["default"] = useFirstMountState;
17
12
  exports.useFirstMountState = useFirstMountState;
@@ -1,12 +1,7 @@
1
1
  import { useRef } from 'react';
2
2
 
3
- let useFirstMountState = () => {
4
- const isFirst = useRef(true);
5
- if (isFirst.current) {
6
- isFirst.current = false;
7
- return true;
8
- }
9
- return isFirst.current;
10
- };
3
+ /**
4
+ * @borrows [streamich/react-use](https://github.com/streamich/react-use/blob/master/src/useFirstMountState.ts)
5
+ */let useFirstMountState=()=>{let r=useRef(!0);return r.current?(r.current=!1,!0):r.current};
11
6
 
12
7
  export { useFirstMountState as default, useFirstMountState };
@@ -7,43 +7,18 @@ var utils = require('@koine/utils');
7
7
  var dom = require('@koine/dom');
8
8
  var useIsomorphicLayoutEffect = require('./useIsomorphicLayoutEffect.cjs.js');
9
9
 
10
- const inject = (value) => {
11
- dom.injectCss("useFixedOffset", `html{scroll-padding-top: ${value}px}`);
12
- };
13
- let useFixedOffset = (selector) => {
14
- const fixedOffset = react.useRef(0);
15
- useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
16
- const update = () => {
17
- const newFixedOffset = dom.calculateFixedOffset();
18
- fixedOffset.current = newFixedOffset;
19
- inject(newFixedOffset);
20
- };
21
- update();
22
- if (ResizeObserver) {
23
- const observer = new ResizeObserver((entries) => {
24
- let newFixedOffset = 0;
25
- entries.forEach((entry) => {
26
- newFixedOffset += entry.contentRect.height;
27
- });
28
- fixedOffset.current = newFixedOffset;
29
- const updateOnResize = utils.debounce(() => inject(newFixedOffset), 400, true);
30
- updateOnResize();
31
- });
32
- dom.domEach(selector || "[data-fixed]", ($el) => {
33
- if (observer)
34
- observer.observe($el);
35
- });
36
- return () => {
37
- observer?.disconnect();
38
- };
39
- }
40
- else {
41
- const listener = dom.listenResizeDebounced(0, update);
42
- return listener;
43
- }
44
- }, [selector]);
45
- return fixedOffset;
46
- };
10
+ let n=e=>{dom.injectCss("useFixedOffset",`html{scroll-padding-top: ${e}px}`);};/**
11
+ * # Use fixed offset
12
+ *
13
+ * Maybe use [ResizeObserver polyfill](https://github.com/juggle/resize-observer)
14
+ *
15
+ * @see https://web.dev/resize-observer/
16
+ *
17
+ * @param selector By default `[data-fixed]`: anyhting with the data attribute `data-fixed`
18
+ */let useFixedOffset=i=>{let l=react.useRef(0);return useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(()=>{let e=()=>{let e=dom.calculateFixedOffset();l.current=e,// inject this CSS make the hashed deeplinks position the scroll at the
19
+ // right offset
20
+ n(e);};if(e(),!ResizeObserver)return dom.listenResizeDebounced(0,e);{// const elements = domAll("[data-fixed]");
21
+ let e=new ResizeObserver(e=>{let r=0;e.forEach(e=>{r+=e.contentRect.height;}),l.current=r,utils.debounce(()=>n(r),400,!0)();});return dom.domEach(i||"[data-fixed]",t=>{e&&e.observe(t);}),()=>{e?.disconnect();}}},[i]),l};
47
22
 
48
23
  exports["default"] = useFixedOffset;
49
24
  exports.useFixedOffset = useFixedOffset;
@@ -1,44 +1,19 @@
1
1
  import { useRef } from 'react';
2
2
  import { debounce } from '@koine/utils';
3
- import { domEach, listenResizeDebounced, calculateFixedOffset, injectCss } from '@koine/dom';
3
+ import { listenResizeDebounced, domEach, calculateFixedOffset, injectCss } from '@koine/dom';
4
4
  import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect.esm.js';
5
5
 
6
- const inject = (value) => {
7
- injectCss("useFixedOffset", `html{scroll-padding-top: ${value}px}`);
8
- };
9
- let useFixedOffset = (selector) => {
10
- const fixedOffset = useRef(0);
11
- useIsomorphicLayoutEffect(() => {
12
- const update = () => {
13
- const newFixedOffset = calculateFixedOffset();
14
- fixedOffset.current = newFixedOffset;
15
- inject(newFixedOffset);
16
- };
17
- update();
18
- if (ResizeObserver) {
19
- const observer = new ResizeObserver((entries) => {
20
- let newFixedOffset = 0;
21
- entries.forEach((entry) => {
22
- newFixedOffset += entry.contentRect.height;
23
- });
24
- fixedOffset.current = newFixedOffset;
25
- const updateOnResize = debounce(() => inject(newFixedOffset), 400, true);
26
- updateOnResize();
27
- });
28
- domEach(selector || "[data-fixed]", ($el) => {
29
- if (observer)
30
- observer.observe($el);
31
- });
32
- return () => {
33
- observer?.disconnect();
34
- };
35
- }
36
- else {
37
- const listener = listenResizeDebounced(0, update);
38
- return listener;
39
- }
40
- }, [selector]);
41
- return fixedOffset;
42
- };
6
+ let n=e=>{injectCss("useFixedOffset",`html{scroll-padding-top: ${e}px}`);};/**
7
+ * # Use fixed offset
8
+ *
9
+ * Maybe use [ResizeObserver polyfill](https://github.com/juggle/resize-observer)
10
+ *
11
+ * @see https://web.dev/resize-observer/
12
+ *
13
+ * @param selector By default `[data-fixed]`: anyhting with the data attribute `data-fixed`
14
+ */let useFixedOffset=i=>{let l=useRef(0);return useIsomorphicLayoutEffect(()=>{let e=()=>{let e=calculateFixedOffset();l.current=e,// inject this CSS make the hashed deeplinks position the scroll at the
15
+ // right offset
16
+ n(e);};if(e(),!ResizeObserver)return listenResizeDebounced(0,e);{// const elements = domAll("[data-fixed]");
17
+ let e=new ResizeObserver(e=>{let r=0;e.forEach(e=>{r+=e.contentRect.height;}),l.current=r,debounce(()=>n(r),400,!0)();});return domEach(i||"[data-fixed]",t=>{e&&e.observe(t);}),()=>{e?.disconnect();}}},[i]),l};
43
18
 
44
19
  export { useFixedOffset as default, useFixedOffset };
package/useFocus.cjs.js CHANGED
@@ -4,13 +4,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
6
 
7
- let useFocus = () => {
8
- const elementRef = react.useRef(null);
9
- const setFocus = () => {
10
- elementRef.current && elementRef.current.focus();
11
- };
12
- return [elementRef, setFocus];
13
- };
7
+ /**
8
+ * @see https://stackoverflow.com/a/54159564/1938970
9
+ */let useFocus=()=>{let r=react.useRef(null);return [r,()=>{r.current&&r.current.focus();}]};
14
10
 
15
11
  exports["default"] = useFocus;
16
12
  exports.useFocus = useFocus;
package/useFocus.esm.js CHANGED
@@ -1,11 +1,7 @@
1
1
  import { useRef } from 'react';
2
2
 
3
- let useFocus = () => {
4
- const elementRef = useRef(null);
5
- const setFocus = () => {
6
- elementRef.current && elementRef.current.focus();
7
- };
8
- return [elementRef, setFocus];
9
- };
3
+ /**
4
+ * @see https://stackoverflow.com/a/54159564/1938970
5
+ */let useFocus=()=>{let r=useRef(null);return [r,()=>{r.current&&r.current.focus();}]};
10
6
 
11
7
  export { useFocus as default, useFocus };
@@ -5,23 +5,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var react = require('react');
6
6
  var utils = require('@koine/utils');
7
7
 
8
- let useInterval = (callback, delay, deps = []) => {
9
- const savedCallback = react.useRef();
10
- react.useEffect(() => {
11
- savedCallback.current = callback;
12
- }, [callback, ...deps]);
13
- react.useEffect(() => {
14
- function tick() {
15
- if (savedCallback.current)
16
- savedCallback.current();
17
- }
18
- if (delay !== null) {
19
- const id = setInterval(tick, delay);
20
- return () => clearInterval(id);
21
- }
22
- return utils.noop;
23
- }, [delay]);
24
- };
8
+ /**
9
+ * @borrows [dan abramov](https://overreacted.io/making-setinterval-declarative-with-react-hooks/)
10
+ *
11
+ * We just add `deps` array argument and typescript support
12
+ */let useInterval=(n,l,u=[])=>{let o=react.useRef();react.useEffect(()=>{o.current=n;},// eslint-disable-next-line react-hooks/exhaustive-deps
13
+ [n,...u]),react.useEffect(()=>{if(null!==l){let r=setInterval(function(){o.current&&o.current();},l);return ()=>clearInterval(r)}return utils.noop},[l]);};
25
14
 
26
15
  exports["default"] = useInterval;
27
16
  exports.useInterval = useInterval;
@@ -1,22 +1,11 @@
1
1
  import { useRef, useEffect } from 'react';
2
2
  import { noop } from '@koine/utils';
3
3
 
4
- let useInterval = (callback, delay, deps = []) => {
5
- const savedCallback = useRef();
6
- useEffect(() => {
7
- savedCallback.current = callback;
8
- }, [callback, ...deps]);
9
- useEffect(() => {
10
- function tick() {
11
- if (savedCallback.current)
12
- savedCallback.current();
13
- }
14
- if (delay !== null) {
15
- const id = setInterval(tick, delay);
16
- return () => clearInterval(id);
17
- }
18
- return noop;
19
- }, [delay]);
20
- };
4
+ /**
5
+ * @borrows [dan abramov](https://overreacted.io/making-setinterval-declarative-with-react-hooks/)
6
+ *
7
+ * We just add `deps` array argument and typescript support
8
+ */let useInterval=(n,l,u=[])=>{let o=useRef();useEffect(()=>{o.current=n;},// eslint-disable-next-line react-hooks/exhaustive-deps
9
+ [n,...u]),useEffect(()=>{if(null!==l){let r=setInterval(function(){o.current&&o.current();},l);return ()=>clearInterval(r)}return noop},[l]);};
21
10
 
22
11
  export { useInterval as default, useInterval };
@@ -5,7 +5,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var react = require('react');
6
6
  var utils = require('@koine/utils');
7
7
 
8
- let useIsomorphicLayoutEffect = utils.isBrowser ? react.useLayoutEffect : react.useEffect;
8
+ /**
9
+ * @borrows [streamich/react-use](https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts)
10
+ */let useIsomorphicLayoutEffect=utils.isBrowser?react.useLayoutEffect:react.useEffect;
9
11
 
10
12
  exports["default"] = useIsomorphicLayoutEffect;
11
13
  exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
@@ -1,6 +1,8 @@
1
1
  import { useLayoutEffect, useEffect } from 'react';
2
2
  import { isBrowser } from '@koine/utils';
3
3
 
4
- let useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
4
+ /**
5
+ * @borrows [streamich/react-use](https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts)
6
+ */let useIsomorphicLayoutEffect=isBrowser?useLayoutEffect:useEffect;
5
7
 
6
8
  export { useIsomorphicLayoutEffect as default, useIsomorphicLayoutEffect };
package/useKeyUp.cjs.js CHANGED
@@ -5,19 +5,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var react = require('react');
6
6
  var dom = require('@koine/dom');
7
7
 
8
- let useKeyUp = (callback, deps = []) => {
9
- react.useEffect(() => {
10
- const listener = dom.on(window, "keyup", (event) => {
11
- if (!event.ctrlKey &&
12
- !event.altKey &&
13
- !event.shiftKey &&
14
- !event.metaKey) {
15
- callback(event);
16
- }
17
- });
18
- return listener;
19
- }, [callback, ...deps]);
20
- };
8
+ let useKeyUp=(o,r=[])=>{react.useEffect(()=>dom.on(window,"keyup",e=>{// const { key } = event;
9
+ // be sure we do not intercept keys combinations maybe used for other
10
+ // actions like native browser navigation shortcuts
11
+ // @see https://stackoverflow.com/a/37559790/1938970
12
+ e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||o(e);}),// eslint-disable-next-line react-hooks/exhaustive-deps
13
+ [o,...r]);};
21
14
 
22
15
  exports["default"] = useKeyUp;
23
16
  exports.useKeyUp = useKeyUp;
package/useKeyUp.esm.js CHANGED
@@ -1,18 +1,11 @@
1
1
  import { useEffect } from 'react';
2
2
  import { on } from '@koine/dom';
3
3
 
4
- let useKeyUp = (callback, deps = []) => {
5
- useEffect(() => {
6
- const listener = on(window, "keyup", (event) => {
7
- if (!event.ctrlKey &&
8
- !event.altKey &&
9
- !event.shiftKey &&
10
- !event.metaKey) {
11
- callback(event);
12
- }
13
- });
14
- return listener;
15
- }, [callback, ...deps]);
16
- };
4
+ let useKeyUp=(o,r=[])=>{useEffect(()=>on(window,"keyup",e=>{// const { key } = event;
5
+ // be sure we do not intercept keys combinations maybe used for other
6
+ // actions like native browser navigation shortcuts
7
+ // @see https://stackoverflow.com/a/37559790/1938970
8
+ e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||o(e);}),// eslint-disable-next-line react-hooks/exhaustive-deps
9
+ [o,...r]);};
17
10
 
18
11
  export { useKeyUp as default, useKeyUp };
package/useMeasure.cjs.js CHANGED
@@ -6,121 +6,39 @@ var react = require('react');
6
6
  var utils = require('@koine/utils');
7
7
  var dom = require('@koine/dom');
8
8
 
9
- let observer;
10
- let findScrollContainers = (element) => {
11
- const result = [];
12
- if (!element || element === document.body)
13
- return result;
14
- const { overflow, overflowX, overflowY } = window.getComputedStyle(element);
15
- if ([overflow, overflowX, overflowY].some((prop) => prop === "auto" || prop === "scroll"))
16
- result.push(element);
17
- return [...result, ...findScrollContainers(element.parentElement)];
18
- };
19
- const keys = [
20
- "x",
21
- "y",
22
- "top",
23
- "bottom",
24
- "left",
25
- "right",
26
- "width",
27
- "height",
28
- ];
29
- const areBoundsEqual = (a, b) => keys.every((key) => a[key] === b[key]);
30
- let useMeasure = (options) => {
31
- const { scroll = false } = options || {};
32
- const [bounds, setBounds] = react.useState({
33
- left: 0,
34
- top: 0,
35
- width: 0,
36
- height: 0,
37
- bottom: 0,
38
- right: 0,
39
- x: 0,
40
- y: 0,
41
- });
42
- const state = react.useRef([
43
- null,
44
- null,
45
- null,
46
- bounds,
47
- ]);
48
- const mounted = react.useRef(false);
49
- react.useEffect(() => {
50
- mounted.current = true;
51
- return () => void (mounted.current = false);
52
- }, []);
53
- const [forceRefresh, , scrollChange] = react.useMemo(() => {
54
- const callback = (..._args) => {
55
- const [element, , , lastBounds] = state.current;
56
- if (!element)
57
- return;
58
- const size = element.getBoundingClientRect();
59
- Object.freeze(size);
60
- if (mounted.current && !areBoundsEqual(lastBounds, size)) {
61
- state.current[3] = size;
62
- setBounds(size);
63
- }
64
- };
65
- const debouncedCallback = utils.debounce(callback);
66
- return [callback, debouncedCallback, debouncedCallback];
67
- }, [setBounds]);
68
- function removeListeners() {
69
- const [, scrollContainers, resizeObserver] = state.current;
70
- if (scrollContainers) {
71
- scrollContainers.forEach((element) => dom.off(element, "scroll", scrollChange));
72
- state.current[1] = null;
73
- }
74
- if (resizeObserver) {
75
- resizeObserver.disconnect();
76
- state.current[2] = null;
77
- }
78
- }
79
- function addListeners() {
80
- const [element, scrollContainers] = state.current;
81
- if (!element)
82
- return;
83
- if (!observer && ResizeObserver) {
84
- observer = new ResizeObserver(scrollChange);
85
- state.current[2] = observer;
86
- observer.observe(element);
87
- if (scroll && scrollContainers) {
88
- scrollContainers.forEach((scrollContainer) => dom.on(scrollContainer, "scroll", scrollChange, {
89
- capture: true,
90
- passive: true,
91
- }));
92
- }
93
- }
94
- }
95
- const ref = (node) => {
96
- if (!node || node === state.current[0])
97
- return;
98
- removeListeners();
99
- state.current[0] = node;
100
- state.current[1] = findScrollContainers(node);
101
- addListeners();
102
- };
103
- react.useEffect(() => {
104
- if (scroll) {
105
- const listener = dom.listenScrollDebounced(0, forceRefresh, 100);
106
- return listener;
107
- }
108
- return utils.noop;
109
- }, [scroll, forceRefresh]);
110
- react.useEffect(() => {
111
- const listener = dom.listenResizeDebounced(0, forceRefresh, 100);
112
- return listener;
113
- }, [forceRefresh]);
114
- react.useEffect(() => {
115
- removeListeners();
116
- addListeners();
117
- }, [scroll]);
118
- react.useEffect(() => {
119
- forceRefresh();
120
- return removeListeners;
121
- }, []);
122
- return [ref, bounds, forceRefresh];
123
- };
9
+ let e;let m=e=>{let t=[];if(!e||e===document.body)return t;let{overflow:r,overflowX:n,overflowY:u}=window.getComputedStyle(e);return [r,n,u].some(e=>"auto"===e||"scroll"===e)&&t.push(e),[...t,...m(e.parentElement)]},p=["x","y","top","bottom","left","right","width","height"],d=(e,t)=>p.every(r=>e[r]===t[r]);// offsetSize?: boolean;
10
+ /**
11
+ * Use measure hook
12
+ *
13
+ * @borrows [pmndrs/react-use-measure](https://github.com/pmndrs/react-use-measure)
14
+ */let useMeasure=p=>{let{scroll:h=!1}=/* offsetSize = false */p||{},[a,b]=react.useState({left:0,top:0,width:0,height:0,bottom:0,right:0,x:0,y:0}),// keep all state in a ref
15
+ g=react.useRef([// element
16
+ null,// scrollContainers
17
+ null,// resizeObserver
18
+ null,// lastBounds
19
+ a]),// make sure to update state only as long as the component is truly mounted
20
+ v=react.useRef(!1);react.useEffect(()=>(v.current=!0,()=>void(v.current=!1)),[]);// memoize handlers, so event-listeners know when they should update
21
+ let[w,,/* resizeChange */y]=react.useMemo(()=>{let e=(...e)=>{let[t,,,r]=g.current;if(!t)return;let n=t.getBoundingClientRect();// if (element instanceof HTMLElement && offsetSize) {
22
+ // size.height = element.offsetHeight;
23
+ // size.width = element.offsetWidth;
24
+ // }
25
+ Object.freeze(n),v.current&&!d(r,n)&&(g.current[3]=n,b(n));},t=utils.debounce(e);return [e,t,t]},[b]);/* , offsetSize */// cleanup current scroll-listeners / observers
26
+ function x(){let[,e,t]=g.current;e&&(e.forEach(e=>dom.off(e,"scroll",y)),g.current[1]=null),t&&(t.disconnect(),g.current[2]=null);}// add scroll-listeners / observers
27
+ function z(){let[t,r]=g.current;t&&!e&&ResizeObserver&&(e=new ResizeObserver(y),g.current[2]=e,e.observe(t),h&&r&&r.forEach(e=>dom.on(e,"scroll",y,{capture:!0,passive:!0})));}return(// add general event listeners
28
+ // useOnWindowScroll(forceRefresh, Boolean(scroll));
29
+ // useOnWindowResize(() => {
30
+ // debugger;
31
+ // forceRefresh();
32
+ // });
33
+ react.useEffect(()=>h?dom.listenScrollDebounced(0,w,100):utils.noop,[h,w]),react.useEffect(()=>// const listener = listenResizeDebounced(onWindowResize);
34
+ // return listener;
35
+ dom.listenResizeDebounced(0,w,100),[w]),// respond to changes that are relevant for the listeners
36
+ react.useEffect(()=>{x(),z();},// eslint-disable-next-line react-hooks/exhaustive-deps
37
+ [h]),/* , scrollChange, resizeChange */react.useEffect(()=>(// operate on mount, @kuus on the original version there is no call on mount?
38
+ w(),// remove all listeners when the components unmounts
39
+ x),// eslint-disable-next-line react-hooks/exhaustive-deps
40
+ []),[// the ref we expose to the user
41
+ e=>{e&&e!==g.current[0]&&(x(),g.current[0]=e,g.current[1]=m(e),z());},a,w])};
124
42
 
125
43
  exports["default"] = useMeasure;
126
44
  exports.useMeasure = useMeasure;
package/useMeasure.esm.js CHANGED
@@ -2,120 +2,38 @@ import { useState, useRef, useEffect, useMemo } from 'react';
2
2
  import { debounce, noop } from '@koine/utils';
3
3
  import { listenScrollDebounced, listenResizeDebounced, off, on } from '@koine/dom';
4
4
 
5
- let observer;
6
- let findScrollContainers = (element) => {
7
- const result = [];
8
- if (!element || element === document.body)
9
- return result;
10
- const { overflow, overflowX, overflowY } = window.getComputedStyle(element);
11
- if ([overflow, overflowX, overflowY].some((prop) => prop === "auto" || prop === "scroll"))
12
- result.push(element);
13
- return [...result, ...findScrollContainers(element.parentElement)];
14
- };
15
- const keys = [
16
- "x",
17
- "y",
18
- "top",
19
- "bottom",
20
- "left",
21
- "right",
22
- "width",
23
- "height",
24
- ];
25
- const areBoundsEqual = (a, b) => keys.every((key) => a[key] === b[key]);
26
- let useMeasure = (options) => {
27
- const { scroll = false } = options || {};
28
- const [bounds, setBounds] = useState({
29
- left: 0,
30
- top: 0,
31
- width: 0,
32
- height: 0,
33
- bottom: 0,
34
- right: 0,
35
- x: 0,
36
- y: 0,
37
- });
38
- const state = useRef([
39
- null,
40
- null,
41
- null,
42
- bounds,
43
- ]);
44
- const mounted = useRef(false);
45
- useEffect(() => {
46
- mounted.current = true;
47
- return () => void (mounted.current = false);
48
- }, []);
49
- const [forceRefresh, , scrollChange] = useMemo(() => {
50
- const callback = (..._args) => {
51
- const [element, , , lastBounds] = state.current;
52
- if (!element)
53
- return;
54
- const size = element.getBoundingClientRect();
55
- Object.freeze(size);
56
- if (mounted.current && !areBoundsEqual(lastBounds, size)) {
57
- state.current[3] = size;
58
- setBounds(size);
59
- }
60
- };
61
- const debouncedCallback = debounce(callback);
62
- return [callback, debouncedCallback, debouncedCallback];
63
- }, [setBounds]);
64
- function removeListeners() {
65
- const [, scrollContainers, resizeObserver] = state.current;
66
- if (scrollContainers) {
67
- scrollContainers.forEach((element) => off(element, "scroll", scrollChange));
68
- state.current[1] = null;
69
- }
70
- if (resizeObserver) {
71
- resizeObserver.disconnect();
72
- state.current[2] = null;
73
- }
74
- }
75
- function addListeners() {
76
- const [element, scrollContainers] = state.current;
77
- if (!element)
78
- return;
79
- if (!observer && ResizeObserver) {
80
- observer = new ResizeObserver(scrollChange);
81
- state.current[2] = observer;
82
- observer.observe(element);
83
- if (scroll && scrollContainers) {
84
- scrollContainers.forEach((scrollContainer) => on(scrollContainer, "scroll", scrollChange, {
85
- capture: true,
86
- passive: true,
87
- }));
88
- }
89
- }
90
- }
91
- const ref = (node) => {
92
- if (!node || node === state.current[0])
93
- return;
94
- removeListeners();
95
- state.current[0] = node;
96
- state.current[1] = findScrollContainers(node);
97
- addListeners();
98
- };
99
- useEffect(() => {
100
- if (scroll) {
101
- const listener = listenScrollDebounced(0, forceRefresh, 100);
102
- return listener;
103
- }
104
- return noop;
105
- }, [scroll, forceRefresh]);
106
- useEffect(() => {
107
- const listener = listenResizeDebounced(0, forceRefresh, 100);
108
- return listener;
109
- }, [forceRefresh]);
110
- useEffect(() => {
111
- removeListeners();
112
- addListeners();
113
- }, [scroll]);
114
- useEffect(() => {
115
- forceRefresh();
116
- return removeListeners;
117
- }, []);
118
- return [ref, bounds, forceRefresh];
119
- };
5
+ let e;let m=e=>{let t=[];if(!e||e===document.body)return t;let{overflow:r,overflowX:n,overflowY:u}=window.getComputedStyle(e);return [r,n,u].some(e=>"auto"===e||"scroll"===e)&&t.push(e),[...t,...m(e.parentElement)]},p=["x","y","top","bottom","left","right","width","height"],d=(e,t)=>p.every(r=>e[r]===t[r]);// offsetSize?: boolean;
6
+ /**
7
+ * Use measure hook
8
+ *
9
+ * @borrows [pmndrs/react-use-measure](https://github.com/pmndrs/react-use-measure)
10
+ */let useMeasure=p=>{let{scroll:h=!1}=/* offsetSize = false */p||{},[a,b]=useState({left:0,top:0,width:0,height:0,bottom:0,right:0,x:0,y:0}),// keep all state in a ref
11
+ g=useRef([// element
12
+ null,// scrollContainers
13
+ null,// resizeObserver
14
+ null,// lastBounds
15
+ a]),// make sure to update state only as long as the component is truly mounted
16
+ v=useRef(!1);useEffect(()=>(v.current=!0,()=>void(v.current=!1)),[]);// memoize handlers, so event-listeners know when they should update
17
+ let[w,,/* resizeChange */y]=useMemo(()=>{let e=(...e)=>{let[t,,,r]=g.current;if(!t)return;let n=t.getBoundingClientRect();// if (element instanceof HTMLElement && offsetSize) {
18
+ // size.height = element.offsetHeight;
19
+ // size.width = element.offsetWidth;
20
+ // }
21
+ Object.freeze(n),v.current&&!d(r,n)&&(g.current[3]=n,b(n));},t=debounce(e);return [e,t,t]},[b]);/* , offsetSize */// cleanup current scroll-listeners / observers
22
+ function x(){let[,e,t]=g.current;e&&(e.forEach(e=>off(e,"scroll",y)),g.current[1]=null),t&&(t.disconnect(),g.current[2]=null);}// add scroll-listeners / observers
23
+ function z(){let[t,r]=g.current;t&&!e&&ResizeObserver&&(e=new ResizeObserver(y),g.current[2]=e,e.observe(t),h&&r&&r.forEach(e=>on(e,"scroll",y,{capture:!0,passive:!0})));}return(// add general event listeners
24
+ // useOnWindowScroll(forceRefresh, Boolean(scroll));
25
+ // useOnWindowResize(() => {
26
+ // debugger;
27
+ // forceRefresh();
28
+ // });
29
+ useEffect(()=>h?listenScrollDebounced(0,w,100):noop,[h,w]),useEffect(()=>// const listener = listenResizeDebounced(onWindowResize);
30
+ // return listener;
31
+ listenResizeDebounced(0,w,100),[w]),// respond to changes that are relevant for the listeners
32
+ useEffect(()=>{x(),z();},// eslint-disable-next-line react-hooks/exhaustive-deps
33
+ [h]),/* , scrollChange, resizeChange */useEffect(()=>(// operate on mount, @kuus on the original version there is no call on mount?
34
+ w(),// remove all listeners when the components unmounts
35
+ x),// eslint-disable-next-line react-hooks/exhaustive-deps
36
+ []),[// the ref we expose to the user
37
+ e=>{e&&e!==g.current[0]&&(x(),g.current[0]=e,g.current[1]=m(e),z());},a,w])};
120
38
 
121
39
  export { useMeasure as default, useMeasure };