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.
Files changed (31) hide show
  1. package/dist/Icons/ChevronDown/ChevronDown10.d.ts +1 -0
  2. package/dist/Icons/ChevronDown/ChevronDown10.js +3 -2
  3. package/dist/Icons/IconDownload/IconDownload.d.ts +7 -0
  4. package/dist/Icons/IconDownload/IconDownload.js +5 -0
  5. package/dist/Icons/index.d.ts +1 -0
  6. package/dist/Icons/index.js +1 -0
  7. package/dist/components/Checkbox/Checkbox.js +14 -2
  8. package/dist/components/Checkbox/Checkbox.module.css +25 -12
  9. package/dist/components/Dialog/Dialog.d.ts +3 -0
  10. package/dist/components/Dialog/Dialog.js +10 -0
  11. package/dist/components/Dialog/Dialog.module.css +47 -0
  12. package/dist/components/FileAttach/FileAttach.js +4 -4
  13. package/dist/components/FileItem/FileItem.d.ts +3 -0
  14. package/dist/components/FileItem/FileItem.js +20 -0
  15. package/dist/components/FileItem/FileItem.module.css +45 -0
  16. package/dist/components/IconButton/IconButton.d.ts +3 -0
  17. package/dist/components/IconButton/IconButton.js +10 -0
  18. package/dist/components/IconButton/IconButton.module.css +26 -0
  19. package/dist/components/List/List.d.ts +3 -0
  20. package/dist/components/List/List.js +89 -0
  21. package/dist/components/List/List.module.css +40 -0
  22. package/dist/components/ListItem/ListItem.d.ts +3 -0
  23. package/dist/components/ListItem/ListItem.js +41 -0
  24. package/dist/components/ListItem/ListItem.module.css +6 -0
  25. package/dist/index.d.ts +8 -2
  26. package/dist/index.js +7 -1
  27. package/dist/types/index.d.ts +97 -3
  28. package/package.json +1 -1
  29. package/dist/components/Loader/Loader.d.ts +0 -3
  30. package/dist/components/Loader/Loader.js +0 -18
  31. package/dist/components/Loader/Loader.module.css +0 -75
@@ -3,4 +3,5 @@ export declare const ChevronDown10: FC<{
3
3
  color?: string;
4
4
  htmlColor?: string;
5
5
  strokeWidth?: string;
6
+ rotation?: number;
6
7
  }>;
@@ -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("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" })));
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,7 @@
1
+ import React, { FC } from 'react';
2
+ export declare const IconDownload: FC<{
3
+ color?: string;
4
+ htmlColor?: string;
5
+ strokeWidth?: string;
6
+ onClick?: (event: React.MouseEvent<SVGSVGElement>) => void;
7
+ }>;
@@ -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
+ };
@@ -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';
@@ -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
- return (React.createElement("label", { className: styles.checkbox },
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(--icons-active);
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
- .input[type="checkbox"]:checked:hover,
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(--icons-medium);
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(--icons-medium);
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"]:disabled,
61
- .input[type="checkbox"]:disabled:checked,
62
- .input[type="checkbox"]:disabled:checked:after {
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(--icons-light);
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,3 @@
1
+ import { FC } from 'react';
2
+ import { DialogProps } from '../../types';
3
+ export declare const Dialog: FC<DialogProps>;
@@ -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 { Loader } from '../Loader/Loader';
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(Loader, { name: file.name, size: file.size, onClick: () => deleteAcceptedFile(addedFiles, setAddedFiles, file.name), key: index })));
46
- const fileRejectionItems = errorFiles.map(({ file, errors }) => (React.createElement(Loader, { name: file.name, size: file.size, error: errors[0].message, onClick: () => deleteRejectedFile(errorFiles, setErrorFiles, file.name), key: file.path })));
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,3 @@
1
+ import { FC } from 'react';
2
+ import { FileItemProps } from '../../types';
3
+ export declare const FileItem: FC<FileItemProps>;
@@ -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,3 @@
1
+ import React from 'react';
2
+ import { IconButtonProps } from '../../types';
3
+ export declare const IconButton: React.FC<IconButtonProps>;
@@ -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,3 @@
1
+ import { FC } from 'react';
2
+ import { ListProps } from '../../types';
3
+ export declare const List: FC<ListProps>;
@@ -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,3 @@
1
+ import { FC } from 'react';
2
+ import { ListItemProps } from '../../types';
3
+ export declare const ListItem: FC<ListItemProps>;
@@ -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
+ };
@@ -0,0 +1,6 @@
1
+ .listItem {
2
+ display: flex;
3
+ align-items: center;
4
+ padding: 8px;
5
+ cursor: pointer;
6
+ }
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 { Loader as Loader } from './components/Loader/Loader';
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 type { ButtonProps, InputProps, DateInputProps, TagProps, SettingTagProps, ToggleButtonProps, BaseOptions, TOptions, DropdownProps, TypographyProps, ProgressBarProps, ProgressLoaderProps, RadioProps, TabsProps, ColorPickerProps, SnackbarProps, LoaderProps, FileAttachProps, SpinnerProps } from './types';
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 { Loader as Loader } from './components/Loader/Loader';
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';
@@ -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 LoaderProps {
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
- onClick?: () => void;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "kamotive_ui",
3
- "version": "1.2.12",
3
+ "version": "1.2.14",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -1,3 +0,0 @@
1
- import { FC } from 'react';
2
- import { LoaderProps } from '../../types';
3
- export declare const Loader: FC<LoaderProps>;
@@ -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
-