@astral/ui 4.77.1 → 4.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/components/fileUploading/FileUploader/public.d.ts +1 -1
  2. package/components/fileUploading/hooks/useFileUploader/useFileUploader.js +9 -6
  3. package/components/fileUploading/hooks/useSyncFiles/useSyncFiles.d.ts +9 -1
  4. package/components/fileUploading/hooks/useSyncFiles/useSyncFiles.js +3 -3
  5. package/components/fileUploading/hooks/useUploadFiles/useUploadFiles.d.ts +5 -2
  6. package/components/fileUploading/hooks/useUploadFiles/useUploadFiles.js +13 -3
  7. package/components/fileUploading/types.d.ts +10 -2
  8. package/hook-form/FormFileUploader/FormFileUploader.d.ts +5 -2
  9. package/hook-form/FormFileUploader/FormFileUploader.js +8 -3
  10. package/hook-form/FormPreviewFileUploader/FormPreviewFileUploader.d.ts +10 -3
  11. package/hook-form/FormPreviewFileUploader/FormPreviewFileUploader.js +7 -3
  12. package/node/components/fileUploading/FileUploader/public.d.ts +1 -1
  13. package/node/components/fileUploading/hooks/useFileUploader/useFileUploader.js +9 -6
  14. package/node/components/fileUploading/hooks/useSyncFiles/useSyncFiles.d.ts +9 -1
  15. package/node/components/fileUploading/hooks/useSyncFiles/useSyncFiles.js +3 -3
  16. package/node/components/fileUploading/hooks/useUploadFiles/useUploadFiles.d.ts +5 -2
  17. package/node/components/fileUploading/hooks/useUploadFiles/useUploadFiles.js +12 -2
  18. package/node/components/fileUploading/types.d.ts +10 -2
  19. package/node/hook-form/FormFileUploader/FormFileUploader.d.ts +5 -2
  20. package/node/hook-form/FormFileUploader/FormFileUploader.js +8 -3
  21. package/node/hook-form/FormPreviewFileUploader/FormPreviewFileUploader.d.ts +10 -3
  22. package/node/hook-form/FormPreviewFileUploader/FormPreviewFileUploader.js +7 -3
  23. package/package.json +1 -1
@@ -1,3 +1,3 @@
1
1
  export { fileUploaderClassnames } from '../constants';
2
- export type { FileId, FileUploaderNotify, FileUploaderProps, RestrictionFn, RestrictionFnResult, UploadedFileData, UploadFile, } from '../types';
2
+ export type { FileId, FileUploaderMetaInfo, FileUploaderNotify, FileUploaderProps, RestrictionFn, RestrictionFnResult, UploadedFileData, UploadFile, } from '../types';
3
3
  export { FileUploader } from './FileUploader';
@@ -57,7 +57,7 @@ inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, g
57
57
  onUploadFile,
58
58
  getErrorMessage,
59
59
  });
60
- const handleChange = (event) => {
60
+ const handleChange = (event, metaInfo) => {
61
61
  // Преобразуем к массиву и удаляем дубликаты
62
62
  const droppedFiles = Array.from(event.target.files || []).filter((droppedFile) => !files.find((file) => compareFile(droppedFile, file)));
63
63
  const addedFiles = droppedFiles
@@ -78,22 +78,25 @@ inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, g
78
78
  ];
79
79
  }, []);
80
80
  if (isMultiple) {
81
- onChange([...files, ...addedFiles]);
81
+ onChange([...files, ...addedFiles], metaInfo);
82
82
  }
83
83
  else if (addedFiles.length) {
84
- onChange(addedFiles[0]);
84
+ onChange(addedFiles[0], metaInfo);
85
85
  }
86
86
  if (addedFiles.length < droppedFiles.length) {
87
87
  notifyWarning(addedFiles.length, droppedFiles.length);
88
88
  }
89
- enqueueFiles(addedFiles);
89
+ enqueueFiles(addedFiles, metaInfo);
90
+ };
91
+ const handleFileInputChange = (event) => {
92
+ handleChange(event, { inputSourceType: 'fileInput' });
90
93
  };
91
94
  const { isDragActive, ...dropZoneActions } = useDnD({
92
95
  isDisabled,
93
96
  onChange: (droppedFiles) => {
94
97
  handleChange({
95
98
  target: { files: droppedFiles },
96
- });
99
+ }, { inputSourceType: 'dragAndDrop' });
97
100
  },
98
101
  });
99
102
  const handleDelete = (fileId) => {
@@ -142,7 +145,7 @@ inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, g
142
145
  accept: accept.join(),
143
146
  ref: inputRef,
144
147
  value: '',
145
- onChange: handleChange,
148
+ onChange: handleFileInputChange,
146
149
  name,
147
150
  isMultiple,
148
151
  isDisabled,
@@ -1,4 +1,8 @@
1
+ import { type RefObject } from 'react';
1
2
  import type { FileId, SpecificSelfFileParams, UploadFile } from '../../types';
3
+ type ChangeMetaInfo = {
4
+ inputSourceType?: 'fileInput' | 'dragAndDrop';
5
+ };
2
6
  type UseSyncFilesParams<TMultiple extends boolean = false> = {
3
7
  /**
4
8
  * Список файлов, которые приходят как value в компонент
@@ -15,7 +19,11 @@ type UseSyncFilesParams<TMultiple extends boolean = false> = {
15
19
  /**
16
20
  * Функция, вызываемая при изменении списка файлов
17
21
  */
18
- onChange: TMultiple extends true ? (value: UploadFile[]) => void : (value: UploadFile | null) => void;
22
+ onChange: TMultiple extends true ? (value: UploadFile[], metaInfo?: ChangeMetaInfo) => void : (value: UploadFile | null, metaInfo?: ChangeMetaInfo) => void;
23
+ /**
24
+ * Ref с metaInfo последнего пользовательского действия
25
+ */
26
+ metaInfoRef: RefObject<ChangeMetaInfo | undefined>;
19
27
  };
20
28
  export declare const useSyncFiles: <TMultiple extends boolean>(props: UseSyncFilesParams<TMultiple>) => void;
21
29
  export {};
@@ -1,14 +1,14 @@
1
1
  import { useEffect } from 'react';
2
2
  import { isEmpty } from '../../../utils/isEmpty';
3
3
  export const useSyncFiles = (props) => {
4
- const { isMultiple, files, selfFiles } = props;
4
+ const { isMultiple, files, selfFiles, metaInfoRef } = props;
5
5
  const handleSingleFileChange = (updatedFiles) => {
6
6
  const { onChange } = props;
7
- onChange(updatedFiles.length > 0 ? updatedFiles[0] : null);
7
+ onChange(updatedFiles.length > 0 ? updatedFiles[0] : null, metaInfoRef.current);
8
8
  };
9
9
  const handleMultipleFileChange = (updatedFiles) => {
10
10
  const { onChange } = props;
11
- onChange(updatedFiles);
11
+ onChange(updatedFiles, metaInfoRef.current);
12
12
  };
13
13
  useEffect(() => {
14
14
  if (isEmpty(selfFiles)) {
@@ -1,4 +1,7 @@
1
1
  import type { FileId, UploadedFileData, UploadFile } from '../../types';
2
+ type ChangeMetaInfo = {
3
+ inputSourceType?: 'fileInput' | 'dragAndDrop';
4
+ };
2
5
  type UseUploadFilesParams = {
3
6
  /**
4
7
  * Список файлов, которые приходят как value в компонент
@@ -11,7 +14,7 @@ type UseUploadFilesParams = {
11
14
  /**
12
15
  * Функция, вызываемая при изменении списка файлов
13
16
  */
14
- onChange: ((value: UploadFile[]) => void) | ((value: UploadFile | null) => void);
17
+ onChange: ((value: UploadFile[], metaInfo?: ChangeMetaInfo) => void) | ((value: UploadFile | null, metaInfo?: ChangeMetaInfo) => void);
15
18
  /**
16
19
  * Функция загрузки файлов на сервер
17
20
  * @param fileId - Идентификатор файла
@@ -31,7 +34,7 @@ type UseUploadFilesParams = {
31
34
  getErrorMessage?: (fileId: FileId, error: Error) => string;
32
35
  };
33
36
  export declare const useUploadFiles: ({ isMultiple, files: externalFiles, onChange, onUploadFile, getErrorMessage, }: UseUploadFilesParams) => {
34
- enqueueFiles: (files: UploadFile[]) => void;
37
+ enqueueFiles: (files: UploadFile[], metaInfo?: ChangeMetaInfo) => void;
35
38
  refetchFile: (fileToSend: UploadFile) => void;
36
39
  selfFiles: Record<string, UploadFile & import("../../types").SpecificSelfFileParams>;
37
40
  setErrorStatusFile: (fileId: string, errorMsg: string) => void;
@@ -1,13 +1,23 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useEffect, useRef, useState } from 'react';
2
2
  import { ABORT_ERROR_CODE, UPLOAD_ERROR_MESSAGE } from '../../constants';
3
3
  import { useSelfFiles } from '../useSelfFiles';
4
4
  import { useSyncFiles } from '../useSyncFiles';
5
5
  export const useUploadFiles = ({ isMultiple, files: externalFiles, onChange, onUploadFile, getErrorMessage, }) => {
6
6
  const [fileQueue, setFileQueue] = useState([]);
7
+ // Хранит metaInfo последнего пользовательского действия,
8
+ // чтобы передавать его в onChange при синхронизации статусов загрузки
9
+ const metaInfoRef = useRef(undefined);
7
10
  const { selfFiles, setLoadingStatusFile, setSuccessStatusFile, setErrorStatusFile, updateFileInfo, } = useSelfFiles();
8
11
  // При изменении статусов обновляем внешнее состояние
9
- useSyncFiles({ isMultiple, files: externalFiles, selfFiles, onChange });
10
- const enqueueFiles = (files) => {
12
+ useSyncFiles({
13
+ isMultiple,
14
+ files: externalFiles,
15
+ selfFiles,
16
+ onChange,
17
+ metaInfoRef,
18
+ });
19
+ const enqueueFiles = (files, metaInfo) => {
20
+ metaInfoRef.current = metaInfo;
11
21
  const acceptedFiles = files.filter(({ status }) => !status?.isRestrictionError);
12
22
  setFileQueue(acceptedFiles);
13
23
  };
@@ -6,6 +6,12 @@ export type RestrictionFnResult = {
6
6
  };
7
7
  export type RestrictionFn = (value: File) => RestrictionFnResult | undefined;
8
8
  export type FileId = string;
9
+ export type FileUploaderMetaInfo = {
10
+ /**
11
+ * Способ загрузки файла (fileInput или dragAndDrop)
12
+ */
13
+ inputSourceType?: 'fileInput' | 'dragAndDrop';
14
+ };
9
15
  /**
10
16
  * Расширенная информация о переданном accept
11
17
  */
@@ -231,6 +237,7 @@ type SingleFileUploaderProps = {
231
237
  /**
232
238
  * Функция, вызываемая при изменении списка файлов (добавление/удаление)
233
239
  * @param value - Объект загруженного файла или null при удалении
240
+ * @param metaInfo.inputSourceType - Способ загрузки файла (fileInput или dragAndDrop)
234
241
  * @remarks
235
242
  * Вызывается в следующих случаях:
236
243
  * - При добавлении нового файла через диалог выбора или drag-n-drop
@@ -238,7 +245,7 @@ type SingleFileUploaderProps = {
238
245
  * - При изменении статуса загрузки файла (loading/success/error)
239
246
  * - При обновлении информации о файле после успешной загрузки
240
247
  */
241
- onChange: (value: UploadFile | null) => void;
248
+ onChange: (value: UploadFile | null, metaInfo?: FileUploaderMetaInfo) => void;
242
249
  } & BaseFileUploaderProps;
243
250
  type MultipleFileUploaderProps = {
244
251
  value: UploadFile[];
@@ -253,6 +260,7 @@ type MultipleFileUploaderProps = {
253
260
  /**
254
261
  * Функция, вызываемая при изменении списка файлов (добавление/удаление)
255
262
  * @param value - Массив объектов загруженных файлов
263
+ * @param metaInfo.inputSourceType - Способ загрузки файла (fileInput или dragAndDrop)
256
264
  * @remarks
257
265
  * Вызывается в следующих случаях:
258
266
  * - При добавлении новых файлов через диалог выбора или drag-n-drop
@@ -260,7 +268,7 @@ type MultipleFileUploaderProps = {
260
268
  * - При изменении статуса загрузки файла (loading/success/error)
261
269
  * - При обновлении информации о файле после успешной загрузки
262
270
  */
263
- onChange: (value: UploadFile[]) => void;
271
+ onChange: (value: UploadFile[], metaInfo?: FileUploaderMetaInfo) => void;
264
272
  } & BaseFileUploaderProps;
265
273
  export type FileUploaderProps = MultipleFileUploaderProps | SingleFileUploaderProps;
266
274
  export type SpecificSelfFileParams = {
@@ -1,7 +1,10 @@
1
1
  /// <reference types="react" />
2
- import { type FileUploaderNotify, type FileUploaderProps, type UploadFile } from '../../components/fileUploading/FileUploader';
2
+ import { type FileUploaderMetaInfo, type FileUploaderNotify, type FileUploaderProps, type UploadFile } from '../../components/fileUploading/FileUploader';
3
3
  import { type WithFormFieldProps } from '../types';
4
- type BaseFileUploaderProps = Omit<FileUploaderProps, 'value' | 'isMultiple' | 'maxFileCount' | 'notify' | 'onChange'>;
4
+ export type FormFileUploaderMetaInfo = FileUploaderMetaInfo;
5
+ type BaseFileUploaderProps = Omit<FileUploaderProps, 'value' | 'isMultiple' | 'maxFileCount' | 'notify' | 'onChange'> & {
6
+ onChange?: (value: FormFileUploaderValue | FormFileUploaderValue[], metaInfo?: FormFileUploaderMetaInfo) => void;
7
+ };
5
8
  type SingleFileUploaderProps = {
6
9
  isMultiple?: false;
7
10
  maxFileCount?: never;
@@ -5,11 +5,16 @@ import { useFormFieldProps } from '../useFormFieldProps';
5
5
  /**
6
6
  * FileUploader для формы
7
7
  */
8
- const FormFileUploaderInner = (props, ref) => {
9
- const { error, ...fieldProps } = useFormFieldProps(props);
8
+ const FormFileUploaderInner = ({ onChange: propsOnChange, ...props }, ref) => {
9
+ const { error, onChange, ...fieldProps } = useFormFieldProps(props);
10
+ const handleChange = (value, metaInfo) => {
11
+ onChange(value);
12
+ propsOnChange?.(value, metaInfo);
13
+ };
14
+ return (
10
15
  // biome-ignore lint/suspicious/noTsIgnore: Ошибка типизации при пробросе пропсов: isMultiple
11
16
  // @ts-ignore
12
17
  // TODO https://track.astral.ru/soft/browse/UIKIT-1926
13
- return _jsx(FileUploader, { isError: error, ...fieldProps, ref: ref });
18
+ _jsx(FileUploader, { isError: error, onChange: handleChange, ...fieldProps, ref: ref }));
14
19
  };
15
20
  export const FormFileUploader = forwardRefWithGeneric(FormFileUploaderInner);
@@ -1,9 +1,16 @@
1
1
  import type { ForwardedRef } from 'react';
2
2
  import { type PreviewFileUploaderProps } from '../../components/fileUploading/PreviewFileUploader';
3
+ import { type FileUploaderMetaInfo, type UploadFile } from '../../components/fileUploading/types';
3
4
  import { type WithFormFieldProps } from '../types';
4
- export type FormPreviewFileUploaderProps<TFieldValues extends object> = WithFormFieldProps<Omit<PreviewFileUploaderProps, 'value' | 'onChange'>, TFieldValues>;
5
+ export type FormPreviewFileUploaderValue = UploadFile;
6
+ export type FormPreviewFileUploaderMetaInfo = FileUploaderMetaInfo;
7
+ export type FormPreviewFileUploaderProps<TFieldValues extends object> = WithFormFieldProps<Omit<PreviewFileUploaderProps, 'value' | 'onChange'>, TFieldValues> & {
8
+ onChange?: (value: FormPreviewFileUploaderValue | null, metaInfo?: FormPreviewFileUploaderMetaInfo) => void;
9
+ };
5
10
  /**
6
11
  * PreviewFileUploader для формы
7
12
  */
8
- export declare const FormPreviewFileUploaderInner: <TFieldValues extends object>(props: FormPreviewFileUploaderProps<TFieldValues>, ref: ForwardedRef<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
9
- export declare const FormPreviewFileUploader: <TFieldValues extends object>(props: Omit<Omit<import("../..").UsePreviewFileUploaderParams, "onChange" | "value">, "error" | "name"> & Omit<import("react-hook-form").UseControllerProps<TFieldValues>, "rules"> & import("react").RefAttributes<HTMLDivElement>) => import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
13
+ export declare const FormPreviewFileUploaderInner: <TFieldValues extends object>({ onChange: propsOnChange, ...props }: FormPreviewFileUploaderProps<TFieldValues>, ref: ForwardedRef<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
14
+ export declare const FormPreviewFileUploader: <TFieldValues extends object>(props: Omit<Omit<import("../..").UsePreviewFileUploaderParams, "onChange" | "value">, "error" | "name"> & Omit<import("react-hook-form").UseControllerProps<TFieldValues>, "rules"> & {
15
+ onChange?: ((value: FormPreviewFileUploaderValue | null, metaInfo?: FormPreviewFileUploaderMetaInfo) => void) | undefined;
16
+ } & import("react").RefAttributes<HTMLDivElement>) => import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
@@ -5,8 +5,12 @@ import { useFormFieldProps } from '../useFormFieldProps';
5
5
  /**
6
6
  * PreviewFileUploader для формы
7
7
  */
8
- export const FormPreviewFileUploaderInner = (props, ref) => {
9
- const { error, ...fieldProps } = useFormFieldProps(props);
10
- return _jsx(PreviewFileUploader, { isError: error, ...fieldProps, ref: ref });
8
+ export const FormPreviewFileUploaderInner = ({ onChange: propsOnChange, ...props }, ref) => {
9
+ const { error, onChange, ...fieldProps } = useFormFieldProps(props);
10
+ const handleChange = (value, metaInfo) => {
11
+ onChange(value);
12
+ propsOnChange?.(value, metaInfo);
13
+ };
14
+ return (_jsx(PreviewFileUploader, { isError: error, onChange: handleChange, ...fieldProps, ref: ref }));
11
15
  };
12
16
  export const FormPreviewFileUploader = forwardRefWithGeneric(FormPreviewFileUploaderInner);
@@ -1,3 +1,3 @@
1
1
  export { fileUploaderClassnames } from '../constants';
2
- export type { FileId, FileUploaderNotify, FileUploaderProps, RestrictionFn, RestrictionFnResult, UploadedFileData, UploadFile, } from '../types';
2
+ export type { FileId, FileUploaderMetaInfo, FileUploaderNotify, FileUploaderProps, RestrictionFn, RestrictionFnResult, UploadedFileData, UploadFile, } from '../types';
3
3
  export { FileUploader } from './FileUploader';
@@ -60,7 +60,7 @@ inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, g
60
60
  onUploadFile,
61
61
  getErrorMessage,
62
62
  });
63
- const handleChange = (event) => {
63
+ const handleChange = (event, metaInfo) => {
64
64
  // Преобразуем к массиву и удаляем дубликаты
65
65
  const droppedFiles = Array.from(event.target.files || []).filter((droppedFile) => !files.find((file) => (0, compareFile_1.compareFile)(droppedFile, file)));
66
66
  const addedFiles = droppedFiles
@@ -81,22 +81,25 @@ inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, g
81
81
  ];
82
82
  }, []);
83
83
  if (isMultiple) {
84
- onChange([...files, ...addedFiles]);
84
+ onChange([...files, ...addedFiles], metaInfo);
85
85
  }
86
86
  else if (addedFiles.length) {
87
- onChange(addedFiles[0]);
87
+ onChange(addedFiles[0], metaInfo);
88
88
  }
89
89
  if (addedFiles.length < droppedFiles.length) {
90
90
  notifyWarning(addedFiles.length, droppedFiles.length);
91
91
  }
92
- enqueueFiles(addedFiles);
92
+ enqueueFiles(addedFiles, metaInfo);
93
+ };
94
+ const handleFileInputChange = (event) => {
95
+ handleChange(event, { inputSourceType: 'fileInput' });
93
96
  };
94
97
  const { isDragActive, ...dropZoneActions } = (0, useDnD_1.useDnD)({
95
98
  isDisabled,
96
99
  onChange: (droppedFiles) => {
97
100
  handleChange({
98
101
  target: { files: droppedFiles },
99
- });
102
+ }, { inputSourceType: 'dragAndDrop' });
100
103
  },
101
104
  });
102
105
  const handleDelete = (fileId) => {
@@ -145,7 +148,7 @@ inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, g
145
148
  accept: accept.join(),
146
149
  ref: inputRef,
147
150
  value: '',
148
- onChange: handleChange,
151
+ onChange: handleFileInputChange,
149
152
  name,
150
153
  isMultiple,
151
154
  isDisabled,
@@ -1,4 +1,8 @@
1
+ import { type RefObject } from 'react';
1
2
  import type { FileId, SpecificSelfFileParams, UploadFile } from '../../types';
3
+ type ChangeMetaInfo = {
4
+ inputSourceType?: 'fileInput' | 'dragAndDrop';
5
+ };
2
6
  type UseSyncFilesParams<TMultiple extends boolean = false> = {
3
7
  /**
4
8
  * Список файлов, которые приходят как value в компонент
@@ -15,7 +19,11 @@ type UseSyncFilesParams<TMultiple extends boolean = false> = {
15
19
  /**
16
20
  * Функция, вызываемая при изменении списка файлов
17
21
  */
18
- onChange: TMultiple extends true ? (value: UploadFile[]) => void : (value: UploadFile | null) => void;
22
+ onChange: TMultiple extends true ? (value: UploadFile[], metaInfo?: ChangeMetaInfo) => void : (value: UploadFile | null, metaInfo?: ChangeMetaInfo) => void;
23
+ /**
24
+ * Ref с metaInfo последнего пользовательского действия
25
+ */
26
+ metaInfoRef: RefObject<ChangeMetaInfo | undefined>;
19
27
  };
20
28
  export declare const useSyncFiles: <TMultiple extends boolean>(props: UseSyncFilesParams<TMultiple>) => void;
21
29
  export {};
@@ -4,14 +4,14 @@ exports.useSyncFiles = void 0;
4
4
  const react_1 = require("react");
5
5
  const isEmpty_1 = require("../../../utils/isEmpty");
6
6
  const useSyncFiles = (props) => {
7
- const { isMultiple, files, selfFiles } = props;
7
+ const { isMultiple, files, selfFiles, metaInfoRef } = props;
8
8
  const handleSingleFileChange = (updatedFiles) => {
9
9
  const { onChange } = props;
10
- onChange(updatedFiles.length > 0 ? updatedFiles[0] : null);
10
+ onChange(updatedFiles.length > 0 ? updatedFiles[0] : null, metaInfoRef.current);
11
11
  };
12
12
  const handleMultipleFileChange = (updatedFiles) => {
13
13
  const { onChange } = props;
14
- onChange(updatedFiles);
14
+ onChange(updatedFiles, metaInfoRef.current);
15
15
  };
16
16
  (0, react_1.useEffect)(() => {
17
17
  if ((0, isEmpty_1.isEmpty)(selfFiles)) {
@@ -1,4 +1,7 @@
1
1
  import type { FileId, UploadedFileData, UploadFile } from '../../types';
2
+ type ChangeMetaInfo = {
3
+ inputSourceType?: 'fileInput' | 'dragAndDrop';
4
+ };
2
5
  type UseUploadFilesParams = {
3
6
  /**
4
7
  * Список файлов, которые приходят как value в компонент
@@ -11,7 +14,7 @@ type UseUploadFilesParams = {
11
14
  /**
12
15
  * Функция, вызываемая при изменении списка файлов
13
16
  */
14
- onChange: ((value: UploadFile[]) => void) | ((value: UploadFile | null) => void);
17
+ onChange: ((value: UploadFile[], metaInfo?: ChangeMetaInfo) => void) | ((value: UploadFile | null, metaInfo?: ChangeMetaInfo) => void);
15
18
  /**
16
19
  * Функция загрузки файлов на сервер
17
20
  * @param fileId - Идентификатор файла
@@ -31,7 +34,7 @@ type UseUploadFilesParams = {
31
34
  getErrorMessage?: (fileId: FileId, error: Error) => string;
32
35
  };
33
36
  export declare const useUploadFiles: ({ isMultiple, files: externalFiles, onChange, onUploadFile, getErrorMessage, }: UseUploadFilesParams) => {
34
- enqueueFiles: (files: UploadFile[]) => void;
37
+ enqueueFiles: (files: UploadFile[], metaInfo?: ChangeMetaInfo) => void;
35
38
  refetchFile: (fileToSend: UploadFile) => void;
36
39
  selfFiles: Record<string, UploadFile & import("../../types").SpecificSelfFileParams>;
37
40
  setErrorStatusFile: (fileId: string, errorMsg: string) => void;
@@ -7,10 +7,20 @@ const useSelfFiles_1 = require("../useSelfFiles");
7
7
  const useSyncFiles_1 = require("../useSyncFiles");
8
8
  const useUploadFiles = ({ isMultiple, files: externalFiles, onChange, onUploadFile, getErrorMessage, }) => {
9
9
  const [fileQueue, setFileQueue] = (0, react_1.useState)([]);
10
+ // Хранит metaInfo последнего пользовательского действия,
11
+ // чтобы передавать его в onChange при синхронизации статусов загрузки
12
+ const metaInfoRef = (0, react_1.useRef)(undefined);
10
13
  const { selfFiles, setLoadingStatusFile, setSuccessStatusFile, setErrorStatusFile, updateFileInfo, } = (0, useSelfFiles_1.useSelfFiles)();
11
14
  // При изменении статусов обновляем внешнее состояние
12
- (0, useSyncFiles_1.useSyncFiles)({ isMultiple, files: externalFiles, selfFiles, onChange });
13
- const enqueueFiles = (files) => {
15
+ (0, useSyncFiles_1.useSyncFiles)({
16
+ isMultiple,
17
+ files: externalFiles,
18
+ selfFiles,
19
+ onChange,
20
+ metaInfoRef,
21
+ });
22
+ const enqueueFiles = (files, metaInfo) => {
23
+ metaInfoRef.current = metaInfo;
14
24
  const acceptedFiles = files.filter(({ status }) => !status?.isRestrictionError);
15
25
  setFileQueue(acceptedFiles);
16
26
  };
@@ -6,6 +6,12 @@ export type RestrictionFnResult = {
6
6
  };
7
7
  export type RestrictionFn = (value: File) => RestrictionFnResult | undefined;
8
8
  export type FileId = string;
9
+ export type FileUploaderMetaInfo = {
10
+ /**
11
+ * Способ загрузки файла (fileInput или dragAndDrop)
12
+ */
13
+ inputSourceType?: 'fileInput' | 'dragAndDrop';
14
+ };
9
15
  /**
10
16
  * Расширенная информация о переданном accept
11
17
  */
@@ -231,6 +237,7 @@ type SingleFileUploaderProps = {
231
237
  /**
232
238
  * Функция, вызываемая при изменении списка файлов (добавление/удаление)
233
239
  * @param value - Объект загруженного файла или null при удалении
240
+ * @param metaInfo.inputSourceType - Способ загрузки файла (fileInput или dragAndDrop)
234
241
  * @remarks
235
242
  * Вызывается в следующих случаях:
236
243
  * - При добавлении нового файла через диалог выбора или drag-n-drop
@@ -238,7 +245,7 @@ type SingleFileUploaderProps = {
238
245
  * - При изменении статуса загрузки файла (loading/success/error)
239
246
  * - При обновлении информации о файле после успешной загрузки
240
247
  */
241
- onChange: (value: UploadFile | null) => void;
248
+ onChange: (value: UploadFile | null, metaInfo?: FileUploaderMetaInfo) => void;
242
249
  } & BaseFileUploaderProps;
243
250
  type MultipleFileUploaderProps = {
244
251
  value: UploadFile[];
@@ -253,6 +260,7 @@ type MultipleFileUploaderProps = {
253
260
  /**
254
261
  * Функция, вызываемая при изменении списка файлов (добавление/удаление)
255
262
  * @param value - Массив объектов загруженных файлов
263
+ * @param metaInfo.inputSourceType - Способ загрузки файла (fileInput или dragAndDrop)
256
264
  * @remarks
257
265
  * Вызывается в следующих случаях:
258
266
  * - При добавлении новых файлов через диалог выбора или drag-n-drop
@@ -260,7 +268,7 @@ type MultipleFileUploaderProps = {
260
268
  * - При изменении статуса загрузки файла (loading/success/error)
261
269
  * - При обновлении информации о файле после успешной загрузки
262
270
  */
263
- onChange: (value: UploadFile[]) => void;
271
+ onChange: (value: UploadFile[], metaInfo?: FileUploaderMetaInfo) => void;
264
272
  } & BaseFileUploaderProps;
265
273
  export type FileUploaderProps = MultipleFileUploaderProps | SingleFileUploaderProps;
266
274
  export type SpecificSelfFileParams = {
@@ -1,7 +1,10 @@
1
1
  /// <reference types="react" />
2
- import { type FileUploaderNotify, type FileUploaderProps, type UploadFile } from '../../components/fileUploading/FileUploader';
2
+ import { type FileUploaderMetaInfo, type FileUploaderNotify, type FileUploaderProps, type UploadFile } from '../../components/fileUploading/FileUploader';
3
3
  import { type WithFormFieldProps } from '../types';
4
- type BaseFileUploaderProps = Omit<FileUploaderProps, 'value' | 'isMultiple' | 'maxFileCount' | 'notify' | 'onChange'>;
4
+ export type FormFileUploaderMetaInfo = FileUploaderMetaInfo;
5
+ type BaseFileUploaderProps = Omit<FileUploaderProps, 'value' | 'isMultiple' | 'maxFileCount' | 'notify' | 'onChange'> & {
6
+ onChange?: (value: FormFileUploaderValue | FormFileUploaderValue[], metaInfo?: FormFileUploaderMetaInfo) => void;
7
+ };
5
8
  type SingleFileUploaderProps = {
6
9
  isMultiple?: false;
7
10
  maxFileCount?: never;
@@ -8,11 +8,16 @@ const useFormFieldProps_1 = require("../useFormFieldProps");
8
8
  /**
9
9
  * FileUploader для формы
10
10
  */
11
- const FormFileUploaderInner = (props, ref) => {
12
- const { error, ...fieldProps } = (0, useFormFieldProps_1.useFormFieldProps)(props);
11
+ const FormFileUploaderInner = ({ onChange: propsOnChange, ...props }, ref) => {
12
+ const { error, onChange, ...fieldProps } = (0, useFormFieldProps_1.useFormFieldProps)(props);
13
+ const handleChange = (value, metaInfo) => {
14
+ onChange(value);
15
+ propsOnChange?.(value, metaInfo);
16
+ };
17
+ return (
13
18
  // biome-ignore lint/suspicious/noTsIgnore: Ошибка типизации при пробросе пропсов: isMultiple
14
19
  // @ts-ignore
15
20
  // TODO https://track.astral.ru/soft/browse/UIKIT-1926
16
- return (0, jsx_runtime_1.jsx)(FileUploader_1.FileUploader, { isError: error, ...fieldProps, ref: ref });
21
+ (0, jsx_runtime_1.jsx)(FileUploader_1.FileUploader, { isError: error, onChange: handleChange, ...fieldProps, ref: ref }));
17
22
  };
18
23
  exports.FormFileUploader = (0, forwardRefWithGeneric_1.forwardRefWithGeneric)(FormFileUploaderInner);
@@ -1,9 +1,16 @@
1
1
  import type { ForwardedRef } from 'react';
2
2
  import { type PreviewFileUploaderProps } from '../../components/fileUploading/PreviewFileUploader';
3
+ import { type FileUploaderMetaInfo, type UploadFile } from '../../components/fileUploading/types';
3
4
  import { type WithFormFieldProps } from '../types';
4
- export type FormPreviewFileUploaderProps<TFieldValues extends object> = WithFormFieldProps<Omit<PreviewFileUploaderProps, 'value' | 'onChange'>, TFieldValues>;
5
+ export type FormPreviewFileUploaderValue = UploadFile;
6
+ export type FormPreviewFileUploaderMetaInfo = FileUploaderMetaInfo;
7
+ export type FormPreviewFileUploaderProps<TFieldValues extends object> = WithFormFieldProps<Omit<PreviewFileUploaderProps, 'value' | 'onChange'>, TFieldValues> & {
8
+ onChange?: (value: FormPreviewFileUploaderValue | null, metaInfo?: FormPreviewFileUploaderMetaInfo) => void;
9
+ };
5
10
  /**
6
11
  * PreviewFileUploader для формы
7
12
  */
8
- export declare const FormPreviewFileUploaderInner: <TFieldValues extends object>(props: FormPreviewFileUploaderProps<TFieldValues>, ref: ForwardedRef<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
9
- export declare const FormPreviewFileUploader: <TFieldValues extends object>(props: Omit<Omit<import("../..").UsePreviewFileUploaderParams, "onChange" | "value">, "error" | "name"> & Omit<import("react-hook-form").UseControllerProps<TFieldValues>, "rules"> & import("react").RefAttributes<HTMLDivElement>) => import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
13
+ export declare const FormPreviewFileUploaderInner: <TFieldValues extends object>({ onChange: propsOnChange, ...props }: FormPreviewFileUploaderProps<TFieldValues>, ref: ForwardedRef<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
14
+ export declare const FormPreviewFileUploader: <TFieldValues extends object>(props: Omit<Omit<import("../..").UsePreviewFileUploaderParams, "onChange" | "value">, "error" | "name"> & Omit<import("react-hook-form").UseControllerProps<TFieldValues>, "rules"> & {
15
+ onChange?: ((value: FormPreviewFileUploaderValue | null, metaInfo?: FormPreviewFileUploaderMetaInfo) => void) | undefined;
16
+ } & import("react").RefAttributes<HTMLDivElement>) => import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
@@ -8,9 +8,13 @@ const useFormFieldProps_1 = require("../useFormFieldProps");
8
8
  /**
9
9
  * PreviewFileUploader для формы
10
10
  */
11
- const FormPreviewFileUploaderInner = (props, ref) => {
12
- const { error, ...fieldProps } = (0, useFormFieldProps_1.useFormFieldProps)(props);
13
- return (0, jsx_runtime_1.jsx)(PreviewFileUploader_1.PreviewFileUploader, { isError: error, ...fieldProps, ref: ref });
11
+ const FormPreviewFileUploaderInner = ({ onChange: propsOnChange, ...props }, ref) => {
12
+ const { error, onChange, ...fieldProps } = (0, useFormFieldProps_1.useFormFieldProps)(props);
13
+ const handleChange = (value, metaInfo) => {
14
+ onChange(value);
15
+ propsOnChange?.(value, metaInfo);
16
+ };
17
+ return ((0, jsx_runtime_1.jsx)(PreviewFileUploader_1.PreviewFileUploader, { isError: error, onChange: handleChange, ...fieldProps, ref: ref }));
14
18
  };
15
19
  exports.FormPreviewFileUploaderInner = FormPreviewFileUploaderInner;
16
20
  exports.FormPreviewFileUploader = (0, forwardRefWithGeneric_1.forwardRefWithGeneric)(exports.FormPreviewFileUploaderInner);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astral/ui",
3
- "version": "4.77.1",
3
+ "version": "4.78.0",
4
4
  "browser": "./index.js",
5
5
  "main": "./node/index.js",
6
6
  "dependencies": {