@@ -10,8 +10,10 @@ import { Component, Element, Event, Host, Listen, Method, Prop, h } from '@stenc
1010 shadow : true ,
1111} )
1212export class SegmentView implements ComponentInterface {
13- private initialScrollLeft = 0 ;
13+ private initialScrollLeft ?: number ;
1414 private previousScrollLeft = 0 ;
15+ private scrollEndTimeout : ReturnType < typeof setTimeout > | null = null ;
16+ private isTouching = false ;
1517
1618 @Element ( ) el ! : HTMLElement ;
1719
@@ -20,21 +22,31 @@ export class SegmentView implements ComponentInterface {
2022 */
2123 @Prop ( ) disabled = false ;
2224
25+ /**
26+ * Emitted when the segment view is scrolled.
27+ */
2328 @Event ( ) ionSegmentViewScroll ! : EventEmitter < { scrollDirection : string ; scrollDistance : number } > ;
2429
30+ /**
31+ * Emitted when the segment view scroll has ended.
32+ */
33+ @Event ( ) ionSegmentViewScrollEnd ! : EventEmitter < void > ;
34+
2535 @Listen ( 'scroll' )
2636 handleScroll ( ev : Event ) {
2737 const { initialScrollLeft, previousScrollLeft } = this ;
2838 const { scrollLeft, offsetWidth } = ev . target as HTMLElement ;
2939
40+ if ( initialScrollLeft === undefined ) {
41+ this . initialScrollLeft = scrollLeft ;
42+ }
43+
3044 const scrollDirection = scrollLeft > previousScrollLeft ? 'right' : 'left' ;
3145 this . previousScrollLeft = scrollLeft ;
3246
33- let scrollDistance = scrollLeft ;
34-
35- if ( scrollDirection === 'left' ) {
36- scrollDistance = initialScrollLeft - scrollLeft ;
37- }
47+ // If the scroll direction is left then we need to calculate where we started and subtract
48+ // the current scrollLeft to get the distance scrolled. Otherwise, we use the scrollLeft.
49+ const scrollDistance = scrollDirection === 'left' ? initialScrollLeft ! - scrollLeft : scrollLeft ;
3850
3951 // Emit the scroll direction and distance
4052 this . ionSegmentViewScroll . emit ( {
@@ -59,11 +71,54 @@ export class SegmentView implements ComponentInterface {
5971 if ( segment ) {
6072 segment . value = segmentButton . value ;
6173 }
74+
75+ this . resetScrollEndTimeout ( ) ;
6276 }
6377
78+ /**
79+ * Handle touch start event to know when the user is actively dragging the segment view.
80+ */
6481 @Listen ( 'touchstart' )
65- handleTouchStart ( ) {
66- this . initialScrollLeft = this . el . scrollLeft ;
82+ handleScrollStart ( ) {
83+ if ( this . scrollEndTimeout ) {
84+ clearTimeout ( this . scrollEndTimeout ) ;
85+ this . scrollEndTimeout = null ;
86+ }
87+
88+ this . isTouching = true ;
89+ }
90+
91+ /**
92+ * Handle touch end event to know when the user is no longer dragging the segment view.
93+ */
94+ @Listen ( 'touchend' )
95+ handleTouchEnd ( ) {
96+ this . isTouching = false ;
97+ }
98+
99+ /**
100+ * Reset the scroll end detection timer. This is called on every scroll event.
101+ */
102+ private resetScrollEndTimeout ( ) {
103+ if ( this . scrollEndTimeout ) {
104+ clearTimeout ( this . scrollEndTimeout ) ;
105+ this . scrollEndTimeout = null ;
106+ }
107+ this . scrollEndTimeout = setTimeout ( ( ) => {
108+ this . checkForScrollEnd ( ) ;
109+ } , 150 ) ;
110+ }
111+
112+ /**
113+ * Check if the scroll has ended and the user is not actively touching.
114+ * If both conditions are met, reset the initial scroll position and
115+ * emit the scroll end event.
116+ */
117+ private checkForScrollEnd ( ) {
118+ if ( ! this . isTouching ) {
119+ this . ionSegmentViewScrollEnd . emit ( ) ;
120+ this . initialScrollLeft = undefined ;
121+ }
67122 }
68123
69124 /**
0 commit comments