kamotive_ui 1.2.12 → 1.2.14
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/dist/Icons/ChevronDown/ChevronDown10.d.ts +1 -0
- package/dist/Icons/ChevronDown/ChevronDown10.js +3 -2
- package/dist/Icons/IconDownload/IconDownload.d.ts +7 -0
- package/dist/Icons/IconDownload/IconDownload.js +5 -0
- package/dist/Icons/index.d.ts +1 -0
- package/dist/Icons/index.js +1 -0
- package/dist/components/Checkbox/Checkbox.js +14 -2
- package/dist/components/Checkbox/Checkbox.module.css +25 -12
- package/dist/components/Dialog/Dialog.d.ts +3 -0
- package/dist/components/Dialog/Dialog.js +10 -0
- package/dist/components/Dialog/Dialog.module.css +47 -0
- package/dist/components/FileAttach/FileAttach.js +4 -4
- package/dist/components/FileItem/FileItem.d.ts +3 -0
- package/dist/components/FileItem/FileItem.js +20 -0
- package/dist/components/FileItem/FileItem.module.css +45 -0
- package/dist/components/IconButton/IconButton.d.ts +3 -0
- package/dist/components/IconButton/IconButton.js +10 -0
- package/dist/components/IconButton/IconButton.module.css +26 -0
- package/dist/components/List/List.d.ts +3 -0
- package/dist/components/List/List.js +89 -0
- package/dist/components/List/List.module.css +40 -0
- package/dist/components/ListItem/ListItem.d.ts +3 -0
- package/dist/components/ListItem/ListItem.js +41 -0
- package/dist/components/ListItem/ListItem.module.css +6 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +7 -1
- package/dist/types/index.d.ts +97 -3
- package/package.json +1 -1
- package/dist/components/Loader/Loader.d.ts +0 -3
- package/dist/components/Loader/Loader.js +0 -18
- package/dist/components/Loader/Loader.module.css +0 -75
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export const ChevronDown10 = ({ color = 'inherit', htmlColor, strokeWidth, }) => {
|
|
2
|
+
export const ChevronDown10 = ({ color = 'inherit', htmlColor, strokeWidth, rotation = 0, }) => {
|
|
3
3
|
return (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: color },
|
|
4
|
-
React.createElement("
|
|
4
|
+
React.createElement("g", { transform: `rotate(${rotation}, 12, 12)` },
|
|
5
|
+
React.createElement("path", { fill: htmlColor || 'currentColor', stroke: htmlColor || 'currentColor', strokeWidth: strokeWidth || '0', d: "M5.84,9.59L11.5,15.25L17.16,9.59L16.45,8.89L11.5,13.84L6.55,8.89L5.84,9.59Z" }))));
|
|
5
6
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const IconDownload = ({ color = 'inherit', htmlColor, strokeWidth, onClick, }) => {
|
|
3
|
+
return (React.createElement("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: color, onClick: onClick },
|
|
4
|
+
React.createElement("path", { fill: htmlColor || 'currentColor', stroke: htmlColor || 'currentColor', strokeWidth: strokeWidth || '0', d: "M12,4V16.25L17.25,11L18,11.66L11.5,18.16L5,11.66L5.75,11L11,16.25V4H12M3,19H4V21H19V19H20V22H3V19Z" })));
|
|
5
|
+
};
|
package/dist/Icons/index.d.ts
CHANGED
|
@@ -18,3 +18,4 @@ export { IconClose10 } from './IconClose/IconClose10';
|
|
|
18
18
|
export { IconColorPicker10 } from './IconColorPicker/IconColorPicker10';
|
|
19
19
|
export { IconFile } from './IconFile/IconFile';
|
|
20
20
|
export { IconUpload } from './IconUpload/IconUpload';
|
|
21
|
+
export { IconDownload } from './IconDownload/IconDownload';
|
package/dist/Icons/index.js
CHANGED
|
@@ -18,3 +18,4 @@ export { IconClose10 } from './IconClose/IconClose10';
|
|
|
18
18
|
export { IconColorPicker10 } from './IconColorPicker/IconColorPicker10';
|
|
19
19
|
export { IconFile } from './IconFile/IconFile';
|
|
20
20
|
export { IconUpload } from './IconUpload/IconUpload';
|
|
21
|
+
export { IconDownload } from './IconDownload/IconDownload';
|
|
@@ -3,13 +3,25 @@ import styles from './Checkbox.module.css';
|
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
;
|
|
5
5
|
import { Typography } from '../Typography/Typography';
|
|
6
|
-
export const Checkbox = ({ checked, onChange, disabled = false, size = 'sm', label }) => {
|
|
6
|
+
export const Checkbox = ({ checked, onChange, disabled = false, size = 'sm', label, color, filled }) => {
|
|
7
7
|
const handleChange = (e) => {
|
|
8
8
|
if (onChange) {
|
|
9
9
|
onChange(e);
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
|
-
|
|
12
|
+
const checkboxStyles = {
|
|
13
|
+
'--border-color': color || 'var(--icons-active)',
|
|
14
|
+
'--border-color-hover': color ? 'color-mix(in srgb, var(--border-color) 60%, white)' : 'var(--blue-main)',
|
|
15
|
+
'--border-color-checked': color || 'var(--icons-medium)',
|
|
16
|
+
'--border-color-disabled': color ? 'color-mix(in srgb, var(--border-color) 30%, white)' : 'var(--icons-light)',
|
|
17
|
+
'--background-color-hover': filled ? 'var(--border-color-hover)' : 'var(--white)',
|
|
18
|
+
'--background-color-checked': filled ? 'var(--border-color-checked)' : 'var(--white)',
|
|
19
|
+
'--background-color-disabled': filled ? 'var(--border-color-disabled)' : 'var(--white)',
|
|
20
|
+
'--arrow-color': filled ? 'var(--white)' : 'var(--border-color-checked)',
|
|
21
|
+
'--arrow-color-hover': filled ? 'var(--white)' : 'var(--border-color-hover)',
|
|
22
|
+
'--arrow-color-disabled': filled ? 'var(--white)' : 'var(--border-color-disabled)',
|
|
23
|
+
};
|
|
24
|
+
return (React.createElement("label", { className: styles.checkbox, style: checkboxStyles },
|
|
13
25
|
React.createElement("input", { type: "checkbox", checked: checked, onChange: handleChange, disabled: disabled, className: classNames(styles.input, styles[size]) }),
|
|
14
26
|
React.createElement(Typography, { variant: 'Body2' }, label)));
|
|
15
27
|
};
|
|
@@ -23,23 +23,26 @@
|
|
|
23
23
|
display: inline-block;
|
|
24
24
|
padding: 6px;
|
|
25
25
|
|
|
26
|
-
border: 1px solid var(--
|
|
26
|
+
border: 1px solid var(--border-color);
|
|
27
27
|
border-radius: 3px;
|
|
28
28
|
background-color: var(--white);
|
|
29
|
-
background-clip: content-box;
|
|
30
29
|
position: relative;
|
|
31
30
|
cursor: pointer;
|
|
32
31
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
.input[type="checkbox"]:hover
|
|
36
|
-
|
|
37
|
-
.input[type="checkbox"]:checked:hover::after {
|
|
38
|
-
border-color: var(--blue-main);
|
|
34
|
+
.input[type="checkbox"]:hover {
|
|
35
|
+
border-color: var(--border-color-hover);
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
.input[type="checkbox"]:checked {
|
|
42
|
-
border-color: var(--
|
|
39
|
+
border-color: var(--border-color-checked);
|
|
40
|
+
background-color: var(--background-color-checked);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.input[type="checkbox"]:checked:hover {
|
|
44
|
+
border-color: var(--border-color-hover);
|
|
45
|
+
background-color: var(--background-color-hover);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
.input[type="checkbox"]:checked::after {
|
|
@@ -52,16 +55,26 @@
|
|
|
52
55
|
width: 40%;
|
|
53
56
|
height: 75%;
|
|
54
57
|
|
|
55
|
-
border: solid var(--
|
|
58
|
+
border: solid var(--arrow-color);
|
|
56
59
|
border-width: 0 2px 2px 0;
|
|
57
60
|
background-color: none;
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
.input[type="checkbox"]:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
.input[type="checkbox"]:checked:hover::after {
|
|
64
|
+
border-color: var(--arrow-color-hover);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.input[type="checkbox"]:disabled {
|
|
63
68
|
background-color: var(--white);
|
|
64
|
-
border-color: var(--
|
|
69
|
+
border-color: var(--border-color-disabled);
|
|
65
70
|
cursor: not-allowed;
|
|
66
71
|
box-shadow: none;
|
|
67
72
|
}
|
|
73
|
+
|
|
74
|
+
.input[type="checkbox"]:disabled:checked {
|
|
75
|
+
background-color: var(--background-color-disabled);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.input[type="checkbox"]:disabled:checked:after {
|
|
79
|
+
border-color: var(--arrow-color-disabled);
|
|
80
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styles from './Dialog.module.css';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
export const Dialog = ({ open, maxWidth = 'md', children, style, className, overlay = true, fullWidth = false }) => {
|
|
5
|
+
const isMaxWidthInPx = typeof maxWidth === 'string' && !isNaN(Number(maxWidth.replace('px', '')));
|
|
6
|
+
return (React.createElement(React.Fragment, null,
|
|
7
|
+
open && overlay && React.createElement("div", { className: styles.dialogOverlay }),
|
|
8
|
+
React.createElement("dialog", { open: open, className: classNames(styles['dialog'], !isMaxWidthInPx && styles[`maxWidth--${maxWidth}`], className), style: Object.assign(Object.assign({}, style), { maxWidth: isMaxWidthInPx ? maxWidth : '', width: fullWidth ? '100%' : '' }) },
|
|
9
|
+
React.createElement("div", { className: styles['content'] }, children))));
|
|
10
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.dialogOverlay {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
right: 0;
|
|
6
|
+
bottom: 0;
|
|
7
|
+
background-color: var(--dialog-overlay);
|
|
8
|
+
z-index: 999;
|
|
9
|
+
}
|
|
10
|
+
.dialog {
|
|
11
|
+
border: none;
|
|
12
|
+
border-radius: 15px;
|
|
13
|
+
box-shadow: 0px 4px 16px var(--dialog-overlay);
|
|
14
|
+
padding: 30px;
|
|
15
|
+
background-color: var(--white);
|
|
16
|
+
z-index: 1000;
|
|
17
|
+
position: fixed;
|
|
18
|
+
top: 50%;
|
|
19
|
+
left: 50%;
|
|
20
|
+
transform: translate(-50%, -50%);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.content {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: 1rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.maxWidth--xs {
|
|
30
|
+
max-width: 300px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.maxWidth--sm {
|
|
34
|
+
max-width: 400px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.maxWidth--md {
|
|
38
|
+
max-width: 500px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.maxWidth--lg {
|
|
42
|
+
max-width: 600px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.maxWidth--xl {
|
|
46
|
+
max-width: 800px;
|
|
47
|
+
}
|
|
@@ -3,13 +3,13 @@ import { useDropzone } from 'react-dropzone';
|
|
|
3
3
|
import styles from './FileAttach.module.css';
|
|
4
4
|
import { Typography } from '../Typography/Typography';
|
|
5
5
|
import { IconUpload } from '../../Icons';
|
|
6
|
-
import {
|
|
6
|
+
import { FileItem } from '../FileItem/FileItem';
|
|
7
7
|
import classNames from 'classnames';
|
|
8
8
|
export const FileAttach = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats = {
|
|
9
9
|
'image/*': ['.png', '.gif', '.jpeg', '.jpg'],
|
|
10
10
|
'application/pdf': ['.pdf'],
|
|
11
11
|
'application/msword': ['.doc', '.docx'],
|
|
12
|
-
}, addedFiles, setAddedFiles, disabled = false, className, style, }) => {
|
|
12
|
+
}, addedFiles, setAddedFiles, onDownload, disabled = false, className, style, }) => {
|
|
13
13
|
const [errorFiles, setErrorFiles] = useState([]);
|
|
14
14
|
const fileValidator = (file) => {
|
|
15
15
|
if (file.size > maxFileSize * 1024 * 1024 * 1024) {
|
|
@@ -42,8 +42,8 @@ export const FileAttach = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats
|
|
|
42
42
|
maxFiles: maxFileCount,
|
|
43
43
|
disabled: disabled,
|
|
44
44
|
});
|
|
45
|
-
const acceptedFileItems = addedFiles.map((file, index) => (React.createElement(
|
|
46
|
-
const fileRejectionItems = errorFiles.map(({ file, errors }) => (React.createElement(
|
|
45
|
+
const acceptedFileItems = addedFiles.map((file, index) => (React.createElement(FileItem, { name: file.name, size: file.size, onDelete: () => deleteAcceptedFile(addedFiles, setAddedFiles, file.name), onDownload: onDownload, key: index })));
|
|
46
|
+
const fileRejectionItems = errorFiles.map(({ file, errors }) => (React.createElement(FileItem, { name: file.name, size: file.size, error: errors[0].message, onDelete: () => deleteRejectedFile(errorFiles, setErrorFiles, file.name), key: file.path })));
|
|
47
47
|
const deleteAcceptedFile = (addedFiles, setAddedFiles, fileName) => {
|
|
48
48
|
setAddedFiles(addedFiles.filter((file) => file.name !== fileName));
|
|
49
49
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styles from './FileItem.module.css';
|
|
3
|
+
import { Typography } from '../Typography/Typography';
|
|
4
|
+
import { ProgressBar } from '../ProgressBar/ProgressBar';
|
|
5
|
+
import { IconButton } from '../IconButton/IconButton';
|
|
6
|
+
import { IconClose10, IconDownload, IconFile } from '../../Icons';
|
|
7
|
+
export const FileItem = ({ name, size = 0, loading = false, error = '', onDownload, onDelete }) => {
|
|
8
|
+
return (React.createElement("div", { className: `${styles['fileItem']} ${error ? styles['error'] : ''}` },
|
|
9
|
+
React.createElement("div", { className: styles['fileItemFile'] },
|
|
10
|
+
React.createElement("div", { className: styles['fileItemInfo'] },
|
|
11
|
+
React.createElement("div", { className: styles['fileItemIcon'] },
|
|
12
|
+
React.createElement(IconFile, { htmlColor: 'var(--icons-grey)' })),
|
|
13
|
+
React.createElement("div", { className: styles['fileItemName'] },
|
|
14
|
+
React.createElement(Typography, { variant: "Body1-Medium", color: "var(--text-dark)" }, name),
|
|
15
|
+
size !== 0 && (React.createElement(Typography, { variant: "Caption", color: "var(--grey-medium)" }, `${(size / 1024).toFixed(1)} кБ`)))),
|
|
16
|
+
onDownload && (React.createElement(IconButton, { icon: React.createElement(IconDownload, null), onClick: onDownload, color: 'var(--icons-grey)', className: styles['fileIcon'] })),
|
|
17
|
+
onDelete && (React.createElement(IconButton, { icon: React.createElement(IconClose10, null), onClick: onDelete, color: 'var(--icons-grey)' }))),
|
|
18
|
+
loading && React.createElement(ProgressBar, { animated: true, size: "sm", value: 100 }),
|
|
19
|
+
error && (React.createElement(Typography, { variant: "Caption", color: "var(--error-main)" }, error))));
|
|
20
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
.fileItem {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: 5px;
|
|
6
|
+
justify-content: space-between;
|
|
7
|
+
|
|
8
|
+
padding: 10px 15px;
|
|
9
|
+
border: 1px solid var(--info-secondary);
|
|
10
|
+
border-radius: 10px;
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
.error {
|
|
14
|
+
border-color: var(--error-main);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.fileItemFile{
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: row;
|
|
20
|
+
align-items: center;
|
|
21
|
+
}
|
|
22
|
+
.fileItemInfo {
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: row;
|
|
25
|
+
gap: 5px;
|
|
26
|
+
flex-grow: 1;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.fileItemIcon {
|
|
32
|
+
flex-shrink: 0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.fileItemName {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
flex-grow: 1;
|
|
39
|
+
align-items: flex-start;
|
|
40
|
+
overflow: auto;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.fileIcon svg path {
|
|
44
|
+
stroke-width: 0.8;
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import styles from './IconButton.module.css';
|
|
4
|
+
export const IconButton = ({ icon, size = 'md', color, style, disabled = false, onClick, children, className }) => {
|
|
5
|
+
return (React.createElement("button", { className: classNames(styles['iconButton'], styles[`iconButton--${size}`], className), disabled: disabled, "aria-disabled": disabled, type: "button", onClick: onClick, style: style }, (icon || (typeof children === 'object' && children)) &&
|
|
6
|
+
React.cloneElement(icon, {
|
|
7
|
+
htmlColor: color,
|
|
8
|
+
strokeWidth: size === 'lg' ? '0.5' : size === 'md' ? '0.3' : '0.0',
|
|
9
|
+
})));
|
|
10
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.iconButton {
|
|
2
|
+
cursor: pointer;
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
background-color: var(--white);
|
|
5
|
+
border: none;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.iconButton--sm svg{
|
|
9
|
+
width: 14px;
|
|
10
|
+
height: 14px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.iconButton--md svg{
|
|
14
|
+
width: 16px;
|
|
15
|
+
height: 16px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.iconButton--lg svg{
|
|
19
|
+
width: 18px;
|
|
20
|
+
height: 18px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.iconButton:disabled {
|
|
24
|
+
cursor: not-allowed;
|
|
25
|
+
box-shadow: none;
|
|
26
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import styles from './List.module.css';
|
|
4
|
+
import { Typography } from '../Typography/Typography';
|
|
5
|
+
import { Checkbox } from '../Checkbox/Checkbox';
|
|
6
|
+
import { RadioButton } from '../RadioButton/RadioButton';
|
|
7
|
+
import { ChevronDown10 } from '../../Icons';
|
|
8
|
+
export const List = ({ onClick, onCheck, onRadioSelect, checked = false, selected = false, disabled = false, label, id, collapsible = false, withCheckbox = false, checkboxColor, checkboxFilled, withRadioButton = false, customBullet, customItemBullet, bulletClassName, children, isHeader = false, parentChecked = false, }) => {
|
|
9
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
10
|
+
const [isChecked, setIsChecked] = useState(checked || parentChecked);
|
|
11
|
+
const childIds = [];
|
|
12
|
+
React.Children.forEach(children, (child) => {
|
|
13
|
+
if (React.isValidElement(child) && child.props.id) {
|
|
14
|
+
childIds.push(child.props.id);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
const handleClick = (e) => {
|
|
18
|
+
if (collapsible) {
|
|
19
|
+
setIsOpen(!isOpen);
|
|
20
|
+
}
|
|
21
|
+
if (onClick) {
|
|
22
|
+
onClick();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const handleChildCheck = (childId, isChecked) => {
|
|
26
|
+
if (onCheck) {
|
|
27
|
+
onCheck(childId, isChecked);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const handleChildRadioSelect = (childId) => {
|
|
31
|
+
if (onRadioSelect) {
|
|
32
|
+
onRadioSelect(childId);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const handleCheckboxClick = (e) => {
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
const newCheckedState = !isChecked;
|
|
38
|
+
setIsChecked(newCheckedState);
|
|
39
|
+
if (onCheck) {
|
|
40
|
+
onCheck(id || "", newCheckedState);
|
|
41
|
+
}
|
|
42
|
+
if (childIds.length > 0 && onCheck) {
|
|
43
|
+
childIds.forEach((childId) => {
|
|
44
|
+
onCheck(childId, newCheckedState);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const handleRadioClick = (e) => {
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
if (id && onRadioSelect) {
|
|
51
|
+
onRadioSelect(id);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
setIsChecked(parentChecked || checked);
|
|
56
|
+
}, [parentChecked, checked]);
|
|
57
|
+
const headerClassNames = classNames(styles.header);
|
|
58
|
+
const contentClassNames = classNames(styles.content, isOpen ? styles['content--expanded'] : styles['content--collapsed']);
|
|
59
|
+
return (React.createElement("div", { className: styles.collapsibleList },
|
|
60
|
+
label && (React.createElement("div", { className: headerClassNames, onClick: handleClick },
|
|
61
|
+
!isHeader && (React.createElement("div", null,
|
|
62
|
+
withCheckbox && (React.createElement("span", { onClick: handleCheckboxClick },
|
|
63
|
+
React.createElement(Checkbox, { checked: isChecked, color: checkboxColor, filled: checkboxFilled, disabled: disabled }))),
|
|
64
|
+
withRadioButton && (React.createElement("span", { onClick: handleRadioClick },
|
|
65
|
+
React.createElement(RadioButton, { checked: selected, value: id, disabled: disabled }))),
|
|
66
|
+
customBullet && React.createElement("span", { className: classNames(styles.bullet, bulletClassName) }, customBullet))),
|
|
67
|
+
React.createElement(Typography, { variant: "Body1" }, label),
|
|
68
|
+
collapsible && (React.createElement("span", { className: styles.indicator }, isOpen ? React.createElement(ChevronDown10, null) : React.createElement(ChevronDown10, { rotation: 270 }))))),
|
|
69
|
+
React.createElement("div", { className: collapsible ? contentClassNames : styles.content, style: { paddingLeft: !label ? 0 : '16px' } }, React.Children.map(children, (child) => {
|
|
70
|
+
if (React.isValidElement(child)) {
|
|
71
|
+
return React.cloneElement(child, {
|
|
72
|
+
bulletClassName: classNames(styles.bullet, child.props.bulletClassName || bulletClassName),
|
|
73
|
+
customBullet: child.props.customBullet !== undefined
|
|
74
|
+
? child.props.customBullet
|
|
75
|
+
: customItemBullet !== undefined
|
|
76
|
+
? customItemBullet
|
|
77
|
+
: customBullet,
|
|
78
|
+
withCheckbox: child.props.withCheckbox !== undefined ? child.props.withCheckbox : withCheckbox,
|
|
79
|
+
checkboxFilled: child.props.checkboxFilled !== undefined ? child.props.checkboxFilled : checkboxFilled,
|
|
80
|
+
withRadioButton: child.props.withRadioButton !== undefined ? child.props.withRadioButton : withRadioButton,
|
|
81
|
+
onCheck: handleChildCheck,
|
|
82
|
+
onRadioSelect: handleChildRadioSelect,
|
|
83
|
+
parentChecked: isChecked,
|
|
84
|
+
selected: child.props.selected,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return child;
|
|
88
|
+
}))));
|
|
89
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
.collapsibleList {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.header {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
padding: 8px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.checkbox--active {
|
|
15
|
+
font-weight: bold;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.content {
|
|
19
|
+
transition: max-height 0.3s ease-out;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.content--expanded {
|
|
24
|
+
max-height: fit-content;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.content--collapsed {
|
|
28
|
+
max-height: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.bullet {
|
|
32
|
+
margin-right: 10px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.indicator {
|
|
36
|
+
margin-left: auto;
|
|
37
|
+
font-size: 12px;
|
|
38
|
+
display: flex;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import styles from './ListItem.module.css';
|
|
4
|
+
import { Typography } from '../Typography/Typography';
|
|
5
|
+
import { Checkbox } from '../Checkbox/Checkbox';
|
|
6
|
+
import { RadioButton } from '../RadioButton/RadioButton';
|
|
7
|
+
export const ListItem = ({ id, onClick, onCheck, onRadioSelect, checked = false, selected = false, disabled = false, label, style, className, withCheckbox = false, checkboxColor, checkboxFilled, withRadioButton = false, customBullet, bulletClassName, children, parentChecked, }) => {
|
|
8
|
+
const [isChecked, setIsChecked] = useState(checked || parentChecked);
|
|
9
|
+
const itemClassNames = classNames(className, styles.listItem);
|
|
10
|
+
const handleClick = (e) => {
|
|
11
|
+
if (onClick) {
|
|
12
|
+
e.stopPropagation();
|
|
13
|
+
onClick();
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const handleCheckboxClick = (e) => {
|
|
17
|
+
e.stopPropagation();
|
|
18
|
+
const newCheckedState = !isChecked;
|
|
19
|
+
setIsChecked(newCheckedState);
|
|
20
|
+
if (onCheck) {
|
|
21
|
+
onCheck(id || "", newCheckedState);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const handleRadioClick = (e) => {
|
|
25
|
+
e.stopPropagation();
|
|
26
|
+
if (id && onRadioSelect) {
|
|
27
|
+
onRadioSelect(id);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setIsChecked(parentChecked || checked);
|
|
32
|
+
}, [parentChecked, checked]);
|
|
33
|
+
return (React.createElement("div", { className: itemClassNames, style: style, onClick: handleClick },
|
|
34
|
+
withCheckbox && (React.createElement("span", { className: styles.icon, onClick: handleCheckboxClick },
|
|
35
|
+
React.createElement(Checkbox, { checked: isChecked, color: checkboxColor, filled: checkboxFilled, disabled: disabled }))),
|
|
36
|
+
withRadioButton && (React.createElement("span", { className: styles.icon, onClick: handleRadioClick },
|
|
37
|
+
React.createElement(RadioButton, { checked: selected, value: id, disabled: disabled }))),
|
|
38
|
+
customBullet && React.createElement("span", { className: bulletClassName }, customBullet),
|
|
39
|
+
React.createElement(Typography, { variant: "Body1" }, label),
|
|
40
|
+
children));
|
|
41
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -14,8 +14,14 @@ export { Tabs as Tabs } from './components/Tabs/Tabs';
|
|
|
14
14
|
export { Tag as Tag } from './components/Tag/Tag';
|
|
15
15
|
export { ToggleButton as ToggleButton } from './components/ToggleButton/ToggleButton';
|
|
16
16
|
export { Typography as Typography } from './components/Typography/Typography';
|
|
17
|
-
export {
|
|
17
|
+
export { FileItem as FileItem } from './components/FileItem/FileItem';
|
|
18
18
|
export { FileAttach as FileAttach } from './components/FileAttach/FileAttach';
|
|
19
19
|
export { Spinner as Spinner } from './components/Spinner/Spinner';
|
|
20
|
-
export
|
|
20
|
+
export { Dialog as Dialog } from './components/Dialog/Dialog';
|
|
21
|
+
export { IconButton as IconButton } from './components/IconButton/IconButton';
|
|
22
|
+
export { List as List } from './components/List/List';
|
|
23
|
+
export { ListItem as ListItem } from './components/ListItem/ListItem';
|
|
24
|
+
export { Breadcrumb as Breadcrumb } from './components/Breadcrumb/Breadcrumb';
|
|
25
|
+
export { Breadcrumbs as Breadcrumbs } from './components/Breadcrumbs/Breadcrumbs';
|
|
26
|
+
export type { ButtonProps, InputProps, DateInputProps, TagProps, SettingTagProps, ToggleButtonProps, BaseOptions, TOptions, DropdownProps, TypographyProps, ProgressBarProps, ProgressLoaderProps, RadioProps, TabsProps, ColorPickerProps, SnackbarProps, FileItemProps, FileAttachProps, SpinnerProps, DialogProps, IconButtonProps, BaseListProps, ListProps, ListItemProps, BreadcrumbProps, BreadcrumbsProps, } from './types';
|
|
21
27
|
import './fonts.css';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,13 @@ export { Tabs as Tabs } from './components/Tabs/Tabs';
|
|
|
14
14
|
export { Tag as Tag } from './components/Tag/Tag';
|
|
15
15
|
export { ToggleButton as ToggleButton } from './components/ToggleButton/ToggleButton';
|
|
16
16
|
export { Typography as Typography } from './components/Typography/Typography';
|
|
17
|
-
export {
|
|
17
|
+
export { FileItem as FileItem } from './components/FileItem/FileItem';
|
|
18
18
|
export { FileAttach as FileAttach } from './components/FileAttach/FileAttach';
|
|
19
19
|
export { Spinner as Spinner } from './components/Spinner/Spinner';
|
|
20
|
+
export { Dialog as Dialog } from './components/Dialog/Dialog';
|
|
21
|
+
export { IconButton as IconButton } from './components/IconButton/IconButton';
|
|
22
|
+
export { List as List } from './components/List/List';
|
|
23
|
+
export { ListItem as ListItem } from './components/ListItem/ListItem';
|
|
24
|
+
export { Breadcrumb as Breadcrumb } from './components/Breadcrumb/Breadcrumb';
|
|
25
|
+
export { Breadcrumbs as Breadcrumbs } from './components/Breadcrumbs/Breadcrumbs';
|
|
20
26
|
import './fonts.css';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -278,6 +278,10 @@ export interface CheckboxProps {
|
|
|
278
278
|
size?: 'sm' | 'md';
|
|
279
279
|
/** Текст лейбла */
|
|
280
280
|
label?: string;
|
|
281
|
+
/** Цвет чекбока */
|
|
282
|
+
color?: string;
|
|
283
|
+
/** Заливка */
|
|
284
|
+
filled?: boolean;
|
|
281
285
|
}
|
|
282
286
|
export interface RadioProps {
|
|
283
287
|
/** Значение */
|
|
@@ -348,7 +352,7 @@ export type SnackbarProps = {
|
|
|
348
352
|
/** Функция обработки закрытия сообщения */
|
|
349
353
|
onClose?: () => void;
|
|
350
354
|
};
|
|
351
|
-
export interface
|
|
355
|
+
export interface FileItemProps {
|
|
352
356
|
/** Название файла */
|
|
353
357
|
name?: string;
|
|
354
358
|
/** Размер файла */
|
|
@@ -357,8 +361,12 @@ export interface LoaderProps {
|
|
|
357
361
|
loading?: boolean;
|
|
358
362
|
/** Текст ошибки загрузки файла */
|
|
359
363
|
error?: string;
|
|
360
|
-
/** Функция обработки */
|
|
361
|
-
|
|
364
|
+
/** Функция обработки скачивания файла */
|
|
365
|
+
onDownload?: () => void;
|
|
366
|
+
/** Функция обработки удаления файла */
|
|
367
|
+
onDelete?: () => void;
|
|
368
|
+
/** Стили передаваемые напрямую */
|
|
369
|
+
style?: CSSProperties;
|
|
362
370
|
}
|
|
363
371
|
export interface FileAttachProps {
|
|
364
372
|
/** Максимальный размер файла */
|
|
@@ -371,10 +379,96 @@ export interface FileAttachProps {
|
|
|
371
379
|
addedFiles: File[];
|
|
372
380
|
/**Сосотояние для добавления файлов */
|
|
373
381
|
setAddedFiles: (addedFiles: File[]) => void;
|
|
382
|
+
/** Функция обработки скачивания файла */
|
|
383
|
+
onDownload?: () => void;
|
|
374
384
|
/**Заблокировано добавление файлов*/
|
|
375
385
|
disabled?: boolean;
|
|
376
386
|
/** Дополнительный класс */
|
|
377
387
|
className?: string;
|
|
378
388
|
/** Стили передаваемые напрямую */
|
|
389
|
+
style?: React.CSSProperties;
|
|
390
|
+
}
|
|
391
|
+
export interface DialogProps {
|
|
392
|
+
/** Флаг открытия окна */
|
|
393
|
+
open: boolean;
|
|
394
|
+
/** Максимальная ширина окна */
|
|
395
|
+
maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | string;
|
|
396
|
+
/** Содержимое окна */
|
|
397
|
+
children?: React.ReactNode;
|
|
398
|
+
/** Стили передаваемые напрямую */
|
|
379
399
|
style?: CSSProperties;
|
|
400
|
+
/** Дополнительный класс */
|
|
401
|
+
className?: string;
|
|
402
|
+
/**Задний фон окна */
|
|
403
|
+
overlay?: boolean;
|
|
404
|
+
/**Окно растягивается до максимальной ширины*/
|
|
405
|
+
fullWidth?: boolean;
|
|
406
|
+
}
|
|
407
|
+
export interface IconButtonProps {
|
|
408
|
+
/** Иконка кнопки */
|
|
409
|
+
icon?: React.ReactNode;
|
|
410
|
+
/** Размер кнопки */
|
|
411
|
+
size?: 'sm' | 'md' | 'lg';
|
|
412
|
+
/**Цвет кнопки */
|
|
413
|
+
color?: string;
|
|
414
|
+
/** Стиль кнопки иконки*/
|
|
415
|
+
style?: CSSProperties;
|
|
416
|
+
/** Заблокированная кнопка */
|
|
417
|
+
disabled?: boolean;
|
|
418
|
+
/** Callback, который будет вызван при клике по кнопке */
|
|
419
|
+
onClick: () => void;
|
|
420
|
+
/** Дочерние элементы */
|
|
421
|
+
children?: ReactNode;
|
|
422
|
+
/** Дополнительный класс */
|
|
423
|
+
className?: string;
|
|
424
|
+
}
|
|
425
|
+
export interface BaseListProps {
|
|
426
|
+
/** Идентификатор */
|
|
427
|
+
id?: string;
|
|
428
|
+
/** Обработчик клика */
|
|
429
|
+
onClick?: () => void;
|
|
430
|
+
/** Обработчик выбора чекбокса */
|
|
431
|
+
onCheck?: (activeId: string | string[], isChecked: boolean) => void;
|
|
432
|
+
/** Заблокированный чекбокс/RadioButton */
|
|
433
|
+
disabled?: boolean;
|
|
434
|
+
/** Кастомный цвет чекбокса */
|
|
435
|
+
checkboxColor?: string;
|
|
436
|
+
/** Заливка чекбокса */
|
|
437
|
+
checkboxFilled?: boolean;
|
|
438
|
+
/** Обработчик выбора RadioButton */
|
|
439
|
+
onRadioSelect?: (id: string) => void;
|
|
440
|
+
/** Активный чекбокс */
|
|
441
|
+
checked?: boolean;
|
|
442
|
+
/** Активный чекбокс родительского компонента */
|
|
443
|
+
parentChecked?: boolean;
|
|
444
|
+
/** Выбранный RadioButton */
|
|
445
|
+
selected?: boolean;
|
|
446
|
+
/** Отображаемый текст */
|
|
447
|
+
label?: string;
|
|
448
|
+
/** Добавлен чекбокс */
|
|
449
|
+
withCheckbox?: boolean;
|
|
450
|
+
/** Добавлен RadioButton */
|
|
451
|
+
withRadioButton?: boolean;
|
|
452
|
+
/** Кастомный буллит */
|
|
453
|
+
customBullet?: React.ReactNode;
|
|
454
|
+
/** Стиль кастомного буллита */
|
|
455
|
+
bulletClassName?: string;
|
|
456
|
+
}
|
|
457
|
+
export interface ListItemProps extends BaseListProps {
|
|
458
|
+
/** Стиль элемента списка */
|
|
459
|
+
style?: CSSProperties;
|
|
460
|
+
/** Дополнительный класс */
|
|
461
|
+
className?: string;
|
|
462
|
+
/** Дочерние элементы */
|
|
463
|
+
children?: ReactNode;
|
|
464
|
+
}
|
|
465
|
+
export interface ListProps extends BaseListProps {
|
|
466
|
+
/** Дочерние элементы */
|
|
467
|
+
children: React.ReactElement<ListItemProps> | React.ReactElement<ListItemProps>[];
|
|
468
|
+
/** Возможность раскрытия списка */
|
|
469
|
+
collapsible?: boolean;
|
|
470
|
+
/** Кастомный буллит дочернего компонента */
|
|
471
|
+
customItemBullet?: React.ReactNode;
|
|
472
|
+
/** Внешний компонент без буллитов/чекбоксов */
|
|
473
|
+
isHeader?: boolean;
|
|
380
474
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import styles from './Loader.module.css';
|
|
3
|
-
import { Typography } from '../Typography/Typography';
|
|
4
|
-
import { IconFile } from '../../Icons/IconFile/IconFile';
|
|
5
|
-
import { ProgressBar } from '../ProgressBar/ProgressBar';
|
|
6
|
-
export const Loader = ({ name, size = 0, loading = false, error = '', onClick }) => {
|
|
7
|
-
return (React.createElement("div", { className: `${styles['loader']} ${error ? styles['error'] : ''}` },
|
|
8
|
-
React.createElement("div", { className: styles['loaderFile'] },
|
|
9
|
-
React.createElement("div", { className: styles['loaderInfo'] },
|
|
10
|
-
React.createElement("div", { className: styles['loaderIcon'] },
|
|
11
|
-
React.createElement(IconFile, { htmlColor: 'var(--icons-grey)' })),
|
|
12
|
-
React.createElement("div", { className: styles['loaderName'] },
|
|
13
|
-
React.createElement(Typography, { variant: "Body1-Medium", color: "var(--text-dark)" }, name),
|
|
14
|
-
size !== 0 && (React.createElement(Typography, { variant: "Caption", color: "var(--grey-medium)" }, `${(size / 1024).toFixed(1)} кБ`)))),
|
|
15
|
-
React.createElement("button", { type: "button", "aria-label": "\u0417\u0430\u043A\u0440\u044B\u0442\u044C", title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0444\u0430\u0439\u043B", onClick: onClick })),
|
|
16
|
-
loading && React.createElement(ProgressBar, { animated: true, size: "sm", value: 100 }),
|
|
17
|
-
error && (React.createElement(Typography, { variant: "Caption", color: "var(--error-main)" }, error))));
|
|
18
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
.loader {
|
|
3
|
-
display: flex;
|
|
4
|
-
flex-direction: column;
|
|
5
|
-
gap: 5px;
|
|
6
|
-
justify-content: space-between;
|
|
7
|
-
|
|
8
|
-
padding: 10px 15px;
|
|
9
|
-
border: 1px solid var(--info-secondary);
|
|
10
|
-
border-radius: 10px;
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
.error {
|
|
14
|
-
border-color: var(--error-main);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.loaderFile{
|
|
18
|
-
display: flex;
|
|
19
|
-
flex-direction: row;
|
|
20
|
-
align-items: center;
|
|
21
|
-
gap: 5px;
|
|
22
|
-
}
|
|
23
|
-
.loaderInfo {
|
|
24
|
-
display: flex;
|
|
25
|
-
flex-direction: row;
|
|
26
|
-
gap: 5px;
|
|
27
|
-
flex-grow: 1;
|
|
28
|
-
align-items: flex-start;
|
|
29
|
-
overflow: hidden;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.loaderIcon {
|
|
33
|
-
flex-shrink: 0
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.loaderName {
|
|
37
|
-
display: flex;
|
|
38
|
-
flex-direction: column;
|
|
39
|
-
flex-grow: 1;
|
|
40
|
-
align-items: flex-start;
|
|
41
|
-
overflow: auto;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.loaderButton{
|
|
45
|
-
position: absolute;
|
|
46
|
-
left: 50%;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.loader button[aria-label="Закрыть"] {
|
|
50
|
-
background: none;
|
|
51
|
-
border: none;
|
|
52
|
-
padding: 0;
|
|
53
|
-
cursor: pointer;
|
|
54
|
-
position: relative;
|
|
55
|
-
width: 10px;
|
|
56
|
-
height: 10px;
|
|
57
|
-
flex-shrink: 0
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.loader button[aria-label="Закрыть"]::before,
|
|
61
|
-
.loader button[aria-label="Закрыть"]::after {
|
|
62
|
-
content: '';
|
|
63
|
-
position: absolute;
|
|
64
|
-
top: 50%;
|
|
65
|
-
left: 50%;
|
|
66
|
-
transform: translate(-50%, -50%) rotate(45deg);
|
|
67
|
-
height: 1px;
|
|
68
|
-
width: 100%;
|
|
69
|
-
background-color: var(--icons-grey);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.loader button[aria-label="Закрыть"]::after {
|
|
73
|
-
transform: translate(-50%, -50%) rotate(-45deg);
|
|
74
|
-
}
|
|
75
|
-
|