kamotive_ui 2.10.5 → 4.12.25

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.
@@ -3,9 +3,10 @@ export interface FilePreview {
3
3
  file: File;
4
4
  id: string;
5
5
  preview?: string;
6
+ lng: string;
6
7
  }
7
8
  export declare const getFileIcon: (file: File) => React.JSX.Element;
8
- export declare const formatFileSize: (bytes?: number) => string;
9
+ export declare const formatFileSize: (bytes?: number, lng?: string) => string;
9
10
  interface AttachedFilesProps {
10
11
  files: FilePreview[];
11
12
  onDelete?: (id: string) => void;
@@ -14,6 +15,7 @@ interface AttachedFilesProps {
14
15
  className?: string;
15
16
  isEdit?: boolean;
16
17
  allowDownload?: boolean;
18
+ lng: string;
17
19
  }
18
20
  export declare const AttachedFilesPreview: React.FC<AttachedFilesProps>;
19
21
  export {};
@@ -31,15 +31,18 @@ export const getFileIcon = (file) => {
31
31
  return React.createElement(IconFileDefault, null);
32
32
  };
33
33
  // Функция для форматирования размера файла
34
- export const formatFileSize = (bytes) => {
35
- if (!bytes || bytes === 0)
36
- return '0 Bytes';
34
+ export const formatFileSize = (bytes, lng) => {
35
+ if (!bytes || bytes === 0) {
36
+ return lng === 'ru' || (lng === null || lng === void 0 ? void 0 : lng.includes('ru')) ? '0 Байт' : '0 Bytes';
37
+ }
37
38
  const k = 1024;
38
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
39
+ const sizesEn = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
40
+ const sizesRu = ['Байт', 'КБ', 'МБ', 'ГБ', 'ТБ'];
39
41
  const i = Math.floor(Math.log(bytes) / Math.log(k));
42
+ const sizes = lng === 'ru' || (lng === null || lng === void 0 ? void 0 : lng.includes('ru')) ? sizesRu : sizesEn;
40
43
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
41
44
  };
42
- export const AttachedFilesPreview = ({ files, onDelete, onDownload, style, className, isEdit, allowDownload = true, }) => {
45
+ export const AttachedFilesPreview = ({ files, onDelete, onDownload, style, className, isEdit, allowDownload = true, lng, }) => {
43
46
  const handleDelete = (event, id) => {
44
47
  event.stopPropagation();
45
48
  if (onDelete) {
@@ -65,5 +68,5 @@ export const AttachedFilesPreview = ({ files, onDelete, onDownload, style, class
65
68
  React.createElement("div", { onClick: allowDownload ? () => handleDownload(file.file) : undefined, className: styles.filePreview },
66
69
  file.preview ? (React.createElement("img", { src: file.preview, alt: file.file.name, className: styles.previewImage })) : (React.createElement("div", { className: styles.previewImage }, getFileIcon(file.file))),
67
70
  isEdit && (React.createElement("button", { className: styles.removeFileButton, onClick: (event) => handleDelete(event, file.id) }, "\u2715")),
68
- React.createElement("div", { className: styles.fileSize }, formatFileSize(file.file.size))))))));
71
+ React.createElement("div", { className: styles.fileSize }, formatFileSize(file.file.size, lng))))))));
69
72
  };
@@ -6,7 +6,7 @@ import { TextEditor } from '../TextEditor/TextEditor';
6
6
  import { AttachedFilesPreview } from '../AttachedFilesPreview/AttachedFilesPreview';
7
7
  import { IconAccount, IconDeleteFilled, IconPencilFilled } from '../../Icons';
8
8
  import { IconButton } from '../IconButton/IconButton';
9
- export const Comment = ({ id, value, style, className, username, avatar, creationDate, canAttachFiles = false, files = [], canEdit = false, isEdit = false, label, error = false, helperText, onChange, onSubmit, onDelete, }) => {
9
+ export const Comment = ({ id, value, style, className, username, avatar, creationDate, canAttachFiles = false, files = [], canEdit = false, isEdit = false, label, error = false, helperText, onChange, onSubmit, onDelete, lng = 'ru', }) => {
10
10
  const [commentText, setCommentText] = useState(value || '');
11
11
  const [isEditMode, setIsEditMode] = useState(isEdit);
12
12
  const [attachedFiles, setAttachedFiles] = useState(files);
@@ -45,10 +45,10 @@ export const Comment = ({ id, value, style, className, username, avatar, creatio
45
45
  React.createElement(Typography, { variant: "Body2-Medium", className: labelClasses }, username),
46
46
  React.createElement(Typography, { variant: "Caption", className: styles.label, style: { color: '#8E8E93' } }, creationDate))),
47
47
  canEdit && (React.createElement("div", { className: styles.iconsWrapper },
48
- React.createElement(IconButton, { icon: React.createElement(IconPencilFilled, null), onClick: handleEditClick, size: "sm", style: { aspectRatio: 0 } }),
49
- React.createElement(IconButton, { icon: React.createElement(IconDeleteFilled, null), onClick: handleDeleteClick, size: "sm", style: { aspectRatio: 0 } })))),
50
- isEditMode ? (React.createElement(TextEditor, { defaultValue: commentText, onSubmit: handleSubmit, onChange: handleChange, error: error, helperText: helperText, files: attachedFiles, canAttachFiles: canAttachFiles })) : (React.createElement("div", { className: styles.commentWrapper },
51
- attachedFiles.length > 0 && (React.createElement(AttachedFilesPreview, { files: attachedFiles, className: styles.attachedFilesContainer })),
48
+ React.createElement(IconButton, { icon: React.createElement(IconPencilFilled, null), onClick: handleEditClick, size: "sm", style: { aspectRatio: 0, width: '30px', height: '30px' } }),
49
+ React.createElement(IconButton, { icon: React.createElement(IconDeleteFilled, null), onClick: handleDeleteClick, size: "sm", style: { aspectRatio: 0, width: '30px', height: '30px' } })))),
50
+ isEditMode ? (React.createElement(TextEditor, { defaultValue: commentText, onSubmit: handleSubmit, onChange: handleChange, error: error, helperText: helperText, files: attachedFiles, canAttachFiles: canAttachFiles, lng: lng })) : (React.createElement("div", { className: styles.commentWrapper },
51
+ attachedFiles.length > 0 && (React.createElement(AttachedFilesPreview, { files: attachedFiles, className: styles.attachedFilesContainer, lng: lng })),
52
52
  React.createElement("div", { id: id, className: inputClassess, dangerouslySetInnerHTML: { __html: commentText || '' } }))),
53
53
  error && helperText && (React.createElement(Typography, { variant: "Caption", className: classNames(styles.helperText) }, helperText))));
54
54
  };
@@ -25,7 +25,7 @@
25
25
  .iconsWrapper {
26
26
  display: flex;
27
27
  flex-direction: row;
28
- gap: 15px;
28
+ gap: 5px;
29
29
  }
30
30
 
31
31
  .commentWrapper {
@@ -168,11 +168,11 @@ export const DropdownListItem = ({ item, getOptionLabel, size = 'md', selectedIt
168
168
  (item === null || item === void 0 ? void 0 : item.isDivider) && React.createElement("div", { className: styles.divider })),
169
169
  hasChildren && (React.createElement("div", { className: styles.nestedMenu }, (_a = item.children) === null || _a === void 0 ? void 0 : _a.map((child, childIndex) => {
170
170
  var _a;
171
- return (React.createElement(DropdownListItem, { key: (_a = child === null || child === void 0 ? void 0 : child.key) !== null && _a !== void 0 ? _a : `${index}-${childIndex}`, item: child, getOptionLabel: getOptionLabel, size: size, selectedItem: selectedItem, onChange: onChange, isActive: false, activeIndex: activeIndex, index: childIndex, isChild: true }));
171
+ return (React.createElement(DropdownListItem, { key: (_a = child === null || child === void 0 ? void 0 : child.id) !== null && _a !== void 0 ? _a : `${index}-${childIndex}`, item: child, getOptionLabel: getOptionLabel, size: size, selectedItem: selectedItem, onChange: onChange, isActive: false, activeIndex: activeIndex, index: childIndex, isChild: true }));
172
172
  })))));
173
173
  return showTooltip ? (React.createElement(Tooltip, { label: ((_b = getComparisonValue(item, getOptionLabel)) === null || _b === void 0 ? void 0 : _b.toString()) || '', position: "bottom-left" }, itemContent)) : (itemContent);
174
174
  };
175
- export const Dropdown = ({ options, id, label, placeholder, required = false, value, defaultValue, onChange, getOptionLabel, variant = 'text', size = 'lg', style, className, isLeftLabel = false, isDivider = false, disabled = false, readOnly = false, isOpened = false, error = false, helperText, onClick, onBlur, onFocus, onClose, clearable = true, enableAutocomplete = false, noOptionsText = 'Нет вариантов для выбора', lng = 'ru', }) => {
175
+ export const Dropdown = ({ options, id, label, placeholder, required = false, value, defaultValue, onChange, showLoadMore = false, loadMore, getOptionLabel, variant = 'text', size = 'lg', style, className, isLeftLabel = false, isDivider = false, disabled = false, readOnly = false, isOpened = false, error = false, helperText, onClick, onBlur, onFocus, onClose, clearable = true, enableAutocomplete = false, noOptionsText = 'Нет вариантов для выбора', lng = 'ru', }) => {
176
176
  const [isOpen, setIsOpen] = useState(isOpened);
177
177
  const [modifiedOptions, setModifiedOptions] = useState([]);
178
178
  const [selectedItem, setSelectedItem] = useState(null);
@@ -373,12 +373,18 @@ export const Dropdown = ({ options, id, label, placeholder, required = false, va
373
373
  };
374
374
  const getDropdownMenu = () => {
375
375
  const optionsToRender = enableAutocomplete && searchValue ? filteredOptions : modifiedOptions;
376
- const menu = isOpen && (React.createElement("div", { className: dropdownClassess }, optionsToRender && optionsToRender.length > 0 ? (optionsToRender.map((optionsToRender, index) => {
377
- var _a;
378
- return (React.createElement(DropdownListItem, { key: (_a = optionsToRender === null || optionsToRender === void 0 ? void 0 : optionsToRender.key) !== null && _a !== void 0 ? _a : index, item: optionsToRender, getOptionLabel: getOptionLabel, size: size, selectedItem: selectedItem, variant: variant, onChange: onChangeHandler, isActive: activeIndex === index, activeIndex: activeIndex, index: index }));
379
- })) : (React.createElement("div", { className: `${styles['item-container']} ${styles['item-block']}`, style: { paddingLeft: '15px' } }, lng === 'ru' || lng.includes('ru')
380
- ? noOptionsText || 'Нет вариантов для выбора'
381
- : noOptionsText || 'No options to select'))));
376
+ const menu = isOpen && (React.createElement("div", { className: dropdownClassess },
377
+ optionsToRender && optionsToRender.length > 0 ? (optionsToRender.map((optionsToRender, index) => {
378
+ var _a;
379
+ return (React.createElement(DropdownListItem, { key: (_a = optionsToRender === null || optionsToRender === void 0 ? void 0 : optionsToRender.id) !== null && _a !== void 0 ? _a : index, item: optionsToRender, getOptionLabel: getOptionLabel, size: size, selectedItem: selectedItem, variant: variant, onChange: onChangeHandler, isActive: activeIndex === index, activeIndex: activeIndex, index: index }));
380
+ })) : (React.createElement("div", { className: `${styles['item-container']} ${styles['item-block']}`, style: { paddingLeft: '15px' } }, lng === 'ru' || lng.includes('ru')
381
+ ? noOptionsText || 'Нет вариантов для выбора'
382
+ : noOptionsText || 'No options to select')),
383
+ showLoadMore && loadMore && React.createElement("div", { className: styles[`loadMore`], onClick: (e) => {
384
+ e.stopPropagation();
385
+ e.preventDefault();
386
+ loadMore();
387
+ } }, 'Загрузить еще')));
382
388
  return isOpen ? menu : null;
383
389
  };
384
390
  useEffect(() => {
@@ -337,3 +337,16 @@
337
337
  grid-template-columns: 1fr 20px;
338
338
  justify-content: space-between;
339
339
  }
340
+ /* Кнопка Загрузить еще */
341
+ .loadMore {
342
+ /* align-self: flex-end; */
343
+ padding: 6px;
344
+ margin-left: 10px;
345
+ font-size: 12px;
346
+ color: var(--blue-secondary);
347
+ cursor: pointer;
348
+
349
+ }
350
+ .loadMore:hover {
351
+ color: var(--blue-dark);
352
+ }
@@ -7,6 +7,9 @@ export const FileAttach = ({ filesList = [], maxFileSize = 2, maxFileCount = 10,
7
7
  'image/*': ['.png', '.gif', '.jpeg', '.jpg'],
8
8
  'application/pdf': ['.pdf'],
9
9
  'application/msword': ['.doc', '.docx'],
10
+ 'model/gltf-binary': ['.glb'],
11
+ 'application/octet-stream': ['.prt', '.step', '.stp'],
12
+ 'text/plain': ['.syslog'],
10
13
  }, addedFiles, setAddedFiles, onDownload, onDelete, canAdd = true, canDelete = true, canDownload = true, position = 'bottom', lng = 'ru', className, style, fileValidator, }) => {
11
14
  const fileAttachClasses = classNames(styles['fileAttach'], className, {
12
15
  [styles[`fileAttach_position_${position}`]]: position,
@@ -7,7 +7,7 @@ import { IconClose, IconDownload, IconFile } from '../../Icons';
7
7
  import { Tooltip } from '../Tooltip/Tooltip';
8
8
  import classNames from 'classnames';
9
9
  import { formatFileSize } from '../AttachedFilesPreview/AttachedFilesPreview';
10
- export const FileItem = ({ file, loading = false, error = '', onDownload, onDelete, canDelete = true, canDownload = true, style, isAddedFile, isRejectedFile, progressBarWidth }) => {
10
+ export const FileItem = ({ file, loading = false, error = '', onDownload, onDelete, canDelete = true, canDownload = true, style, isAddedFile, isRejectedFile, progressBarWidth, lng }) => {
11
11
  const [isLoadingFinished, setIsLoadingFinished] = useState(false);
12
12
  const [animationDuration, setAnimationDuration] = useState(0);
13
13
  const [maxLength, setMaxLength] = useState(30);
@@ -103,7 +103,7 @@ export const FileItem = ({ file, loading = false, error = '', onDownload, onDele
103
103
  React.createElement("div", { className: styles['fileItemName'], ref: fileNameRef },
104
104
  file.filename.length > maxLength ? (React.createElement(Tooltip, { label: file.filename, position: "bottom-center", displayDelay: 300 },
105
105
  React.createElement(Typography, { variant: "Body1", color: "var(--text-dark)" }, croppedName(file.filename)))) : (React.createElement(Typography, { variant: "Body1", color: "var(--text-dark)" }, croppedName(file.filename))),
106
- file.size !== 0 && (React.createElement(Typography, { variant: "Caption", color: "var(--grey-medium)" }, formatFileSize(file.size))))),
106
+ file.size !== 0 && (React.createElement(Typography, { variant: "Caption", color: "var(--grey-medium)" }, formatFileSize(file.size, lng))))),
107
107
  React.createElement("div", { className: styles['fileItemActions'] },
108
108
  !(isAddedFile || isRejectedFile) && canDownload && (React.createElement(IconButton, { className: styles.fileIcon, icon: React.createElement(IconDownload, null), onClick: (e) => handleDownloadClick(e, file), color: "var(--icons-grey)", size: "sm" })),
109
109
  canDelete && (React.createElement(IconButton, { className: styles.fileIcon, icon: React.createElement(IconClose, null), onClick: (e) => handleDeleteClick(e, file.id || ''), color: "var(--icons-grey)", size: "sm" })))),
@@ -10,5 +10,5 @@ export const FileListAttaсhed = ({ filesList, onDelete, onDownload, canDelete,
10
10
  return (React.createElement("div", { className: classNames(styles['fileList'], className), style: style },
11
11
  isInfoShown &&
12
12
  (lng === 'ru' || lng.includes('ru') ? (React.createElement(Typography, { variant: "Body2-SemiBold", color: "var(--text-dark)", style: { lineHeight: '20px' }, className: styles['fileListHeader'] }, `Прикрепленные файлы (${filesList.length})`)) : (React.createElement(Typography, { variant: "Body2-SemiBold", color: "var(--text-dark)", style: { lineHeight: '20px' }, className: styles['fileListHeader'] }, `Attached files (${filesList.length})`))),
13
- React.createElement("div", { className: styles['fileListFiles'] }, filesList.map((file) => (React.createElement(FileItem, { key: file.id, file: file, onDownload: onDownload, onDelete: onDelete, canDelete: canDelete, canDownload: canDownload }))))));
13
+ React.createElement("div", { className: styles['fileListFiles'] }, filesList.map((file) => (React.createElement(FileItem, { key: file.id, file: file, onDownload: onDownload, onDelete: onDelete, canDelete: canDelete, canDownload: canDownload, lng: lng }))))));
14
14
  };
@@ -1,3 +1,3 @@
1
- import { FC } from 'react';
2
- import { FileLoaderProps } from '../../types';
3
- export declare const FileLoader: FC<FileLoaderProps>;
1
+ import React from 'react';
2
+ import { FileLoaderHandle, FileLoaderProps } from '../../types';
3
+ export declare const FileLoader: React.ForwardRefExoticComponent<FileLoaderProps & React.RefAttributes<FileLoaderHandle>>;
@@ -1,19 +1,30 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
2
2
  import { useDropzone } from 'react-dropzone';
3
3
  import styles from './FileLoader.module.css';
4
4
  import { Typography } from '../Typography/Typography';
5
5
  import { IconUpload } from '../../Icons';
6
6
  import { FileItem } from '../FileItem/FileItem';
7
7
  import classNames from 'classnames';
8
- export const FileLoader = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats = {
8
+ export const FileLoader = forwardRef(({ maxFileSize = 2, maxFileCount = 10, acceptedFormats = {
9
9
  'image/*': ['.png', '.gif', '.jpeg', '.jpg'],
10
10
  'application/pdf': ['.pdf'],
11
- 'application/msword': ['.doc', '.docx'],
12
- }, addedFiles, setAddedFiles, filesList = [], canAdd = true, lng = 'ru', className, style, fileValidator, progressBarWidth }) => {
11
+ 'application/msword': ['.doc', '.docx', '.log', '.syslog', '.txt'],
12
+ }, rejectedFormats, addedFiles, setAddedFiles, filesList = [], canAdd = true, lng = 'ru', className, style, fileValidator, progressBarWidth }, ref) => {
13
13
  const [isLoadingFiles, setIsLoadingFiles] = useState(false);
14
14
  const [loadingFilesNames, setLoadingFilesNames] = useState([]);
15
15
  const [errorFiles, setErrorFiles] = useState([]);
16
16
  const [addedFilesFormated, setAddedFilesFormatted] = useState([]);
17
+ useImperativeHandle(ref, () => ({
18
+ clearErrorFiles: () => {
19
+ setErrorFiles([]);
20
+ },
21
+ clearAllFiles: () => {
22
+ setErrorFiles([]);
23
+ setAddedFiles([]);
24
+ setAddedFilesFormatted([]);
25
+ setLoadingFilesNames([]);
26
+ }
27
+ }));
17
28
  const fileValidatorInner = (file) => {
18
29
  if (file.size > maxFileSize * 1024 * 1024 * 1024) {
19
30
  return {
@@ -43,7 +54,7 @@ export const FileLoader = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats
43
54
  message: lng === 'ru' || lng.includes('ru') ? `Максимальное количество файлов ${maxFileCount}` : `Maximum number of files ${maxFileCount}`,
44
55
  };
45
56
  }
46
- if (acceptedFormats) {
57
+ if (acceptedFormats && !rejectedFormats) {
47
58
  const acceptedExtensions = Object.values(acceptedFormats)
48
59
  .reduce((acc, val) => acc.concat(val), []);
49
60
  const fileParts = file.name.split('.');
@@ -59,6 +70,22 @@ export const FileLoader = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats
59
70
  };
60
71
  }
61
72
  }
73
+ if (rejectedFormats) {
74
+ const rejectedExtensions = Object.values(rejectedFormats)
75
+ .reduce((acc, val) => acc.concat(val), []);
76
+ const fileParts = file.name.split('.');
77
+ const fileExtension = fileParts.length > 1
78
+ ? `.${fileParts.pop().toLowerCase()}`
79
+ : '';
80
+ if (rejectedExtensions.includes(fileExtension)) {
81
+ return {
82
+ code: 'file-invalid-type',
83
+ message: lng === 'ru' || lng.includes('ru')
84
+ ? `Файл не должен быть одного из следующих типов: ${getAcceptedFormatsString(rejectedFormats)}`
85
+ : `File must not be one of: ${getAcceptedFormatsString(rejectedFormats)}`,
86
+ };
87
+ }
88
+ }
62
89
  if (fileValidator) {
63
90
  const customValidationResult = fileValidator(file);
64
91
  if (customValidationResult) {
@@ -141,21 +168,23 @@ export const FileLoader = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats
141
168
  setLoadingFilesNames(loadingFilesNames.filter((id) => id !== id));
142
169
  };
143
170
  const acceptedFileItems = addedFilesFormated.map((file) => {
144
- return (React.createElement(FileItem, { key: file.id, file: file, loading: loadingFilesNames.includes(file.filename), onDelete: handleDeleteFiles, isAddedFile: true, progressBarWidth: progressBarWidth }));
171
+ return (React.createElement(FileItem, { key: file.id, file: file, loading: loadingFilesNames.includes(file.filename), onDelete: handleDeleteFiles, isAddedFile: true, progressBarWidth: progressBarWidth, lng: lng }));
145
172
  });
146
173
  const handleDeleteRejectedFile = (id) => {
147
174
  setErrorFiles(errorFiles.filter((rejection) => rejection.file.id !== id));
148
175
  };
149
- const fileRejectionItems = errorFiles.map(({ file, errors }) => (React.createElement(FileItem, { key: file.id, file: file, error: errors[0].message, onDelete: handleDeleteRejectedFile, isRejectedFile: true })));
176
+ const fileRejectionItems = errorFiles.map(({ file, errors }) => (React.createElement(FileItem, { key: file.id, file: file, error: errors[0].message, onDelete: handleDeleteRejectedFile, isRejectedFile: true, lng: lng })));
150
177
  // Функция для получения всех доступных форматов в виде строки
151
178
  const getAcceptedFormatsString = (acceptedFormats) => {
152
- const formats = [];
179
+ const uniqueFormats = new Set();
153
180
  for (const key in acceptedFormats) {
154
181
  if (acceptedFormats.hasOwnProperty(key)) {
155
- formats.push(...acceptedFormats[key].map((format) => format.replace('.', '')));
182
+ acceptedFormats[key].forEach((format) => {
183
+ uniqueFormats.add(format.replace('.', ''));
184
+ });
156
185
  }
157
186
  }
158
- return formats.join(', ');
187
+ return Array.from(uniqueFormats).join(', ');
159
188
  };
160
189
  useEffect(() => {
161
190
  if (addedFiles.length === 0) {
@@ -189,9 +218,9 @@ export const FileLoader = ({ maxFileSize = 2, maxFileCount = 10, acceptedFormats
189
218
  React.createElement("br", null)))),
190
219
  maxFileCount &&
191
220
  (lng === 'ru' || lng.includes('ru') ? (React.createElement(Typography, { variant: "Body2", color: "var(--grey-medium)" }, `За раз можно загрузить ${maxFileCount} ${maxFileCount > 1 ? `файлов` : `файл`}`)) : (React.createElement(Typography, { variant: "Body2", color: "var(--grey-medium)" }, `You can upload ${maxFileCount} ${maxFileCount > 1 ? `files` : `file`}`))))),
192
- acceptedFormats &&
193
- (lng === 'ru' || lng.includes('ru') ? (React.createElement(Typography, { variant: "Body2", color: "var(--grey-medium)" }, `Поддерживаемые форматы: ${getAcceptedFormatsString(acceptedFormats)}`)) : (React.createElement(Typography, { variant: "Body2", color: "var(--grey-medium)" }, `Supported formats: ${getAcceptedFormatsString(acceptedFormats)}`))),
221
+ acceptedFormats && !rejectedFormats && (React.createElement(Typography, { variant: "Body2", color: "var(--grey-medium)" }, `${lng === 'ru' || lng.includes('ru') ? 'Поддерживаемые форматы:' : 'Supported formats:'} ${getAcceptedFormatsString(acceptedFormats)}`)),
222
+ rejectedFormats && (React.createElement(Typography, { variant: "Body2", color: "var(--grey-medium)" }, `${lng === 'ru' || lng.includes('ru') ? 'Неподдерживаемые форматы:' : 'Unsupported formats:'} ${getAcceptedFormatsString(rejectedFormats)}`)),
194
223
  (addedFiles === null || addedFiles === void 0 ? void 0 : addedFiles.length) > 0 || (errorFiles === null || errorFiles === void 0 ? void 0 : errorFiles.length) > 0 ? (React.createElement("div", { className: styles['addedFiles'] },
195
224
  acceptedFileItems,
196
225
  fileRejectionItems)) : lng === 'ru' || lng.includes('ru') ? (React.createElement(Typography, { variant: "Body2-SemiBold", color: "var(--grey-medium)", style: { marginTop: '5px' } }, "\u0424\u0430\u0439\u043B\u044B \u043D\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B")) : (React.createElement(Typography, { variant: "Body2-SemiBold", color: "var(--grey-medium)", style: { marginTop: '5px' } }, "Files not added"))));
197
- };
226
+ });
@@ -7,6 +7,7 @@
7
7
  align-items: center;
8
8
  justify-content: center;
9
9
  aspect-ratio: 1 / 1;
10
+ border-radius: var(--default-border-radius, 50%);
10
11
  }
11
12
 
12
13
  .iconButton--sm svg {
@@ -23,7 +23,7 @@ const getElementFromRange = (range) => {
23
23
  const container = range.commonAncestorContainer;
24
24
  return container.nodeType === Node.TEXT_NODE ? container.parentElement : container;
25
25
  };
26
- export const TextEditor = ({ label, onSubmit, onChange, defaultValue, error, helperText, canAttachFiles = false, files, required, className, isButtonDisabled, }) => {
26
+ export const TextEditor = ({ label, onSubmit, onChange, defaultValue, error, helperText, canAttachFiles = false, files, required, className, isButtonDisabled, lng = 'ru', }) => {
27
27
  const editorRef = useRef(null);
28
28
  const uploaderRef = useRef(null);
29
29
  const submitButtonRef = useRef(null);
@@ -293,6 +293,7 @@ export const TextEditor = ({ label, onSubmit, onChange, defaultValue, error, hel
293
293
  file,
294
294
  id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
295
295
  preview: file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined,
296
+ lng,
296
297
  }));
297
298
  setAttachedFiles((prev) => [...prev, ...newAttachedFiles]);
298
299
  event.target.value = '';
@@ -535,7 +536,7 @@ export const TextEditor = ({ label, onSubmit, onChange, defaultValue, error, hel
535
536
  return (React.createElement("div", { className: wrapperClassess },
536
537
  label && (React.createElement(Typography, { variant: "Caption", className: labelClasses }, label)),
537
538
  React.createElement("div", { className: inputClassess },
538
- attachedFiles.length > 0 && (React.createElement(AttachedFilesPreview, { files: attachedFiles, onDelete: (id) => removeAttachedFile(id), className: styles.attachedFilesContainer, isEdit: true })),
539
+ attachedFiles.length > 0 && (React.createElement(AttachedFilesPreview, { files: attachedFiles, onDelete: (id) => removeAttachedFile(id), className: styles.attachedFilesContainer, isEdit: true, lng: lng })),
539
540
  React.createElement("div", { ref: editorRef }),
540
541
  canAttachFiles && (React.createElement("input", { ref: uploaderRef, type: "file", style: { display: 'none' }, multiple: true, onChange: handleUploadFiles, accept: ACCEPTED_FILE_TYPES }))),
541
542
  error && helperText && (React.createElement(Typography, { variant: "Caption", className: classNames(styles.helperText) }, helperText))));
@@ -186,6 +186,10 @@ export interface DropdownProps {
186
186
  defaultValue?: string | number | TOptions | null;
187
187
  /** Callback, который будет вызван при изменении значения */
188
188
  onChange?: (event: any, value: string | number | TOptions | null) => void;
189
+ /** Флаг, является ли выпадающий список пагинированным */
190
+ showLoadMore?: boolean;
191
+ /** Функция для загрузки списка при пагинированных данных */
192
+ loadMore?: () => void;
189
193
  /** Функция для получения текста опции */
190
194
  getOptionLabel?: (option: TOptions) => string;
191
195
  /** Вариaнты выпадающего списка(текст + иконка, текст)' */
@@ -453,6 +457,8 @@ export interface FileItemProps {
453
457
  isRejectedFile?: boolean;
454
458
  /** Ширина прогресс бара */
455
459
  progressBarWidth?: string;
460
+ /** Язык интерфейса для типов данных*/
461
+ lng?: string;
456
462
  }
457
463
  export interface FileLoaderProps {
458
464
  /** Максимальный размер файла */
@@ -461,6 +467,8 @@ export interface FileLoaderProps {
461
467
  maxFileCount?: number;
462
468
  /**Поддерживаемые форматы файлов */
463
469
  acceptedFormats?: Accept;
470
+ /** Неподдерживаемые форматы файлов */
471
+ rejectedFormats?: Accept;
464
472
  /**Добавленные файлы */
465
473
  addedFiles: File[];
466
474
  /**Сосотояние для добавления файлов */
@@ -480,6 +488,10 @@ export interface FileLoaderProps {
480
488
  /** Ширина прогресс бара */
481
489
  progressBarWidth?: string;
482
490
  }
491
+ export interface FileLoaderHandle {
492
+ clearErrorFiles: () => void;
493
+ clearAllFiles: () => void;
494
+ }
483
495
  export interface DialogProps {
484
496
  /** Флаг открытия окна */
485
497
  open: boolean;
@@ -606,6 +618,8 @@ export interface TextEditorProps {
606
618
  required?: boolean;
607
619
  className?: string;
608
620
  isButtonDisabled?: boolean;
621
+ /** Язык */
622
+ lng?: string;
609
623
  }
610
624
  export interface CommentProps {
611
625
  /** Идентификатор элемента */
@@ -635,6 +649,8 @@ export interface CommentProps {
635
649
  onChange?: (value: string, files: FilePreview[]) => void;
636
650
  onSubmit?: (value: string, files: FilePreview[]) => void;
637
651
  onDelete?: (id: string) => void;
652
+ /** Язык */
653
+ lng?: string;
638
654
  }
639
655
  export interface LinkProps {
640
656
  /**Гипертекстовая ссылка */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kamotive_ui",
3
- "version": "2.10.5",
3
+ "version": "4.12.25",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -27,7 +27,7 @@
27
27
  "react": "^18.3.1",
28
28
  "react-datepicker": "^8.2.1",
29
29
  "react-dom": "^18.3.1",
30
- "react-dropzone": "^14.3.5"
30
+ "react-dropzone": "^14.3.8"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@chromatic-com/storybook": "^3.2.2",