@lumx/react 2.1.0 → 2.1.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/README.md +1 -1
- package/esm/_internal/Button2.js.map +1 -1
- package/esm/_internal/ButtonRoot.js +14 -4
- package/esm/_internal/ButtonRoot.js.map +1 -1
- package/esm/_internal/ClickAwayProvider.js +1 -1
- package/esm/_internal/Dialog2.js +13 -8
- package/esm/_internal/Dialog2.js.map +1 -1
- package/esm/_internal/Flag2.js +1 -3
- package/esm/_internal/Flag2.js.map +1 -1
- package/esm/_internal/IconButton.js +7 -6
- package/esm/_internal/IconButton.js.map +1 -1
- package/esm/_internal/List2.js +16 -9
- package/esm/_internal/List2.js.map +1 -1
- package/esm/_internal/Message2.js +2 -2
- package/esm/_internal/Message2.js.map +1 -1
- package/esm/_internal/SlideshowControls.js +3 -3
- package/esm/_internal/SlideshowControls.js.map +1 -1
- package/esm/_internal/TextField.js +5 -2
- package/esm/_internal/TextField.js.map +1 -1
- package/esm/_internal/Tooltip2.js +1 -1
- package/esm/_internal/getRootClassName.js +17 -1
- package/esm/_internal/getRootClassName.js.map +1 -1
- package/package.json +4 -4
- package/src/components/avatar/Avatar.stories.tsx +1 -1
- package/src/components/button/Button.stories.tsx +95 -10
- package/src/components/button/Button.tsx +2 -0
- package/src/components/button/ButtonRoot.test.tsx +13 -0
- package/src/components/button/ButtonRoot.tsx +10 -1
- package/src/components/button/IconButton.test.tsx +20 -1
- package/src/components/button/IconButton.tsx +20 -7
- package/src/components/button/__snapshots__/ButtonRoot.test.tsx.snap +13 -0
- package/src/components/button/__snapshots__/IconButton.test.tsx.snap +38 -0
- package/src/components/comment-block/CommentBlock.stories.tsx +1 -1
- package/src/components/dialog/Dialog.stories.tsx +45 -3
- package/src/components/dialog/Dialog.tsx +15 -11
- package/src/components/dialog/__snapshots__/Dialog.test.tsx.snap +76 -0
- package/src/components/flag/Flag.test.tsx +1 -2
- package/src/components/flag/Flag.tsx +2 -10
- package/src/components/flag/__snapshots__/Flag.test.tsx.snap +0 -15
- package/src/components/image-block/ImageBlock.stories.tsx +1 -1
- package/src/components/link-preview/LinkPreview.stories.tsx +1 -1
- package/src/components/list/List.stories.tsx +7 -1
- package/src/components/list/ListItem.stories.tsx +28 -3
- package/src/components/list/ListItem.tsx +25 -7
- package/src/components/list/__snapshots__/List.test.tsx.snap +23 -3
- package/src/components/list/__snapshots__/ListItem.test.tsx.snap +84 -11
- package/src/components/list/useInteractiveList.tsx +1 -1
- package/src/components/message/Message.tsx +2 -2
- package/src/components/skeleton/SkeletonRectangle.stories.tsx +1 -1
- package/src/components/slideshow/useKeyNavigate.ts +2 -2
- package/src/components/text-field/TextField.stories.tsx +97 -82
- package/src/components/text-field/TextField.tsx +5 -0
- package/src/components/thumbnail/Thumbnail.stories.tsx +1 -1
- package/src/components/user-block/UserBlock.stories.tsx +1 -1
- package/src/stories/generated/Button/Demos.stories.tsx +1 -0
- package/src/stories/knobs/buttonKnob.ts +9 -0
- package/src/stories/knobs/emphasisKnob.ts +8 -0
- package/src/utils/MaterialThemeSwitcher/MaterialThemeSwitcher.tsx +54 -0
- package/src/utils/MaterialThemeSwitcher/index.ts +1 -0
- package/types.d.ts +16 -5
- package/src/stories/knobs/index.ts +0 -2
|
@@ -1,18 +1,41 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`<ListItem> Snapshots and structure should render story '
|
|
3
|
+
exports[`<ListItem> Snapshots and structure should render story 'Button' 1`] = `
|
|
4
4
|
<li
|
|
5
5
|
className="lumx-list-item lumx-list-item--size-regular"
|
|
6
6
|
>
|
|
7
|
-
<
|
|
8
|
-
className="lumx-list-
|
|
7
|
+
<a
|
|
8
|
+
className="lumx-list-item__link"
|
|
9
|
+
onClick={[Function]}
|
|
10
|
+
onKeyDown={[Function]}
|
|
11
|
+
role="button"
|
|
12
|
+
tabIndex={0}
|
|
9
13
|
>
|
|
10
14
|
<div
|
|
11
15
|
className="lumx-list-item__content"
|
|
12
16
|
>
|
|
13
17
|
Text
|
|
14
18
|
</div>
|
|
15
|
-
</
|
|
19
|
+
</a>
|
|
20
|
+
</li>
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
exports[`<ListItem> Snapshots and structure should render story 'ButtonDisabled' 1`] = `
|
|
24
|
+
<li
|
|
25
|
+
className="lumx-list-item lumx-list-item--size-regular"
|
|
26
|
+
>
|
|
27
|
+
<a
|
|
28
|
+
aria-disabled={true}
|
|
29
|
+
className="lumx-list-item__link lumx-list-item__link--is-disabled"
|
|
30
|
+
onKeyDown={[Function]}
|
|
31
|
+
role="button"
|
|
32
|
+
>
|
|
33
|
+
<div
|
|
34
|
+
className="lumx-list-item__content"
|
|
35
|
+
>
|
|
36
|
+
Text
|
|
37
|
+
</div>
|
|
38
|
+
</a>
|
|
16
39
|
</li>
|
|
17
40
|
`;
|
|
18
41
|
|
|
@@ -23,7 +46,7 @@ exports[`<ListItem> Snapshots and structure should render story 'Highlighted' 1`
|
|
|
23
46
|
<a
|
|
24
47
|
className="lumx-list-item__link lumx-list-item__link--is-highlighted"
|
|
25
48
|
href="#"
|
|
26
|
-
|
|
49
|
+
role="link"
|
|
27
50
|
>
|
|
28
51
|
<div
|
|
29
52
|
className="lumx-list-item__content"
|
|
@@ -34,6 +57,58 @@ exports[`<ListItem> Snapshots and structure should render story 'Highlighted' 1`
|
|
|
34
57
|
</li>
|
|
35
58
|
`;
|
|
36
59
|
|
|
60
|
+
exports[`<ListItem> Snapshots and structure should render story 'Link' 1`] = `
|
|
61
|
+
<li
|
|
62
|
+
className="lumx-list-item lumx-list-item--size-regular"
|
|
63
|
+
>
|
|
64
|
+
<a
|
|
65
|
+
className="lumx-list-item__link"
|
|
66
|
+
href="#"
|
|
67
|
+
role="link"
|
|
68
|
+
>
|
|
69
|
+
<div
|
|
70
|
+
className="lumx-list-item__content"
|
|
71
|
+
>
|
|
72
|
+
Text
|
|
73
|
+
</div>
|
|
74
|
+
</a>
|
|
75
|
+
</li>
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
exports[`<ListItem> Snapshots and structure should render story 'LinkDisabled' 1`] = `
|
|
79
|
+
<li
|
|
80
|
+
className="lumx-list-item lumx-list-item--size-regular"
|
|
81
|
+
>
|
|
82
|
+
<a
|
|
83
|
+
aria-disabled={true}
|
|
84
|
+
className="lumx-list-item__link lumx-list-item__link--is-disabled"
|
|
85
|
+
role="link"
|
|
86
|
+
>
|
|
87
|
+
<div
|
|
88
|
+
className="lumx-list-item__content"
|
|
89
|
+
>
|
|
90
|
+
Text
|
|
91
|
+
</div>
|
|
92
|
+
</a>
|
|
93
|
+
</li>
|
|
94
|
+
`;
|
|
95
|
+
|
|
96
|
+
exports[`<ListItem> Snapshots and structure should render story 'NonClickable' 1`] = `
|
|
97
|
+
<li
|
|
98
|
+
className="lumx-list-item lumx-list-item--size-regular"
|
|
99
|
+
>
|
|
100
|
+
<div
|
|
101
|
+
className="lumx-list-item__wrapper"
|
|
102
|
+
>
|
|
103
|
+
<div
|
|
104
|
+
className="lumx-list-item__content"
|
|
105
|
+
>
|
|
106
|
+
Text
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</li>
|
|
110
|
+
`;
|
|
111
|
+
|
|
37
112
|
exports[`<ListItem> Snapshots and structure should render story 'Selected' 1`] = `
|
|
38
113
|
<li
|
|
39
114
|
className="lumx-list-item lumx-list-item--size-regular"
|
|
@@ -41,7 +116,7 @@ exports[`<ListItem> Snapshots and structure should render story 'Selected' 1`] =
|
|
|
41
116
|
<a
|
|
42
117
|
className="lumx-list-item__link lumx-list-item__link--is-selected"
|
|
43
118
|
href="#"
|
|
44
|
-
|
|
119
|
+
role="link"
|
|
45
120
|
>
|
|
46
121
|
<div
|
|
47
122
|
className="lumx-list-item__content"
|
|
@@ -72,16 +147,14 @@ exports[`<ListItem> Snapshots and structure should render story 'WithCustomLink'
|
|
|
72
147
|
<li
|
|
73
148
|
className="lumx-list-item lumx-list-item--size-regular"
|
|
74
149
|
>
|
|
75
|
-
<
|
|
76
|
-
className="lumx-list-
|
|
77
|
-
href="http://google.com"
|
|
78
|
-
tabIndex={0}
|
|
150
|
+
<div
|
|
151
|
+
className="lumx-list-item__wrapper"
|
|
79
152
|
>
|
|
80
153
|
<div
|
|
81
154
|
className="lumx-list-item__content"
|
|
82
155
|
>
|
|
83
156
|
My custom link
|
|
84
157
|
</div>
|
|
85
|
-
</
|
|
158
|
+
</div>
|
|
86
159
|
</li>
|
|
87
160
|
`;
|
|
@@ -75,7 +75,7 @@ function onKeyboardFocus(props: any, handler: (evt: FocusEvent) => void) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
const isNavigableItem = (node: ReactNode): node is ReactElement => {
|
|
78
|
-
return isComponent('ListItem')(node) && isClickable(node.props);
|
|
78
|
+
return isComponent('ListItem')(node) && isClickable(node.props) && !node.props.isDisabled;
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
/**
|
|
@@ -62,8 +62,8 @@ export const Message: Comp<MessageProps, HTMLDivElement> = forwardRef((props, re
|
|
|
62
62
|
)}
|
|
63
63
|
{...forwardedProps}
|
|
64
64
|
>
|
|
65
|
-
{(customIcon || icon) && <Icon className=
|
|
66
|
-
<div className=
|
|
65
|
+
{(customIcon || icon) && <Icon className={`${CLASSNAME}__icon`} icon={customIcon || icon} size={Size.xs} />}
|
|
66
|
+
<div className={`${CLASSNAME}__text`}>{children}</div>
|
|
67
67
|
</div>
|
|
68
68
|
);
|
|
69
69
|
});
|
|
@@ -9,9 +9,9 @@ export function useKeyNavigate(element?: HTMLElement | null, onNext?: () => void
|
|
|
9
9
|
const onKeyNavigate = (evt: KeyboardEvent) => {
|
|
10
10
|
let callback;
|
|
11
11
|
if (evt?.key === 'ArrowRight') {
|
|
12
|
-
callback = onPrevious;
|
|
13
|
-
} else if (evt?.key === 'ArrowLeft') {
|
|
14
12
|
callback = onNext;
|
|
13
|
+
} else if (evt?.key === 'ArrowLeft') {
|
|
14
|
+
callback = onPrevious;
|
|
15
15
|
}
|
|
16
16
|
if (!callback) return;
|
|
17
17
|
|
|
@@ -1,90 +1,87 @@
|
|
|
1
|
-
import { TextField } from '@lumx/react';
|
|
2
|
-
import { text } from '@storybook/addon-knobs';
|
|
3
|
-
import noop from 'lodash/noop';
|
|
4
1
|
import React from 'react';
|
|
2
|
+
import { mdiTranslate } from '@lumx/icons/';
|
|
3
|
+
import { Emphasis, IconButton, Size, TextField } from '@lumx/react';
|
|
4
|
+
import { boolean, number, text } from '@storybook/addon-knobs';
|
|
5
|
+
import { buttonSize } from '@lumx/react/stories/knobs/buttonKnob';
|
|
6
|
+
import { emphasis } from '@lumx/react/stories/knobs/emphasisKnob';
|
|
5
7
|
|
|
6
8
|
export default { title: 'LumX components/text-field/TextField' };
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
);
|
|
10
|
+
export const TextField_ = ({ theme }: any) => {
|
|
11
|
+
const [value, onChange] = React.useState('Value');
|
|
12
|
+
return (
|
|
13
|
+
<TextField
|
|
14
|
+
value={value}
|
|
15
|
+
onChange={onChange}
|
|
16
|
+
label={text('Label', 'Label')}
|
|
17
|
+
placeholder={text('Placeholder', 'Placeholder')}
|
|
18
|
+
theme={theme}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
21
22
|
|
|
22
|
-
export const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
export const Clearable = ({ theme }: any) => {
|
|
24
|
+
const [value, onChange] = React.useState('Value');
|
|
25
|
+
return (
|
|
26
|
+
<TextField
|
|
27
|
+
value={value}
|
|
28
|
+
onChange={onChange}
|
|
29
|
+
label={text('Label', 'Label')}
|
|
30
|
+
clearButtonProps={{ label: 'Clear' }}
|
|
31
|
+
theme={theme}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
32
35
|
|
|
33
|
-
export const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
export const States = ({ theme }: any) => {
|
|
37
|
+
const [value1, onChange1] = React.useState('Value');
|
|
38
|
+
const [value2, onChange2] = React.useState('Value');
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
<TextField
|
|
42
|
+
label="Has error"
|
|
43
|
+
hasError
|
|
44
|
+
error="Error message"
|
|
45
|
+
theme={theme}
|
|
46
|
+
value={value1}
|
|
47
|
+
onChange={onChange1}
|
|
48
|
+
/>
|
|
49
|
+
<TextField label="Is valid" isValid theme={theme} value={value2} onChange={onChange2} />
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
43
53
|
|
|
44
|
-
export const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
placeholder={text('Placeholder', 'ex: A value')}
|
|
49
|
-
theme={theme}
|
|
50
|
-
onChange={noop}
|
|
51
|
-
helper={<span>{text('Helper', 'ex: toto@acme.com')}</span>}
|
|
52
|
-
hasError
|
|
53
|
-
error={
|
|
54
|
-
<span>
|
|
55
|
-
You must provide <strong>something</strong>
|
|
56
|
-
</span>
|
|
57
|
-
}
|
|
58
|
-
/>
|
|
59
|
-
);
|
|
54
|
+
export const NumberField = ({ theme }: any) => {
|
|
55
|
+
const [value, onChange] = React.useState('0');
|
|
56
|
+
return <TextField value={value} onChange={onChange} label={text('Label', 'Label')} theme={theme} type="number" />;
|
|
57
|
+
};
|
|
60
58
|
|
|
61
|
-
export const
|
|
62
|
-
const [value,
|
|
59
|
+
export const WithHelper = ({ theme }: any) => {
|
|
60
|
+
const [value, onChange] = React.useState('Value');
|
|
63
61
|
return (
|
|
64
62
|
<TextField
|
|
65
63
|
value={value}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
minimumRows={1}
|
|
64
|
+
onChange={onChange}
|
|
65
|
+
label={text('Label', 'Label')}
|
|
66
|
+
placeholder={text('Placeholder', 'Placeholder')}
|
|
70
67
|
theme={theme}
|
|
71
|
-
|
|
72
|
-
helper={<span>{text('Helper', 'ex: toto@acme.com')}</span>}
|
|
68
|
+
helper={<span>{text('Helper', 'Helper')}</span>}
|
|
73
69
|
/>
|
|
74
70
|
);
|
|
75
71
|
};
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
|
|
73
|
+
export const TextArea = ({ theme }: any) => {
|
|
74
|
+
const [value, setValue] = React.useState('Value');
|
|
78
75
|
return (
|
|
79
76
|
<TextField
|
|
80
77
|
value={value}
|
|
81
|
-
label={text('Label', '
|
|
82
|
-
placeholder={text('Placeholder', '
|
|
78
|
+
label={text('Label', 'Label')}
|
|
79
|
+
placeholder={text('Placeholder', 'Placeholder')}
|
|
83
80
|
multiline
|
|
84
|
-
minimumRows={
|
|
81
|
+
minimumRows={number('Minimum number of rows', 1, { min: 0, max: 100 })}
|
|
85
82
|
theme={theme}
|
|
86
83
|
onChange={setValue}
|
|
87
|
-
helper={<span>{text('Helper', '
|
|
84
|
+
helper={<span>{text('Helper', 'Helper')}</span>}
|
|
88
85
|
/>
|
|
89
86
|
);
|
|
90
87
|
};
|
|
@@ -99,26 +96,44 @@ text`;
|
|
|
99
96
|
return (
|
|
100
97
|
<TextField
|
|
101
98
|
value={value}
|
|
102
|
-
label={text('Label', '
|
|
103
|
-
placeholder={text('Placeholder', '
|
|
99
|
+
label={text('Label', 'Label')}
|
|
100
|
+
placeholder={text('Placeholder', 'Placeholder')}
|
|
104
101
|
multiline
|
|
105
|
-
minimumRows={2}
|
|
102
|
+
minimumRows={number('Minimum number of rows', 2, { min: 0, max: 100 })}
|
|
106
103
|
theme={theme}
|
|
107
104
|
onChange={setValue}
|
|
108
|
-
helper={<span>{text('Helper', '
|
|
105
|
+
helper={<span>{text('Helper', 'Helper')}</span>}
|
|
109
106
|
/>
|
|
110
107
|
);
|
|
111
108
|
};
|
|
112
109
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
110
|
+
export const WithAfterElement = ({ theme }: any) => {
|
|
111
|
+
const [value, onChange] = React.useState('Value');
|
|
112
|
+
const multiline = boolean('Multiline', true);
|
|
113
|
+
const minimumRows = number('Minimum number of rows', 2, { min: 0, max: 100 });
|
|
114
|
+
const isClearable = boolean('Clearable', true);
|
|
115
|
+
const hasError = boolean('Has error', true);
|
|
116
|
+
return (
|
|
117
|
+
<TextField
|
|
118
|
+
value={value}
|
|
119
|
+
label={text('Label', 'Label')}
|
|
120
|
+
placeholder={text('Placeholder', 'Placeholder')}
|
|
121
|
+
theme={theme}
|
|
122
|
+
onChange={onChange}
|
|
123
|
+
multiline={multiline}
|
|
124
|
+
minimumRows={minimumRows}
|
|
125
|
+
hasError={hasError}
|
|
126
|
+
maxLength={200}
|
|
127
|
+
clearButtonProps={isClearable ? { label: 'Clear' } : undefined}
|
|
128
|
+
helper={<span>{text('Helper', 'Helper')}</span>}
|
|
129
|
+
afterElement={
|
|
130
|
+
<IconButton
|
|
131
|
+
label="foo"
|
|
132
|
+
emphasis={emphasis('Button emphasis', Emphasis.medium, 'After element')}
|
|
133
|
+
size={buttonSize('Button size', Size.s, 'After element')}
|
|
134
|
+
icon={mdiTranslate}
|
|
135
|
+
/>
|
|
136
|
+
}
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
@@ -24,6 +24,8 @@ export interface TextFieldProps extends GenericProps {
|
|
|
24
24
|
forceFocusStyle?: boolean;
|
|
25
25
|
/** Whether the text field is displayed with error style or not. */
|
|
26
26
|
hasError?: boolean;
|
|
27
|
+
/** Additional element to put at the end of the text field. */
|
|
28
|
+
afterElement?: ReactNode;
|
|
27
29
|
/** Helper text. */
|
|
28
30
|
helper?: string | ReactNode;
|
|
29
31
|
/** Icon (SVG path). */
|
|
@@ -259,6 +261,7 @@ export const TextField: Comp<TextFieldProps, HTMLDivElement> = forwardRef((props
|
|
|
259
261
|
theme,
|
|
260
262
|
type,
|
|
261
263
|
value,
|
|
264
|
+
afterElement,
|
|
262
265
|
...forwardedProps
|
|
263
266
|
} = props;
|
|
264
267
|
const textFieldId = useMemo(() => id || `text-field-${uid()}`, [id]);
|
|
@@ -405,6 +408,8 @@ export const TextField: Comp<TextFieldProps, HTMLDivElement> = forwardRef((props
|
|
|
405
408
|
type="button"
|
|
406
409
|
/>
|
|
407
410
|
)}
|
|
411
|
+
|
|
412
|
+
{afterElement && <div className={`${CLASSNAME}__after-element`}>{afterElement}</div>}
|
|
408
413
|
</div>
|
|
409
414
|
|
|
410
415
|
{hasError && error && (
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
Thumbnail,
|
|
13
13
|
ThumbnailVariant,
|
|
14
14
|
} from '@lumx/react';
|
|
15
|
-
import { imageKnob, IMAGES } from '@lumx/react/stories/knobs';
|
|
15
|
+
import { imageKnob, IMAGES } from '@lumx/react/stories/knobs/image';
|
|
16
16
|
import { htmlDecode } from '@lumx/react/utils/htmlDecode';
|
|
17
17
|
import { boolean, select, text } from '@storybook/addon-knobs';
|
|
18
18
|
import { enumKnob } from '@lumx/react/stories/knobs/enumKnob';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mdiStar } from '@lumx/icons';
|
|
2
2
|
import { Badge, ColorPalette, Icon, List, ListItem, Size } from '@lumx/react';
|
|
3
|
-
import { AVATAR_IMAGES, avatarImageKnob } from '@lumx/react/stories/knobs';
|
|
3
|
+
import { AVATAR_IMAGES, avatarImageKnob } from '@lumx/react/stories/knobs/image';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { UserBlock } from './UserBlock';
|
|
6
6
|
|
|
@@ -6,5 +6,6 @@ export default { title: 'LumX components/button/Demos' };
|
|
|
6
6
|
export { App as EmphasisHigh } from './emphasis-high';
|
|
7
7
|
export { App as EmphasisLow } from './emphasis-low';
|
|
8
8
|
export { App as EmphasisMedium } from './emphasis-medium';
|
|
9
|
+
export { App as FullWidth } from './full-width';
|
|
9
10
|
export { App as Small } from './small';
|
|
10
11
|
export { App as Toggle } from './toggle';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Button, ButtonProps, Size } from '@lumx/react';
|
|
2
|
+
import { select } from '@storybook/addon-knobs';
|
|
3
|
+
import { ButtonSize } from '@lumx/react/components/button/ButtonRoot';
|
|
4
|
+
|
|
5
|
+
export const buttonSize = (
|
|
6
|
+
name = 'Size',
|
|
7
|
+
value: ButtonSize = Button.defaultProps?.size as any,
|
|
8
|
+
groupId: string | undefined = undefined,
|
|
9
|
+
): ButtonProps['size'] => select(name, [Size.m, Size.s], value, groupId);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Emphasis } from '@lumx/react';
|
|
2
|
+
import { select } from '@storybook/addon-knobs';
|
|
3
|
+
|
|
4
|
+
export const emphasis = (
|
|
5
|
+
name = 'Emphasis',
|
|
6
|
+
value: Emphasis = Emphasis.high,
|
|
7
|
+
groupId: string | undefined = undefined,
|
|
8
|
+
): Emphasis => select(name, Emphasis, value, groupId);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { Switch } from '@lumx/react/components/switch';
|
|
3
|
+
import { Alignment } from '@lumx/react';
|
|
4
|
+
|
|
5
|
+
// Global state used to
|
|
6
|
+
const globalState = {
|
|
7
|
+
isEnabled: false,
|
|
8
|
+
styleSheet: null as any,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Toggle apply the material CSS override. */
|
|
12
|
+
async function toggleMaterialTheme(wasEnabled: boolean) {
|
|
13
|
+
globalState.isEnabled = !wasEnabled;
|
|
14
|
+
|
|
15
|
+
// Inject the material theme CSS file.
|
|
16
|
+
if (!globalState.styleSheet) {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
const cssCode = await import('!!raw-loader!@lumx/core/css/material.css');
|
|
20
|
+
|
|
21
|
+
// Inject CSS override in a <style> node in <head>
|
|
22
|
+
const style = document.createElement('style');
|
|
23
|
+
style.textContent = cssCode.default;
|
|
24
|
+
document.head.appendChild(style);
|
|
25
|
+
|
|
26
|
+
globalState.styleSheet = style.sheet;
|
|
27
|
+
}
|
|
28
|
+
// Disable/Enable stylesheet
|
|
29
|
+
globalState.styleSheet.disabled = !globalState.isEnabled;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const MaterialThemeSwitcher: React.FC<any> = ({ theme }) => {
|
|
33
|
+
const [isEnabled, setEnabled] = useState(globalState.isEnabled);
|
|
34
|
+
const toggleTheme = useCallback(
|
|
35
|
+
() =>
|
|
36
|
+
setEnabled((wasEnabled) => {
|
|
37
|
+
toggleMaterialTheme(wasEnabled);
|
|
38
|
+
return !wasEnabled;
|
|
39
|
+
}),
|
|
40
|
+
[],
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Switch
|
|
45
|
+
className="material-theme-switcher"
|
|
46
|
+
isChecked={isEnabled}
|
|
47
|
+
onChange={toggleTheme}
|
|
48
|
+
position={Alignment.right}
|
|
49
|
+
theme={theme}
|
|
50
|
+
>
|
|
51
|
+
Material theme
|
|
52
|
+
</Switch>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './MaterialThemeSwitcher';
|
package/types.d.ts
CHANGED
|
@@ -518,6 +518,8 @@ export interface ButtonProps extends BaseButtonProps {
|
|
|
518
518
|
leftIcon?: string;
|
|
519
519
|
/** Right icon (SVG path). */
|
|
520
520
|
rightIcon?: string;
|
|
521
|
+
/** When `true`, the button gets as large as possible. */
|
|
522
|
+
fullWidth?: boolean;
|
|
521
523
|
}
|
|
522
524
|
/**
|
|
523
525
|
* Button component.
|
|
@@ -527,12 +529,17 @@ export interface ButtonProps extends BaseButtonProps {
|
|
|
527
529
|
* @return React element.
|
|
528
530
|
*/
|
|
529
531
|
export declare const Button: Comp<ButtonProps, HTMLButtonElement | HTMLAnchorElement>;
|
|
530
|
-
/**
|
|
531
|
-
* Defines the props of the component.
|
|
532
|
-
*/
|
|
533
532
|
export interface IconButtonProps extends BaseButtonProps {
|
|
534
|
-
/**
|
|
535
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Icon (SVG path).
|
|
535
|
+
* If `image` is also set, `image` will be used instead.
|
|
536
|
+
*/
|
|
537
|
+
icon?: string;
|
|
538
|
+
/**
|
|
539
|
+
* Image (image url).
|
|
540
|
+
* Has priority over `icon`.
|
|
541
|
+
*/
|
|
542
|
+
image?: string;
|
|
536
543
|
/**
|
|
537
544
|
* Label text (required for a11y purpose).
|
|
538
545
|
* If you really don't want an aria-label, you can set an empty label (this is not recommended).
|
|
@@ -1480,6 +1487,8 @@ export interface ListItemProps extends GenericProps {
|
|
|
1480
1487
|
isHighlighted?: boolean;
|
|
1481
1488
|
/** Whether the component is selected or not. */
|
|
1482
1489
|
isSelected?: boolean;
|
|
1490
|
+
/** Whether link/button is disabled or not. */
|
|
1491
|
+
isDisabled?: boolean;
|
|
1483
1492
|
/** Reference to the <li> element. */
|
|
1484
1493
|
listItemRef?: Ref<HTMLLIElement>;
|
|
1485
1494
|
/** Custom react component for the link (can be used to inject react router Link). */
|
|
@@ -2369,6 +2378,8 @@ export interface TextFieldProps extends GenericProps {
|
|
|
2369
2378
|
forceFocusStyle?: boolean;
|
|
2370
2379
|
/** Whether the text field is displayed with error style or not. */
|
|
2371
2380
|
hasError?: boolean;
|
|
2381
|
+
/** Additional element to put at the end of the text field. */
|
|
2382
|
+
afterElement?: ReactNode;
|
|
2372
2383
|
/** Helper text. */
|
|
2373
2384
|
helper?: string | ReactNode;
|
|
2374
2385
|
/** Icon (SVG path). */
|