@lumx/react 3.1.4 → 3.2.0
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/_internal/types.d.ts +16 -5
- package/index.d.ts +51 -4
- package/index.js +621 -417
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/alert-dialog/AlertDialog.stories.tsx +96 -165
- package/src/components/alert-dialog/AlertDialog.test.tsx +15 -23
- package/src/components/avatar/Avatar.stories.tsx +91 -62
- package/src/components/avatar/Avatar.test.tsx +9 -24
- package/src/components/badge/Badge.stories.tsx +63 -38
- package/src/components/button/Button.stories.tsx +147 -139
- package/src/components/button/IconButton.stories.tsx +45 -0
- package/src/components/checkbox/Checkbox.stories.tsx +37 -30
- package/src/components/chip/Chip.stories.tsx +77 -15
- package/src/components/comment-block/CommentBlock.stories.tsx +90 -25
- package/src/components/comment-block/CommentBlock.test.tsx +12 -17
- package/src/components/date-picker/DatePickerField.stories.tsx +52 -83
- package/src/components/dialog/Dialog.stories.tsx +132 -240
- package/src/components/dialog/Dialog.test.tsx +6 -30
- package/src/components/dialog/Dialog.tsx +17 -3
- package/src/components/dropdown/Dropdown.stories.tsx +1 -186
- package/src/components/flag/Flag.stories.tsx +33 -18
- package/src/components/flag/Flag.test.tsx +1 -8
- package/src/components/flex-box/FlexBox.stories.tsx +151 -238
- package/src/components/flex-box/FlexBox.test.tsx +9 -49
- package/src/components/generic-block/GenericBlock.stories.jsx +1 -1
- package/src/components/grid-column/GridColumn.stories.tsx +46 -0
- package/src/components/heading/Heading.stories.tsx +57 -95
- package/src/components/icon/Icon.stories.tsx +67 -70
- package/src/components/image-block/ImageBlock.stories.tsx +103 -47
- package/src/components/image-block/ImageBlock.test.tsx +12 -17
- package/src/components/inline-list/InlineList.stories.tsx +45 -29
- package/src/components/input-helper/InputHelper.stories.tsx +31 -25
- package/src/components/input-label/InputLabel.stories.tsx +33 -10
- package/src/components/lightbox/Lightbox.stories.tsx +39 -77
- package/src/components/lightbox/Lightbox.test.tsx +12 -17
- package/src/components/link/Link.stories.tsx +98 -128
- package/src/components/link-preview/LinkPreview.stories.tsx +48 -75
- package/src/components/list/List.stories.tsx +59 -84
- package/src/components/list/List.test.tsx +8 -17
- package/src/components/list/ListDivider.stories.tsx +9 -4
- package/src/components/list/ListDivider.test.tsx +12 -17
- package/src/components/list/ListItem.stories.tsx +97 -59
- package/src/components/list/ListItem.test.tsx +12 -17
- package/src/components/list/ListSubheader.stories.tsx +8 -5
- package/src/components/list/ListSubheader.test.tsx +12 -18
- package/src/components/message/Message.stories.tsx +51 -22
- package/src/components/mosaic/Mosaic.stories.tsx +78 -74
- package/src/components/mosaic/Mosaic.test.tsx +0 -31
- package/src/components/navigation/Navigation.stories.tsx +67 -0
- package/src/components/navigation/Navigation.test.tsx +58 -0
- package/src/components/navigation/Navigation.tsx +62 -0
- package/src/components/navigation/NavigationItem.test.tsx +37 -0
- package/src/components/navigation/NavigationItem.tsx +89 -0
- package/src/components/navigation/NavigationSection.test.tsx +126 -0
- package/src/components/navigation/NavigationSection.tsx +109 -0
- package/src/components/navigation/context.tsx +6 -0
- package/src/components/navigation/index.ts +1 -0
- package/src/components/notification/Notifications.stories.tsx +52 -47
- package/src/components/popover/Popover.stories.tsx +68 -201
- package/src/components/popover-dialog/PopoverDialog.stories.tsx +26 -65
- package/src/components/post-block/PostBlock.test.tsx +12 -17
- package/src/components/progress/ProgressCircular.stories.tsx +24 -12
- package/src/components/progress/ProgressLinear.stories.tsx +6 -2
- package/src/components/radio-button/RadioButton.stories.tsx +35 -24
- package/src/components/select/Select.stories.tsx +19 -23
- package/src/components/skeleton/SkeletonCircle.stories.tsx +37 -21
- package/src/components/skeleton/SkeletonCircle.test.tsx +12 -17
- package/src/components/skeleton/SkeletonRectangle.stories.tsx +74 -99
- package/src/components/skeleton/SkeletonRectangle.test.tsx +12 -17
- package/src/components/skeleton/SkeletonTypography.test.tsx +12 -17
- package/src/components/slider/Slider.stories.tsx +41 -25
- package/src/components/slider/Slider.test.tsx +12 -18
- package/src/components/slideshow/Slideshow.stories.tsx +31 -61
- package/src/components/slideshow/Slideshow.test.tsx +15 -23
- package/src/components/slideshow/SlideshowControls.stories.tsx +4 -6
- package/src/components/switch/Switch.stories.tsx +35 -32
- package/src/components/table/Table.test.tsx +12 -17
- package/src/components/tabs/Tabs.stories.tsx +4 -3
- package/src/components/text/Text.stories.tsx +130 -0
- package/src/components/text-field/TextField.stories.tsx +114 -148
- package/src/components/thumbnail/Thumbnail.stories.tsx +106 -255
- package/src/components/thumbnail/Thumbnail.test.tsx +12 -35
- package/src/components/tooltip/Tooltip.stories.tsx +51 -136
- package/src/components/user-block/UserBlock.stories.tsx +67 -56
- package/src/components/user-block/UserBlock.test.tsx +1 -5
- package/src/index.ts +1 -0
- package/src/stories/controls/color.ts +6 -0
- package/src/stories/controls/element.ts +6 -0
- package/src/stories/controls/focusPoint.ts +1 -0
- package/src/stories/controls/icons.ts +6 -0
- package/src/stories/{knobs → controls}/image.ts +6 -16
- package/src/stories/controls/selectArgType.ts +4 -0
- package/src/stories/controls/theme.ts +3 -0
- package/src/stories/controls/typography.ts +5 -0
- package/src/stories/controls/withUndefined.ts +1 -0
- package/src/stories/decorators/withChromaticForceScreenSize.tsx +8 -0
- package/src/stories/decorators/withCombinations.tsx +99 -0
- package/src/stories/decorators/withNestedProps.tsx +23 -0
- package/src/stories/{withResizableBox.tsx → decorators/withResizableBox.tsx} +6 -10
- package/src/stories/decorators/withValueOnChange.tsx +18 -0
- package/src/stories/decorators/withWrapper.tsx +19 -0
- package/src/stories/utils/CustomLink.tsx +8 -2
- package/src/stories/{knobs → utils}/lorem.ts +9 -9
- package/src/testing/utils/commonTestsSuiteRTL.ts +2 -3
- package/src/testing/utils/index.ts +0 -2
- package/src/untypped-modules.d.ts +0 -2
- package/src/utils/MaterialThemeSwitcher/MaterialThemeSwitcher.tsx +1 -1
- package/src/utils/ThemeContext.ts +4 -0
- package/src/utils/forwardRefPolymorphic.ts +9 -0
- package/src/utils/type.ts +28 -4
- package/src/components/alert-dialog/__snapshots__/AlertDialog.test.tsx.snap +0 -551
- package/src/components/avatar/__snapshots__/Avatar.test.tsx.snap +0 -681
- package/src/components/comment-block/__snapshots__/CommentBlock.test.tsx.snap +0 -92
- package/src/components/dialog/__snapshots__/Dialog.test.tsx.snap +0 -960
- package/src/components/expansion-panel/ExpansionPanel.stories.tsx +0 -65
- package/src/components/flag/__snapshots__/Flag.test.tsx.snap +0 -133
- package/src/components/flex-box/__snapshots__/FlexBox.test.tsx.snap +0 -492
- package/src/components/grid-column/GridColumn.stories.jsx +0 -56
- package/src/components/image-block/__snapshots__/ImageBlock.test.tsx.snap +0 -64
- package/src/components/lightbox/__snapshots__/Lightbox.test.tsx.snap +0 -194
- package/src/components/list/__snapshots__/List.test.tsx.snap +0 -360
- package/src/components/list/__snapshots__/ListDivider.test.tsx.snap +0 -7
- package/src/components/list/__snapshots__/ListItem.test.tsx.snap +0 -160
- package/src/components/list/__snapshots__/ListSubheader.test.tsx.snap +0 -9
- package/src/components/mosaic/__snapshots__/Mosaic.test.tsx.snap +0 -357
- package/src/components/post-block/__snapshots__/PostBlock.test.tsx.snap +0 -139
- package/src/components/skeleton/__snapshots__/SkeletonCircle.test.tsx.snap +0 -54
- package/src/components/skeleton/__snapshots__/SkeletonRectangle.test.tsx.snap +0 -177
- package/src/components/skeleton/__snapshots__/SkeletonTypography.test.tsx.snap +0 -174
- package/src/components/slider/__snapshots__/Slider.test.tsx.snap +0 -122
- package/src/components/slideshow/__snapshots__/Slideshow.test.tsx.snap +0 -157
- package/src/components/table/__snapshots__/Table.test.tsx.snap +0 -263
- package/src/components/text/Text.stories.jsx +0 -75
- package/src/components/thumbnail/__snapshots__/Thumbnail.test.tsx.snap +0 -130
- package/src/components/user-block/__snapshots__/UserBlock.test.tsx.snap +0 -362
- package/src/stories/chromaticForceScreenSize.tsx +0 -7
- package/src/stories/knobs/buttonKnob.ts +0 -9
- package/src/stories/knobs/emphasisKnob.ts +0 -8
- package/src/stories/knobs/enumKnob.ts +0 -14
- package/src/stories/knobs/focusKnob.ts +0 -3
- package/src/stories/knobs/sizeKnob.ts +0 -5
- package/src/stories/knobs/thumbnailsKnob.ts +0 -9
- package/src/testing/utils/itShouldRenderStories.tsx +0 -103
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks,react/jsx-key */
|
|
2
|
+
import React, { useRef, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import over from 'lodash/over';
|
|
1
5
|
import { mdiClose } from '@lumx/icons';
|
|
2
6
|
import {
|
|
3
7
|
AlertDialog,
|
|
@@ -6,25 +10,28 @@ import {
|
|
|
6
10
|
DatePickerField,
|
|
7
11
|
Emphasis,
|
|
8
12
|
FlexBox,
|
|
13
|
+
Heading,
|
|
9
14
|
IconButton,
|
|
10
15
|
List,
|
|
11
16
|
ListItem,
|
|
12
17
|
Select,
|
|
13
18
|
Size,
|
|
14
19
|
TextField,
|
|
15
|
-
Theme,
|
|
16
20
|
Toolbar,
|
|
17
21
|
} from '@lumx/react';
|
|
18
22
|
import { DIALOG_TRANSITION_DURATION } from '@lumx/core/js/constants';
|
|
19
|
-
import { select } from '@storybook/addon-knobs';
|
|
20
|
-
import React, { RefObject, useCallback, useRef, useState } from 'react';
|
|
21
23
|
import { useBooleanState } from '@lumx/react/hooks/useBooleanState';
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
24
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
25
|
+
import { withChromaticForceScreenSize } from '@lumx/react/stories/decorators/withChromaticForceScreenSize';
|
|
26
|
+
|
|
27
|
+
import { Dialog } from './Dialog';
|
|
28
|
+
import { loremIpsum } from '../../stories/utils/lorem';
|
|
29
|
+
|
|
30
|
+
const dialogSizes = [Size.tiny, Size.regular, Size.big, Size.huge];
|
|
25
31
|
|
|
26
32
|
export default {
|
|
27
33
|
title: 'LumX components/dialog/Dialog',
|
|
34
|
+
component: Dialog,
|
|
28
35
|
parameters: {
|
|
29
36
|
// Delay Chromatic snapshot to wait for dialog to open.
|
|
30
37
|
chromatic: {
|
|
@@ -32,261 +39,148 @@ export default {
|
|
|
32
39
|
delay: DIALOG_TRANSITION_DURATION,
|
|
33
40
|
},
|
|
34
41
|
},
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
decorators: [
|
|
43
|
+
// Force minimum chromatic screen size to make sure the dialog appears in view.
|
|
44
|
+
withChromaticForceScreenSize(),
|
|
45
|
+
],
|
|
46
|
+
args: Dialog.defaultProps,
|
|
47
|
+
argTypes: {
|
|
48
|
+
size: getSelectArgType(dialogSizes),
|
|
49
|
+
onVisibilityChange: { action: true },
|
|
50
|
+
children: { control: false },
|
|
51
|
+
},
|
|
52
|
+
render(props: any) {
|
|
53
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
54
|
+
const [isOpen, close, open] = useBooleanState(true);
|
|
55
|
+
return (
|
|
56
|
+
<>
|
|
57
|
+
<Button ref={buttonRef} onClick={open}>
|
|
58
|
+
Open dialog
|
|
59
|
+
</Button>
|
|
60
|
+
<Dialog {...props} isOpen={isOpen} onClose={close} parentElement={buttonRef} />
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
},
|
|
37
64
|
};
|
|
38
65
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
function useOpenButton(theme: Theme, defaultState = true) {
|
|
45
|
-
const buttonRef = useRef() as RefObject<HTMLButtonElement>;
|
|
46
|
-
const [isOpen, setOpen] = useState(defaultState);
|
|
47
|
-
const openDialog = useCallback(() => setOpen(true), []);
|
|
48
|
-
const closeDialog = useCallback(() => setOpen(false), []);
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
button: (
|
|
52
|
-
<Button ref={buttonRef} onClick={openDialog} theme={theme}>
|
|
53
|
-
Open dialog
|
|
54
|
-
</Button>
|
|
55
|
-
),
|
|
56
|
-
buttonRef,
|
|
57
|
-
openDialog,
|
|
58
|
-
closeDialog,
|
|
59
|
-
isOpen,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export const SimpleDialog = ({ theme }: any) => {
|
|
64
|
-
const { button, buttonRef, closeDialog, isOpen } = useOpenButton(theme);
|
|
65
|
-
return (
|
|
66
|
-
<>
|
|
67
|
-
{button}
|
|
68
|
-
<Dialog isOpen={isOpen} onClose={closeDialog} parentElement={buttonRef}>
|
|
69
|
-
{content}
|
|
70
|
-
</Dialog>
|
|
71
|
-
</>
|
|
72
|
-
);
|
|
66
|
+
/**
|
|
67
|
+
* Default dialog
|
|
68
|
+
*/
|
|
69
|
+
export const Default = {
|
|
70
|
+
args: { children: loremIpsum('short') },
|
|
73
71
|
};
|
|
74
72
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<Dialog preventAutoClose isOpen={isOpen} onClose={closeDialog} parentElement={buttonRef}>
|
|
81
|
-
{content}
|
|
82
|
-
<footer>
|
|
83
|
-
<Toolbar
|
|
84
|
-
after={
|
|
85
|
-
<Button onClick={closeDialog} emphasis={Emphasis.low}>
|
|
86
|
-
Close
|
|
87
|
-
</Button>
|
|
88
|
-
}
|
|
89
|
-
/>
|
|
90
|
-
</footer>
|
|
91
|
-
</Dialog>
|
|
92
|
-
</>
|
|
93
|
-
);
|
|
73
|
+
/**
|
|
74
|
+
* Loading state
|
|
75
|
+
*/
|
|
76
|
+
export const Loading = {
|
|
77
|
+
args: { ...Default.args, isLoading: true },
|
|
94
78
|
};
|
|
95
79
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const handleSubmitDialog = () => {
|
|
104
|
-
closeDialog();
|
|
105
|
-
openAlertDialog();
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<>
|
|
110
|
-
{button}
|
|
111
|
-
<Dialog isOpen={isOpen} onClose={closeDialog} parentElement={buttonRef}>
|
|
112
|
-
{content}
|
|
113
|
-
<footer>
|
|
114
|
-
<Toolbar
|
|
115
|
-
after={
|
|
116
|
-
<Button onClick={handleSubmitDialog} emphasis={Emphasis.low}>
|
|
117
|
-
Close
|
|
118
|
-
</Button>
|
|
119
|
-
}
|
|
120
|
-
/>
|
|
121
|
-
</footer>
|
|
122
|
-
</Dialog>
|
|
123
|
-
<AlertDialog
|
|
124
|
-
isOpen={isAlertDialogOpen}
|
|
125
|
-
onClose={closeDialog}
|
|
126
|
-
parentElement={buttonRef}
|
|
127
|
-
title="Default (info)"
|
|
128
|
-
confirmProps={{ onClick: closeAlertDialog, label: 'Confirm' }}
|
|
129
|
-
>
|
|
130
|
-
Consequat deserunt officia aute laborum tempor anim sint est.
|
|
131
|
-
</AlertDialog>
|
|
132
|
-
</>
|
|
133
|
-
);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export const Sizes = ({ theme }: any) => {
|
|
137
|
-
const { button, buttonRef, closeDialog, isOpen } = useOpenButton(theme);
|
|
138
|
-
const sizes: DialogSizes[] = [Size.tiny, Size.regular, Size.big, Size.huge];
|
|
139
|
-
return (
|
|
140
|
-
<>
|
|
141
|
-
{button}
|
|
142
|
-
Use the knobs to change the dialog size!
|
|
143
|
-
<Dialog
|
|
144
|
-
isOpen={isOpen}
|
|
145
|
-
onClose={closeDialog}
|
|
146
|
-
size={select('Dialog size', sizes, Size.tiny)}
|
|
147
|
-
parentElement={buttonRef}
|
|
148
|
-
>
|
|
149
|
-
{longContent}
|
|
150
|
-
</Dialog>
|
|
151
|
-
</>
|
|
152
|
-
);
|
|
80
|
+
/**
|
|
81
|
+
* Basic header/footer props
|
|
82
|
+
*/
|
|
83
|
+
export const WithHeaderFooter = {
|
|
84
|
+
args: { ...Default.args, header: 'Dialog header', footer: 'Dialog footer' },
|
|
153
85
|
};
|
|
154
86
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
87
|
+
/**
|
|
88
|
+
* More complex header/footer in children
|
|
89
|
+
*/
|
|
90
|
+
export const WithHeaderFooterChildren = {
|
|
91
|
+
args: {
|
|
92
|
+
children: [
|
|
93
|
+
<header>
|
|
94
|
+
<Toolbar
|
|
95
|
+
label={<Heading typography="title">Dialog heading</Heading>}
|
|
96
|
+
after={<IconButton label="Close" emphasis="low" icon={mdiClose} />}
|
|
97
|
+
/>
|
|
98
|
+
</header>,
|
|
99
|
+
<div className="lumx-spacing-padding-huge">{loremIpsum('short')}</div>,
|
|
100
|
+
<footer>
|
|
101
|
+
<Toolbar after={<Button>Close</Button>} />
|
|
102
|
+
</footer>,
|
|
103
|
+
],
|
|
104
|
+
},
|
|
165
105
|
};
|
|
166
106
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
<Dialog
|
|
173
|
-
isOpen={isOpen}
|
|
174
|
-
onClose={closeDialog}
|
|
175
|
-
header="Header prop"
|
|
176
|
-
footer="Footer prop"
|
|
177
|
-
parentElement={buttonRef}
|
|
178
|
-
>
|
|
179
|
-
{content}
|
|
180
|
-
</Dialog>
|
|
181
|
-
</>
|
|
182
|
-
);
|
|
107
|
+
/**
|
|
108
|
+
* Forcing header/footer dividers
|
|
109
|
+
*/
|
|
110
|
+
export const ForceDivider = {
|
|
111
|
+
args: { ...WithHeaderFooter.args, forceFooterDivider: true, forceHeaderDivider: true },
|
|
183
112
|
};
|
|
184
113
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
<Dialog isOpen={isOpen} onClose={closeDialog} parentElement={buttonRef}>
|
|
191
|
-
{header}
|
|
192
|
-
{content}
|
|
193
|
-
{footer}
|
|
194
|
-
</Dialog>
|
|
195
|
-
</>
|
|
196
|
-
);
|
|
114
|
+
/**
|
|
115
|
+
* Long scrollable content
|
|
116
|
+
*/
|
|
117
|
+
export const LongContent = {
|
|
118
|
+
args: { ...WithHeaderFooter.args, children: loremIpsum('long') },
|
|
197
119
|
};
|
|
198
120
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
<Dialog
|
|
205
|
-
isOpen={isOpen}
|
|
206
|
-
onClose={closeDialog}
|
|
207
|
-
header=" Header prop"
|
|
208
|
-
footer=" Footer prop"
|
|
209
|
-
parentElement={buttonRef}
|
|
210
|
-
>
|
|
211
|
-
{header}
|
|
212
|
-
{content}
|
|
213
|
-
{footer}
|
|
214
|
-
</Dialog>
|
|
215
|
-
</>
|
|
216
|
-
);
|
|
121
|
+
/**
|
|
122
|
+
* Prevent auto close (click outside & close on escape)
|
|
123
|
+
*/
|
|
124
|
+
export const PreventAutoClose = {
|
|
125
|
+
args: { ...Default.args, preventAutoClose: true },
|
|
217
126
|
};
|
|
218
127
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
<Dialog
|
|
225
|
-
isOpen={isOpen}
|
|
226
|
-
onClose={closeDialog}
|
|
227
|
-
forceFooterDivider
|
|
228
|
-
forceHeaderDivider
|
|
229
|
-
parentElement={buttonRef}
|
|
230
|
-
>
|
|
231
|
-
{header}
|
|
232
|
-
{content}
|
|
233
|
-
{footer}
|
|
234
|
-
</Dialog>
|
|
235
|
-
</>
|
|
236
|
-
);
|
|
128
|
+
/**
|
|
129
|
+
* Prevent close on escape
|
|
130
|
+
*/
|
|
131
|
+
export const PreventCloseOnEscape = {
|
|
132
|
+
args: { ...Default.args, preventCloseOnEscape: true },
|
|
237
133
|
};
|
|
238
134
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
<Dialog isOpen={isOpen} onClose={closeDialog} size={Size.regular} parentElement={buttonRef}>
|
|
245
|
-
{longContent}
|
|
246
|
-
</Dialog>
|
|
247
|
-
</>
|
|
248
|
-
);
|
|
135
|
+
/**
|
|
136
|
+
* Prevent close on click outside
|
|
137
|
+
*/
|
|
138
|
+
export const PreventCloseOnClick = {
|
|
139
|
+
args: { ...Default.args, preventCloseOnClick: true },
|
|
249
140
|
};
|
|
250
141
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
{button}
|
|
260
|
-
<Dialog
|
|
261
|
-
isOpen={isOpen}
|
|
262
|
-
onClose={closeDialog}
|
|
263
|
-
size={Size.regular}
|
|
264
|
-
parentElement={buttonRef}
|
|
265
|
-
onVisibilityChange={handleVisibiltyCallback}
|
|
266
|
-
>
|
|
267
|
-
{content}
|
|
268
|
-
</Dialog>
|
|
269
|
-
</>
|
|
270
|
-
);
|
|
271
|
-
};
|
|
142
|
+
/**
|
|
143
|
+
* Dialog needing a confirmation before close using an AlertDialog
|
|
144
|
+
*/
|
|
145
|
+
export const WithConfirmClose = () => {
|
|
146
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
147
|
+
const closeButtonRef = useRef<HTMLButtonElement>(null);
|
|
148
|
+
const [isOpen, close, open] = useBooleanState(true);
|
|
149
|
+
const [isAlertDialogOpen, closeAlertDialog, openAlertDialog] = useBooleanState(false);
|
|
272
150
|
|
|
273
|
-
export const ScrollableDialogWithHeaderAndFooter = ({ theme }: any) => {
|
|
274
|
-
const { button, buttonRef, closeDialog, isOpen } = useOpenButton(theme);
|
|
275
151
|
return (
|
|
276
152
|
<>
|
|
277
|
-
{
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
153
|
+
<Button ref={buttonRef} onClick={open}>
|
|
154
|
+
Open dialog
|
|
155
|
+
</Button>
|
|
156
|
+
<Dialog isOpen={isOpen} onClose={openAlertDialog} parentElement={buttonRef}>
|
|
157
|
+
<FlexBox orientation="vertical" vAlign="center" className="lumx-spacing-padding-huge">
|
|
158
|
+
{loremIpsum('tiny')}
|
|
159
|
+
<Button ref={closeButtonRef} onClick={openAlertDialog}>
|
|
160
|
+
Close
|
|
161
|
+
</Button>
|
|
162
|
+
</FlexBox>
|
|
282
163
|
</Dialog>
|
|
164
|
+
<AlertDialog
|
|
165
|
+
isOpen={isAlertDialogOpen}
|
|
166
|
+
onClose={closeAlertDialog}
|
|
167
|
+
parentElement={closeButtonRef}
|
|
168
|
+
title="Confirm close"
|
|
169
|
+
confirmProps={{ onClick: over([close, closeAlertDialog]), label: 'Confirm' }}
|
|
170
|
+
cancelProps={{ onClick: closeAlertDialog, label: 'Cancel' }}
|
|
171
|
+
>
|
|
172
|
+
{loremIpsum('tiny')}
|
|
173
|
+
</AlertDialog>
|
|
283
174
|
</>
|
|
284
175
|
);
|
|
285
176
|
};
|
|
286
177
|
|
|
287
|
-
/**
|
|
288
|
-
|
|
289
|
-
|
|
178
|
+
/**
|
|
179
|
+
* Test dialog focus trap (focus is contained inside the dialog) with all kinds of focusable and non-focusable items
|
|
180
|
+
*/
|
|
181
|
+
export const FocusTrap = () => {
|
|
182
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
183
|
+
const [isOpen, close, open] = useBooleanState(true);
|
|
290
184
|
const [textValue, setTextValue] = useState('value');
|
|
291
185
|
const [checkboxValue, setCheckboxValue] = useState(false);
|
|
292
186
|
const inputRef = useRef(null);
|
|
@@ -308,14 +202,14 @@ export const DialogFocusTrap = ({ theme }: any) => {
|
|
|
308
202
|
|
|
309
203
|
return (
|
|
310
204
|
<>
|
|
311
|
-
{
|
|
312
|
-
|
|
205
|
+
<Button ref={buttonRef} onClick={open}>
|
|
206
|
+
Open dialog
|
|
207
|
+
</Button>
|
|
208
|
+
<Dialog isOpen={isOpen} onClose={close} parentElement={buttonRef} focusElement={inputRef}>
|
|
313
209
|
<header>
|
|
314
210
|
<Toolbar
|
|
315
211
|
label={<span className="lumx-typography-title">Dialog header</span>}
|
|
316
|
-
after={
|
|
317
|
-
<IconButton label="Close" icon={mdiClose} onClick={closeDialog} emphasis={Emphasis.low} />
|
|
318
|
-
}
|
|
212
|
+
after={<IconButton label="Close" icon={mdiClose} onClick={close} emphasis={Emphasis.low} />}
|
|
319
213
|
/>
|
|
320
214
|
</header>
|
|
321
215
|
<div className="lumx-spacing-padding-horizontal-huge lumx-spacing-padding-bottom-huge">
|
|
@@ -370,7 +264,6 @@ export const DialogFocusTrap = ({ theme }: any) => {
|
|
|
370
264
|
locale="fr"
|
|
371
265
|
label="Start date"
|
|
372
266
|
placeholder="Pick a date"
|
|
373
|
-
theme={theme}
|
|
374
267
|
onChange={setDate}
|
|
375
268
|
value={date}
|
|
376
269
|
nextButtonProps={{ label: 'Next month' }}
|
|
@@ -380,7 +273,6 @@ export const DialogFocusTrap = ({ theme }: any) => {
|
|
|
380
273
|
locale="fr"
|
|
381
274
|
label="Start date"
|
|
382
275
|
placeholder="Pick a date"
|
|
383
|
-
theme={theme}
|
|
384
276
|
onChange={setDate2}
|
|
385
277
|
value={date2}
|
|
386
278
|
nextButtonProps={{ label: 'Next month' }}
|
|
@@ -5,8 +5,6 @@ import { mount, shallow } from 'enzyme';
|
|
|
5
5
|
import 'jest-enzyme';
|
|
6
6
|
import React, { ReactElement } from 'react';
|
|
7
7
|
|
|
8
|
-
import * as stories from './Dialog.stories';
|
|
9
|
-
|
|
10
8
|
const CLASSNAME = Dialog.className as string;
|
|
11
9
|
|
|
12
10
|
// Mock out the useIntersectionObserver hook since it can't work with Jest/Enzyme.
|
|
@@ -29,26 +27,6 @@ const setup = (propsOverride: SetupProps = {}, shallowRendering = true) => {
|
|
|
29
27
|
};
|
|
30
28
|
|
|
31
29
|
describe(`<${Dialog.displayName}>`, () => {
|
|
32
|
-
// 1. Test render via snapshot.
|
|
33
|
-
describe('Snapshots and structure', () => {
|
|
34
|
-
// Do snapshot render test on every stories.
|
|
35
|
-
for (const [storyName, Story] of Object.entries(stories)) {
|
|
36
|
-
if (typeof Story !== 'function') {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
it(`should render story ${storyName}`, () => {
|
|
41
|
-
const wrapper = shallow(<Story />);
|
|
42
|
-
expect(wrapper).toMatchSnapshot();
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// 2. Test defaultProps value and important props custom values.
|
|
48
|
-
describe('Props', () => {
|
|
49
|
-
// Nothing to do here.
|
|
50
|
-
});
|
|
51
|
-
|
|
52
30
|
// 3. Test events.
|
|
53
31
|
describe('Events', () => {
|
|
54
32
|
const keyDown = (key: string) => new KeyboardEvent('keydown', { key } as any);
|
|
@@ -76,16 +54,14 @@ describe(`<${Dialog.displayName}>`, () => {
|
|
|
76
54
|
document.body.dispatchEvent(keyDown('Escape'));
|
|
77
55
|
expect(onClose).not.toHaveBeenCalled();
|
|
78
56
|
});
|
|
79
|
-
});
|
|
80
57
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
58
|
+
it('should not trigger `onClose` when pressing `escape` key with `preventCloseOnEscape` set to `true`', () => {
|
|
59
|
+
const onClose = jest.fn();
|
|
60
|
+
setup({ isOpen: true, onClose, preventCloseOnEscape: true }, false);
|
|
85
61
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
document.body.dispatchEvent(keyDown('Escape'));
|
|
63
|
+
expect(onClose).not.toHaveBeenCalled();
|
|
64
|
+
});
|
|
89
65
|
});
|
|
90
66
|
|
|
91
67
|
// Common tests suite.
|
|
@@ -43,6 +43,10 @@ export interface DialogProps extends GenericProps {
|
|
|
43
43
|
focusElement?: RefObject<HTMLElement>;
|
|
44
44
|
/** Whether to keep the dialog open on clickaway or escape press. */
|
|
45
45
|
preventAutoClose?: boolean;
|
|
46
|
+
/** Whether to keep the dialog open on escape press. */
|
|
47
|
+
preventCloseOnEscape?: boolean;
|
|
48
|
+
/** Whether to keep the dialog open on clickaway. */
|
|
49
|
+
preventCloseOnClick?: boolean;
|
|
46
50
|
/** Size variant. */
|
|
47
51
|
size?: DialogSizes;
|
|
48
52
|
/** Z-axis position. */
|
|
@@ -53,6 +57,8 @@ export interface DialogProps extends GenericProps {
|
|
|
53
57
|
onClose?(): void;
|
|
54
58
|
/** Callback called when the open animation starts and the close animation finishes. */
|
|
55
59
|
onVisibilityChange?(isVisible: boolean): void;
|
|
60
|
+
/** whether to disable the scroll on the body or not */
|
|
61
|
+
disableBodyScroll?: boolean;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
export type DialogSizes = Extract<Size, 'tiny' | 'regular' | 'big' | 'huge'>;
|
|
@@ -75,6 +81,7 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
|
75
81
|
*/
|
|
76
82
|
const DEFAULT_PROPS: Partial<DialogProps> = {
|
|
77
83
|
size: Size.big,
|
|
84
|
+
disableBodyScroll: true,
|
|
78
85
|
};
|
|
79
86
|
|
|
80
87
|
/**
|
|
@@ -108,6 +115,9 @@ export const Dialog: Comp<DialogProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
108
115
|
zIndex,
|
|
109
116
|
dialogProps,
|
|
110
117
|
onVisibilityChange,
|
|
118
|
+
disableBodyScroll,
|
|
119
|
+
preventCloseOnClick,
|
|
120
|
+
preventCloseOnEscape,
|
|
111
121
|
...forwardedProps
|
|
112
122
|
} = props;
|
|
113
123
|
|
|
@@ -125,8 +135,10 @@ export const Dialog: Comp<DialogProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
125
135
|
}
|
|
126
136
|
}, [isOpen, parentElement]);
|
|
127
137
|
|
|
138
|
+
const shouldPreventCloseOnEscape = preventAutoClose || preventCloseOnEscape;
|
|
139
|
+
|
|
128
140
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
129
|
-
useCallbackOnEscape(onClose, isOpen && !
|
|
141
|
+
useCallbackOnEscape(onClose, isOpen && !shouldPreventCloseOnEscape);
|
|
130
142
|
|
|
131
143
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
132
144
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
@@ -141,7 +153,7 @@ export const Dialog: Comp<DialogProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
141
153
|
useFocusTrap(isOpen && wrapperRef.current, focusElement?.current);
|
|
142
154
|
|
|
143
155
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
144
|
-
useDisableBodyScroll(isOpen && localContentRef.current);
|
|
156
|
+
useDisableBodyScroll(disableBodyScroll && isOpen && localContentRef.current);
|
|
145
157
|
|
|
146
158
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
147
159
|
const [sentinelTop, setSentinelTop] = useState<Element | null>(null);
|
|
@@ -175,6 +187,8 @@ export const Dialog: Comp<DialogProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
175
187
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
176
188
|
const isVisible = useTransitionVisibility(rootRef, Boolean(isOpen), onVisibilityChange);
|
|
177
189
|
|
|
190
|
+
const shouldPreventCloseOnClickAway = preventAutoClose || preventCloseOnClick;
|
|
191
|
+
|
|
178
192
|
return isOpen || isVisible
|
|
179
193
|
? createPortal(
|
|
180
194
|
<div
|
|
@@ -196,7 +210,7 @@ export const Dialog: Comp<DialogProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
196
210
|
|
|
197
211
|
<section className={`${CLASSNAME}__container`} role="dialog" aria-modal="true" {...dialogProps}>
|
|
198
212
|
<ClickAwayProvider
|
|
199
|
-
callback={!
|
|
213
|
+
callback={!shouldPreventCloseOnClickAway && onClose}
|
|
200
214
|
childrenRefs={clickAwayRefs}
|
|
201
215
|
parentRef={rootRef}
|
|
202
216
|
>
|