@lumx/react 3.9.4-alpha.3 → 3.9.4
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.d.ts +18 -12
- package/index.js +5831 -5798
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/badge/BadgeWrapper.stories.tsx +76 -0
- package/src/components/badge/BadgeWrapper.test.tsx +49 -0
- package/src/components/badge/BadgeWrapper.tsx +36 -0
- package/src/components/badge/index.ts +1 -0
- package/src/components/expansion-panel/ExpansionPanel.test.tsx +5 -2
- package/src/components/expansion-panel/ExpansionPanel.tsx +32 -3
- package/src/components/image-lightbox/internal/ImageSlideshow.tsx +0 -2
- package/src/components/image-lightbox/internal/usePointerZoom.ts +1 -1
- package/src/components/slideshow/Slides.tsx +7 -15
- package/src/components/slideshow/Slideshow.stories.tsx +1 -12
- package/src/components/slideshow/Slideshow.tsx +16 -2
- package/src/components/slideshow/SlideshowControls.stories.tsx +3 -2
- package/src/components/slideshow/SlideshowControls.tsx +73 -63
- package/src/components/slideshow/SlideshowItem.tsx +10 -1
- package/src/components/slideshow/SlideshowItemGroup.tsx +33 -16
- package/src/components/slideshow/constants.ts +0 -4
- package/src/components/slideshow/useSlideFocusManagement.tsx +62 -74
- package/src/{components/slideshow → hooks}/useSlideshowControls.ts +60 -69
- package/src/stories/generated/Mosaic/Demos.stories.tsx +1 -0
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import React, { forwardRef, RefObject, useCallback,
|
|
1
|
+
import React, { forwardRef, RefObject, useCallback, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import range from 'lodash/range';
|
|
5
5
|
|
|
6
6
|
import { mdiChevronLeft, mdiChevronRight, mdiPlayCircleOutline, mdiPauseCircleOutline } from '@lumx/icons';
|
|
7
|
-
import { Emphasis, IconButton, IconButtonProps,
|
|
7
|
+
import { Emphasis, IconButton, IconButtonProps, Theme } from '@lumx/react';
|
|
8
8
|
import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
|
|
9
9
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
10
10
|
import { WINDOW } from '@lumx/react/constants';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { useSlideshowControls, DEFAULT_OPTIONS } from '@lumx/react/hooks/useSlideshowControls';
|
|
12
|
+
import { useRovingTabIndex } from '@lumx/react/hooks/useRovingTabIndex';
|
|
13
13
|
|
|
14
|
-
import { buildSlideShowGroupId } from '@lumx/react/components/slideshow/SlideshowItemGroup';
|
|
15
|
-
import { DEFAULT_OPTIONS, useSlideshowControls } from './useSlideshowControls';
|
|
16
14
|
import { useSwipeNavigate } from './useSwipeNavigate';
|
|
17
15
|
import { PAGINATION_ITEM_SIZE, PAGINATION_ITEMS_MAX } from './constants';
|
|
18
16
|
import { usePaginationVisibleRange } from './usePaginationVisibleRange';
|
|
@@ -36,11 +34,11 @@ export interface SlideshowControlsProps extends GenericProps, HasTheme {
|
|
|
36
34
|
/** Number of slides. */
|
|
37
35
|
slidesCount: number;
|
|
38
36
|
/** On next button click callback. */
|
|
39
|
-
onNextClick?(
|
|
37
|
+
onNextClick?(loopback?: boolean): void;
|
|
40
38
|
/** On pagination change callback. */
|
|
41
39
|
onPaginationClick?(index: number): void;
|
|
42
40
|
/** On previous button click callback. */
|
|
43
|
-
onPreviousClick?(
|
|
41
|
+
onPreviousClick?(loopback?: boolean): void;
|
|
44
42
|
/** whether the slideshow is currently playing */
|
|
45
43
|
isAutoPlaying?: boolean;
|
|
46
44
|
/**
|
|
@@ -102,7 +100,7 @@ const InternalSlideshowControls: Comp<SlideshowControlsProps, HTMLDivElement> =
|
|
|
102
100
|
...forwardedProps
|
|
103
101
|
} = props;
|
|
104
102
|
|
|
105
|
-
let parent
|
|
103
|
+
let parent;
|
|
106
104
|
if (WINDOW) {
|
|
107
105
|
// Checking window object to avoid errors in SSR.
|
|
108
106
|
parent = parentRef instanceof HTMLElement ? parentRef : parentRef?.current;
|
|
@@ -111,30 +109,33 @@ const InternalSlideshowControls: Comp<SlideshowControlsProps, HTMLDivElement> =
|
|
|
111
109
|
// Listen to touch swipe navigate left & right.
|
|
112
110
|
useSwipeNavigate(
|
|
113
111
|
parent,
|
|
114
|
-
// Go next without
|
|
112
|
+
// Go next without loopback.
|
|
115
113
|
useCallback(() => onNextClick?.(false), [onNextClick]),
|
|
116
|
-
// Go previous without
|
|
114
|
+
// Go previous without loopback.
|
|
117
115
|
useCallback(() => onPreviousClick?.(false), [onPreviousClick]),
|
|
118
116
|
);
|
|
119
117
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Add roving tab index pattern to pagination items and activate slide on focus.
|
|
120
|
+
*/
|
|
121
|
+
useRovingTabIndex({
|
|
122
|
+
parentRef: paginationRef,
|
|
123
|
+
elementSelector: 'button',
|
|
124
|
+
keepTabIndex: true,
|
|
125
|
+
onElementFocus: (element) => {
|
|
126
|
+
element.click();
|
|
127
|
+
},
|
|
128
|
+
});
|
|
123
129
|
|
|
124
130
|
// Pagination "bullet" range.
|
|
125
|
-
const visibleRange = usePaginationVisibleRange(
|
|
131
|
+
const visibleRange = usePaginationVisibleRange(activeIndex as number, slidesCount);
|
|
126
132
|
|
|
127
133
|
// Inline style of wrapper element.
|
|
128
134
|
const wrapperStyle = { transform: `translateX(-${PAGINATION_ITEM_SIZE * visibleRange.min}px)` };
|
|
129
135
|
|
|
130
|
-
const controlsRef = React.useRef<HTMLDivElement>(null);
|
|
131
|
-
useKeyNavigate(controlsRef.current, onNextClick, onPreviousClick);
|
|
132
|
-
|
|
133
|
-
const slideshowSlidesId = React.useMemo(() => parent?.querySelector(`.${Slides.className}__slides`)?.id, [parent]);
|
|
134
|
-
|
|
135
136
|
return (
|
|
136
137
|
<div
|
|
137
|
-
ref={
|
|
138
|
+
ref={ref}
|
|
138
139
|
{...forwardedProps}
|
|
139
140
|
className={classNames(className, handleBasicClasses({ prefix: CLASSNAME, theme }), {
|
|
140
141
|
[`${CLASSNAME}--has-infinite-pagination`]: slidesCount > PAGINATION_ITEMS_MAX,
|
|
@@ -147,53 +148,64 @@ const InternalSlideshowControls: Comp<SlideshowControlsProps, HTMLDivElement> =
|
|
|
147
148
|
color={theme === Theme.dark ? 'light' : 'dark'}
|
|
148
149
|
emphasis={Emphasis.low}
|
|
149
150
|
onClick={onPreviousClick}
|
|
150
|
-
aria-controls={slideshowSlidesId}
|
|
151
151
|
/>
|
|
152
|
-
|
|
153
152
|
<div ref={paginationRef} className={`${CLASSNAME}__pagination`}>
|
|
154
153
|
<div
|
|
155
154
|
className={`${CLASSNAME}__pagination-items`}
|
|
156
155
|
style={wrapperStyle}
|
|
156
|
+
role="tablist"
|
|
157
157
|
{...paginationProps}
|
|
158
|
-
onBlur={onFocusOut}
|
|
159
158
|
>
|
|
160
|
-
{
|
|
161
|
-
|
|
162
|
-
index
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
159
|
+
{useMemo(
|
|
160
|
+
() =>
|
|
161
|
+
range(slidesCount).map((index) => {
|
|
162
|
+
const isOnEdge =
|
|
163
|
+
index !== 0 &&
|
|
164
|
+
index !== slidesCount - 1 &&
|
|
165
|
+
(index === visibleRange.min || index === visibleRange.max);
|
|
166
|
+
const isActive = activeIndex === index;
|
|
167
|
+
const isOutRange = index < visibleRange.min || index > visibleRange.max;
|
|
168
|
+
const {
|
|
169
|
+
className: itemClassName = undefined,
|
|
170
|
+
label = undefined,
|
|
171
|
+
...itemProps
|
|
172
|
+
} = paginationItemProps ? paginationItemProps(index) : {};
|
|
173
|
+
|
|
174
|
+
const ariaLabel =
|
|
175
|
+
label || paginationItemLabel?.(index) || `${index + 1} / ${slidesCount}`;
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<button
|
|
179
|
+
className={classNames(
|
|
180
|
+
handleBasicClasses({
|
|
181
|
+
prefix: `${CLASSNAME}__pagination-item`,
|
|
182
|
+
isActive,
|
|
183
|
+
isOnEdge,
|
|
184
|
+
isOutRange,
|
|
185
|
+
}),
|
|
186
|
+
itemClassName,
|
|
187
|
+
)}
|
|
188
|
+
key={index}
|
|
189
|
+
type="button"
|
|
190
|
+
tabIndex={isActive ? undefined : -1}
|
|
191
|
+
role="tab"
|
|
192
|
+
aria-selected={isActive}
|
|
193
|
+
onClick={() => onPaginationClick?.(index)}
|
|
194
|
+
aria-label={ariaLabel}
|
|
195
|
+
{...itemProps}
|
|
196
|
+
/>
|
|
197
|
+
);
|
|
198
|
+
}),
|
|
199
|
+
[
|
|
200
|
+
slidesCount,
|
|
201
|
+
visibleRange.min,
|
|
202
|
+
visibleRange.max,
|
|
203
|
+
activeIndex,
|
|
204
|
+
paginationItemProps,
|
|
205
|
+
paginationItemLabel,
|
|
206
|
+
onPaginationClick,
|
|
207
|
+
],
|
|
208
|
+
)}
|
|
197
209
|
</div>
|
|
198
210
|
</div>
|
|
199
211
|
|
|
@@ -204,7 +216,6 @@ const InternalSlideshowControls: Comp<SlideshowControlsProps, HTMLDivElement> =
|
|
|
204
216
|
className={`${CLASSNAME}__play`}
|
|
205
217
|
color={theme === Theme.dark ? 'light' : 'dark'}
|
|
206
218
|
emphasis={Emphasis.low}
|
|
207
|
-
aria-controls={slideshowSlidesId}
|
|
208
219
|
/>
|
|
209
220
|
) : null}
|
|
210
221
|
|
|
@@ -215,7 +226,6 @@ const InternalSlideshowControls: Comp<SlideshowControlsProps, HTMLDivElement> =
|
|
|
215
226
|
color={theme === Theme.dark ? 'light' : 'dark'}
|
|
216
227
|
emphasis={Emphasis.low}
|
|
217
228
|
onClick={onNextClick}
|
|
218
|
-
aria-controls={slideshowSlidesId}
|
|
219
229
|
/>
|
|
220
230
|
</div>
|
|
221
231
|
);
|
|
@@ -33,7 +33,16 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
|
33
33
|
export const SlideshowItem: Comp<SlideshowItemProps, HTMLDivElement> = forwardRef((props, ref) => {
|
|
34
34
|
const { className, children, ...forwardedProps } = props;
|
|
35
35
|
return (
|
|
36
|
-
<div
|
|
36
|
+
<div
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={classNames(
|
|
39
|
+
className,
|
|
40
|
+
handleBasicClasses({
|
|
41
|
+
prefix: CLASSNAME,
|
|
42
|
+
}),
|
|
43
|
+
)}
|
|
44
|
+
{...forwardedProps}
|
|
45
|
+
>
|
|
37
46
|
{children}
|
|
38
47
|
</div>
|
|
39
48
|
);
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
4
5
|
|
|
6
|
+
import { Comp, GenericProps } from '@lumx/react/utils/type';
|
|
7
|
+
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
5
8
|
import { useSlideFocusManagement } from './useSlideFocusManagement';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Defines the props of the component.
|
|
9
12
|
*/
|
|
10
|
-
export interface SlideshowItemGroupProps {
|
|
11
|
-
|
|
13
|
+
export interface SlideshowItemGroupProps extends GenericProps {
|
|
14
|
+
role?: 'tabpanel' | 'group';
|
|
12
15
|
label?: string;
|
|
13
16
|
isDisplayed?: boolean;
|
|
14
|
-
slidesRef?: React.RefObject<HTMLDivElement>;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -24,24 +26,39 @@ const COMPONENT_NAME = 'SlideshowItemGroup';
|
|
|
24
26
|
*/
|
|
25
27
|
export const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
26
28
|
|
|
27
|
-
export const buildSlideShowGroupId = (slidesId: string
|
|
28
|
-
slidesId && `${slidesId}-slide-${index}`;
|
|
29
|
+
export const buildSlideShowGroupId = (slidesId: string, index: number) => `${slidesId}-slide-${index}`;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
+
* SlideshowItemGroup component.
|
|
33
|
+
*
|
|
34
|
+
* @param props Component props.
|
|
35
|
+
* @param ref Component ref.
|
|
36
|
+
* @return React element.
|
|
32
37
|
*/
|
|
33
|
-
export const SlideshowItemGroup:
|
|
34
|
-
const {
|
|
38
|
+
export const SlideshowItemGroup: Comp<SlideshowItemGroupProps, HTMLDivElement> = forwardRef((props, ref) => {
|
|
39
|
+
const { className, children, role = 'group', label, isDisplayed, ...forwardedProps } = props;
|
|
40
|
+
const groupRef = React.useRef<HTMLDivElement>(null);
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
isSlideDisplayed: isDisplayed,
|
|
38
|
-
slidesRef,
|
|
39
|
-
});
|
|
42
|
+
useSlideFocusManagement({ isSlideDisplayed: isDisplayed, slideRef: groupRef });
|
|
40
43
|
|
|
41
44
|
return (
|
|
42
|
-
<div
|
|
45
|
+
<div
|
|
46
|
+
ref={mergeRefs(groupRef, ref)}
|
|
47
|
+
role={role}
|
|
48
|
+
className={classNames(
|
|
49
|
+
className,
|
|
50
|
+
handleBasicClasses({
|
|
51
|
+
prefix: CLASSNAME,
|
|
52
|
+
}),
|
|
53
|
+
)}
|
|
54
|
+
aria-roledescription="slide"
|
|
55
|
+
aria-label={label}
|
|
56
|
+
{...forwardedProps}
|
|
57
|
+
>
|
|
43
58
|
{children}
|
|
44
59
|
</div>
|
|
45
60
|
);
|
|
46
|
-
};
|
|
61
|
+
});
|
|
62
|
+
|
|
47
63
|
SlideshowItemGroup.displayName = COMPONENT_NAME;
|
|
64
|
+
SlideshowItemGroup.className = CLASSNAME;
|
|
@@ -22,7 +22,3 @@ export const PAGINATION_ITEMS_MAX = 5;
|
|
|
22
22
|
* Size of a pagination item. Used to translate wrapper.
|
|
23
23
|
*/
|
|
24
24
|
export const PAGINATION_ITEM_SIZE = 12;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export const NEXT_SLIDE_EVENT = 'lumx-next-slide-event';
|
|
28
|
-
export const PREV_SLIDE_EVENT = 'lumx-prev-slide-event';
|
|
@@ -3,102 +3,90 @@ import { getFocusableElements } from '@lumx/react/utils/focus/getFocusableElemen
|
|
|
3
3
|
|
|
4
4
|
export interface UseSlideFocusManagementProps {
|
|
5
5
|
isSlideDisplayed?: boolean;
|
|
6
|
-
|
|
6
|
+
slideRef: React.RefObject<HTMLDivElement>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Classname set on elements whose focus was blocked.
|
|
11
11
|
* This is to easily find elements that have been tempered with,
|
|
12
12
|
* and not elements whose focus was already initially blocked.
|
|
13
|
-
*/
|
|
14
|
-
const
|
|
13
|
+
* */
|
|
14
|
+
const BLOCKED_FOCUS_CLASSNAME = 'focus-blocked';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Manage how slides must behave when visible or not.
|
|
18
18
|
* When not visible, they should be hidden from screen readers and not focusable.
|
|
19
19
|
*/
|
|
20
|
-
export const useSlideFocusManagement = ({ isSlideDisplayed,
|
|
21
|
-
|
|
20
|
+
export const useSlideFocusManagement = ({ isSlideDisplayed, slideRef }: UseSlideFocusManagementProps) => {
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const element = slideRef?.current;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
React.useEffect(() => {
|
|
25
|
-
if (!slide) {
|
|
24
|
+
if (!element) {
|
|
26
25
|
return undefined;
|
|
27
26
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return set;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Display given slide to screen readers and, if focus was blocked, restore focus on elements.
|
|
30
|
+
*/
|
|
31
|
+
const enableSlide = () => {
|
|
32
|
+
// Hide from screen readers
|
|
33
|
+
element.setAttribute('aria-hidden', 'false');
|
|
34
|
+
// Find elements we have blocked focus on
|
|
35
|
+
element.querySelectorAll(`.${BLOCKED_FOCUS_CLASSNAME}`).forEach((focusableElement) => {
|
|
36
|
+
focusableElement.removeAttribute('tabindex');
|
|
37
|
+
focusableElement.classList.remove(BLOCKED_FOCUS_CLASSNAME);
|
|
40
38
|
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Hide given slide from screen readers and block focus on all focusable elements within.
|
|
43
|
+
*/
|
|
44
|
+
const blockSlide = () => {
|
|
45
|
+
element.setAttribute('aria-hidden', 'true');
|
|
46
|
+
getFocusableElements(element).forEach((focusableElement) => {
|
|
47
|
+
focusableElement.setAttribute('tabindex', '-1');
|
|
48
|
+
focusableElement.classList.add(BLOCKED_FOCUS_CLASSNAME);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
41
51
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
updateFocusableElements();
|
|
52
|
+
const handleDisplay = () => {
|
|
53
|
+
if (!element) {
|
|
54
|
+
return;
|
|
46
55
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
observer.observe(slide, { attributes: true, childList: true, subtree: true });
|
|
52
|
-
return observer.disconnect();
|
|
53
|
-
}, [slide]);
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
if (!slide || !focusableElementSet) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const focusableElements = Array.from(focusableElementSet);
|
|
60
|
-
|
|
61
|
-
if (!isSlideDisplayed) {
|
|
62
|
-
/* Block slide */
|
|
63
|
-
slide.setAttribute('inert', '');
|
|
64
|
-
slide.setAttribute('aria-hidden', 'true');
|
|
65
|
-
|
|
66
|
-
// TODO: remove when `inert` gets sufficient browser support
|
|
67
|
-
for (const focusableElement of focusableElements) {
|
|
68
|
-
focusableElement.setAttribute('tabindex', '-1');
|
|
69
|
-
focusableElement.setAttribute(BLOCKED_FOCUS, '');
|
|
56
|
+
if (isSlideDisplayed) {
|
|
57
|
+
enableSlide();
|
|
58
|
+
} else {
|
|
59
|
+
blockSlide();
|
|
70
60
|
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Callback function to execute when mutations are observed
|
|
64
|
+
const callback: MutationCallback = (mutationsList) => {
|
|
65
|
+
if (element) {
|
|
66
|
+
for (const mutation of mutationsList) {
|
|
67
|
+
if (mutation.type === 'childList') {
|
|
68
|
+
handleDisplay();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
80
71
|
}
|
|
72
|
+
};
|
|
81
73
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (isUserActivated) {
|
|
85
|
-
let elementToFocus: HTMLElement | undefined = slide;
|
|
74
|
+
// Create an observer instance linked to the callback function
|
|
75
|
+
const observer = new MutationObserver(callback);
|
|
86
76
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// eslint-disable-next-line prefer-destructuring
|
|
90
|
-
elementToFocus = focusableElements[0];
|
|
91
|
-
}
|
|
77
|
+
if (element) {
|
|
78
|
+
handleDisplay();
|
|
92
79
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
elementToFocus?.focus({ preventScroll: true });
|
|
80
|
+
/** If slide is hidden, start observing for elements to block focus */
|
|
81
|
+
if (!isSlideDisplayed) {
|
|
82
|
+
observer.observe(element, { attributes: true, childList: true, subtree: true });
|
|
99
83
|
}
|
|
100
84
|
}
|
|
101
|
-
}, [focusableElementSet, isSlideDisplayed, slide, slidesRef]);
|
|
102
85
|
|
|
103
|
-
|
|
86
|
+
return () => {
|
|
87
|
+
if (!isSlideDisplayed) {
|
|
88
|
+
observer.disconnect();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}, [isSlideDisplayed, slideRef]);
|
|
104
92
|
};
|