Skip to content

Commit 3a2af4d

Browse files
committed
feat: react-hook-scroll npm publish v 0.1.0
1 parent de6d80e commit 3a2af4d

5 files changed

Lines changed: 138 additions & 17 deletions

File tree

dist/VirtualScroll.hook.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useEffect, useMemo, useRef, useState } from "react";
2+
export const useVirtualScroll = ({
3+
list,
4+
onItemSelected
5+
}) => {
6+
const scrollList = useMemo(() => [null, null, ...list, null, null], [list]);
7+
const scrollRef = useRef(null);
8+
const [centerIndex, setCenterIndex] = useState(0);
9+
useEffect(() => {
10+
if (scrollRef.current) {
11+
const scrollContainer = scrollRef.current;
12+
const updateCenterItemWithRef = () => {
13+
const containerHeight = scrollContainer.clientHeight;
14+
const itemHeight = 2.5 * 16;
15+
const scrollTop = scrollContainer.scrollTop;
16+
const centerScroll = containerHeight / 2;
17+
const centerItemIndex = Math.floor((scrollTop + centerScroll) / itemHeight);
18+
setCenterIndex(centerItemIndex);
19+
onItemSelected(scrollList[centerItemIndex]);
20+
};
21+
scrollContainer.addEventListener("scroll", updateCenterItemWithRef);
22+
updateCenterItemWithRef();
23+
return () => {
24+
scrollContainer.removeEventListener("scroll", updateCenterItemWithRef);
25+
};
26+
}
27+
}, [scrollList, onItemSelected]);
28+
return {
29+
state: {
30+
scrollList,
31+
scrollRef,
32+
centerIndex
33+
}
34+
};
35+
};

src/index.js

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1 @@
1-
import React from 'react';
2-
import ReactDOM from 'react-dom/client';
3-
import './index.css';
4-
import App from './App';
5-
import reportWebVitals from './reportWebVitals';
6-
7-
const root = ReactDOM.createRoot(document.getElementById('root'));
8-
root.render(
9-
<React.StrictMode>
10-
<App />
11-
</React.StrictMode>
12-
);
13-
14-
// If you want to start measuring performance in your app, pass a function
15-
// to log results (for example: reportWebVitals(console.log))
16-
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17-
reportWebVitals();
1+
export { default as VirtualScroll } from "./VirtualScroll";

src/lib/VirtualScroll.hook.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useEffect, useMemo, useRef, useState } from "react";
2+
3+
export const useVirtualScroll = ({ list, onItemSelected }) => {
4+
const scrollList = useMemo(() => [null, null, ...list, null, null], [list]);
5+
const scrollRef = useRef(null);
6+
const [centerIndex, setCenterIndex] = useState(0);
7+
8+
useEffect(() => {
9+
if (scrollRef.current) {
10+
const scrollContainer = scrollRef.current;
11+
const updateCenterItemWithRef = () => {
12+
const containerHeight = scrollContainer.clientHeight;
13+
const itemHeight = 2.5 * 16;
14+
const scrollTop = scrollContainer.scrollTop;
15+
const centerScroll = containerHeight / 2;
16+
const centerItemIndex = Math.floor(
17+
(scrollTop + centerScroll) / itemHeight
18+
);
19+
setCenterIndex(centerItemIndex);
20+
21+
onItemSelected(scrollList[centerItemIndex]);
22+
};
23+
scrollContainer.addEventListener("scroll", updateCenterItemWithRef);
24+
25+
updateCenterItemWithRef();
26+
27+
return () => {
28+
scrollContainer.removeEventListener("scroll", updateCenterItemWithRef);
29+
};
30+
}
31+
}, [scrollList, onItemSelected]);
32+
33+
return {
34+
state: {
35+
scrollList,
36+
scrollRef,
37+
centerIndex,
38+
},
39+
};
40+
};

src/lib/VirtualScroll.jsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useVirtualScroll } from "./VirtualScroll.hook";
2+
import "./VirtualScroll.styles.css";
3+
4+
export const VirtualScroll = ({ list, onItemSelected, width }) => {
5+
const {
6+
state: { scrollList, scrollRef, centerIndex },
7+
} = useVirtualScroll({
8+
list,
9+
onItemSelected,
10+
});
11+
12+
return (
13+
<div ref={scrollRef} width={width} className="Container">
14+
<div className="List">
15+
{scrollList.map((item, index) => (
16+
<div key={index}>
17+
{index === centerIndex ? (
18+
<div className="CenterItem">{item}</div>
19+
) : (
20+
<div className="Item">{item}</div>
21+
)}
22+
</div>
23+
))}
24+
</div>
25+
</div>
26+
);
27+
};

src/lib/VirtualScroll.styles.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.Container {
2+
width: 100px;
3+
height: 13rem;
4+
overflow: auto;
5+
box-sizing: border-box;
6+
scroll-behavior: smooth;
7+
&::-webkit-scrollbar {
8+
display: none;
9+
}
10+
}
11+
12+
.List {
13+
display: flex;
14+
flex-direction: column;
15+
list-style: none;
16+
}
17+
18+
.Item {
19+
display: flex;
20+
justify-content: center;
21+
align-items: center;
22+
height: 2.5rem;
23+
font-weight: 300;
24+
color: #374151;
25+
transition: background-color 0.3s;
26+
}
27+
28+
.CenterItem {
29+
display: flex;
30+
justify-content: center;
31+
align-items: center;
32+
height: 2.5rem;
33+
font-weight: 300;
34+
background-color: rgba(200, 200, 200, 0.3);
35+
}

0 commit comments

Comments
 (0)