@koine/react 2.0.0-beta.73 → 2.0.0-beta.75

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.d.ts +9 -0
  2. package/FaviconTags.js +5 -0
  3. package/Meta.d.ts +5 -0
  4. package/Meta.js +5 -0
  5. package/NoJs.d.ts +3 -0
  6. package/NoJs.js +7 -0
  7. package/Polymorphic.d.ts +26 -0
  8. package/Polymorphic.js +1 -0
  9. package/classed.d.ts +8 -0
  10. package/classed.js +41 -0
  11. package/createUseMediaQueryWidth.d.ts +6 -0
  12. package/createUseMediaQueryWidth.js +38 -0
  13. package/extendComponent.d.ts +16 -0
  14. package/extendComponent.js +9 -0
  15. package/index.cjs.js +33 -23
  16. package/index.d.ts +28 -3
  17. package/index.esm.js +33 -26
  18. package/index.js +26 -3
  19. package/mergeRefs.d.ts +2 -0
  20. package/mergeRefs.js +13 -0
  21. package/package.json +245 -5
  22. package/useAsyncFn.d.ts +24 -0
  23. package/useAsyncFn.js +26 -0
  24. package/useFirstMountState.d.ts +2 -0
  25. package/useFirstMountState.js +10 -0
  26. package/useFixedOffset.d.ts +2 -0
  27. package/useFixedOffset.js +42 -0
  28. package/useFocus.d.ts +2 -0
  29. package/useFocus.js +9 -0
  30. package/useInterval.d.ts +2 -0
  31. package/useInterval.js +20 -0
  32. package/useIsomorphicLayoutEffect.d.ts +3 -0
  33. package/useIsomorphicLayoutEffect.js +4 -0
  34. package/useKeyUp.d.ts +2 -0
  35. package/useKeyUp.js +16 -0
  36. package/useMeasure.d.ts +22 -0
  37. package/useMeasure.js +119 -0
  38. package/useMountedState.d.ts +2 -0
  39. package/useMountedState.js +13 -0
  40. package/useNavigateAway.d.ts +3 -0
  41. package/useNavigateAway.js +25 -0
  42. package/usePrevious.d.ts +2 -0
  43. package/usePrevious.js +9 -0
  44. package/usePreviousRef.d.ts +2 -0
  45. package/usePreviousRef.js +9 -0
  46. package/useReveal.d.ts +13 -0
  47. package/useReveal.js +42 -0
  48. package/useScrollPosition.d.ts +7 -0
  49. package/useScrollPosition.js +58 -0
  50. package/useScrollThreshold.d.ts +2 -0
  51. package/useScrollThreshold.js +26 -0
  52. package/useScrollTo.d.ts +2 -0
  53. package/useScrollTo.js +18 -0
  54. package/useSmoothScroll.d.ts +2 -0
  55. package/useSmoothScroll.js +32 -0
  56. package/useSpinDelay.d.ts +2 -0
  57. package/useSpinDelay.js +36 -0
  58. package/useTraceUpdate.d.ts +2 -0
  59. package/useTraceUpdate.js +17 -0
  60. package/useUpdateEffect.d.ts +3 -0
  61. package/useUpdateEffect.js +11 -0
  62. package/useWindowSize.d.ts +3 -0
  63. package/useWindowSize.js +20 -0
@@ -0,0 +1,9 @@
1
+ import { useEffect, useRef } from "react";
2
+ export let usePreviousRef = (value) => {
3
+ const ref = useRef();
4
+ useEffect(() => {
5
+ ref.current = value;
6
+ });
7
+ return ref.current;
8
+ };
9
+ export default usePreviousRef;
package/useReveal.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export type UseRevealOptions = {
2
+ direction?: "left" | "right";
3
+ offsetStartY?: number;
4
+ offsetEndY?: number;
5
+ offsetStartX?: number | "all";
6
+ };
7
+ export declare let useReveal: <T extends HTMLElement = HTMLDivElement>({ direction, offsetStartY, offsetEndY, offsetStartX, }: UseRevealOptions) => {
8
+ ref: import("react").RefObject<T>;
9
+ startY: number;
10
+ endY: number;
11
+ startX: number;
12
+ };
13
+ export default useReveal;
package/useReveal.js ADDED
@@ -0,0 +1,42 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ export let useReveal = ({ direction = "left", offsetStartY = -2, offsetEndY = 0, offsetStartX = "all", }) => {
3
+ const ref = useRef(null);
4
+ const [startY, setStartY] = useState(0);
5
+ const [endY, setEndY] = useState(0);
6
+ const [startX, setStartX] = useState(0);
7
+ useEffect(() => {
8
+ if (!ref.current) {
9
+ return;
10
+ }
11
+ const rect = ref.current.getBoundingClientRect();
12
+ const scrollTop = window.scrollY || document.documentElement.scrollTop;
13
+ const elementHeight = rect.height;
14
+ const elementTop = rect.top;
15
+ const distanceTop = elementTop + scrollTop;
16
+ const offsetTop = offsetStartY ? elementHeight * offsetStartY : 0;
17
+ const offsetBottom = offsetEndY ? elementHeight * offsetEndY : offsetTop;
18
+ const startY = (distanceTop + offsetTop) / document.body.clientHeight;
19
+ const endY = (distanceTop + elementHeight + offsetBottom) / document.body.clientHeight;
20
+ let startX;
21
+ if (offsetStartX === "all") {
22
+ startX = direction === "left" ? -rect.right : rect.left;
23
+ }
24
+ else {
25
+ startX = rect.width * offsetStartX;
26
+ startX = direction === "left" ? -startX : startX;
27
+ }
28
+ setStartY(startY);
29
+ setEndY(endY);
30
+ setStartX(startX);
31
+ }, [
32
+ setStartY,
33
+ setEndY,
34
+ setStartX,
35
+ offsetStartY,
36
+ offsetEndY,
37
+ offsetStartX,
38
+ direction,
39
+ ]);
40
+ return { ref, startY, endY, startX };
41
+ };
42
+ export default useReveal;
@@ -0,0 +1,7 @@
1
+ type Position = {
2
+ x: number;
3
+ y: number;
4
+ };
5
+ type ElementRef = React.MutableRefObject<HTMLElement | undefined>;
6
+ export declare let useScrollPosition: (effect: (currentPosition: Position, prevPosition: Position) => void, deps?: import("react").DependencyList, element?: ElementRef, boundingElement?: ElementRef, wait?: number) => void;
7
+ export default useScrollPosition;
@@ -0,0 +1,58 @@
1
+ import { useRef } from "react";
2
+ import { isBrowser } from "@koine/utils";
3
+ import { listenScroll } from "@koine/dom";
4
+ import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
5
+ const zeroPosition = { x: 0, y: 0 };
6
+ const getClientRect = (element) => element?.getBoundingClientRect();
7
+ const getScrollPosition = (element, boundingElement) => {
8
+ if (!isBrowser) {
9
+ return zeroPosition;
10
+ }
11
+ if (!boundingElement) {
12
+ return { x: window.scrollX, y: window.scrollY };
13
+ }
14
+ const targetPosition = getClientRect(element?.current || document.body);
15
+ const containerPosition = getClientRect(boundingElement.current);
16
+ if (!targetPosition) {
17
+ return zeroPosition;
18
+ }
19
+ return containerPosition
20
+ ? {
21
+ x: (containerPosition.x || 0) - (targetPosition.x || 0),
22
+ y: (containerPosition.y || 0) - (targetPosition.y || 0),
23
+ }
24
+ : { x: targetPosition.left, y: targetPosition.top };
25
+ };
26
+ export let useScrollPosition = (effect, deps = [], element, boundingElement, wait) => {
27
+ const position = useRef(getScrollPosition(null, boundingElement));
28
+ let throttleTimeout = null;
29
+ const callBack = () => {
30
+ const current = getScrollPosition(element, boundingElement);
31
+ effect(current, position.current);
32
+ position.current = current;
33
+ throttleTimeout = null;
34
+ };
35
+ useIsomorphicLayoutEffect(() => {
36
+ if (!isBrowser) {
37
+ return undefined;
38
+ }
39
+ const handleScroll = () => {
40
+ if (wait) {
41
+ if (throttleTimeout === null) {
42
+ throttleTimeout = window.setTimeout(callBack, wait);
43
+ }
44
+ }
45
+ else {
46
+ callBack();
47
+ }
48
+ };
49
+ const listener = listenScroll(handleScroll, boundingElement?.current);
50
+ return () => {
51
+ listener();
52
+ if (throttleTimeout) {
53
+ clearTimeout(throttleTimeout);
54
+ }
55
+ };
56
+ }, deps);
57
+ };
58
+ export default useScrollPosition;
@@ -0,0 +1,2 @@
1
+ export declare let useScrollThreshold: (threshold?: number, callback?: ((isAbove: boolean, isBelow: boolean) => void) | undefined) => boolean;
2
+ export default useScrollThreshold;
@@ -0,0 +1,26 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { noop } from "@koine/utils";
3
+ import { listenScroll } from "@koine/dom";
4
+ export let useScrollThreshold = (threshold, callback) => {
5
+ const [isBelow, setIsBelow] = useState(false);
6
+ const handler = useCallback(() => {
7
+ if (threshold) {
8
+ const posY = window.scrollY;
9
+ const isAbove = posY < threshold;
10
+ const isBelow = posY > threshold;
11
+ setIsBelow(isBelow);
12
+ if (callback)
13
+ callback(isAbove, isBelow);
14
+ }
15
+ }, [threshold, callback]);
16
+ useEffect(() => {
17
+ if (threshold) {
18
+ const listener = listenScroll(handler);
19
+ handler();
20
+ return listener;
21
+ }
22
+ return noop;
23
+ }, [threshold, handler]);
24
+ return isBelow;
25
+ };
26
+ export default useScrollThreshold;
@@ -0,0 +1,2 @@
1
+ export declare let useScrollTo: (id?: string, offset?: number) => void;
2
+ export default useScrollTo;
package/useScrollTo.js ADDED
@@ -0,0 +1,18 @@
1
+ import { isBrowser } from "@koine/utils";
2
+ export let useScrollTo = (id = "", offset = 0) => {
3
+ if (!isBrowser) {
4
+ return;
5
+ }
6
+ const headerOffset = 0;
7
+ let element = document.getElementById(id);
8
+ let top = 0;
9
+ if (element && element.offsetParent) {
10
+ do {
11
+ top += element.offsetTop;
12
+ } while ((element = element.offsetParent));
13
+ }
14
+ top -= offset;
15
+ top -= headerOffset;
16
+ window.scroll(0, top);
17
+ };
18
+ export default useScrollTo;
@@ -0,0 +1,2 @@
1
+ export declare let useSmoothScroll: (disregardAutomaticFixedOffset?: boolean) => (to?: number | string, customOffset?: number, callback?: () => void, fallbackTimeout?: number, behavior?: ScrollBehavior) => void;
2
+ export default useSmoothScroll;
@@ -0,0 +1,32 @@
1
+ import { useCallback } from "react";
2
+ import { isNumber } from "@koine/utils";
3
+ import { getOffsetTopSlim, scrollTo } from "@koine/dom";
4
+ import { useFixedOffset } from "./useFixedOffset";
5
+ export let useSmoothScroll = (disregardAutomaticFixedOffset) => {
6
+ const fixedOffset = useFixedOffset();
7
+ const scroll = useCallback((to, customOffset, callback, fallbackTimeout, behavior) => {
8
+ let top = undefined;
9
+ let toIsElement = false;
10
+ if (isNumber(to)) {
11
+ top = to;
12
+ }
13
+ else if (to) {
14
+ const el = document.getElementById(to);
15
+ if (el) {
16
+ top = getOffsetTopSlim(el) - fixedOffset.current;
17
+ toIsElement = true;
18
+ }
19
+ }
20
+ if (isNumber(top)) {
21
+ top =
22
+ top +
23
+ (customOffset || 0) +
24
+ (disregardAutomaticFixedOffset || toIsElement
25
+ ? 0
26
+ : fixedOffset.current);
27
+ scrollTo(top, callback, fallbackTimeout, behavior);
28
+ }
29
+ }, [disregardAutomaticFixedOffset, fixedOffset]);
30
+ return scroll;
31
+ };
32
+ export default useSmoothScroll;
@@ -0,0 +1,2 @@
1
+ export declare let useSpinDelay: (loading: boolean, delay?: number, minDuration?: number) => boolean;
2
+ export default useSpinDelay;
@@ -0,0 +1,36 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ var State;
3
+ (function (State) {
4
+ State[State["IDLE"] = 0] = "IDLE";
5
+ State[State["DELAY"] = 1] = "DELAY";
6
+ State[State["DISPLAY"] = 2] = "DISPLAY";
7
+ State[State["EXPIRE"] = 3] = "EXPIRE";
8
+ })(State || (State = {}));
9
+ export let useSpinDelay = (loading, delay = 500, minDuration = 200) => {
10
+ const [state, setState] = useState(State.IDLE);
11
+ const timeout = useRef();
12
+ useEffect(() => {
13
+ if (loading && state === State.IDLE) {
14
+ clearTimeout(timeout.current);
15
+ timeout.current = setTimeout(() => {
16
+ if (!loading) {
17
+ return setState(State.IDLE);
18
+ }
19
+ timeout.current = setTimeout(() => {
20
+ setState(State.EXPIRE);
21
+ }, minDuration);
22
+ setState(State.DISPLAY);
23
+ }, delay);
24
+ setState(State.DELAY);
25
+ }
26
+ if (!loading && state !== State.DISPLAY) {
27
+ clearTimeout(timeout.current);
28
+ setState(State.IDLE);
29
+ }
30
+ }, [loading, state, delay, minDuration]);
31
+ useEffect(() => {
32
+ return () => clearTimeout(timeout.current);
33
+ }, []);
34
+ return state === State.DISPLAY || state === State.EXPIRE;
35
+ };
36
+ export default useSpinDelay;
@@ -0,0 +1,2 @@
1
+ export declare let useTraceUpdate: (props: any) => void;
2
+ export default useTraceUpdate;
@@ -0,0 +1,17 @@
1
+ import { useEffect, useRef } from "react";
2
+ export let useTraceUpdate = (props) => {
3
+ const prev = useRef(props);
4
+ useEffect(() => {
5
+ const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
6
+ if (prev.current[k] !== v) {
7
+ ps[k] = [prev.current[k], v];
8
+ }
9
+ return ps;
10
+ }, {});
11
+ if (Object.keys(changedProps).length > 0) {
12
+ console.info("[@koine/react:useTraceUpdate] changed props:", changedProps);
13
+ }
14
+ prev.current = props;
15
+ });
16
+ };
17
+ export default useTraceUpdate;
@@ -0,0 +1,3 @@
1
+ import { useEffect } from "react";
2
+ export declare let useUpdateEffect: typeof useEffect;
3
+ export default useUpdateEffect;
@@ -0,0 +1,11 @@
1
+ import { useEffect } from "react";
2
+ import { useFirstMountState } from "./useFirstMountState";
3
+ export let useUpdateEffect = (effect, deps) => {
4
+ const isFirstMount = useFirstMountState();
5
+ useEffect(() => {
6
+ if (!isFirstMount) {
7
+ return effect();
8
+ }
9
+ }, deps);
10
+ };
11
+ export default useUpdateEffect;
@@ -0,0 +1,3 @@
1
+ import { debounce } from "@koine/utils";
2
+ export declare let useWindowSize: (wait?: Parameters<typeof debounce>[1], immediate?: Parameters<typeof debounce>[2]) => readonly [number, number];
3
+ export default useWindowSize;
@@ -0,0 +1,20 @@
1
+ import { useEffect, useState } from "react";
2
+ import { debounce } from "@koine/utils";
3
+ import { listenResize, listenResizeDebounced } from "@koine/dom";
4
+ export let useWindowSize = (wait, immediate) => {
5
+ const [width, widthSet] = useState(0);
6
+ const [height, heightSet] = useState(0);
7
+ useEffect(() => {
8
+ const updateSize = () => {
9
+ widthSet(window.innerWidth);
10
+ heightSet(window.innerHeight);
11
+ };
12
+ const listener = wait
13
+ ? listenResizeDebounced(0, updateSize, wait, immediate)
14
+ : listenResize(updateSize);
15
+ updateSize();
16
+ return listener;
17
+ }, [wait, immediate]);
18
+ return [width, height];
19
+ };
20
+ export default useWindowSize;