1- import { RefObject , useRef , useCallback , useEffect } from 'react' ;
1+ import {
2+ RefObject ,
3+ useRef ,
4+ useCallback ,
5+ useEffect ,
6+ useState ,
7+ Dispatch ,
8+ SetStateAction ,
9+ } from 'react' ;
210import useRefs from './useRefs' ;
311import useMeasures , { Measure } from './useMeasures' ;
412
13+ type CarouselItem = {
14+ refObject : RefObject < HTMLElement > ;
15+ isHidden : boolean ;
16+ setIsHidden : Dispatch < SetStateAction < boolean > > ;
17+ } ;
18+
519type CarouselReturn < T > = [
620 {
721 container : RefObject < T > ;
8- items : RefObject < HTMLElement > [ ] ;
22+ items : CarouselItem [ ] ;
923 } ,
1024 ( ) => void ,
1125 ( ) => void ,
@@ -19,26 +33,24 @@ function getMeanX(
1933 return Math . round ( ( previous . x + previous . width + target . x ) / 2 ) ;
2034}
2135
22- function setAriaAttributes (
36+ function setHiddenItems (
2337 measures : Measure [ ] ,
24- itemRefs : RefObject < HTMLElement > [ ] ,
38+ carouselItems : CarouselItem [ ] ,
2539 targetIndex : number ,
2640 width : number ,
2741) {
2842 if ( width !== 0 ) {
29- itemRefs . forEach ( ( item ) => {
30- const offsetLeftItem = item . current ?. offsetLeft || 0 ;
43+ carouselItems . forEach ( ( item ) => {
44+ const offsetLeftItem = item . refObject . current ?. offsetLeft || 0 ;
3145
3246 if (
3347 offsetLeftItem < measures [ targetIndex ] . x ||
34- offsetLeftItem + ( item . current ?. offsetWidth || 0 ) >
48+ offsetLeftItem + ( item . refObject . current ?. offsetWidth || 0 ) >
3549 measures [ targetIndex ] . x + width
3650 ) {
37- item . current ?. setAttribute ( 'aria-hidden' , 'true' ) ;
38- item . current ?. setAttribute ( 'tabIndex' , '-1' ) ;
51+ item . setIsHidden ( true ) ;
3952 } else {
40- item . current ?. removeAttribute ( 'aria-hidden' ) ;
41- item . current ?. removeAttribute ( 'tabIndex' ) ;
53+ item . setIsHidden ( false ) ;
4254 }
4355 } ) ;
4456 }
@@ -48,7 +60,7 @@ function scrollStep(
4860 direction : 'NEXT' | 'PREVIOUS' ,
4961 container : HTMLElement | null ,
5062 measures : Measure [ ] ,
51- itemRefs : RefObject < HTMLElement > [ ] ,
63+ carouselItems : CarouselItem [ ] ,
5264) {
5365 if ( ! container ) return ;
5466 const x = container . scrollLeft ;
@@ -62,7 +74,7 @@ function scrollStep(
6274 measures [ targetIndex ] ,
6375 measures [ targetIndex - 1 ] ,
6476 ) ;
65- setAriaAttributes ( measures , itemRefs , targetIndex , width ) ;
77+ setHiddenItems ( measures , carouselItems , targetIndex , width ) ;
6678 } else {
6779 const firstLeftHidden = measures
6880 . slice ( )
@@ -78,30 +90,36 @@ function scrollStep(
7890 measures [ targetIndex - 1 ] ,
7991 measures [ targetIndex ] ,
8092 ) ;
81- setAriaAttributes ( measures , itemRefs , targetIndex , width ) ;
93+ setHiddenItems ( measures , carouselItems , targetIndex , width ) ;
8294 }
8395}
8496
8597export default function useCarousel < T > ( itemCount = 0 ) : CarouselReturn < T > {
8698 const containerRef = useRef ( null ) ;
8799 const itemRefs = useRefs ( itemCount ) ;
88100 const measures = useMeasures ( itemRefs ) ;
101+ const carouselItems : CarouselItem [ ] = Array . from ( Array ( itemCount ) ) . map <
102+ CarouselItem
103+ > ( ( _ , i ) => {
104+ const [ isHidden , setIsHidden ] = useState ( false ) ;
105+ return Object . create ( { refObject : itemRefs [ i ++ ] , isHidden, setIsHidden } ) ;
106+ } ) ;
89107
90108 const previous = useCallback (
91- ( ) => scrollStep ( 'PREVIOUS' , containerRef . current , measures , itemRefs ) ,
109+ ( ) => scrollStep ( 'PREVIOUS' , containerRef . current , measures , carouselItems ) ,
92110 [ containerRef , measures ] ,
93111 ) ;
94112
95113 const next = useCallback (
96- ( ) => scrollStep ( 'NEXT' , containerRef . current , measures , itemRefs ) ,
114+ ( ) => scrollStep ( 'NEXT' , containerRef . current , measures , carouselItems ) ,
97115 [ containerRef , measures ] ,
98116 ) ;
99117
100118 useEffect ( ( ) => {
101119 if ( measures !== undefined && measures . length !== 0 ) {
102- setAriaAttributes (
120+ setHiddenItems (
103121 measures ,
104- itemRefs ,
122+ carouselItems ,
105123 0 ,
106124 ( containerRef . current as HTMLElement | null ) ?. clientWidth || 0 ,
107125 ) ;
@@ -111,7 +129,7 @@ export default function useCarousel<T>(itemCount = 0): CarouselReturn<T> {
111129 return [
112130 {
113131 container : containerRef ,
114- items : itemRefs ,
132+ items : carouselItems ,
115133 } ,
116134 previous ,
117135 next ,
0 commit comments