@jbpark/use-hooks 2.10.0 → 3.0.0
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/dist/hooks/index.d.mts +12 -1
- package/dist/hooks/index.mjs +12 -1
- package/dist/hooks/use-click-outside.d.mts +9 -2
- package/dist/hooks/use-click-outside.mjs +27 -11
- package/dist/hooks/use-click-outside.mjs.map +1 -1
- package/dist/hooks/use-controllable-state.d.mts +4 -5
- package/dist/hooks/use-controllable-state.mjs +10 -4
- package/dist/hooks/use-controllable-state.mjs.map +1 -1
- package/dist/hooks/use-debounced-value.d.mts +5 -0
- package/dist/hooks/use-debounced-value.mjs +20 -0
- package/dist/hooks/use-debounced-value.mjs.map +1 -0
- package/dist/hooks/use-element-position.mjs +37 -8
- package/dist/hooks/use-element-position.mjs.map +1 -1
- package/dist/hooks/use-element-scroll.d.mts +6 -1
- package/dist/hooks/use-element-scroll.mjs +30 -8
- package/dist/hooks/use-element-scroll.mjs.map +1 -1
- package/dist/hooks/use-event-listener.d.mts +21 -0
- package/dist/hooks/use-event-listener.mjs +37 -0
- package/dist/hooks/use-event-listener.mjs.map +1 -0
- package/dist/hooks/use-file-drop.d.mts +14 -0
- package/dist/hooks/use-file-drop.mjs +85 -0
- package/dist/hooks/use-file-drop.mjs.map +1 -0
- package/dist/hooks/use-image.d.mts +2 -1
- package/dist/hooks/use-image.mjs +4 -3
- package/dist/hooks/use-image.mjs.map +1 -1
- package/dist/hooks/use-intersection-observer.d.mts +8 -1
- package/dist/hooks/use-intersection-observer.mjs +37 -5
- package/dist/hooks/use-intersection-observer.mjs.map +1 -1
- package/dist/hooks/use-interval.d.mts +5 -0
- package/dist/hooks/use-interval.mjs +20 -0
- package/dist/hooks/use-interval.mjs.map +1 -0
- package/dist/hooks/use-key-press.d.mts +14 -0
- package/dist/hooks/use-key-press.mjs +63 -0
- package/dist/hooks/use-key-press.mjs.map +1 -0
- package/dist/hooks/use-merged-ref.d.mts +8 -0
- package/dist/hooks/use-merged-ref.mjs +25 -0
- package/dist/hooks/use-merged-ref.mjs.map +1 -0
- package/dist/hooks/use-multi-select.mjs +14 -5
- package/dist/hooks/use-multi-select.mjs.map +1 -1
- package/dist/hooks/use-mutation-observer.d.mts +11 -0
- package/dist/hooks/use-mutation-observer.mjs +33 -0
- package/dist/hooks/use-mutation-observer.mjs.map +1 -0
- package/dist/hooks/use-previous.d.mts +5 -0
- package/dist/hooks/use-previous.mjs +14 -0
- package/dist/hooks/use-previous.mjs.map +1 -0
- package/dist/hooks/use-resize-observer.d.mts +12 -0
- package/dist/hooks/use-resize-observer.mjs +29 -0
- package/dist/hooks/use-resize-observer.mjs.map +1 -0
- package/dist/hooks/use-responsive-size.d.mts +1 -0
- package/dist/hooks/use-responsive-size.mjs +70 -54
- package/dist/hooks/use-responsive-size.mjs.map +1 -1
- package/dist/hooks/use-scroll-to-elements.d.mts +7 -5
- package/dist/hooks/use-scroll-to-elements.mjs +52 -27
- package/dist/hooks/use-scroll-to-elements.mjs.map +1 -1
- package/dist/hooks/use-throttle.d.mts +5 -1
- package/dist/hooks/use-throttle.mjs +6 -32
- package/dist/hooks/use-throttle.mjs.map +1 -1
- package/dist/hooks/use-throttled-callback.d.mts +12 -0
- package/dist/hooks/use-throttled-callback.mjs +54 -0
- package/dist/hooks/use-throttled-callback.mjs.map +1 -0
- package/dist/hooks/use-timeout.d.mts +8 -0
- package/dist/hooks/use-timeout.mjs +38 -0
- package/dist/hooks/use-timeout.mjs.map +1 -0
- package/dist/hooks/use-toggle.d.mts +5 -0
- package/dist/hooks/use-toggle.mjs +17 -0
- package/dist/hooks/use-toggle.mjs.map +1 -0
- package/dist/hooks/use-window-scroll.mjs +60 -38
- package/dist/hooks/use-window-scroll.mjs.map +1 -1
- package/dist/index.d.mts +13 -2
- package/dist/index.mjs +13 -2
- package/package.json +1 -1
- package/dist/hooks/use-timeline.d.mts +0 -50
- package/dist/hooks/use-timeline.mjs +0 -176
- package/dist/hooks/use-timeline.mjs.map +0 -1
|
@@ -11,47 +11,69 @@ const useWindowScroll = (targetRef) => {
|
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
13
|
useEffect(() => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
14
|
+
let cancelled = false;
|
|
15
|
+
let rafId;
|
|
16
|
+
let cleanup;
|
|
17
|
+
const attach = () => {
|
|
18
|
+
if (cancelled) return;
|
|
19
|
+
if (targetRef && !targetRef.current) {
|
|
20
|
+
rafId = requestAnimationFrame(attach);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const target = targetRef?.current?.ownerDocument.defaultView ?? window;
|
|
24
|
+
const doc = target.document;
|
|
25
|
+
const calculate = () => {
|
|
26
|
+
const x = target.scrollX || 0;
|
|
27
|
+
const y = target.scrollY || 0;
|
|
28
|
+
const isIOS = /iPad|iPhone|iPod/.test(target.navigator.userAgent);
|
|
29
|
+
const visualViewport = target.visualViewport;
|
|
30
|
+
const viewportWidth = isIOS && visualViewport ? visualViewport.width : target.innerWidth;
|
|
31
|
+
const viewportHeight = isIOS && visualViewport ? visualViewport.height : target.innerHeight;
|
|
32
|
+
const maxScrollX = Math.max(0, doc.documentElement.scrollWidth - viewportWidth);
|
|
33
|
+
const maxScrollY = Math.max(0, doc.documentElement.scrollHeight - viewportHeight);
|
|
34
|
+
const percentX = maxScrollX === 0 ? 0 : Math.min(100, x / maxScrollX * 100);
|
|
35
|
+
const percentY = maxScrollY === 0 ? 0 : Math.min(100, y / maxScrollY * 100);
|
|
36
|
+
setState({
|
|
37
|
+
x,
|
|
38
|
+
y,
|
|
39
|
+
percent: {
|
|
40
|
+
x: Math.round(Math.max(0, percentX)),
|
|
41
|
+
y: Math.round(Math.max(0, percentY))
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
};
|
|
38
45
|
calculate();
|
|
46
|
+
const onScroll = () => {
|
|
47
|
+
calculate();
|
|
48
|
+
};
|
|
49
|
+
const onResize = () => {
|
|
50
|
+
setTimeout(calculate, 100);
|
|
51
|
+
};
|
|
52
|
+
const onVisualViewportChange = () => {
|
|
53
|
+
setTimeout(calculate, 50);
|
|
54
|
+
};
|
|
55
|
+
target.addEventListener("scroll", onScroll, { passive: true });
|
|
56
|
+
target.addEventListener("resize", onResize);
|
|
57
|
+
target.addEventListener("orientationchange", onResize);
|
|
58
|
+
if (target.visualViewport) target.visualViewport.addEventListener("resize", onVisualViewportChange);
|
|
59
|
+
let resizeObserver;
|
|
60
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
61
|
+
resizeObserver = new ResizeObserver(() => calculate());
|
|
62
|
+
resizeObserver.observe(doc.documentElement);
|
|
63
|
+
}
|
|
64
|
+
cleanup = () => {
|
|
65
|
+
target.removeEventListener("scroll", onScroll);
|
|
66
|
+
target.removeEventListener("resize", onResize);
|
|
67
|
+
target.removeEventListener("orientationchange", onResize);
|
|
68
|
+
if (target.visualViewport) target.visualViewport.removeEventListener("resize", onVisualViewportChange);
|
|
69
|
+
resizeObserver?.disconnect();
|
|
70
|
+
};
|
|
39
71
|
};
|
|
40
|
-
|
|
41
|
-
setTimeout(calculate, 100);
|
|
42
|
-
};
|
|
43
|
-
const onVisualViewportChange = () => {
|
|
44
|
-
setTimeout(calculate, 50);
|
|
45
|
-
};
|
|
46
|
-
target.addEventListener("scroll", onScroll, { passive: true });
|
|
47
|
-
target.addEventListener("resize", onResize);
|
|
48
|
-
target.addEventListener("orientationchange", onResize);
|
|
49
|
-
if (target.visualViewport) target.visualViewport.addEventListener("resize", onVisualViewportChange);
|
|
72
|
+
attach();
|
|
50
73
|
return () => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (target.visualViewport) target.visualViewport.removeEventListener("resize", onVisualViewportChange);
|
|
74
|
+
cancelled = true;
|
|
75
|
+
if (rafId !== void 0) cancelAnimationFrame(rafId);
|
|
76
|
+
cleanup?.();
|
|
55
77
|
};
|
|
56
78
|
}, [targetRef]);
|
|
57
79
|
return state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-window-scroll.mjs","names":[],"sources":["../../src/hooks/use-window-scroll.ts"],"sourcesContent":["import { type RefObject, useEffect, useState } from 'react';\n\n// Pass a ref to an element rendered inside the window you actually want to\n// track (e.g. a node portaled into an iframe). Without one, this defaults\n// to the host `window`, which is wrong whenever the caller doesn't live in\n// the top-level document
|
|
1
|
+
{"version":3,"file":"use-window-scroll.mjs","names":[],"sources":["../../src/hooks/use-window-scroll.ts"],"sourcesContent":["import { type RefObject, useEffect, useState } from 'react';\n\n// Pass a ref to an element rendered inside the window you actually want to\n// track (e.g. a node portaled into an iframe). Without one, this defaults\n// to the host `window`, which is wrong whenever the caller doesn't live in\n// the top-level document.\nconst useWindowScroll = (targetRef?: RefObject<Element | null>) => {\n const [state, setState] = useState({\n x: 0,\n y: 0,\n percent: {\n x: 0,\n y: 0,\n },\n });\n\n useEffect(() => {\n let cancelled = false;\n let rafId: number | undefined;\n let cleanup: (() => void) | undefined;\n\n const attach = () => {\n if (cancelled) {\n return;\n }\n\n // `targetRef.current` can still be null right after mount (e.g. a\n // conditionally-rendered or portaled node) — retry every frame\n // until it's populated instead of permanently falling back to the\n // host `window`.\n if (targetRef && !targetRef.current) {\n rafId = requestAnimationFrame(attach);\n return;\n }\n\n const target = targetRef?.current?.ownerDocument.defaultView ?? window;\n const doc = target.document;\n\n const calculate = () => {\n const x = target.scrollX || 0;\n const y = target.scrollY || 0;\n\n const isIOS = /iPad|iPhone|iPod/.test(target.navigator.userAgent);\n const visualViewport = target.visualViewport;\n\n const viewportWidth =\n isIOS && visualViewport ? visualViewport.width : target.innerWidth;\n\n const viewportHeight =\n isIOS && visualViewport ? visualViewport.height : target.innerHeight;\n\n const maxScrollX = Math.max(\n 0,\n doc.documentElement.scrollWidth - viewportWidth,\n );\n const maxScrollY = Math.max(\n 0,\n doc.documentElement.scrollHeight - viewportHeight,\n );\n\n const percentX =\n maxScrollX === 0 ? 0 : Math.min(100, (x / maxScrollX) * 100);\n const percentY =\n maxScrollY === 0 ? 0 : Math.min(100, (y / maxScrollY) * 100);\n\n setState({\n x,\n y,\n percent: {\n // Rounded (not floored) so reaching the true bottom/right edge\n // reads as 100 instead of falling just short of it.\n x: Math.round(Math.max(0, percentX)),\n y: Math.round(Math.max(0, percentY)),\n },\n });\n };\n\n calculate();\n\n const onScroll = () => {\n calculate();\n };\n\n const onResize = () => {\n setTimeout(calculate, 100);\n };\n\n const onVisualViewportChange = () => {\n setTimeout(calculate, 50);\n };\n\n target.addEventListener('scroll', onScroll, { passive: true });\n target.addEventListener('resize', onResize);\n target.addEventListener('orientationchange', onResize);\n\n if (target.visualViewport) {\n target.visualViewport.addEventListener(\n 'resize',\n onVisualViewportChange,\n );\n }\n\n // `resize`/`orientationchange` only fire for the viewport itself —\n // content that grows/shrinks the document height without resizing\n // the window (images loading, dynamic content) needs its own\n // observer to keep maxScrollY accurate.\n let resizeObserver: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(() => calculate());\n resizeObserver.observe(doc.documentElement);\n }\n\n cleanup = () => {\n target.removeEventListener('scroll', onScroll);\n target.removeEventListener('resize', onResize);\n target.removeEventListener('orientationchange', onResize);\n\n if (target.visualViewport) {\n target.visualViewport.removeEventListener(\n 'resize',\n onVisualViewportChange,\n );\n }\n\n resizeObserver?.disconnect();\n };\n };\n\n attach();\n\n return () => {\n cancelled = true;\n if (rafId !== undefined) {\n cancelAnimationFrame(rafId);\n }\n cleanup?.();\n };\n }, [targetRef]);\n\n return state;\n};\n\nexport default useWindowScroll;\n"],"mappings":";;;AAMA,MAAM,mBAAmB,cAA0C;CACjE,MAAM,CAAC,OAAO,YAAY,SAAS;EACjC,GAAG;EACH,GAAG;EACH,SAAS;GACP,GAAG;GACH,GAAG;GACJ;EACF,CAAC;AAEF,iBAAgB;EACd,IAAI,YAAY;EAChB,IAAI;EACJ,IAAI;EAEJ,MAAM,eAAe;AACnB,OAAI,UACF;AAOF,OAAI,aAAa,CAAC,UAAU,SAAS;AACnC,YAAQ,sBAAsB,OAAO;AACrC;;GAGF,MAAM,SAAS,WAAW,SAAS,cAAc,eAAe;GAChE,MAAM,MAAM,OAAO;GAEnB,MAAM,kBAAkB;IACtB,MAAM,IAAI,OAAO,WAAW;IAC5B,MAAM,IAAI,OAAO,WAAW;IAE5B,MAAM,QAAQ,mBAAmB,KAAK,OAAO,UAAU,UAAU;IACjE,MAAM,iBAAiB,OAAO;IAE9B,MAAM,gBACJ,SAAS,iBAAiB,eAAe,QAAQ,OAAO;IAE1D,MAAM,iBACJ,SAAS,iBAAiB,eAAe,SAAS,OAAO;IAE3D,MAAM,aAAa,KAAK,IACtB,GACA,IAAI,gBAAgB,cAAc,cACnC;IACD,MAAM,aAAa,KAAK,IACtB,GACA,IAAI,gBAAgB,eAAe,eACpC;IAED,MAAM,WACJ,eAAe,IAAI,IAAI,KAAK,IAAI,KAAM,IAAI,aAAc,IAAI;IAC9D,MAAM,WACJ,eAAe,IAAI,IAAI,KAAK,IAAI,KAAM,IAAI,aAAc,IAAI;AAE9D,aAAS;KACP;KACA;KACA,SAAS;MAGP,GAAG,KAAK,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;MACpC,GAAG,KAAK,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;MACrC;KACF,CAAC;;AAGJ,cAAW;GAEX,MAAM,iBAAiB;AACrB,eAAW;;GAGb,MAAM,iBAAiB;AACrB,eAAW,WAAW,IAAI;;GAG5B,MAAM,+BAA+B;AACnC,eAAW,WAAW,GAAG;;AAG3B,UAAO,iBAAiB,UAAU,UAAU,EAAE,SAAS,MAAM,CAAC;AAC9D,UAAO,iBAAiB,UAAU,SAAS;AAC3C,UAAO,iBAAiB,qBAAqB,SAAS;AAEtD,OAAI,OAAO,eACT,QAAO,eAAe,iBACpB,UACA,uBACD;GAOH,IAAI;AACJ,OAAI,OAAO,mBAAmB,aAAa;AACzC,qBAAiB,IAAI,qBAAqB,WAAW,CAAC;AACtD,mBAAe,QAAQ,IAAI,gBAAgB;;AAG7C,mBAAgB;AACd,WAAO,oBAAoB,UAAU,SAAS;AAC9C,WAAO,oBAAoB,UAAU,SAAS;AAC9C,WAAO,oBAAoB,qBAAqB,SAAS;AAEzD,QAAI,OAAO,eACT,QAAO,eAAe,oBACpB,UACA,uBACD;AAGH,oBAAgB,YAAY;;;AAIhC,UAAQ;AAER,eAAa;AACX,eAAY;AACZ,OAAI,UAAU,OACZ,sBAAqB,MAAM;AAE7B,cAAW;;IAEZ,CAAC,UAAU,CAAC;AAEf,QAAO"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
import { useDebounce } from "./hooks/use-debounce.mjs";
|
|
2
|
+
import { useDebouncedValue } from "./hooks/use-debounced-value.mjs";
|
|
2
3
|
import { useBodyScrollLock } from "./hooks/use-body-scroll-lock.mjs";
|
|
3
4
|
import { useClickOutside } from "./hooks/use-click-outside.mjs";
|
|
4
5
|
import { useControllableState } from "./hooks/use-controllable-state.mjs";
|
|
5
6
|
import { useElementPosition } from "./hooks/use-element-position.mjs";
|
|
6
7
|
import { useElementScroll } from "./hooks/use-element-scroll.mjs";
|
|
8
|
+
import { useEventListener } from "./hooks/use-event-listener.mjs";
|
|
9
|
+
import { useFileDrop } from "./hooks/use-file-drop.mjs";
|
|
7
10
|
import { useFileToDataUrl } from "./hooks/use-file-to-data-url.mjs";
|
|
8
11
|
import { useHistoryState } from "./hooks/use-history-state.mjs";
|
|
9
12
|
import { useIntersectionObserver } from "./hooks/use-intersection-observer.mjs";
|
|
13
|
+
import { useInterval } from "./hooks/use-interval.mjs";
|
|
10
14
|
import { useResponsiveSize } from "./hooks/use-responsive-size.mjs";
|
|
11
15
|
import { useImage } from "./hooks/use-image.mjs";
|
|
16
|
+
import { useKeyPress } from "./hooks/use-key-press.mjs";
|
|
12
17
|
import { useLocalStorage } from "./hooks/use-local-storage.mjs";
|
|
18
|
+
import { useMergedRef } from "./hooks/use-merged-ref.mjs";
|
|
13
19
|
import { useMultiSelect } from "./hooks/use-multi-select.mjs";
|
|
20
|
+
import { useMutationObserver } from "./hooks/use-mutation-observer.mjs";
|
|
21
|
+
import { usePrevious } from "./hooks/use-previous.mjs";
|
|
14
22
|
import { useRecursiveTimeout } from "./hooks/use-recursive-timeout.mjs";
|
|
23
|
+
import { useResizeObserver } from "./hooks/use-resize-observer.mjs";
|
|
15
24
|
import { useScrollToElements } from "./hooks/use-scroll-to-elements.mjs";
|
|
16
25
|
import { useThrottle } from "./hooks/use-throttle.mjs";
|
|
17
|
-
import {
|
|
26
|
+
import { useThrottledCallback } from "./hooks/use-throttled-callback.mjs";
|
|
27
|
+
import { useTimeout } from "./hooks/use-timeout.mjs";
|
|
28
|
+
import { useToggle } from "./hooks/use-toggle.mjs";
|
|
18
29
|
import { useWindowScroll } from "./hooks/use-window-scroll.mjs";
|
|
19
30
|
import { useViewport } from "./hooks/use-viewport.mjs";
|
|
20
31
|
import "./hooks/index.mjs";
|
|
21
|
-
export { useBodyScrollLock, useClickOutside, useControllableState, useDebounce, useElementPosition, useElementScroll, useFileToDataUrl, useHistoryState, useImage, useIntersectionObserver, useLocalStorage, useMultiSelect, useRecursiveTimeout, useResponsiveSize, useScrollToElements, useThrottle,
|
|
32
|
+
export { useBodyScrollLock, useClickOutside, useControllableState, useDebounce, useDebouncedValue, useElementPosition, useElementScroll, useEventListener, useFileDrop, useFileToDataUrl, useHistoryState, useImage, useIntersectionObserver, useInterval, useKeyPress, useLocalStorage, useMergedRef, useMultiSelect, useMutationObserver, usePrevious, useRecursiveTimeout, useResizeObserver, useResponsiveSize, useScrollToElements, useThrottle, useThrottledCallback, useTimeout, useToggle, useViewport, useWindowScroll };
|
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
import useDebounce from "./hooks/use-debounce.mjs";
|
|
2
|
+
import useDebouncedValue from "./hooks/use-debounced-value.mjs";
|
|
2
3
|
import useBodyScrollLock from "./hooks/use-body-scroll-lock.mjs";
|
|
3
4
|
import useClickOutside from "./hooks/use-click-outside.mjs";
|
|
4
5
|
import useControllableState from "./hooks/use-controllable-state.mjs";
|
|
5
6
|
import useElementPosition from "./hooks/use-element-position.mjs";
|
|
6
7
|
import useElementScroll from "./hooks/use-element-scroll.mjs";
|
|
8
|
+
import useEventListener from "./hooks/use-event-listener.mjs";
|
|
9
|
+
import useFileDrop from "./hooks/use-file-drop.mjs";
|
|
7
10
|
import useFileToDataUrl from "./hooks/use-file-to-data-url.mjs";
|
|
8
11
|
import useHistoryState from "./hooks/use-history-state.mjs";
|
|
9
12
|
import useIntersectionObserver from "./hooks/use-intersection-observer.mjs";
|
|
13
|
+
import useInterval from "./hooks/use-interval.mjs";
|
|
10
14
|
import useResponsiveSize from "./hooks/use-responsive-size.mjs";
|
|
11
15
|
import useImage from "./hooks/use-image.mjs";
|
|
16
|
+
import useKeyPress from "./hooks/use-key-press.mjs";
|
|
12
17
|
import useLocalStorage from "./hooks/use-local-storage.mjs";
|
|
18
|
+
import useMergedRef from "./hooks/use-merged-ref.mjs";
|
|
13
19
|
import useMultiSelect from "./hooks/use-multi-select.mjs";
|
|
20
|
+
import useMutationObserver from "./hooks/use-mutation-observer.mjs";
|
|
21
|
+
import usePrevious from "./hooks/use-previous.mjs";
|
|
14
22
|
import useRecursiveTimeout from "./hooks/use-recursive-timeout.mjs";
|
|
23
|
+
import useResizeObserver from "./hooks/use-resize-observer.mjs";
|
|
15
24
|
import useScrollToElements from "./hooks/use-scroll-to-elements.mjs";
|
|
25
|
+
import useThrottledCallback from "./hooks/use-throttled-callback.mjs";
|
|
16
26
|
import useThrottle from "./hooks/use-throttle.mjs";
|
|
17
|
-
import
|
|
27
|
+
import useTimeout from "./hooks/use-timeout.mjs";
|
|
28
|
+
import useToggle from "./hooks/use-toggle.mjs";
|
|
18
29
|
import useWindowScroll from "./hooks/use-window-scroll.mjs";
|
|
19
30
|
import useViewport from "./hooks/use-viewport.mjs";
|
|
20
31
|
import "./hooks/index.mjs";
|
|
21
32
|
|
|
22
|
-
export { useBodyScrollLock, useClickOutside, useControllableState, useDebounce, useElementPosition, useElementScroll, useFileToDataUrl, useHistoryState, useImage, useIntersectionObserver, useLocalStorage, useMultiSelect, useRecursiveTimeout, useResponsiveSize, useScrollToElements, useThrottle,
|
|
33
|
+
export { useBodyScrollLock, useClickOutside, useControllableState, useDebounce, useDebouncedValue, useElementPosition, useElementScroll, useEventListener, useFileDrop, useFileToDataUrl, useHistoryState, useImage, useIntersectionObserver, useInterval, useKeyPress, useLocalStorage, useMergedRef, useMultiSelect, useMutationObserver, usePrevious, useRecursiveTimeout, useResizeObserver, useResponsiveSize, useScrollToElements, useThrottle, useThrottledCallback, useTimeout, useToggle, useViewport, useWindowScroll };
|
package/package.json
CHANGED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import * as react from "react";
|
|
2
|
-
|
|
3
|
-
//#region src/hooks/use-timeline.d.ts
|
|
4
|
-
interface TimelineStep {
|
|
5
|
-
scale?: number;
|
|
6
|
-
rotate?: {
|
|
7
|
-
x?: number;
|
|
8
|
-
y?: number;
|
|
9
|
-
z?: number;
|
|
10
|
-
};
|
|
11
|
-
position?: {
|
|
12
|
-
x?: number;
|
|
13
|
-
y?: number;
|
|
14
|
-
};
|
|
15
|
-
top?: number;
|
|
16
|
-
left?: number;
|
|
17
|
-
width?: number;
|
|
18
|
-
height?: number;
|
|
19
|
-
zIndex?: number;
|
|
20
|
-
filter?: string;
|
|
21
|
-
backgroundColor?: string;
|
|
22
|
-
opacity?: number;
|
|
23
|
-
selector: string;
|
|
24
|
-
transition: Transition;
|
|
25
|
-
}
|
|
26
|
-
interface Transition {
|
|
27
|
-
duration: number;
|
|
28
|
-
ease?: string;
|
|
29
|
-
delay?: number;
|
|
30
|
-
easeX?: string;
|
|
31
|
-
easeY?: string;
|
|
32
|
-
}
|
|
33
|
-
interface Options {
|
|
34
|
-
steps?: TimelineStep[];
|
|
35
|
-
loading?: boolean;
|
|
36
|
-
immediate?: boolean;
|
|
37
|
-
loop?: boolean;
|
|
38
|
-
}
|
|
39
|
-
declare const useTimeline: ({
|
|
40
|
-
steps,
|
|
41
|
-
loading,
|
|
42
|
-
immediate,
|
|
43
|
-
loop
|
|
44
|
-
}: Options) => {
|
|
45
|
-
ref: react.RefObject<HTMLDivElement | null>;
|
|
46
|
-
completed: boolean;
|
|
47
|
-
};
|
|
48
|
-
//#endregion
|
|
49
|
-
export { useTimeline };
|
|
50
|
-
//# sourceMappingURL=use-timeline.d.mts.map
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
|
-
|
|
3
|
-
//#region src/hooks/use-timeline.ts
|
|
4
|
-
const registeredProperties = /* @__PURE__ */ new Set();
|
|
5
|
-
const registerCSSProperty = (name, syntax = "<length>", initialValue = "0px") => {
|
|
6
|
-
if (registeredProperties.has(name) || typeof CSS === "undefined" || !CSS.registerProperty) return;
|
|
7
|
-
try {
|
|
8
|
-
CSS.registerProperty({
|
|
9
|
-
name,
|
|
10
|
-
syntax,
|
|
11
|
-
inherits: false,
|
|
12
|
-
initialValue
|
|
13
|
-
});
|
|
14
|
-
registeredProperties.add(name);
|
|
15
|
-
} catch {}
|
|
16
|
-
};
|
|
17
|
-
const buildTimeline = (steps) => {
|
|
18
|
-
const groups = [];
|
|
19
|
-
for (const step of steps) if (step.transition.delay === 0 && groups.length > 0) groups[groups.length - 1]?.push(step);
|
|
20
|
-
else groups.push([step]);
|
|
21
|
-
return groups;
|
|
22
|
-
};
|
|
23
|
-
const buildTransform = (step) => {
|
|
24
|
-
const parts = [];
|
|
25
|
-
if (step.position?.x != null || step.position?.y != null) parts.push(`translate(${step.position.x ?? 0}px, ${step.position.y ?? 0}px)`);
|
|
26
|
-
if (step.scale != null) parts.push(`scale(${step.scale})`);
|
|
27
|
-
if (step.rotate?.x != null) parts.push(`rotateX(${step.rotate.x}deg)`);
|
|
28
|
-
if (step.rotate?.y != null) parts.push(`rotateY(${step.rotate.y}deg)`);
|
|
29
|
-
if (step.rotate?.z != null) parts.push(`rotateZ(${step.rotate.z}deg)`);
|
|
30
|
-
return parts.join(" ") || void 0;
|
|
31
|
-
};
|
|
32
|
-
const applyStep = (container, step, skipTransition) => {
|
|
33
|
-
const elements = container.matches(step.selector) ? [container] : Array.from(container.querySelectorAll(step.selector));
|
|
34
|
-
if (!elements.length) return;
|
|
35
|
-
const dur = `${step.transition.duration}ms`;
|
|
36
|
-
const eas = step.transition.ease ?? "ease-out";
|
|
37
|
-
const easX = step.transition.easeX;
|
|
38
|
-
const easY = step.transition.easeY;
|
|
39
|
-
const hasCurve = !!(easX || easY);
|
|
40
|
-
const timers = [];
|
|
41
|
-
elements.forEach((el) => {
|
|
42
|
-
if (skipTransition) el.style.transition = "none";
|
|
43
|
-
else if (hasCurve) {
|
|
44
|
-
const xEase = easX ?? eas;
|
|
45
|
-
const yEase = easY ?? eas;
|
|
46
|
-
el.style.transition = [
|
|
47
|
-
`--tx ${dur} ${xEase}`,
|
|
48
|
-
`--ty ${dur} ${yEase}`,
|
|
49
|
-
`--s ${dur} ${eas}`,
|
|
50
|
-
`rotate ${dur} ${eas}`,
|
|
51
|
-
`width ${dur} ${eas}`,
|
|
52
|
-
`height ${dur} ${eas}`,
|
|
53
|
-
`filter ${dur} ${eas}`,
|
|
54
|
-
`opacity ${dur} ${eas}`
|
|
55
|
-
].join(", ");
|
|
56
|
-
} else el.style.transition = `all ${dur} ${eas}`;
|
|
57
|
-
if (step.backgroundColor) el.style.backgroundColor = step.backgroundColor;
|
|
58
|
-
if (step.opacity !== void 0) el.style.opacity = String(step.opacity);
|
|
59
|
-
if (step.top !== void 0) el.style.top = `${step.top}px`;
|
|
60
|
-
if (step.left !== void 0) el.style.left = `${step.left}px`;
|
|
61
|
-
if (step.width !== void 0) el.style.width = `${step.width}px`;
|
|
62
|
-
if (step.height !== void 0) el.style.height = `${step.height}px`;
|
|
63
|
-
if (step.zIndex !== void 0) if (skipTransition) el.style.zIndex = String(step.zIndex);
|
|
64
|
-
else {
|
|
65
|
-
const timerId = setTimeout(() => {
|
|
66
|
-
el.style.zIndex = String(step.zIndex);
|
|
67
|
-
}, step.transition.duration / 2);
|
|
68
|
-
timers.push(timerId);
|
|
69
|
-
}
|
|
70
|
-
if (step.filter !== void 0) el.style.filter = step.filter;
|
|
71
|
-
if (step.rotate?.z !== void 0) el.style.rotate = `${step.rotate.z}deg`;
|
|
72
|
-
if (hasCurve) {
|
|
73
|
-
if (step.position?.x != null || step.position?.y != null) {
|
|
74
|
-
el.style.setProperty("--tx", `${step.position.x ?? 0}px`);
|
|
75
|
-
el.style.setProperty("--ty", `${step.position.y ?? 0}px`);
|
|
76
|
-
}
|
|
77
|
-
if (step.scale != null) el.style.setProperty("--s", String(step.scale));
|
|
78
|
-
el.style.transform = `translate(var(--tx), var(--ty)) scale(var(--s, 1))`;
|
|
79
|
-
} else {
|
|
80
|
-
const transform = buildTransform(step);
|
|
81
|
-
if (transform) el.style.transform = transform;
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
return timers;
|
|
85
|
-
};
|
|
86
|
-
const useTimeline = ({ steps = [], loading, immediate, loop }) => {
|
|
87
|
-
const [slotIndex, setSlotIndex] = useState(-1);
|
|
88
|
-
const [completed, setCompleted] = useState(() => !!immediate);
|
|
89
|
-
const ref = useRef(null);
|
|
90
|
-
const timeline = useMemo(() => buildTimeline(steps), [steps]);
|
|
91
|
-
const hasCurveSteps = useMemo(() => steps.some((s) => s.transition.easeX || s.transition.easeY), [steps]);
|
|
92
|
-
useLayoutEffect(() => {
|
|
93
|
-
if (hasCurveSteps) {
|
|
94
|
-
registerCSSProperty("--tx");
|
|
95
|
-
registerCSSProperty("--ty");
|
|
96
|
-
registerCSSProperty("--s", "<number>", "1");
|
|
97
|
-
}
|
|
98
|
-
}, [hasCurveSteps]);
|
|
99
|
-
useLayoutEffect(() => {
|
|
100
|
-
if (!immediate || !ref.current || !steps.length) return;
|
|
101
|
-
const container = ref.current;
|
|
102
|
-
steps.forEach((step) => applyStep(container, step, true));
|
|
103
|
-
}, [immediate, steps]);
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
if (immediate || loading || !timeline.length) return;
|
|
106
|
-
const firstDelay = timeline[0]?.[0]?.transition.delay ?? 0;
|
|
107
|
-
const timerId = window.setTimeout(() => {
|
|
108
|
-
requestAnimationFrame(() => setSlotIndex(0));
|
|
109
|
-
}, firstDelay);
|
|
110
|
-
return () => clearTimeout(timerId);
|
|
111
|
-
}, [
|
|
112
|
-
loading,
|
|
113
|
-
timeline,
|
|
114
|
-
immediate
|
|
115
|
-
]);
|
|
116
|
-
useEffect(() => {
|
|
117
|
-
if (immediate || loading || slotIndex < 0) return;
|
|
118
|
-
const isLast = slotIndex >= timeline.length - 1;
|
|
119
|
-
if (isLast && !loop) return;
|
|
120
|
-
const currentSlot = timeline[slotIndex];
|
|
121
|
-
const maxDuration = Math.max(...currentSlot?.map((s) => s.transition.duration) ?? [0]);
|
|
122
|
-
const nextIndex = isLast ? 0 : slotIndex + 1;
|
|
123
|
-
const nextDelay = timeline[nextIndex]?.[0]?.transition.delay ?? 0;
|
|
124
|
-
const timerId = window.setTimeout(() => {
|
|
125
|
-
setSlotIndex(nextIndex);
|
|
126
|
-
}, maxDuration + nextDelay);
|
|
127
|
-
return () => clearTimeout(timerId);
|
|
128
|
-
}, [
|
|
129
|
-
loading,
|
|
130
|
-
slotIndex,
|
|
131
|
-
timeline,
|
|
132
|
-
immediate,
|
|
133
|
-
loop
|
|
134
|
-
]);
|
|
135
|
-
useEffect(() => {
|
|
136
|
-
if (immediate || slotIndex < 0 || !ref.current) return;
|
|
137
|
-
const container = ref.current;
|
|
138
|
-
const timers = [];
|
|
139
|
-
const rafId = requestAnimationFrame(() => {
|
|
140
|
-
timeline[slotIndex]?.forEach((step) => {
|
|
141
|
-
const stepTimers = applyStep(container, step);
|
|
142
|
-
if (stepTimers) timers.push(...stepTimers);
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
return () => {
|
|
146
|
-
cancelAnimationFrame(rafId);
|
|
147
|
-
timers.forEach(clearTimeout);
|
|
148
|
-
};
|
|
149
|
-
}, [
|
|
150
|
-
immediate,
|
|
151
|
-
slotIndex,
|
|
152
|
-
timeline
|
|
153
|
-
]);
|
|
154
|
-
useEffect(() => {
|
|
155
|
-
if (immediate || loop || slotIndex < 0 || slotIndex < timeline.length - 1 || !timeline.length) return;
|
|
156
|
-
const lastSlot = timeline[slotIndex];
|
|
157
|
-
const maxDuration = Math.max(...lastSlot?.map((s) => s.transition.duration) ?? [0]);
|
|
158
|
-
const timerId = window.setTimeout(() => {
|
|
159
|
-
setCompleted(true);
|
|
160
|
-
}, maxDuration);
|
|
161
|
-
return () => clearTimeout(timerId);
|
|
162
|
-
}, [
|
|
163
|
-
slotIndex,
|
|
164
|
-
timeline,
|
|
165
|
-
immediate,
|
|
166
|
-
loop
|
|
167
|
-
]);
|
|
168
|
-
return {
|
|
169
|
-
ref,
|
|
170
|
-
completed
|
|
171
|
-
};
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
//#endregion
|
|
175
|
-
export { useTimeline as default };
|
|
176
|
-
//# sourceMappingURL=use-timeline.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-timeline.mjs","names":[],"sources":["../../src/hooks/use-timeline.ts"],"sourcesContent":["import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nconst registeredProperties = new Set<string>();\n\nconst registerCSSProperty = (\n name: string,\n syntax = '<length>',\n initialValue = '0px',\n) => {\n if (\n registeredProperties.has(name) ||\n typeof CSS === 'undefined' ||\n !CSS.registerProperty\n ) {\n return;\n }\n\n try {\n CSS.registerProperty({\n name,\n syntax,\n inherits: false,\n initialValue,\n });\n registeredProperties.add(name);\n } catch {\n // 이미 등록된 경우 무시\n }\n};\n\nexport interface TimelineStep {\n scale?: number;\n rotate?: { x?: number; y?: number; z?: number };\n position?: { x?: number; y?: number };\n top?: number;\n left?: number;\n width?: number;\n height?: number;\n zIndex?: number;\n filter?: string;\n backgroundColor?: string;\n opacity?: number;\n selector: string;\n transition: Transition;\n}\n\ninterface Transition {\n duration: number;\n ease?: string;\n delay?: number;\n easeX?: string;\n easeY?: string;\n}\n\ninterface Options {\n steps?: TimelineStep[];\n loading?: boolean;\n immediate?: boolean;\n loop?: boolean;\n}\n\nconst buildTimeline = (steps: TimelineStep[]): TimelineStep[][] => {\n const groups: TimelineStep[][] = [];\n\n for (const step of steps) {\n if (step.transition.delay === 0 && groups.length > 0) {\n groups[groups.length - 1]?.push(step);\n } else {\n groups.push([step]);\n }\n }\n\n return groups;\n};\n\nconst buildTransform = (step: TimelineStep) => {\n const parts: string[] = [];\n\n if (step.position?.x != null || step.position?.y != null) {\n parts.push(\n `translate(${step.position.x ?? 0}px, ${step.position.y ?? 0}px)`,\n );\n }\n\n if (step.scale != null) {\n parts.push(`scale(${step.scale})`);\n }\n\n if (step.rotate?.x != null) {\n parts.push(`rotateX(${step.rotate.x}deg)`);\n }\n\n if (step.rotate?.y != null) {\n parts.push(`rotateY(${step.rotate.y}deg)`);\n }\n\n if (step.rotate?.z != null) {\n parts.push(`rotateZ(${step.rotate.z}deg)`);\n }\n\n return parts.join(' ') || undefined;\n};\n\nconst applyStep = (\n container: HTMLElement,\n step: TimelineStep,\n skipTransition?: boolean,\n) => {\n const elements = container.matches(step.selector)\n ? [container]\n : Array.from(container.querySelectorAll<HTMLElement>(step.selector));\n\n if (!elements.length) {\n return;\n }\n\n const dur = `${step.transition.duration}ms`;\n const eas = step.transition.ease ?? 'ease-out';\n const easX = step.transition.easeX;\n const easY = step.transition.easeY;\n const hasCurve = !!(easX || easY);\n const timers: ReturnType<typeof setTimeout>[] = [];\n\n elements.forEach(el => {\n if (skipTransition) {\n el.style.transition = 'none';\n } else if (hasCurve) {\n const xEase = easX ?? eas;\n const yEase = easY ?? eas;\n el.style.transition = [\n `--tx ${dur} ${xEase}`,\n `--ty ${dur} ${yEase}`,\n `--s ${dur} ${eas}`,\n `rotate ${dur} ${eas}`,\n `width ${dur} ${eas}`,\n `height ${dur} ${eas}`,\n `filter ${dur} ${eas}`,\n `opacity ${dur} ${eas}`,\n ].join(', ');\n } else {\n el.style.transition = `all ${dur} ${eas}`;\n }\n\n if (step.backgroundColor) {\n el.style.backgroundColor = step.backgroundColor;\n }\n\n if (step.opacity !== undefined) {\n el.style.opacity = String(step.opacity);\n }\n\n if (step.top !== undefined) {\n el.style.top = `${step.top}px`;\n }\n\n if (step.left !== undefined) {\n el.style.left = `${step.left}px`;\n }\n\n if (step.width !== undefined) {\n el.style.width = `${step.width}px`;\n }\n\n if (step.height !== undefined) {\n el.style.height = `${step.height}px`;\n }\n\n if (step.zIndex !== undefined) {\n if (skipTransition) {\n el.style.zIndex = String(step.zIndex);\n } else {\n const timerId = setTimeout(() => {\n el.style.zIndex = String(step.zIndex);\n }, step.transition.duration / 2);\n timers.push(timerId);\n }\n }\n\n if (step.filter !== undefined) {\n el.style.filter = step.filter;\n }\n\n if (step.rotate?.z !== undefined) {\n el.style.rotate = `${step.rotate.z}deg`;\n }\n\n if (hasCurve) {\n if (step.position?.x != null || step.position?.y != null) {\n el.style.setProperty('--tx', `${step.position.x ?? 0}px`);\n el.style.setProperty('--ty', `${step.position.y ?? 0}px`);\n }\n if (step.scale != null) {\n el.style.setProperty('--s', String(step.scale));\n }\n el.style.transform = `translate(var(--tx), var(--ty)) scale(var(--s, 1))`;\n } else {\n const transform = buildTransform(step);\n\n if (transform) {\n el.style.transform = transform;\n }\n }\n });\n\n return timers;\n};\n\nconst useTimeline = ({ steps = [], loading, immediate, loop }: Options) => {\n const [slotIndex, setSlotIndex] = useState(-1);\n const [completed, setCompleted] = useState(() => !!immediate);\n\n const ref = useRef<HTMLDivElement>(null);\n const timeline = useMemo(() => buildTimeline(steps), [steps]);\n const hasCurveSteps = useMemo(\n () => steps.some(s => s.transition.easeX || s.transition.easeY),\n [steps],\n );\n\n useLayoutEffect(() => {\n if (hasCurveSteps) {\n registerCSSProperty('--tx');\n registerCSSProperty('--ty');\n registerCSSProperty('--s', '<number>', '1');\n }\n }, [hasCurveSteps]);\n\n useLayoutEffect(() => {\n if (!immediate || !ref.current || !steps.length) {\n return;\n }\n\n const container = ref.current;\n steps.forEach(step => applyStep(container, step, true));\n }, [immediate, steps]);\n\n useEffect(() => {\n if (immediate || loading || !timeline.length) {\n return;\n }\n\n const firstDelay = timeline[0]?.[0]?.transition.delay ?? 0;\n const timerId = window.setTimeout(() => {\n requestAnimationFrame(() => setSlotIndex(0));\n }, firstDelay);\n\n return () => clearTimeout(timerId);\n }, [loading, timeline, immediate]);\n\n useEffect(() => {\n if (immediate || loading || slotIndex < 0) {\n return;\n }\n\n const isLast = slotIndex >= timeline.length - 1;\n\n if (isLast && !loop) {\n return;\n }\n\n const currentSlot = timeline[slotIndex];\n const maxDuration = Math.max(\n ...(currentSlot?.map(s => s.transition.duration) ?? [0]),\n );\n\n const nextIndex = isLast ? 0 : slotIndex + 1;\n const nextDelay = timeline[nextIndex]?.[0]?.transition.delay ?? 0;\n\n const timerId = window.setTimeout(() => {\n setSlotIndex(nextIndex);\n }, maxDuration + nextDelay);\n\n return () => clearTimeout(timerId);\n }, [loading, slotIndex, timeline, immediate, loop]);\n\n useEffect(() => {\n if (immediate || slotIndex < 0 || !ref.current) {\n return;\n }\n\n const container = ref.current;\n const timers: ReturnType<typeof setTimeout>[] = [];\n\n const rafId = requestAnimationFrame(() => {\n timeline[slotIndex]?.forEach(step => {\n const stepTimers = applyStep(container, step);\n\n if (stepTimers) {\n timers.push(...stepTimers);\n }\n });\n });\n\n return () => {\n cancelAnimationFrame(rafId);\n timers.forEach(clearTimeout);\n };\n }, [immediate, slotIndex, timeline]);\n\n useEffect(() => {\n if (\n immediate ||\n loop ||\n slotIndex < 0 ||\n slotIndex < timeline.length - 1 ||\n !timeline.length\n ) {\n return;\n }\n\n const lastSlot = timeline[slotIndex];\n const maxDuration = Math.max(\n ...(lastSlot?.map(s => s.transition.duration) ?? [0]),\n );\n\n const timerId = window.setTimeout(() => {\n setCompleted(true);\n }, maxDuration);\n\n return () => clearTimeout(timerId);\n }, [slotIndex, timeline, immediate, loop]);\n\n return { ref, completed };\n};\n\nexport default useTimeline;\n"],"mappings":"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"}
|