use-scroller 1.1.0 → 2.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/README.md +406 -72
- package/dist/chunk-BDIJT5M4.js +1188 -0
- package/dist/core.d.ts +121 -0
- package/dist/core.js +36 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +346 -0
- package/package.json +39 -26
- package/dist/cjs/hooks/use-iso-morphic-effect.d.ts +0 -2
- package/dist/cjs/hooks/use-iso-morphic-effect.js +0 -6
- package/dist/cjs/hooks/use-scroll.d.ts +0 -20
- package/dist/cjs/hooks/use-scroll.js +0 -90
- package/dist/cjs/hooks/use-window-scroll.d.ts +0 -13
- package/dist/cjs/hooks/use-window-scroll.js +0 -60
- package/dist/cjs/index.d.ts +0 -3
- package/dist/cjs/index.js +0 -19
- package/dist/cjs/scroller.d.ts +0 -10
- package/dist/cjs/scroller.js +0 -97
- package/dist/cjs/types.d.ts +0 -17
- package/dist/cjs/types.js +0 -2
- package/dist/cjs/utils.d.ts +0 -24
- package/dist/cjs/utils.js +0 -79
- package/dist/esm/hooks/use-iso-morphic-effect.d.ts +0 -2
- package/dist/esm/hooks/use-iso-morphic-effect.js +0 -3
- package/dist/esm/hooks/use-scroll.d.ts +0 -20
- package/dist/esm/hooks/use-scroll.js +0 -86
- package/dist/esm/hooks/use-window-scroll.d.ts +0 -13
- package/dist/esm/hooks/use-window-scroll.js +0 -56
- package/dist/esm/index.d.ts +0 -3
- package/dist/esm/index.js +0 -3
- package/dist/esm/scroller.d.ts +0 -10
- package/dist/esm/scroller.js +0 -93
- package/dist/esm/types.d.ts +0 -17
- package/dist/esm/types.js +0 -1
- package/dist/esm/utils.d.ts +0 -24
- package/dist/esm/utils.js +0 -72
- package/src/hooks/use-iso-morphic-effect.ts +0 -4
- package/src/hooks/use-scroll.ts +0 -95
- package/src/hooks/use-window-scroll.ts +0 -60
- package/src/index.ts +0 -3
- package/src/scroller.ts +0 -110
- package/src/types.ts +0 -21
- package/src/utils.ts +0 -90
package/dist/esm/scroller.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { defaultScrollOptions, getEasing, resolveScrollValues, validateElement } from './utils';
|
|
2
|
-
export function scroller(_a) {
|
|
3
|
-
var container = _a.container, _b = _a.options, options = _b === void 0 ? defaultScrollOptions : _b;
|
|
4
|
-
validateElement(container);
|
|
5
|
-
var duration = options.duration, easingOption = options.easingOption, direction = options.direction;
|
|
6
|
-
var _c = resolveScrollValues(container), scrollLeft = _c.scrollLeft, scrollTop = _c.scrollTop, clientWidth = _c.clientWidth, clientHeight = _c.clientHeight, scrollWidth = _c.scrollWidth, scrollHeight = _c.scrollHeight;
|
|
7
|
-
/**
|
|
8
|
-
* Scroll the Element or Window to the given
|
|
9
|
-
* position.
|
|
10
|
-
*
|
|
11
|
-
* @param {number} from the current scroll position.
|
|
12
|
-
* @param {number} to the new position to scroll.
|
|
13
|
-
* @param {string} layout the scroll direction.
|
|
14
|
-
*/
|
|
15
|
-
function scrollTo(from, to, layout) {
|
|
16
|
-
if (layout === void 0) { layout = direction; }
|
|
17
|
-
var startTime = null;
|
|
18
|
-
var requestId = 0;
|
|
19
|
-
function loop(currentTime) {
|
|
20
|
-
if (!startTime)
|
|
21
|
-
startTime = currentTime;
|
|
22
|
-
var time = Math.min((currentTime - startTime) / duration, 1);
|
|
23
|
-
var easingFunc = getEasing(easingOption);
|
|
24
|
-
var currentPositionInTime = easingFunc(time) * (to - from) + from;
|
|
25
|
-
container.scrollTo({
|
|
26
|
-
left: layout === 'horizontal' ? currentPositionInTime : undefined,
|
|
27
|
-
top: layout === 'vertical' ? currentPositionInTime : undefined,
|
|
28
|
-
});
|
|
29
|
-
if (time < 1) {
|
|
30
|
-
requestId = requestAnimationFrame(loop);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
cancelAnimationFrame(requestId);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
requestId = requestAnimationFrame(loop);
|
|
37
|
-
}
|
|
38
|
-
function scrollToCenter() {
|
|
39
|
-
var from = 0;
|
|
40
|
-
var to = 0;
|
|
41
|
-
if (direction === 'vertical') {
|
|
42
|
-
var scrollYCenterPosition = (scrollHeight - clientHeight) / 2;
|
|
43
|
-
from = scrollTop;
|
|
44
|
-
to = scrollYCenterPosition;
|
|
45
|
-
}
|
|
46
|
-
if (direction === 'horizontal') {
|
|
47
|
-
var scrollXCenterPosition = (scrollWidth - clientWidth) / 2;
|
|
48
|
-
from = scrollLeft;
|
|
49
|
-
to = scrollXCenterPosition;
|
|
50
|
-
}
|
|
51
|
-
scrollTo(from, to, direction);
|
|
52
|
-
}
|
|
53
|
-
function scrollToTarget(target) {
|
|
54
|
-
validateElement(target);
|
|
55
|
-
var offsetTop = target.offsetTop, offsetLeft = target.offsetLeft;
|
|
56
|
-
var from = 0;
|
|
57
|
-
var to = 0;
|
|
58
|
-
if (direction === 'vertical') {
|
|
59
|
-
from = scrollTop;
|
|
60
|
-
to = offsetTop;
|
|
61
|
-
}
|
|
62
|
-
if (direction === 'horizontal') {
|
|
63
|
-
from = scrollLeft;
|
|
64
|
-
to = offsetLeft;
|
|
65
|
-
}
|
|
66
|
-
scrollTo(from, to, direction);
|
|
67
|
-
}
|
|
68
|
-
var scrollToLeft = function (offset) {
|
|
69
|
-
var scrollPosition = offset || scrollLeft - clientWidth;
|
|
70
|
-
scrollTo(scrollLeft, scrollPosition, 'horizontal');
|
|
71
|
-
};
|
|
72
|
-
var scrollToRight = function (offset) {
|
|
73
|
-
var scrollPosition = offset || scrollLeft + clientWidth;
|
|
74
|
-
scrollTo(scrollLeft, scrollPosition, 'horizontal');
|
|
75
|
-
};
|
|
76
|
-
var scrollToTop = function (offset) {
|
|
77
|
-
var scrollPosition = offset || scrollTop - clientHeight;
|
|
78
|
-
scrollTo(scrollTop, scrollPosition, 'vertical');
|
|
79
|
-
};
|
|
80
|
-
var scrollToBottom = function (offset) {
|
|
81
|
-
var scrollPosition = offset || scrollTop + clientHeight;
|
|
82
|
-
scrollTo(scrollTop, scrollPosition, 'vertical');
|
|
83
|
-
};
|
|
84
|
-
return {
|
|
85
|
-
scrollToLeft: scrollToLeft,
|
|
86
|
-
scrollToRight: scrollToRight,
|
|
87
|
-
scrollToTop: scrollToTop,
|
|
88
|
-
scrollToBottom: scrollToBottom,
|
|
89
|
-
scrollToTarget: scrollToTarget,
|
|
90
|
-
scrollToCenter: scrollToCenter,
|
|
91
|
-
scrollTo: scrollTo,
|
|
92
|
-
};
|
|
93
|
-
}
|
package/dist/esm/types.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export type ScrollOptions = {
|
|
2
|
-
direction: 'horizontal' | 'vertical';
|
|
3
|
-
duration: number;
|
|
4
|
-
easingOption: EasingOptions;
|
|
5
|
-
};
|
|
6
|
-
export type ScrollerProps = {
|
|
7
|
-
container: HTMLElement | Window;
|
|
8
|
-
options: ScrollOptions;
|
|
9
|
-
};
|
|
10
|
-
export type EasingOptions = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
|
|
11
|
-
export type EasingFunction = (t: number) => number;
|
|
12
|
-
export interface EasingFunctions {
|
|
13
|
-
linear: EasingFunction;
|
|
14
|
-
'ease-in': EasingFunction;
|
|
15
|
-
'ease-out': EasingFunction;
|
|
16
|
-
'ease-in-out': EasingFunction;
|
|
17
|
-
}
|
package/dist/esm/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/esm/utils.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { RefObject } from 'react';
|
|
2
|
-
import { EasingFunction, EasingFunctions, EasingOptions, ScrollOptions } from './types';
|
|
3
|
-
export declare const isServer: boolean;
|
|
4
|
-
export declare const defaultScrollOptions: ScrollOptions;
|
|
5
|
-
/**
|
|
6
|
-
* Resolves scroll values based on the type of param.
|
|
7
|
-
* @param {HTMLElement | Window} element
|
|
8
|
-
*/
|
|
9
|
-
export declare const resolveScrollValues: (element: HTMLElement | Window) => {
|
|
10
|
-
scrollLeft: number;
|
|
11
|
-
scrollTop: number;
|
|
12
|
-
scrollWidth: number;
|
|
13
|
-
clientWidth: number;
|
|
14
|
-
clientHeight: number;
|
|
15
|
-
scrollHeight: number;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Validate if element passed to the function is valid.
|
|
19
|
-
* @param {HTMLElement | Window} element
|
|
20
|
-
*/
|
|
21
|
-
export declare function validateElement(element?: HTMLElement | Window): void;
|
|
22
|
-
export declare const getElement: (ref: RefObject<HTMLElement>) => HTMLElement;
|
|
23
|
-
export declare const easingMap: EasingFunctions;
|
|
24
|
-
export declare const getEasing: (easing?: EasingOptions) => EasingFunction;
|
package/dist/esm/utils.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
export var isServer = typeof window === 'undefined' || typeof document === 'undefined';
|
|
2
|
-
export var defaultScrollOptions = {
|
|
3
|
-
direction: 'vertical',
|
|
4
|
-
duration: 300,
|
|
5
|
-
easingOption: 'ease-in-out',
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Resolves scroll values based on the type of param.
|
|
9
|
-
* @param {HTMLElement | Window} element
|
|
10
|
-
*/
|
|
11
|
-
export var resolveScrollValues = function (element) {
|
|
12
|
-
if (element === document.body ||
|
|
13
|
-
element === document.documentElement ||
|
|
14
|
-
element instanceof Window) {
|
|
15
|
-
return {
|
|
16
|
-
scrollLeft: document.body.scrollLeft || document.documentElement.scrollLeft,
|
|
17
|
-
scrollTop: document.body.scrollTop || document.documentElement.scrollTop,
|
|
18
|
-
scrollWidth: document.body.scrollWidth || document.documentElement.scrollWidth,
|
|
19
|
-
clientWidth: document.body.clientWidth || document.documentElement.clientWidth,
|
|
20
|
-
clientHeight: document.body.clientHeight || document.documentElement.clientHeight,
|
|
21
|
-
scrollHeight: document.body.scrollHeight || document.documentElement.scrollHeight,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
return {
|
|
25
|
-
scrollLeft: element.scrollLeft,
|
|
26
|
-
scrollTop: element.scrollTop,
|
|
27
|
-
scrollWidth: element.scrollWidth,
|
|
28
|
-
clientWidth: element.clientWidth,
|
|
29
|
-
clientHeight: element.clientHeight,
|
|
30
|
-
scrollHeight: element.scrollHeight,
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Validate if element passed to the function is valid.
|
|
35
|
-
* @param {HTMLElement | Window} element
|
|
36
|
-
*/
|
|
37
|
-
export function validateElement(element) {
|
|
38
|
-
if (element === undefined) {
|
|
39
|
-
throw new Error("The element passed to scroller() was undefined");
|
|
40
|
-
}
|
|
41
|
-
if (!(element instanceof HTMLElement || Window)) {
|
|
42
|
-
throw new TypeError("\n The element passed to scroller() must be a valid element. \n You passed ".concat(element, ".\n "));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export var getElement = function (ref) {
|
|
46
|
-
if (!ref.current) {
|
|
47
|
-
throw new Error("Could not resolve ref object: ".concat(ref.current));
|
|
48
|
-
}
|
|
49
|
-
return ref.current;
|
|
50
|
-
};
|
|
51
|
-
export var easingMap = {
|
|
52
|
-
linear: function (t) {
|
|
53
|
-
return t;
|
|
54
|
-
},
|
|
55
|
-
'ease-in': function (t) {
|
|
56
|
-
return t * t;
|
|
57
|
-
},
|
|
58
|
-
'ease-out': function (t) {
|
|
59
|
-
return t * (2 - t);
|
|
60
|
-
},
|
|
61
|
-
'ease-in-out': function (t) {
|
|
62
|
-
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
export var getEasing = function (easing) {
|
|
66
|
-
var easeFunc = easingMap[easing || defaultScrollOptions.easingOption];
|
|
67
|
-
if (!easeFunc) {
|
|
68
|
-
var options = Object.keys(easingMap).join(',');
|
|
69
|
-
throw new Error("Scroll error: scroller does not support an easing option of \"".concat(easing, "\". Supported options are ").concat(options));
|
|
70
|
-
}
|
|
71
|
-
return easeFunc;
|
|
72
|
-
};
|
package/src/hooks/use-scroll.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef, useState } from 'react'
|
|
2
|
-
import { scroller } from '../scroller'
|
|
3
|
-
import { ScrollOptions } from '../types'
|
|
4
|
-
import { defaultScrollOptions, getElement } from '../utils'
|
|
5
|
-
import { useIsoMorphicEffect } from './use-iso-morphic-effect'
|
|
6
|
-
|
|
7
|
-
export function useScroll<T extends HTMLElement>(props?: Partial<ScrollOptions>) {
|
|
8
|
-
const ref = useRef<T>(null)
|
|
9
|
-
const [state, setState] = useState(() => ({
|
|
10
|
-
left: 0,
|
|
11
|
-
top: 0,
|
|
12
|
-
isScrollable: false,
|
|
13
|
-
isScrolledLeft: false,
|
|
14
|
-
isScrolledRight: false,
|
|
15
|
-
isScrolledTop: false,
|
|
16
|
-
isScrolledBottom: false,
|
|
17
|
-
}))
|
|
18
|
-
const scrollOpt = { ...defaultScrollOptions, ...props }
|
|
19
|
-
|
|
20
|
-
const scroll = useCallback((from: number, to: number) => {
|
|
21
|
-
const container = getElement(ref)
|
|
22
|
-
const scrollContainer = scroller({ container, options: scrollOpt })
|
|
23
|
-
scrollContainer.scrollTo(from, to)
|
|
24
|
-
}, [])
|
|
25
|
-
|
|
26
|
-
const scrollCenter = useCallback(() => {
|
|
27
|
-
const container = getElement(ref)
|
|
28
|
-
const scrollContainer = scroller({ container, options: scrollOpt })
|
|
29
|
-
scrollContainer.scrollToCenter()
|
|
30
|
-
}, [])
|
|
31
|
-
|
|
32
|
-
const scrollTop = useCallback((offset?: number) => {
|
|
33
|
-
const container = getElement(ref)
|
|
34
|
-
const scrollContainer = scroller({ container, options: scrollOpt })
|
|
35
|
-
scrollContainer.scrollToTop(offset)
|
|
36
|
-
}, [])
|
|
37
|
-
|
|
38
|
-
const scrollBottom = useCallback((offset?: number) => {
|
|
39
|
-
const container = getElement(ref)
|
|
40
|
-
const scrollContainer = scroller({ container, options: scrollOpt })
|
|
41
|
-
scrollContainer.scrollToBottom(offset)
|
|
42
|
-
}, [])
|
|
43
|
-
|
|
44
|
-
const scrollRight = useCallback((offset?: number) => {
|
|
45
|
-
const container = getElement(ref)
|
|
46
|
-
const scrollContainer = scroller({ container, options: scrollOpt })
|
|
47
|
-
scrollContainer.scrollToRight(offset)
|
|
48
|
-
}, [])
|
|
49
|
-
|
|
50
|
-
const scrollLeft = useCallback((offset?: number) => {
|
|
51
|
-
const container = getElement(ref)
|
|
52
|
-
const scrollContainer = scroller({ container, options: scrollOpt })
|
|
53
|
-
scrollContainer.scrollToLeft(offset)
|
|
54
|
-
}, [])
|
|
55
|
-
|
|
56
|
-
useIsoMorphicEffect(() => {
|
|
57
|
-
const scrollContainer = ref.current
|
|
58
|
-
if (!scrollContainer) return
|
|
59
|
-
|
|
60
|
-
const { scrollWidth, clientWidth, clientHeight, scrollHeight } = scrollContainer
|
|
61
|
-
const isScrollable = clientWidth !== scrollWidth || clientHeight !== scrollHeight
|
|
62
|
-
setState((prev) => ({ ...prev, isScrollable }))
|
|
63
|
-
|
|
64
|
-
const handleScroll = () => {
|
|
65
|
-
if (scrollContainer) {
|
|
66
|
-
const { scrollLeft, scrollTop } = scrollContainer
|
|
67
|
-
const scrollState = {
|
|
68
|
-
...state,
|
|
69
|
-
isScrolledLeft: scrollLeft === 0,
|
|
70
|
-
isScrolledRight: scrollLeft >= scrollWidth - clientWidth,
|
|
71
|
-
isScrolledTop: scrollTop === 0,
|
|
72
|
-
isScrolledBottom: scrollTop >= scrollHeight - clientHeight,
|
|
73
|
-
left: scrollLeft,
|
|
74
|
-
top: scrollTop,
|
|
75
|
-
}
|
|
76
|
-
setState(scrollState)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
handleScroll()
|
|
81
|
-
scrollContainer?.addEventListener('scroll', handleScroll)
|
|
82
|
-
return () => scrollContainer?.removeEventListener('scroll', handleScroll)
|
|
83
|
-
}, [])
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
ref,
|
|
87
|
-
state,
|
|
88
|
-
scrollLeft,
|
|
89
|
-
scrollRight,
|
|
90
|
-
scrollBottom,
|
|
91
|
-
scrollTop,
|
|
92
|
-
scrollCenter,
|
|
93
|
-
scroll,
|
|
94
|
-
}
|
|
95
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { useCallback, useState } from 'react'
|
|
2
|
-
import { scroller } from '../scroller'
|
|
3
|
-
import { ScrollerProps, ScrollOptions } from '../types'
|
|
4
|
-
import { useIsoMorphicEffect } from './use-iso-morphic-effect'
|
|
5
|
-
import { defaultScrollOptions, resolveScrollValues } from '../utils'
|
|
6
|
-
|
|
7
|
-
export function useWindowScroll(props?: Partial<Omit<ScrollOptions, 'direction'>>) {
|
|
8
|
-
const [state, setState] = useState(() => ({
|
|
9
|
-
left: 0,
|
|
10
|
-
top: 0,
|
|
11
|
-
isScrolledTop: false,
|
|
12
|
-
isScrolledBottom: false,
|
|
13
|
-
}))
|
|
14
|
-
|
|
15
|
-
const scrollArgs: ScrollerProps = {
|
|
16
|
-
container: window,
|
|
17
|
-
options: { ...defaultScrollOptions, ...props },
|
|
18
|
-
}
|
|
19
|
-
const scroll = useCallback((from: number, to: number) => {
|
|
20
|
-
const scrollContainer = scroller(scrollArgs)
|
|
21
|
-
scrollContainer.scrollTo(from, to)
|
|
22
|
-
}, [])
|
|
23
|
-
|
|
24
|
-
const scrollToTarget = useCallback((currentTarget: HTMLElement) => {
|
|
25
|
-
const scrollContainer = scroller(scrollArgs)
|
|
26
|
-
scrollContainer.scrollToTarget(currentTarget)
|
|
27
|
-
}, [])
|
|
28
|
-
|
|
29
|
-
const scrollTop = useCallback((offset?: number | undefined) => {
|
|
30
|
-
const scrollContainer = scroller(scrollArgs)
|
|
31
|
-
scrollContainer.scrollToTop(offset)
|
|
32
|
-
}, [])
|
|
33
|
-
|
|
34
|
-
const scrollBottom = useCallback((offset?: number | undefined) => {
|
|
35
|
-
const scrollContainer = scroller(scrollArgs)
|
|
36
|
-
scrollContainer.scrollToBottom(offset)
|
|
37
|
-
}, [])
|
|
38
|
-
|
|
39
|
-
useIsoMorphicEffect(() => {
|
|
40
|
-
const handleScroll = () => {
|
|
41
|
-
if (window) {
|
|
42
|
-
const { scrollLeft, scrollTop, scrollHeight, clientHeight } = resolveScrollValues(window)
|
|
43
|
-
const scrollState = {
|
|
44
|
-
...state,
|
|
45
|
-
isScrolledTop: scrollTop === 0,
|
|
46
|
-
isScrolledBottom: scrollTop >= scrollHeight - clientHeight,
|
|
47
|
-
left: scrollLeft,
|
|
48
|
-
top: scrollTop,
|
|
49
|
-
}
|
|
50
|
-
setState(scrollState)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
handleScroll()
|
|
55
|
-
window?.addEventListener('scroll', handleScroll)
|
|
56
|
-
return () => window?.removeEventListener('scroll', handleScroll)
|
|
57
|
-
}, [])
|
|
58
|
-
|
|
59
|
-
return { state, scrollTop, scrollBottom, scrollToTarget, scroll }
|
|
60
|
-
}
|
package/src/index.ts
DELETED
package/src/scroller.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { ScrollerProps } from './types'
|
|
2
|
-
import { defaultScrollOptions, getEasing, resolveScrollValues, validateElement } from './utils'
|
|
3
|
-
|
|
4
|
-
export function scroller({ container, options = defaultScrollOptions }: ScrollerProps) {
|
|
5
|
-
validateElement(container)
|
|
6
|
-
|
|
7
|
-
const { duration, easingOption, direction } = options
|
|
8
|
-
const { scrollLeft, scrollTop, clientWidth, clientHeight, scrollWidth, scrollHeight } =
|
|
9
|
-
resolveScrollValues(container)
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Scroll the Element or Window to the given
|
|
13
|
-
* position.
|
|
14
|
-
*
|
|
15
|
-
* @param {number} from the current scroll position.
|
|
16
|
-
* @param {number} to the new position to scroll.
|
|
17
|
-
* @param {string} layout the scroll direction.
|
|
18
|
-
*/
|
|
19
|
-
function scrollTo(from: number, to: number, layout: 'horizontal' | 'vertical' = direction) {
|
|
20
|
-
let startTime: number | null = null
|
|
21
|
-
let requestId = 0
|
|
22
|
-
|
|
23
|
-
function loop(currentTime: number) {
|
|
24
|
-
if (!startTime) startTime = currentTime
|
|
25
|
-
|
|
26
|
-
const time = Math.min((currentTime - startTime) / duration, 1)
|
|
27
|
-
const easingFunc = getEasing(easingOption)
|
|
28
|
-
const currentPositionInTime = easingFunc(time) * (to - from) + from
|
|
29
|
-
|
|
30
|
-
container.scrollTo({
|
|
31
|
-
left: layout === 'horizontal' ? currentPositionInTime : undefined,
|
|
32
|
-
top: layout === 'vertical' ? currentPositionInTime : undefined,
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
if (time < 1) {
|
|
36
|
-
requestId = requestAnimationFrame(loop)
|
|
37
|
-
} else {
|
|
38
|
-
cancelAnimationFrame(requestId)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
requestId = requestAnimationFrame(loop)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function scrollToCenter() {
|
|
45
|
-
let from = 0
|
|
46
|
-
let to = 0
|
|
47
|
-
|
|
48
|
-
if (direction === 'vertical') {
|
|
49
|
-
const scrollYCenterPosition = (scrollHeight - clientHeight) / 2
|
|
50
|
-
from = scrollTop
|
|
51
|
-
to = scrollYCenterPosition
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (direction === 'horizontal') {
|
|
55
|
-
const scrollXCenterPosition = (scrollWidth - clientWidth) / 2
|
|
56
|
-
from = scrollLeft
|
|
57
|
-
to = scrollXCenterPosition
|
|
58
|
-
}
|
|
59
|
-
scrollTo(from, to, direction)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function scrollToTarget(target: HTMLElement) {
|
|
63
|
-
validateElement(target)
|
|
64
|
-
const { offsetTop, offsetLeft } = target
|
|
65
|
-
let from = 0
|
|
66
|
-
let to = 0
|
|
67
|
-
|
|
68
|
-
if (direction === 'vertical') {
|
|
69
|
-
from = scrollTop
|
|
70
|
-
to = offsetTop
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (direction === 'horizontal') {
|
|
74
|
-
from = scrollLeft
|
|
75
|
-
to = offsetLeft
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
scrollTo(from, to, direction)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const scrollToLeft = (offset?: number) => {
|
|
82
|
-
const scrollPosition = offset || scrollLeft - clientWidth
|
|
83
|
-
scrollTo(scrollLeft, scrollPosition, 'horizontal')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const scrollToRight = (offset?: number) => {
|
|
87
|
-
const scrollPosition = offset || scrollLeft + clientWidth
|
|
88
|
-
scrollTo(scrollLeft, scrollPosition, 'horizontal')
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const scrollToTop = (offset?: number) => {
|
|
92
|
-
const scrollPosition = offset || scrollTop - clientHeight
|
|
93
|
-
scrollTo(scrollTop, scrollPosition, 'vertical')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const scrollToBottom = (offset?: number) => {
|
|
97
|
-
const scrollPosition = offset || scrollTop + clientHeight
|
|
98
|
-
scrollTo(scrollTop, scrollPosition, 'vertical')
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
scrollToLeft,
|
|
103
|
-
scrollToRight,
|
|
104
|
-
scrollToTop,
|
|
105
|
-
scrollToBottom,
|
|
106
|
-
scrollToTarget,
|
|
107
|
-
scrollToCenter,
|
|
108
|
-
scrollTo,
|
|
109
|
-
}
|
|
110
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export type ScrollOptions = {
|
|
2
|
-
direction: 'horizontal' | 'vertical'
|
|
3
|
-
duration: number
|
|
4
|
-
easingOption: EasingOptions
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export type ScrollerProps = {
|
|
8
|
-
container: HTMLElement | Window
|
|
9
|
-
options: ScrollOptions
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type EasingOptions = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out'
|
|
13
|
-
|
|
14
|
-
export type EasingFunction = (t: number) => number
|
|
15
|
-
|
|
16
|
-
export interface EasingFunctions {
|
|
17
|
-
linear: EasingFunction
|
|
18
|
-
'ease-in': EasingFunction
|
|
19
|
-
'ease-out': EasingFunction
|
|
20
|
-
'ease-in-out': EasingFunction
|
|
21
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { RefObject } from 'react'
|
|
2
|
-
import { EasingFunction, EasingFunctions, EasingOptions, ScrollOptions } from './types'
|
|
3
|
-
|
|
4
|
-
export const isServer = typeof window === 'undefined' || typeof document === 'undefined'
|
|
5
|
-
|
|
6
|
-
export const defaultScrollOptions: ScrollOptions = {
|
|
7
|
-
direction: 'vertical',
|
|
8
|
-
duration: 300,
|
|
9
|
-
easingOption: 'ease-in-out',
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Resolves scroll values based on the type of param.
|
|
14
|
-
* @param {HTMLElement | Window} element
|
|
15
|
-
*/
|
|
16
|
-
export const resolveScrollValues = (element: HTMLElement | Window) => {
|
|
17
|
-
if (
|
|
18
|
-
element === document.body ||
|
|
19
|
-
element === document.documentElement ||
|
|
20
|
-
element instanceof Window
|
|
21
|
-
) {
|
|
22
|
-
return {
|
|
23
|
-
scrollLeft: document.body.scrollLeft || document.documentElement.scrollLeft,
|
|
24
|
-
scrollTop: document.body.scrollTop || document.documentElement.scrollTop,
|
|
25
|
-
scrollWidth: document.body.scrollWidth || document.documentElement.scrollWidth,
|
|
26
|
-
clientWidth: document.body.clientWidth || document.documentElement.clientWidth,
|
|
27
|
-
clientHeight: document.body.clientHeight || document.documentElement.clientHeight,
|
|
28
|
-
scrollHeight: document.body.scrollHeight || document.documentElement.scrollHeight,
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
scrollLeft: element.scrollLeft,
|
|
33
|
-
scrollTop: element.scrollTop,
|
|
34
|
-
scrollWidth: element.scrollWidth,
|
|
35
|
-
clientWidth: element.clientWidth,
|
|
36
|
-
clientHeight: element.clientHeight,
|
|
37
|
-
scrollHeight: element.scrollHeight,
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Validate if element passed to the function is valid.
|
|
43
|
-
* @param {HTMLElement | Window} element
|
|
44
|
-
*/
|
|
45
|
-
export function validateElement(element?: HTMLElement | Window) {
|
|
46
|
-
if (element === undefined) {
|
|
47
|
-
throw new Error(`The element passed to scroller() was undefined`)
|
|
48
|
-
}
|
|
49
|
-
if (!(element instanceof HTMLElement || Window)) {
|
|
50
|
-
throw new TypeError(
|
|
51
|
-
`
|
|
52
|
-
The element passed to scroller() must be a valid element.
|
|
53
|
-
You passed ${element}.
|
|
54
|
-
`
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const getElement = (ref: RefObject<HTMLElement>) => {
|
|
60
|
-
if (!ref.current) {
|
|
61
|
-
throw new Error(`Could not resolve ref object: ${ref.current}`)
|
|
62
|
-
}
|
|
63
|
-
return ref.current
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export const easingMap: EasingFunctions = {
|
|
67
|
-
linear(t: number) {
|
|
68
|
-
return t
|
|
69
|
-
},
|
|
70
|
-
'ease-in'(t: number) {
|
|
71
|
-
return t * t
|
|
72
|
-
},
|
|
73
|
-
'ease-out'(t: number) {
|
|
74
|
-
return t * (2 - t)
|
|
75
|
-
},
|
|
76
|
-
'ease-in-out'(t: number) {
|
|
77
|
-
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
|
|
78
|
-
},
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export const getEasing = (easing?: EasingOptions): EasingFunction => {
|
|
82
|
-
const easeFunc = easingMap[easing || defaultScrollOptions.easingOption]
|
|
83
|
-
if (!easeFunc) {
|
|
84
|
-
const options = Object.keys(easingMap).join(',')
|
|
85
|
-
throw new Error(
|
|
86
|
-
`Scroll error: scroller does not support an easing option of "${easing}". Supported options are ${options}`
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
return easeFunc
|
|
90
|
-
}
|