Explorar el Código

Remove a SR text from each slide and add it to the track.

NaotoshiFujita hace 3 años
padre
commit
91db20c8d0

+ 33 - 37
dist/js/splide.js

@@ -849,15 +849,12 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         updateOnMove = options.updateOnMove,
         i18n = options.i18n,
         pagination = options.pagination,
-        slideFocus = options.slideFocus,
-        live = options.live;
+        slideFocus = options.slideFocus;
     var resolve = Components.Direction.resolve;
     var styles = getAttribute(slide, "style");
     var label = getAttribute(slide, ARIA_LABEL);
-    var slideLabel = label || format(i18n.slideLabel, [index + 1, Splide2.length]);
     var isClone = slideIndex > -1;
     var container = child(slide, "." + CLASS_CONTAINER);
-    var sr = create("span", CLASS_SR);
     var focusableNodes = queryAll(slide, options.focusableNodes || "");
     var destroyed;
 
@@ -867,8 +864,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         slide.id = root.id + "-slide" + pad(index + 1);
         setAttribute(slide, ROLE, pagination ? "tabpanel" : "group");
         setAttribute(slide, ARIA_ROLEDESCRIPTION, noDescription ? "" : i18n.slide);
-        setAttribute(slide, ARIA_LABEL, slideLabel);
-        live && before(sr, child(slide));
+        setAttribute(slide, ARIA_LABEL, label || format(i18n.slideLabel, [index + 1, Splide2.length]));
       }
 
       listen();
@@ -877,8 +873,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function listen() {
       bind(slide, "click", apply(emit, EVENT_CLICK, self));
       bind(slide, "keydown", apply(emit, EVENT_SLIDE_KEYDOWN, self));
-      on([EVENT_MOVED, EVENT_SCROLLED], apply(update, false));
-      on(EVENT_SHIFTED, apply(update, true));
+      on([EVENT_MOVED, EVENT_SHIFTED, EVENT_SCROLLED], update);
       on(EVENT_NAVIGATION_MOUNTED, initNavigation);
 
       if (updateOnMove) {
@@ -889,7 +884,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function destroy() {
       destroyed = true;
       event.destroy();
-      remove(sr);
       removeClass(slide, STATUS_CLASSES);
       removeAttribute(slide, ALL_ATTRIBUTES);
       setAttribute(slide, "style", styles);
@@ -904,23 +898,21 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       setAttribute(slide, ARIA_LABEL, format(i18n.slideX, (isClone ? slideIndex : index) + 1));
       setAttribute(slide, ARIA_CONTROLS, controls);
       setAttribute(slide, ROLE, slideFocus ? "button" : "");
-      updateA11y();
     }
 
     function onMove() {
       if (!destroyed) {
-        update(true);
+        update();
       }
     }
 
-    function update(excludeA11y) {
+    function update() {
       if (!destroyed) {
         var curr = Splide2.index;
         updateActivity();
         updateVisibility();
         toggleClass(slide, CLASS_PREV, index === curr - 1);
         toggleClass(slide, CLASS_NEXT, index === curr + 1);
-        !excludeA11y && updateA11y();
       }
     }
 
@@ -929,37 +921,33 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
       if (active !== hasClass(slide, CLASS_ACTIVE)) {
         toggleClass(slide, CLASS_ACTIVE, active);
+        setAttribute(slide, ARIA_CURRENT, isNavigation && active || "");
         emit(active ? EVENT_ACTIVE : EVENT_INACTIVE, self);
       }
     }
 
     function updateVisibility() {
       var visible = isVisible();
+      var hidden = !visible && (!isActive() || isClone);
 
-      if (visible !== hasClass(slide, CLASS_VISIBLE)) {
-        toggleClass(slide, CLASS_VISIBLE, visible);
-        emit(visible ? EVENT_VISIBLE : EVENT_HIDDEN, self);
-      }
-
-      if (!visible && document.activeElement === slide) {
-        var Slide2 = Components.Slides.getAt(Splide2.index);
-        Slide2 && focus(Slide2.slide);
+      if (!Splide2.state.is([MOVING, SCROLLING])) {
+        setAttribute(slide, ARIA_HIDDEN, hidden || "");
       }
-    }
 
-    function updateA11y() {
-      var active = isActive();
-      var hidden = !isVisible() && (!active || isClone);
-      setAttribute(slide, ARIA_CURRENT, isNavigation && active || "");
-      setAttribute(slide, ARIA_HIDDEN, hidden || "");
       setAttribute(focusableNodes, TAB_INDEX, hidden ? -1 : "");
 
       if (slideFocus) {
         setAttribute(slide, TAB_INDEX, hidden ? -1 : 0);
       }
 
-      if (live) {
-        sr.textContent = hidden ? "" : slideLabel;
+      if (visible !== hasClass(slide, CLASS_VISIBLE)) {
+        toggleClass(slide, CLASS_VISIBLE, visible);
+        emit(visible ? EVENT_VISIBLE : EVENT_HIDDEN, self);
+      }
+
+      if (!visible && document.activeElement === slide) {
+        var Slide2 = Components.Slides.getAt(Splide2.index);
+        Slide2 && focus(Slide2.slide);
       }
     }
 
@@ -1739,7 +1727,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         i18n = options.i18n;
     var Elements = Components2.Elements,
         Controller = Components2.Controller;
-    var userArrows = Elements.arrows;
+    var userArrows = Elements.arrows,
+        track = Elements.track;
     var wrapper = userArrows;
     var prev = Elements.prev;
     var next = Elements.next;
@@ -1775,7 +1764,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         if (enabled) {
           listen();
           update();
-          setAttribute([prev, next], ARIA_CONTROLS, Elements.list.id);
+          setAttribute([prev, next], ARIA_CONTROLS, track.id);
           emit(EVENT_ARROWS_MOUNTED, prev, next);
         }
       }
@@ -1809,7 +1798,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       next = createArrow(false);
       created = true;
       append(wrapper, [prev, next]);
-      !userArrows && before(wrapper, Elements.track);
+      !userArrows && before(wrapper, track);
     }
 
     function createArrow(prev2) {
@@ -1859,7 +1848,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function mount() {
       if (autoplay) {
         listen();
-        toggle && setAttribute(toggle, ARIA_CONTROLS, Elements.list.id);
+        toggle && setAttribute(toggle, ARIA_CONTROLS, Elements.track.id);
         stopped || play();
         update();
       }
@@ -2763,28 +2752,35 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     var _EventInterface14 = EventInterface(Splide2),
         on = _EventInterface14.on;
 
-    var list = Components2.Elements.list;
+    var track = Components2.Elements.track;
     var live = options.live;
     var enabled = live && !options.isNavigation;
+    var sr = create("span", CLASS_SR);
 
     function mount() {
       if (enabled) {
-        setAttribute(list, ARIA_ATOMIC, false);
         disable(!Components2.Autoplay.isPaused());
         on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
         on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
+        on([EVENT_MOVED, EVENT_SCROLLED], update);
       }
     }
 
     function disable(disabled) {
       if (enabled) {
-        setAttribute(list, ARIA_LIVE, disabled ? "off" : "polite");
+        setAttribute(track, ARIA_LIVE, disabled ? "off" : "polite");
       }
     }
 
+    function update() {
+      append(track, sr);
+      sr.textContent = "\u2026";
+    }
+
     return {
       mount: mount,
-      disable: disable
+      disable: disable,
+      destroy: apply(remove, sr)
     };
   }
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/js/splide.min.js


BIN
dist/js/splide.min.js.gz


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/js/splide.min.js.map


+ 3 - 3
src/js/components/Arrows/Arrows.ts

@@ -53,7 +53,7 @@ export function Arrows( Splide: Splide, Components: Components, options: Options
   const { on, bind, emit } = event;
   const { classes, i18n } = options;
   const { Elements, Controller } = Components;
-  const userArrows = Elements.arrows;
+  const { arrows: userArrows, track } = Elements;
 
   /**
    * The wrapper element.
@@ -119,7 +119,7 @@ export function Arrows( Splide: Splide, Components: Components, options: Options
       if ( enabled ) {
         listen();
         update();
-        setAttribute( [ prev, next ], ARIA_CONTROLS, Elements.list.id );
+        setAttribute( [ prev, next ], ARIA_CONTROLS, track.id );
         emit( EVENT_ARROWS_MOUNTED, prev, next );
       }
     }
@@ -168,7 +168,7 @@ export function Arrows( Splide: Splide, Components: Components, options: Options
     created = true;
 
     append( wrapper, [ prev, next ] );
-    ! userArrows && before( wrapper, Elements.track );
+    ! userArrows && before( wrapper, track );
   }
 
   /**

+ 1 - 1
src/js/components/Autoplay/Autoplay.ts

@@ -66,7 +66,7 @@ export function Autoplay( Splide: Splide, Components: Components, options: Optio
   function mount(): void {
     if ( autoplay ) {
       listen();
-      toggle && setAttribute( toggle, ARIA_CONTROLS, Elements.list.id );
+      toggle && setAttribute( toggle, ARIA_CONTROLS, Elements.track.id );
       stopped || play();
       update();
     }

+ 21 - 6
src/js/components/Live/Live.ts

@@ -1,9 +1,10 @@
-import { ARIA_ATOMIC, ARIA_LIVE } from '../../constants/attributes';
-import { EVENT_AUTOPLAY_PAUSE, EVENT_AUTOPLAY_PLAY } from '../../constants/events';
+import { ARIA_LIVE } from '../../constants/attributes';
+import { CLASS_SR } from '../../constants/classes';
+import { EVENT_AUTOPLAY_PAUSE, EVENT_AUTOPLAY_PLAY, EVENT_MOVED, EVENT_SCROLLED } from '../../constants/events';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
-import { apply, setAttribute } from '../../utils';
+import { append, apply, create, remove, setAttribute } from '../../utils';
 
 
 /**
@@ -30,7 +31,7 @@ export interface LiveComponent extends BaseComponent {
  */
 export function Live( Splide: Splide, Components: Components, options: Options ): LiveComponent {
   const { on } = EventInterface( Splide );
-  const { list } = Components.Elements;
+  const { track } = Components.Elements;
   const { live } = options;
 
   /**
@@ -38,6 +39,11 @@ export function Live( Splide: Splide, Components: Components, options: Options )
    */
   const enabled = live && ! options.isNavigation;
 
+  /**
+   * The span element for the SR only text.
+   */
+  const sr = create( 'span', CLASS_SR );
+
   /**
    * Called when the component is mounted.
    * Explicitly sets `aria-atomic` to avoid SR from reading the content twice.
@@ -46,10 +52,10 @@ export function Live( Splide: Splide, Components: Components, options: Options )
    */
   function mount(): void {
     if ( enabled ) {
-      setAttribute( list, ARIA_ATOMIC, false );
       disable( ! Components.Autoplay.isPaused() );
       on( EVENT_AUTOPLAY_PLAY, apply( disable, true ) );
       on( EVENT_AUTOPLAY_PAUSE, apply( disable, false ) );
+      on( [ EVENT_MOVED, EVENT_SCROLLED ], update );
     }
   }
 
@@ -61,12 +67,21 @@ export function Live( Splide: Splide, Components: Components, options: Options )
    */
   function disable( disabled: boolean ): void {
     if ( enabled ) {
-      setAttribute( list, ARIA_LIVE, disabled ? 'off' : 'polite' );
+      setAttribute( track, ARIA_LIVE, disabled ? 'off' : 'polite' );
     }
   }
 
+  /**
+   * Updates the live region status with unreadable texts.
+   */
+  function update(): void {
+    append( track, sr );
+    sr.textContent = '…';
+  }
+
   return {
     mount,
     disable,
+    destroy: apply( remove, sr ),
   };
 }

+ 23 - 20
src/js/components/Live/test/general.test.ts

@@ -1,72 +1,75 @@
 import { ARIA_ATOMIC, ARIA_LIVE } from '../../../constants/attributes';
+import { CLASS_SR } from '../../../constants/classes';
 import { init } from '../../../test';
 
 
 describe( 'Live', () => {
-  test( 'can assign aria-atomic="false" to the list element.', () => {
-    const splide = init( { live: true } );
-    expect( splide.Components.Elements.list.getAttribute( ARIA_ATOMIC ) ).toBe( 'false' );
+  test( 'can append a SR text to the track element after move.', () => {
+    const splide = init( { live: true, speed: 0 } );
+
+    splide.go( 1 );
+    expect( splide.Components.Elements.track.getElementsByClassName( CLASS_SR ).length ).toBe( 1 );
   } );
 
   test( 'can assign aria-live="polite" to the list element.', () => {
     const splide = init( { live: true } );
-    expect( splide.Components.Elements.list.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
+    expect( splide.Components.Elements.track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
   } );
 
   test( 'can assign aria-live="off" to the list element when the autoplay is `true`.', () => {
     const splide = init( { live: true, autoplay: true } );
-    expect( splide.Components.Elements.list.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
+    expect( splide.Components.Elements.track.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
   } );
 
   test( 'can assign aria-live="polite" to the list element when the autoplay is `"pause".`', () => {
     const splide = init( { live: true, autoplay: 'pause' } );
-    expect( splide.Components.Elements.list.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
+    expect( splide.Components.Elements.track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
   } );
 
   test( 'can change aria-live to "off" when autoplay starts, or to "polite" when autoplay stops.', () => {
     const splide = init( { live: true, autoplay: 'pause' } );
-    const { list } = splide.Components.Elements;
+    const { track } = splide.Components.Elements;
     const { play, pause } = splide.Components.Autoplay;
 
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
 
     play();
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
 
     pause();
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
 
     play();
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
   } );
 
   test( 'can toggle aria-live by `disable()`', () => {
     const splide = init( { live: true } );
-    const { list } = splide.Components.Elements;
+    const { track } = splide.Components.Elements;
     const { disable } = splide.Components.Live;
 
     disable( true );
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
 
     disable( false );
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
 
     disable( true );
-    expect( list.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
+    expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'off' );
   } );
 
   test( 'should do nothing when the `live` option is false.', () => {
     const splide = init( { live: false } );
-    const { list } = splide.Components.Elements;
+    const { track } = splide.Components.Elements;
     const { disable } = splide.Components.Live;
 
-    expect( list.getAttribute( ARIA_ATOMIC ) ).toBeNull();
-    expect( list.getAttribute( ARIA_LIVE ) ).toBeNull();
+    expect( track.getAttribute( ARIA_ATOMIC ) ).toBeNull();
+    expect( track.getAttribute( ARIA_LIVE ) ).toBeNull();
 
     disable( true );
-    expect( list.getAttribute( ARIA_LIVE ) ).toBeNull();
+    expect( track.getAttribute( ARIA_LIVE ) ).toBeNull();
 
     disable( false );
-    expect( list.getAttribute( ARIA_LIVE ) ).toBeNull();
+    expect( track.getAttribute( ARIA_LIVE ) ).toBeNull();
   } );
 } );

+ 20 - 40
src/js/components/Slides/Slide.ts

@@ -13,7 +13,6 @@ import {
   CLASS_CONTAINER,
   CLASS_NEXT,
   CLASS_PREV,
-  CLASS_SR,
   CLASS_VISIBLE,
   STATUS_CLASSES,
 } from '../../constants/classes';
@@ -30,6 +29,7 @@ import {
   EVENT_SLIDE_KEYDOWN,
   EVENT_VISIBLE,
 } from '../../constants/events';
+import { MOVING, SCROLLING } from '../../constants/states';
 import { FADE, LOOP } from '../../constants/types';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
@@ -37,10 +37,8 @@ import { BaseComponent } from '../../types';
 import {
   abs,
   apply,
-  before,
   ceil,
   child,
-  create,
   floor,
   focus,
   format,
@@ -50,7 +48,6 @@ import {
   pad,
   queryAll,
   rect,
-  remove,
   removeAttribute,
   removeClass,
   setAttribute,
@@ -91,14 +88,12 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
   const event = EventInterface( Splide );
   const { on, emit, bind } = event;
   const { Components, root, options } = Splide;
-  const { isNavigation, updateOnMove, i18n, pagination, slideFocus, live } = options;
+  const { isNavigation, updateOnMove, i18n, pagination, slideFocus } = options;
   const { resolve } = Components.Direction;
   const styles         = getAttribute( slide, 'style' );
   const label          = getAttribute( slide, ARIA_LABEL );
-  const slideLabel     = label || format( i18n.slideLabel, [ index + 1, Splide.length ] );
   const isClone        = slideIndex > -1;
   const container      = child( slide, `.${ CLASS_CONTAINER }` );
-  const sr             = create( 'span', CLASS_SR );
   const focusableNodes = queryAll( slide, options.focusableNodes || '' );
 
   /**
@@ -116,8 +111,7 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
       slide.id = `${ root.id }-slide${ pad( index + 1 ) }`;
       setAttribute( slide, ROLE, pagination ? 'tabpanel' : 'group' );
       setAttribute( slide, ARIA_ROLEDESCRIPTION, noDescription ? '' : i18n.slide );
-      setAttribute( slide, ARIA_LABEL, slideLabel );
-      live && before( sr, child( slide ) );
+      setAttribute( slide, ARIA_LABEL, label || format( i18n.slideLabel, [ index + 1, Splide.length ] ) );
     }
 
     listen();
@@ -129,8 +123,7 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
   function listen(): void {
     bind( slide, 'click', apply( emit, EVENT_CLICK, self ) );
     bind( slide, 'keydown', apply( emit, EVENT_SLIDE_KEYDOWN, self ) );
-    on( [ EVENT_MOVED, EVENT_SCROLLED ], apply( update, false ) );
-    on( EVENT_SHIFTED, apply( update, true ) );
+    on( [ EVENT_MOVED, EVENT_SHIFTED, EVENT_SCROLLED ], update );
     on( EVENT_NAVIGATION_MOUNTED, initNavigation );
 
     if ( updateOnMove ) {
@@ -144,7 +137,6 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
   function destroy(): void {
     destroyed = true;
     event.destroy();
-    remove( sr );
     removeClass( slide, STATUS_CLASSES );
     removeAttribute( slide, ALL_ATTRIBUTES );
     setAttribute( slide, 'style', styles );
@@ -163,7 +155,6 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
     setAttribute( slide, ARIA_LABEL, format( i18n.slideX, ( isClone ? slideIndex : index ) + 1 ) );
     setAttribute( slide, ARIA_CONTROLS, controls );
     setAttribute( slide, ROLE, slideFocus ? 'button' : '' );
-    updateA11y();
   }
 
   /**
@@ -171,16 +162,14 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
    */
   function onMove(): void {
     if ( ! destroyed ) {
-      update( true );
+      update();
     }
   }
 
   /**
    * Updates attribute and classes of the slide.
-   *
-   * @param excludeA11y - If `true`, attributes will be not updated.
    */
-  function update( excludeA11y?: boolean ): void {
+  function update(): void {
     if ( ! destroyed ) {
       const { index: curr } = Splide;
 
@@ -188,7 +177,6 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
       updateVisibility();
       toggleClass( slide, CLASS_PREV, index === curr - 1 );
       toggleClass( slide, CLASS_NEXT, index === curr + 1 );
-      ! excludeA11y && updateA11y();
     }
   }
 
@@ -200,46 +188,38 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
 
     if ( active !== hasClass( slide, CLASS_ACTIVE ) ) {
       toggleClass( slide, CLASS_ACTIVE, active );
+      setAttribute( slide, ARIA_CURRENT, isNavigation && active || '' );
       emit( active ? EVENT_ACTIVE : EVENT_INACTIVE, self );
     }
   }
 
   /**
    * Updates classes and attributes related with visibility.
-   * If the slide has focus and gets hidden, moves focus to the active slide.
+   * - Do not update aria-hidden on shifting to avoid Window Narrator from start reading contents.
+   * - If the slide has focus and gets hidden, moves focus to the active slide.
    */
   function updateVisibility(): void {
     const visible = isVisible();
+    const hidden = ! visible && ( ! isActive() || isClone );
 
-    if ( visible !== hasClass( slide, CLASS_VISIBLE ) ) {
-      toggleClass( slide, CLASS_VISIBLE, visible );
-      emit( visible ? EVENT_VISIBLE : EVENT_HIDDEN, self );
+    if ( ! Splide.state.is( [ MOVING, SCROLLING ] ) ) {
+      setAttribute( slide, ARIA_HIDDEN, hidden || '' );
     }
 
-    if ( ! visible && document.activeElement === slide ) {
-      const Slide = Components.Slides.getAt( Splide.index );
-      Slide && focus( Slide.slide );
-    }
-  }
-
-  /**
-   * Updates attributes.
-   * Do not call this on "shifted" event to avoid SR from reading clone's contents.
-   */
-  function updateA11y(): void {
-    const active = isActive();
-    const hidden = ! isVisible() && ( ! active || isClone );
-
-    setAttribute( slide, ARIA_CURRENT, isNavigation && active || '' );
-    setAttribute( slide, ARIA_HIDDEN, hidden || '' );
     setAttribute( focusableNodes, TAB_INDEX, hidden ? -1 : '' );
 
     if ( slideFocus ) {
       setAttribute( slide, TAB_INDEX, hidden ? -1 : 0 );
     }
 
-    if ( live ) {
-      sr.textContent = hidden ? '' : slideLabel;
+    if ( visible !== hasClass( slide, CLASS_VISIBLE ) ) {
+      toggleClass( slide, CLASS_VISIBLE, visible );
+      emit( visible ? EVENT_VISIBLE : EVENT_HIDDEN, self );
+    }
+
+    if ( ! visible && document.activeElement === slide ) {
+      const Slide = Components.Slides.getAt( Splide.index );
+      Slide && focus( Slide.slide );
     }
   }
 

+ 0 - 53
src/js/components/Slides/test/sr.test.ts

@@ -1,53 +0,0 @@
-import { CLASS_SR } from '../../../constants/classes';
-import { init } from '../../../test';
-
-
-describe( 'The SR field', () => {
-  test( 'should be prepended to each slide when `live` option is `true`.', () => {
-    const splide   = init();
-    const Slides   = splide.Components.Slides;
-    const callback = jest.fn();
-
-    Slides.forEach( Slide => {
-      expect( Slide.slide.firstElementChild.classList.contains( CLASS_SR ) ).toBe( true );
-      callback();
-    } );
-
-    expect( callback ).toHaveBeenCalled();
-  } );
-
-  test( 'should not be prepended when `live` option is `false`.', () => {
-    const splide   = init( { live: false } );
-    const Slides   = splide.Components.Slides;
-    const callback = jest.fn();
-
-    Slides.forEach( Slide => {
-      expect( Slide.slide.firstElementChild.classList.contains( CLASS_SR ) ).toBe( false );
-      callback();
-    } );
-
-    expect( callback ).toHaveBeenCalled();
-  } );
-
-  test( 'should describe the current slide position.', () => {
-    const splide = init( { speed: 0 } );
-    const Slides = splide.Components.Slides;
-    const Slide0 = Slides.getAt( 0 );
-    const Slide1 = Slides.getAt( 1 );
-    const Slide2 = Slides.getAt( 2 );
-
-    expect( Slide0.slide.firstElementChild.textContent ).toBe( `1 of ${ splide.length }` );
-    expect( Slide1.slide.firstElementChild.textContent ).toBe( '' );
-    expect( Slide2.slide.firstElementChild.textContent ).toBe( '' );
-
-    splide.go( 1 );
-    expect( Slide0.slide.firstElementChild.textContent ).toBe( '' );
-    expect( Slide1.slide.firstElementChild.textContent ).toBe( `2 of ${ splide.length }` );
-    expect( Slide2.slide.firstElementChild.textContent ).toBe( '' );
-
-    splide.go( 2 );
-    expect( Slide0.slide.firstElementChild.textContent ).toBe( '' );
-    expect( Slide1.slide.firstElementChild.textContent ).toBe( '' );
-    expect( Slide2.slide.firstElementChild.textContent ).toBe( `3 of ${ splide.length }` );
-  } );
-} );

+ 1 - 1
src/js/types/options.ts

@@ -100,7 +100,7 @@ export interface Options extends ResponsiveOptions {
    * - 'focused': Listens to the `keydown` event of the slider root element with adding `tabindex="0"` to it.
    * - `false`: Disables keyboard shortcuts (default).
    */
-  keyboard?: boolean | string;
+  keyboard?: boolean | 'global' | 'focused';
 
   /**
    * Enables navigation by the mouse wheel.

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio