@swan-io/shared-business 11.3.0 → 11.3.2
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/package.json +9 -9
- package/src/components/ChoicePicker.js +2 -1
- package/src/components/FileInput.js +4 -1
- package/src/components/FileTile.js +2 -2
- package/src/components/FilesUploader.js +2 -2
- package/src/components/LakeModal.js +1 -1
- package/src/components/SupportChat.js +4 -1
- package/src/components/SupportingDocumentCollection.js +9 -17
- package/src/components/ToastStack.js +1 -1
- package/src/hooks/useFilesUploader.d.ts +1 -2
- package/src/hooks/useFilesUploader.js +4 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swan-io/shared-business",
|
|
3
|
-
"version": "11.3.
|
|
3
|
+
"version": "11.3.2",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.9.0",
|
|
6
6
|
"pnpm": "^9.13.0"
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
],
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@swan-io/lake": "11.3.
|
|
29
|
+
"@swan-io/lake": "11.3.2"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@formatjs/intl": "^3.1.
|
|
32
|
+
"@formatjs/intl": "^3.1.3",
|
|
33
33
|
"@placekit/client-js": "^2.3.0",
|
|
34
34
|
"@swan-io/boxed": "^3.2.0",
|
|
35
|
-
"@swan-io/request": "^
|
|
35
|
+
"@swan-io/request": "^2.0.0",
|
|
36
36
|
"@swan-io/use-form": "^3.1.0",
|
|
37
37
|
"dayjs": "^1.11.13",
|
|
38
38
|
"iban": "^0.0.14",
|
|
@@ -42,16 +42,16 @@
|
|
|
42
42
|
"react-dropzone": "^14.3.5",
|
|
43
43
|
"react-native-web": "^0.19.13",
|
|
44
44
|
"rifm": "^0.12.1",
|
|
45
|
-
"ts-pattern": "^5.6.
|
|
46
|
-
"uuid": "^11.0.
|
|
45
|
+
"ts-pattern": "^5.6.1",
|
|
46
|
+
"uuid": "^11.0.5"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/iban": "0.0.35",
|
|
50
50
|
"@types/react": "^18.3.12",
|
|
51
51
|
"@types/react-dom": "^18.3.1",
|
|
52
52
|
"@types/react-native": "^0.72.8",
|
|
53
|
-
"jsdom": "^
|
|
54
|
-
"vitest": "^
|
|
55
|
-
"@swan-io/lake": "11.3.
|
|
53
|
+
"jsdom": "^26.0.0",
|
|
54
|
+
"vitest": "^3.0.2",
|
|
55
|
+
"@swan-io/lake": "11.3.2"
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -107,6 +107,7 @@ export const ChoicePicker = ({ tile = true, items, getId = identity, large = fal
|
|
|
107
107
|
const containerRef = useRef(null);
|
|
108
108
|
const { desktop } = useResponsive(breakpoints.medium);
|
|
109
109
|
const [mobilePosition, setMobilePosition] = useState("start");
|
|
110
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
110
111
|
useEffect(() => {
|
|
111
112
|
if (desktop) {
|
|
112
113
|
return;
|
|
@@ -126,7 +127,7 @@ export const ChoicePicker = ({ tile = true, items, getId = identity, large = fal
|
|
|
126
127
|
onChange(items[0]);
|
|
127
128
|
}
|
|
128
129
|
// disable exhaustive-deps because we only want to run this effect only when screen size go from desktop to mobile
|
|
129
|
-
}, [desktop]);
|
|
130
|
+
}, [desktop]);
|
|
130
131
|
const onScroll = () => {
|
|
131
132
|
// prevent scroll event when we change screen size from mobile to desktop
|
|
132
133
|
if (desktop) {
|
|
@@ -114,7 +114,10 @@ export const FileInput = ({ icon = "document-regular", accept, value, disabled =
|
|
|
114
114
|
.exhaustive();
|
|
115
115
|
}, [value]);
|
|
116
116
|
const { getRootProps, getInputProps, isDragActive, fileRejections } = useDropzone({
|
|
117
|
-
accept: accept.reduce((acc, item) =>
|
|
117
|
+
accept: accept.reduce((acc, item) => {
|
|
118
|
+
acc[item] = [];
|
|
119
|
+
return acc;
|
|
120
|
+
}, {}),
|
|
118
121
|
onDropAccepted: onFiles,
|
|
119
122
|
onDropRejected: onError,
|
|
120
123
|
disabled,
|
|
@@ -39,7 +39,7 @@ const styles = StyleSheet.create({
|
|
|
39
39
|
progress: {
|
|
40
40
|
height: 4,
|
|
41
41
|
transitionProperty: "width",
|
|
42
|
-
transitionDuration: "
|
|
42
|
+
transitionDuration: "1000ms",
|
|
43
43
|
transitionTimingFunction: "ease-in-out",
|
|
44
44
|
borderRadius: 2,
|
|
45
45
|
backgroundColor: colors.current[500],
|
|
@@ -52,7 +52,7 @@ export const FileTile = ({ file: { id, statusInfo, name, url }, showId = false,
|
|
|
52
52
|
const [isDeleting, setIsDeleting] = useState(false);
|
|
53
53
|
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
|
|
54
54
|
const onPressRemove = useCallback(() => {
|
|
55
|
-
if (onRemove !=
|
|
55
|
+
if (onRemove != null) {
|
|
56
56
|
setIsDeleting(true);
|
|
57
57
|
onRemove().tap(() => {
|
|
58
58
|
setIsDeleting(false);
|
|
@@ -22,7 +22,7 @@ const FilesUploaderWithRef = ({ maxSize, accept, icon, getUploadConfig, onRemove
|
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
const onChange = onChangeRef.current;
|
|
25
|
-
if (onChange !=
|
|
25
|
+
if (onChange != null) {
|
|
26
26
|
onChange(files);
|
|
27
27
|
}
|
|
28
28
|
}, [files]);
|
|
@@ -30,7 +30,7 @@ const FilesUploaderWithRef = ({ maxSize, accept, icon, getUploadConfig, onRemove
|
|
|
30
30
|
files.forEach(file => {
|
|
31
31
|
upload(getUploadConfig(file), file);
|
|
32
32
|
});
|
|
33
|
-
}, accept: accept, icon: icon, description: formatAndSizeDescription, maxSize: maxSize }), _jsx(Space, { height: 12 })] })) : null, files.map((file, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(Space, { height: 12 }) : null, _jsx(FileTile, { file: file, showId: showIds, onRemove: onRemoveFile !=
|
|
33
|
+
}, accept: accept, icon: icon, description: formatAndSizeDescription, maxSize: maxSize }), _jsx(Space, { height: 12 })] })) : null, files.map((file, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(Space, { height: 12 }) : null, _jsx(FileTile, { file: file, showId: showIds, onRemove: onRemoveFile != null && file.statusInfo.status === "Uploaded"
|
|
34
34
|
? () => onRemoveFile(file).tapOk(() => {
|
|
35
35
|
remove(file.id);
|
|
36
36
|
})
|
|
@@ -136,5 +136,5 @@ export const LakeModal = ({ visible, icon, title, color = "current", children, m
|
|
|
136
136
|
if (rootElement == null) {
|
|
137
137
|
return null;
|
|
138
138
|
}
|
|
139
|
-
return (_jsx(Portal, { container: rootElement, children: _jsxs(View, { "aria-modal": true, style: [styles.container, !visible && styles.inert], children: [_jsx(TransitionView, { style: styles.fill, enter: styles.overlayEnter, leave: styles.overlayLeave, children: visible ? _jsx(View, { style: styles.overlay }) : null }), _jsx(Suspendable, { fallback: _jsx(LoadingView, { color: backgroundColor.accented, delay: 0 }), children: _jsx(TransitionView, { style: styles.fill, enter: styles.modalEnter, leave: styles.modalLeave, children: visible ? (_jsx(ResponsiveContainer, { style: styles.root, breakpoint: breakpoints.tiny, children: ({ large, small }) => (_jsx(FocusTrap, { autoFocus: true, focusLock: true, returnFocus: true, onEscapeKey: onPressClose, style: styles.trap, children: _jsxs(ScrollView, { style: styles.modalContainer, contentContainerStyle: large ? styles.modalContentContainer : styles.modalContentContainerSmall, children: [onPressClose != null ? (_jsx(Pressable, { onPress: onPressClose, style: styles.pressableOverlay })) : null, _jsxs(View, { role: "dialog", style: [large ? styles.modal : styles.modalSmall, { maxWidth }], children: [_jsxs(View, { style: styles.modalHeader, children: [_jsxs(View, { style: styles.modalIconTitle, children: [icon != null ? (_jsx(Icon, { name: icon, size: large ? 40 : 32, color: colors[color][500] })) : null, icon != null && title != null ? _jsx(Space, { height: 12 }) : null, title != null ? (_jsxs(_Fragment, { children: [_jsx(LakeHeading, { level: 2, variant: "h3", children: title }), _jsx(Space, { height: 12 })] })) : null] }), onPressClose != null ? (_jsx(LakeButton, { style: styles.closeButton, mode: "tertiary", onPress: onPressClose, icon: "lake-close", ariaLabel: t("common.close") })) : null] }), typeof children
|
|
139
|
+
return (_jsx(Portal, { container: rootElement, children: _jsxs(View, { "aria-modal": true, style: [styles.container, !visible && styles.inert], children: [_jsx(TransitionView, { style: styles.fill, enter: styles.overlayEnter, leave: styles.overlayLeave, children: visible ? _jsx(View, { style: styles.overlay }) : null }), _jsx(Suspendable, { fallback: _jsx(LoadingView, { color: backgroundColor.accented, delay: 0 }), children: _jsx(TransitionView, { style: styles.fill, enter: styles.modalEnter, leave: styles.modalLeave, children: visible ? (_jsx(ResponsiveContainer, { style: styles.root, breakpoint: breakpoints.tiny, children: ({ large, small }) => (_jsx(FocusTrap, { autoFocus: true, focusLock: true, returnFocus: true, onEscapeKey: onPressClose, style: styles.trap, children: _jsxs(ScrollView, { style: styles.modalContainer, contentContainerStyle: large ? styles.modalContentContainer : styles.modalContentContainerSmall, children: [onPressClose != null ? (_jsx(Pressable, { onPress: onPressClose, style: styles.pressableOverlay })) : null, _jsxs(View, { role: "dialog", style: [large ? styles.modal : styles.modalSmall, { maxWidth }], children: [_jsxs(View, { style: styles.modalHeader, children: [_jsxs(View, { style: styles.modalIconTitle, children: [icon != null ? (_jsx(Icon, { name: icon, size: large ? 40 : 32, color: colors[color][500] })) : null, icon != null && title != null ? _jsx(Space, { height: 12 }) : null, title != null ? (_jsxs(_Fragment, { children: [_jsx(LakeHeading, { level: 2, variant: "h3", children: title }), _jsx(Space, { height: 12 })] })) : null] }), onPressClose != null ? (_jsx(LakeButton, { style: styles.closeButton, mode: "tertiary", onPress: onPressClose, icon: "lake-close", ariaLabel: t("common.close") })) : null] }), typeof children === "function" ? children({ large, small }) : children] })] }) })) })) : null }) })] }) }));
|
|
140
140
|
};
|
|
@@ -14,6 +14,7 @@ const zendeskFieldMapping = {
|
|
|
14
14
|
};
|
|
15
15
|
const [zendeskApi, setZendeskApi] = Deferred.make();
|
|
16
16
|
export const SupportChat = ({ children, accentColor, type, additionalInfo }) => {
|
|
17
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies(zE):
|
|
17
18
|
useEffect(() => {
|
|
18
19
|
const script = document.createElement("script");
|
|
19
20
|
script.id = "ze-snippet";
|
|
@@ -21,7 +22,7 @@ export const SupportChat = ({ children, accentColor, type, additionalInfo }) =>
|
|
|
21
22
|
document.body.append(script);
|
|
22
23
|
script.addEventListener("load", () => {
|
|
23
24
|
const intervalId = setInterval(() => {
|
|
24
|
-
if (typeof zE
|
|
25
|
+
if (typeof zE !== "undefined") {
|
|
25
26
|
setZendeskApi(zE);
|
|
26
27
|
clearInterval(intervalId);
|
|
27
28
|
}
|
|
@@ -37,6 +38,7 @@ export const SupportChat = ({ children, accentColor, type, additionalInfo }) =>
|
|
|
37
38
|
color: { theme: accentColor !== null && accentColor !== void 0 ? accentColor : "#26232f" },
|
|
38
39
|
};
|
|
39
40
|
}, [accentColor]);
|
|
41
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies(zE):
|
|
40
42
|
useEffect(() => {
|
|
41
43
|
const { firstName, lastName, email, projectName, ...fieldInfos } = additionalInfo;
|
|
42
44
|
const values = Dict.entries({ ...fieldInfos, email });
|
|
@@ -74,6 +76,7 @@ export const SupportChat = ({ children, accentColor, type, additionalInfo }) =>
|
|
|
74
76
|
}
|
|
75
77
|
});
|
|
76
78
|
}, [accentColor, additionalInfo]);
|
|
79
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies(zE):
|
|
77
80
|
const onPressShow = useCallback(() => {
|
|
78
81
|
try {
|
|
79
82
|
zE("webWidget", "show");
|
|
@@ -41,21 +41,11 @@ const Help = (props) => {
|
|
|
41
41
|
};
|
|
42
42
|
export const getSupportingDocumentPurposeLabel = (purpose) => {
|
|
43
43
|
const key = `supportingDocuments.purpose.${purpose}`;
|
|
44
|
-
|
|
45
|
-
return t(key);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
return purpose;
|
|
49
|
-
}
|
|
44
|
+
return isTranslationKey(key) ? t(key) : purpose;
|
|
50
45
|
};
|
|
51
46
|
export const getSupportingDocumentPurposeDescriptionLabel = (purpose) => {
|
|
52
47
|
const key = `supportingDocuments.purpose.${purpose}.description`;
|
|
53
|
-
|
|
54
|
-
return t(key);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
return "";
|
|
58
|
-
}
|
|
48
|
+
return isTranslationKey(key) ? t(key) : "";
|
|
59
49
|
};
|
|
60
50
|
export const SupportingDocumentCollectionWithRef = ({ documents, generateUpload, uploadFile, requiredDocumentPurposes, templateLanguage = locale.language, status, onRemoveFile, showIds = false, readOnly = false, getPurposeMetadata, readonlyDocumentPurposes = [], }, ref) => {
|
|
61
51
|
const [showPowerOfAttorneyModal, setShowPowerOfAttorneyModal] = useState(false);
|
|
@@ -141,7 +131,9 @@ export const SupportingDocumentCollectionWithRef = ({ documents, generateUpload,
|
|
|
141
131
|
return (_jsxs(Fragment, { children: [_jsx(LakeLabel, { label: getSupportingDocumentPurposeLabel(purpose), description: label, help: isNotNullish(metadata) ? (_jsx(Help, { type: "button", label: metadata.title, onPress: () => setCurrentMetadata(metadata) })) : (match(purpose)
|
|
142
132
|
.with("PowerOfAttorney", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowPowerOfAttorneyModal(true) })))
|
|
143
133
|
.with("SwornStatement", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowSwornStatementModal(true) })))
|
|
144
|
-
.otherwise(() => null)), render: () => (_jsx(FilesUploader, { ref: ref =>
|
|
134
|
+
.otherwise(() => null)), render: () => (_jsx(FilesUploader, { ref: ref => {
|
|
135
|
+
filesUploaderRefByPurpose.current[purpose] = ref;
|
|
136
|
+
},
|
|
145
137
|
// Only allow uploading is the Supporting Document Collection awaits for docs
|
|
146
138
|
// and that the specific purpose isn't already fully validated
|
|
147
139
|
canUpload: !readonlyDocumentPurposes.includes(purpose) &&
|
|
@@ -149,16 +141,16 @@ export const SupportingDocumentCollectionWithRef = ({ documents, generateUpload,
|
|
|
149
141
|
status === "WaitingForDocument" &&
|
|
150
142
|
!areAllDocumentsValidated, accept: ACCEPTED_FORMATS, maxSize: 20000000, icon: "document-regular", initialFiles: files, generateUpload: generateUpload, getUploadConfig: file => ({ fileName: file.name, purpose }), uploadFile: isNotNullish(uploadFile)
|
|
151
143
|
? uploadFile
|
|
152
|
-
: ({ upload, file,
|
|
144
|
+
: ({ upload, file, onProgress }) => {
|
|
153
145
|
const body = new FormData();
|
|
154
146
|
upload.fields.forEach(({ key, value }) => body.append(key, value));
|
|
155
147
|
body.append("file", file);
|
|
148
|
+
setTimeout(() => onProgress(0.8), 100);
|
|
156
149
|
return Request.make({
|
|
157
150
|
url: upload.url,
|
|
158
151
|
method: "POST",
|
|
159
|
-
onLoadStart,
|
|
160
|
-
onProgress,
|
|
161
152
|
body,
|
|
153
|
+
type: "text",
|
|
162
154
|
}).mapOkToResult(badStatusToError);
|
|
163
155
|
}, formatAndSizeDescription: t("supportingDocuments.documentTypes", {
|
|
164
156
|
maxSizeMB: 20000000 / 1000000,
|
|
@@ -171,6 +163,6 @@ export const SupportingDocumentCollectionWithRef = ({ documents, generateUpload,
|
|
|
171
163
|
.with("fr", () => "fr")
|
|
172
164
|
.with("de", () => "de")
|
|
173
165
|
.with("es", () => "es")
|
|
174
|
-
.otherwise(() => "en")}.pdf`), children: t("supportingDocuments.downloadTemplate") }) })] }), _jsxs(LakeModal, { visible: showSwornStatementModal, title: t("supportingDocuments.purpose.SwornStatement"), icon: "document-regular", onPressClose: () => setShowSwornStatementModal(false), children: [_jsx(LakeText, { children: t("supportingDocuments.purpose.SwornStatement.description") }), _jsx(Space, { height: 16 }), _jsx(LakeButtonGroup, { paddingBottom: 0, children: _jsx(LakeButton, { grow: true, color: "current", onPress: () => window.open("/sworn-statement-template/es.pdf"), children: t("supportingDocuments.downloadTemplate") }) })] }), _jsx(LakeModal, { visible: isNotNullish(currentMetadata), title: t("supportingDocuments.informations"), icon: "document-regular", onPressClose: () => setCurrentMetadata(undefined), children: _jsx(ReadOnlyFieldList, { children: currentMetadata === null || currentMetadata === void 0 ? void 0 : currentMetadata.values.map(({ title, value, type }) => (_jsx(LakeLabel, { type: "viewSmall", label: title, actions: type === "copy" && (_jsx(LakeCopyButton, { valueToCopy: value, copiedText: t("copyButton.copiedTooltip"), copyText: t("copyButton.copyTooltip") })), render: () => (_jsx(LakeText, { variant: "regular", color: colors.gray[900], children: value })) }))) }) })] }));
|
|
166
|
+
.otherwise(() => "en")}.pdf`), children: t("supportingDocuments.downloadTemplate") }) })] }), _jsxs(LakeModal, { visible: showSwornStatementModal, title: t("supportingDocuments.purpose.SwornStatement"), icon: "document-regular", onPressClose: () => setShowSwornStatementModal(false), children: [_jsx(LakeText, { children: t("supportingDocuments.purpose.SwornStatement.description") }), _jsx(Space, { height: 16 }), _jsx(LakeButtonGroup, { paddingBottom: 0, children: _jsx(LakeButton, { grow: true, color: "current", onPress: () => window.open("/sworn-statement-template/es.pdf"), children: t("supportingDocuments.downloadTemplate") }) })] }), _jsx(LakeModal, { visible: isNotNullish(currentMetadata), title: t("supportingDocuments.informations"), icon: "document-regular", onPressClose: () => setCurrentMetadata(undefined), children: _jsx(ReadOnlyFieldList, { children: currentMetadata === null || currentMetadata === void 0 ? void 0 : currentMetadata.values.map(({ title, value, type }, index) => (_jsx(LakeLabel, { type: "viewSmall", label: title, actions: type === "copy" && (_jsx(LakeCopyButton, { valueToCopy: value, copiedText: t("copyButton.copiedTooltip"), copyText: t("copyButton.copyTooltip") })), render: () => (_jsx(LakeText, { variant: "regular", color: colors.gray[900], children: value })) }, `metadata-${index}`))) }) })] }));
|
|
175
167
|
};
|
|
176
168
|
export const SupportingDocumentCollection = forwardRef(SupportingDocumentCollectionWithRef);
|
|
@@ -77,7 +77,7 @@ const Toast = memo(({ variant, uid, title, description, error, progress, onClose
|
|
|
77
77
|
const [visibleState, setVisibleState] = useState("copy");
|
|
78
78
|
const hasDescription = isNotNullishOrEmpty(description);
|
|
79
79
|
const [requestId] = useState(() => {
|
|
80
|
-
if (error ==
|
|
80
|
+
if (error == null) {
|
|
81
81
|
return Option.None();
|
|
82
82
|
}
|
|
83
83
|
return Array.findMap(errorsToArray(error), error => Option.fromNullable(getErrorToRequestId().get(error)));
|
|
@@ -4,8 +4,7 @@ export type UploadFileInput<UploadOutput> = {
|
|
|
4
4
|
id: string;
|
|
5
5
|
upload: UploadOutput;
|
|
6
6
|
file: File;
|
|
7
|
-
|
|
8
|
-
onProgress: (event: ProgressEvent<XMLHttpRequestEventTarget>) => void;
|
|
7
|
+
onProgress: (progress: number) => void;
|
|
9
8
|
};
|
|
10
9
|
export type UploadOutputWithId<UploadOutput> = {
|
|
11
10
|
id: string;
|
|
@@ -15,7 +15,7 @@ export const useFilesUploader = (config) => {
|
|
|
15
15
|
return config
|
|
16
16
|
.generateUpload(uploadInput)
|
|
17
17
|
.tapError(error => {
|
|
18
|
-
if (config.onError !=
|
|
18
|
+
if (config.onError != null) {
|
|
19
19
|
config.onError(error);
|
|
20
20
|
}
|
|
21
21
|
})
|
|
@@ -28,14 +28,14 @@ export const useFilesUploader = (config) => {
|
|
|
28
28
|
name: file.name,
|
|
29
29
|
},
|
|
30
30
|
]);
|
|
31
|
-
const onProgress = (
|
|
31
|
+
const onProgress = (progress) => {
|
|
32
32
|
setFiles(files => files.map(file => {
|
|
33
33
|
if (file.id !== id) {
|
|
34
34
|
return file;
|
|
35
35
|
}
|
|
36
36
|
return {
|
|
37
37
|
...file,
|
|
38
|
-
statusInfo: { status: "Uploading", progress
|
|
38
|
+
statusInfo: { status: "Uploading", progress },
|
|
39
39
|
};
|
|
40
40
|
}));
|
|
41
41
|
};
|
|
@@ -44,7 +44,6 @@ export const useFilesUploader = (config) => {
|
|
|
44
44
|
id,
|
|
45
45
|
upload,
|
|
46
46
|
file,
|
|
47
|
-
onLoadStart: onProgress,
|
|
48
47
|
onProgress,
|
|
49
48
|
})
|
|
50
49
|
.tapOk(() => {
|
|
@@ -59,7 +58,7 @@ export const useFilesUploader = (config) => {
|
|
|
59
58
|
}));
|
|
60
59
|
})
|
|
61
60
|
.tapError(error => {
|
|
62
|
-
if (config.onError !=
|
|
61
|
+
if (config.onError != null) {
|
|
63
62
|
config.onError(error);
|
|
64
63
|
}
|
|
65
64
|
setFiles(files => files.filter(file => file.id !== id));
|