@via-profit/ui-kit 0.8.0 → 0.9.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/Autocomplete/AutocompleteContainer.d.ts +13 -0
- package/Autocomplete/AutocompleteContainer.js +46 -7
- package/Badge/BadgeBase.d.ts +10 -1
- package/Badge/BadgeBase.js +9 -2
- package/Badge/BadgeDot.d.ts +4 -0
- package/Badge/BadgeDot.js +20 -0
- package/Badge/BadgeStyled.js +67 -26
- package/Badge/index.d.ts +4 -4
- package/CHANGELOG.md +18 -0
- package/EmptyState/EmptyStateAction.d.ts +4 -0
- package/EmptyState/EmptyStateAction.js +16 -0
- package/EmptyState/EmptyStateContainer.d.ts +8 -0
- package/EmptyState/EmptyStateContainer.js +34 -0
- package/EmptyState/EmptyStateContent.d.ts +4 -0
- package/EmptyState/EmptyStateContent.js +15 -0
- package/EmptyState/EmptyStateIcon.d.ts +4 -0
- package/EmptyState/EmptyStateIcon.js +38 -0
- package/EmptyState/EmptyStateTitle.d.ts +4 -0
- package/EmptyState/EmptyStateTitle.js +13 -0
- package/EmptyState/index.d.ts +82 -0
- package/EmptyState/index.js +61 -0
- package/FileDropzone/FileDropzoneArea.d.ts +24 -0
- package/FileDropzone/FileDropzoneArea.js +81 -0
- package/FileDropzone/index.d.ts +107 -0
- package/FileDropzone/index.js +169 -0
- package/FileDropzone/utils.d.ts +9 -0
- package/FileDropzone/utils.js +42 -0
- package/HintPopover/HintPopoverButton.d.ts +4 -0
- package/HintPopover/HintPopoverButton.js +67 -0
- package/HintPopover/HintPopoverContainer.d.ts +4 -0
- package/HintPopover/HintPopoverContainer.js +52 -0
- package/HintPopover/index.d.ts +67 -0
- package/HintPopover/index.js +71 -0
- package/InfoNote/InfoNoteContainer.d.ts +14 -0
- package/InfoNote/InfoNoteContainer.js +56 -0
- package/InfoNote/InfoNoteContent.d.ts +4 -0
- package/InfoNote/InfoNoteContent.js +16 -0
- package/InfoNote/InfoNoteIcon.d.ts +9 -0
- package/InfoNote/InfoNoteIcon.js +47 -0
- package/InfoNote/InfoNoteTitle.d.ts +4 -0
- package/InfoNote/InfoNoteTitle.js +13 -0
- package/InfoNote/index.d.ts +65 -0
- package/InfoNote/index.js +59 -0
- package/Modal/BaseModal/ModalWrapper.js +3 -1
- package/Skeleton/index.d.ts +39 -0
- package/Skeleton/index.js +69 -0
- package/esm/Autocomplete/AutocompleteContainer.js +46 -7
- package/esm/Badge/BadgeBase.js +9 -2
- package/esm/Badge/BadgeDot.js +15 -0
- package/esm/Badge/BadgeStyled.js +67 -26
- package/esm/EmptyState/EmptyStateAction.js +11 -0
- package/esm/EmptyState/EmptyStateContainer.js +29 -0
- package/esm/EmptyState/EmptyStateContent.js +10 -0
- package/esm/EmptyState/EmptyStateIcon.js +33 -0
- package/esm/EmptyState/EmptyStateTitle.js +8 -0
- package/esm/EmptyState/index.js +42 -0
- package/esm/FileDropzone/FileDropzoneArea.js +76 -0
- package/esm/FileDropzone/index.js +148 -0
- package/esm/FileDropzone/utils.js +37 -0
- package/esm/HintPopover/HintPopoverButton.js +62 -0
- package/esm/HintPopover/HintPopoverContainer.js +47 -0
- package/esm/HintPopover/index.js +52 -0
- package/esm/InfoNote/InfoNoteContainer.js +49 -0
- package/esm/InfoNote/InfoNoteContent.js +11 -0
- package/esm/InfoNote/InfoNoteIcon.js +42 -0
- package/esm/InfoNote/InfoNoteTitle.js +8 -0
- package/esm/InfoNote/index.js +40 -0
- package/esm/Modal/BaseModal/ModalWrapper.js +3 -1
- package/esm/Skeleton/index.js +64 -0
- package/package.json +121 -1
|
@@ -29,7 +29,7 @@ const AutocompleteMenuList = React.forwardRef((props, ref) => (React.createEleme
|
|
|
29
29
|
AutocompleteMenuList.displayName = 'AutocompleteMenuList';
|
|
30
30
|
const MENU_OVERRIDES = { List: AutocompleteMenuList };
|
|
31
31
|
const Autocomplete = React.forwardRef((props, ref) => {
|
|
32
|
-
const { items, value, multiple, isOpen = false, isLoading = false, clearOnBlur = true, anchorPos = 'bottom-fill', alternativePlacements = ['bottom-fill', 'top-fill'], openOnFocus = true, autoFlip = true, viewportMargin, positionStrategy, requiredAsterisk, startIcon, fullWidth, placeholder, label, error, errorText, inputRef, filterItems, children, onChange, selectedItemToString, clearable = true, onInputChange, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides } = props, nativeInputProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "clearOnBlur", "anchorPos", "alternativePlacements", "openOnFocus", "autoFlip", "viewportMargin", "positionStrategy", "requiredAsterisk", "startIcon", "fullWidth", "placeholder", "label", "error", "errorText", "inputRef", "filterItems", "children", "onChange", "selectedItemToString", "clearable", "onInputChange", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides"]);
|
|
32
|
+
const { items, value, multiple, isOpen = false, isLoading = false, clearOnBlur = true, anchorPos = 'bottom-fill', alternativePlacements = ['bottom-fill', 'top-fill'], openOnFocus = true, autoFlip = true, viewportMargin, positionStrategy, requiredAsterisk, startIcon, fullWidth, placeholder, label, error, errorText, inputRef, filterItems, children, onChange, selectedItemToString, clearable = true, onInputChange, inputValue: controlledInputValue, onInputValueChange, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides } = props, nativeInputProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "clearOnBlur", "anchorPos", "alternativePlacements", "openOnFocus", "autoFlip", "viewportMargin", "positionStrategy", "requiredAsterisk", "startIcon", "fullWidth", "placeholder", "label", "error", "errorText", "inputRef", "filterItems", "children", "onChange", "selectedItemToString", "clearable", "onInputChange", "inputValue", "onInputValueChange", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides"]);
|
|
33
33
|
const menuRef = React.useRef(null);
|
|
34
34
|
const fieldInputRef = React.useRef(null);
|
|
35
35
|
const isFocusedRef = React.useRef(false);
|
|
@@ -39,10 +39,12 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
39
39
|
const overridesMap = React.useMemo(() => ({
|
|
40
40
|
TextField: (overrides === null || overrides === void 0 ? void 0 : overrides.TextField) || TextField,
|
|
41
41
|
}), [overrides]);
|
|
42
|
+
const isInputControlled = typeof controlledInputValue === 'string';
|
|
42
43
|
const clear = React.useCallback(() => {
|
|
43
44
|
if (onChange) {
|
|
44
45
|
onChange((multiple ? [] : null));
|
|
45
46
|
}
|
|
47
|
+
onInputValueChange === null || onInputValueChange === void 0 ? void 0 : onInputValueChange('');
|
|
46
48
|
dispatch(actionSetPartial({
|
|
47
49
|
filteredItems: items,
|
|
48
50
|
inputValue: '',
|
|
@@ -51,7 +53,7 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
51
53
|
var _a;
|
|
52
54
|
(_a = fieldInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
53
55
|
}, 15);
|
|
54
|
-
}, [dispatch, onChange, items, multiple]);
|
|
56
|
+
}, [dispatch, onChange, onInputValueChange, items, multiple]);
|
|
55
57
|
/**
|
|
56
58
|
* API
|
|
57
59
|
*/
|
|
@@ -70,13 +72,27 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
70
72
|
*/
|
|
71
73
|
const restoreInputValue = React.useCallback(() => {
|
|
72
74
|
// With multiple the field holds only the search text, the selected items are tags
|
|
73
|
-
|
|
75
|
+
// The controlled text is the value itself: it stays as it is
|
|
76
|
+
const newInputValue = isInputControlled
|
|
77
|
+
? controlledInputValue
|
|
78
|
+
: multiple || currentValue === null
|
|
79
|
+
? ''
|
|
80
|
+
: selectedItemToString(currentValue);
|
|
74
81
|
const newFilteredItems = applyFilterForItems(newInputValue, items);
|
|
75
82
|
dispatch(actionSetPartial({
|
|
76
83
|
filteredItems: newFilteredItems,
|
|
77
84
|
inputValue: newInputValue,
|
|
78
85
|
}));
|
|
79
|
-
}, [
|
|
86
|
+
}, [
|
|
87
|
+
currentValue,
|
|
88
|
+
selectedItemToString,
|
|
89
|
+
multiple,
|
|
90
|
+
applyFilterForItems,
|
|
91
|
+
items,
|
|
92
|
+
dispatch,
|
|
93
|
+
isInputControlled,
|
|
94
|
+
controlledInputValue,
|
|
95
|
+
]);
|
|
80
96
|
const inputKeydownEvent = React.useCallback((event) => {
|
|
81
97
|
var _a, _b, _c, _d, _e;
|
|
82
98
|
if (!isFocusedRef.current) {
|
|
@@ -169,14 +185,35 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
169
185
|
if (value === currentValue) {
|
|
170
186
|
return;
|
|
171
187
|
}
|
|
172
|
-
// With multiple the selected items are shown as tags and the search text is kept
|
|
173
|
-
|
|
188
|
+
// With multiple the selected items are shown as tags and the search text is kept,
|
|
189
|
+
// the controlled text is not replaced by the text of the item
|
|
190
|
+
dispatch(actionSetPartial(multiple || isInputControlled
|
|
174
191
|
? { currentValue: value }
|
|
175
192
|
: {
|
|
176
193
|
currentValue: value,
|
|
177
194
|
inputValue: value === null ? '' : selectedItemToString(value),
|
|
178
195
|
}));
|
|
179
|
-
}, [
|
|
196
|
+
}, [
|
|
197
|
+
value,
|
|
198
|
+
multiple,
|
|
199
|
+
currentValue,
|
|
200
|
+
inputValue,
|
|
201
|
+
dispatch,
|
|
202
|
+
selectedItemToString,
|
|
203
|
+
isInputControlled,
|
|
204
|
+
]);
|
|
205
|
+
/**
|
|
206
|
+
* The controlled text: the field follows `inputValue`
|
|
207
|
+
*/
|
|
208
|
+
React.useEffect(() => {
|
|
209
|
+
if (!isInputControlled || controlledInputValue === inputValue) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
dispatch(actionSetPartial({
|
|
213
|
+
inputValue: controlledInputValue,
|
|
214
|
+
filteredItems: applyFilterForItems(controlledInputValue, items),
|
|
215
|
+
}));
|
|
216
|
+
}, [isInputControlled, controlledInputValue, inputValue, dispatch, applyFilterForItems, items]);
|
|
180
217
|
React.useEffect(() => {
|
|
181
218
|
if (currentOpen && menuRef.current) {
|
|
182
219
|
menuRef.current.scrollToFirstSelected();
|
|
@@ -267,6 +304,7 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
267
304
|
if (typeof onInputChange === 'function') {
|
|
268
305
|
onInputChange(event);
|
|
269
306
|
}
|
|
307
|
+
onInputValueChange === null || onInputValueChange === void 0 ? void 0 : onInputValueChange(event.currentTarget.value);
|
|
270
308
|
// If openOnFocus is false, but value is not empty
|
|
271
309
|
// we should open menu list if is not opened
|
|
272
310
|
if (!openOnFocus && isFocusedRef.current && !currentOpen && filteredItems.length > 0) {
|
|
@@ -290,6 +328,7 @@ const Autocomplete = React.forwardRef((props, ref) => {
|
|
|
290
328
|
filteredItems.length,
|
|
291
329
|
items,
|
|
292
330
|
onInputChange,
|
|
331
|
+
onInputValueChange,
|
|
293
332
|
onRequestClose,
|
|
294
333
|
onRequestOpen,
|
|
295
334
|
openOnFocus,
|
package/esm/Badge/BadgeBase.js
CHANGED
|
@@ -14,14 +14,16 @@ import IconWrapper from './BadgeIconWrapper';
|
|
|
14
14
|
import TextWrapper from './BadgeTextWrapper';
|
|
15
15
|
import Container from './BadgeContainer';
|
|
16
16
|
import ButtonDelete from './BadgeDeleteButton';
|
|
17
|
+
import Dot from './BadgeDot';
|
|
17
18
|
const BadgeBase = (props, ref) => {
|
|
18
|
-
const { children, startIcon, color, variant, overrides, onDelete, deleteButtonLabel = 'Delete', onClick, onKeyDown } = props, nativeProps = __rest(props, ["children", "startIcon", "color", "variant", "overrides", "onDelete", "deleteButtonLabel", "onClick", "onKeyDown"]);
|
|
19
|
+
const { children, startIcon, dot = false, color, variant, overrides, onDelete, deleteButtonLabel = 'Delete', onClick, onKeyDown } = props, nativeProps = __rest(props, ["children", "startIcon", "dot", "color", "variant", "overrides", "onDelete", "deleteButtonLabel", "onClick", "onKeyDown"]);
|
|
19
20
|
const clickable = typeof onClick === 'function';
|
|
20
21
|
const overridesMap = React.useMemo(() => ({
|
|
21
22
|
TextWrapper: (overrides === null || overrides === void 0 ? void 0 : overrides.TextWrapper) || TextWrapper,
|
|
22
23
|
IconWrapper: (overrides === null || overrides === void 0 ? void 0 : overrides.IconWrapper) || IconWrapper,
|
|
23
24
|
Container: (overrides === null || overrides === void 0 ? void 0 : overrides.Container) || Container,
|
|
24
25
|
ButtonDelete: (overrides === null || overrides === void 0 ? void 0 : overrides.ButtonDelete) || ButtonDelete,
|
|
26
|
+
Dot: (overrides === null || overrides === void 0 ? void 0 : overrides.Dot) || Dot,
|
|
25
27
|
}), [overrides]);
|
|
26
28
|
// A clickable badge acts as a button, so it is activated by Enter and Space too
|
|
27
29
|
const handleKeyDown = React.useCallback((event) => {
|
|
@@ -41,8 +43,13 @@ const BadgeBase = (props, ref) => {
|
|
|
41
43
|
onDelete === null || onDelete === void 0 ? void 0 : onDelete(event);
|
|
42
44
|
}, [onDelete]);
|
|
43
45
|
return (React.createElement(overridesMap.Container, Object.assign({ role: clickable ? 'button' : undefined, tabIndex: clickable ? 0 : undefined }, nativeProps, { onClick: onClick, onKeyDown: handleKeyDown, color: color, ref: ref }),
|
|
46
|
+
dot && React.createElement(overridesMap.Dot, null),
|
|
44
47
|
typeof startIcon !== 'undefined' && startIcon !== null && (React.createElement(overridesMap.IconWrapper, null, startIcon)),
|
|
45
48
|
React.createElement(overridesMap.TextWrapper, null, children),
|
|
46
|
-
typeof onDelete === 'function' && (React.createElement(overridesMap.ButtonDelete
|
|
49
|
+
typeof onDelete === 'function' && (React.createElement(overridesMap.ButtonDelete
|
|
50
|
+
// the pale soft badge has the colored icon, as the outlined one
|
|
51
|
+
, {
|
|
52
|
+
// the pale soft badge has the colored icon, as the outlined one
|
|
53
|
+
variant: variant === 'soft' ? 'outlined' : variant, onClick: handleDelete, color: color, "aria-label": deleteButtonLabel }))));
|
|
47
54
|
};
|
|
48
55
|
export default React.forwardRef(BadgeBase);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
/**
|
|
4
|
+
* The color of the badge (`--badge-dot-color`), not the color of its text
|
|
5
|
+
*/
|
|
6
|
+
const StyledDot = styled.span `
|
|
7
|
+
flex: none;
|
|
8
|
+
width: 0.5em;
|
|
9
|
+
height: 0.5em;
|
|
10
|
+
margin-left: 0.55em;
|
|
11
|
+
border-radius: 50%;
|
|
12
|
+
background-color: var(--badge-dot-color, currentColor);
|
|
13
|
+
`;
|
|
14
|
+
const BadgeDot = (props, ref) => (React.createElement(StyledDot, Object.assign({ "aria-hidden": true }, props, { ref: ref })));
|
|
15
|
+
export default React.forwardRef(BadgeDot);
|
package/esm/Badge/BadgeStyled.js
CHANGED
|
@@ -65,6 +65,23 @@ const getOutlinedColors = (color, theme) => {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* The pale background of the color and the text of the same hue: dark on the light theme,
|
|
70
|
+
* light on the dark one. `$background` is the color itself
|
|
71
|
+
*/
|
|
72
|
+
const getSoftColors = (color, theme) => {
|
|
73
|
+
const base = color === 'primary'
|
|
74
|
+
? theme.color.accentPrimary
|
|
75
|
+
: color === 'secondary'
|
|
76
|
+
? theme.color.accentSecondary
|
|
77
|
+
: typeof color === 'undefined' || color === 'default'
|
|
78
|
+
? theme.color.textPrimary
|
|
79
|
+
: parseColor(String(color), theme.color.textPrimary);
|
|
80
|
+
return {
|
|
81
|
+
$background: base,
|
|
82
|
+
$color: theme.isDark ? base.lighten(60) : base.darken(60),
|
|
83
|
+
};
|
|
84
|
+
};
|
|
68
85
|
/**
|
|
69
86
|
* Both variants are one styled component: switching the variant (e.g. a toggling filter badge)
|
|
70
87
|
* must not remount the element, otherwise the focused badge loses the focus
|
|
@@ -73,42 +90,62 @@ const StyledBadge = styled(BadgeBase) `
|
|
|
73
90
|
border-style: solid;
|
|
74
91
|
border-width: ${BORDER_WIDTH};
|
|
75
92
|
border-color: ${({ $background }) => $background.toString()};
|
|
93
|
+
--badge-dot-color: ${({ $variant, $background, $color }) => ($variant === 'standard' ? $color : $background).toString()};
|
|
76
94
|
|
|
77
|
-
${({ $variant, $color, $background
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
${({ $variant, $color, $background }) => $variant === 'soft' &&
|
|
96
|
+
css `
|
|
97
|
+
color: ${$color.toString()};
|
|
98
|
+
background-color: ${$background.alpha(0.18).toString()};
|
|
99
|
+
border-color: transparent;
|
|
81
100
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
: css `
|
|
89
|
-
color: ${$color.toString()};
|
|
90
|
-
background-color: ${$background.toString()};
|
|
101
|
+
&:focus-visible {
|
|
102
|
+
outline-style: solid;
|
|
103
|
+
outline-width: 0.14em;
|
|
104
|
+
outline-color: ${$background.alpha(0.6).toString()};
|
|
105
|
+
}
|
|
106
|
+
`}
|
|
91
107
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
108
|
+
${({ $variant, $color, $background, theme }) => $variant === 'soft'
|
|
109
|
+
? ''
|
|
110
|
+
: $variant === 'outlined'
|
|
111
|
+
? css `
|
|
112
|
+
color: ${$color.darken(30).toString()};
|
|
113
|
+
background-color: transparent;
|
|
114
|
+
|
|
115
|
+
&:focus-visible {
|
|
116
|
+
outline-style: solid;
|
|
117
|
+
outline-width: 0.14em;
|
|
118
|
+
outline-color: ${$background.rgbString()};
|
|
119
|
+
}
|
|
120
|
+
`
|
|
121
|
+
: css `
|
|
122
|
+
color: ${$color.toString()};
|
|
123
|
+
background-color: ${$background.toString()};
|
|
124
|
+
|
|
125
|
+
&:focus-visible {
|
|
126
|
+
outline-color: ${$background.rgbString() === theme.color.accentPrimary.rgbString()
|
|
127
|
+
? theme.color.textPrimary.toString()
|
|
128
|
+
: theme.color.accentPrimary.toString()};
|
|
129
|
+
}
|
|
130
|
+
`}
|
|
98
131
|
|
|
99
132
|
${({ $clickable, $variant, $background }) => $clickable &&
|
|
100
133
|
css `
|
|
101
134
|
cursor: pointer;
|
|
102
135
|
|
|
103
136
|
&:hover {
|
|
104
|
-
${$variant === '
|
|
137
|
+
${$variant === 'soft'
|
|
105
138
|
? css `
|
|
106
|
-
background-color: ${$background.
|
|
139
|
+
background-color: ${$background.alpha(0.3).toString()};
|
|
107
140
|
`
|
|
108
|
-
:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
141
|
+
: $variant === 'outlined'
|
|
142
|
+
? css `
|
|
143
|
+
background-color: ${$background.darken(20).alpha(0.1).toString()};
|
|
144
|
+
`
|
|
145
|
+
: css `
|
|
146
|
+
background-color: ${$background.darken(30).toString()};
|
|
147
|
+
border-color: ${$background.darken(30).toString()};
|
|
148
|
+
`}
|
|
112
149
|
}
|
|
113
150
|
`}
|
|
114
151
|
${({ theme }) => themeFocusRing(theme)}
|
|
@@ -116,7 +153,11 @@ const StyledBadge = styled(BadgeBase) `
|
|
|
116
153
|
const BadgeStyled = (props, ref) => {
|
|
117
154
|
const { children, color, variant = 'standard', onClick } = props, restProps = __rest(props, ["children", "color", "variant", "onClick"]);
|
|
118
155
|
const theme = useTheme();
|
|
119
|
-
const { $background, $color } = React.useMemo(() => variant === '
|
|
156
|
+
const { $background, $color } = React.useMemo(() => variant === 'soft'
|
|
157
|
+
? getSoftColors(color, theme)
|
|
158
|
+
: variant === 'outlined'
|
|
159
|
+
? getOutlinedColors(color, theme)
|
|
160
|
+
: getStandardColors(color, theme), [color, variant, theme]);
|
|
120
161
|
return (React.createElement(StyledBadge, Object.assign({ "$variant": variant, "$clickable": typeof onClick === 'function', "$color": $color, "$background": $background, color: color, variant: variant, onClick: onClick }, restProps, { ref: ref }), children));
|
|
121
162
|
};
|
|
122
163
|
export default React.forwardRef(BadgeStyled);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
const StyledAction = styled.div `
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-wrap: wrap;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
gap: 0.5em;
|
|
8
|
+
margin-top: 0.5em;
|
|
9
|
+
`;
|
|
10
|
+
const EmptyStateAction = (props, ref) => React.createElement(StyledAction, Object.assign({}, props, { ref: ref }));
|
|
11
|
+
export default React.forwardRef(EmptyStateAction);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import styled from '@emotion/styled';
|
|
14
|
+
const StyledContainer = styled.div `
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
gap: 0.75em;
|
|
21
|
+
padding: 2em 1em;
|
|
22
|
+
text-align: center;
|
|
23
|
+
height: ${({ $fullHeight }) => ($fullHeight ? '100%' : 'auto')};
|
|
24
|
+
`;
|
|
25
|
+
const EmptyStateContainer = (props, ref) => {
|
|
26
|
+
const { fullHeight } = props, nativeProps = __rest(props, ["fullHeight"]);
|
|
27
|
+
return React.createElement(StyledContainer, Object.assign({}, nativeProps, { "$fullHeight": fullHeight, ref: ref }));
|
|
28
|
+
};
|
|
29
|
+
export default React.forwardRef(EmptyStateContainer);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
const StyledContent = styled.div `
|
|
4
|
+
max-width: 22em;
|
|
5
|
+
font-size: 0.9em;
|
|
6
|
+
line-height: 1.45;
|
|
7
|
+
color: ${({ theme }) => theme.color.textSecondary.toString()};
|
|
8
|
+
`;
|
|
9
|
+
const EmptyStateContent = (props, ref) => React.createElement(StyledContent, Object.assign({}, props, { ref: ref }));
|
|
10
|
+
export default React.forwardRef(EmptyStateContent);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import styled from '@emotion/styled';
|
|
14
|
+
const StyledIcon = styled.span `
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
margin-bottom: 0.75em;
|
|
17
|
+
font-size: 6em;
|
|
18
|
+
color: ${({ theme }) => theme.color.textPrimary.alpha(0.6).toString()};
|
|
19
|
+
`;
|
|
20
|
+
const Path = styled.path `
|
|
21
|
+
fill: currentColor;
|
|
22
|
+
`;
|
|
23
|
+
/**
|
|
24
|
+
* The open empty box. `children` replaces it
|
|
25
|
+
*/
|
|
26
|
+
const EmptyStateIcon = (props, ref) => {
|
|
27
|
+
const { children } = props, nativeProps = __rest(props, ["children"]);
|
|
28
|
+
return (React.createElement(StyledIcon, Object.assign({ "aria-hidden": true }, nativeProps, { ref: ref }), children !== null && children !== void 0 ? children : (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 511.99 511.99" },
|
|
29
|
+
React.createElement(Path, { d: "M446.822 213.631l-190.827-63.256-190.827 63.256L.01 317.129l59.984 19.884V447.02l196 64.97 196-64.97V337.013l59.984-19.884zm-57.5 12.545l-133.327 44.195-133.327-44.195 133.327-44.195zm-343.52 74.527l35.627-56.592 151.67 50.276-35.626 56.591zm44.193 46.255L210.34 386.85l30.655-48.693v137.256l-151-50.054zm181 128.454V338.156l30.655 48.693 120.345-39.892v78.401zm43.522-124.433l-35.626-56.591 151.67-50.276 35.627 56.592zM240.995 0h30v100.174h-30z" }),
|
|
30
|
+
React.createElement(Path, { d: "M122.952 31.63h30v100.174h-30z", transform: "rotate(-30 137.947 81.722)" }),
|
|
31
|
+
React.createElement(Path, { d: "M323.951 66.717h100.174v30H323.951z", transform: "rotate(-60 374.044 81.724)" })))));
|
|
32
|
+
};
|
|
33
|
+
export default React.forwardRef(EmptyStateIcon);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
const StyledTitle = styled.div `
|
|
4
|
+
font-weight: 600;
|
|
5
|
+
color: ${({ theme }) => theme.color.textPrimary.toString()};
|
|
6
|
+
`;
|
|
7
|
+
const EmptyStateTitle = (props, ref) => React.createElement(StyledTitle, Object.assign({}, props, { ref: ref }));
|
|
8
|
+
export default React.forwardRef(EmptyStateTitle);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import Container from './EmptyStateContainer';
|
|
14
|
+
import Icon from './EmptyStateIcon';
|
|
15
|
+
import Title from './EmptyStateTitle';
|
|
16
|
+
import Content from './EmptyStateContent';
|
|
17
|
+
import Action from './EmptyStateAction';
|
|
18
|
+
/**
|
|
19
|
+
* The empty list, the nothing found, the not chosen yet: the illustration, what is empty
|
|
20
|
+
* and what to do next
|
|
21
|
+
*/
|
|
22
|
+
const EmptyState = (props, ref) => {
|
|
23
|
+
const { title, children, action, icon, fullHeight = false, overrides } = props, nativeProps = __rest(props, ["title", "children", "action", "icon", "fullHeight", "overrides"]);
|
|
24
|
+
const overridesMap = React.useMemo(() => ({
|
|
25
|
+
Container: (overrides === null || overrides === void 0 ? void 0 : overrides.Container) || Container,
|
|
26
|
+
Icon: (overrides === null || overrides === void 0 ? void 0 : overrides.Icon) || Icon,
|
|
27
|
+
Title: (overrides === null || overrides === void 0 ? void 0 : overrides.Title) || Title,
|
|
28
|
+
Content: (overrides === null || overrides === void 0 ? void 0 : overrides.Content) || Content,
|
|
29
|
+
Action: (overrides === null || overrides === void 0 ? void 0 : overrides.Action) || Action,
|
|
30
|
+
}), [overrides]);
|
|
31
|
+
return (React.createElement(overridesMap.Container, Object.assign({}, nativeProps, { fullHeight: fullHeight, ref: ref }),
|
|
32
|
+
icon !== false && React.createElement(overridesMap.Icon, null, icon),
|
|
33
|
+
title && React.createElement(overridesMap.Title, null, title),
|
|
34
|
+
children && React.createElement(overridesMap.Content, null, children),
|
|
35
|
+
action && React.createElement(overridesMap.Action, null, action)));
|
|
36
|
+
};
|
|
37
|
+
export * from './EmptyStateContainer';
|
|
38
|
+
export * from './EmptyStateIcon';
|
|
39
|
+
export * from './EmptyStateTitle';
|
|
40
|
+
export * from './EmptyStateContent';
|
|
41
|
+
export * from './EmptyStateAction';
|
|
42
|
+
export default React.forwardRef(EmptyState);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import styled from '@emotion/styled';
|
|
14
|
+
import { css } from '@emotion/react';
|
|
15
|
+
const StyledArea = styled.div `
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
display: flex;
|
|
18
|
+
width: 100%;
|
|
19
|
+
min-height: 6.5em;
|
|
20
|
+
padding: 1em;
|
|
21
|
+
border-radius: ${({ theme }) => theme.shape.radiusFactor * 1.6}em;
|
|
22
|
+
border: 1px ${({ $filled }) => ($filled ? 'solid' : 'dashed')}
|
|
23
|
+
${({ theme, $active }) => ($active ? theme.color.accentPrimary : theme.color.textSecondary.alpha(0.45)).toString()};
|
|
24
|
+
background-color: ${({ theme, $active }) => ($active
|
|
25
|
+
? theme.color.accentPrimary.alpha(0.1)
|
|
26
|
+
: theme.color.textPrimary.alpha(0.03)).toString()};
|
|
27
|
+
color: ${({ theme }) => theme.color.textPrimary.toString()};
|
|
28
|
+
transition:
|
|
29
|
+
border-color 120ms ease-out,
|
|
30
|
+
background-color 120ms ease-out;
|
|
31
|
+
|
|
32
|
+
${({ $filled, $disabled, theme }) => !$filled &&
|
|
33
|
+
!$disabled &&
|
|
34
|
+
css `
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
|
|
37
|
+
&:hover,
|
|
38
|
+
&:focus-visible {
|
|
39
|
+
border-color: ${theme.color.accentPrimary.toString()};
|
|
40
|
+
}
|
|
41
|
+
`}
|
|
42
|
+
|
|
43
|
+
${({ $filled }) => $filled
|
|
44
|
+
? css `
|
|
45
|
+
flex-direction: row;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: 0.75em;
|
|
48
|
+
`
|
|
49
|
+
: css `
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
align-items: center;
|
|
52
|
+
justify-content: center;
|
|
53
|
+
gap: 0.3em;
|
|
54
|
+
text-align: center;
|
|
55
|
+
`}
|
|
56
|
+
|
|
57
|
+
${({ $disabled }) => $disabled &&
|
|
58
|
+
css `
|
|
59
|
+
opacity: 0.5;
|
|
60
|
+
cursor: default;
|
|
61
|
+
`}
|
|
62
|
+
|
|
63
|
+
&:focus-visible {
|
|
64
|
+
outline: 2px solid ${({ theme }) => theme.color.accentPrimary.alpha(0.4).toString()};
|
|
65
|
+
outline-offset: 2px;
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
/**
|
|
69
|
+
* The area: without the file — the icon and two lines in the middle (it chooses the file),
|
|
70
|
+
* with the file — the row of the file
|
|
71
|
+
*/
|
|
72
|
+
const FileDropzoneArea = (props, ref) => {
|
|
73
|
+
const { active, filled, disabled } = props, nativeProps = __rest(props, ["active", "filled", "disabled"]);
|
|
74
|
+
return (React.createElement(StyledArea, Object.assign({}, nativeProps, { "$active": active, "$filled": filled, "$disabled": disabled, ref: ref })));
|
|
75
|
+
};
|
|
76
|
+
export default React.forwardRef(FileDropzoneArea);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import styled from '@emotion/styled';
|
|
14
|
+
import Button from '../Button';
|
|
15
|
+
import Area from './FileDropzoneArea';
|
|
16
|
+
import { formatFileSize, isFileAccepted } from './utils';
|
|
17
|
+
export { formatFileSize, isFileAccepted };
|
|
18
|
+
const Icon = styled.span `
|
|
19
|
+
flex: none;
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
font-size: 1.5em;
|
|
22
|
+
color: ${({ theme }) => theme.color.textSecondary.toString()};
|
|
23
|
+
`;
|
|
24
|
+
const Label = styled.span `
|
|
25
|
+
font-size: 0.875em;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
`;
|
|
28
|
+
const Hint = styled.span `
|
|
29
|
+
font-size: 0.75em;
|
|
30
|
+
color: ${({ theme }) => theme.color.textSecondary.toString()};
|
|
31
|
+
`;
|
|
32
|
+
const FileText = styled.span `
|
|
33
|
+
flex: 1;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
gap: 0.15em;
|
|
38
|
+
text-align: left;
|
|
39
|
+
`;
|
|
40
|
+
/**
|
|
41
|
+
* The long name in one line: the whole name is in the tooltip
|
|
42
|
+
*/
|
|
43
|
+
const FileName = styled(Label) `
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
text-overflow: ellipsis;
|
|
47
|
+
`;
|
|
48
|
+
const Path = styled.path `
|
|
49
|
+
fill: currentColor;
|
|
50
|
+
`;
|
|
51
|
+
const UploadIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 24 24", "aria-hidden": true },
|
|
52
|
+
React.createElement(Path, { d: "M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4 0-2.05 1.53-3.76 3.56-3.97l1.07-.11.5-.95A5.469 5.469 0 0 1 12 6c2.62 0 4.88 1.86 5.39 4.43l.3 1.5 1.53.11A2.98 2.98 0 0 1 22 15c0 1.65-1.35 3-3 3zM8 13h2.55v3h2.9v-3H16l-4-4z" })));
|
|
53
|
+
const FileIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 24 24", "aria-hidden": true },
|
|
54
|
+
React.createElement(Path, { d: "M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6zm2-6h8v2H8zm0 3h5v2H8z" })));
|
|
55
|
+
const TrashIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 24 24", "aria-hidden": true },
|
|
56
|
+
React.createElement(Path, { d: "M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z" })));
|
|
57
|
+
/**
|
|
58
|
+
* The file by the click or by the drop: one area with the dashed border. The chosen file
|
|
59
|
+
* is the row with its name and size, «Replace» and the delete button; a new file can be
|
|
60
|
+
* dropped onto it too
|
|
61
|
+
*/
|
|
62
|
+
const FileDropzone = (props, ref) => {
|
|
63
|
+
const { value, onChange, accept, maxSize, onReject, label = 'Choose a file', hint, replaceLabel = 'Replace', removeLabel = 'Remove the file', formatSize = formatFileSize, disabled = false, overrides } = props, nativeProps = __rest(props, ["value", "onChange", "accept", "maxSize", "onReject", "label", "hint", "replaceLabel", "removeLabel", "formatSize", "disabled", "overrides"]);
|
|
64
|
+
const AreaComponent = (overrides === null || overrides === void 0 ? void 0 : overrides.Area) || Area;
|
|
65
|
+
const inputRef = React.useRef(null);
|
|
66
|
+
// dragenter/dragleave fire on every child: the counter keeps the highlight steady
|
|
67
|
+
const dragDepthRef = React.useRef(0);
|
|
68
|
+
const [isDragActive, setDragActive] = React.useState(false);
|
|
69
|
+
const take = (file) => {
|
|
70
|
+
if (!file) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!isFileAccepted(file, accept)) {
|
|
74
|
+
onReject === null || onReject === void 0 ? void 0 : onReject(file, 'type');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (typeof maxSize === 'number' && file.size > maxSize) {
|
|
78
|
+
onReject === null || onReject === void 0 ? void 0 : onReject(file, 'size');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
onChange(file);
|
|
82
|
+
};
|
|
83
|
+
const choose = () => {
|
|
84
|
+
var _a;
|
|
85
|
+
if (!disabled) {
|
|
86
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const dropHandlers = disabled
|
|
90
|
+
? {}
|
|
91
|
+
: {
|
|
92
|
+
onDragEnter: (event) => {
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
dragDepthRef.current += 1;
|
|
95
|
+
setDragActive(true);
|
|
96
|
+
},
|
|
97
|
+
onDragOver: (event) => {
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
},
|
|
100
|
+
onDragLeave: () => {
|
|
101
|
+
dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
|
|
102
|
+
if (dragDepthRef.current === 0) {
|
|
103
|
+
setDragActive(false);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
onDrop: (event) => {
|
|
107
|
+
var _a;
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
dragDepthRef.current = 0;
|
|
110
|
+
setDragActive(false);
|
|
111
|
+
take((_a = event.dataTransfer.files) === null || _a === void 0 ? void 0 : _a[0]);
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const input = (React.createElement("input", { hidden: true, ref: inputRef, type: "file", accept: accept, disabled: disabled,
|
|
115
|
+
// the input is inside the area: its click must not reach the area and open the dialog again
|
|
116
|
+
onClick: event => event.stopPropagation(), onChange: event => {
|
|
117
|
+
var _a;
|
|
118
|
+
const file = (_a = event.currentTarget.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
119
|
+
// the same file can be chosen again after the removal
|
|
120
|
+
event.currentTarget.value = '';
|
|
121
|
+
take(file);
|
|
122
|
+
} }));
|
|
123
|
+
if (value) {
|
|
124
|
+
return (React.createElement(AreaComponent, Object.assign({}, nativeProps, dropHandlers, { active: isDragActive, filled: true, disabled: disabled, ref: ref }),
|
|
125
|
+
input,
|
|
126
|
+
React.createElement(Icon, null,
|
|
127
|
+
React.createElement(FileIcon, null)),
|
|
128
|
+
React.createElement(FileText, null,
|
|
129
|
+
React.createElement(FileName, { title: value.name }, value.name),
|
|
130
|
+
React.createElement(Hint, null, formatSize(value.size))),
|
|
131
|
+
React.createElement(Button, { type: "button", variant: "plain", disabled: disabled, onClick: choose }, replaceLabel),
|
|
132
|
+
React.createElement(Button, { type: "button", variant: "plain", color: "error", iconOnly: true, disabled: disabled, title: removeLabel, "aria-label": removeLabel, onClick: () => onChange(null) },
|
|
133
|
+
React.createElement(TrashIcon, null))));
|
|
134
|
+
}
|
|
135
|
+
return (React.createElement(AreaComponent, Object.assign({ role: "button", tabIndex: disabled ? -1 : 0, "aria-disabled": disabled || undefined }, nativeProps, dropHandlers, { active: isDragActive, filled: false, disabled: disabled, onClick: choose, onKeyDown: event => {
|
|
136
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
choose();
|
|
139
|
+
}
|
|
140
|
+
}, ref: ref }),
|
|
141
|
+
input,
|
|
142
|
+
React.createElement(Icon, null,
|
|
143
|
+
React.createElement(UploadIcon, null)),
|
|
144
|
+
React.createElement(Label, null, label),
|
|
145
|
+
hint && React.createElement(Hint, null, hint)));
|
|
146
|
+
};
|
|
147
|
+
export * from './FileDropzoneArea';
|
|
148
|
+
export default React.forwardRef(FileDropzone);
|