@cites/react-hooks 0.0.1
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/core/useBoundingClientRect.d.ts +12 -0
- package/dist/core/useBoundingClientRect.d.ts.map +1 -0
- package/dist/core/useBoundingClientRect.js +72 -0
- package/dist/core/useBoundingClientRect.js.map +1 -0
- package/dist/core/useComposedRefs.d.ts +9 -0
- package/dist/core/useComposedRefs.d.ts.map +1 -0
- package/dist/core/useComposedRefs.js +58 -0
- package/dist/core/useComposedRefs.js.map +1 -0
- package/dist/core/useCustomScroller.d.ts +6 -0
- package/dist/core/useCustomScroller.d.ts.map +1 -0
- package/dist/core/useCustomScroller.js +21 -0
- package/dist/core/useCustomScroller.js.map +1 -0
- package/dist/core/useDraggable.d.ts +22 -0
- package/dist/core/useDraggable.d.ts.map +1 -0
- package/dist/core/useDraggable.js +82 -0
- package/dist/core/useDraggable.js.map +1 -0
- package/dist/core/useEventCallback.d.ts +14 -0
- package/dist/core/useEventCallback.d.ts.map +1 -0
- package/dist/core/useEventCallback.js +32 -0
- package/dist/core/useEventCallback.js.map +1 -0
- package/dist/core/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/core/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/core/useIsomorphicLayoutEffect.js +3 -0
- package/dist/core/useIsomorphicLayoutEffect.js.map +1 -0
- package/dist/core/useKeepActiveItemIntoView.d.ts +20 -0
- package/dist/core/useKeepActiveItemIntoView.d.ts.map +1 -0
- package/dist/core/useKeepActiveItemIntoView.js +46 -0
- package/dist/core/useKeepActiveItemIntoView.js.map +1 -0
- package/dist/core/useScrollIntoViewHelper.d.ts +24 -0
- package/dist/core/useScrollIntoViewHelper.d.ts.map +1 -0
- package/dist/core/useScrollIntoViewHelper.js +65 -0
- package/dist/core/useScrollIntoViewHelper.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/scroll-helper.d.ts +37 -0
- package/dist/utils/scroll-helper.d.ts.map +1 -0
- package/dist/utils/scroll-helper.js +115 -0
- package/dist/utils/scroll-helper.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface BoundingClientRectOptions {
|
|
2
|
+
measureOnce?: boolean;
|
|
3
|
+
trackElementResize?: boolean;
|
|
4
|
+
trackScroll?: boolean;
|
|
5
|
+
trackResize?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface BoundingClientRectResults<T extends HTMLElement> {
|
|
8
|
+
rect: DOMRect | null;
|
|
9
|
+
ref: React.RefCallback<T>;
|
|
10
|
+
}
|
|
11
|
+
export declare function useBoundingClientRect<T extends HTMLElement>(options?: BoundingClientRectOptions): BoundingClientRectResults<T>;
|
|
12
|
+
//# sourceMappingURL=useBoundingClientRect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBoundingClientRect.d.ts","sourceRoot":"","sources":["../../src/core/useBoundingClientRect.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,yBAAyB;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,WAAW;IAC5D,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,WAAW,EACvD,OAAO,GAAE,yBAA8B,GACxC,yBAAyB,CAAC,CAAC,CAAC,CAmF9B"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useState, useCallback, useRef } from "react";
|
|
2
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
3
|
+
import { useEventCallback } from "./useEventCallback.js";
|
|
4
|
+
export function useBoundingClientRect(options = {}) {
|
|
5
|
+
const { measureOnce = false, trackElementResize = true, trackScroll = true, trackResize = true, } = options;
|
|
6
|
+
const [node, setNode] = useState();
|
|
7
|
+
const [rect, setRect] = useState(null);
|
|
8
|
+
const animationFrameId = useRef(null);
|
|
9
|
+
const ref = useCallback(nodeInstance => {
|
|
10
|
+
setNode(nodeInstance);
|
|
11
|
+
return () => {
|
|
12
|
+
setNode(undefined);
|
|
13
|
+
};
|
|
14
|
+
}, []);
|
|
15
|
+
const updateRect = useEventCallback(() => {
|
|
16
|
+
if (node) {
|
|
17
|
+
setRect(node.getBoundingClientRect());
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
useIsomorphicLayoutEffect(() => {
|
|
21
|
+
const element = node;
|
|
22
|
+
if (!element) {
|
|
23
|
+
setRect(null);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
updateRect();
|
|
27
|
+
if (measureOnce)
|
|
28
|
+
return;
|
|
29
|
+
const handleScrollAndResize = () => {
|
|
30
|
+
if (animationFrameId.current) {
|
|
31
|
+
cancelAnimationFrame(animationFrameId.current);
|
|
32
|
+
}
|
|
33
|
+
animationFrameId.current = requestAnimationFrame(updateRect);
|
|
34
|
+
};
|
|
35
|
+
if (trackScroll) {
|
|
36
|
+
window.addEventListener("scroll", handleScrollAndResize, {
|
|
37
|
+
capture: true,
|
|
38
|
+
passive: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (trackResize) {
|
|
42
|
+
window.addEventListener("resize", handleScrollAndResize, {
|
|
43
|
+
passive: true,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
let resizeObserver;
|
|
47
|
+
if (trackElementResize) {
|
|
48
|
+
resizeObserver = new ResizeObserver(handleScrollAndResize);
|
|
49
|
+
resizeObserver.observe(element);
|
|
50
|
+
}
|
|
51
|
+
return () => {
|
|
52
|
+
if (trackScroll) {
|
|
53
|
+
window.removeEventListener("scroll", handleScrollAndResize, true);
|
|
54
|
+
}
|
|
55
|
+
if (trackResize) {
|
|
56
|
+
window.removeEventListener("resize", handleScrollAndResize);
|
|
57
|
+
}
|
|
58
|
+
if (resizeObserver) {
|
|
59
|
+
resizeObserver.disconnect();
|
|
60
|
+
}
|
|
61
|
+
if (animationFrameId.current) {
|
|
62
|
+
cancelAnimationFrame(animationFrameId.current);
|
|
63
|
+
animationFrameId.current = null;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}, [node, measureOnce, trackElementResize, trackScroll, trackResize]);
|
|
67
|
+
return {
|
|
68
|
+
rect,
|
|
69
|
+
ref,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=useBoundingClientRect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBoundingClientRect.js","sourceRoot":"","sources":["../../src/core/useBoundingClientRect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
type PossibleRef<T> = React.Ref<T> | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* A custom hook that composes multiple refs
|
|
5
|
+
* Accepts callback refs and RefObject(s)
|
|
6
|
+
*/
|
|
7
|
+
export declare function useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=useComposedRefs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useComposedRefs.d.ts","sourceRoot":"","sources":["../../src/core/useComposedRefs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAE3C,KAAK,WAAW,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AAoD/C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAGlF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
const isFunction = (value) => {
|
|
3
|
+
return typeof value === "function";
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Set a given ref to a given value
|
|
7
|
+
* This utility takes care of different types of refs: callback refs and RefObject(s)
|
|
8
|
+
*/
|
|
9
|
+
function setRef(ref, value) {
|
|
10
|
+
if (isFunction(ref)) {
|
|
11
|
+
return ref(value);
|
|
12
|
+
}
|
|
13
|
+
else if (ref !== null && ref !== undefined) {
|
|
14
|
+
ref.current = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A utility to compose multiple refs together
|
|
19
|
+
* Accepts callback refs and RefObject(s)
|
|
20
|
+
*/
|
|
21
|
+
function composeRefs(...refs) {
|
|
22
|
+
return (node) => {
|
|
23
|
+
let hasCleanup = false;
|
|
24
|
+
const cleanups = refs.map((ref) => {
|
|
25
|
+
const cleanup = setRef(ref, node);
|
|
26
|
+
if (!hasCleanup && isFunction(cleanup)) {
|
|
27
|
+
hasCleanup = true;
|
|
28
|
+
}
|
|
29
|
+
return cleanup;
|
|
30
|
+
});
|
|
31
|
+
// React <19 will log an error to the console if a callback ref returns a
|
|
32
|
+
// value. We don"t use ref cleanups internally so this will only happen if a
|
|
33
|
+
// user"s ref callback returns a value, which we only expect if they are
|
|
34
|
+
// using the cleanup functionality added in React 19.
|
|
35
|
+
if (hasCleanup) {
|
|
36
|
+
return () => {
|
|
37
|
+
for (let i = 0; i < cleanups.length; i++) {
|
|
38
|
+
const cleanup = cleanups[i];
|
|
39
|
+
if (isFunction(cleanup)) {
|
|
40
|
+
cleanup();
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
setRef(refs[i], null);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A custom hook that composes multiple refs
|
|
52
|
+
* Accepts callback refs and RefObject(s)
|
|
53
|
+
*/
|
|
54
|
+
export function useComposedRefs(...refs) {
|
|
55
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
56
|
+
return useCallback(composeRefs(...refs), refs);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=useComposedRefs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useComposedRefs.js","sourceRoot":"","sources":["../../src/core/useComposedRefs.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAI3C,MAAM,UAAU,GAAG,CAAC,KAAc,EAAqB,EAAE;IACrD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACvC,CAAC,CAAA;AAED;;;GAGG;AACH,SAAS,MAAM,CAAI,GAAmB,EAAE,KAAQ;IAC5C,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;SAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3C,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IACxB,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAI,GAAG,IAAsB;IAC7C,OAAO,CAAC,IAAI,EAAE,EAAE;QACZ,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,UAAU,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,OAAO,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,4EAA4E;QAC5E,wEAAwE;QACxE,qDAAqD;QACrD,IAAI,UAAU,EAAE,CAAC;YACb,OAAO,GAAG,EAAE;gBACR,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAC5B,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;wBACtB,OAAO,EAAE,CAAC;oBACd,CAAC;yBAAM,CAAC;wBACJ,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;oBAC1B,CAAC;gBACL,CAAC;YACL,CAAC,CAAC;QACN,CAAC;IACL,CAAC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAI,GAAG,IAAsB;IACxD,uDAAuD;IACvD,OAAO,WAAW,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AnimatedScrollOptions } from "../utils/scroll-helper.js";
|
|
2
|
+
export declare function useCustomScroller<T extends HTMLElement>(): {
|
|
3
|
+
containerRef: import("react").RefObject<T | null>;
|
|
4
|
+
scrollTo: (target: HTMLElement, options?: AnimatedScrollOptions) => void;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=useCustomScroller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCustomScroller.d.ts","sourceRoot":"","sources":["../../src/core/useCustomScroller.ts"],"names":[],"mappings":"AAGA,OAAO,EAEH,qBAAqB,EAGxB,MAAM,2BAA2B,CAAC;AAEnC,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW;;uBAKvC,WAAW,YACV,qBAAqB;EAoBrC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useRef, useCallback, } from "react";
|
|
2
|
+
import { ScrollDirections, animatedScrollTo, calculateScrollOffset, } from "../utils/scroll-helper.js";
|
|
3
|
+
export function useCustomScroller() {
|
|
4
|
+
const containerRef = useRef(null);
|
|
5
|
+
const runningAnimation = useRef(null);
|
|
6
|
+
const scrollTo = useCallback((target, options = {}) => {
|
|
7
|
+
if (!containerRef.current) {
|
|
8
|
+
console.warn("滚动容器的 ref 尚未附加到元素上。");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (runningAnimation.current) {
|
|
12
|
+
runningAnimation.current();
|
|
13
|
+
}
|
|
14
|
+
const { direction = ScrollDirections.vertical, ...restOptions } = options;
|
|
15
|
+
const container = containerRef.current;
|
|
16
|
+
const targetOffset = calculateScrollOffset(container, target, direction, options);
|
|
17
|
+
runningAnimation.current = animatedScrollTo(container, targetOffset, direction, restOptions);
|
|
18
|
+
}, []);
|
|
19
|
+
return { containerRef, scrollTo };
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=useCustomScroller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCustomScroller.js","sourceRoot":"","sources":["../../src/core/useCustomScroller.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,MAAM,EAAE,WAAW,GACtB,MAAM,OAAO,CAAC;AACf,OAAO,EACH,gBAAgB,EAEhB,gBAAgB,EAChB,qBAAqB,GACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,UAAU,iBAAiB;IAC7B,MAAM,YAAY,GAAG,MAAM,CAAI,IAAI,CAAC,CAAC;IACrC,MAAM,gBAAgB,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IAE3D,MAAM,QAAQ,GAAG,WAAW,CAAC,CACzB,MAAmB,EACnB,UAAiC,EAAE,EACrC,EAAE;QACA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACpC,OAAO;QACX,CAAC;QAED,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC3B,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC;QAED,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAAC,QAAQ,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;QAC1E,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QAEvC,MAAM,YAAY,GAAG,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAElF,gBAAgB,CAAC,OAAO,GAAG,gBAAgB,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACjG,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface Point {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}
|
|
6
|
+
export interface Bounds {
|
|
7
|
+
left: number;
|
|
8
|
+
top: number;
|
|
9
|
+
right: number;
|
|
10
|
+
bottom: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DragInfo<T extends HTMLElement> extends Point {
|
|
13
|
+
ref: React.Ref<T>;
|
|
14
|
+
isDragging: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface DraggableOptions {
|
|
17
|
+
mode?: "object" | "slider";
|
|
18
|
+
initialPosition?: Point;
|
|
19
|
+
bounds?: Bounds;
|
|
20
|
+
}
|
|
21
|
+
export declare const useDraggable: <T extends HTMLElement>(options?: DraggableOptions) => DragInfo<T>;
|
|
22
|
+
//# sourceMappingURL=useDraggable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDraggable.d.ts","sourceRoot":"","sources":["../../src/core/useDraggable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAGxE,MAAM,WAAW,KAAK;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAE,SAAQ,KAAK;IAC1D,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,WAAW,EAAE,UAAS,gBAAqB,KAAG,QAAQ,CAAC,CAAC,CAmG9F,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useState, useEffect, useRef, useCallback } from "react";
|
|
2
|
+
import { useEventCallback } from "./useEventCallback.js";
|
|
3
|
+
export const useDraggable = (options = {}) => {
|
|
4
|
+
const { initialPosition, bounds, mode = "object" } = options;
|
|
5
|
+
const [position, setPosition] = useState(null);
|
|
6
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
7
|
+
const animationFrameId = useRef(null);
|
|
8
|
+
const currentPosition = position ?? initialPosition ?? { x: 0, y: 0 };
|
|
9
|
+
const [handleNode, setHandleNode] = useState(null);
|
|
10
|
+
const handleRefCallback = useCallback((node) => {
|
|
11
|
+
setHandleNode(node);
|
|
12
|
+
return () => {
|
|
13
|
+
setHandleNode(null);
|
|
14
|
+
};
|
|
15
|
+
}, []);
|
|
16
|
+
const dragInfo = useRef(null);
|
|
17
|
+
const animate = useEventCallback(() => {
|
|
18
|
+
if (!dragInfo.current)
|
|
19
|
+
return;
|
|
20
|
+
const newPosition = {
|
|
21
|
+
x: dragInfo.current.initialPosition.x + (dragInfo.current.lastPoint.x - dragInfo.current.startPoint.x),
|
|
22
|
+
y: dragInfo.current.initialPosition.y + (dragInfo.current.lastPoint.y - dragInfo.current.startPoint.y),
|
|
23
|
+
};
|
|
24
|
+
if (bounds) {
|
|
25
|
+
newPosition.x = Math.max(bounds.left, Math.min(newPosition.x, bounds.right));
|
|
26
|
+
newPosition.y = Math.max(bounds.top, Math.min(newPosition.y, bounds.bottom));
|
|
27
|
+
}
|
|
28
|
+
setPosition(newPosition);
|
|
29
|
+
animationFrameId.current = requestAnimationFrame(animate);
|
|
30
|
+
});
|
|
31
|
+
const handlePointerMove = useEventCallback((event) => {
|
|
32
|
+
if (dragInfo.current) {
|
|
33
|
+
dragInfo.current.lastPoint = { x: event.clientX, y: event.clientY };
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const handlePointerUp = useEventCallback(() => {
|
|
37
|
+
window.removeEventListener("pointermove", handlePointerMove);
|
|
38
|
+
window.removeEventListener("pointerup", handlePointerUp);
|
|
39
|
+
if (animationFrameId.current) {
|
|
40
|
+
cancelAnimationFrame(animationFrameId.current);
|
|
41
|
+
}
|
|
42
|
+
dragInfo.current = null;
|
|
43
|
+
setIsDragging(false);
|
|
44
|
+
});
|
|
45
|
+
const handlePointerDown = useEventCallback((event) => {
|
|
46
|
+
if (event.button !== 0)
|
|
47
|
+
return;
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
const isSliderMode = mode === "slider";
|
|
50
|
+
const startPosition = isSliderMode
|
|
51
|
+
? { x: event.clientX, y: event.clientY }
|
|
52
|
+
: { ...currentPosition };
|
|
53
|
+
dragInfo.current = {
|
|
54
|
+
initialPosition: startPosition,
|
|
55
|
+
startPoint: { x: event.clientX, y: event.clientY },
|
|
56
|
+
lastPoint: { x: event.clientX, y: event.clientY },
|
|
57
|
+
};
|
|
58
|
+
window.addEventListener("pointermove", handlePointerMove);
|
|
59
|
+
window.addEventListener("pointerup", handlePointerUp);
|
|
60
|
+
animationFrameId.current = requestAnimationFrame(animate);
|
|
61
|
+
setIsDragging(true);
|
|
62
|
+
});
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!handleNode)
|
|
65
|
+
return;
|
|
66
|
+
handleNode.addEventListener("pointerdown", handlePointerDown);
|
|
67
|
+
return () => {
|
|
68
|
+
handleNode.removeEventListener("pointerdown", handlePointerDown);
|
|
69
|
+
window.removeEventListener("pointermove", handlePointerMove);
|
|
70
|
+
window.removeEventListener("pointerup", handlePointerUp);
|
|
71
|
+
if (animationFrameId.current) {
|
|
72
|
+
cancelAnimationFrame(animationFrameId.current);
|
|
73
|
+
if (animationFrameId) {
|
|
74
|
+
animationFrameId.current = null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
dragInfo.current = null;
|
|
78
|
+
};
|
|
79
|
+
}, [handleNode]);
|
|
80
|
+
return { ...currentPosition, isDragging, ref: handleRefCallback };
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=useDraggable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDraggable.js","sourceRoot":"","sources":["../../src/core/useDraggable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A custom React hook that creates a stable function reference (a "callback event")
|
|
3
|
+
* that will always call the latest version of the function passed to it.
|
|
4
|
+
* This is a TypeScript implementation of the pattern used to polyfill the
|
|
5
|
+
* upcoming official `useEffectEvent` hook.
|
|
6
|
+
*
|
|
7
|
+
* @template T - The type of the callback function.
|
|
8
|
+
* @param {T} callback - The function to be made stable. This function can use
|
|
9
|
+
* the latest props and state, and it will be updated on every render.
|
|
10
|
+
* @returns {T} A memoized function that has a stable identity across re-renders
|
|
11
|
+
* but executes the most recent version of the `callback`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useEventCallback<T extends (...args: any[]) => any>(callback: T): T;
|
|
14
|
+
//# sourceMappingURL=useEventCallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEventCallback.d.ts","sourceRoot":"","sources":["../../src/core/useEventCallback.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAkBlF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useRef, useCallback } from "react";
|
|
2
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
3
|
+
/**
|
|
4
|
+
* A custom React hook that creates a stable function reference (a "callback event")
|
|
5
|
+
* that will always call the latest version of the function passed to it.
|
|
6
|
+
* This is a TypeScript implementation of the pattern used to polyfill the
|
|
7
|
+
* upcoming official `useEffectEvent` hook.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of the callback function.
|
|
10
|
+
* @param {T} callback - The function to be made stable. This function can use
|
|
11
|
+
* the latest props and state, and it will be updated on every render.
|
|
12
|
+
* @returns {T} A memoized function that has a stable identity across re-renders
|
|
13
|
+
* but executes the most recent version of the `callback`.
|
|
14
|
+
*/
|
|
15
|
+
export function useEventCallback(callback) {
|
|
16
|
+
// 1. Store the latest callback in a ref. The ref's type is the function signature.
|
|
17
|
+
const callbackRef = useRef(callback);
|
|
18
|
+
// 2. Use useLayoutEffect to update the ref synchronously after every render.
|
|
19
|
+
// This ensures the ref always holds the latest version of the callback
|
|
20
|
+
// before any other effects run.
|
|
21
|
+
useIsomorphicLayoutEffect(() => {
|
|
22
|
+
callbackRef.current = callback;
|
|
23
|
+
}); // No dependency array means this effect runs on every render.
|
|
24
|
+
// 3. Return a stable, memoized function.
|
|
25
|
+
// This function's identity will never change because of the empty dependency array.
|
|
26
|
+
// We cast the returned function to type T to match the input function signature.
|
|
27
|
+
return useCallback((...args) => {
|
|
28
|
+
// When called, it executes the *current* function stored in the ref.
|
|
29
|
+
return callbackRef.current(...args);
|
|
30
|
+
}, []);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=useEventCallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEventCallback.js","sourceRoot":"","sources":["../../src/core/useEventCallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAoC,QAAW;IAC3E,mFAAmF;IACnF,MAAM,WAAW,GAAG,MAAM,CAAI,QAAQ,CAAC,CAAC;IAExC,6EAA6E;IAC7E,uEAAuE;IACvE,gCAAgC;IAChC,yBAAyB,CAAC,GAAG,EAAE;QAC3B,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACnC,CAAC,CAAC,CAAC,CAAC,8DAA8D;IAElE,yCAAyC;IACzC,oFAAoF;IACpF,iFAAiF;IACjF,OAAO,WAAW,CAAC,CAAC,GAAG,IAAmB,EAAiB,EAAE;QACzD,qEAAqE;QACrE,OAAO,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACxC,CAAC,EAAE,EAAE,CAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsomorphicLayoutEffect.d.ts","sourceRoot":"","sources":["../../src/core/useIsomorphicLayoutEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,OAAO,CAAC;AAEnD,eAAO,MAAM,yBAAyB,wBAA8D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsomorphicLayoutEffect.js","sourceRoot":"","sources":["../../src/core/useIsomorphicLayoutEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnD,MAAM,CAAC,MAAM,yBAAyB,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AnimatedScrollOptions } from "./useScrollIntoViewHelper.js";
|
|
2
|
+
interface UseKeepActiveItemIntoViewOptions<T, K = T> extends AnimatedScrollOptions {
|
|
3
|
+
activeItem?: T | null;
|
|
4
|
+
getKey?: (item: T) => K;
|
|
5
|
+
}
|
|
6
|
+
type SetContainerRef = (element: HTMLElement | null) => void;
|
|
7
|
+
type SetItemRef<K> = (key: K, element: HTMLElement | null) => void;
|
|
8
|
+
type ManualScrollToItem<T> = (item: T, overrideOptions?: AnimatedScrollOptions) => void;
|
|
9
|
+
/**
|
|
10
|
+
* 维持列表中的活动项始终在视图内的 Hook.
|
|
11
|
+
* @param options 配置项,包括活动项、key 生成函数和滚动选项
|
|
12
|
+
* @returns 返回一个元组:[设置容器的 ref 回调, 设置列表项的 ref 回调, 手动滚动函数]
|
|
13
|
+
*/
|
|
14
|
+
export declare function useKeepActiveItemIntoView<T, K = T>(options?: UseKeepActiveItemIntoViewOptions<T, K>): {
|
|
15
|
+
setContainerRef: SetContainerRef;
|
|
16
|
+
setItemRef: SetItemRef<K>;
|
|
17
|
+
scrollToItem: ManualScrollToItem<T>;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=useKeepActiveItemIntoView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeepActiveItemIntoView.d.ts","sourceRoot":"","sources":["../../src/core/useKeepActiveItemIntoView.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,qBAAqB,EAE7B,MAAM,8BAA8B,CAAC;AAEtC,UAAU,gCAAgC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAE,SAAQ,qBAAqB;IAC9E,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;CAC3B;AAED,KAAK,eAAe,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;AAC7D,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;AACnE,KAAK,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,eAAe,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAExF;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAC9C,OAAO,GAAE,gCAAgC,CAAC,CAAC,EAAE,CAAC,CAAM;;;;EA2CvD"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useRef, useCallback, useEffect, } from "react";
|
|
2
|
+
import { useScrollIntoViewHelper, } from "./useScrollIntoViewHelper.js";
|
|
3
|
+
/**
|
|
4
|
+
* 维持列表中的活动项始终在视图内的 Hook.
|
|
5
|
+
* @param options 配置项,包括活动项、key 生成函数和滚动选项
|
|
6
|
+
* @returns 返回一个元组:[设置容器的 ref 回调, 设置列表项的 ref 回调, 手动滚动函数]
|
|
7
|
+
*/
|
|
8
|
+
export function useKeepActiveItemIntoView(options = {}) {
|
|
9
|
+
const { activeItem, getKey, ...scrollOptions } = options;
|
|
10
|
+
const containerRef = useRef(null);
|
|
11
|
+
const itemsRef = useRef(new Map());
|
|
12
|
+
const scrollHelper = useScrollIntoViewHelper(containerRef.current);
|
|
13
|
+
// 检查并更新滚动助手的容器
|
|
14
|
+
const setContainerRef = useCallback((element) => {
|
|
15
|
+
containerRef.current = element;
|
|
16
|
+
scrollHelper.current?.setContainer(element);
|
|
17
|
+
}, [scrollHelper]);
|
|
18
|
+
// 注册或注销列表项及其对应的 DOM 元素
|
|
19
|
+
const setItemRef = useCallback((key, element) => {
|
|
20
|
+
if (element) {
|
|
21
|
+
itemsRef.current.set(key, element);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
itemsRef.current.delete(key);
|
|
25
|
+
}
|
|
26
|
+
}, []);
|
|
27
|
+
// 手动滚动函数
|
|
28
|
+
const scrollToItem = useCallback((item, overrideOptions) => {
|
|
29
|
+
const key = getKey ? getKey(item) : item;
|
|
30
|
+
const element = itemsRef.current.get(key);
|
|
31
|
+
if (element) {
|
|
32
|
+
// 合并默认选项和手动覆盖选项
|
|
33
|
+
const finalOptions = { ...scrollOptions, ...overrideOptions };
|
|
34
|
+
scrollHelper.current?.scrollTo(element, finalOptions);
|
|
35
|
+
}
|
|
36
|
+
}, [getKey, scrollHelper, scrollOptions]);
|
|
37
|
+
// 自动滚动逻辑
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (activeItem) {
|
|
40
|
+
// 使用 setTimeout 确保 DOM 元素已经渲染并注册
|
|
41
|
+
setTimeout(() => scrollToItem(activeItem), 0);
|
|
42
|
+
}
|
|
43
|
+
}, [activeItem, scrollToItem]);
|
|
44
|
+
return { setContainerRef, setItemRef, scrollToItem };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=useKeepActiveItemIntoView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeepActiveItemIntoView.js","sourceRoot":"","sources":["../../src/core/useKeepActiveItemIntoView.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,MAAM,EAAE,WAAW,EAAE,SAAS,GACjC,MAAM,OAAO,CAAC;AAEf,OAAO,EAEH,uBAAuB,GAC1B,MAAM,8BAA8B,CAAC;AAWtC;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACrC,UAAkD,EAAE;IAEpD,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IAEzD,MAAM,YAAY,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAE,CAAC,CAAC;IACxD,MAAM,YAAY,GAAG,uBAAuB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAEnE,eAAe;IACf,MAAM,eAAe,GAAoB,WAAW,CAAC,CAAC,OAA2B,EAAE,EAAE;QACjF,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC;QAC/B,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,uBAAuB;IACvB,MAAM,UAAU,GAAkB,WAAW,CAAC,CAAC,GAAM,EAAE,OAA2B,EAAE,EAAE;QAClF,IAAI,OAAO,EAAE,CAAC;YACV,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACJ,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS;IACT,MAAM,YAAY,GAA0B,WAAW,CAAC,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE;QAC9E,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAqB,CAAC;QAC3D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,OAAO,EAAE,CAAC;YACV,gBAAgB;YAChB,MAAM,YAAY,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,eAAe,EAAE,CAAC;YAC9D,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC1D,CAAC;IACL,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IAE1C,SAAS;IACT,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,UAAU,EAAE,CAAC;YACb,iCAAiC;YACjC,UAAU,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC;IACL,CAAC,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IAE/B,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
import { type AnimatedScrollOptions } from "../utils/scroll-helper.js";
|
|
3
|
+
export type { AnimatedScrollOptions };
|
|
4
|
+
/**
|
|
5
|
+
* A helper class that encapsulates scrolling logic.
|
|
6
|
+
* This is managed by the useScrollIntoViewHelper hook.
|
|
7
|
+
*/
|
|
8
|
+
declare class ScrollIntoViewHelper {
|
|
9
|
+
private _container;
|
|
10
|
+
private _runningAnimation;
|
|
11
|
+
constructor(container: HTMLElement | null);
|
|
12
|
+
scrollTo(element: HTMLElement, options?: AnimatedScrollOptions): void;
|
|
13
|
+
stopScroll(): void;
|
|
14
|
+
getContainer(): HTMLElement | null;
|
|
15
|
+
setContainer(container: HTMLElement | null): void;
|
|
16
|
+
destroy(): void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 创建并管理一个 ScrollIntoViewHelper 实例的 Hook.
|
|
20
|
+
* @param container 初始的滚动容器元素
|
|
21
|
+
* @returns 返回一个包含 ScrollIntoViewHelper 实例的 RefObject
|
|
22
|
+
*/
|
|
23
|
+
export declare function useScrollIntoViewHelper(container: HTMLElement | null): RefObject<ScrollIntoViewHelper | null>;
|
|
24
|
+
//# sourceMappingURL=useScrollIntoViewHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollIntoViewHelper.d.ts","sourceRoot":"","sources":["../../src/core/useScrollIntoViewHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,SAAS,EAEjB,MAAM,OAAO,CAAC;AAEf,OAAO,EACH,KAAK,qBAAqB,EAI7B,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC;;;GAGG;AACH,cAAM,oBAAoB;IACtB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,iBAAiB,CAA6B;gBAE1C,SAAS,EAAE,WAAW,GAAG,IAAI;IAIlC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,GAAE,qBAA0B,GAAG,IAAI;IAuBzE,UAAU,IAAI,IAAI;IAQlB,YAAY,IAAI,WAAW,GAAG,IAAI;IAGlC,YAAY,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI;IAIjD,OAAO,IAAI,IAAI;CAIzB;AAGD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACnC,SAAS,EAAE,WAAW,GAAG,IAAI,GAC9B,SAAS,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAaxC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useRef, useEffect, } from "react";
|
|
2
|
+
import { ensureNotNull } from "../utils/index.js";
|
|
3
|
+
import { ScrollDirections, animatedScrollTo, calculateScrollOffset, } from "../utils/scroll-helper.js";
|
|
4
|
+
/**
|
|
5
|
+
* A helper class that encapsulates scrolling logic.
|
|
6
|
+
* This is managed by the useScrollIntoViewHelper hook.
|
|
7
|
+
*/
|
|
8
|
+
class ScrollIntoViewHelper {
|
|
9
|
+
_container;
|
|
10
|
+
_runningAnimation = null; // 用于停止动画
|
|
11
|
+
constructor(container) {
|
|
12
|
+
this._container = container;
|
|
13
|
+
}
|
|
14
|
+
scrollTo(element, options = {}) {
|
|
15
|
+
if (!this._container || !element) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// [新引擎] 功能强大
|
|
19
|
+
// 1. 如果有正在进行的动画,先停止它
|
|
20
|
+
if (this._runningAnimation) {
|
|
21
|
+
this._runningAnimation();
|
|
22
|
+
}
|
|
23
|
+
// 2. 解构出 direction,因为它决定了计算方式
|
|
24
|
+
const { direction = ScrollDirections.vertical, ...restOptions } = options;
|
|
25
|
+
// 3. 调用我们的核心计算函数
|
|
26
|
+
const targetOffset = calculateScrollOffset(this._container, element, direction, options);
|
|
27
|
+
// 4. 调用我们的核心动画函数,并保存停止句柄
|
|
28
|
+
this._runningAnimation = animatedScrollTo(this._container, targetOffset, direction, restOptions);
|
|
29
|
+
}
|
|
30
|
+
// 别忘了在 stopScroll 和 destroy 方法里也调用它
|
|
31
|
+
stopScroll() {
|
|
32
|
+
if (this._runningAnimation) {
|
|
33
|
+
this._runningAnimation();
|
|
34
|
+
this._runningAnimation = null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// These two methods are what useKeepActiveItemIntoView needs.
|
|
38
|
+
getContainer() {
|
|
39
|
+
return this._container;
|
|
40
|
+
}
|
|
41
|
+
setContainer(container) {
|
|
42
|
+
this._container = container;
|
|
43
|
+
}
|
|
44
|
+
destroy() {
|
|
45
|
+
this.stopScroll();
|
|
46
|
+
this._container = null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 创建并管理一个 ScrollIntoViewHelper 实例的 Hook.
|
|
51
|
+
* @param container 初始的滚动容器元素
|
|
52
|
+
* @returns 返回一个包含 ScrollIntoViewHelper 实例的 RefObject
|
|
53
|
+
*/
|
|
54
|
+
export function useScrollIntoViewHelper(container) {
|
|
55
|
+
const helperRef = useRef(null);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
helperRef.current = new ScrollIntoViewHelper(container);
|
|
58
|
+
return () => {
|
|
59
|
+
// 在组件卸载时销毁实例,防止内存泄漏
|
|
60
|
+
ensureNotNull(helperRef.current).destroy();
|
|
61
|
+
};
|
|
62
|
+
}, [container]); // 当容器变化时重新创建实例
|
|
63
|
+
return helperRef;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=useScrollIntoViewHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollIntoViewHelper.js","sourceRoot":"","sources":["../../src/core/useScrollIntoViewHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,MAAM,EAAE,SAAS,GACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAEH,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,GACxB,MAAM,2BAA2B,CAAC;AAInC;;;GAGG;AACH,MAAM,oBAAoB;IACd,UAAU,CAAqB;IAC/B,iBAAiB,GAAwB,IAAI,CAAC,CAAC,SAAS;IAEhE,YAAY,SAA6B;QACrC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAChC,CAAC;IAEM,QAAQ,CAAC,OAAoB,EAAE,UAAiC,EAAE;QACrE,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,OAAO;QACX,CAAC;QAED,aAAa;QAEb,qBAAqB;QACrB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC7B,CAAC;QAED,8BAA8B;QAC9B,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAAC,QAAQ,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;QAE1E,iBAAiB;QACjB,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAEzF,yBAAyB;QACzB,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACrG,CAAC;IAED,oCAAoC;IAC7B,UAAU;QACb,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAClC,CAAC;IACL,CAAC;IAED,8DAA8D;IACvD,YAAY;QACf,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IACM,YAAY,CAAC,SAA6B;QAC7C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAChC,CAAC;IAEM,OAAO;QACV,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IAC3B,CAAC;CACJ;AAGD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACnC,SAA6B;IAE7B,MAAM,SAAS,GAAG,MAAM,CAA8B,IAAI,CAAC,CAAC;IAE5D,SAAS,CAAC,GAAG,EAAE;QACX,SAAS,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAExD,OAAO,GAAG,EAAE;YACR,oBAAoB;YACpB,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QAC/C,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe;IAEhC,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./core/useBoundingClientRect.js";
|
|
2
|
+
export * from "./core/useComposedRefs.js";
|
|
3
|
+
export * from "./core/useDraggable.js";
|
|
4
|
+
export * from "./core/useEventCallback.js";
|
|
5
|
+
export * from "./core/useIsomorphicLayoutEffect.js";
|
|
6
|
+
export * from "./core/useCustomScroller.js";
|
|
7
|
+
export * from "./core/useKeepActiveItemIntoView.js";
|
|
8
|
+
export * from "./core/useScrollIntoViewHelper.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qCAAqC,CAAC;AAEpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./core/useBoundingClientRect.js";
|
|
2
|
+
export * from "./core/useComposedRefs.js";
|
|
3
|
+
export * from "./core/useDraggable.js";
|
|
4
|
+
export * from "./core/useEventCallback.js";
|
|
5
|
+
export * from "./core/useIsomorphicLayoutEffect.js";
|
|
6
|
+
export * from "./core/useCustomScroller.js";
|
|
7
|
+
export * from "./core/useKeepActiveItemIntoView.js";
|
|
8
|
+
export * from "./core/useScrollIntoViewHelper.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qCAAqC,CAAC;AAEpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,CAK/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAI,KAA2B;IACxD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
type ValueOf<T> = T[keyof T];
|
|
2
|
+
export declare const ScrollDirections: {
|
|
3
|
+
readonly vertical: "vertical";
|
|
4
|
+
readonly horizontal: "horizontal";
|
|
5
|
+
};
|
|
6
|
+
export type ScrollDirections = ValueOf<typeof ScrollDirections>;
|
|
7
|
+
export declare const Anchors: {
|
|
8
|
+
readonly start: "start";
|
|
9
|
+
readonly middle: "middle";
|
|
10
|
+
readonly end: "end";
|
|
11
|
+
};
|
|
12
|
+
export type Anchors = ValueOf<typeof Anchors>;
|
|
13
|
+
export declare const BuiltinEasingFunctions: {
|
|
14
|
+
readonly linear: "linear";
|
|
15
|
+
readonly easeInOutCubic: "easeInOutCubic";
|
|
16
|
+
};
|
|
17
|
+
export type BuiltinEasingFunctions = ValueOf<typeof BuiltinEasingFunctions>;
|
|
18
|
+
export interface AnimatedScrollOptions {
|
|
19
|
+
/** 动画的最大时长 (毫秒),实际时长会自适应调整 */
|
|
20
|
+
duration?: number;
|
|
21
|
+
/** 缓动函数 */
|
|
22
|
+
easing?: BuiltinEasingFunctions | ((t: number) => number);
|
|
23
|
+
/** 要对齐的目标元素的锚点,默认为 'start' (顶部/左侧) */
|
|
24
|
+
targetAnchor?: Anchors;
|
|
25
|
+
/** 要对齐到的容器的锚点,可以是固定位置或百分比 (0-100),默认为 'start' */
|
|
26
|
+
containerAnchor?: Anchors | number;
|
|
27
|
+
/** 在对齐后应用的额外偏移量,支持 'px' 和 '%' (相对于目标元素尺寸) */
|
|
28
|
+
offset?: number | string;
|
|
29
|
+
/** 滚动方向,默认为 'vertical' */
|
|
30
|
+
direction?: ScrollDirections;
|
|
31
|
+
/** 滚动动画结束后的回调 */
|
|
32
|
+
onScrollEnd?: () => void;
|
|
33
|
+
}
|
|
34
|
+
export declare function animatedScrollTo(container: HTMLElement, targetOffset: number, direction: NonNullable<AnimatedScrollOptions["direction"]>, options?: Pick<AnimatedScrollOptions, "duration" | "easing" | "onScrollEnd">): () => void;
|
|
35
|
+
export declare function calculateScrollOffset(container: HTMLElement, target: HTMLElement, direction: NonNullable<AnimatedScrollOptions["direction"]>, options?: AnimatedScrollOptions): number;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=scroll-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-helper.d.ts","sourceRoot":"","sources":["../../src/utils/scroll-helper.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE7B,eAAO,MAAM,gBAAgB;;;CAGnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,eAAO,MAAM,OAAO;;;;CAIV,CAAC;AACX,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,OAAO,CAAC,CAAC;AAE9C,eAAO,MAAM,sBAAsB;;;CAGzB,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,MAAM,WAAW,qBAAqB;IAClC,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,MAAM,CAAC,EAAE,sBAAsB,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAC1D,sCAAsC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iDAAiD;IACjD,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACnC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,iBAAiB;IACjB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAuBD,wBAAgB,gBAAgB,CAC5B,SAAS,EAAE,WAAW,EACtB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,WAAW,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC,EAC1D,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC,GAC7E,MAAM,IAAI,CAmDZ;AAKD,wBAAgB,qBAAqB,CACjC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,WAAW,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC,EAC1D,OAAO,CAAC,EAAE,qBAAqB,GAChC,MAAM,CA+CR"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export const ScrollDirections = {
|
|
2
|
+
vertical: "vertical",
|
|
3
|
+
horizontal: "horizontal",
|
|
4
|
+
};
|
|
5
|
+
export const Anchors = {
|
|
6
|
+
start: "start",
|
|
7
|
+
middle: "middle",
|
|
8
|
+
end: "end",
|
|
9
|
+
};
|
|
10
|
+
export const BuiltinEasingFunctions = {
|
|
11
|
+
linear: "linear",
|
|
12
|
+
easeInOutCubic: "easeInOutCubic",
|
|
13
|
+
};
|
|
14
|
+
const EASING_FUNCTIONS = {
|
|
15
|
+
linear: (t) => t,
|
|
16
|
+
easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,
|
|
17
|
+
};
|
|
18
|
+
function parseOffset(offset, referenceSize) {
|
|
19
|
+
if (typeof offset === "number") {
|
|
20
|
+
return offset;
|
|
21
|
+
}
|
|
22
|
+
if (typeof offset === "string") {
|
|
23
|
+
if (offset.endsWith("%")) {
|
|
24
|
+
const percent = parseFloat(offset.slice(0, -1));
|
|
25
|
+
return (percent / 100) * referenceSize;
|
|
26
|
+
}
|
|
27
|
+
return parseFloat(offset);
|
|
28
|
+
}
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
// 2. 核心动画函数 (V5.4 更新:基于速度的自适应时长)
|
|
32
|
+
// ==========================================================
|
|
33
|
+
export function animatedScrollTo(container, targetOffset, direction, options) {
|
|
34
|
+
const { duration: userMaxDuration = 800, easing = BuiltinEasingFunctions.linear, onScrollEnd, } = options ?? {};
|
|
35
|
+
let animationFrameId;
|
|
36
|
+
const scrollProperty = direction === ScrollDirections.vertical ? "scrollTop" : "scrollLeft";
|
|
37
|
+
const startPosition = container[scrollProperty];
|
|
38
|
+
const distance = targetOffset - startPosition;
|
|
39
|
+
// --- 基于速度的自适应时长逻辑 ---
|
|
40
|
+
const PIXELS_PER_MS = 1.5; // 定义一个理想滚动速度 (1500px/s)
|
|
41
|
+
const MIN_DURATION = 200; // 保证动画可被感知的最小时长
|
|
42
|
+
// 根据速度计算理想时长
|
|
43
|
+
const idealDuration = Math.abs(distance) / PIXELS_PER_MS;
|
|
44
|
+
// 最终时长 = 在[最小时长, 用户设定的最大时长]区间内,取理想时长
|
|
45
|
+
const finalDuration = Math.max(MIN_DURATION, Math.min(idealDuration, userMaxDuration));
|
|
46
|
+
// --- 逻辑结束 ---
|
|
47
|
+
if (Math.abs(distance) < 1) {
|
|
48
|
+
onScrollEnd?.();
|
|
49
|
+
return () => { };
|
|
50
|
+
}
|
|
51
|
+
const startTime = performance.now();
|
|
52
|
+
const easingFunction = typeof easing === "string" ? EASING_FUNCTIONS[easing] : easing;
|
|
53
|
+
const animationLoop = (currentTime) => {
|
|
54
|
+
const elapsedTime = currentTime - startTime;
|
|
55
|
+
const progress = Math.min(elapsedTime / finalDuration, 1);
|
|
56
|
+
const easedProgress = easingFunction(progress);
|
|
57
|
+
container[scrollProperty] = startPosition + distance * easedProgress;
|
|
58
|
+
if (progress < 1) {
|
|
59
|
+
animationFrameId = requestAnimationFrame(animationLoop);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
container[scrollProperty] = targetOffset;
|
|
63
|
+
onScrollEnd?.();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
animationFrameId = requestAnimationFrame(animationLoop);
|
|
67
|
+
return () => {
|
|
68
|
+
cancelAnimationFrame(animationFrameId);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// 3. 核心计算函数
|
|
72
|
+
// ==========================================================
|
|
73
|
+
export function calculateScrollOffset(container, target, direction, options) {
|
|
74
|
+
const { targetAnchor = Anchors.start, containerAnchor = Anchors.start, offset = 0, } = options ?? {};
|
|
75
|
+
const DIMS = {
|
|
76
|
+
vertical: {
|
|
77
|
+
clientSize: "clientHeight",
|
|
78
|
+
offsetPos: "offsetTop",
|
|
79
|
+
offsetSize: "offsetHeight",
|
|
80
|
+
scrollSize: "scrollHeight"
|
|
81
|
+
},
|
|
82
|
+
horizontal: {
|
|
83
|
+
clientSize: "clientWidth",
|
|
84
|
+
offsetPos: "offsetLeft",
|
|
85
|
+
offsetSize: "offsetWidth",
|
|
86
|
+
scrollSize: "scrollWidth",
|
|
87
|
+
},
|
|
88
|
+
}[direction];
|
|
89
|
+
const containerSize = container[DIMS.clientSize];
|
|
90
|
+
const targetPos = target[DIMS.offsetPos];
|
|
91
|
+
const targetSize = target[DIMS.offsetSize];
|
|
92
|
+
const maxScrollPos = container[DIMS.scrollSize] - containerSize;
|
|
93
|
+
if (maxScrollPos <= 0)
|
|
94
|
+
return 0;
|
|
95
|
+
let targetAnchorPos = targetPos;
|
|
96
|
+
if (targetAnchor === Anchors.middle)
|
|
97
|
+
targetAnchorPos += targetSize / 2;
|
|
98
|
+
if (targetAnchor === Anchors.end)
|
|
99
|
+
targetAnchorPos += targetSize;
|
|
100
|
+
let containerAnchorPos = 0;
|
|
101
|
+
if (typeof containerAnchor === "number") {
|
|
102
|
+
containerAnchorPos = containerSize * (containerAnchor / 100);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
if (containerAnchor === Anchors.middle)
|
|
106
|
+
containerAnchorPos = containerSize / 2;
|
|
107
|
+
if (containerAnchor === Anchors.end)
|
|
108
|
+
containerAnchorPos = containerSize;
|
|
109
|
+
}
|
|
110
|
+
let targetOffset = targetAnchorPos - containerAnchorPos;
|
|
111
|
+
const finalPixelOffset = parseOffset(offset, targetSize);
|
|
112
|
+
targetOffset += finalPixelOffset;
|
|
113
|
+
return Math.max(0, Math.min(targetOffset, maxScrollPos));
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=scroll-helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-helper.js","sourceRoot":"","sources":["../../src/utils/scroll-helper.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cites/react-hooks",
|
|
3
|
+
"description": "React hooks",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"clean": "rm -rf dist && rm -rf .cache",
|
|
8
|
+
"build": "tsc --build",
|
|
9
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
10
|
+
"pretest": "npm run build",
|
|
11
|
+
"test": "node --test './dist/**/*.test.js'"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"default": "./dist/core/index.js",
|
|
16
|
+
"types": "./dist/core/index.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./useBoundingClientRect": {
|
|
19
|
+
"default": "./dist/core/useBoundingClientRect.js",
|
|
20
|
+
"types": "./dist/core/useBoundingClientRect.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./useComposedRefs": {
|
|
23
|
+
"default": "./dist/core/useComposedRefs.js",
|
|
24
|
+
"types": "./dist/core/useComposedRefs.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./useDraggable": {
|
|
27
|
+
"default": "./dist/core/useDraggable.js",
|
|
28
|
+
"types": "./dist/core/useDraggable.d.ts"
|
|
29
|
+
},
|
|
30
|
+
"./useEventCallback": {
|
|
31
|
+
"default": "./dist/core/useEventCallback.js",
|
|
32
|
+
"types": "./dist/core/useEventCallback.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./useIsomorphicLayoutEffect": {
|
|
35
|
+
"default": "./dist/core/useIsomorphicLayoutEffect.js",
|
|
36
|
+
"types": "./dist/core/useIsomorphicLayoutEffect.d.ts"
|
|
37
|
+
},
|
|
38
|
+
"./useCustomScroller": {
|
|
39
|
+
"default": "./dist/core/useCustomScroller.js",
|
|
40
|
+
"types": "./dist/core/useCustomScroller.d.ts"
|
|
41
|
+
},
|
|
42
|
+
"./useKeepActiveItemIntoView": {
|
|
43
|
+
"default": "./dist/core/useKeepActiveItemIntoView.js",
|
|
44
|
+
"types": "./dist/core/useKeepActiveItemIntoView.d.ts"
|
|
45
|
+
},
|
|
46
|
+
"./useScrollIntoViewHelper": {
|
|
47
|
+
"default": "./dist/core/useScrollIntoViewHelper.js",
|
|
48
|
+
"types": "./dist/core/useScrollIntoViewHelper.d.ts"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"react",
|
|
53
|
+
"hooks"
|
|
54
|
+
],
|
|
55
|
+
"author": "Colin Cheng <zbinlin@outlook.com>",
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/zbinlin/react-hooks.git"
|
|
59
|
+
},
|
|
60
|
+
"files": [
|
|
61
|
+
"./dist/",
|
|
62
|
+
"README.md"
|
|
63
|
+
],
|
|
64
|
+
"license": "MIT",
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
67
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/jsdom": "^21.1.7",
|
|
71
|
+
"@types/node": "^22.15.19",
|
|
72
|
+
"@types/react": "^19.1.6",
|
|
73
|
+
"@types/react-dom": "^19.1.6",
|
|
74
|
+
"react": "^19.1.0",
|
|
75
|
+
"react-dom": "^19.1.0",
|
|
76
|
+
"typescript": "^5.8.3"
|
|
77
|
+
}
|
|
78
|
+
}
|