-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.ts
55 lines (47 loc) · 1.73 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { createRef, RefObject, useRef, useCallback, useState } from 'react';
import useDeepCompareEffect from 'use-deep-compare-effect';
type ScrollToElementRefs = {
[key: string]: RefObject<HTMLElement>;
};
/**
* Removes all special characters and spaces except alphanumeric characters
* @param str
* @returns string
*/
const removeSpecialCharacters = (str: string) => str.replace(/[^a-zA-Z0-9]/g, '');
const defaultScrollIntoViewOptions: ScrollIntoViewOptions = {
behavior: 'smooth',
};
export const useScrollToElement = (
elementNames: string[],
scrollIntoViewOptions: ScrollIntoViewOptions = defaultScrollIntoViewOptions,
) => {
const scrollToElementRefs = useRef<ScrollToElementRefs>({});
const [trigger, setTrigger] = useState(0);
useDeepCompareEffect(() => {
scrollToElementRefs.current = elementNames.reduce((acc, elementName, index) => {
acc[removeSpecialCharacters(elementName) || index] = createRef<HTMLElement>();
return acc;
}, {} as ScrollToElementRefs);
//set trigger to force update to below handlers
setTrigger(prevState => prevState + 1);
}, [elementNames]);
const scrollToElementClickHandler = useCallback(
(elementName: string, index: number = 0) => {
// scroll to element ref if it exists
scrollToElementRefs?.current[
removeSpecialCharacters(elementName) || index
].current?.scrollIntoView(scrollIntoViewOptions);
},
[trigger, scrollIntoViewOptions],
);
const getScrollToElementRef = useCallback(
(elementName: string, index: number = 0) => {
return scrollToElementRefs?.current[
removeSpecialCharacters(elementName) || index
];
},
[trigger],
);
return { getScrollToElementRef, scrollToElementClickHandler };
};