@lumx/react 3.9.4-alpha.0 → 3.9.4-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -12125,11 +12125,11 @@ function useKeyNavigate(element, onNext, onPrevious) {
12125
12125
  }
12126
12126
 
12127
12127
  /**
12128
- * Classname set on elements whose focus was blocked.
12128
+ * Data attribute set on elements whose focus was blocked.
12129
12129
  * This is to easily find elements that have been tempered with,
12130
12130
  * and not elements whose focus was already initially blocked.
12131
- * */
12132
- const BLOCKED_FOCUS_CLASSNAME = 'focus-blocked';
12131
+ */
12132
+ const BLOCKED_FOCUS = 'data-focus-blocked';
12133
12133
 
12134
12134
  /**
12135
12135
  * Manage how slides must behave when visible or not.
@@ -12141,91 +12141,88 @@ const useSlideFocusManagement = _ref => {
12141
12141
  slidesRef
12142
12142
  } = _ref;
12143
12143
  const [slide, setSlide] = React__default.useState(null);
12144
- useEffect(() => {
12145
- var _slidesRef$current;
12144
+ const [focusableElementSet, setFocusableElementSet] = React__default.useState();
12145
+ React__default.useEffect(() => {
12146
12146
  if (!slide) {
12147
12147
  return undefined;
12148
12148
  }
12149
- const isUserActivated = (slidesRef === null || slidesRef === void 0 ? void 0 : (_slidesRef$current = slidesRef.current) === null || _slidesRef$current === void 0 ? void 0 : _slidesRef$current.dataset.lumxUserActivated) === 'true';
12150
- let focusableElements = [];
12151
-
12152
- /**
12153
- * Display given slide to screen readers and, if focus was blocked, restore focus on elements.
12154
- */
12155
- const enableSlide = () => {
12156
- slide.removeAttribute('inert');
12157
- slide.setAttribute('aria-hidden', 'false');
12158
- // Find elements we have blocked focus on
12159
- // (won't be necessary once "inert" gets sufficient browser support)
12160
- focusableElements = Array.from(slide.querySelectorAll(`.${BLOCKED_FOCUS_CLASSNAME}`));
12161
- for (const focusableElement of focusableElements) {
12162
- focusableElement.removeAttribute('tabindex');
12163
- focusableElement.classList.remove(BLOCKED_FOCUS_CLASSNAME);
12149
+ // Update the slide's focusable element list (including the blocked elements)
12150
+ const updateFocusableElements = () => setFocusableElementSet(function () {
12151
+ let set = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Set();
12152
+ // TODO: remove when `inert` gets sufficient browser support
12153
+ const focusedBlocked = Array.from(slide.querySelectorAll(`[${BLOCKED_FOCUS}]`));
12154
+ for (const element of focusedBlocked) {
12155
+ set.add(element);
12164
12156
  }
12165
- };
12157
+ for (const element of getFocusableElements(slide)) {
12158
+ set.add(element);
12159
+ }
12160
+ return set;
12161
+ });
12166
12162
 
12167
- /**
12168
- * Hide given slide from screen readers and block focus on all focusable elements within.
12169
- */
12170
- const blockSlide = () => {
12163
+ // Observe changes in the content of the slide
12164
+ const observer = new MutationObserver(mutationsList => {
12165
+ if (mutationsList.some(mutation => mutation.type === 'childList')) {
12166
+ updateFocusableElements();
12167
+ }
12168
+ });
12169
+ updateFocusableElements();
12170
+ observer.observe(slide, {
12171
+ attributes: true,
12172
+ childList: true,
12173
+ subtree: true
12174
+ });
12175
+ return observer.disconnect();
12176
+ }, [slide]);
12177
+ useEffect(() => {
12178
+ if (!slide || !focusableElementSet) {
12179
+ return;
12180
+ }
12181
+ const focusableElements = Array.from(focusableElementSet);
12182
+ if (!isSlideDisplayed) {
12183
+ /* Block slide */
12171
12184
  slide.setAttribute('inert', '');
12172
12185
  slide.setAttribute('aria-hidden', 'true');
12173
- focusableElements = getFocusableElements(slide);
12186
+
12187
+ // TODO: remove when `inert` gets sufficient browser support
12174
12188
  for (const focusableElement of focusableElements) {
12175
12189
  focusableElement.setAttribute('tabindex', '-1');
12176
- focusableElement.classList.add(BLOCKED_FOCUS_CLASSNAME);
12190
+ focusableElement.setAttribute(BLOCKED_FOCUS, '');
12177
12191
  }
12178
- };
12179
- const handleDisplay = () => {
12180
- if (isSlideDisplayed) {
12181
- enableSlide();
12182
- } else {
12183
- blockSlide();
12184
- }
12185
- };
12192
+ } else {
12193
+ var _slidesRef$current;
12194
+ /* Un-block slide */
12195
+ slide.removeAttribute('inert');
12196
+ slide.removeAttribute('aria-hidden');
12186
12197
 
12187
- // Create an observer instance linked to the callback function
12188
- // (won't be necessary once "inert" gets sufficient browser support)
12189
- const observer = new MutationObserver(mutationsList => {
12190
- for (const mutation of mutationsList) {
12191
- if (mutation.type === 'childList') {
12192
- handleDisplay();
12193
- }
12198
+ // TODO: remove when `inert` gets sufficient browser support
12199
+ for (const focusableElement of focusableElements) {
12200
+ focusableElement.removeAttribute('tabindex');
12201
+ focusableElement.removeAttribute(BLOCKED_FOCUS);
12194
12202
  }
12195
- });
12196
- handleDisplay();
12197
12203
 
12198
- // Change focus on slide displayed
12199
- if (isSlideDisplayed && isUserActivated) {
12200
- var _elementToFocus;
12201
- let elementToFocus = slide;
12204
+ // Change focus on slide displayed
12205
+ const isUserActivated = (slidesRef === null || slidesRef === void 0 ? void 0 : (_slidesRef$current = slidesRef.current) === null || _slidesRef$current === void 0 ? void 0 : _slidesRef$current.dataset.lumxUserActivated) === 'true';
12206
+ if (isUserActivated) {
12207
+ var _elementToFocus;
12208
+ let elementToFocus = slide;
12202
12209
 
12203
- // We have exactly one focusable element => focus it
12204
- if (focusableElements.length === 1) {
12205
- // eslint-disable-next-line prefer-destructuring
12206
- elementToFocus = focusableElements[0];
12207
- }
12210
+ // We have exactly one focusable element => focus it
12211
+ if (focusableElementSet.size === 1) {
12212
+ // eslint-disable-next-line prefer-destructuring
12213
+ elementToFocus = focusableElements[0];
12214
+ }
12208
12215
 
12209
- // We have not focusable element => focus the pagination item
12210
- if (focusableElements.length === 0) {
12211
- elementToFocus = document.querySelector(`[aria-controls="${slide === null || slide === void 0 ? void 0 : slide.id}"]`);
12216
+ // We have not focusable element => focus the pagination item
12217
+ if (focusableElementSet.size === 0) {
12218
+ elementToFocus = document.querySelector(`[aria-controls="${slide === null || slide === void 0 ? void 0 : slide.id}"]`);
12219
+ }
12220
+ (_elementToFocus = elementToFocus) === null || _elementToFocus === void 0 ? void 0 : _elementToFocus.focus({
12221
+ preventScroll: true
12222
+ });
12212
12223
  }
12213
- (_elementToFocus = elementToFocus) === null || _elementToFocus === void 0 ? void 0 : _elementToFocus.focus({
12214
- preventScroll: true
12215
- });
12216
12224
  }
12217
-
12218
- /** If slide is hidden, start observing for elements to block focus */
12219
- if (!isSlideDisplayed) {
12220
- observer.observe(slide, {
12221
- attributes: true,
12222
- childList: true,
12223
- subtree: true
12224
- });
12225
- return () => observer.disconnect();
12226
- }
12227
- return undefined;
12228
- }, [isSlideDisplayed, slide, slidesRef]);
12225
+ }, [focusableElementSet, isSlideDisplayed, slide, slidesRef]);
12229
12226
  return setSlide;
12230
12227
  };
12231
12228