@@ -56,6 +56,42 @@ const getProgress = (): number => {
5656 return Math . max ( 0 , Math . min ( 1 , scrollProgress || 0 ) ) ;
5757} ;
5858
59+ const getSlideAnnouncement = (
60+ context : CarouselContext ,
61+ selectedIndex : number ,
62+ slideCount : number ,
63+ ) : string => {
64+ if ( ! slideCount || slideCount <= 1 || ! context . announcementPattern ) {
65+ return '' ;
66+ }
67+ return context . announcementPattern
68+ . replace ( '{{currentSlide}}' , ( selectedIndex + 1 ) . toString ( ) )
69+ . replace ( '{{totalSlides}}' , slideCount . toString ( ) ) ;
70+ } ;
71+
72+ const updateSlideAnnouncement = (
73+ context : CarouselContext ,
74+ previousSelectedIndex : number ,
75+ ) : void => {
76+ if ( ! context . shouldAnnounce ) {
77+ return ;
78+ }
79+
80+ if ( context . selectedIndex !== previousSelectedIndex ) {
81+ context . announcement = getSlideAnnouncement (
82+ context ,
83+ context . selectedIndex ,
84+ context . slideCount ,
85+ ) ;
86+ }
87+
88+ context . shouldAnnounce = false ;
89+ } ;
90+
91+ const markForAnnouncement = ( ) : void => {
92+ getContext < CarouselContext > ( ) . shouldAnnounce = true ;
93+ } ;
94+
5995store ( 'rt-carousel/carousel' , {
6096 state : {
6197 get canScrollPrev ( ) {
@@ -72,6 +108,9 @@ store( 'rt-carousel/carousel', {
72108 const element = getElementRef ( getElement ( ) ) ;
73109 const embla = getEmblaFromElement ( element ) ;
74110 if ( embla ) {
111+ if ( embla . canScrollPrev ( ) ) {
112+ markForAnnouncement ( ) ;
113+ }
75114 embla . scrollPrev ( ) ;
76115 } else {
77116 // eslint-disable-next-line no-console
@@ -82,6 +121,9 @@ store( 'rt-carousel/carousel', {
82121 const element = getElementRef ( getElement ( ) ) ;
83122 const embla = getEmblaFromElement ( element ) ;
84123 if ( embla ) {
124+ if ( embla . canScrollNext ( ) ) {
125+ markForAnnouncement ( ) ;
126+ }
85127 embla . scrollNext ( ) ;
86128 } else {
87129 // eslint-disable-next-line no-console
@@ -98,6 +140,9 @@ store( 'rt-carousel/carousel', {
98140 const element = getElementRef ( getElement ( ) ) ;
99141 const embla = getEmblaFromElement ( element ) ;
100142 if ( embla ) {
143+ if ( snap . index !== context . selectedIndex ) {
144+ markForAnnouncement ( ) ;
145+ }
101146 embla . scrollTo ( snap . index ) ;
102147 }
103148 }
@@ -237,6 +282,7 @@ store( 'rt-carousel/carousel', {
237282 viewport [ EMBLA_KEY ] = embla ;
238283
239284 const updateState = ( ) => {
285+ const previousSelectedIndex = context . selectedIndex ;
240286 const scrollSnapList = embla . scrollSnapList ( ) ;
241287 context . initialized = true ;
242288 context . canScrollPrev = embla . canScrollPrev ( ) ;
@@ -249,6 +295,7 @@ store( 'rt-carousel/carousel', {
249295 }
250296 context . scrollProgress = embla . scrollProgress ( ) ;
251297 context . slideCount = embla . slideNodes ( ) . length ;
298+ updateSlideAnnouncement ( context , previousSelectedIndex ) ;
252299 } ;
253300
254301 embla . on ( 'select' , updateState ) ;
0 commit comments