1- import React , { useCallback , useMemo , useState } from "react"
1+ import React , { useCallback , useMemo , useState , useRef } from "react"
22import styled from "styled-components"
3+ import { useVirtualizer } from "@tanstack/react-virtual"
34import Flex from "src/components/templates/flex"
45import Search from "src/components/search"
56import { Box } from "src/index"
@@ -20,9 +21,11 @@ const Dropdown = ({
2021 value,
2122 hasSearch,
2223 searchMargin = [ 4 ] ,
24+ gap = 0 ,
2325 ...rest
2426} ) => {
2527 const [ searchParams , setSearchParams ] = useState ( "" )
28+
2629 const filteredItems = useMemo ( ( ) => {
2730 if ( ! searchParams ) return items
2831 const searchLowerCase = searchParams . toLowerCase ( )
@@ -32,12 +35,26 @@ const Dropdown = ({
3235 return false
3336 } )
3437 } , [ items , searchParams ] )
38+
3539 const handleSearch = useCallback (
3640 event => {
3741 setSearchParams ( event . target . value )
3842 } ,
3943 [ setSearchParams ]
4044 )
45+
46+ const ref = useRef ( )
47+ const measuresRef = useRef ( { } )
48+
49+ const rowVirtualizer = useVirtualizer ( {
50+ count : filteredItems . length ,
51+ getScrollElement : ( ) => ref . current ,
52+ scrollOffsetFn : event => ( event ? event . target . scrollTop - ref . current . offsetTop : 0 ) ,
53+ overscan : 3 ,
54+ enableSmoothScroll : false ,
55+ estimateSize : ( ) => 30 ,
56+ } )
57+
4158 return (
4259 < Container
4360 as = "ul"
@@ -61,7 +78,47 @@ const Dropdown = ({
6178 />
6279 </ Box >
6380 ) }
64- { filteredItems . map ( item => renderItem ( { item, itemProps, value, onItemClick } ) ) }
81+ < div
82+ ref = { ref }
83+ style = { {
84+ minHeight : "100%" ,
85+ width : "100%" ,
86+ overflow : "auto" ,
87+ } }
88+ >
89+ < div
90+ style = { {
91+ minHeight : `${ rowVirtualizer . getTotalSize ( ) } px` ,
92+ width : "100%" ,
93+ position : "relative" ,
94+ } }
95+ >
96+ { rowVirtualizer . getVirtualItems ( ) . map ( virtualRow => (
97+ < div
98+ key = { virtualRow . key }
99+ data-index = { virtualRow . index }
100+ ref = { rowVirtualizer . measureElement }
101+ style = { {
102+ position : "absolute" ,
103+ top : 0 ,
104+ left : 0 ,
105+ width : "100%" ,
106+ transform : `translateY(${ virtualRow . start } px)` ,
107+ padding : gap * 2 ,
108+ overflow : "hidden" ,
109+ } }
110+ >
111+ { renderItem ( {
112+ item : filteredItems [ virtualRow . index ] ,
113+ index : virtualRow . index ,
114+ itemProps,
115+ value,
116+ onItemClick,
117+ } ) }
118+ </ div >
119+ ) ) }
120+ </ div >
121+ </ div >
65122 </ Container >
66123 )
67124}
0 commit comments