@lumx/react 2.0.0-alpha.0 → 2.0.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/esm/_internal/AlertDialog.js +15 -5
- package/esm/_internal/AlertDialog.js.map +1 -1
- package/esm/_internal/AutocompleteMultiple.js +6 -2
- package/esm/_internal/AutocompleteMultiple.js.map +1 -1
- package/esm/_internal/ButtonRoot.js +1 -0
- package/esm/_internal/ButtonRoot.js.map +1 -1
- package/esm/_internal/ClickAwayProvider.js +31 -30
- package/esm/_internal/ClickAwayProvider.js.map +1 -1
- package/esm/_internal/Dialog2.js +6 -3
- package/esm/_internal/Dialog2.js.map +1 -1
- package/esm/_internal/Dropdown2.js +6 -2
- package/esm/_internal/Dropdown2.js.map +1 -1
- package/esm/_internal/Icon2.js +1 -1
- package/esm/_internal/Icon2.js.map +1 -1
- package/esm/_internal/Lightbox2.js +4 -2
- package/esm/_internal/Lightbox2.js.map +1 -1
- package/esm/_internal/Message2.js +4 -3
- package/esm/_internal/Message2.js.map +1 -1
- package/esm/_internal/Popover2.js +4 -2
- package/esm/_internal/Popover2.js.map +1 -1
- package/esm/_internal/SelectMultiple.js +39 -61
- package/esm/_internal/SelectMultiple.js.map +1 -1
- package/esm/_internal/SlideshowControls.js +93 -44
- package/esm/_internal/SlideshowControls.js.map +1 -1
- package/esm/_internal/Switch2.js +2 -0
- package/esm/_internal/Switch2.js.map +1 -1
- package/esm/_internal/alert-dialog.js +1 -1
- package/esm/_internal/autocomplete.js +1 -2
- package/esm/_internal/autocomplete.js.map +1 -1
- package/esm/_internal/button.js +1 -2
- package/esm/_internal/button.js.map +1 -1
- package/esm/_internal/date-picker.js +1 -2
- package/esm/_internal/date-picker.js.map +1 -1
- package/esm/_internal/dialog.js +1 -1
- package/esm/_internal/dropdown.js +1 -1
- package/esm/_internal/expansion-panel.js +1 -2
- package/esm/_internal/expansion-panel.js.map +1 -1
- package/esm/_internal/getRootClassName.js +78 -68
- package/esm/_internal/getRootClassName.js.map +1 -1
- package/esm/_internal/lightbox.js +1 -2
- package/esm/_internal/lightbox.js.map +1 -1
- package/esm/_internal/popover.js +1 -1
- package/esm/_internal/select.js +1 -2
- package/esm/_internal/select.js.map +1 -1
- package/esm/_internal/side-navigation.js +1 -2
- package/esm/_internal/side-navigation.js.map +1 -1
- package/esm/_internal/slideshow.js +1 -2
- package/esm/_internal/slideshow.js.map +1 -1
- package/esm/_internal/text-field.js +1 -2
- package/esm/_internal/text-field.js.map +1 -1
- package/esm/_internal/tooltip.js +1 -2
- package/esm/_internal/tooltip.js.map +1 -1
- package/esm/_internal/useDelayedVisibility.js +16 -2
- package/esm/_internal/useDelayedVisibility.js.map +1 -1
- package/esm/_internal/useDisableBodyScroll.js +205 -7
- package/esm/_internal/useDisableBodyScroll.js.map +1 -1
- package/esm/index.js +1 -2
- package/esm/index.js.map +1 -1
- package/package.json +6 -6
- package/src/components/alert-dialog/AlertDialog.stories.tsx +29 -0
- package/src/components/alert-dialog/AlertDialog.tsx +29 -9
- package/src/components/alert-dialog/__snapshots__/AlertDialog.test.tsx.snap +91 -0
- package/src/components/autocomplete/Autocomplete.test.tsx +2 -0
- package/src/components/autocomplete/Autocomplete.tsx +7 -0
- package/src/components/autocomplete/AutocompleteMultiple.test.tsx +2 -0
- package/src/components/autocomplete/AutocompleteMultiple.tsx +2 -0
- package/src/components/autocomplete/__snapshots__/Autocomplete.test.tsx.snap +2 -0
- package/src/components/autocomplete/__snapshots__/AutocompleteMultiple.test.tsx.snap +2 -0
- package/src/components/button/Button.stories.tsx +8 -2
- package/src/components/button/ButtonRoot.tsx +1 -1
- package/src/components/comment-block/CommentBlock.stories.tsx +3 -2
- package/src/components/comment-block/__snapshots__/CommentBlock.test.tsx.snap +1 -1
- package/src/components/dialog/Dialog.stories.tsx +62 -22
- package/src/components/dialog/Dialog.tsx +8 -2
- package/src/components/dialog/__snapshots__/Dialog.test.tsx.snap +99 -35
- package/src/components/icon/Icon.tsx +1 -0
- package/src/components/icon/__snapshots__/Icon.test.tsx.snap +2 -2
- package/src/components/lightbox/Lightbox.tsx +4 -1
- package/src/components/lightbox/__snapshots__/Lightbox.test.tsx.snap +7 -5
- package/src/components/message/Message.stories.tsx +8 -0
- package/src/components/message/Message.tsx +4 -2
- package/src/components/popover/Popover.tsx +4 -1
- package/src/components/popover/__snapshots__/Popover.test.tsx.snap +100 -80
- package/src/components/select/WithSelectContext.tsx +3 -60
- package/src/components/slideshow/Slideshow.stories.tsx +47 -7
- package/src/components/slideshow/Slideshow.test.tsx +4 -1
- package/src/components/slideshow/Slideshow.tsx +51 -26
- package/src/components/slideshow/SlideshowControls.stories.tsx +0 -4
- package/src/components/slideshow/SlideshowControls.tsx +23 -8
- package/src/components/slideshow/__snapshots__/Slideshow.test.tsx.snap +0 -5
- package/src/components/slideshow/useKeyNavigate.ts +28 -0
- package/src/components/slideshow/useSwipeNavigate.ts +18 -0
- package/src/components/switch/Switch.tsx +2 -0
- package/src/components/switch/__snapshots__/Switch.test.tsx.snap +8 -0
- package/src/hooks/useClickAway.tsx +6 -5
- package/src/hooks/useDelayedVisibility.tsx +22 -2
- package/src/hooks/useDisableBodyScroll.ts +16 -1
- package/src/hooks/useInfiniteScroll.tsx +14 -3
- package/src/hooks/useListenFocus.tsx +26 -0
- package/src/utils/ClickAwayProvider/ClickAwayProvider.tsx +23 -32
- package/types.d.ts +17 -8
- package/src/components/slideshow/useKeyOrSwipeNavigate.ts +0 -37
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { detectHorizontalSwipe } from '@lumx/core/js/utils';
|
|
3
|
+
|
|
4
|
+
const isTouchDevice = () => 'ontouchstart' in window;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Listen swipe to navigate left and right.
|
|
8
|
+
*/
|
|
9
|
+
export function useSwipeNavigate(element?: HTMLElement | null, onNext?: () => void, onPrevious?: () => void): void {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!element || !isTouchDevice()) return undefined;
|
|
12
|
+
|
|
13
|
+
return detectHorizontalSwipe(element, (swipe) => {
|
|
14
|
+
const callback = swipe === 'right' ? onPrevious : onNext;
|
|
15
|
+
callback?.();
|
|
16
|
+
});
|
|
17
|
+
}, [onPrevious, onNext, element]);
|
|
18
|
+
}
|
|
@@ -100,12 +100,14 @@ export const Switch: Comp<SwitchProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
100
100
|
<div className={`${CLASSNAME}__input-wrapper`}>
|
|
101
101
|
<input
|
|
102
102
|
type="checkbox"
|
|
103
|
+
role="switch"
|
|
103
104
|
id={switchId}
|
|
104
105
|
className={`${CLASSNAME}__input-native`}
|
|
105
106
|
name={name}
|
|
106
107
|
value={value}
|
|
107
108
|
disabled={isDisabled}
|
|
108
109
|
checked={isChecked}
|
|
110
|
+
aria-checked={Boolean(isChecked)}
|
|
109
111
|
onChange={handleChange}
|
|
110
112
|
/>
|
|
111
113
|
|
|
@@ -8,9 +8,11 @@ exports[`<Switch> Conditions should not display the \`helper\` if no \`label\` i
|
|
|
8
8
|
className="lumx-switch__input-wrapper"
|
|
9
9
|
>
|
|
10
10
|
<input
|
|
11
|
+
aria-checked={false}
|
|
11
12
|
className="lumx-switch__input-native"
|
|
12
13
|
id="switch-uid"
|
|
13
14
|
onChange={[Function]}
|
|
15
|
+
role="switch"
|
|
14
16
|
type="checkbox"
|
|
15
17
|
/>
|
|
16
18
|
<div
|
|
@@ -35,9 +37,11 @@ exports[`<Switch> Snapshots and structure should render correctly with a \`label
|
|
|
35
37
|
className="lumx-switch__input-wrapper"
|
|
36
38
|
>
|
|
37
39
|
<input
|
|
40
|
+
aria-checked={false}
|
|
38
41
|
className="lumx-switch__input-native"
|
|
39
42
|
id="switch-uid"
|
|
40
43
|
onChange={[Function]}
|
|
44
|
+
role="switch"
|
|
41
45
|
type="checkbox"
|
|
42
46
|
/>
|
|
43
47
|
<div
|
|
@@ -80,9 +84,11 @@ exports[`<Switch> Snapshots and structure should render correctly with only a \`
|
|
|
80
84
|
className="lumx-switch__input-wrapper"
|
|
81
85
|
>
|
|
82
86
|
<input
|
|
87
|
+
aria-checked={false}
|
|
83
88
|
className="lumx-switch__input-native"
|
|
84
89
|
id="switch-uid"
|
|
85
90
|
onChange={[Function]}
|
|
91
|
+
role="switch"
|
|
86
92
|
type="checkbox"
|
|
87
93
|
/>
|
|
88
94
|
<div
|
|
@@ -118,9 +124,11 @@ exports[`<Switch> Snapshots and structure should render correctly without any la
|
|
|
118
124
|
className="lumx-switch__input-wrapper"
|
|
119
125
|
>
|
|
120
126
|
<input
|
|
127
|
+
aria-checked={false}
|
|
121
128
|
className="lumx-switch__input-native"
|
|
122
129
|
id="switch-uid"
|
|
123
130
|
onChange={[Function]}
|
|
131
|
+
role="switch"
|
|
124
132
|
type="checkbox"
|
|
125
133
|
/>
|
|
126
134
|
<div
|
|
@@ -8,7 +8,7 @@ const EVENT_TYPES = ['mousedown', 'touchstart'];
|
|
|
8
8
|
|
|
9
9
|
function isClickAway(target: HTMLElement, refs: Array<RefObject<HTMLElement>>): boolean {
|
|
10
10
|
// The target element is not contained in any of the listed element references.
|
|
11
|
-
return !refs.some((e) => e
|
|
11
|
+
return !refs.some((e) => e?.current?.contains(target));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface ClickAwayParameters {
|
|
@@ -19,7 +19,7 @@ export interface ClickAwayParameters {
|
|
|
19
19
|
/**
|
|
20
20
|
* Elements from which we want to detect the click away.
|
|
21
21
|
*/
|
|
22
|
-
refs: Array<RefObject<HTMLElement
|
|
22
|
+
refs: RefObject<Array<RefObject<HTMLElement>>>;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -29,12 +29,13 @@ export interface ClickAwayParameters {
|
|
|
29
29
|
*/
|
|
30
30
|
export function useClickAway({ callback, refs }: ClickAwayParameters): void {
|
|
31
31
|
useEffect(() => {
|
|
32
|
-
|
|
32
|
+
const { current: currentRefs } = refs;
|
|
33
|
+
if (!callback || !currentRefs || isEmpty(currentRefs)) {
|
|
33
34
|
return undefined;
|
|
34
35
|
}
|
|
35
36
|
const listener: EventListener = (evt) => {
|
|
36
|
-
if (isClickAway(evt.target as HTMLElement,
|
|
37
|
-
|
|
37
|
+
if (isClickAway(evt.target as HTMLElement, currentRefs)) {
|
|
38
|
+
callback(evt);
|
|
38
39
|
}
|
|
39
40
|
};
|
|
40
41
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { useEffect, useState, useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns true if the component is visible taking into account the component's
|
|
@@ -6,9 +6,14 @@ import { useEffect, useState } from 'react';
|
|
|
6
6
|
*
|
|
7
7
|
* @param isComponentVisible Whether the component intends to be visible or not.
|
|
8
8
|
* @param transitionDuration time in ms that the transition takes for the specific component.
|
|
9
|
+
* @param onVisibilityChange Callback called when the visibility changes.
|
|
9
10
|
* @return true if the component should be rendered
|
|
10
11
|
*/
|
|
11
|
-
export function useDelayedVisibility(
|
|
12
|
+
export function useDelayedVisibility(
|
|
13
|
+
isComponentVisible: boolean,
|
|
14
|
+
transitionDuration: number,
|
|
15
|
+
onVisibilityChange?: (isVisible: boolean) => void,
|
|
16
|
+
): boolean {
|
|
12
17
|
// Delay visibility to account for the 400ms of CSS opacity animation.
|
|
13
18
|
const [isVisible, setVisible] = useState(isComponentVisible);
|
|
14
19
|
|
|
@@ -20,5 +25,20 @@ export function useDelayedVisibility(isComponentVisible: boolean, transitionDura
|
|
|
20
25
|
}
|
|
21
26
|
}, [isComponentVisible, transitionDuration]);
|
|
22
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Since we don't want onVisibiltyChange function to trigger itself if when it changes,
|
|
30
|
+
* we store the previous visibility and only trigger when visibility is different
|
|
31
|
+
* than previous value.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const previousVisibility = useRef(isVisible);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (onVisibilityChange && previousVisibility.current !== isVisible) {
|
|
38
|
+
onVisibilityChange(isVisible);
|
|
39
|
+
previousVisibility.current = isVisible;
|
|
40
|
+
}
|
|
41
|
+
}, [isVisible, onVisibilityChange]);
|
|
42
|
+
|
|
23
43
|
return isComponentVisible || isVisible;
|
|
24
44
|
}
|
|
@@ -2,12 +2,27 @@ import { useEffect } from 'react';
|
|
|
2
2
|
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
|
|
3
3
|
import { Falsy } from '@lumx/react/utils';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Disables the scroll on the body to make it only usable in the current modal element.
|
|
7
|
+
* When the modal element is not provided anymore, the scroll is restored.
|
|
8
|
+
*
|
|
9
|
+
* @param modalElement The modal element.
|
|
10
|
+
*/
|
|
5
11
|
export const useDisableBodyScroll = (modalElement: Element | Falsy): void => {
|
|
6
12
|
useEffect(() => {
|
|
7
13
|
if (!modalElement) {
|
|
8
14
|
return undefined;
|
|
9
15
|
}
|
|
16
|
+
// Fixing the document overflow style to prevent a bug that scrolls the window to the top.
|
|
17
|
+
const previousDocumentOverflow = document.documentElement.style.overflow;
|
|
18
|
+
document.documentElement.style.overflow = 'visible';
|
|
10
19
|
disableBodyScroll(modalElement);
|
|
11
|
-
return () =>
|
|
20
|
+
return () => {
|
|
21
|
+
enableBodyScroll(modalElement);
|
|
22
|
+
// Restore the previous overflow style.
|
|
23
|
+
requestAnimationFrame(() => {
|
|
24
|
+
document.documentElement.style.overflow = previousDocumentOverflow;
|
|
25
|
+
});
|
|
26
|
+
};
|
|
12
27
|
}, [modalElement]);
|
|
13
28
|
};
|
|
@@ -7,6 +7,9 @@ type useInfiniteScrollType = (
|
|
|
7
7
|
) => void;
|
|
8
8
|
type EventCallback = (evt?: Event) => void;
|
|
9
9
|
|
|
10
|
+
// The error margin in px we want to have for triggering infinite scroll
|
|
11
|
+
const SCROLL_TRIGGER_MARGIN = 5;
|
|
12
|
+
|
|
10
13
|
/**
|
|
11
14
|
* Listen to clicks away from a given element and callback the passed in function.
|
|
12
15
|
*
|
|
@@ -14,14 +17,22 @@ type EventCallback = (evt?: Event) => void;
|
|
|
14
17
|
* @param [callback] A callback function to call when the bottom of the reference element is reached.
|
|
15
18
|
* @param [callbackOnMount] A callback function to call when the component is mounted.
|
|
16
19
|
*/
|
|
17
|
-
export const useInfiniteScroll: useInfiniteScrollType = (
|
|
20
|
+
export const useInfiniteScroll: useInfiniteScrollType = (
|
|
21
|
+
ref,
|
|
22
|
+
callback,
|
|
23
|
+
callbackOnMount = false,
|
|
24
|
+
scrollTriggerMargin = SCROLL_TRIGGER_MARGIN,
|
|
25
|
+
) => {
|
|
18
26
|
useEffect(() => {
|
|
19
27
|
const { current } = ref;
|
|
20
28
|
if (!callback || !current) {
|
|
21
29
|
return undefined;
|
|
22
30
|
}
|
|
23
31
|
|
|
24
|
-
const isAtBottom = () =>
|
|
32
|
+
const isAtBottom = () =>
|
|
33
|
+
Boolean(
|
|
34
|
+
current && current.scrollHeight - (current.scrollTop + current.clientHeight) <= scrollTriggerMargin,
|
|
35
|
+
);
|
|
25
36
|
|
|
26
37
|
const onScroll = (e?: Event): void => {
|
|
27
38
|
if (isAtBottom()) {
|
|
@@ -39,7 +50,7 @@ export const useInfiniteScroll: useInfiniteScrollType = (ref, callback, callback
|
|
|
39
50
|
current.removeEventListener('scroll', onScroll);
|
|
40
51
|
current.removeEventListener('resize', onScroll);
|
|
41
52
|
};
|
|
42
|
-
}, [ref, callback]);
|
|
53
|
+
}, [ref, callback, scrollTriggerMargin]);
|
|
43
54
|
|
|
44
55
|
useEffect(() => {
|
|
45
56
|
if (callback && callbackOnMount) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RefObject, useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Listen on element focus to store the focus status.
|
|
5
|
+
*/
|
|
6
|
+
export function useListenFocus(ref: RefObject<HTMLElement>) {
|
|
7
|
+
const [isFocus, setFocus] = useState(false);
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const { current: element } = ref;
|
|
11
|
+
if (!element) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const onFocus = () => setFocus(true);
|
|
16
|
+
const onBlur = () => setFocus(false);
|
|
17
|
+
element.addEventListener('focus', onFocus);
|
|
18
|
+
element.addEventListener('blur', onBlur);
|
|
19
|
+
return () => {
|
|
20
|
+
element.removeEventListener('focus', onFocus);
|
|
21
|
+
element.removeEventListener('blur', onBlur);
|
|
22
|
+
};
|
|
23
|
+
}, [ref, setFocus]);
|
|
24
|
+
|
|
25
|
+
return isFocus;
|
|
26
|
+
}
|
|
@@ -1,42 +1,33 @@
|
|
|
1
|
-
import React, { createContext,
|
|
2
|
-
|
|
1
|
+
import React, { createContext, useContext, useEffect } from 'react';
|
|
2
|
+
import pull from 'lodash/pull';
|
|
3
3
|
import { ClickAwayParameters, useClickAway } from '@lumx/react/hooks/useClickAway';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
type appendChildrenRefsType = (refs: ClickAwayParameters['refs']) => void;
|
|
8
|
-
const ClickAwayAncestorContext = createContext<appendChildrenRefsType | null>(null);
|
|
5
|
+
const ClickAwayAncestorContext = createContext<ClickAwayParameters['refs'] | null>(null);
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
|
-
* Component combining the `useClickAway` hook with a React context to hook into the React
|
|
12
|
-
*
|
|
8
|
+
* Component combining the `useClickAway` hook with a React context to hook into the React component tree and make sure
|
|
9
|
+
* we take into account both the DOM tree and the React tree we trying to detect click away.
|
|
13
10
|
*
|
|
14
11
|
* @return the react component.
|
|
15
12
|
*/
|
|
16
13
|
export const ClickAwayProvider: React.FC<ClickAwayParameters> = ({ children, callback, refs }) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return concatenatedRefs;
|
|
37
|
-
}, [refs, childrenRefs, appendAncestorChildrenRefs]);
|
|
38
|
-
|
|
39
|
-
useClickAway({ callback, refs: clickAwayRefs });
|
|
40
|
-
return <ClickAwayAncestorContext.Provider value={appendChildrenRefs}>{children}</ClickAwayAncestorContext.Provider>;
|
|
14
|
+
const ancestorChildrenRefs = useContext(ClickAwayAncestorContext);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const { current: currentRefs } = refs;
|
|
18
|
+
const { current: currentAncestorChildrenRefs } = ancestorChildrenRefs || {};
|
|
19
|
+
if (!currentAncestorChildrenRefs || !currentRefs) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
// Push current refs to parent.
|
|
23
|
+
currentAncestorChildrenRefs.push(...currentRefs);
|
|
24
|
+
return () => {
|
|
25
|
+
// Pull current refs from parent.
|
|
26
|
+
pull(currentAncestorChildrenRefs, ...currentRefs);
|
|
27
|
+
};
|
|
28
|
+
}, [ancestorChildrenRefs, refs]);
|
|
29
|
+
|
|
30
|
+
useClickAway({ callback, refs });
|
|
31
|
+
return <ClickAwayAncestorContext.Provider value={refs}>{children}</ClickAwayAncestorContext.Provider>;
|
|
41
32
|
};
|
|
42
33
|
ClickAwayProvider.displayName = 'ClickAwayProvider';
|
package/types.d.ts
CHANGED
|
@@ -152,16 +152,16 @@ export interface AlertDialogProps extends Omit<DialogProps, "header" | "footer">
|
|
|
152
152
|
kind?: Kind;
|
|
153
153
|
/** Dialog title. */
|
|
154
154
|
title?: string;
|
|
155
|
-
/**
|
|
156
|
-
confirmProps: {
|
|
155
|
+
/** Props forwarded to the confirm button */
|
|
156
|
+
confirmProps: ButtonProps & {
|
|
157
157
|
onClick(): void;
|
|
158
158
|
label: string;
|
|
159
159
|
};
|
|
160
160
|
/**
|
|
161
|
-
*
|
|
161
|
+
* Props forwarded to the cancel button.
|
|
162
162
|
* Will not render a cancel button if undefined.
|
|
163
163
|
*/
|
|
164
|
-
cancelProps?: {
|
|
164
|
+
cancelProps?: ButtonProps & {
|
|
165
165
|
onClick(): void;
|
|
166
166
|
label: string;
|
|
167
167
|
};
|
|
@@ -240,6 +240,11 @@ export interface AutocompleteProps extends GenericProps {
|
|
|
240
240
|
* @see {@link TextFieldProps#isDisabled}
|
|
241
241
|
*/
|
|
242
242
|
isDisabled?: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* Whether the component is required or not.
|
|
245
|
+
* @see {@link TextFieldProps#isRequired}
|
|
246
|
+
*/
|
|
247
|
+
isRequired?: boolean;
|
|
243
248
|
/**
|
|
244
249
|
* Whether the text field is displayed with valid style or not.
|
|
245
250
|
* @see {@link TextFieldProps#isValid}
|
|
@@ -755,6 +760,8 @@ export interface DialogProps extends GenericProps {
|
|
|
755
760
|
dialogProps?: GenericProps;
|
|
756
761
|
/** On close callback. */
|
|
757
762
|
onClose?(): void;
|
|
763
|
+
/** Callback called when the open animation starts and the close animation finishes. */
|
|
764
|
+
onVisibilityChange?(isVisible: boolean): void;
|
|
758
765
|
}
|
|
759
766
|
export declare type DialogSizes = Extract<Size, "tiny" | "regular" | "big" | "huge">;
|
|
760
767
|
/**
|
|
@@ -1473,6 +1480,8 @@ export interface MessageProps extends GenericProps {
|
|
|
1473
1480
|
hasBackground?: boolean;
|
|
1474
1481
|
/** Message variant. */
|
|
1475
1482
|
kind?: Kind;
|
|
1483
|
+
/** Message custom icon SVG path. */
|
|
1484
|
+
icon?: string;
|
|
1476
1485
|
}
|
|
1477
1486
|
/**
|
|
1478
1487
|
* Message component.
|
|
@@ -2027,8 +2036,8 @@ export interface SlideshowControlsProps extends GenericProps {
|
|
|
2027
2036
|
activeIndex?: number;
|
|
2028
2037
|
/** Props to pass to the next button (minus those already set by the SlideshowControls props). */
|
|
2029
2038
|
nextButtonProps: Pick<IconButtonProps, "label"> & Omit<IconButtonProps, "label" | "onClick" | "icon" | "emphasis" | "color">;
|
|
2030
|
-
/** Reference to the parent element. */
|
|
2031
|
-
parentRef
|
|
2039
|
+
/** Reference to the parent element on which we want to listen touch swipe. */
|
|
2040
|
+
parentRef?: RefObject<HTMLDivElement> | HTMLDivElement;
|
|
2032
2041
|
/** Props to pass to the previous button (minus those already set by the SlideshowControls props). */
|
|
2033
2042
|
previousButtonProps: Pick<IconButtonProps, "label"> & Omit<IconButtonProps, "label" | "onClick" | "icon" | "emphasis" | "color">;
|
|
2034
2043
|
/** Number of slides. */
|
|
@@ -2036,11 +2045,11 @@ export interface SlideshowControlsProps extends GenericProps {
|
|
|
2036
2045
|
/** Theme adapting the component to light or dark background. */
|
|
2037
2046
|
theme?: Theme;
|
|
2038
2047
|
/** On next button click callback. */
|
|
2039
|
-
onNextClick?(): void;
|
|
2048
|
+
onNextClick?(loopback?: boolean): void;
|
|
2040
2049
|
/** On pagination change callback. */
|
|
2041
2050
|
onPaginationClick?(index: number): void;
|
|
2042
2051
|
/** On previous button click callback. */
|
|
2043
|
-
onPreviousClick?(): void;
|
|
2052
|
+
onPreviousClick?(loopback?: boolean): void;
|
|
2044
2053
|
}
|
|
2045
2054
|
/**
|
|
2046
2055
|
* SlideshowControls component.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
import { detectSwipe } from '@lumx/core/js/utils';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Listen keyboard and swipe to navigate left and right.
|
|
6
|
-
*/
|
|
7
|
-
export function useKeyOrSwipeNavigate(
|
|
8
|
-
element?: HTMLElement | null,
|
|
9
|
-
onNext?: () => void,
|
|
10
|
-
onPrevious?: () => void,
|
|
11
|
-
): void {
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
if (!element) return undefined;
|
|
14
|
-
|
|
15
|
-
const onNavigate = (evt: KeyboardEvent | string) => {
|
|
16
|
-
let callback;
|
|
17
|
-
if (typeof evt === 'string' ? evt === 'right' : evt?.key === 'ArrowRight') {
|
|
18
|
-
callback = onPrevious;
|
|
19
|
-
} else if (typeof evt === 'string' ? evt === 'left' : evt?.key === 'ArrowLeft') {
|
|
20
|
-
callback = onNext;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
callback?.();
|
|
24
|
-
if (callback && typeof evt !== 'string') {
|
|
25
|
-
evt.preventDefault();
|
|
26
|
-
evt.stopPropagation();
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
element.addEventListener('keydown', onNavigate);
|
|
31
|
-
const removeSwipeListeners = detectSwipe(element, onNavigate);
|
|
32
|
-
return () => {
|
|
33
|
-
element.removeEventListener('keydown', onNavigate);
|
|
34
|
-
removeSwipeListeners();
|
|
35
|
-
};
|
|
36
|
-
}, [onPrevious, onNext, element]);
|
|
37
|
-
}
|