@lumx/react 3.1.5 → 3.2.1-alpha.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 +45 -4
- package/index.js +632 -423
- 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 +131 -293
- package/src/components/dialog/Dialog.test.tsx +0 -32
- 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/Popover.tsx +7 -9
- 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/select/SelectMultiple.stories.tsx +105 -2
- package/src/components/select/WithSelectContext.tsx +10 -4
- 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/hooks/useFocusTrap.ts +2 -2
- 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 -558
- 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 -1133
- 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,86 +1,62 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Dropdown,
|
|
6
|
-
FlexBox,
|
|
7
|
-
Icon,
|
|
8
|
-
IconButton,
|
|
9
|
-
Orientation,
|
|
10
|
-
Placement,
|
|
11
|
-
Size,
|
|
12
|
-
Switch,
|
|
13
|
-
Tooltip,
|
|
14
|
-
} from '@lumx/react';
|
|
15
|
-
import { select, text } from '@storybook/addon-knobs';
|
|
16
|
-
import noop from 'lodash/noop';
|
|
17
|
-
import range from 'lodash/range';
|
|
18
|
-
import React, { Fragment, useRef, useState } from 'react';
|
|
1
|
+
import { Button, Dialog, Dropdown, Placement, Tooltip } from '@lumx/react';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
4
|
+
import { withChromaticForceScreenSize } from '@lumx/react/stories/decorators/withChromaticForceScreenSize';
|
|
19
5
|
|
|
20
|
-
|
|
6
|
+
const placements = [Placement.TOP, Placement.BOTTOM, Placement.RIGHT, Placement.LEFT];
|
|
21
7
|
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<Button>Button</Button>
|
|
34
|
-
</Tooltip>
|
|
35
|
-
);
|
|
8
|
+
export default {
|
|
9
|
+
title: 'LumX components/tooltip/Tooltip',
|
|
10
|
+
component: Tooltip,
|
|
11
|
+
args: Tooltip.defaultProps,
|
|
12
|
+
argTypes: {
|
|
13
|
+
placement: getSelectArgType(placements),
|
|
14
|
+
},
|
|
15
|
+
decorators: [
|
|
16
|
+
// Force minimum chromatic screen size to make sure the dialog appears in view.
|
|
17
|
+
withChromaticForceScreenSize(),
|
|
18
|
+
],
|
|
36
19
|
};
|
|
37
20
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<Tooltip
|
|
46
|
-
label="A contextual help is help that is displayed in your product or web site"
|
|
47
|
-
placement={Placement.TOP}
|
|
48
|
-
forceOpen
|
|
49
|
-
>
|
|
50
|
-
<Icon icon={mdiHelp} size={Size.xxs} style={{ display: 'inline-block', verticalAlign: 'super' }} />
|
|
51
|
-
</Tooltip>
|
|
52
|
-
.
|
|
53
|
-
</div>
|
|
54
|
-
);
|
|
21
|
+
/** Simple tooltip on a button*/
|
|
22
|
+
export const OnAButton = {
|
|
23
|
+
args: {
|
|
24
|
+
label: 'Tooltip label',
|
|
25
|
+
children: <Button>Button</Button>,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
55
28
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
</
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</Tooltip>
|
|
64
|
-
</>
|
|
65
|
-
);
|
|
29
|
+
/** Simple tooltip on a button*/
|
|
30
|
+
export const OnADisabledButton = {
|
|
31
|
+
args: {
|
|
32
|
+
...OnAButton.args,
|
|
33
|
+
children: <Button isDisabled>Button</Button>,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
66
36
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
37
|
+
/** Forcing the tooltip to appear */
|
|
38
|
+
export const ForceOpen = {
|
|
39
|
+
args: {
|
|
40
|
+
...OnAButton.args,
|
|
41
|
+
forceOpen: true,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Display a multiline tooltip */
|
|
46
|
+
export const MultilineTooltip = {
|
|
47
|
+
args: {
|
|
48
|
+
...OnAButton.args,
|
|
49
|
+
label: 'First sentence.\nSecond sentence.\nThird sentence.\n',
|
|
50
|
+
},
|
|
51
|
+
};
|
|
77
52
|
|
|
78
|
-
|
|
53
|
+
/** Tooltip should hide when a dropdown opens */
|
|
54
|
+
export const TooltipWithDropdown = (props: any) => {
|
|
79
55
|
const [button, setButton] = useState<HTMLElement | null>(null);
|
|
80
56
|
const [isOpen, setOpen] = useState(false);
|
|
81
57
|
return (
|
|
82
58
|
<>
|
|
83
|
-
<Tooltip label={!isOpen && 'Tooltip'}
|
|
59
|
+
<Tooltip label={!isOpen && 'Tooltip'} {...props}>
|
|
84
60
|
<Button ref={setButton} onClick={() => setOpen((o) => !o)}>
|
|
85
61
|
Anchor
|
|
86
62
|
</Button>
|
|
@@ -92,66 +68,16 @@ export const TooltipWithDropdown = () => {
|
|
|
92
68
|
);
|
|
93
69
|
};
|
|
94
70
|
|
|
95
|
-
|
|
96
|
-
const [disabled, setDisabled] = useState(false);
|
|
97
|
-
|
|
98
|
-
return (
|
|
99
|
-
<>
|
|
100
|
-
<Switch isChecked={disabled} onChange={setDisabled}>
|
|
101
|
-
Toggle button disabled
|
|
102
|
-
</Switch>
|
|
103
|
-
<Tooltip label="Tooltip on disabled button">
|
|
104
|
-
<Button isDisabled={disabled} onClick={noop}>
|
|
105
|
-
Click to disable button
|
|
106
|
-
</Button>
|
|
107
|
-
</Tooltip>
|
|
108
|
-
</>
|
|
109
|
-
);
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export const TooltipOnDifferentComponents = () => {
|
|
113
|
-
return (
|
|
114
|
-
<FlexBox orientation={Orientation.horizontal} className="lumx-spacing-margin-top-huge">
|
|
115
|
-
<FlexBox fillSpace />
|
|
116
|
-
<FlexBox fillSpace>
|
|
117
|
-
<Tooltip forceOpen label="Tooltip on Button">
|
|
118
|
-
<Button>Button</Button>
|
|
119
|
-
</Tooltip>
|
|
120
|
-
</FlexBox>
|
|
121
|
-
<FlexBox fillSpace>
|
|
122
|
-
<IconButton icon={mdiPrinter} label="Tooltip on IconButton" tooltipProps={{ forceOpen: true }} />
|
|
123
|
-
</FlexBox>
|
|
124
|
-
<FlexBox fillSpace>
|
|
125
|
-
<Tooltip forceOpen label="Tooltip on Icon">
|
|
126
|
-
<Icon icon={mdiPrinter} style={{ display: 'inline-block' }} />
|
|
127
|
-
</Tooltip>
|
|
128
|
-
</FlexBox>
|
|
129
|
-
<FlexBox fillSpace>
|
|
130
|
-
<Tooltip forceOpen label="Tooltip on shaped Icon">
|
|
131
|
-
<Icon icon={mdiPrinter} hasShape />
|
|
132
|
-
</Tooltip>
|
|
133
|
-
</FlexBox>
|
|
134
|
-
<FlexBox fillSpace>
|
|
135
|
-
<Tooltip forceOpen label="Tooltip on word">
|
|
136
|
-
<span>word</span>
|
|
137
|
-
</Tooltip>
|
|
138
|
-
</FlexBox>
|
|
139
|
-
</FlexBox>
|
|
140
|
-
);
|
|
141
|
-
};
|
|
142
|
-
|
|
71
|
+
/** Tooltip should hide when the anchor is hidden */
|
|
143
72
|
export const HideTooltipOnHiddenAnchor = () => {
|
|
144
|
-
const anchorRef = useRef(null);
|
|
145
73
|
const [isOpen, setOpen] = useState(false);
|
|
146
74
|
return (
|
|
147
75
|
<>
|
|
148
|
-
The tooltip should show when the button is hovered but it should disappear when the
|
|
76
|
+
The tooltip should show when the button is hovered but it should disappear when the dialog get in-between
|
|
149
77
|
the mouse and the button
|
|
150
78
|
<br />
|
|
151
79
|
<Tooltip label="Tooltip label">
|
|
152
|
-
<Button
|
|
153
|
-
Open popover
|
|
154
|
-
</Button>
|
|
80
|
+
<Button onClick={() => setOpen((wasOpen) => !wasOpen)}>Open dialog</Button>
|
|
155
81
|
</Tooltip>
|
|
156
82
|
<Dialog isOpen={isOpen} onClose={() => setOpen(false)}>
|
|
157
83
|
Dialog
|
|
@@ -159,14 +85,3 @@ export const HideTooltipOnHiddenAnchor = () => {
|
|
|
159
85
|
</>
|
|
160
86
|
);
|
|
161
87
|
};
|
|
162
|
-
|
|
163
|
-
export const StressTest = () => {
|
|
164
|
-
return range(1000).map((i) => (
|
|
165
|
-
<Fragment key={i}>
|
|
166
|
-
<Tooltip label={`Label ${i}`}>
|
|
167
|
-
<Button>Button {i}</Button>
|
|
168
|
-
</Tooltip>
|
|
169
|
-
<br />
|
|
170
|
-
</Fragment>
|
|
171
|
-
));
|
|
172
|
-
};
|
|
@@ -1,76 +1,87 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import { mdiStar } from '@lumx/icons';
|
|
4
|
-
import { Badge, ColorPalette, Icon, Size } from '@lumx/react';
|
|
5
|
-
import { avatarImageKnob } from '@lumx/react/stories/knobs/image';
|
|
4
|
+
import { Badge, ColorPalette, Icon, Orientation, Size } from '@lumx/react';
|
|
6
5
|
import { CustomLink } from '@lumx/react/stories/utils/CustomLink';
|
|
7
6
|
|
|
7
|
+
import { AVATAR_IMAGES } from '@lumx/react/stories/controls/image';
|
|
8
|
+
import { withCombinations } from '@lumx/react/stories/decorators/withCombinations';
|
|
9
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
8
10
|
import { UserBlock } from './UserBlock';
|
|
9
11
|
|
|
10
|
-
export default { title: 'LumX components/user-block/UserBlock' };
|
|
11
|
-
|
|
12
|
-
const logAction = (action: string) => () => console.log(action);
|
|
13
12
|
const sizes = [Size.s, Size.m, Size.l];
|
|
14
13
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
export default {
|
|
15
|
+
title: 'LumX components/user-block/UserBlock',
|
|
16
|
+
component: UserBlock,
|
|
17
|
+
args: UserBlock.defaultProps,
|
|
18
|
+
argTypes: {
|
|
19
|
+
size: getSelectArgType(sizes),
|
|
20
|
+
orientation: getSelectArgType(Orientation),
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Only an avatar */
|
|
25
|
+
export const AvatarOnly = {
|
|
26
|
+
args: { avatarProps: { image: AVATAR_IMAGES.avatar1 } },
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Avatar and name */
|
|
30
|
+
export const AvatarAndName = {
|
|
31
|
+
args: { ...AvatarOnly.args, name: 'Emmitt O. Lum' },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** Avatar, name and secondary fields */
|
|
35
|
+
export const AvatarAndNameAndSecondaryFields = {
|
|
36
|
+
args: { ...AvatarAndName.args, fields: ['Creative developer', 'Denpasar'] },
|
|
37
|
+
};
|
|
25
38
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
));
|
|
39
|
+
/** Size variants */
|
|
40
|
+
export const SizesAndOrientations = {
|
|
41
|
+
...AvatarAndNameAndSecondaryFields,
|
|
42
|
+
decorators: [
|
|
43
|
+
withCombinations({
|
|
44
|
+
combinations: {
|
|
45
|
+
rows: { key: 'size', options: sizes },
|
|
46
|
+
cols: { key: 'orientation', options: Object.values(Orientation) },
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
],
|
|
50
|
+
};
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
fields: ['Creative developer', 'Denpasar'],
|
|
46
|
-
avatarProps: { image: avatarImageKnob() },
|
|
47
|
-
} as any;
|
|
48
|
-
return (
|
|
49
|
-
<>
|
|
50
|
-
<p>As a button</p>
|
|
51
|
-
<UserBlock {...baseProps} onClick={logAction('UserBlock clicked')} />
|
|
52
|
+
/** Setting `onClick` to use it as a button */
|
|
53
|
+
export const AsButton = {
|
|
54
|
+
...AvatarAndNameAndSecondaryFields,
|
|
55
|
+
argTypes: { onClick: { action: true } },
|
|
56
|
+
};
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
/** Setting the `linkProps` prop to use it as a link */
|
|
59
|
+
export const AsLink = {
|
|
60
|
+
args: {
|
|
61
|
+
...AvatarAndNameAndSecondaryFields.args,
|
|
62
|
+
linkProps: { href: 'https://example.com' },
|
|
63
|
+
},
|
|
64
|
+
};
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
/** Setting the `linkAs` prop to inject a custom link component */
|
|
67
|
+
export const AsCustomLink = {
|
|
68
|
+
args: {
|
|
69
|
+
...AvatarAndNameAndSecondaryFields.args,
|
|
70
|
+
linkAs: CustomLink,
|
|
71
|
+
},
|
|
60
72
|
};
|
|
61
73
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
image: avatarImageKnob(),
|
|
74
|
+
/** Setting the `avatarProps.badge` prop to inject a badge */
|
|
75
|
+
export const WithBadge = {
|
|
76
|
+
args: {
|
|
77
|
+
...AvatarAndNameAndSecondaryFields.args,
|
|
78
|
+
avatarProps: {
|
|
79
|
+
...AvatarAndNameAndSecondaryFields.args.avatarProps,
|
|
69
80
|
badge: (
|
|
70
81
|
<Badge color={ColorPalette.blue}>
|
|
71
82
|
<Icon icon={mdiStar} />
|
|
72
83
|
</Badge>
|
|
73
84
|
),
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
};
|
|
@@ -3,10 +3,8 @@ import React, { ReactElement } from 'react';
|
|
|
3
3
|
import { mount, shallow } from 'enzyme';
|
|
4
4
|
import 'jest-enzyme';
|
|
5
5
|
|
|
6
|
-
import { commonTestsSuite,
|
|
7
|
-
|
|
6
|
+
import { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
|
|
8
7
|
import { UserBlock, UserBlockProps } from './UserBlock';
|
|
9
|
-
import * as stories from './UserBlock.stories';
|
|
10
8
|
|
|
11
9
|
const CLASSNAME = UserBlock.className as string;
|
|
12
10
|
|
|
@@ -24,8 +22,6 @@ const setup = ({ ...propsOverride }: Partial<UserBlockProps> = {}, shallowRender
|
|
|
24
22
|
describe(`<${UserBlock.displayName}>`, () => {
|
|
25
23
|
// 1. Test render via snapshot.
|
|
26
24
|
describe('Snapshots and structure', () => {
|
|
27
|
-
itShouldRenderStories(stories, UserBlock);
|
|
28
|
-
|
|
29
25
|
it('should forward name props', () => {
|
|
30
26
|
const { wrapper } = setup({ name: 'John Doe', nameProps: { 'data-custom-attribute': true } });
|
|
31
27
|
|
|
@@ -72,10 +72,10 @@ export function useFocusTrap(focusZoneElement: HTMLElement | Falsy, focusElement
|
|
|
72
72
|
// SETUP:
|
|
73
73
|
if (focusElement && focusZoneElement.contains(focusElement)) {
|
|
74
74
|
// Focus the given element.
|
|
75
|
-
focusElement.focus();
|
|
75
|
+
focusElement.focus({ preventScroll: true });
|
|
76
76
|
} else {
|
|
77
77
|
// Focus the first focusable element in the zone.
|
|
78
|
-
getFirstAndLastFocusable(focusZoneElement).first?.focus();
|
|
78
|
+
getFirstAndLastFocusable(focusZoneElement).first?.focus({ preventScroll: true });
|
|
79
79
|
}
|
|
80
80
|
FOCUS_TRAPS.register(focusTrap);
|
|
81
81
|
|
package/src/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ export * from './components/link-preview';
|
|
|
34
34
|
export * from './components/list';
|
|
35
35
|
export * from './components/message';
|
|
36
36
|
export * from './components/mosaic';
|
|
37
|
+
export * from './components/navigation';
|
|
37
38
|
export * from './components/notification';
|
|
38
39
|
export * from './components/popover';
|
|
39
40
|
export * from './components/popover-dialog';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ColorPalette, ColorVariant } from '@lumx/react';
|
|
2
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
3
|
+
|
|
4
|
+
export const ALL_COLORS = Object.values(ColorPalette);
|
|
5
|
+
export const colorArgType = getSelectArgType(ALL_COLORS);
|
|
6
|
+
export const colorVariantArgType = getSelectArgType(ColorVariant);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
2
|
+
import { HeadingElement, TextElement } from '@lumx/react';
|
|
3
|
+
|
|
4
|
+
export const HEADING_ELEMENTS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as HeadingElement[];
|
|
5
|
+
export const headingElementArgType = getSelectArgType<HeadingElement>(HEADING_ELEMENTS);
|
|
6
|
+
export const textElementArgType = getSelectArgType<TextElement>(['p', 'span', ...HEADING_ELEMENTS]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const focusPoint = { control: { type: 'range', min: -1, max: 1, step: 0.01 } };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
2
2
|
|
|
3
3
|
const avatar1 = '/demo-assets/avatar1.jpg';
|
|
4
4
|
const avatar2 = '/demo-assets/avatar2.jpg';
|
|
@@ -19,23 +19,13 @@ export const AVATAR_IMAGES = { avatar1, avatar2, avatar3, avatar4 };
|
|
|
19
19
|
export const SQUARE_IMAGES = { square1, square2 };
|
|
20
20
|
export const LANDSCAPE_IMAGES = { landscape1, landscape1s200, landscape2, landscape3 };
|
|
21
21
|
export const PORTRAIT_IMAGES = { portrait1, portrait1s200, portrait2, portrait3 };
|
|
22
|
-
|
|
23
22
|
export const IMAGES = { ...LANDSCAPE_IMAGES, ...PORTRAIT_IMAGES, ...SQUARE_IMAGES, ...AVATAR_IMAGES };
|
|
24
23
|
|
|
25
|
-
export const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export const portraitImageKnob = (name = 'Image', value = Object.values(PORTRAIT_IMAGES)[0], groupId?: string) =>
|
|
32
|
-
select(name, PORTRAIT_IMAGES, value, groupId);
|
|
33
|
-
|
|
34
|
-
export const squareImageKnob = (name = 'Image', value = Object.values(SQUARE_IMAGES)[0], groupId?: string) =>
|
|
35
|
-
select(name, SQUARE_IMAGES, value, groupId);
|
|
36
|
-
|
|
37
|
-
export const imageKnob = (name = 'Image', value = Object.values(IMAGES)[0], groupId?: string) =>
|
|
38
|
-
select(name, IMAGES, value, groupId);
|
|
24
|
+
export const avatarImageArgType = getSelectArgType(AVATAR_IMAGES);
|
|
25
|
+
export const squareImageArgType = getSelectArgType(SQUARE_IMAGES);
|
|
26
|
+
export const landscapeImageArgType = getSelectArgType(LANDSCAPE_IMAGES);
|
|
27
|
+
export const portraitImageArgType = getSelectArgType(PORTRAIT_IMAGES);
|
|
28
|
+
export const imageArgType = getSelectArgType(IMAGES);
|
|
39
29
|
|
|
40
30
|
type Size = { width: number; height: number };
|
|
41
31
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
2
|
+
import { TypographyCustom, TypographyInterface } from '@lumx/react';
|
|
3
|
+
|
|
4
|
+
export const ALL_TYPOGRAPHY = [...Object.values(TypographyInterface), ...Object.values(TypographyCustom)];
|
|
5
|
+
export const allTypographyArgType = getSelectArgType(ALL_TYPOGRAPHY);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const withUndefined = <E>(options: Array<E> | Record<string, E>) => [undefined, ...Object.values(options)];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import isChromatic from 'chromatic/isChromatic';
|
|
3
|
+
|
|
4
|
+
/** Story decorator used to force a minimum screen size when running in chromatic */
|
|
5
|
+
export const withChromaticForceScreenSize = () => {
|
|
6
|
+
// eslint-disable-next-line react/display-name
|
|
7
|
+
return (story: any) => (isChromatic() ? <div style={{ minWidth: 1200, minHeight: 800 }}>{story()}</div> : story());
|
|
8
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* eslint-disable react/display-name,jsx-a11y/control-has-associated-label */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import isEmpty from 'lodash/isEmpty';
|
|
4
|
+
|
|
5
|
+
type PropCombination = Record<string, Record<string, unknown>>;
|
|
6
|
+
type PropArrayCombination = { key: string; options: Array<any> };
|
|
7
|
+
type Combination = PropArrayCombination | PropCombination;
|
|
8
|
+
|
|
9
|
+
const toProps = <E,>(arr: Array<E>, prop: string) =>
|
|
10
|
+
Object.fromEntries(arr.map((value) => [value || '', { [prop]: value }]));
|
|
11
|
+
|
|
12
|
+
const isArrayConfig = (c?: Combination): c is PropArrayCombination => !!c?.key;
|
|
13
|
+
|
|
14
|
+
function formatProps(config?: Combination): PropCombination {
|
|
15
|
+
if (isEmpty(config)) return { '': {} };
|
|
16
|
+
if (isArrayConfig(config)) return toProps(config.options, config.key);
|
|
17
|
+
return config as PropCombination;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* SB decorator generating a tables of combination of props (max 3 levels of props)
|
|
22
|
+
*/
|
|
23
|
+
export const withCombinations = ({
|
|
24
|
+
combinations,
|
|
25
|
+
tableStyle,
|
|
26
|
+
firstColStyle,
|
|
27
|
+
cellStyle,
|
|
28
|
+
combinator = Object.assign,
|
|
29
|
+
}: {
|
|
30
|
+
/** Props combinations */
|
|
31
|
+
combinations: {
|
|
32
|
+
rows?: Combination;
|
|
33
|
+
cols?: Combination;
|
|
34
|
+
sections?: Combination;
|
|
35
|
+
};
|
|
36
|
+
/** Inject style on table */
|
|
37
|
+
tableStyle?: React.CSSProperties;
|
|
38
|
+
/** Inject style on first col */
|
|
39
|
+
firstColStyle?: React.CSSProperties;
|
|
40
|
+
/** Inject style on cells */
|
|
41
|
+
cellStyle?: React.CSSProperties;
|
|
42
|
+
/** Combinator function */
|
|
43
|
+
combinator?: (a: any, b: any) => any;
|
|
44
|
+
}) => (Story: any, ctx: any) => {
|
|
45
|
+
const rows = formatProps(combinations.rows);
|
|
46
|
+
const cols = formatProps(combinations.cols);
|
|
47
|
+
const sections = formatProps(combinations.sections);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
{Object.entries(sections).map(([level2Key, level2Value]) => (
|
|
52
|
+
<div key={level2Key}>
|
|
53
|
+
{level2Key && <h2>{level2Key}</h2>}
|
|
54
|
+
|
|
55
|
+
<table style={{ ...tableStyle, borderCollapse: 'separate', borderSpacing: 8 }}>
|
|
56
|
+
{combinations.cols && (
|
|
57
|
+
<thead>
|
|
58
|
+
<tr>
|
|
59
|
+
<th />
|
|
60
|
+
{Object.keys(cols).map((key) => (
|
|
61
|
+
<th key={key}>
|
|
62
|
+
<small>{key}</small>
|
|
63
|
+
</th>
|
|
64
|
+
))}
|
|
65
|
+
</tr>
|
|
66
|
+
</thead>
|
|
67
|
+
)}
|
|
68
|
+
<tbody>
|
|
69
|
+
{Object.entries(rows).map(([level0Key, level0Value], i1) => (
|
|
70
|
+
<tr key={i1}>
|
|
71
|
+
<th style={{ ...firstColStyle, textAlign: 'left' }}>
|
|
72
|
+
<small>{level0Key}</small>
|
|
73
|
+
</th>
|
|
74
|
+
{Object.entries(cols).map(([level1Key, level1Value]) => {
|
|
75
|
+
const args = [level0Value, level1Value, level2Value].reduce(
|
|
76
|
+
(acc, value) => combinator(acc, value),
|
|
77
|
+
{ ...ctx.args },
|
|
78
|
+
);
|
|
79
|
+
return (
|
|
80
|
+
<td
|
|
81
|
+
key={level1Key}
|
|
82
|
+
style={{
|
|
83
|
+
textAlign: combinations.cols ? 'center' : undefined,
|
|
84
|
+
...cellStyle,
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<Story args={args} />
|
|
88
|
+
</td>
|
|
89
|
+
);
|
|
90
|
+
})}
|
|
91
|
+
</tr>
|
|
92
|
+
))}
|
|
93
|
+
</tbody>
|
|
94
|
+
</table>
|
|
95
|
+
</div>
|
|
96
|
+
))}
|
|
97
|
+
</>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import set from 'lodash/set';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Convert flattened props into nested props
|
|
6
|
+
*
|
|
7
|
+
* @example: toNestedProps({ 'foo.bar': 4 }) => { foo: { bar: 4 } }
|
|
8
|
+
*/
|
|
9
|
+
export function toNestedProps(flattenedProps: Record<string, any>): Record<string, any> {
|
|
10
|
+
const props = {};
|
|
11
|
+
for (const [key, value] of Object.entries(flattenedProps)) {
|
|
12
|
+
set(props, key, value);
|
|
13
|
+
}
|
|
14
|
+
return props;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* SB decorator converting args from flattened props to nested props
|
|
19
|
+
*/
|
|
20
|
+
export const withNestedProps = () => {
|
|
21
|
+
// eslint-disable-next-line react/display-name
|
|
22
|
+
return (Story: any, ctx: any) => <Story args={toNestedProps(ctx.args)} />;
|
|
23
|
+
};
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { withWrapper } from './withWrapper';
|
|
2
2
|
|
|
3
3
|
/** Storybook decorator wrapping story in a resizable box */
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
style={{
|
|
4
|
+
export const withResizableBox = ({ width = 150, height = 50 } = {}) =>
|
|
5
|
+
withWrapper({
|
|
6
|
+
style: {
|
|
8
7
|
display: 'flex',
|
|
9
8
|
width,
|
|
10
9
|
height,
|
|
11
10
|
border: '1px solid red',
|
|
12
11
|
resize: 'both',
|
|
13
12
|
overflow: 'hidden',
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
<Story />
|
|
17
|
-
</div>
|
|
18
|
-
);
|
|
13
|
+
},
|
|
14
|
+
});
|