@ssa-ui-kit/core 3.16.4 → 3.17.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.
- package/dist/components/FileAttachment/FileAttachment.d.ts +36 -0
- package/dist/components/FileAttachment/hooks/index.d.ts +1 -0
- package/dist/components/FileAttachment/hooks/useFilePreviewUrl.d.ts +2 -0
- package/dist/components/FileAttachment/index.d.ts +2 -0
- package/dist/components/FileAttachment/styles.d.ts +22 -0
- package/dist/components/FileAttachment/types.d.ts +24 -0
- package/dist/components/FileAttachment/utils.d.ts +6 -0
- package/dist/components/FileUpload/FileUpload.d.ts +33 -2
- package/dist/components/FileUpload/index.d.ts +1 -2
- package/dist/components/FileUpload/styles.d.ts +0 -6
- package/dist/components/FileUpload/types.d.ts +10 -0
- package/dist/components/index.d.ts +2 -1
- package/dist/index.js +266 -83
- package/package.json +3 -3
- package/dist/components/FileUpload/FileUploadItem.d.ts +0 -7
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { FileAttachmentProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* FileAttachment - Read-only row displaying a single attached/uploading file
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* <FileAttachment
|
|
8
|
+
* file={{ name: 'Report.pdf', size: 20 * 1024 * 1024 }}
|
|
9
|
+
* progress={50}
|
|
10
|
+
* onRemove={() => handleRemove(file)}
|
|
11
|
+
* />
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // Progress bar look instead of the default percentage text
|
|
17
|
+
* <FileAttachment
|
|
18
|
+
* file={{ name: 'Report.pdf', size: 20 * 1024 * 1024 }}
|
|
19
|
+
* progress={50}
|
|
20
|
+
* progressDisplay="bar"
|
|
21
|
+
* onRemove={() => handleRemove(file)}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Omitting `progress` entirely shows just the file size, no progress copy —
|
|
28
|
+
* // e.g. a file that's been selected but whose upload hasn't started yet.
|
|
29
|
+
* <FileAttachment
|
|
30
|
+
* file={{ name: 'Report.pdf', size: 20 * 1024 * 1024 }}
|
|
31
|
+
* onRemove={() => handleRemove(file)}
|
|
32
|
+
* />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare const FileAttachment: ({ file, size, progress, progressDisplay, uploadingText, uploadedText, showDescription, icon, isDisabled, onRemove, className, css: cssProp, }: FileAttachmentProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
36
|
+
export default FileAttachment;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useFilePreviewUrl } from './useFilePreviewUrl';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Theme } from '@emotion/react';
|
|
2
|
+
export declare const iconSizeBySize: {
|
|
3
|
+
large: number;
|
|
4
|
+
small: number;
|
|
5
|
+
};
|
|
6
|
+
/** Placeholder glyph is inset ~20% on each side of its box in the design (40px box -> 24px glyph). */
|
|
7
|
+
export declare const placeholderIconSizeBySize: {
|
|
8
|
+
large: number;
|
|
9
|
+
small: number;
|
|
10
|
+
};
|
|
11
|
+
export declare const container: (theme: Theme, size: "large" | "small") => import("@emotion/react").SerializedStyles;
|
|
12
|
+
export declare const disabledContainer: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
13
|
+
export declare const iconWrapper: (size: "large" | "small") => import("@emotion/react").SerializedStyles;
|
|
14
|
+
export declare const placeholderWrapper: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
15
|
+
export declare const previewImage: import("@emotion/react").SerializedStyles;
|
|
16
|
+
export declare const textColumn: import("@emotion/react").SerializedStyles;
|
|
17
|
+
export declare const title: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
18
|
+
export declare const description: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
19
|
+
export declare const dot: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
20
|
+
export declare const progressTrack: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
21
|
+
export declare const progressFill: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
22
|
+
export declare const deleteButton: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Interpolation, Theme } from '@emotion/react';
|
|
2
|
+
import { IconProps } from '../Icon/types';
|
|
3
|
+
export interface FileAttachmentFile {
|
|
4
|
+
name: string;
|
|
5
|
+
size: number;
|
|
6
|
+
/** Local file/blob not yet uploaded — used to render an image preview via an object URL. Ignored for non-image file names. */
|
|
7
|
+
content?: File | Blob;
|
|
8
|
+
/** URL of an already-uploaded image, e.g. returned by the backend. Ignored for non-image file names. Takes precedence over `content`. */
|
|
9
|
+
previewUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FileAttachmentProps {
|
|
12
|
+
file: FileAttachmentFile;
|
|
13
|
+
size?: 'large' | 'small';
|
|
14
|
+
progress?: number;
|
|
15
|
+
progressDisplay?: 'text' | 'bar';
|
|
16
|
+
uploadingText?: string;
|
|
17
|
+
uploadedText?: string;
|
|
18
|
+
showDescription?: boolean;
|
|
19
|
+
icon?: IconProps['name'];
|
|
20
|
+
isDisabled?: boolean;
|
|
21
|
+
onRemove?: () => void;
|
|
22
|
+
className?: string;
|
|
23
|
+
css?: Interpolation<Theme>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IconProps } from '../Icon/types';
|
|
2
|
+
export declare const formatBytes: (bytes: number) => string;
|
|
3
|
+
/** Returns the file-type icon for a known extension, or `null` when the design's grey Placeholder look should be used instead. */
|
|
4
|
+
export declare const getFileTypeIcon: (fileName: string) => IconProps["name"] | null;
|
|
5
|
+
/** Gates image-preview rendering strictly on the file name's extension, so a pdf/php/etc. is never rendered via `<img>` even if preview data is (incorrectly) supplied for it. */
|
|
6
|
+
export declare const isImageFile: (fileName: string) => boolean;
|
|
@@ -4,7 +4,8 @@ import { FileUploadProps } from './types';
|
|
|
4
4
|
*
|
|
5
5
|
* Supports single and multi-file selection with built-in validation for
|
|
6
6
|
* file formats and size. In multi-file mode, selected files are listed
|
|
7
|
-
* below the input with individual remove controls.
|
|
7
|
+
* below the input with individual remove controls. Single-file mode can opt
|
|
8
|
+
* into the same list treatment via `showFileAttachment`.
|
|
8
9
|
*
|
|
9
10
|
* @example
|
|
10
11
|
* ```tsx
|
|
@@ -32,6 +33,36 @@ import { FileUploadProps } from './types';
|
|
|
32
33
|
* onChange={setFiles}
|
|
33
34
|
* />
|
|
34
35
|
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Multi-file with per-file upload progress, driven by the consumer's own
|
|
40
|
+
* // upload requests — FileUpload only handles local selection, so it has no
|
|
41
|
+
* // progress data of its own.
|
|
42
|
+
* <FileUpload
|
|
43
|
+
* isMultiFile
|
|
44
|
+
* value={files}
|
|
45
|
+
* onChange={setFiles}
|
|
46
|
+
* uploadProgress={[
|
|
47
|
+
* { name: 'report.pdf', progress: 50 },
|
|
48
|
+
* { name: 'photo.png', progress: 100 },
|
|
49
|
+
* ]}
|
|
50
|
+
* />
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* // Single file, shown as a FileAttachment card below the input (icon,
|
|
56
|
+
* // size, delete button, image preview) instead of inline text next to the
|
|
57
|
+
* // button. `uploadProgress` here can just be a single number, since there's
|
|
58
|
+
* // only ever one file.
|
|
59
|
+
* <FileUpload
|
|
60
|
+
* showFileAttachment
|
|
61
|
+
* value={file}
|
|
62
|
+
* onChange={(files) => setFile(files[0])}
|
|
63
|
+
* uploadProgress={70}
|
|
64
|
+
* />
|
|
65
|
+
* ```
|
|
35
66
|
*/
|
|
36
|
-
declare const FileUpload: ({ label, placeholder, helperText, actionText, error, disabled, css, className, allowedFormats, maxFileSize, isMultiFile, maxFiles, withDropArea, uploadedSectionTitle, value, onChange, onFileRejected, }: FileUploadProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
67
|
+
declare const FileUpload: ({ label, placeholder, helperText, actionText, error, disabled, css, className, allowedFormats, maxFileSize, isMultiFile, maxFiles, withDropArea, uploadedSectionTitle, uploadProgress, showFileAttachment, value, onChange, onFileRejected, }: FileUploadProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
37
68
|
export default FileUpload;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export { default } from './FileUpload';
|
|
2
|
-
export {
|
|
3
|
-
export type { FileUploadProps, FileRejectionReason } from './types';
|
|
2
|
+
export type { FileUploadProps, FileRejectionReason, FileUploadProgress, FileUploadProgressEntry, } from './types';
|
|
@@ -16,9 +16,3 @@ export declare const dropAreaAction: (theme: Theme) => import("@emotion/react").
|
|
|
16
16
|
export declare const dropAreaClearButton: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
17
17
|
export declare const filesList: import("@emotion/react").SerializedStyles;
|
|
18
18
|
export declare const filesListTitle: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
19
|
-
export declare const fileItem: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
20
|
-
export declare const fileIconWrapper: import("@emotion/react").SerializedStyles;
|
|
21
|
-
export declare const fileInfo: import("@emotion/react").SerializedStyles;
|
|
22
|
-
export declare const fileName: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
23
|
-
export declare const fileSize: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
24
|
-
export declare const deleteButton: (theme: Theme) => import("@emotion/react").SerializedStyles;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Interpolation, Theme } from '@emotion/react';
|
|
2
2
|
export type FileRejectionReason = 'size' | 'format';
|
|
3
|
+
export interface FileUploadProgressEntry {
|
|
4
|
+
name: string;
|
|
5
|
+
progress: number;
|
|
6
|
+
}
|
|
7
|
+
/** A single percentage applies to every listed file uniformly; a list matches per-file by `name` — files with no matching entry show no progress. */
|
|
8
|
+
export type FileUploadProgress = number | FileUploadProgressEntry[];
|
|
3
9
|
export interface FileUploadProps {
|
|
4
10
|
label?: string;
|
|
5
11
|
placeholder?: string;
|
|
@@ -14,6 +20,10 @@ export interface FileUploadProps {
|
|
|
14
20
|
maxFiles?: number;
|
|
15
21
|
withDropArea?: boolean;
|
|
16
22
|
uploadedSectionTitle?: string;
|
|
23
|
+
/** Upload progress for files in the multi-file list (`isMultiFile`). FileUpload only handles local selection, not the network upload itself — pass this in as the consumer's own upload reports progress. Files with no corresponding progress show just their size. */
|
|
24
|
+
uploadProgress?: FileUploadProgress;
|
|
25
|
+
/** Single-file mode only (`!isMultiFile`, ignored when `withDropArea` is set — its own selected-file view already covers this): show the selected file as a `FileAttachment` card below the input, instead of inline text next to the button. The input row then always shows `placeholder`, matching how multi-file mode behaves. */
|
|
26
|
+
showFileAttachment?: boolean;
|
|
17
27
|
className?: string;
|
|
18
28
|
value?: File | File[];
|
|
19
29
|
onChange?: (files: File[]) => void;
|
|
@@ -41,8 +41,9 @@ export * from './ColorPicker';
|
|
|
41
41
|
export * from './SearchBox';
|
|
42
42
|
export type * from './SearchBox/types';
|
|
43
43
|
export { default as FileUpload } from './FileUpload';
|
|
44
|
-
export { FileUploadItem } from './FileUpload';
|
|
45
44
|
export type * from './FileUpload/types';
|
|
45
|
+
export { default as FileAttachment } from './FileAttachment';
|
|
46
|
+
export type * from './FileAttachment/types';
|
|
46
47
|
export * from './Field';
|
|
47
48
|
export { default as Form } from './Form';
|
|
48
49
|
export { default as FormAction } from './FormAction';
|
package/dist/index.js
CHANGED
|
@@ -7999,8 +7999,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
7999
7999
|
DropdownOptions: () => (/* reexport */ DropdownOptions_DropdownOptions),
|
|
8000
8000
|
DropdownToggle: () => (/* reexport */ DropdownToggle_DropdownToggle),
|
|
8001
8001
|
Field: () => (/* reexport */ index_parts_namespaceObject),
|
|
8002
|
+
FileAttachment: () => (/* reexport */ FileAttachment_FileAttachment),
|
|
8002
8003
|
FileUpload: () => (/* reexport */ FileUpload_FileUpload),
|
|
8003
|
-
FileUploadItem: () => (/* reexport */ FileUpload_FileUploadItem),
|
|
8004
8004
|
Filters: () => (/* reexport */ Filters),
|
|
8005
8005
|
FiltersMultiSelect: () => (/* reexport */ FiltersMultiSelect),
|
|
8006
8006
|
FiltersMultiSelectEmpty: () => (/* reexport */ FiltersMultiSelectEmpty),
|
|
@@ -20626,11 +20626,11 @@ const multipleStyles = ({
|
|
|
20626
20626
|
isOpen
|
|
20627
20627
|
}) => {
|
|
20628
20628
|
const borderColor = isOpen ? theme.palette.primary.main : theme.colors.grey;
|
|
20629
|
-
return /*#__PURE__*/(0,react_namespaceObject.css)("
|
|
20629
|
+
return /*#__PURE__*/(0,react_namespaceObject.css)("height:40px;padding:11px 15px 9px 10px;font-size:14px;font-weight:500;color:", theme.colors.greyDarker, ";border:1px solid ", borderColor, ";border-radius:12px;background:", theme.colors.white, ";max-width:250px;svg path{stroke:", theme.colors.greyDarker, ";}&:disabled{background:", theme.colors.greyLighter, ";border-color:", theme.colors.grey, ";color:", theme.colors.greyDarker60, ";cursor:default;svg path{stroke:", theme.colors.grey, ";}}&:focus:not(:disabled){border-color:", theme.palette.primary.main, ";}&:hover:not(:disabled){border-color:", isOpen ? theme.palette.primary.main : theme.colors.greyDarker80, ";}" + ( true ? "" : 0), true ? "" : 0);
|
|
20630
20630
|
};
|
|
20631
20631
|
const DropdownToggleBase = /*#__PURE__*/base_default()("button", true ? {
|
|
20632
20632
|
target: "er3kf7h0"
|
|
20633
|
-
} : 0)("display:flex;flex-flow:row nowrap;align-items:center;justify-content:
|
|
20633
|
+
} : 0)("display:flex;flex-flow:row nowrap;align-items:center;justify-content:space-between;gap:8px;position:relative;width:auto;height:44px;padding:0 14px;font:inherit;font-size:14px;font-weight:500;text-align:left;line-height:18px;cursor:pointer;outline:inherit;border-radius:12px;", ({
|
|
20634
20634
|
isMultiple,
|
|
20635
20635
|
isOpen,
|
|
20636
20636
|
disabled,
|
|
@@ -28423,6 +28423,207 @@ const SearchBox = ({
|
|
|
28423
28423
|
|
|
28424
28424
|
|
|
28425
28425
|
|
|
28426
|
+
;// ./src/components/FileAttachment/utils.ts
|
|
28427
|
+
const formatBytes = bytes => {
|
|
28428
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
28429
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
28430
|
+
return `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
28431
|
+
};
|
|
28432
|
+
const EXTENSION_ICON_MAP = {
|
|
28433
|
+
pdf: 'file-pdf',
|
|
28434
|
+
doc: 'file-word',
|
|
28435
|
+
docx: 'file-word',
|
|
28436
|
+
xls: 'excel-download',
|
|
28437
|
+
xlsx: 'excel-download'
|
|
28438
|
+
};
|
|
28439
|
+
|
|
28440
|
+
/** Returns the file-type icon for a known extension, or `null` when the design's grey Placeholder look should be used instead. */
|
|
28441
|
+
const getFileTypeIcon = fileName => {
|
|
28442
|
+
const extension = fileName.split('.').pop()?.toLowerCase();
|
|
28443
|
+
return extension && EXTENSION_ICON_MAP[extension] || null;
|
|
28444
|
+
};
|
|
28445
|
+
const IMAGE_FILE_NAME_REGEX = /\.(png|jpe?g|gif|webp|bmp|avif|svg)$/i;
|
|
28446
|
+
|
|
28447
|
+
/** Gates image-preview rendering strictly on the file name's extension, so a pdf/php/etc. is never rendered via `<img>` even if preview data is (incorrectly) supplied for it. */
|
|
28448
|
+
const isImageFile = fileName => IMAGE_FILE_NAME_REGEX.test(fileName);
|
|
28449
|
+
;// ./src/components/FileAttachment/hooks/useFilePreviewUrl.ts
|
|
28450
|
+
|
|
28451
|
+
|
|
28452
|
+
/** Creates an object URL for a local File/Blob and revokes it on unmount or when `content` changes, avoiding a memory leak. */
|
|
28453
|
+
const useFilePreviewUrl = content => {
|
|
28454
|
+
const [url, setUrl] = (0,external_react_namespaceObject.useState)();
|
|
28455
|
+
(0,external_react_namespaceObject.useEffect)(() => {
|
|
28456
|
+
if (!content) {
|
|
28457
|
+
setUrl(undefined);
|
|
28458
|
+
return;
|
|
28459
|
+
}
|
|
28460
|
+
const objectUrl = URL.createObjectURL(content);
|
|
28461
|
+
setUrl(objectUrl);
|
|
28462
|
+
return () => URL.revokeObjectURL(objectUrl);
|
|
28463
|
+
}, [content]);
|
|
28464
|
+
return url;
|
|
28465
|
+
};
|
|
28466
|
+
;// ./src/components/FileAttachment/styles.ts
|
|
28467
|
+
function FileAttachment_styles_EMOTION_STRINGIFIED_CSS_ERROR_() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
|
|
28468
|
+
|
|
28469
|
+
const paddingBySize = {
|
|
28470
|
+
large: 16,
|
|
28471
|
+
small: 12
|
|
28472
|
+
};
|
|
28473
|
+
const iconSizeBySize = {
|
|
28474
|
+
large: 40,
|
|
28475
|
+
small: 24
|
|
28476
|
+
};
|
|
28477
|
+
/** Placeholder glyph is inset ~20% on each side of its box in the design (40px box -> 24px glyph). */
|
|
28478
|
+
const placeholderIconSizeBySize = {
|
|
28479
|
+
large: 24,
|
|
28480
|
+
small: 14
|
|
28481
|
+
};
|
|
28482
|
+
const container = (theme, size) => /*#__PURE__*/(0,react_namespaceObject.css)("display:flex;align-items:center;gap:8px;width:100%;padding:", paddingBySize[size], "px;background:", theme.colors.white, ";border:1px solid ", theme.colors.grey, ";border-radius:12px;" + ( true ? "" : 0), true ? "" : 0);
|
|
28483
|
+
const disabledContainer = theme => /*#__PURE__*/(0,react_namespaceObject.css)("background:", theme.colors.greyLighter, ";" + ( true ? "" : 0), true ? "" : 0);
|
|
28484
|
+
const iconWrapper = size => /*#__PURE__*/(0,react_namespaceObject.css)("flex-shrink:0;display:flex;align-items:center;justify-content:center;width:", iconSizeBySize[size], "px;height:", iconSizeBySize[size], "px;" + ( true ? "" : 0), true ? "" : 0);
|
|
28485
|
+
const placeholderWrapper = theme => /*#__PURE__*/(0,react_namespaceObject.css)("background:", theme.palette.secondary.dark, ";border-radius:4px;" + ( true ? "" : 0), true ? "" : 0);
|
|
28486
|
+
const previewImage = true ? {
|
|
28487
|
+
name: "rys4i",
|
|
28488
|
+
styles: "width:100%;height:100%;border-radius:4px;object-fit:cover;display:block"
|
|
28489
|
+
} : 0;
|
|
28490
|
+
const textColumn = true ? {
|
|
28491
|
+
name: "1vjbjgs",
|
|
28492
|
+
styles: "flex:1;min-width:0;display:flex;flex-direction:column;gap:4px"
|
|
28493
|
+
} : 0;
|
|
28494
|
+
const title = theme => /*#__PURE__*/(0,react_namespaceObject.css)("font-size:0.875rem;font-weight:600;color:", theme.colors.greyDarker, ";overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" + ( true ? "" : 0), true ? "" : 0);
|
|
28495
|
+
const description = theme => /*#__PURE__*/(0,react_namespaceObject.css)("display:flex;align-items:center;gap:6px;font-size:0.875rem;font-weight:500;color:", theme.colors.greyDarker60, ";white-space:nowrap;" + ( true ? "" : 0), true ? "" : 0);
|
|
28496
|
+
const dot = theme => /*#__PURE__*/(0,react_namespaceObject.css)("flex-shrink:0;width:4px;height:4px;border-radius:50%;background:", theme.colors.greyDarker60, ";" + ( true ? "" : 0), true ? "" : 0);
|
|
28497
|
+
const progressTrack = theme => /*#__PURE__*/(0,react_namespaceObject.css)("position:relative;flex-shrink:0;overflow:hidden;width:60px;height:4px;border-radius:4px;background:", theme.palette.secondary.light, ";" + ( true ? "" : 0), true ? "" : 0);
|
|
28498
|
+
const progressFill = theme => /*#__PURE__*/(0,react_namespaceObject.css)("position:absolute;top:0;left:0;height:4px;border-radius:4px;background:", theme.palette.primary.main, ";" + ( true ? "" : 0), true ? "" : 0);
|
|
28499
|
+
const deleteButton = theme => /*#__PURE__*/(0,react_namespaceObject.css)("flex-shrink:0;display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;border:none;cursor:pointer;color:", theme.colors.greyDarker60, ";transition:color 0.15s ease;&:hover{color:", theme.palette.error.main, ";}&:disabled{cursor:default;color:", theme.colors.grey, ";}" + ( true ? "" : 0), true ? "" : 0);
|
|
28500
|
+
;// ./src/components/FileAttachment/FileAttachment.tsx
|
|
28501
|
+
|
|
28502
|
+
|
|
28503
|
+
|
|
28504
|
+
|
|
28505
|
+
|
|
28506
|
+
|
|
28507
|
+
/**
|
|
28508
|
+
* FileAttachment - Read-only row displaying a single attached/uploading file
|
|
28509
|
+
*
|
|
28510
|
+
* @example
|
|
28511
|
+
* ```tsx
|
|
28512
|
+
* <FileAttachment
|
|
28513
|
+
* file={{ name: 'Report.pdf', size: 20 * 1024 * 1024 }}
|
|
28514
|
+
* progress={50}
|
|
28515
|
+
* onRemove={() => handleRemove(file)}
|
|
28516
|
+
* />
|
|
28517
|
+
* ```
|
|
28518
|
+
*
|
|
28519
|
+
* @example
|
|
28520
|
+
* ```tsx
|
|
28521
|
+
* // Progress bar look instead of the default percentage text
|
|
28522
|
+
* <FileAttachment
|
|
28523
|
+
* file={{ name: 'Report.pdf', size: 20 * 1024 * 1024 }}
|
|
28524
|
+
* progress={50}
|
|
28525
|
+
* progressDisplay="bar"
|
|
28526
|
+
* onRemove={() => handleRemove(file)}
|
|
28527
|
+
* />
|
|
28528
|
+
* ```
|
|
28529
|
+
*
|
|
28530
|
+
* @example
|
|
28531
|
+
* ```tsx
|
|
28532
|
+
* // Omitting `progress` entirely shows just the file size, no progress copy —
|
|
28533
|
+
* // e.g. a file that's been selected but whose upload hasn't started yet.
|
|
28534
|
+
* <FileAttachment
|
|
28535
|
+
* file={{ name: 'Report.pdf', size: 20 * 1024 * 1024 }}
|
|
28536
|
+
* onRemove={() => handleRemove(file)}
|
|
28537
|
+
* />
|
|
28538
|
+
* ```
|
|
28539
|
+
*/
|
|
28540
|
+
|
|
28541
|
+
const FileAttachment = ({
|
|
28542
|
+
file,
|
|
28543
|
+
size = 'large',
|
|
28544
|
+
progress,
|
|
28545
|
+
progressDisplay = 'text',
|
|
28546
|
+
uploadingText = 'Uploading',
|
|
28547
|
+
uploadedText = 'Uploaded Successfully',
|
|
28548
|
+
showDescription = true,
|
|
28549
|
+
icon,
|
|
28550
|
+
isDisabled = false,
|
|
28551
|
+
onRemove,
|
|
28552
|
+
className,
|
|
28553
|
+
css: cssProp
|
|
28554
|
+
}) => {
|
|
28555
|
+
const theme = (0,react_namespaceObject.useTheme)();
|
|
28556
|
+
const clampedProgress = progress === undefined ? undefined : Math.min(100, Math.max(0, progress));
|
|
28557
|
+
const isUploaded = clampedProgress !== undefined && clampedProgress >= 100;
|
|
28558
|
+
const iconName = icon ?? getFileTypeIcon(file.name);
|
|
28559
|
+
const canPreviewImage = !icon && isImageFile(file.name);
|
|
28560
|
+
const objectPreviewUrl = useFilePreviewUrl(canPreviewImage ? file.content : undefined);
|
|
28561
|
+
const previewSrc = canPreviewImage ? file.previewUrl ?? objectPreviewUrl : undefined;
|
|
28562
|
+
return (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28563
|
+
css: [container(theme, size), isDisabled && disabledContainer(theme), cssProp, true ? "" : 0, true ? "" : 0],
|
|
28564
|
+
className: className,
|
|
28565
|
+
children: [(0,jsx_runtime_namespaceObject.jsx)("div", {
|
|
28566
|
+
css: [iconWrapper(size), !iconName && !previewSrc && placeholderWrapper(theme), true ? "" : 0, true ? "" : 0],
|
|
28567
|
+
children: previewSrc ? (0,jsx_runtime_namespaceObject.jsx)("img", {
|
|
28568
|
+
src: previewSrc,
|
|
28569
|
+
alt: "",
|
|
28570
|
+
css: previewImage
|
|
28571
|
+
}) : (0,jsx_runtime_namespaceObject.jsx)(Icon_Icon, {
|
|
28572
|
+
name: iconName ?? 'picture',
|
|
28573
|
+
size: iconName ? iconSizeBySize[size] : placeholderIconSizeBySize[size],
|
|
28574
|
+
color: iconName ? theme.colors.greyDarker60 : theme.colors.white
|
|
28575
|
+
})
|
|
28576
|
+
}), (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28577
|
+
css: textColumn,
|
|
28578
|
+
children: [(0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28579
|
+
css: title(theme),
|
|
28580
|
+
children: file.name
|
|
28581
|
+
}), showDescription && (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28582
|
+
css: description(theme),
|
|
28583
|
+
children: [(0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28584
|
+
children: formatBytes(file.size)
|
|
28585
|
+
}), clampedProgress !== undefined && (0,jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
|
|
28586
|
+
children: [(0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28587
|
+
children: "|"
|
|
28588
|
+
}), progressDisplay === 'bar' ? (0,jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
|
|
28589
|
+
children: [(0,jsx_runtime_namespaceObject.jsx)("div", {
|
|
28590
|
+
css: progressTrack(theme),
|
|
28591
|
+
role: "progressbar",
|
|
28592
|
+
children: (0,jsx_runtime_namespaceObject.jsx)("div", {
|
|
28593
|
+
css: progressFill(theme),
|
|
28594
|
+
style: {
|
|
28595
|
+
width: `${clampedProgress}%`
|
|
28596
|
+
}
|
|
28597
|
+
})
|
|
28598
|
+
}), (0,jsx_runtime_namespaceObject.jsxs)("span", {
|
|
28599
|
+
children: [clampedProgress, "%"]
|
|
28600
|
+
})]
|
|
28601
|
+
}) : (0,jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
|
|
28602
|
+
children: [(0,jsx_runtime_namespaceObject.jsxs)("span", {
|
|
28603
|
+
children: [clampedProgress, "%"]
|
|
28604
|
+
}), (0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28605
|
+
css: dot(theme)
|
|
28606
|
+
}), (0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28607
|
+
children: isUploaded ? uploadedText : uploadingText
|
|
28608
|
+
})]
|
|
28609
|
+
})]
|
|
28610
|
+
})]
|
|
28611
|
+
})]
|
|
28612
|
+
}), onRemove && (0,jsx_runtime_namespaceObject.jsx)("button", {
|
|
28613
|
+
type: "button",
|
|
28614
|
+
css: deleteButton(theme),
|
|
28615
|
+
disabled: isDisabled,
|
|
28616
|
+
onClick: onRemove,
|
|
28617
|
+
"aria-label": `Remove ${file.name}`,
|
|
28618
|
+
children: (0,jsx_runtime_namespaceObject.jsx)(Icon_Icon, {
|
|
28619
|
+
name: "delete",
|
|
28620
|
+
size: 16,
|
|
28621
|
+
color: "currentColor"
|
|
28622
|
+
})
|
|
28623
|
+
})]
|
|
28624
|
+
});
|
|
28625
|
+
};
|
|
28626
|
+
/* harmony default export */ const FileAttachment_FileAttachment = (FileAttachment);
|
|
28426
28627
|
;// ./src/components/FileUpload/styles.ts
|
|
28427
28628
|
function FileUpload_styles_EMOTION_STRINGIFIED_CSS_ERROR_() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
|
|
28428
28629
|
|
|
@@ -28461,71 +28662,6 @@ const filesList = true ? {
|
|
|
28461
28662
|
styles: "display:flex;flex-direction:column;gap:8px;margin-top:12px"
|
|
28462
28663
|
} : 0;
|
|
28463
28664
|
const filesListTitle = theme => /*#__PURE__*/(0,react_namespaceObject.css)("font-size:0.875rem;font-weight:500;color:", theme.colors.greyDarker, ";margin-bottom:4px;" + ( true ? "" : 0), true ? "" : 0);
|
|
28464
|
-
|
|
28465
|
-
// ─── File item ────────────────────────────────────────────────────────────────
|
|
28466
|
-
|
|
28467
|
-
const fileItem = theme => /*#__PURE__*/(0,react_namespaceObject.css)("display:flex;align-items:center;gap:12px;padding:12px 16px;background:", theme.colors.white, ";border:1px solid ", theme.colors.grey, ";border-radius:12px;" + ( true ? "" : 0), true ? "" : 0);
|
|
28468
|
-
const fileIconWrapper = true ? {
|
|
28469
|
-
name: "1xuq60z",
|
|
28470
|
-
styles: "flex-shrink:0;display:flex;align-items:center;justify-content:center"
|
|
28471
|
-
} : 0;
|
|
28472
|
-
const fileInfo = true ? {
|
|
28473
|
-
name: "1k33dov",
|
|
28474
|
-
styles: "flex:1;display:flex;flex-direction:column;gap:2px;min-width:0"
|
|
28475
|
-
} : 0;
|
|
28476
|
-
const fileName = theme => /*#__PURE__*/(0,react_namespaceObject.css)("font-size:0.875rem;font-weight:600;color:", theme.colors.greyDarker, ";overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" + ( true ? "" : 0), true ? "" : 0);
|
|
28477
|
-
const fileSize = theme => /*#__PURE__*/(0,react_namespaceObject.css)("font-size:0.75rem;font-weight:400;color:", theme.colors.greyDarker60, ";" + ( true ? "" : 0), true ? "" : 0);
|
|
28478
|
-
const deleteButton = theme => /*#__PURE__*/(0,react_namespaceObject.css)("flex-shrink:0;display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:none;border-radius:8px;cursor:pointer;color:", theme.colors.greyDarker60, ";transition:color 0.15s ease,background 0.15s ease;&:hover{color:", theme.palette.error.main, ";background:", theme.colors.greyLighter, ";}&:disabled{cursor:not-allowed;opacity:0.5;}" + ( true ? "" : 0), true ? "" : 0);
|
|
28479
|
-
;// ./src/components/FileUpload/FileUploadItem.tsx
|
|
28480
|
-
|
|
28481
|
-
|
|
28482
|
-
|
|
28483
|
-
|
|
28484
|
-
const formatFileSize = bytes => {
|
|
28485
|
-
if (bytes === 0) return '0 B';
|
|
28486
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
28487
|
-
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
28488
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
28489
|
-
};
|
|
28490
|
-
const FileUploadItem = ({
|
|
28491
|
-
file,
|
|
28492
|
-
onRemove,
|
|
28493
|
-
disabled
|
|
28494
|
-
}) => {
|
|
28495
|
-
const theme = (0,react_namespaceObject.useTheme)();
|
|
28496
|
-
return (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28497
|
-
css: fileItem(theme),
|
|
28498
|
-
children: [(0,jsx_runtime_namespaceObject.jsx)("div", {
|
|
28499
|
-
css: fileIconWrapper,
|
|
28500
|
-
children: (0,jsx_runtime_namespaceObject.jsx)(Icon_Icon, {
|
|
28501
|
-
name: "file-pdf",
|
|
28502
|
-
size: 32,
|
|
28503
|
-
color: theme.colors.greyDarker60
|
|
28504
|
-
})
|
|
28505
|
-
}), (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28506
|
-
css: fileInfo,
|
|
28507
|
-
children: [(0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28508
|
-
css: fileName(theme),
|
|
28509
|
-
children: file.name
|
|
28510
|
-
}), (0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28511
|
-
css: fileSize(theme),
|
|
28512
|
-
children: formatFileSize(file.size)
|
|
28513
|
-
})]
|
|
28514
|
-
}), (0,jsx_runtime_namespaceObject.jsx)("button", {
|
|
28515
|
-
css: deleteButton(theme),
|
|
28516
|
-
type: "button",
|
|
28517
|
-
disabled: disabled,
|
|
28518
|
-
onClick: () => onRemove(file),
|
|
28519
|
-
"aria-label": `Remove ${file.name}`,
|
|
28520
|
-
children: (0,jsx_runtime_namespaceObject.jsx)(Icon_Icon, {
|
|
28521
|
-
name: "bin",
|
|
28522
|
-
size: 16,
|
|
28523
|
-
color: "currentColor"
|
|
28524
|
-
})
|
|
28525
|
-
})]
|
|
28526
|
-
});
|
|
28527
|
-
};
|
|
28528
|
-
/* harmony default export */ const FileUpload_FileUploadItem = (FileUploadItem);
|
|
28529
28665
|
;// ./src/components/FileUpload/FileUpload.tsx
|
|
28530
28666
|
|
|
28531
28667
|
|
|
@@ -28536,14 +28672,23 @@ const FileUploadItem = ({
|
|
|
28536
28672
|
|
|
28537
28673
|
|
|
28538
28674
|
|
|
28675
|
+
|
|
28539
28676
|
const normalizeValue = value => {
|
|
28540
28677
|
if (!value) return [];
|
|
28541
28678
|
return Array.isArray(value) ? value : [value];
|
|
28542
28679
|
};
|
|
28543
|
-
|
|
28544
|
-
|
|
28545
|
-
|
|
28546
|
-
|
|
28680
|
+
|
|
28681
|
+
/**
|
|
28682
|
+
* Matches by the Nth occurrence of a name rather than the first, so files
|
|
28683
|
+
* that share a name (e.g. two "photo.png" from different folders) each get
|
|
28684
|
+
* their own progress entry instead of colliding on the same one.
|
|
28685
|
+
*/
|
|
28686
|
+
const getFileProgress = (file, index, files, uploadProgress) => {
|
|
28687
|
+
if (uploadProgress === undefined) return undefined;
|
|
28688
|
+
if (typeof uploadProgress === 'number') return uploadProgress;
|
|
28689
|
+
const occurrence = files.slice(0, index + 1).filter(f => f.name === file.name).length;
|
|
28690
|
+
const matches = uploadProgress.filter(entry => entry.name === file.name);
|
|
28691
|
+
return matches[occurrence - 1]?.progress;
|
|
28547
28692
|
};
|
|
28548
28693
|
|
|
28549
28694
|
/**
|
|
@@ -28551,7 +28696,8 @@ const formatBytes = bytes => {
|
|
|
28551
28696
|
*
|
|
28552
28697
|
* Supports single and multi-file selection with built-in validation for
|
|
28553
28698
|
* file formats and size. In multi-file mode, selected files are listed
|
|
28554
|
-
* below the input with individual remove controls.
|
|
28699
|
+
* below the input with individual remove controls. Single-file mode can opt
|
|
28700
|
+
* into the same list treatment via `showFileAttachment`.
|
|
28555
28701
|
*
|
|
28556
28702
|
* @example
|
|
28557
28703
|
* ```tsx
|
|
@@ -28579,6 +28725,36 @@ const formatBytes = bytes => {
|
|
|
28579
28725
|
* onChange={setFiles}
|
|
28580
28726
|
* />
|
|
28581
28727
|
* ```
|
|
28728
|
+
*
|
|
28729
|
+
* @example
|
|
28730
|
+
* ```tsx
|
|
28731
|
+
* // Multi-file with per-file upload progress, driven by the consumer's own
|
|
28732
|
+
* // upload requests — FileUpload only handles local selection, so it has no
|
|
28733
|
+
* // progress data of its own.
|
|
28734
|
+
* <FileUpload
|
|
28735
|
+
* isMultiFile
|
|
28736
|
+
* value={files}
|
|
28737
|
+
* onChange={setFiles}
|
|
28738
|
+
* uploadProgress={[
|
|
28739
|
+
* { name: 'report.pdf', progress: 50 },
|
|
28740
|
+
* { name: 'photo.png', progress: 100 },
|
|
28741
|
+
* ]}
|
|
28742
|
+
* />
|
|
28743
|
+
* ```
|
|
28744
|
+
*
|
|
28745
|
+
* @example
|
|
28746
|
+
* ```tsx
|
|
28747
|
+
* // Single file, shown as a FileAttachment card below the input (icon,
|
|
28748
|
+
* // size, delete button, image preview) instead of inline text next to the
|
|
28749
|
+
* // button. `uploadProgress` here can just be a single number, since there's
|
|
28750
|
+
* // only ever one file.
|
|
28751
|
+
* <FileUpload
|
|
28752
|
+
* showFileAttachment
|
|
28753
|
+
* value={file}
|
|
28754
|
+
* onChange={(files) => setFile(files[0])}
|
|
28755
|
+
* uploadProgress={70}
|
|
28756
|
+
* />
|
|
28757
|
+
* ```
|
|
28582
28758
|
*/
|
|
28583
28759
|
const FileUpload = ({
|
|
28584
28760
|
label,
|
|
@@ -28595,6 +28771,8 @@ const FileUpload = ({
|
|
|
28595
28771
|
maxFiles,
|
|
28596
28772
|
withDropArea = false,
|
|
28597
28773
|
uploadedSectionTitle,
|
|
28774
|
+
uploadProgress,
|
|
28775
|
+
showFileAttachment = false,
|
|
28598
28776
|
value,
|
|
28599
28777
|
onChange,
|
|
28600
28778
|
onFileRejected
|
|
@@ -28657,8 +28835,8 @@ const FileUpload = ({
|
|
|
28657
28835
|
};
|
|
28658
28836
|
const acceptAttr = allowedFormats?.map(f => `.${f}`).join(',');
|
|
28659
28837
|
const hasError = !!error;
|
|
28660
|
-
const inlineFileName = !isMultiFile && files[0]?.name;
|
|
28661
|
-
const
|
|
28838
|
+
const inlineFileName = !isMultiFile && !showFileAttachment && files[0]?.name;
|
|
28839
|
+
const attachmentFiles = isMultiFile || showFileAttachment && !withDropArea ? files : [];
|
|
28662
28840
|
return (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28663
28841
|
css: [wrapper, css, true ? "" : 0, true ? "" : 0],
|
|
28664
28842
|
className: className,
|
|
@@ -28684,7 +28862,7 @@ const FileUpload = ({
|
|
|
28684
28862
|
onKeyDown: e => e.key === 'Enter' && !files[0] && handleChooseClick(),
|
|
28685
28863
|
children: !isMultiFile && files[0] ? (0,jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
|
|
28686
28864
|
children: [(0,jsx_runtime_namespaceObject.jsx)(Icon_Icon, {
|
|
28687
|
-
name:
|
|
28865
|
+
name: getFileTypeIcon(files[0].name) ?? 'picture',
|
|
28688
28866
|
size: 36,
|
|
28689
28867
|
color: theme.colors.greyDarker60
|
|
28690
28868
|
}), (0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
@@ -28741,15 +28919,20 @@ const FileUpload = ({
|
|
|
28741
28919
|
marginTop: 12
|
|
28742
28920
|
} : undefined,
|
|
28743
28921
|
children: error || helperText
|
|
28744
|
-
}),
|
|
28922
|
+
}), attachmentFiles.length > 0 && (0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
28745
28923
|
css: filesList,
|
|
28746
28924
|
children: [uploadedSectionTitle && (0,jsx_runtime_namespaceObject.jsx)("span", {
|
|
28747
28925
|
css: filesListTitle(theme),
|
|
28748
28926
|
children: uploadedSectionTitle
|
|
28749
|
-
}),
|
|
28750
|
-
file:
|
|
28751
|
-
|
|
28752
|
-
|
|
28927
|
+
}), attachmentFiles.map((file, index) => (0,jsx_runtime_namespaceObject.jsx)(FileAttachment_FileAttachment, {
|
|
28928
|
+
file: {
|
|
28929
|
+
name: file.name,
|
|
28930
|
+
size: file.size,
|
|
28931
|
+
content: file
|
|
28932
|
+
},
|
|
28933
|
+
progress: getFileProgress(file, index, files, uploadProgress),
|
|
28934
|
+
onRemove: () => handleRemove(file),
|
|
28935
|
+
isDisabled: disabled
|
|
28753
28936
|
}, `${file.name}-${index}`))]
|
|
28754
28937
|
})]
|
|
28755
28938
|
});
|
|
@@ -53986,7 +54169,7 @@ function History_styles_EMOTION_STRINGIFIED_CSS_ERROR_() { return "You have trie
|
|
|
53986
54169
|
|
|
53987
54170
|
const FIRST_LINE_TOP_PADDING = 2;
|
|
53988
54171
|
const FIRST_LINE_HEIGHT = 20;
|
|
53989
|
-
const
|
|
54172
|
+
const styles_container = true ? {
|
|
53990
54173
|
name: "1fttcpj",
|
|
53991
54174
|
styles: "display:flex;flex-direction:column"
|
|
53992
54175
|
} : 0;
|
|
@@ -54053,7 +54236,7 @@ const History_History = ({
|
|
|
54053
54236
|
const circleTopOffset = Math.max(0, FIRST_LINE_TOP_PADDING + (FIRST_LINE_HEIGHT - circleSize) / 2);
|
|
54054
54237
|
return (0,jsx_runtime_namespaceObject.jsx)("div", {
|
|
54055
54238
|
"data-testid": "history",
|
|
54056
|
-
css:
|
|
54239
|
+
css: styles_container,
|
|
54057
54240
|
style: sx,
|
|
54058
54241
|
children: items.map((item, index) => {
|
|
54059
54242
|
const isLast = index === items.length - 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssa-ui-kit/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"luxon": "3.5.0",
|
|
40
40
|
"plotly.js": "3.0.0",
|
|
41
41
|
"react-plotly.js": "2.6.0",
|
|
42
|
-
"@ssa-ui-kit/
|
|
43
|
-
"@ssa-ui-kit/
|
|
42
|
+
"@ssa-ui-kit/hooks": "^3.17.0",
|
|
43
|
+
"@ssa-ui-kit/utils": "^3.17.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@emotion/css": "11.13.5",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
interface FileUploadItemProps {
|
|
2
|
-
file: File;
|
|
3
|
-
onRemove: (file: File) => void;
|
|
4
|
-
disabled?: boolean;
|
|
5
|
-
}
|
|
6
|
-
declare const FileUploadItem: ({ file, onRemove, disabled }: FileUploadItemProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
7
|
-
export default FileUploadItem;
|