@lifesg/web-frontend-engine 1.19.18 → 1.19.20
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/chunks/{file-upload-manager.58d10a8b.js → file-upload-manager.072099ea.js} +2 -2
- package/chunks/file-upload-manager.072099ea.js.map +1 -0
- package/chunks/{index.2a117e92.js → index.0dbde68f.js} +10 -8
- package/chunks/{index.2a117e92.js.map → index.0dbde68f.js.map} +1 -1
- package/chunks/{index.3396b1bb.js → index.2a176c7d.js} +2 -2
- package/chunks/{index.3396b1bb.js.map → index.2a176c7d.js.map} +1 -1
- package/chunks/{index.e11ec601.js → index.2cd8e0dd.js} +2 -2
- package/chunks/{index.e11ec601.js.map → index.2cd8e0dd.js.map} +1 -1
- package/chunks/{location-modal.559a916a.js → location-modal.54ab5d47.js} +2 -2
- package/chunks/{location-modal.559a916a.js.map → location-modal.54ab5d47.js.map} +1 -1
- package/cjs/chunks/{file-upload-manager.3328a5eb.js → file-upload-manager.b0dc7ccd.js} +2 -2
- package/cjs/chunks/file-upload-manager.b0dc7ccd.js.map +1 -0
- package/cjs/chunks/{index.252a45d0.js → index.b96b1565.js} +2 -2
- package/cjs/chunks/{index.252a45d0.js.map → index.b96b1565.js.map} +1 -1
- package/cjs/chunks/{index.62020cb0.js → index.bb56604f.js} +10 -8
- package/cjs/chunks/{index.62020cb0.js.map → index.bb56604f.js.map} +1 -1
- package/cjs/chunks/{index.f8611425.js → index.e6c89bb0.js} +2 -2
- package/cjs/chunks/{index.f8611425.js.map → index.e6c89bb0.js.map} +1 -1
- package/cjs/chunks/{location-modal.17dc94b3.js → location-modal.c6e65d41.js} +2 -2
- package/cjs/chunks/{location-modal.17dc94b3.js.map → location-modal.c6e65d41.js.map} +1 -1
- package/cjs/index.js +1 -1
- package/components/custom/array-field/array-field.styles.d.ts +4 -1
- package/components/custom/array-field/types.d.ts +14 -5
- package/components/custom/types.d.ts +1 -1
- package/components/shared/error-messages.d.ts +3 -0
- package/context-providers/yup/types.d.ts +8 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/chunks/file-upload-manager.58d10a8b.js.map +0 -1
- package/cjs/chunks/file-upload-manager.3328a5eb.js.map +0 -1
package/cjs/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./chunks/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./chunks/index.bb56604f.js");require("react/jsx-runtime"),require("@lifesg/react-design-system/box-container"),require("@lifesg/react-design-system/button"),require("@lifesg/react-design-system/layout"),require("react"),require("@lifesg/react-design-system/alert"),require("@lifesg/react-design-system/text"),require("@lifesg/react-icons"),require("@lifesg/react-icons/plus-circle-fill"),require("@lifesg/react-design-system/markup"),require("react-dom/server"),require("@lifesg/react-design-system/media"),require("@lifesg/react-design-system/filter"),require("@lifesg/react-design-system/uneditable-section"),require("@lifesg/react-design-system/timeline"),require("@lifesg/react-design-system/form"),require("@lifesg/react-design-system/toggle"),require("@lifesg/react-design-system/text-list"),require("@lifesg/react-design-system/popover-v2"),require("@lifesg/react-design-system/tab"),require("@lifesg/react-design-system/color"),require("styled-components"),require("@lifesg/react-design-system/modal"),require("@lifesg/react-design-system/divider"),require("@lifesg/react-design-system/button-with-icon"),require("@lifesg/react-design-system/error-display"),require("@lifesg/react-design-system/checkbox"),require("@lifesg/react-design-system/file-upload"),require("@lifesg/react-icons/cross"),require("@lifesg/react-design-system/icon-button"),require("@lifesg/react-icons/bin"),require("@lifesg/react-icons/eraser"),require("@lifesg/react-icons/pencil"),require("@lifesg/react-icons/pencil-stroke"),require("@lifesg/react-design-system"),require("@lifesg/react-icons/plus"),require("@lifesg/react-icons/exclamation-triangle"),require("@lifesg/react-icons/pin-fill"),require("@lifesg/react-design-system/design-token"),require("@lifesg/react-design-system/image-button"),require("@lifesg/react-design-system/radio-button"),Object.defineProperty(exports,"EElementType",{enumerable:!0,get:function(){return e.EElementType}}),Object.defineProperty(exports,"EFieldType",{enumerable:!0,get:function(){return e.EFieldType}}),exports.FrontendEngine=e.FrontendEngine,exports.useFrontendEngineComponent=e.useFrontendEngineComponent;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
interface InsetStyleProps {
|
|
3
3
|
$inset?: string | number;
|
|
4
4
|
}
|
|
5
|
+
interface RemoveButtonStyleProps {
|
|
6
|
+
$alignment?: "left" | "right";
|
|
7
|
+
}
|
|
5
8
|
export declare const Inset: import("styled-components").StyledComponent<"div", any, InsetStyleProps, never>;
|
|
6
9
|
export declare const SectionHeader: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
7
|
-
export declare const RemoveButton: import("styled-components").StyledComponent<(props: import("@lifesg/react-design-system/button-with-icon").ButtonWithIconProps & import("react").RefAttributes<HTMLButtonElement>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>, any,
|
|
10
|
+
export declare const RemoveButton: import("styled-components").StyledComponent<(props: import("@lifesg/react-design-system/button-with-icon").ButtonWithIconProps & import("react").RefAttributes<HTMLButtonElement>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>, any, RemoveButtonStyleProps, never>;
|
|
8
11
|
export declare const AddButton: import("styled-components").StyledComponent<(props: import("@lifesg/react-design-system/button-with-icon").ButtonWithIconProps & import("react").RefAttributes<HTMLButtonElement>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>, any, {}, never>;
|
|
9
12
|
export declare const SectionDivider: import("styled-components").StyledComponent<({ thickness, lineStyle, layoutType, color, className, mobileCols, tabletCols, desktopCols, ...otherProps }: import("@lifesg/react-design-system/divider").DividerProps) => import("react/jsx-runtime").JSX.Element, any, {}, never>;
|
|
10
13
|
export declare const WarningAlert: import("styled-components").StyledComponent<({ id, message, className }: import("../../shared").IWarningProps) => import("react/jsx-runtime").JSX.Element, any, {}, never>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ButtonStyleType } from "@lifesg/react-design-system/button/types";
|
|
1
2
|
import * as Icons from "@lifesg/react-icons";
|
|
2
3
|
import { IYupValidationRule, TFrontendEngineFieldSchema } from "../../frontend-engine/types";
|
|
3
4
|
import { IBaseCustomFieldSchema } from "../types";
|
|
@@ -8,16 +9,24 @@ export interface IArrayFieldValidationRule extends IYupValidationRule {
|
|
|
8
9
|
export interface IArrayFieldButton {
|
|
9
10
|
label?: string | undefined;
|
|
10
11
|
icon?: keyof typeof Icons | undefined;
|
|
12
|
+
styleType?: ButtonStyleType | undefined;
|
|
11
13
|
}
|
|
12
|
-
export interface
|
|
13
|
-
|
|
14
|
+
export interface IArrayFieldRemoveButton extends IArrayFieldButton {
|
|
15
|
+
position?: "top" | "bottom" | undefined;
|
|
16
|
+
alignment?: "left" | "right" | undefined;
|
|
14
17
|
}
|
|
15
|
-
export
|
|
16
|
-
|
|
18
|
+
export type IArrayFieldRemoveConfirmationModal = {
|
|
19
|
+
skip: true;
|
|
20
|
+
} | {
|
|
21
|
+
skip?: false | undefined;
|
|
22
|
+
title?: string | undefined;
|
|
23
|
+
};
|
|
24
|
+
export interface IArrayFieldSchema<V = undefined, C = undefined> extends IBaseCustomFieldSchema<"array-field", V, IArrayFieldValidationRule> {
|
|
25
|
+
fieldSchema: Record<string, TFrontendEngineFieldSchema<V, C>>;
|
|
17
26
|
sectionInset?: number | string | undefined;
|
|
18
27
|
sectionTitle?: string | undefined;
|
|
19
28
|
showDivider?: boolean | undefined;
|
|
20
29
|
addButton?: IArrayFieldButton | undefined;
|
|
21
|
-
removeButton?:
|
|
30
|
+
removeButton?: IArrayFieldRemoveButton | undefined;
|
|
22
31
|
removeConfirmationModal?: IArrayFieldRemoveConfirmationModal | undefined;
|
|
23
32
|
}
|
|
@@ -31,7 +31,7 @@ export declare enum ECustomFieldType {
|
|
|
31
31
|
/**
|
|
32
32
|
* union type to represent all custom elements / fields schema
|
|
33
33
|
*/
|
|
34
|
-
export type TCustomSchema<V = undefined, C = undefined> = IArrayFieldSchema<V> | ICustomElementJsonSchema<string> | IFilterSchema<V, C> | IIframeSchema | ITimelineSchema<V, C> | TReviewSchema | C;
|
|
34
|
+
export type TCustomSchema<V = undefined, C = undefined> = IArrayFieldSchema<V, C> | ICustomElementJsonSchema<string> | IFilterSchema<V, C> | IIframeSchema | ITimelineSchema<V, C> | TReviewSchema | C;
|
|
35
35
|
/**
|
|
36
36
|
* intersection type to represent all field events
|
|
37
37
|
*/
|
|
@@ -51,6 +51,7 @@ export declare const ERROR_MESSAGES: {
|
|
|
51
51
|
MAX_FILE_SIZE: (maxSize: number) => string;
|
|
52
52
|
GENERIC: string;
|
|
53
53
|
FILE_TYPE: (acceptedFileTypes: string[]) => string;
|
|
54
|
+
UPLOADING: string;
|
|
54
55
|
MODAL: {
|
|
55
56
|
FILE_TYPE: {
|
|
56
57
|
TITLE: string;
|
|
@@ -78,5 +79,7 @@ export declare const ERROR_MESSAGES: {
|
|
|
78
79
|
ARRAY_FIELD: {
|
|
79
80
|
INVALID: string;
|
|
80
81
|
REQUIRED: string;
|
|
82
|
+
MIN: (min: number) => string;
|
|
83
|
+
MAX: (max: number) => string;
|
|
81
84
|
};
|
|
82
85
|
};
|
|
@@ -9,7 +9,6 @@ interface IYupRule {
|
|
|
9
9
|
max?: number | undefined;
|
|
10
10
|
matches?: string | undefined;
|
|
11
11
|
notMatches?: string | undefined;
|
|
12
|
-
noWhitespaceOnly?: boolean | undefined;
|
|
13
12
|
email?: boolean | undefined;
|
|
14
13
|
url?: boolean | undefined;
|
|
15
14
|
uuid?: boolean | undefined;
|
|
@@ -27,6 +26,11 @@ interface IYupRule {
|
|
|
27
26
|
uen?: boolean | undefined;
|
|
28
27
|
equalsField?: string | undefined;
|
|
29
28
|
notEqualsField?: string | undefined;
|
|
29
|
+
whitespace?: boolean | IWhitespaceRule | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use `whitespace` rule instead.
|
|
32
|
+
*/
|
|
33
|
+
noWhitespaceOnly?: boolean | undefined;
|
|
30
34
|
}
|
|
31
35
|
/**
|
|
32
36
|
* V and U generics are needed here to be passed into `then` and `otherwise` conditional validation
|
|
@@ -71,4 +75,7 @@ export interface IWithinDaysRangeRule extends IDaysRangeRule {
|
|
|
71
75
|
/** inclusive of today (or `fromDate` if specified). defaults to false, meaning today will fail validation */
|
|
72
76
|
inclusive?: boolean;
|
|
73
77
|
}
|
|
78
|
+
export interface IWhitespaceRule {
|
|
79
|
+
noLeadingOrTrailingWhitespace?: boolean | undefined;
|
|
80
|
+
}
|
|
74
81
|
export {};
|
package/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{o as EElementType,p as EFieldType,n as FrontendEngine,m as useFrontendEngineComponent}from"./chunks/index.
|
|
1
|
+
export{o as EElementType,p as EFieldType,n as FrontendEngine,m as useFrontendEngineComponent}from"./chunks/index.0dbde68f.js";import"react/jsx-runtime";import"@lifesg/react-design-system/box-container";import"@lifesg/react-design-system/button";import"@lifesg/react-design-system/layout";import"react";import"@lifesg/react-design-system/alert";import"@lifesg/react-design-system/text";import"@lifesg/react-icons";import"@lifesg/react-icons/plus-circle-fill";import"@lifesg/react-design-system/markup";import"react-dom/server";import"@lifesg/react-design-system/media";import"@lifesg/react-design-system/filter";import"@lifesg/react-design-system/uneditable-section";import"@lifesg/react-design-system/timeline";import"@lifesg/react-design-system/form";import"@lifesg/react-design-system/toggle";import"@lifesg/react-design-system/text-list";import"@lifesg/react-design-system/popover-v2";import"@lifesg/react-design-system/tab";import"@lifesg/react-design-system/color";import"styled-components";import"@lifesg/react-design-system/modal";import"@lifesg/react-design-system/divider";import"@lifesg/react-design-system/button-with-icon";import"@lifesg/react-design-system/error-display";import"@lifesg/react-design-system/checkbox";import"@lifesg/react-design-system/file-upload";import"@lifesg/react-icons/cross";import"@lifesg/react-design-system/icon-button";import"@lifesg/react-icons/bin";import"@lifesg/react-icons/eraser";import"@lifesg/react-icons/pencil";import"@lifesg/react-icons/pencil-stroke";import"@lifesg/react-design-system";import"@lifesg/react-icons/plus";import"@lifesg/react-icons/exclamation-triangle";import"@lifesg/react-icons/pin-fill";import"@lifesg/react-design-system/design-token";import"@lifesg/react-design-system/image-button";import"@lifesg/react-design-system/radio-button";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-manager.58d10a8b.js","sources":["../../src/components/fields/file-upload/file-upload-manager.ts"],"sourcesContent":["import { AxiosError } from \"axios\";\nimport { useContext, useEffect, useRef } from \"react\";\nimport { useFormContext } from \"react-hook-form\";\nimport { AxiosApiClient, FileHelper, ImageHelper, generateRandomId } from \"../../../utils\";\nimport { useFieldEvent, usePrevious } from \"../../../utils/hooks\";\nimport { ERROR_MESSAGES } from \"../../shared\";\nimport { FileUploadContext } from \"./file-upload-context\";\nimport {\n\tEFileStatus,\n\tIFile,\n\tIFileUploadSchema,\n\tIFileUploadValidationRule,\n\tIFileUploadValue,\n\tTUploadErrorDetail,\n} from \"./types\";\n\ninterface IProps {\n\tcompressImages: boolean;\n\tfileTypeRule: IFileUploadValidationRule;\n\thideThumbnail?: boolean | undefined;\n\tid: string;\n\tmaxFileSizeRule: IFileUploadValidationRule;\n\tupload: IFileUploadSchema[\"uploadOnAddingFile\"];\n\tuploadRule: IFileUploadValidationRule;\n\tvalue: IFileUploadValue[];\n}\n\nconst RESIZEABLE_IMAGE_TYPES = [\"image/jpeg\", \"image/gif\", \"image/png\"];\n\nconst FileUploadManager = (props: IProps) => {\n\t// =============================================================================\n\t// CONST, STATE, REFS\n\t// =============================================================================\n\tconst { compressImages, fileTypeRule, hideThumbnail, id, maxFileSizeRule, upload, uploadRule, value } = props;\n\tconst { files, setFiles, setCurrentFileIds } = useContext(FileUploadContext);\n\tconst previousValue = usePrevious(value);\n\tconst { setValue } = useFormContext();\n\tconst { dispatchFieldEvent } = useFieldEvent();\n\tconst sessionId = useRef<string>();\n\n\t// =============================================================================\n\t// EFFECTS\n\t// =============================================================================\n\tuseEffect(() => {\n\t\tsessionId.current = generateRandomId();\n\t}, []);\n\n\tuseEffect(\n\t\t() => {\n\t\t\t// handle file status\n\t\t\tfiles.forEach(async (file, index) => {\n\t\t\t\ttry {\n\t\t\t\t\tswitch (file.status) {\n\t\t\t\t\t\tcase EFileStatus.INJECTED:\n\t\t\t\t\t\t\tawait injectFile(file, index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EFileStatus.NONE:\n\t\t\t\t\t\t\tawait parseFile(file, index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EFileStatus.UPLOAD_READY:\n\t\t\t\t\t\t\tawait uploadFile(file, index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EFileStatus.TO_DELETE:\n\t\t\t\t\t\t\tdeleteFile(index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\thandleGenericError(index);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// track / update values\n\t\t\tconst uploadedFiles = files.filter(({ status }) => status === EFileStatus.UPLOADED);\n\t\t\tconst notPrefilledFiles = uploadedFiles.filter(({ addedFrom }) => addedFrom !== \"schema\");\n\t\t\tconst hasNotPrefilledFiles = notPrefilledFiles.length > 0;\n\t\t\tconst gotDeleteFiles = files.filter(({ status }) => status === EFileStatus.TO_DELETE).length > 0;\n\n\t\t\t/**\n\t\t\t * should dirty if\n\t\t\t * - it is dirty in the first place\n\t\t\t * - there are non-prefilled files\n\t\t\t * - user deleted file (differentiated from reset)\n\t\t\t */\n\t\t\tconst shouldDirty = hasNotPrefilledFiles || gotDeleteFiles;\n\n\t\t\tsetCurrentFileIds(uploadedFiles.map(({ fileItem }) => fileItem.id));\n\n\t\t\tsetValue(\n\t\t\t\tid,\n\t\t\t\tuploadedFiles.map(({ dataURL, fileItem, fileUrl, uploadResponse }) => ({\n\t\t\t\t\t...(upload.type === \"base64\" ? { dataURL } : {}),\n\t\t\t\t\tfileId: fileItem.id,\n\t\t\t\t\tfileName: fileItem.name,\n\t\t\t\t\tfileUrl,\n\t\t\t\t\tuploadResponse,\n\t\t\t\t})),\n\t\t\t\t{ shouldDirty, shouldTouch: hasNotPrefilledFiles }\n\t\t\t);\n\t\t}, // eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[files.map(({ fileItem, status }) => `${fileItem?.id}-${status}`).join(\",\")]\n\t);\n\n\t// for reset\n\tuseEffect(() => {\n\t\tif (previousValue !== undefined && value === undefined && files.length) {\n\t\t\tsetFiles([]);\n\t\t}\n\t}, [files, previousValue, setFiles, value]);\n\n\t// =============================================================================\n\t// HELPER FUNCTIONS\n\t// =============================================================================\n\n\tconst handleGenericError = (index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tconst file = prev[index];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...file,\n\t\t\t\tfileItem: {\n\t\t\t\t\t...file.fileItem,\n\t\t\t\t\tid: file.fileItem?.id || generateRandomId(),\n\t\t\t\t\tname: file.rawFile.name,\n\t\t\t\t\terrorMessage: uploadRule?.errorMessage || ERROR_MESSAGES.UPLOAD().GENERIC,\n\t\t\t\t},\n\t\t\t\tstatus: EFileStatus.ERROR_GENERIC,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\t};\n\n\tconst generateThumbnail = async (file: IFile, fileType?: string | undefined) => {\n\t\tif (hideThumbnail !== true && RESIZEABLE_IMAGE_TYPES.includes(fileType || file.fileItem?.type)) {\n\t\t\tconst image = await ImageHelper.dataUrlToImage(file.dataURL);\n\t\t\tconst thumbnail = await ImageHelper.resampleImage(image, { width: 94, height: 94, crop: true });\n\t\t\treturn await FileHelper.fileToDataUrl(thumbnail);\n\t\t}\n\t\treturn \"\";\n\t};\n\n\tconst readFile = async (fileToRead: IFile) => {\n\t\tconst { addedFrom, dataURL, rawFile } = fileToRead;\n\t\tconst fileType = await FileHelper.getType(rawFile);\n\t\tconst fileTypeResult = validateFileType(fileType);\n\n\t\tif (fileTypeResult?.status < 0) {\n\t\t\treturn fileTypeResult;\n\t\t}\n\n\t\tconst fileSize = upload.type === \"base64\" ? FileHelper.getFilesizeFromBase64(dataURL) : rawFile.size;\n\t\tconst { errorMessage, status } = validateFileSize(fileSize);\n\t\tif (status < 0) {\n\t\t\treturn { errorMessage, fileType, status };\n\t\t}\n\n\t\tif (addedFrom === \"schema\") {\n\t\t\treturn {\n\t\t\t\tfileType,\n\t\t\t\tstatus: EFileStatus.UPLOADED,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tfileType,\n\t\t\tstatus: EFileStatus.UPLOAD_READY,\n\t\t};\n\t};\n\n\tconst validateFileType = (fileType: { mime: string; ext: string }) => {\n\t\tconst validFileType = fileTypeRule.fileType?.length ? fileTypeRule.fileType?.includes(fileType.ext) : true;\n\n\t\tif (!validFileType) {\n\t\t\treturn {\n\t\t\t\terrorMessage:\n\t\t\t\t\tfileTypeRule.errorMessage || ERROR_MESSAGES.UPLOAD().FILE_TYPE(fileTypeRule.fileType || []),\n\t\t\t\tfileType,\n\t\t\t\tstatus: EFileStatus.ERROR_FORMAT,\n\t\t\t};\n\t\t}\n\n\t\treturn {};\n\t};\n\n\tconst validateFileSize = (fileSizeInKb: number) => {\n\t\tif (maxFileSizeRule.maxSizeInKb > 0) {\n\t\t\tconst maxSizeInB = maxFileSizeRule.maxSizeInKb * 1024;\n\t\t\tif (fileSizeInKb > maxSizeInB) {\n\t\t\t\treturn {\n\t\t\t\t\terrorMessage:\n\t\t\t\t\t\tmaxFileSizeRule.errorMessage ||\n\t\t\t\t\t\tERROR_MESSAGES.UPLOAD().MAX_FILE_SIZE(maxFileSizeRule.maxSizeInKb),\n\t\t\t\t\tstatus: EFileStatus.ERROR_SIZE,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {};\n\t};\n\n\t// =============================================================================\n\t// FILE STATUS HANDLERS\n\t// =============================================================================\n\tconst injectFile = async (fileToInject: IFile, index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...prev[index],\n\t\t\t\tstatus: EFileStatus.INJECTING,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\n\t\tlet rawFile: File;\n\t\tif (fileToInject.dataURL) {\n\t\t\tconst blob = await FileHelper.dataUrlToBlob(fileToInject.dataURL);\n\t\t\trawFile = new File([blob], fileToInject.rawFile.name);\n\t\t} else if (fileToInject.fileUrl) {\n\t\t\tconst response: Blob = await new AxiosApiClient(\"\", undefined, undefined, false, {\n\t\t\t\tresponseType: \"blob\",\n\t\t\t}).get(fileToInject.fileUrl);\n\t\t\tconst fileType = await FileHelper.getType(new File([response], fileToInject.rawFile.name));\n\t\t\trawFile = new File([response], fileToInject.rawFile.name, { type: fileType.mime });\n\t\t\tfileToInject.dataURL = await FileHelper.fileToDataUrl(rawFile);\n\t\t}\n\n\t\t// rawFile may not be available because some use cases is not able to return dataURL / fileUrl due to security concerns\n\t\t// in such cases, we will rely on the uploadResponse for file info\n\t\tconst { errorMessage, fileType } = rawFile\n\t\t\t? await readFile({ ...fileToInject, rawFile })\n\t\t\t: validateFileType({\n\t\t\t\t\tmime: fileToInject.uploadResponse?.[\"mimeType\"],\n\t\t\t\t\text: fileToInject.uploadResponse?.[\"ext\"],\n\t\t\t });\n\n\t\tlet size = rawFile?.size || fileToInject.uploadResponse?.[\"fileSize\"] || 0;\n\t\tif (isNaN(size)) {\n\t\t\tsize = 0;\n\t\t}\n\t\tconst { errorMessage: filesizeErrorMessage } = validateFileSize(size);\n\n\t\tconst thumbnailImageDataUrl = rawFile ? await generateThumbnail(fileToInject, fileType?.mime) : undefined;\n\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...fileToInject,\n\t\t\t\tfileItem: {\n\t\t\t\t\terrorMessage: errorMessage || filesizeErrorMessage,\n\t\t\t\t\tid: fileToInject.fileItem?.id || generateRandomId(),\n\t\t\t\t\tname: FileHelper.deduplicateFileName(\n\t\t\t\t\t\tfiles.map(({ fileItem }) => fileItem.name),\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\trawFile?.name || fileToInject.rawFile.name\n\t\t\t\t\t),\n\t\t\t\t\tprogress: 1,\n\t\t\t\t\tsize,\n\t\t\t\t\ttype: fileType?.mime || fileToInject.uploadResponse?.[\"mimeType\"],\n\t\t\t\t\tthumbnailImageDataUrl,\n\t\t\t\t},\n\t\t\t\trawFile,\n\t\t\t\tstatus: EFileStatus.UPLOADED,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\t};\n\n\tconst parseFile = async (fileToParse: IFile, index: number) => {\n\t\tconst compressedFile = await compressImageFile(fileToParse);\n\t\tconst dataURL = await FileHelper.fileToDataUrl(compressedFile.rawFile);\n\t\tconst { errorMessage, fileType, status } = await readFile({ dataURL, ...compressedFile });\n\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...compressedFile,\n\t\t\t\tdataURL,\n\t\t\t\tfileItem: {\n\t\t\t\t\terrorMessage,\n\t\t\t\t\tid: generateRandomId(),\n\t\t\t\t\tname: FileHelper.deduplicateFileName(\n\t\t\t\t\t\tfiles.map(({ fileItem }) => fileItem?.name),\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tFileHelper.sanitizeFileName(compressedFile.rawFile.name)\n\t\t\t\t\t),\n\t\t\t\t\tsize: compressedFile.rawFile.size,\n\t\t\t\t\ttype: fileType.mime,\n\t\t\t\t\tprogress: 0,\n\t\t\t\t},\n\t\t\t\tstatus,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\t};\n\n\tconst uploadFile = async (fileToUpload: IFile, index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...prev[index],\n\t\t\t\tstatus: EFileStatus.UPLOADING,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\n\t\tconst formData = new FormData();\n\t\tformData.append(\"sessionId\", upload?.sessionId || sessionId.current || \"\");\n\t\tformData.append(\"fileId\", fileToUpload.fileItem.id);\n\t\tformData.append(\"slot\", fileToUpload.slot.toString());\n\t\tif (upload.type === \"base64\") {\n\t\t\tformData.append(\"dataURL\", fileToUpload.dataURL);\n\t\t} else if (upload.type === \"multipart\") {\n\t\t\tformData.append(\"file\", fileToUpload.rawFile, fileToUpload.fileItem?.name);\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await new AxiosApiClient(\"\", undefined, undefined, true).post(upload.url, formData, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": upload.type === \"base64\" ? \"application/json\" : \"multipart/form-data\",\n\t\t\t\t\t...upload.headers,\n\t\t\t\t},\n\t\t\t\tonUploadProgress: (progressEvent) => {\n\t\t\t\t\tconst { loaded, total } = progressEvent;\n\t\t\t\t\tsetFiles((prev) => {\n\t\t\t\t\t\tif (!prev[index]) return prev;\n\t\t\t\t\t\tconst updatedFiles = [...prev];\n\t\t\t\t\t\tupdatedFiles[index] = {\n\t\t\t\t\t\t\t...prev[index],\n\t\t\t\t\t\t\tfileItem: {\n\t\t\t\t\t\t\t\t...prev[index].fileItem,\n\t\t\t\t\t\t\t\tprogress: loaded / total,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\treturn updatedFiles;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst thumbnailImageDataUrl = await generateThumbnail(fileToUpload);\n\t\t\tsetFiles((prev) => {\n\t\t\t\tif (!prev[index]) return prev;\n\t\t\t\tconst updatedFiles = [...prev];\n\t\t\t\tupdatedFiles[index] = {\n\t\t\t\t\t...prev[index],\n\t\t\t\t\tfileItem: {\n\t\t\t\t\t\t...prev[index].fileItem,\n\t\t\t\t\t\tprogress: 1,\n\t\t\t\t\t\tthumbnailImageDataUrl,\n\t\t\t\t\t},\n\t\t\t\t\tfileUrl: response?.[\"data\"]?.[\"fileUrl\"],\n\t\t\t\t\tstatus: EFileStatus.UPLOADED,\n\t\t\t\t\tuploadResponse: response,\n\t\t\t\t};\n\t\t\t\treturn updatedFiles;\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tdispatchFieldEvent<TUploadErrorDetail>(\"upload-error\", id, {\n\t\t\t\tfileId: fileToUpload.fileItem.id,\n\t\t\t\terrorData: (err as AxiosError)?.response?.data,\n\t\t\t});\n\n\t\t\tthrow err;\n\t\t}\n\t};\n\n\tconst deleteFile = (index: number) => {\n\t\tsetFiles((prev) => prev.filter((_file, i) => i !== index));\n\t};\n\n\tconst compressImageFile = async (fileToCompress: IFile) => {\n\t\tif (maxFileSizeRule.maxSizeInKb > 0 && compressImages) {\n\t\t\tconst maxSizeInB = maxFileSizeRule.maxSizeInKb * 1024;\n\t\t\tif (fileToCompress.rawFile.size > maxSizeInB) {\n\t\t\t\tconst fileType = await FileHelper.getType(fileToCompress.rawFile);\n\t\t\t\tif (RESIZEABLE_IMAGE_TYPES.includes(fileType.mime)) {\n\t\t\t\t\tlet fileOrBlob = await ImageHelper.compressImage(fileToCompress.rawFile, {\n\t\t\t\t\t\tfileSize: maxFileSizeRule.maxSizeInKb,\n\t\t\t\t\t});\n\t\t\t\t\tif (fileOrBlob instanceof Blob) {\n\t\t\t\t\t\tfileOrBlob = FileHelper.blobToFile(fileOrBlob, {\n\t\t\t\t\t\t\tname: fileToCompress.rawFile.name,\n\t\t\t\t\t\t\tlastModified: fileToCompress.rawFile.lastModified,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...fileToCompress,\n\t\t\t\t\t\trawFile: fileOrBlob,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fileToCompress;\n\t};\n\n\t// =============================================================================\n\t// RENDER FUNCTIONS\n\t// =============================================================================\n\treturn null;\n};\n\nexport default FileUploadManager;\n"],"names":["RESIZEABLE_IMAGE_TYPES","FileUploadManager","props","compressImages","fileTypeRule","hideThumbnail","id","maxFileSizeRule","upload","uploadRule","value","files","setFiles","setCurrentFileIds","useContext","FileUploadContext","previousValue","usePrevious","setValue","useFormContext","dispatchFieldEvent","useFieldEvent","sessionId","useRef","useEffect","current","generateRandomId","forEach","async","file","index","status","EFileStatus","INJECTED","injectFile","NONE","parseFile","UPLOAD_READY","uploadFile","TO_DELETE","deleteFile","err","handleGenericError","uploadedFiles","filter","UPLOADED","hasNotPrefilledFiles","addedFrom","length","gotDeleteFiles","shouldDirty","map","fileItem","dataURL","fileUrl","uploadResponse","type","fileId","fileName","name","shouldTouch","join","undefined","prev","updatedFiles","rawFile","errorMessage","ERROR_MESSAGES","UPLOAD","GENERIC","ERROR_GENERIC","generateThumbnail","fileType","includes","image","ImageHelper","dataUrlToImage","thumbnail","resampleImage","width","height","crop","FileHelper","fileToDataUrl","readFile","fileToRead","getType","fileTypeResult","validateFileType","fileSize","getFilesizeFromBase64","size","validateFileSize","ext","FILE_TYPE","ERROR_FORMAT","fileSizeInKb","maxSizeInKb","MAX_FILE_SIZE","ERROR_SIZE","fileToInject","INJECTING","blob","dataUrlToBlob","File","response","AxiosApiClient","responseType","get","mime","isNaN","filesizeErrorMessage","thumbnailImageDataUrl","deduplicateFileName","progress","fileToParse","compressedFile","compressImageFile","sanitizeFileName","fileToUpload","UPLOADING","formData","FormData","append","slot","toString","post","url","headers","onUploadProgress","progressEvent","loaded","total","errorData","data","_file","i","fileToCompress","maxSizeInB","fileOrBlob","compressImage","Blob","blobToFile","lastModified"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-manager.3328a5eb.js","sources":["../../../src/components/fields/file-upload/file-upload-manager.ts"],"sourcesContent":["import { AxiosError } from \"axios\";\nimport { useContext, useEffect, useRef } from \"react\";\nimport { useFormContext } from \"react-hook-form\";\nimport { AxiosApiClient, FileHelper, ImageHelper, generateRandomId } from \"../../../utils\";\nimport { useFieldEvent, usePrevious } from \"../../../utils/hooks\";\nimport { ERROR_MESSAGES } from \"../../shared\";\nimport { FileUploadContext } from \"./file-upload-context\";\nimport {\n\tEFileStatus,\n\tIFile,\n\tIFileUploadSchema,\n\tIFileUploadValidationRule,\n\tIFileUploadValue,\n\tTUploadErrorDetail,\n} from \"./types\";\n\ninterface IProps {\n\tcompressImages: boolean;\n\tfileTypeRule: IFileUploadValidationRule;\n\thideThumbnail?: boolean | undefined;\n\tid: string;\n\tmaxFileSizeRule: IFileUploadValidationRule;\n\tupload: IFileUploadSchema[\"uploadOnAddingFile\"];\n\tuploadRule: IFileUploadValidationRule;\n\tvalue: IFileUploadValue[];\n}\n\nconst RESIZEABLE_IMAGE_TYPES = [\"image/jpeg\", \"image/gif\", \"image/png\"];\n\nconst FileUploadManager = (props: IProps) => {\n\t// =============================================================================\n\t// CONST, STATE, REFS\n\t// =============================================================================\n\tconst { compressImages, fileTypeRule, hideThumbnail, id, maxFileSizeRule, upload, uploadRule, value } = props;\n\tconst { files, setFiles, setCurrentFileIds } = useContext(FileUploadContext);\n\tconst previousValue = usePrevious(value);\n\tconst { setValue } = useFormContext();\n\tconst { dispatchFieldEvent } = useFieldEvent();\n\tconst sessionId = useRef<string>();\n\n\t// =============================================================================\n\t// EFFECTS\n\t// =============================================================================\n\tuseEffect(() => {\n\t\tsessionId.current = generateRandomId();\n\t}, []);\n\n\tuseEffect(\n\t\t() => {\n\t\t\t// handle file status\n\t\t\tfiles.forEach(async (file, index) => {\n\t\t\t\ttry {\n\t\t\t\t\tswitch (file.status) {\n\t\t\t\t\t\tcase EFileStatus.INJECTED:\n\t\t\t\t\t\t\tawait injectFile(file, index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EFileStatus.NONE:\n\t\t\t\t\t\t\tawait parseFile(file, index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EFileStatus.UPLOAD_READY:\n\t\t\t\t\t\t\tawait uploadFile(file, index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EFileStatus.TO_DELETE:\n\t\t\t\t\t\t\tdeleteFile(index);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\thandleGenericError(index);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// track / update values\n\t\t\tconst uploadedFiles = files.filter(({ status }) => status === EFileStatus.UPLOADED);\n\t\t\tconst notPrefilledFiles = uploadedFiles.filter(({ addedFrom }) => addedFrom !== \"schema\");\n\t\t\tconst hasNotPrefilledFiles = notPrefilledFiles.length > 0;\n\t\t\tconst gotDeleteFiles = files.filter(({ status }) => status === EFileStatus.TO_DELETE).length > 0;\n\n\t\t\t/**\n\t\t\t * should dirty if\n\t\t\t * - it is dirty in the first place\n\t\t\t * - there are non-prefilled files\n\t\t\t * - user deleted file (differentiated from reset)\n\t\t\t */\n\t\t\tconst shouldDirty = hasNotPrefilledFiles || gotDeleteFiles;\n\n\t\t\tsetCurrentFileIds(uploadedFiles.map(({ fileItem }) => fileItem.id));\n\n\t\t\tsetValue(\n\t\t\t\tid,\n\t\t\t\tuploadedFiles.map(({ dataURL, fileItem, fileUrl, uploadResponse }) => ({\n\t\t\t\t\t...(upload.type === \"base64\" ? { dataURL } : {}),\n\t\t\t\t\tfileId: fileItem.id,\n\t\t\t\t\tfileName: fileItem.name,\n\t\t\t\t\tfileUrl,\n\t\t\t\t\tuploadResponse,\n\t\t\t\t})),\n\t\t\t\t{ shouldDirty, shouldTouch: hasNotPrefilledFiles }\n\t\t\t);\n\t\t}, // eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[files.map(({ fileItem, status }) => `${fileItem?.id}-${status}`).join(\",\")]\n\t);\n\n\t// for reset\n\tuseEffect(() => {\n\t\tif (previousValue !== undefined && value === undefined && files.length) {\n\t\t\tsetFiles([]);\n\t\t}\n\t}, [files, previousValue, setFiles, value]);\n\n\t// =============================================================================\n\t// HELPER FUNCTIONS\n\t// =============================================================================\n\n\tconst handleGenericError = (index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tconst file = prev[index];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...file,\n\t\t\t\tfileItem: {\n\t\t\t\t\t...file.fileItem,\n\t\t\t\t\tid: file.fileItem?.id || generateRandomId(),\n\t\t\t\t\tname: file.rawFile.name,\n\t\t\t\t\terrorMessage: uploadRule?.errorMessage || ERROR_MESSAGES.UPLOAD().GENERIC,\n\t\t\t\t},\n\t\t\t\tstatus: EFileStatus.ERROR_GENERIC,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\t};\n\n\tconst generateThumbnail = async (file: IFile, fileType?: string | undefined) => {\n\t\tif (hideThumbnail !== true && RESIZEABLE_IMAGE_TYPES.includes(fileType || file.fileItem?.type)) {\n\t\t\tconst image = await ImageHelper.dataUrlToImage(file.dataURL);\n\t\t\tconst thumbnail = await ImageHelper.resampleImage(image, { width: 94, height: 94, crop: true });\n\t\t\treturn await FileHelper.fileToDataUrl(thumbnail);\n\t\t}\n\t\treturn \"\";\n\t};\n\n\tconst readFile = async (fileToRead: IFile) => {\n\t\tconst { addedFrom, dataURL, rawFile } = fileToRead;\n\t\tconst fileType = await FileHelper.getType(rawFile);\n\t\tconst fileTypeResult = validateFileType(fileType);\n\n\t\tif (fileTypeResult?.status < 0) {\n\t\t\treturn fileTypeResult;\n\t\t}\n\n\t\tconst fileSize = upload.type === \"base64\" ? FileHelper.getFilesizeFromBase64(dataURL) : rawFile.size;\n\t\tconst { errorMessage, status } = validateFileSize(fileSize);\n\t\tif (status < 0) {\n\t\t\treturn { errorMessage, fileType, status };\n\t\t}\n\n\t\tif (addedFrom === \"schema\") {\n\t\t\treturn {\n\t\t\t\tfileType,\n\t\t\t\tstatus: EFileStatus.UPLOADED,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tfileType,\n\t\t\tstatus: EFileStatus.UPLOAD_READY,\n\t\t};\n\t};\n\n\tconst validateFileType = (fileType: { mime: string; ext: string }) => {\n\t\tconst validFileType = fileTypeRule.fileType?.length ? fileTypeRule.fileType?.includes(fileType.ext) : true;\n\n\t\tif (!validFileType) {\n\t\t\treturn {\n\t\t\t\terrorMessage:\n\t\t\t\t\tfileTypeRule.errorMessage || ERROR_MESSAGES.UPLOAD().FILE_TYPE(fileTypeRule.fileType || []),\n\t\t\t\tfileType,\n\t\t\t\tstatus: EFileStatus.ERROR_FORMAT,\n\t\t\t};\n\t\t}\n\n\t\treturn {};\n\t};\n\n\tconst validateFileSize = (fileSizeInKb: number) => {\n\t\tif (maxFileSizeRule.maxSizeInKb > 0) {\n\t\t\tconst maxSizeInB = maxFileSizeRule.maxSizeInKb * 1024;\n\t\t\tif (fileSizeInKb > maxSizeInB) {\n\t\t\t\treturn {\n\t\t\t\t\terrorMessage:\n\t\t\t\t\t\tmaxFileSizeRule.errorMessage ||\n\t\t\t\t\t\tERROR_MESSAGES.UPLOAD().MAX_FILE_SIZE(maxFileSizeRule.maxSizeInKb),\n\t\t\t\t\tstatus: EFileStatus.ERROR_SIZE,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {};\n\t};\n\n\t// =============================================================================\n\t// FILE STATUS HANDLERS\n\t// =============================================================================\n\tconst injectFile = async (fileToInject: IFile, index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...prev[index],\n\t\t\t\tstatus: EFileStatus.INJECTING,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\n\t\tlet rawFile: File;\n\t\tif (fileToInject.dataURL) {\n\t\t\tconst blob = await FileHelper.dataUrlToBlob(fileToInject.dataURL);\n\t\t\trawFile = new File([blob], fileToInject.rawFile.name);\n\t\t} else if (fileToInject.fileUrl) {\n\t\t\tconst response: Blob = await new AxiosApiClient(\"\", undefined, undefined, false, {\n\t\t\t\tresponseType: \"blob\",\n\t\t\t}).get(fileToInject.fileUrl);\n\t\t\tconst fileType = await FileHelper.getType(new File([response], fileToInject.rawFile.name));\n\t\t\trawFile = new File([response], fileToInject.rawFile.name, { type: fileType.mime });\n\t\t\tfileToInject.dataURL = await FileHelper.fileToDataUrl(rawFile);\n\t\t}\n\n\t\t// rawFile may not be available because some use cases is not able to return dataURL / fileUrl due to security concerns\n\t\t// in such cases, we will rely on the uploadResponse for file info\n\t\tconst { errorMessage, fileType } = rawFile\n\t\t\t? await readFile({ ...fileToInject, rawFile })\n\t\t\t: validateFileType({\n\t\t\t\t\tmime: fileToInject.uploadResponse?.[\"mimeType\"],\n\t\t\t\t\text: fileToInject.uploadResponse?.[\"ext\"],\n\t\t\t });\n\n\t\tlet size = rawFile?.size || fileToInject.uploadResponse?.[\"fileSize\"] || 0;\n\t\tif (isNaN(size)) {\n\t\t\tsize = 0;\n\t\t}\n\t\tconst { errorMessage: filesizeErrorMessage } = validateFileSize(size);\n\n\t\tconst thumbnailImageDataUrl = rawFile ? await generateThumbnail(fileToInject, fileType?.mime) : undefined;\n\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...fileToInject,\n\t\t\t\tfileItem: {\n\t\t\t\t\terrorMessage: errorMessage || filesizeErrorMessage,\n\t\t\t\t\tid: fileToInject.fileItem?.id || generateRandomId(),\n\t\t\t\t\tname: FileHelper.deduplicateFileName(\n\t\t\t\t\t\tfiles.map(({ fileItem }) => fileItem.name),\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\trawFile?.name || fileToInject.rawFile.name\n\t\t\t\t\t),\n\t\t\t\t\tprogress: 1,\n\t\t\t\t\tsize,\n\t\t\t\t\ttype: fileType?.mime || fileToInject.uploadResponse?.[\"mimeType\"],\n\t\t\t\t\tthumbnailImageDataUrl,\n\t\t\t\t},\n\t\t\t\trawFile,\n\t\t\t\tstatus: EFileStatus.UPLOADED,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\t};\n\n\tconst parseFile = async (fileToParse: IFile, index: number) => {\n\t\tconst compressedFile = await compressImageFile(fileToParse);\n\t\tconst dataURL = await FileHelper.fileToDataUrl(compressedFile.rawFile);\n\t\tconst { errorMessage, fileType, status } = await readFile({ dataURL, ...compressedFile });\n\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...compressedFile,\n\t\t\t\tdataURL,\n\t\t\t\tfileItem: {\n\t\t\t\t\terrorMessage,\n\t\t\t\t\tid: generateRandomId(),\n\t\t\t\t\tname: FileHelper.deduplicateFileName(\n\t\t\t\t\t\tfiles.map(({ fileItem }) => fileItem?.name),\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tFileHelper.sanitizeFileName(compressedFile.rawFile.name)\n\t\t\t\t\t),\n\t\t\t\t\tsize: compressedFile.rawFile.size,\n\t\t\t\t\ttype: fileType.mime,\n\t\t\t\t\tprogress: 0,\n\t\t\t\t},\n\t\t\t\tstatus,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\t};\n\n\tconst uploadFile = async (fileToUpload: IFile, index: number) => {\n\t\tsetFiles((prev) => {\n\t\t\tconst updatedFiles = [...prev];\n\t\t\tupdatedFiles[index] = {\n\t\t\t\t...prev[index],\n\t\t\t\tstatus: EFileStatus.UPLOADING,\n\t\t\t};\n\t\t\treturn updatedFiles;\n\t\t});\n\n\t\tconst formData = new FormData();\n\t\tformData.append(\"sessionId\", upload?.sessionId || sessionId.current || \"\");\n\t\tformData.append(\"fileId\", fileToUpload.fileItem.id);\n\t\tformData.append(\"slot\", fileToUpload.slot.toString());\n\t\tif (upload.type === \"base64\") {\n\t\t\tformData.append(\"dataURL\", fileToUpload.dataURL);\n\t\t} else if (upload.type === \"multipart\") {\n\t\t\tformData.append(\"file\", fileToUpload.rawFile, fileToUpload.fileItem?.name);\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await new AxiosApiClient(\"\", undefined, undefined, true).post(upload.url, formData, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": upload.type === \"base64\" ? \"application/json\" : \"multipart/form-data\",\n\t\t\t\t\t...upload.headers,\n\t\t\t\t},\n\t\t\t\tonUploadProgress: (progressEvent) => {\n\t\t\t\t\tconst { loaded, total } = progressEvent;\n\t\t\t\t\tsetFiles((prev) => {\n\t\t\t\t\t\tif (!prev[index]) return prev;\n\t\t\t\t\t\tconst updatedFiles = [...prev];\n\t\t\t\t\t\tupdatedFiles[index] = {\n\t\t\t\t\t\t\t...prev[index],\n\t\t\t\t\t\t\tfileItem: {\n\t\t\t\t\t\t\t\t...prev[index].fileItem,\n\t\t\t\t\t\t\t\tprogress: loaded / total,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\treturn updatedFiles;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst thumbnailImageDataUrl = await generateThumbnail(fileToUpload);\n\t\t\tsetFiles((prev) => {\n\t\t\t\tif (!prev[index]) return prev;\n\t\t\t\tconst updatedFiles = [...prev];\n\t\t\t\tupdatedFiles[index] = {\n\t\t\t\t\t...prev[index],\n\t\t\t\t\tfileItem: {\n\t\t\t\t\t\t...prev[index].fileItem,\n\t\t\t\t\t\tprogress: 1,\n\t\t\t\t\t\tthumbnailImageDataUrl,\n\t\t\t\t\t},\n\t\t\t\t\tfileUrl: response?.[\"data\"]?.[\"fileUrl\"],\n\t\t\t\t\tstatus: EFileStatus.UPLOADED,\n\t\t\t\t\tuploadResponse: response,\n\t\t\t\t};\n\t\t\t\treturn updatedFiles;\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tdispatchFieldEvent<TUploadErrorDetail>(\"upload-error\", id, {\n\t\t\t\tfileId: fileToUpload.fileItem.id,\n\t\t\t\terrorData: (err as AxiosError)?.response?.data,\n\t\t\t});\n\n\t\t\tthrow err;\n\t\t}\n\t};\n\n\tconst deleteFile = (index: number) => {\n\t\tsetFiles((prev) => prev.filter((_file, i) => i !== index));\n\t};\n\n\tconst compressImageFile = async (fileToCompress: IFile) => {\n\t\tif (maxFileSizeRule.maxSizeInKb > 0 && compressImages) {\n\t\t\tconst maxSizeInB = maxFileSizeRule.maxSizeInKb * 1024;\n\t\t\tif (fileToCompress.rawFile.size > maxSizeInB) {\n\t\t\t\tconst fileType = await FileHelper.getType(fileToCompress.rawFile);\n\t\t\t\tif (RESIZEABLE_IMAGE_TYPES.includes(fileType.mime)) {\n\t\t\t\t\tlet fileOrBlob = await ImageHelper.compressImage(fileToCompress.rawFile, {\n\t\t\t\t\t\tfileSize: maxFileSizeRule.maxSizeInKb,\n\t\t\t\t\t});\n\t\t\t\t\tif (fileOrBlob instanceof Blob) {\n\t\t\t\t\t\tfileOrBlob = FileHelper.blobToFile(fileOrBlob, {\n\t\t\t\t\t\t\tname: fileToCompress.rawFile.name,\n\t\t\t\t\t\t\tlastModified: fileToCompress.rawFile.lastModified,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...fileToCompress,\n\t\t\t\t\t\trawFile: fileOrBlob,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fileToCompress;\n\t};\n\n\t// =============================================================================\n\t// RENDER FUNCTIONS\n\t// =============================================================================\n\treturn null;\n};\n\nexport default FileUploadManager;\n"],"names":["RESIZEABLE_IMAGE_TYPES","props","compressImages","fileTypeRule","hideThumbnail","id","maxFileSizeRule","upload","uploadRule","value","files","setFiles","setCurrentFileIds","useContext","FileUploadContext","previousValue","usePrevious","setValue","useFormContext","dispatchFieldEvent","useFieldEvent","sessionId","useRef","useEffect","current","generateRandomId","forEach","async","file","index","status","EFileStatus","INJECTED","injectFile","NONE","parseFile","UPLOAD_READY","uploadFile","TO_DELETE","deleteFile","err","handleGenericError","uploadedFiles","filter","UPLOADED","hasNotPrefilledFiles","addedFrom","length","gotDeleteFiles","shouldDirty","map","fileItem","dataURL","fileUrl","uploadResponse","type","fileId","fileName","name","shouldTouch","join","undefined","prev","updatedFiles","rawFile","errorMessage","ERROR_MESSAGES","UPLOAD","GENERIC","ERROR_GENERIC","generateThumbnail","fileType","includes","image","ImageHelper","dataUrlToImage","thumbnail","resampleImage","width","height","crop","FileHelper","fileToDataUrl","readFile","fileToRead","getType","fileTypeResult","validateFileType","fileSize","getFilesizeFromBase64","size","validateFileSize","ext","FILE_TYPE","ERROR_FORMAT","fileSizeInKb","maxSizeInKb","MAX_FILE_SIZE","ERROR_SIZE","fileToInject","INJECTING","blob","dataUrlToBlob","File","response","AxiosApiClient","responseType","get","mime","isNaN","filesizeErrorMessage","thumbnailImageDataUrl","deduplicateFileName","progress","fileToParse","compressedFile","compressImageFile","sanitizeFileName","fileToUpload","UPLOADING","formData","FormData","append","slot","toString","post","url","headers","onUploadProgress","progressEvent","loaded","total","errorData","data","_file","i","fileToCompress","maxSizeInB","fileOrBlob","compressImage","Blob","blobToFile","lastModified"],"mappings":"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"}
|