@bosonprotocol/react-kit 0.33.0-alpha.14 → 0.33.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/cjs/components/error/SimpleError.d.ts +2 -2
  2. package/dist/cjs/components/error/SimpleError.d.ts.map +1 -1
  3. package/dist/cjs/components/error/SimpleError.js.map +1 -1
  4. package/dist/cjs/components/form/CountrySelect.d.ts +1 -0
  5. package/dist/cjs/components/form/CountrySelect.d.ts.map +1 -1
  6. package/dist/cjs/components/form/CountrySelect.js +12 -8
  7. package/dist/cjs/components/form/CountrySelect.js.map +1 -1
  8. package/dist/cjs/components/form/Field.styles.d.ts +13 -1
  9. package/dist/cjs/components/form/Field.styles.d.ts.map +1 -1
  10. package/dist/cjs/components/form/Field.styles.js +17 -10
  11. package/dist/cjs/components/form/Field.styles.js.map +1 -1
  12. package/dist/cjs/components/form/FormField.d.ts +2 -1
  13. package/dist/cjs/components/form/FormField.d.ts.map +1 -1
  14. package/dist/cjs/components/form/FormField.js +14 -2
  15. package/dist/cjs/components/form/FormField.js.map +1 -1
  16. package/dist/cjs/components/form/Select.d.ts.map +1 -1
  17. package/dist/cjs/components/form/Select.js +7 -7
  18. package/dist/cjs/components/form/Select.js.map +1 -1
  19. package/dist/cjs/components/form/Upload/BaseUpload.d.ts +69 -0
  20. package/dist/cjs/components/form/Upload/BaseUpload.d.ts.map +1 -0
  21. package/dist/cjs/components/form/Upload/BaseUpload.js +264 -0
  22. package/dist/cjs/components/form/Upload/BaseUpload.js.map +1 -0
  23. package/dist/cjs/components/form/Upload/Upload.d.ts +3 -41
  24. package/dist/cjs/components/form/Upload/Upload.d.ts.map +1 -1
  25. package/dist/cjs/components/form/Upload/Upload.js +7 -258
  26. package/dist/cjs/components/form/Upload/Upload.js.map +1 -1
  27. package/dist/cjs/components/form/Upload/UploadedFile.js +2 -2
  28. package/dist/cjs/components/form/Upload/UploadedFile.js.map +1 -1
  29. package/dist/cjs/components/form/Upload/WithUploadToIpfs.js +2 -2
  30. package/dist/cjs/components/form/Upload/WithUploadToIpfs.js.map +1 -1
  31. package/dist/cjs/components/form/index.d.ts +3 -2
  32. package/dist/cjs/components/form/index.d.ts.map +1 -1
  33. package/dist/cjs/components/form/index.js +4 -2
  34. package/dist/cjs/components/form/index.js.map +1 -1
  35. package/dist/cjs/components/form/types.d.ts +12 -6
  36. package/dist/cjs/components/form/types.d.ts.map +1 -1
  37. package/dist/cjs/index.d.ts +1 -0
  38. package/dist/cjs/index.d.ts.map +1 -1
  39. package/dist/cjs/index.js +1 -0
  40. package/dist/cjs/index.js.map +1 -1
  41. package/dist/cjs/lib/bytes/bytesToSize.d.ts +1 -1
  42. package/dist/cjs/lib/bytes/bytesToSize.d.ts.map +1 -1
  43. package/dist/cjs/lib/bytes/bytesToSize.js +2 -1
  44. package/dist/cjs/lib/bytes/bytesToSize.js.map +1 -1
  45. package/dist/esm/components/error/SimpleError.d.ts +2 -2
  46. package/dist/esm/components/error/SimpleError.d.ts.map +1 -1
  47. package/dist/esm/components/error/SimpleError.js.map +1 -1
  48. package/dist/esm/components/form/CountrySelect.d.ts +1 -0
  49. package/dist/esm/components/form/CountrySelect.d.ts.map +1 -1
  50. package/dist/esm/components/form/CountrySelect.js +5 -2
  51. package/dist/esm/components/form/CountrySelect.js.map +1 -1
  52. package/dist/esm/components/form/Field.styles.d.ts +13 -1
  53. package/dist/esm/components/form/Field.styles.d.ts.map +1 -1
  54. package/dist/esm/components/form/Field.styles.js +11 -7
  55. package/dist/esm/components/form/Field.styles.js.map +1 -1
  56. package/dist/esm/components/form/FormField.d.ts +2 -1
  57. package/dist/esm/components/form/FormField.d.ts.map +1 -1
  58. package/dist/esm/components/form/FormField.js +2 -2
  59. package/dist/esm/components/form/FormField.js.map +1 -1
  60. package/dist/esm/components/form/Select.d.ts.map +1 -1
  61. package/dist/esm/components/form/Select.js +30 -26
  62. package/dist/esm/components/form/Select.js.map +1 -1
  63. package/dist/esm/components/form/Upload/BaseUpload.d.ts +69 -0
  64. package/dist/esm/components/form/Upload/BaseUpload.d.ts.map +1 -0
  65. package/dist/esm/components/form/Upload/BaseUpload.js +226 -0
  66. package/dist/esm/components/form/Upload/BaseUpload.js.map +1 -0
  67. package/dist/esm/components/form/Upload/Upload.d.ts +3 -41
  68. package/dist/esm/components/form/Upload/Upload.d.ts.map +1 -1
  69. package/dist/esm/components/form/Upload/Upload.js +5 -225
  70. package/dist/esm/components/form/Upload/Upload.js.map +1 -1
  71. package/dist/esm/components/form/Upload/UploadedFile.js +1 -1
  72. package/dist/esm/components/form/Upload/UploadedFile.js.map +1 -1
  73. package/dist/esm/components/form/Upload/WithUploadToIpfs.js +1 -1
  74. package/dist/esm/components/form/Upload/WithUploadToIpfs.js.map +1 -1
  75. package/dist/esm/components/form/index.d.ts +3 -2
  76. package/dist/esm/components/form/index.d.ts.map +1 -1
  77. package/dist/esm/components/form/index.js +2 -1
  78. package/dist/esm/components/form/index.js.map +1 -1
  79. package/dist/esm/components/form/types.d.ts +12 -6
  80. package/dist/esm/components/form/types.d.ts.map +1 -1
  81. package/dist/esm/index.d.ts +1 -0
  82. package/dist/esm/index.d.ts.map +1 -1
  83. package/dist/esm/index.js +1 -0
  84. package/dist/esm/index.js.map +1 -1
  85. package/dist/esm/lib/bytes/bytesToSize.d.ts +1 -1
  86. package/dist/esm/lib/bytes/bytesToSize.d.ts.map +1 -1
  87. package/dist/esm/lib/bytes/bytesToSize.js +1 -1
  88. package/dist/esm/lib/bytes/bytesToSize.js.map +1 -1
  89. package/package.json +5 -5
  90. package/src/components/error/SimpleError.tsx +2 -2
  91. package/src/components/form/CountrySelect.tsx +6 -2
  92. package/src/components/form/Field.styles.ts +28 -9
  93. package/src/components/form/FormField.tsx +4 -1
  94. package/src/components/form/Select.tsx +36 -32
  95. package/src/components/form/Upload/BaseUpload.tsx +366 -0
  96. package/src/components/form/Upload/Upload.tsx +8 -360
  97. package/src/components/form/Upload/UploadedFile.tsx +1 -1
  98. package/src/components/form/Upload/WithUploadToIpfs.tsx +1 -1
  99. package/src/components/form/index.ts +3 -2
  100. package/src/components/form/types.ts +12 -6
  101. package/src/index.tsx +1 -0
  102. package/src/lib/bytes/bytesToSize.ts +1 -1
@@ -0,0 +1,366 @@
1
+ import * as Sentry from "@sentry/browser";
2
+ import { useField } from "formik";
3
+ import { Image, Trash, VideoCamera } from "phosphor-react";
4
+ import React, { useCallback, useEffect, useRef, useState } from "react";
5
+ import { loadAndSetMedia } from "../../../lib/base64/base64";
6
+ import { bytesToSize } from "../../../lib/bytes/bytesToSize";
7
+ import { theme } from "../../../theme";
8
+
9
+ import Loading from "../../ui/loading/LoadingWrapper";
10
+ import ThemedButton from "../../ui/ThemedButton";
11
+ import { Typography } from "../../ui/Typography";
12
+ import Error from "../Error";
13
+ import {
14
+ FieldFileUploadWrapper,
15
+ FieldInput,
16
+ FileUploadWrapper,
17
+ ImagePreview,
18
+ VideoPreview
19
+ } from "../Field.styles";
20
+ import type {
21
+ UploadFileType,
22
+ UploadProps as UploadPropsWithNoIpfs,
23
+ FileProps
24
+ } from "../types";
25
+ import UploadedFiles from "./UploadedFiles";
26
+ import { WithUploadToIpfs, WithUploadToIpfsProps } from "./WithUploadToIpfs";
27
+ import { useModal } from "../../modal/useModal";
28
+ import { ImageEditorModal } from "./ImageEditorModal/ImageEditorModal";
29
+ const colors = theme.colors.light;
30
+ export type BaseUploadProps = UploadPropsWithNoIpfs;
31
+ function BaseUpload({
32
+ name,
33
+ accept = "image/*",
34
+ disabled,
35
+ maxSize,
36
+ multiple = false,
37
+ trigger,
38
+ onFilesSelect,
39
+ placeholder,
40
+ wrapperProps,
41
+ onLoadSinglePreviewImage,
42
+ withUpload,
43
+ withEditor,
44
+ saveToIpfs,
45
+ loadMedia,
46
+ onLoading,
47
+ width,
48
+ height,
49
+ borderRadius,
50
+ imgPreviewStyle,
51
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
+ removeFile,
53
+ saveButtonTheme,
54
+ theme,
55
+ ...props
56
+ }: UploadPropsWithNoIpfs & WithUploadToIpfsProps) {
57
+ const { updateProps, store } = useModal();
58
+ const [showEditor, setShowEditor] = useState<boolean>(false);
59
+ const [isLoading, setIsLoading] = useState<boolean>(false);
60
+ const [preview, setPreview] = useState<string | null>();
61
+ const [field, meta, helpers] = useField(name);
62
+
63
+ const handleLoading = useCallback(
64
+ (loadingValue: boolean) => {
65
+ onLoading?.(loadingValue);
66
+ setIsLoading(loadingValue);
67
+ },
68
+ [onLoading]
69
+ );
70
+
71
+ const errorMessage = meta.error && meta.touched ? meta.error : "";
72
+ const displayError = typeof errorMessage === "string" && errorMessage !== "";
73
+
74
+ const inputRef = useRef<HTMLInputElement | null>(null);
75
+ const [nativeFiles, setNativeFiles] = useState<File[] | null>(null);
76
+ const setFiles = useCallback(
77
+ (value: unknown) => {
78
+ helpers.setValue(value);
79
+ },
80
+ [helpers]
81
+ );
82
+
83
+ const files = field.value as UploadFileType[];
84
+ const mimetypes = accept.split(",").map((acc) => acc.trim());
85
+ const isImageOnly = mimetypes.every((mimetype) =>
86
+ mimetype.startsWith("image/")
87
+ );
88
+ const isVideoOnly = mimetypes.every((mimetype) =>
89
+ mimetype.startsWith("video/")
90
+ );
91
+
92
+ useEffect(() => {
93
+ onFilesSelect?.(files);
94
+ helpers.setValue(files);
95
+
96
+ if (!multiple && files && files?.length !== 0) {
97
+ if (isImageOnly) {
98
+ if (withUpload) {
99
+ loadIpfsImagePreview(files[0] as FileProps);
100
+ } else {
101
+ loadAndSetMedia(files[0] as File, (base64Uri) => {
102
+ setPreview(base64Uri);
103
+ onLoadSinglePreviewImage?.(base64Uri);
104
+ });
105
+ }
106
+ } else if (isVideoOnly) {
107
+ if (withUpload) {
108
+ loadIpfsVideo(files[0] as FileProps);
109
+ } else {
110
+ loadAndSetMedia(files[0] as File, (base64Uri) => {
111
+ setPreview(base64Uri);
112
+ });
113
+ }
114
+ }
115
+ }
116
+ }, [files]); // eslint-disable-line
117
+
118
+ const loadIpfsVideo = async (file: FileProps) => {
119
+ const fileSrc = file && file?.src ? file?.src : false;
120
+ if (!fileSrc) {
121
+ return false;
122
+ }
123
+ handleLoading(true);
124
+ try {
125
+ const imagePreview = await loadMedia(fileSrc || "");
126
+ if (imagePreview) {
127
+ setPreview(imagePreview);
128
+ } else {
129
+ console.warn(
130
+ `imagePreview ${imagePreview} is falsy in loadIpfsImagePreview`
131
+ );
132
+ }
133
+ } catch (error) {
134
+ console.error(error);
135
+ Sentry.captureException(error);
136
+ } finally {
137
+ handleLoading(false);
138
+ }
139
+ };
140
+
141
+ const loadIpfsImagePreview = async (file: FileProps) => {
142
+ const fileSrc = file && file?.src ? file?.src : false;
143
+ if (!fileSrc) {
144
+ return false;
145
+ }
146
+ try {
147
+ handleLoading(true);
148
+ const imagePreview = await loadMedia(fileSrc || "");
149
+ if (imagePreview) {
150
+ setPreview(imagePreview);
151
+ onLoadSinglePreviewImage?.(imagePreview);
152
+ } else {
153
+ console.warn(
154
+ `imagePreview ${imagePreview} is falsy in loadIpfsImagePreview`
155
+ );
156
+ }
157
+ } catch (error) {
158
+ console.error(error);
159
+ Sentry.captureException(error);
160
+ } finally {
161
+ handleLoading(false);
162
+ }
163
+ };
164
+
165
+ const handleChooseFile = () => {
166
+ const input = inputRef.current;
167
+ if (input) {
168
+ input.click();
169
+ }
170
+ };
171
+
172
+ const handleRemoveAllFiles = () => {
173
+ if (disabled) {
174
+ return;
175
+ }
176
+ setFiles([]);
177
+ setPreview(null);
178
+ };
179
+
180
+ const handleRemoveFile = (index: number) => {
181
+ const newArray = files.filter(
182
+ (i: File | FileProps, k: number) => k !== index
183
+ );
184
+ setFiles(newArray);
185
+ };
186
+
187
+ const handleChange = useCallback(
188
+ async (filesArray: File[] | null) => {
189
+ if (!meta.touched) {
190
+ helpers.setTouched(true);
191
+ }
192
+
193
+ if (!filesArray) {
194
+ return;
195
+ }
196
+ for (const file of filesArray) {
197
+ if (maxSize) {
198
+ if (file.size > maxSize) {
199
+ const error = `File size cannot exceed more than ${bytesToSize(
200
+ maxSize
201
+ )}`;
202
+ // TODO: change to notification
203
+ console.error(error);
204
+ }
205
+ }
206
+ }
207
+ setFiles(filesArray);
208
+ },
209
+ [helpers, maxSize, meta.touched, setFiles]
210
+ );
211
+
212
+ const handleSave = useCallback(
213
+ async (efiles: File[] | null) => {
214
+ if (!meta.touched) {
215
+ helpers.setTouched(true);
216
+ }
217
+ handleLoading(true);
218
+ const files = await saveToIpfs(efiles);
219
+ if (files) {
220
+ setFiles(files);
221
+ } else {
222
+ setFiles([]);
223
+ console.warn(
224
+ `There has been an error because 'files' ${files} is falsy in handleSave`
225
+ );
226
+ }
227
+ handleLoading(false);
228
+ },
229
+ [meta.touched, handleLoading, saveToIpfs, helpers, setFiles]
230
+ );
231
+ const saveFn = withUpload ? handleSave : handleChange;
232
+ const style = {
233
+ borderRadius: borderRadius ? `${borderRadius}%` : "",
234
+ width: width ? `100%` : ""
235
+ };
236
+ return (
237
+ <>
238
+ {withEditor && showEditor && (
239
+ <ImageEditorModal
240
+ saveButtonTheme={saveButtonTheme}
241
+ files={nativeFiles}
242
+ borderRadius={borderRadius}
243
+ width={width}
244
+ height={height}
245
+ hideModal={async (fileList) => {
246
+ if (fileList) {
247
+ await saveFn(fileList);
248
+ }
249
+
250
+ setShowEditor(false);
251
+ updateProps({
252
+ ...store,
253
+ modalType: store.modalType,
254
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
255
+ // @ts-ignore
256
+ modalProps: {
257
+ ...store.modalProps,
258
+ hidden: false
259
+ }
260
+ });
261
+ }}
262
+ />
263
+ )}
264
+ <FieldFileUploadWrapper {...wrapperProps} $disabled={!!disabled}>
265
+ <FieldInput
266
+ {...props}
267
+ hidden
268
+ type="file"
269
+ accept={accept}
270
+ multiple={multiple}
271
+ onChange={async (e) => {
272
+ const files = e.target.files
273
+ ? Object.values(e.target.files)
274
+ : e.target.files;
275
+
276
+ if (files && withEditor) {
277
+ setNativeFiles(files);
278
+ setShowEditor(true);
279
+ updateProps({
280
+ ...store,
281
+ modalType: store.modalType,
282
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
283
+ // @ts-ignore
284
+ modalProps: {
285
+ ...store.modalProps,
286
+ hidden: true
287
+ }
288
+ });
289
+ } else {
290
+ await saveFn(files);
291
+ }
292
+ e.target.value = ""; // allow user to select the same file again
293
+ }}
294
+ ref={(ref) => {
295
+ inputRef.current = ref;
296
+ }}
297
+ disabled={disabled}
298
+ />
299
+ {trigger ? (
300
+ <ThemedButton onClick={handleChooseFile} type="button">
301
+ <>{trigger}</>
302
+ </ThemedButton>
303
+ ) : (
304
+ <FileUploadWrapper
305
+ data-disabled={disabled}
306
+ onClick={handleChooseFile}
307
+ $error={errorMessage}
308
+ style={style}
309
+ theme={theme?.triggerTheme}
310
+ >
311
+ {isLoading ? (
312
+ <Loading size={2} />
313
+ ) : (
314
+ <>
315
+ {field.value && field.value?.length !== 0 && preview ? (
316
+ <>
317
+ {isVideoOnly ? (
318
+ <VideoPreview
319
+ src={
320
+ preview?.startsWith("http")
321
+ ? preview
322
+ : "data:video/mp4;base64," +
323
+ preview?.substring(
324
+ "data:application/octet-stream;base64,".length
325
+ )
326
+ }
327
+ autoPlay
328
+ muted
329
+ loop
330
+ />
331
+ ) : (
332
+ <ImagePreview
333
+ style={{ ...imgPreviewStyle }}
334
+ src={preview}
335
+ />
336
+ )}
337
+ </>
338
+ ) : isVideoOnly ? (
339
+ <VideoCamera size={24} />
340
+ ) : (
341
+ <Image size={24} />
342
+ )}
343
+ {placeholder && (
344
+ <Typography tag="p" marginBottom={0} textAlign="center">
345
+ {placeholder}
346
+ </Typography>
347
+ )}
348
+ </>
349
+ )}
350
+ </FileUploadWrapper>
351
+ )}
352
+ {!disabled && field.value && field.value?.length !== 0 && preview && (
353
+ <div onClick={handleRemoveAllFiles} data-remove style={style}>
354
+ <Trash size={24} color={colors.white} />
355
+ </div>
356
+ )}
357
+ {multiple && (
358
+ <UploadedFiles files={files} handleRemoveFile={handleRemoveFile} />
359
+ )}
360
+ </FieldFileUploadWrapper>
361
+ <Error display={displayError} message={errorMessage} />
362
+ </>
363
+ );
364
+ }
365
+
366
+ export default WithUploadToIpfs(BaseUpload);