@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
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"url": "https://github.com/lumapps/design-system/issues"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@lumx/core": "^3.9.4
|
|
10
|
-
"@lumx/icons": "^3.9.4
|
|
9
|
+
"@lumx/core": "^3.9.4",
|
|
10
|
+
"@lumx/icons": "^3.9.4",
|
|
11
11
|
"@popperjs/core": "^2.5.4",
|
|
12
12
|
"body-scroll-lock": "^3.1.5",
|
|
13
13
|
"classnames": "^2.3.2",
|
|
@@ -111,5 +111,5 @@
|
|
|
111
111
|
"build:storybook": "storybook build"
|
|
112
112
|
},
|
|
113
113
|
"sideEffects": false,
|
|
114
|
-
"version": "3.9.4
|
|
114
|
+
"version": "3.9.4"
|
|
115
115
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { mdiAccount, mdiBee, mdiHeart } from '@lumx/icons';
|
|
2
|
+
import { Badge, BadgeWrapper, Button, Chip, ColorPalette, FlexBox, Icon, Orientation, Size } from '@lumx/react';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'LumX components/badge/BadgeWrapper',
|
|
7
|
+
component: BadgeWrapper,
|
|
8
|
+
argTypes: {
|
|
9
|
+
children: { control: false },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Using badge wrapper with icon
|
|
15
|
+
*/
|
|
16
|
+
export const WithIcon = {
|
|
17
|
+
args: {
|
|
18
|
+
badge: (
|
|
19
|
+
<Badge color={ColorPalette.red}>
|
|
20
|
+
<Icon icon={mdiHeart} />
|
|
21
|
+
</Badge>
|
|
22
|
+
),
|
|
23
|
+
children: <Icon icon={mdiAccount} size={Size.m} color={ColorPalette.dark} />,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Using badge wrapper with icon
|
|
29
|
+
*/
|
|
30
|
+
export const WithButton = {
|
|
31
|
+
args: {
|
|
32
|
+
badge: (
|
|
33
|
+
<Badge color={ColorPalette.red}>
|
|
34
|
+
<Icon icon={mdiHeart} />
|
|
35
|
+
</Badge>
|
|
36
|
+
),
|
|
37
|
+
children: <Button>Some button</Button>,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const WithChip = {
|
|
42
|
+
args: {
|
|
43
|
+
badge: (
|
|
44
|
+
<Badge color={ColorPalette.red}>
|
|
45
|
+
<Icon icon={mdiHeart} />
|
|
46
|
+
</Badge>
|
|
47
|
+
),
|
|
48
|
+
children: <Chip>Some chip</Chip>,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const InFlexbox = ({ orientation }: { orientation: Orientation }) => (
|
|
53
|
+
<FlexBox orientation={orientation} gap={Size.medium} vAlign="left">
|
|
54
|
+
<BadgeWrapper
|
|
55
|
+
badge={
|
|
56
|
+
<Badge color={ColorPalette.yellow}>
|
|
57
|
+
<Icon icon={mdiBee} />
|
|
58
|
+
</Badge>
|
|
59
|
+
}
|
|
60
|
+
>
|
|
61
|
+
<Chip color={ColorPalette.green}>Some chip</Chip>
|
|
62
|
+
</BadgeWrapper>
|
|
63
|
+
<BadgeWrapper
|
|
64
|
+
badge={
|
|
65
|
+
<Badge color={ColorPalette.red}>
|
|
66
|
+
<Icon icon={mdiHeart} />
|
|
67
|
+
</Badge>
|
|
68
|
+
}
|
|
69
|
+
>
|
|
70
|
+
<Chip color={ColorPalette.blue}>Some other chip</Chip>
|
|
71
|
+
</BadgeWrapper>
|
|
72
|
+
</FlexBox>
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
export const InVerticalFlexbox = () => <InFlexbox orientation={Orientation.vertical} />;
|
|
76
|
+
export const InHorizontalFlexbox = () => <InFlexbox orientation={Orientation.horizontal} />;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import omit from 'lodash/omit';
|
|
5
|
+
import last from 'lodash/last';
|
|
6
|
+
|
|
7
|
+
import { mdiAccount, mdiHeart } from '@lumx/icons/override/generated';
|
|
8
|
+
import { Badge, BadgeWrapper, BadgeWrapperProps, ColorPalette, Icon } from '@lumx/react';
|
|
9
|
+
import { getByClassName } from '@lumx/react/testing/utils/queries';
|
|
10
|
+
import { render } from '@testing-library/react';
|
|
11
|
+
|
|
12
|
+
const CLASSNAME = BadgeWrapper.className as string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Mounts the component and returns common DOM elements / data needed in multiple tests further down.
|
|
16
|
+
*/
|
|
17
|
+
const setup = (propsOverride: Partial<BadgeWrapperProps> = {}) => {
|
|
18
|
+
const props = {
|
|
19
|
+
badge: (
|
|
20
|
+
<Badge color={ColorPalette.red}>
|
|
21
|
+
<Icon icon={mdiHeart} />
|
|
22
|
+
</Badge>
|
|
23
|
+
),
|
|
24
|
+
children: <Icon icon={mdiAccount} />,
|
|
25
|
+
...propsOverride,
|
|
26
|
+
};
|
|
27
|
+
render(<BadgeWrapper {...omit(props, 'children')}>{props.children}</BadgeWrapper>);
|
|
28
|
+
const badgeWrapper = getByClassName(document.body, CLASSNAME);
|
|
29
|
+
return { badgeWrapper, props };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
describe(`<${BadgeWrapper.displayName}>`, () => {
|
|
33
|
+
describe('Props', () => {
|
|
34
|
+
it('should render badge', () => {
|
|
35
|
+
const { badgeWrapper } = setup();
|
|
36
|
+
|
|
37
|
+
expect(badgeWrapper).toHaveClass('lumx-badge-wrapper');
|
|
38
|
+
expect(badgeWrapper.children).toHaveLength(2);
|
|
39
|
+
expect(last(badgeWrapper.children)).toHaveClass('lumx-badge-wrapper__badge');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
commonTestsSuiteRTL(setup, {
|
|
44
|
+
baseClassName: CLASSNAME,
|
|
45
|
+
forwardClassName: 'badgeWrapper',
|
|
46
|
+
forwardAttributes: 'badgeWrapper',
|
|
47
|
+
forwardRef: 'badgeWrapper',
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
2
|
+
import { DEFAULT_PROPS } from '@lumx/react/components/select/WithSelectContext';
|
|
3
|
+
import { Comp, GenericProps } from '@lumx/react/utils/type';
|
|
4
|
+
import classNames from 'classnames';
|
|
5
|
+
import React, { forwardRef, ReactElement, ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
export interface BadgeWrapperProps extends GenericProps {
|
|
8
|
+
/** Badge. */
|
|
9
|
+
badge: ReactElement;
|
|
10
|
+
/** Node to display the badge on */
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Component display name.
|
|
16
|
+
*/
|
|
17
|
+
const COMPONENT_NAME = 'BadgeWrapper';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Component default class name and class prefix.
|
|
21
|
+
*/
|
|
22
|
+
const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
23
|
+
|
|
24
|
+
export const BadgeWrapper: Comp<BadgeWrapperProps, HTMLDivElement> = forwardRef((props, ref) => {
|
|
25
|
+
const { badge, children, className, ...forwardedProps } = props;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div ref={ref} {...forwardedProps} className={classNames(className, handleBasicClasses({ prefix: CLASSNAME }))}>
|
|
29
|
+
{children}
|
|
30
|
+
{badge && <div className={`${CLASSNAME}__badge`}>{badge}</div>}
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
BadgeWrapper.displayName = 'BadgeWrapper';
|
|
35
|
+
BadgeWrapper.className = CLASSNAME;
|
|
36
|
+
BadgeWrapper.defaultProps = DEFAULT_PROPS;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
|
|
4
|
-
import { queryByRole, render } from '@testing-library/react';
|
|
4
|
+
import { queryByRole, render, screen } from '@testing-library/react';
|
|
5
5
|
import { getByClassName, queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
6
6
|
import userEvent from '@testing-library/user-event';
|
|
7
7
|
import { isFocusVisible } from '@lumx/react/utils/isFocusVisible';
|
|
@@ -12,12 +12,15 @@ const CLASSNAME = ExpansionPanel.className as string;
|
|
|
12
12
|
|
|
13
13
|
jest.mock('@lumx/react/utils/isFocusVisible');
|
|
14
14
|
|
|
15
|
+
const mockChildrenContent = 'children content';
|
|
16
|
+
|
|
15
17
|
/**
|
|
16
18
|
* Mounts the component and returns common DOM elements / data needed in multiple tests further down.
|
|
17
19
|
*/
|
|
18
20
|
const setup = (propsOverride: Partial<ExpansionPanelProps> = {}) => {
|
|
19
21
|
const props = {
|
|
20
22
|
toggleButtonProps: { label: 'Toggle' },
|
|
23
|
+
children: mockChildrenContent,
|
|
21
24
|
...propsOverride,
|
|
22
25
|
};
|
|
23
26
|
const { container } = render(<ExpansionPanel {...props} />);
|
|
@@ -28,7 +31,7 @@ const setup = (propsOverride: Partial<ExpansionPanelProps> = {}) => {
|
|
|
28
31
|
query: {
|
|
29
32
|
toggleButton: () => queryByRole(container, 'button', { name: /Toggle/i }),
|
|
30
33
|
header: () => queryByClassName(container, `${CLASSNAME}__header`),
|
|
31
|
-
content: () =>
|
|
34
|
+
content: () => screen.queryByText(mockChildrenContent),
|
|
32
35
|
},
|
|
33
36
|
props,
|
|
34
37
|
};
|
|
@@ -12,6 +12,7 @@ import { ColorPalette, DragHandle, Emphasis, IconButton, IconButtonProps, Theme
|
|
|
12
12
|
import { Comp, GenericProps, HasTheme, isComponent } from '@lumx/react/utils/type';
|
|
13
13
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
14
14
|
import { partitionMulti } from '@lumx/react/utils/partitionMulti';
|
|
15
|
+
import { WINDOW } from '@lumx/react/constants';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Defines the props of the component.
|
|
@@ -80,6 +81,7 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
80
81
|
...forwardedProps
|
|
81
82
|
} = props;
|
|
82
83
|
|
|
84
|
+
const [isChildrenVisible, setIsChildrenVisible] = useState(isOpen);
|
|
83
85
|
const children: ReactNode[] = Children.toArray(anyChildren);
|
|
84
86
|
|
|
85
87
|
// Partition children by types.
|
|
@@ -94,15 +96,34 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
94
96
|
);
|
|
95
97
|
|
|
96
98
|
const toggleOpen = (event: React.MouseEvent) => {
|
|
99
|
+
const hasReducedMotionEnabled = WINDOW?.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches;
|
|
97
100
|
const shouldOpen = !isOpen;
|
|
101
|
+
|
|
98
102
|
if (isFunction(onOpen) && shouldOpen) {
|
|
99
103
|
onOpen(event);
|
|
104
|
+
// On open, we immediately show children
|
|
105
|
+
setIsChildrenVisible(true);
|
|
100
106
|
}
|
|
101
107
|
if (isFunction(onClose) && !shouldOpen) {
|
|
102
108
|
onClose(event);
|
|
109
|
+
/**
|
|
110
|
+
* On close, we only show children immediately if reduced motion is enabled
|
|
111
|
+
* When disabled, the children will be hidden via the `onTransitionEnd` prop.
|
|
112
|
+
*/
|
|
113
|
+
if (hasReducedMotionEnabled) {
|
|
114
|
+
setIsChildrenVisible(false);
|
|
115
|
+
}
|
|
103
116
|
}
|
|
104
117
|
if (isFunction(onToggleOpen)) {
|
|
105
118
|
onToggleOpen(shouldOpen, event);
|
|
119
|
+
/**
|
|
120
|
+
* On toggle, we forward the show state if
|
|
121
|
+
* * the toggle will open the expansion panel
|
|
122
|
+
* * reduced motion is enabled. When disabled, the children will be hidden via the `onTransitionEnd` prop.
|
|
123
|
+
* */
|
|
124
|
+
if (shouldOpen || hasReducedMotionEnabled) {
|
|
125
|
+
setIsChildrenVisible(shouldOpen);
|
|
126
|
+
}
|
|
106
127
|
}
|
|
107
128
|
};
|
|
108
129
|
|
|
@@ -123,7 +144,6 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
123
144
|
);
|
|
124
145
|
|
|
125
146
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
126
|
-
const isContentVisible = (): boolean => get(wrapperRef.current, 'clientHeight', 0) > 0;
|
|
127
147
|
|
|
128
148
|
// Switch max height on/off to activate the CSS transition (updates when children changes).
|
|
129
149
|
const [maxHeight, setMaxHeight] = useState('0');
|
|
@@ -153,8 +173,17 @@ export const ExpansionPanel: Comp<ExpansionPanelProps, HTMLDivElement> = forward
|
|
|
153
173
|
</div>
|
|
154
174
|
</header>
|
|
155
175
|
|
|
156
|
-
{(isOpen ||
|
|
157
|
-
<div
|
|
176
|
+
{(isOpen || isChildrenVisible) && (
|
|
177
|
+
<div
|
|
178
|
+
className={`${CLASSNAME}__wrapper`}
|
|
179
|
+
style={{ maxHeight }}
|
|
180
|
+
// At the end of the closing transition, remove the children from the DOM
|
|
181
|
+
onTransitionEnd={() => {
|
|
182
|
+
if (!isOpen) {
|
|
183
|
+
setIsChildrenVisible(false);
|
|
184
|
+
}
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
158
187
|
<div className={`${CLASSNAME}__container`} ref={wrapperRef}>
|
|
159
188
|
<div className={`${CLASSNAME}__content`}>{content}</div>
|
|
160
189
|
|
|
@@ -31,7 +31,6 @@ export const ImageSlideshow: React.FC<ImageSlideshowProps> = ({
|
|
|
31
31
|
activeIndex,
|
|
32
32
|
slideshowId,
|
|
33
33
|
setSlideshow,
|
|
34
|
-
slideshow,
|
|
35
34
|
slideshowSlidesId,
|
|
36
35
|
slidesCount,
|
|
37
36
|
onNextClick,
|
|
@@ -62,7 +61,6 @@ export const ImageSlideshow: React.FC<ImageSlideshowProps> = ({
|
|
|
62
61
|
onNextClick={onNextClick}
|
|
63
62
|
onPreviousClick={onPreviousClick}
|
|
64
63
|
onPaginationClick={onPaginationClick}
|
|
65
|
-
parentRef={slideshow}
|
|
66
64
|
{...slideshowControlsProps}
|
|
67
65
|
paginationItemProps={(index: number) => {
|
|
68
66
|
const props = slideshowControlsProps?.paginationItemProps?.(index) || {};
|
|
@@ -74,7 +74,7 @@ export function usePointerZoom(
|
|
|
74
74
|
const pointers = Object.values(activePointers);
|
|
75
75
|
|
|
76
76
|
// Make sure we run computation on one of the pointer in the group
|
|
77
|
-
if (pointers[0]
|
|
77
|
+
if (pointers[0]?.pointerId !== event.pointerId) {
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -3,11 +3,9 @@ import chunk from 'lodash/chunk';
|
|
|
3
3
|
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
|
|
6
|
-
import { FULL_WIDTH_PERCENT
|
|
6
|
+
import { FULL_WIDTH_PERCENT } from '@lumx/react/components/slideshow/constants';
|
|
7
7
|
import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
|
|
8
8
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
9
|
-
import { useMergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
10
|
-
import { useKeyNavigate } from '@lumx/react/components/slideshow/useKeyNavigate';
|
|
11
9
|
import { buildSlideShowGroupId, SlideshowItemGroup } from './SlideshowItemGroup';
|
|
12
10
|
|
|
13
11
|
export interface SlidesProps extends GenericProps, HasTheme {
|
|
@@ -34,7 +32,7 @@ export interface SlidesProps extends GenericProps, HasTheme {
|
|
|
34
32
|
/**
|
|
35
33
|
* Accessible label to set on a slide group.
|
|
36
34
|
* Receives the group position starting from 1 and the total number of groups.
|
|
37
|
-
*/
|
|
35
|
+
* */
|
|
38
36
|
slideGroupLabel?: (groupPosition: number, groupTotal: number) => string;
|
|
39
37
|
}
|
|
40
38
|
|
|
@@ -72,6 +70,7 @@ export const Slides: Comp<SlidesProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
72
70
|
slideGroupLabel,
|
|
73
71
|
...forwardedProps
|
|
74
72
|
} = props;
|
|
73
|
+
const wrapperRef = React.useRef<HTMLDivElement>(null);
|
|
75
74
|
const startIndexVisible = activeIndex;
|
|
76
75
|
const endIndexVisible = startIndexVisible + 1;
|
|
77
76
|
|
|
@@ -83,17 +82,10 @@ export const Slides: Comp<SlidesProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
83
82
|
return groupBy && groupBy > 1 ? chunk(childrenArray, groupBy) : childrenArray;
|
|
84
83
|
}, [children, groupBy]);
|
|
85
84
|
|
|
86
|
-
const slidesRef = React.useRef<HTMLDivElement>(null);
|
|
87
|
-
|
|
88
|
-
const slide = slidesRef.current;
|
|
89
|
-
const onNextSlide = React.useCallback(() => slide?.dispatchEvent(new CustomEvent(NEXT_SLIDE_EVENT)), [slide]);
|
|
90
|
-
const onPrevSlide = React.useCallback(() => slide?.dispatchEvent(new CustomEvent(PREV_SLIDE_EVENT)), [slide]);
|
|
91
|
-
useKeyNavigate(slide, onNextSlide, onPrevSlide);
|
|
92
|
-
|
|
93
85
|
return (
|
|
94
86
|
<section
|
|
95
87
|
id={id}
|
|
96
|
-
ref={
|
|
88
|
+
ref={ref}
|
|
97
89
|
{...forwardedProps}
|
|
98
90
|
className={classNames(className, handleBasicClasses({ prefix: CLASSNAME, theme }), {
|
|
99
91
|
[`${CLASSNAME}--fill-height`]: fillHeight,
|
|
@@ -108,14 +100,14 @@ export const Slides: Comp<SlidesProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
108
100
|
onMouseLeave={toggleAutoPlay}
|
|
109
101
|
aria-live={isAutoPlaying ? 'off' : 'polite'}
|
|
110
102
|
>
|
|
111
|
-
<div className={`${CLASSNAME}__wrapper`} style={wrapperStyle}>
|
|
103
|
+
<div ref={wrapperRef} className={`${CLASSNAME}__wrapper`} style={wrapperStyle}>
|
|
112
104
|
{groups.map((group, index) => (
|
|
113
105
|
<SlideshowItemGroup
|
|
114
106
|
key={index}
|
|
115
107
|
id={slidesId && buildSlideShowGroupId(slidesId, index)}
|
|
116
|
-
|
|
108
|
+
role={hasControls ? 'tabpanel' : 'group'}
|
|
109
|
+
label={slideGroupLabel ? slideGroupLabel(index + 1, groups.length) : undefined}
|
|
117
110
|
isDisplayed={index >= startIndexVisible && index < endIndexVisible}
|
|
118
|
-
slidesRef={slidesRef}
|
|
119
111
|
>
|
|
120
112
|
{group}
|
|
121
113
|
</SlideshowItemGroup>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/anchor-is-valid */
|
|
2
1
|
import React from 'react';
|
|
3
2
|
import range from 'lodash/range';
|
|
4
|
-
import { AspectRatio, Button, FlexBox, ImageBlock, Slideshow, SlideshowItem, Orientation
|
|
3
|
+
import { AspectRatio, Button, FlexBox, ImageBlock, Slideshow, SlideshowItem, Orientation } from '@lumx/react';
|
|
5
4
|
import { IMAGES, LANDSCAPE_IMAGES } from '@lumx/react/stories/controls/image';
|
|
6
5
|
|
|
7
6
|
export default {
|
|
@@ -66,16 +65,6 @@ export const ResponsiveSlideShowSwipe = () => {
|
|
|
66
65
|
}}
|
|
67
66
|
slideGroupLabel={(currentGroup, totalGroup) => `${currentGroup} of ${totalGroup}`}
|
|
68
67
|
>
|
|
69
|
-
<SlideshowItem>
|
|
70
|
-
<FlexBox
|
|
71
|
-
style={{ border: '1px solid grey', maxWidth: 300, height: 300 }}
|
|
72
|
-
hAlign="center"
|
|
73
|
-
vAlign="center"
|
|
74
|
-
>
|
|
75
|
-
<Link href="#">A link</Link>
|
|
76
|
-
<Button>A button</Button>
|
|
77
|
-
</FlexBox>
|
|
78
|
-
</SlideshowItem>
|
|
79
68
|
{slides.map((slide) => (
|
|
80
69
|
<SlideshowItem key={`${slide}`}>
|
|
81
70
|
<FlexBox
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import { SlideshowControls, SlideshowControlsProps, Theme, Slides, SlidesProps } from '@lumx/react';
|
|
4
|
+
import { DEFAULT_OPTIONS } from '@lumx/react/hooks/useSlideshowControls';
|
|
4
5
|
import { Comp, GenericProps } from '@lumx/react/utils/type';
|
|
5
6
|
import { useFocusWithin } from '@lumx/react/hooks/useFocusWithin';
|
|
6
7
|
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
7
|
-
import {
|
|
8
|
+
import { buildSlideShowGroupId } from './SlideshowItemGroup';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Defines the props of the component.
|
|
@@ -13,7 +14,7 @@ export interface SlideshowProps
|
|
|
13
14
|
extends GenericProps,
|
|
14
15
|
Pick<SlidesProps, 'autoPlay' | 'slidesId' | 'id' | 'theme' | 'fillHeight' | 'groupBy' | 'slideGroupLabel'> {
|
|
15
16
|
/** current slide active */
|
|
16
|
-
activeIndex?:
|
|
17
|
+
activeIndex?: SlidesProps['activeIndex'];
|
|
17
18
|
/** Interval between each slide when automatic rotation is enabled. */
|
|
18
19
|
interval?: number;
|
|
19
20
|
/** Props to pass to the slideshow controls (minus those already set by the Slideshow props). */
|
|
@@ -133,14 +134,27 @@ export const Slideshow: Comp<SlideshowProps, HTMLDivElement> = forwardRef((props
|
|
|
133
134
|
parentRef={slideshow}
|
|
134
135
|
theme={theme}
|
|
135
136
|
isAutoPlaying={isAutoPlaying}
|
|
137
|
+
nextButtonProps={{
|
|
138
|
+
'aria-controls': slideshowSlidesId,
|
|
139
|
+
...slideshowControlsProps.nextButtonProps,
|
|
140
|
+
}}
|
|
141
|
+
previousButtonProps={{
|
|
142
|
+
'aria-controls': slideshowSlidesId,
|
|
143
|
+
...slideshowControlsProps.previousButtonProps,
|
|
144
|
+
}}
|
|
136
145
|
playButtonProps={
|
|
137
146
|
autoPlay
|
|
138
147
|
? {
|
|
148
|
+
'aria-controls': slideshowSlidesId,
|
|
139
149
|
onClick: toggleForcePause,
|
|
140
150
|
...slideshowControlsProps.playButtonProps,
|
|
141
151
|
}
|
|
142
152
|
: undefined
|
|
143
153
|
}
|
|
154
|
+
paginationItemProps={(index) => ({
|
|
155
|
+
'aria-controls': buildSlideShowGroupId(slideshowSlidesId, index),
|
|
156
|
+
...slideshowControlsProps.paginationItemProps?.(index),
|
|
157
|
+
})}
|
|
144
158
|
/>
|
|
145
159
|
</div>
|
|
146
160
|
) : undefined
|
|
@@ -78,10 +78,11 @@ export const ControllingSlideshow = ({ images = Object.values(LANDSCAPE_IMAGES),
|
|
|
78
78
|
parentRef={slideshow}
|
|
79
79
|
theme={theme}
|
|
80
80
|
isAutoPlaying={isAutoPlaying}
|
|
81
|
-
nextButtonProps={{ label: 'Next' }}
|
|
82
|
-
previousButtonProps={{ label: 'Previous' }}
|
|
81
|
+
nextButtonProps={{ label: 'Next', 'aria-controls': slideshowSlidesId }}
|
|
82
|
+
previousButtonProps={{ label: 'Previous', 'aria-controls': slideshowSlidesId }}
|
|
83
83
|
playButtonProps={{
|
|
84
84
|
label: 'Play/Pause',
|
|
85
|
+
'aria-controls': slideshowSlidesId,
|
|
85
86
|
onClick: toggleForcePause,
|
|
86
87
|
}}
|
|
87
88
|
paginationItemLabel={(index) => `Slide ${index}`}
|