33import  {  tString ,  useLanguage  }  from  '@/intl/client' ; 
44import  {  tcls  }  from  '@/lib/tailwind' ; 
55import  *  as  React  from  'react' ; 
6+ import  {  useScrollListener  }  from  '../hooks/useScrollListener' ; 
67import  {  Button  }  from  './Button' ; 
78
89/** 
@@ -46,63 +47,61 @@ export function ScrollContainer(props: ScrollContainerProps) {
4647
4748    const  language  =  useLanguage ( ) ; 
4849
49-     React . useEffect ( ( )  =>  { 
50+     useScrollListener ( ( )  =>  { 
5051        const  container  =  containerRef . current ; 
5152        if  ( ! container )  { 
5253            return ; 
5354        } 
5455
55-         // Update scroll position on scroll using requestAnimationFrame 
56-         const  scrollListener : EventListener  =  ( )  =>  { 
57-             requestAnimationFrame ( ( )  =>  { 
58-                 setScrollPosition ( 
59-                     orientation  ===  'horizontal'  ? container . scrollLeft  : container . scrollTop 
60-                 ) ; 
61-             } ) ; 
62-         } ; 
63-         container . addEventListener ( 'scroll' ,  scrollListener ) ; 
56+         setScrollPosition ( 
57+             orientation  ===  'horizontal'  ? container . scrollLeft  : container . scrollTop 
58+         ) ; 
59+     } ,  containerRef ) ; 
60+ 
61+     React . useEffect ( ( )  =>  { 
62+         const  container  =  containerRef . current ; 
63+         if  ( ! container )  { 
64+             return ; 
65+         } 
6466
6567        // Update max scroll position using resize observer 
66-         const  resizeObserver  =  new  ResizeObserver ( ( entries )  =>  { 
67-             const  containerEntry  =  entries . find ( ( i )   =>   i . target   ===   containerRef . current ) ; 
68-             if  ( containerEntry )  { 
68+         const  ro  =  new  ResizeObserver ( ( entries )  =>  { 
69+             const  [ entry ]  =  entries ; 
70+             if  ( entry )  { 
6971                setScrollSize ( 
7072                    orientation  ===  'horizontal' 
71-                         ? containerEntry . target . scrollWidth  -  containerEntry . target . clientWidth  -  1 
72-                         : containerEntry . target . scrollHeight  - 
73-                               containerEntry . target . clientHeight  - 
74-                               1 
73+                         ? entry . target . scrollWidth  -  entry . target . clientWidth  -  1 
74+                         : entry . target . scrollHeight  -  entry . target . clientHeight  -  1 
7575                ) ; 
7676            } 
7777        } ) ; 
78-         resizeObserver . observe ( container ) ; 
7978
80-         return  ( )  =>  { 
81-             container . removeEventListener ( 'scroll' ,  scrollListener ) ; 
82-             resizeObserver . disconnect ( ) ; 
83-         } ; 
79+         ro . observe ( container ) ; 
80+ 
81+         return  ( )  =>  ro . disconnect ( ) ; 
8482    } ,  [ orientation ] ) ; 
8583
86-     // Scroll to the active item 
8784    React . useEffect ( ( )  =>  { 
8885        const  container  =  containerRef . current ; 
89-         if  ( ! container   ||   ! activeId )  { 
86+         if  ( ! container )  { 
9087            return ; 
9188        } 
92-         const   activeItem   =   container . querySelector ( `# ${ CSS . escape ( activeId ) } ` ) ; 
93-         if   ( activeItem )   { 
94-              activeItem . scrollIntoView ( { 
95-                  inline :  'center' , 
96-                  block :  'center' , 
97-             } ) ; 
89+         if   ( ! activeId )   { 
90+              return ; 
91+         } 
92+         const   activeItem   =   document . getElementById ( activeId ) ; 
93+         if   ( ! activeItem   ||   ! container . contains ( activeItem ) )   { 
94+             return ; 
9895        } 
96+         scrollToElementInContainer ( activeItem ,  container ) ; 
9997    } ,  [ activeId ] ) ; 
10098
10199    const  scrollFurther  =  ( )  =>  { 
102100        const  container  =  containerRef . current ; 
103101        if  ( ! container )  { 
104102            return ; 
105103        } 
104+ 
106105        container . scrollTo ( { 
107106            top : orientation  ===  'vertical'  ? scrollPosition  +  container . clientHeight  : undefined , 
108107            left : orientation  ===  'horizontal'  ? scrollPosition  +  container . clientWidth  : undefined , 
@@ -115,6 +114,7 @@ export function ScrollContainer(props: ScrollContainerProps) {
115114        if  ( ! container )  { 
116115            return ; 
117116        } 
117+ 
118118        container . scrollTo ( { 
119119            top : orientation  ===  'vertical'  ? scrollPosition  -  container . clientHeight  : undefined , 
120120            left : orientation  ===  'horizontal'  ? scrollPosition  -  container . clientWidth  : undefined , 
@@ -194,3 +194,25 @@ export function ScrollContainer(props: ScrollContainerProps) {
194194        </ div > 
195195    ) ; 
196196} 
197+ 
198+ /** 
199+  * Scroll to an element in a container. 
200+  */ 
201+ function  scrollToElementInContainer ( element : HTMLElement ,  container : HTMLElement )  { 
202+     const  containerRect  =  container . getBoundingClientRect ( ) ; 
203+     const  rect  =  element . getBoundingClientRect ( ) ; 
204+ 
205+     return  container . scrollTo ( { 
206+         top :
207+             container . scrollTop  + 
208+             ( rect . top  -  containerRect . top )  - 
209+             container . clientHeight  /  2  + 
210+             rect . height  /  2 , 
211+         left :
212+             container . scrollLeft  + 
213+             ( rect . left  -  containerRect . left )  - 
214+             container . clientWidth  /  2  + 
215+             rect . width  /  2 , 
216+         behavior : 'smooth' , 
217+     } ) ; 
218+ } 
0 commit comments