@via-profit/ui-kit 0.7.0 → 0.9.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.
Files changed (77) hide show
  1. package/Autocomplete/AutocompleteContainer.d.ts +13 -0
  2. package/Autocomplete/AutocompleteContainer.js +46 -7
  3. package/Badge/BadgeBase.d.ts +10 -1
  4. package/Badge/BadgeBase.js +9 -2
  5. package/Badge/BadgeDot.d.ts +4 -0
  6. package/Badge/BadgeDot.js +20 -0
  7. package/Badge/BadgeStyled.js +67 -26
  8. package/Badge/index.d.ts +4 -4
  9. package/CHANGELOG.md +20 -0
  10. package/EmptyState/EmptyStateAction.d.ts +4 -0
  11. package/EmptyState/EmptyStateAction.js +16 -0
  12. package/EmptyState/EmptyStateContainer.d.ts +8 -0
  13. package/EmptyState/EmptyStateContainer.js +34 -0
  14. package/EmptyState/EmptyStateContent.d.ts +4 -0
  15. package/EmptyState/EmptyStateContent.js +15 -0
  16. package/EmptyState/EmptyStateIcon.d.ts +4 -0
  17. package/EmptyState/EmptyStateIcon.js +38 -0
  18. package/EmptyState/EmptyStateTitle.d.ts +4 -0
  19. package/EmptyState/EmptyStateTitle.js +13 -0
  20. package/EmptyState/index.d.ts +82 -0
  21. package/EmptyState/index.js +61 -0
  22. package/FileDropzone/FileDropzoneArea.d.ts +24 -0
  23. package/FileDropzone/FileDropzoneArea.js +81 -0
  24. package/FileDropzone/index.d.ts +107 -0
  25. package/FileDropzone/index.js +169 -0
  26. package/FileDropzone/utils.d.ts +9 -0
  27. package/FileDropzone/utils.js +42 -0
  28. package/HintPopover/HintPopoverButton.d.ts +4 -0
  29. package/HintPopover/HintPopoverButton.js +67 -0
  30. package/HintPopover/HintPopoverContainer.d.ts +4 -0
  31. package/HintPopover/HintPopoverContainer.js +52 -0
  32. package/HintPopover/index.d.ts +67 -0
  33. package/HintPopover/index.js +71 -0
  34. package/InfoNote/InfoNoteContainer.d.ts +14 -0
  35. package/InfoNote/InfoNoteContainer.js +56 -0
  36. package/InfoNote/InfoNoteContent.d.ts +4 -0
  37. package/InfoNote/InfoNoteContent.js +16 -0
  38. package/InfoNote/InfoNoteIcon.d.ts +9 -0
  39. package/InfoNote/InfoNoteIcon.js +47 -0
  40. package/InfoNote/InfoNoteTitle.d.ts +4 -0
  41. package/InfoNote/InfoNoteTitle.js +13 -0
  42. package/InfoNote/index.d.ts +65 -0
  43. package/InfoNote/index.js +59 -0
  44. package/Modal/Drawer/DrawerInner.d.ts +6 -0
  45. package/Modal/Drawer/DrawerInner.js +91 -2
  46. package/Modal/Drawer/index.d.ts +8 -0
  47. package/Modal/Drawer/index.js +3 -3
  48. package/Modal/Drawer/useSwipeToClose.d.ts +30 -0
  49. package/Modal/Drawer/useSwipeToClose.js +238 -0
  50. package/Skeleton/index.d.ts +39 -0
  51. package/Skeleton/index.js +69 -0
  52. package/esm/Autocomplete/AutocompleteContainer.js +46 -7
  53. package/esm/Badge/BadgeBase.js +9 -2
  54. package/esm/Badge/BadgeDot.js +15 -0
  55. package/esm/Badge/BadgeStyled.js +67 -26
  56. package/esm/EmptyState/EmptyStateAction.js +11 -0
  57. package/esm/EmptyState/EmptyStateContainer.js +29 -0
  58. package/esm/EmptyState/EmptyStateContent.js +10 -0
  59. package/esm/EmptyState/EmptyStateIcon.js +33 -0
  60. package/esm/EmptyState/EmptyStateTitle.js +8 -0
  61. package/esm/EmptyState/index.js +42 -0
  62. package/esm/FileDropzone/FileDropzoneArea.js +76 -0
  63. package/esm/FileDropzone/index.js +148 -0
  64. package/esm/FileDropzone/utils.js +37 -0
  65. package/esm/HintPopover/HintPopoverButton.js +62 -0
  66. package/esm/HintPopover/HintPopoverContainer.js +47 -0
  67. package/esm/HintPopover/index.js +52 -0
  68. package/esm/InfoNote/InfoNoteContainer.js +49 -0
  69. package/esm/InfoNote/InfoNoteContent.js +11 -0
  70. package/esm/InfoNote/InfoNoteIcon.js +42 -0
  71. package/esm/InfoNote/InfoNoteTitle.js +8 -0
  72. package/esm/InfoNote/index.js +40 -0
  73. package/esm/Modal/Drawer/DrawerInner.js +91 -2
  74. package/esm/Modal/Drawer/index.js +3 -3
  75. package/esm/Modal/Drawer/useSwipeToClose.js +233 -0
  76. package/esm/Skeleton/index.js +64 -0
  77. package/package.json +126 -1
@@ -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);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The file matches `accept` of the input: the MIME types (`image/png`), the groups (`image/*`)
3
+ * and the extensions (`.pdf`). The empty `accept` takes any file
4
+ */
5
+ export const isFileAccepted = (file, accept) => {
6
+ if (!accept) {
7
+ return true;
8
+ }
9
+ const name = file.name.toLowerCase();
10
+ const type = file.type.toLowerCase();
11
+ return accept
12
+ .split(',')
13
+ .map(item => item.trim().toLowerCase())
14
+ .filter(Boolean)
15
+ .some(item => {
16
+ if (item.startsWith('.')) {
17
+ return name.endsWith(item);
18
+ }
19
+ if (item.endsWith('/*')) {
20
+ return type.startsWith(item.slice(0, -1));
21
+ }
22
+ return type === item;
23
+ });
24
+ };
25
+ /**
26
+ * «54.1 KB», «2.3 MB»: the decimal units, as the file managers show
27
+ */
28
+ export const formatFileSize = (bytes) => {
29
+ const units = ['B', 'KB', 'MB', 'GB'];
30
+ let value = bytes;
31
+ let unit = 0;
32
+ while (value >= 1000 && unit < units.length - 1) {
33
+ value /= 1000;
34
+ unit += 1;
35
+ }
36
+ return `${unit === 0 ? value : value.toFixed(1).replace(/\.0$/, '')} ${units[unit]}`;
37
+ };
@@ -0,0 +1,62 @@
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
+ /**
15
+ * The color of the text around: the button stands in the text, in the label of a field,
16
+ * in a colored header of the dialog
17
+ */
18
+ const StyledButton = styled.button `
19
+ box-sizing: content-box;
20
+ display: inline-flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ margin: 0 0.15em;
24
+ padding: 0.2em;
25
+ border: none;
26
+ border-radius: 50%;
27
+ background: none;
28
+ font: inherit;
29
+ font-size: 1em;
30
+ line-height: 1;
31
+ color: inherit;
32
+ opacity: 0.6;
33
+ cursor: pointer;
34
+ vertical-align: middle;
35
+ transition:
36
+ opacity 120ms ease-out,
37
+ background-color 120ms ease-out;
38
+
39
+ &:hover,
40
+ &:focus-visible,
41
+ &[aria-expanded='true'] {
42
+ opacity: 1;
43
+ background-color: color-mix(in srgb, currentColor 15%, transparent);
44
+ }
45
+
46
+ &:focus-visible {
47
+ outline: 2px solid ${({ theme }) => theme.color.accentPrimary.toString()};
48
+ outline-offset: 1px;
49
+ }
50
+ `;
51
+ const Path = styled.path `
52
+ fill: currentColor;
53
+ `;
54
+ /**
55
+ * «?» in the circle. `children` replaces the icon
56
+ */
57
+ const HintPopoverButton = (props, ref) => {
58
+ const { children } = props, nativeProps = __rest(props, ["children"]);
59
+ return (React.createElement(StyledButton, Object.assign({ type: "button" }, 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 24 24", "aria-hidden": true },
60
+ React.createElement(Path, { d: "M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z" })))));
61
+ };
62
+ export default React.forwardRef(HintPopoverButton);
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import styled from '@emotion/styled';
3
+ import { keyframes } from '@emotion/react';
4
+ import { elevation } from '../ThemeProvider/tokens';
5
+ const appear = keyframes `
6
+ from {
7
+ opacity: 0;
8
+ transform: scale(0.96);
9
+ }
10
+ to {
11
+ opacity: 1;
12
+ transform: scale(1);
13
+ }
14
+ `;
15
+ const StyledContainer = styled.div `
16
+ box-sizing: border-box;
17
+ max-width: 22em;
18
+ padding: 0.7em 0.9em;
19
+ font-size: 0.875rem;
20
+ font-weight: normal;
21
+ line-height: 1.45;
22
+ text-align: left;
23
+ white-space: normal;
24
+ overflow-wrap: break-word;
25
+ color: ${({ theme }) => theme.color.textPrimary.toString()};
26
+ background-color: ${({ theme }) => theme.color.surface.toString()};
27
+ border-radius: ${({ theme }) => theme.shape.radiusFactor * 1.6}em;
28
+ box-shadow: ${({ theme }) => elevation(theme, 'popup')};
29
+ animation: ${appear} 120ms ease-out;
30
+
31
+ & p {
32
+ margin: 0 0 0.5em;
33
+ }
34
+
35
+ & p:last-child {
36
+ margin-bottom: 0;
37
+ }
38
+
39
+ @media (prefers-reduced-motion: reduce) {
40
+ animation: none;
41
+ }
42
+ `;
43
+ /**
44
+ * The bubble with the content of the hint
45
+ */
46
+ const HintPopoverContainer = (props, ref) => React.createElement(StyledContainer, Object.assign({}, props, { ref: ref }));
47
+ export default React.forwardRef(HintPopoverContainer);
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { useTheme } from '@emotion/react';
3
+ import Popper from '../Popper';
4
+ import ClickOutside from '../ClickOutside';
5
+ import Button from './HintPopoverButton';
6
+ import Container from './HintPopoverContainer';
7
+ /**
8
+ * «?» next to a field, a button or a title: the explanation in the popper by the click.
9
+ * For what is needed sometimes; what everybody must know goes into InfoNote.
10
+ * Closes by the outside click and by Escape, Escape returns the focus to the button
11
+ */
12
+ const HintPopover = props => {
13
+ const { children, label = 'Hint', icon, placement = 'bottom-start', isOpen, onOpenChange, offset = 6, zIndex, id, overrides, } = props;
14
+ const theme = useTheme();
15
+ const generatedId = `hint-popover-${React.useId().replace(/:/g, '')}`;
16
+ const hintId = id || generatedId;
17
+ const [button, setButton] = React.useState(null);
18
+ const [internalOpen, setInternalOpen] = React.useState(false);
19
+ const isControlled = typeof isOpen !== 'undefined';
20
+ const open = isControlled ? Boolean(isOpen) : internalOpen;
21
+ const overridesMap = React.useMemo(() => ({
22
+ Button: (overrides === null || overrides === void 0 ? void 0 : overrides.Button) || Button,
23
+ Container: (overrides === null || overrides === void 0 ? void 0 : overrides.Container) || Container,
24
+ }), [overrides]);
25
+ const setOpen = React.useCallback((next) => {
26
+ if (!isControlled) {
27
+ setInternalOpen(next);
28
+ }
29
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
30
+ }, [isControlled, onOpenChange]);
31
+ React.useEffect(() => {
32
+ if (!open) {
33
+ return undefined;
34
+ }
35
+ const onKeyDown = (event) => {
36
+ if (event.key === 'Escape') {
37
+ setOpen(false);
38
+ button === null || button === void 0 ? void 0 : button.focus();
39
+ }
40
+ };
41
+ document.addEventListener('keydown', onKeyDown);
42
+ return () => document.removeEventListener('keydown', onKeyDown);
43
+ }, [open, setOpen, button]);
44
+ return (React.createElement(React.Fragment, null,
45
+ React.createElement(overridesMap.Button, { ref: setButton, title: label, "aria-label": label, "aria-expanded": open, "aria-controls": open ? hintId : undefined, onClick: () => setOpen(!open) }, icon),
46
+ React.createElement(ClickOutside, { onOutsideClick: () => open && setOpen(false), ignoreElements: [button] },
47
+ React.createElement(Popper, { isOpen: open, anchorElement: button, anchorPos: placement, autoFlip: true, offset: offset, viewportMargin: 8, zIndex: zIndex !== null && zIndex !== void 0 ? zIndex : theme.zIndex.modal + 1, id: hintId },
48
+ React.createElement(overridesMap.Container, null, children)))));
49
+ };
50
+ export * from './HintPopoverButton';
51
+ export * from './HintPopoverContainer';
52
+ export default HintPopover;
@@ -0,0 +1,49 @@
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
+ /**
15
+ * The color of the variant: the border, the icon and the tint of the background
16
+ */
17
+ export const variantColor = (theme, variant) => {
18
+ switch (variant) {
19
+ case 'success':
20
+ return theme.color.success;
21
+ case 'warning':
22
+ return theme.color.warning;
23
+ case 'error':
24
+ return theme.color.error;
25
+ default:
26
+ return theme.color.accentPrimary;
27
+ }
28
+ };
29
+ const StyledContainer = styled.div `
30
+ box-sizing: border-box;
31
+ display: flex;
32
+ gap: 0.6em;
33
+ align-items: flex-start;
34
+ padding: 0.6em 0.8em;
35
+ font-size: 0.875em;
36
+ line-height: 1.4;
37
+ overflow-wrap: break-word;
38
+ color: ${({ theme }) => theme.color.textPrimary.toString()};
39
+ border-radius: ${({ theme }) => theme.shape.radiusFactor * 1.6}em;
40
+ border-left: 3px solid ${({ theme, $variant }) => variantColor(theme, $variant).toString()};
41
+ background-color: ${({ theme, $variant }) => variantColor(theme, $variant)
42
+ .alpha($variant === 'warning' ? 0.14 : 0.1)
43
+ .toString()};
44
+ `;
45
+ const InfoNoteContainer = (props, ref) => {
46
+ const { variant, children } = props, nativeProps = __rest(props, ["variant", "children"]);
47
+ return (React.createElement(StyledContainer, Object.assign({}, nativeProps, { "$variant": variant, ref: ref }), children));
48
+ };
49
+ export default React.forwardRef(InfoNoteContainer);
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import styled from '@emotion/styled';
3
+ const StyledContent = styled.div `
4
+ flex: 1;
5
+ min-width: 0;
6
+ `;
7
+ /**
8
+ * The title and the text, to the right of the icon
9
+ */
10
+ const InfoNoteContent = (props, ref) => React.createElement(StyledContent, Object.assign({}, props, { ref: ref }));
11
+ export default React.forwardRef(InfoNoteContent);