@pareto-engineering/design-system 4.2.3 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/cjs/f/fields/FileUpload/FileUpload.js +38 -32
  2. package/dist/cjs/f/fields/FileUpload/common/FilePreview/FilePreview.js +46 -18
  3. package/dist/cjs/f/fields/FileUpload/common/FilePreview/styles.scss +5 -4
  4. package/dist/cjs/f/fields/FileUpload/index.js +14 -2
  5. package/dist/cjs/f/fields/FileUpload/{fileUploadOptions.js → utils.js} +16 -2
  6. package/dist/cjs/f/fields/index.js +12 -0
  7. package/dist/cjs/g/FormBuilder/FormBuilder.js +11 -3
  8. package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +6 -2
  9. package/dist/cjs/g/FormBuilder/common/Renderer/common/Section/Section.js +6 -2
  10. package/dist/es/f/fields/FileUpload/FileUpload.js +37 -32
  11. package/dist/es/f/fields/FileUpload/common/FilePreview/FilePreview.js +46 -18
  12. package/dist/es/f/fields/FileUpload/common/FilePreview/styles.scss +5 -4
  13. package/dist/es/f/fields/FileUpload/index.js +1 -1
  14. package/dist/es/f/fields/FileUpload/{fileUploadOptions.js → utils.js} +13 -1
  15. package/dist/es/f/fields/index.js +1 -1
  16. package/dist/es/g/FormBuilder/FormBuilder.js +11 -3
  17. package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +6 -2
  18. package/dist/es/g/FormBuilder/common/Renderer/common/Section/Section.js +6 -2
  19. package/package.json +2 -2
  20. package/src/ui/f/fields/FileUpload/FileUpload.jsx +32 -30
  21. package/src/ui/f/fields/FileUpload/common/FilePreview/FilePreview.jsx +64 -19
  22. package/src/ui/f/fields/FileUpload/common/FilePreview/styles.scss +5 -4
  23. package/src/ui/f/fields/FileUpload/index.js +1 -1
  24. package/src/ui/f/fields/FileUpload/{fileUploadOptions.js → utils.js} +17 -0
  25. package/src/ui/f/fields/index.js +6 -1
  26. package/src/ui/g/FormBuilder/FormBuilder.jsx +9 -0
  27. package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +4 -0
  28. package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +4 -0
  29. package/tests/__snapshots__/Storyshots.test.js.snap +22 -0
@@ -40,16 +40,13 @@ const FileUpload = _ref => {
40
40
  maxSize,
41
41
  maxSizeError,
42
42
  onChange,
43
- onDelete,
44
- // TODO: TBD when connecting with BE
45
- // onPreview,
46
- // progress,
47
- // percent,
48
- // uploadStatus,
43
+ uploadStatus,
49
44
  filePreviewAlignment,
50
45
  optional,
51
46
  labelColor,
52
- color
47
+ color,
48
+ viewOnly,
49
+ handleFileDelete
53
50
  // ...otherProps
54
51
  } = _ref;
55
52
  const [field,, helpers] = (0, _formik.useField)({
@@ -91,10 +88,17 @@ const FileUpload = _ref => {
91
88
  // eslint-disable-next-line no-param-reassign
92
89
  event.target.value = null;
93
90
  };
94
- const handleDelete = fileIndex => {
95
- const updatedFiles = value.filter((_, i) => i !== fileIndex);
91
+ const handleDelete = _ref2 => {
92
+ let {
93
+ fileIndex,
94
+ identifier
95
+ } = _ref2;
96
+ const updatedFiles = value?.filter((_, i) => i !== fileIndex);
96
97
  setValue(updatedFiles);
97
- onDelete?.(fileIndex);
98
+ handleFileDelete?.({
99
+ fileIndex,
100
+ identifier
101
+ });
98
102
  };
99
103
  const acceptOptions = Array.isArray(accept) ? accept?.join(',') : accept;
100
104
  return /*#__PURE__*/React.createElement("div", {
@@ -105,7 +109,7 @@ const FileUpload = _ref => {
105
109
  className: "s-1",
106
110
  description: description,
107
111
  name: name
108
- }), !disabled && /*#__PURE__*/React.createElement(_common2.FormLabel, {
112
+ }), !viewOnly && /*#__PURE__*/React.createElement(_common2.FormLabel, {
109
113
  name: name,
110
114
  color: labelColor,
111
115
  optional: optional
@@ -123,12 +127,20 @@ const FileUpload = _ref => {
123
127
  className: "attached-files"
124
128
  }, /*#__PURE__*/React.createElement("p", null, "Attached files:"), /*#__PURE__*/React.createElement("div", {
125
129
  className: "files"
126
- }, value.map((file, indx) => /*#__PURE__*/React.createElement(_common.FilePreview, {
127
- file: file,
128
- key: file.name,
129
- disabled: disabled,
130
- handleDelete: () => handleDelete(indx)
131
- })))));
130
+ }, value.map((file, indx) => {
131
+ const isFileObject = file instanceof File;
132
+ return /*#__PURE__*/React.createElement(_common.FilePreview, {
133
+ file: file,
134
+ key: isFileObject ? file.name : file,
135
+ disabled: disabled,
136
+ handleDelete: () => handleDelete({
137
+ fileIndex: indx,
138
+ identifier: isFileObject ? file.name : file?.id
139
+ }),
140
+ uploadStatus: uploadStatus?.[file?.name],
141
+ viewOnly: viewOnly
142
+ });
143
+ }))));
132
144
  };
133
145
  FileUpload.propTypes = {
134
146
  /**
@@ -199,30 +211,24 @@ FileUpload.propTypes = {
199
211
  /**
200
212
  * The function to handle file delete events
201
213
  */
202
- onDelete: _propTypes.default.func,
203
- /**
204
- * The function to handle file download events
205
- */
206
- // onDownload:PropTypes.func,
207
-
214
+ handleFileDelete: _propTypes.default.func,
208
215
  /**
209
- * The function to handle file preview events
216
+ * The upload status of the file with the file name as the key
210
217
  */
211
- // onPreview:PropTypes.func,
212
-
218
+ uploadStatus: _propTypes.default.objectOf(_propTypes.default.string),
213
219
  /**
214
- * The upload status of the file if being sent to an external service (e.g., 'uploading', 'done')
220
+ * The alignment for file previews WRT the upload input
215
221
  */
216
- // uploadStatus:PropTypes.oneOf(['uploading', 'done', 'failed']),
217
-
222
+ filePreviewAlignment: _propTypes.default.oneOf(['left', 'right', 'top', 'bottom']),
218
223
  /**
219
- * The alignment for file previews WRT the upload input
224
+ * Whether the file upload is in view only mode
220
225
  */
221
- filePreviewAlignment: _propTypes.default.oneOf(['left', 'right', 'top', 'bottom'])
226
+ viewOnly: _propTypes.default.bool
222
227
  };
223
228
  FileUpload.defaultProps = {
224
229
  disabled: false,
225
230
  color: 'paragraph',
226
- filePreviewAlignment: 'bottom'
231
+ filePreviewAlignment: 'bottom',
232
+ viewOnly: false
227
233
  };
228
234
  var _default = exports.default = FileUpload;
@@ -7,10 +7,10 @@ exports.default = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _exports = _interopRequireDefault(require("@pareto-engineering/bem/exports"));
10
- require("./styles.scss");
11
10
  var _a = require("../../../../../a");
11
+ require("./styles.scss");
12
12
  var _b = require("../../../../../b");
13
- var _fileUploadOptions = require("../../fileUploadOptions");
13
+ var _utils = require("../../utils");
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
15
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
16
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -20,12 +20,12 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
20
20
 
21
21
  const baseClassName = _exports.default.base;
22
22
  const componentClassName = 'file-preview';
23
- const getFileType = file => {
24
- const mimeType = file.type;
25
- const extension = file.name.split('.').pop().toLowerCase();
26
- const fileType = _fileUploadOptions.fileUploadOptions.find(option => option.value.includes(mimeType) || option.value.includes(extension));
27
- return fileType ? fileType.key : 'unknown';
23
+ const statusColorMap = {
24
+ pending: 'yellow',
25
+ error: 'red',
26
+ success: 'green'
28
27
  };
28
+ const FILE_UPLOAD_COMPLETE_PROGRESS = 100;
29
29
 
30
30
  /**
31
31
  * This is the component description.
@@ -37,10 +37,25 @@ const FilePreview = _ref => {
37
37
  style,
38
38
  file,
39
39
  disabled,
40
- handleDelete
40
+ handleDelete,
41
+ uploadStatus,
42
+ color,
43
+ uploadProgress
41
44
  // ...otherProps
42
45
  } = _ref;
43
- const type = getFileType(file);
46
+ const isFileObject = file instanceof File;
47
+ const type = isFileObject ? (0, _utils.getFileType)(file) : (0, _utils.getFileTypeFromUrl)(file?.url);
48
+ const status = uploadStatus?.status;
49
+ const statusColor = statusColorMap[status] ?? color;
50
+ const isPending = status === 'pending';
51
+ // isPreview means the file is uploaded and previewed while other files can still be uploaded
52
+ const isSuccess = status === 'success' || file?.isPreview;
53
+ const handlePreview = () => {
54
+ if (!isFileObject) {
55
+ window.open(file.url, '_blank');
56
+ }
57
+ };
58
+ const canDelete = file?.isPreview || isFileObject;
44
59
  return /*#__PURE__*/React.createElement("div", {
45
60
  id: id,
46
61
  className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
@@ -55,18 +70,22 @@ const FilePreview = _ref => {
55
70
  }, file.name), /*#__PURE__*/React.createElement(_b.Button, {
56
71
  isCompact: true,
57
72
  isSimple: true,
58
- onClick: handleDelete
73
+ onClick: () => canDelete ? handleDelete() : handlePreview()
59
74
  }, /*#__PURE__*/React.createElement("span", {
60
75
  className: "icon x-ui-icons c-x"
61
- }, "Y"))), !disabled && /*#__PURE__*/React.createElement("div", {
62
- className: "progress-status"
76
+ }, canDelete ? 'Y' : '9'))), !disabled && /*#__PURE__*/React.createElement("div", {
77
+ className: `progress-status x-${statusColor}`
63
78
  }, /*#__PURE__*/React.createElement("div", {
64
79
  className: "status"
65
- }, /*#__PURE__*/React.createElement("span", {
80
+ }, isPending ? /*#__PURE__*/React.createElement(_a.LoadingCircle, {
81
+ className: `x-${statusColor}`,
82
+ heightWidth: "1rem",
83
+ color: statusColor
84
+ }) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
66
85
  className: "icon"
67
- }, "I"), /*#__PURE__*/React.createElement("span", null, "Uploaded")), /*#__PURE__*/React.createElement(_a.ProgressBar, {
68
- color: "green",
69
- progress: 100,
86
+ }, isSuccess ? 'I' : 'Y'), /*#__PURE__*/React.createElement("span", null, isSuccess ? 'Uploaded' : 'Error'))), /*#__PURE__*/React.createElement(_a.ProgressBar, {
87
+ color: statusColor,
88
+ progress: isPending ? uploadProgress : FILE_UPLOAD_COMPLETE_PROGRESS,
70
89
  height: "3px"
71
90
  })));
72
91
  };
@@ -82,9 +101,18 @@ FilePreview.propTypes = {
82
101
  /**
83
102
  * The React-written, css properties for this element.
84
103
  */
85
- style: _propTypes.default.objectOf(_propTypes.default.string)
104
+ style: _propTypes.default.objectOf(_propTypes.default.string),
105
+ /**
106
+ * The base color of the file preview
107
+ */
108
+ color: _propTypes.default.string,
109
+ /**
110
+ * The upload progress of the file
111
+ */
112
+ uploadProgress: _propTypes.default.number
86
113
  };
87
114
  FilePreview.defaultProps = {
88
- // someProp:false
115
+ color: 'green',
116
+ uploadProgress: 45
89
117
  };
90
118
  var _default = exports.default = FilePreview;
@@ -3,6 +3,7 @@
3
3
  @use "@pareto-engineering/bem";
4
4
 
5
5
  $default-padding: 1rem;
6
+ $default-margin: 1rem;
6
7
  $files-per-row: 3;
7
8
  $total-gaps: $files-per-row - 1;
8
9
  $combined-gap: calc(var(--gap) * $total-gaps);
@@ -75,15 +76,15 @@ $default-file-width: calc($width-without-gaps / $files-per-row);
75
76
  > .progress-status {
76
77
  > .status {
77
78
  align-items: center;
78
- // TODO handle as a prop
79
- color: var(--green);
79
+ color: var(--x);
80
80
  display: flex;
81
81
  gap: calc(var(--gap) / 2);
82
+ margin-bottom: calc($default-margin / 4);
82
83
 
83
84
  > .icon {
84
- background-color: var(--green);
85
+ background-color: var(--x);
85
86
  border-radius: 50%;
86
- color: var(--on-green);
87
+ color: var(--on-x);
87
88
  font-size: calc(var(--s-2) * 1rem);
88
89
  padding: calc($default-padding / 4);
89
90
  }
@@ -12,9 +12,21 @@ Object.defineProperty(exports, "FileUpload", {
12
12
  Object.defineProperty(exports, "fileUploadOptions", {
13
13
  enumerable: true,
14
14
  get: function () {
15
- return _fileUploadOptions.fileUploadOptions;
15
+ return _utils.fileUploadOptions;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "getFileType", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _utils.getFileType;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "getFileTypeFromUrl", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _utils.getFileTypeFromUrl;
16
28
  }
17
29
  });
18
30
  var _FileUpload = _interopRequireDefault(require("./FileUpload"));
19
- var _fileUploadOptions = require("./fileUploadOptions");
31
+ var _utils = require("./utils");
20
32
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.fileUploadOptions = void 0;
6
+ exports.getFileTypeFromUrl = exports.getFileType = exports.fileUploadOptions = void 0;
7
7
  const fileUploadOptions = exports.fileUploadOptions = [{
8
8
  key: 'FILE',
9
9
  value: '.doc,.docx,.odt,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.text',
@@ -28,4 +28,18 @@ const fileUploadOptions = exports.fileUploadOptions = [{
28
28
  key: 'AUD',
29
29
  value: '.mp3,.ogg,.wav,audio/mpeg,audio/ogg,audio/wav',
30
30
  label: 'Audio'
31
- }];
31
+ }];
32
+ const getFileType = file => {
33
+ const mimeType = file?.type;
34
+ const extension = file?.name?.split('.').pop().toLowerCase();
35
+ const fileType = fileUploadOptions.find(option => option.value.includes(mimeType) || option.value.includes(extension));
36
+ return fileType ? fileType.key : 'unknown';
37
+ };
38
+ exports.getFileType = getFileType;
39
+ const getFileTypeFromUrl = url => {
40
+ const urlWithoutParams = url.split('?')[0];
41
+ const extension = urlWithoutParams.split('.').pop().toLowerCase();
42
+ const fileType = fileUploadOptions.find(option => option.value.includes(extension));
43
+ return fileType ? fileType.key : 'unknown';
44
+ };
45
+ exports.getFileTypeFromUrl = getFileTypeFromUrl;
@@ -81,6 +81,18 @@ Object.defineProperty(exports, "fileUploadOptions", {
81
81
  return _FileUpload.fileUploadOptions;
82
82
  }
83
83
  });
84
+ Object.defineProperty(exports, "getFileType", {
85
+ enumerable: true,
86
+ get: function () {
87
+ return _FileUpload.getFileType;
88
+ }
89
+ });
90
+ Object.defineProperty(exports, "getFileTypeFromUrl", {
91
+ enumerable: true,
92
+ get: function () {
93
+ return _FileUpload.getFileTypeFromUrl;
94
+ }
95
+ });
84
96
  var _TextInput = require("./TextInput");
85
97
  var _SelectInput = require("./SelectInput");
86
98
  var _ChoicesInput = require("./ChoicesInput");
@@ -37,7 +37,9 @@ const FormBuilder = _ref => {
37
37
  onRendererError,
38
38
  onRendererFormSave,
39
39
  onBuilderValidate,
40
- initialBuilderValues
40
+ initialBuilderValues,
41
+ fileUploadStatus,
42
+ handleFileDelete
41
43
  // ...otherProps
42
44
  } = _ref;
43
45
  return /*#__PURE__*/React.createElement("div", {
@@ -56,7 +58,9 @@ const FormBuilder = _ref => {
56
58
  onSave: onRendererFormSave,
57
59
  readOnly: readOnly,
58
60
  shouldSubmit: shouldSubmit,
59
- onError: onRendererError
61
+ onError: onRendererError,
62
+ fileUploadStatus: fileUploadStatus,
63
+ handleFileDelete: handleFileDelete
60
64
  }));
61
65
  };
62
66
  FormBuilder.propTypes = {
@@ -99,7 +103,11 @@ FormBuilder.propTypes = {
99
103
  /**
100
104
  * Whether the form builder in renderer mode should submit the form values itself
101
105
  */
102
- shouldSubmit: _propTypes.default.bool
106
+ shouldSubmit: _propTypes.default.bool,
107
+ /**
108
+ * The upload status of files if any
109
+ */
110
+ fileUploadStatus: _propTypes.default.objectOf(_propTypes.default.string)
103
111
  };
104
112
  FormBuilder.defaultProps = {
105
113
  mode: 'build',
@@ -57,7 +57,9 @@ const Renderer = _ref => {
57
57
  readOnly,
58
58
  onSave,
59
59
  onError,
60
- shouldSubmit
60
+ shouldSubmit,
61
+ fileUploadStatus,
62
+ handleFileDelete
61
63
  // ...otherProps
62
64
  } = _ref;
63
65
  const [currentSectionIndex, setCurrentSectionIndex] = (0, _react.useState)(0);
@@ -131,7 +133,9 @@ const Renderer = _ref => {
131
133
  key: `${section.title}`
132
134
  }, section, {
133
135
  readOnly: readOnly,
134
- setUpdatedFormData: setUpdatedFormData
136
+ setUpdatedFormData: setUpdatedFormData,
137
+ fileUploadStatus: fileUploadStatus,
138
+ handleFileDelete: handleFileDelete
135
139
  }))), /*#__PURE__*/React.createElement("div", {
136
140
  className: "navigator-container"
137
141
  }, /*#__PURE__*/React.createElement(_b.Button, {
@@ -27,7 +27,9 @@ const Section = _ref => {
27
27
  title,
28
28
  description,
29
29
  inputs,
30
- readOnly
30
+ readOnly,
31
+ fileUploadStatus,
32
+ handleFileDelete
31
33
  // ...otherProps
32
34
  } = _ref;
33
35
  return /*#__PURE__*/React.createElement("div", {
@@ -42,7 +44,9 @@ const Section = _ref => {
42
44
  }), inputs?.map(input => /*#__PURE__*/React.createElement(_f.FormInput, _extends({
43
45
  key: input.name
44
46
  }, input, {
45
- disabled: readOnly
47
+ disabled: readOnly,
48
+ uploadStatus: fileUploadStatus,
49
+ handleFileDelete: handleFileDelete
46
50
  }))));
47
51
  };
48
52
  Section.propTypes = {
@@ -30,16 +30,13 @@ const FileUpload = ({
30
30
  maxSize,
31
31
  maxSizeError,
32
32
  onChange,
33
- onDelete,
34
- // TODO: TBD when connecting with BE
35
- // onPreview,
36
- // progress,
37
- // percent,
38
- // uploadStatus,
33
+ uploadStatus,
39
34
  filePreviewAlignment,
40
35
  optional,
41
36
  labelColor,
42
- color
37
+ color,
38
+ viewOnly,
39
+ handleFileDelete
43
40
  // ...otherProps
44
41
  }) => {
45
42
  const [field,, helpers] = useField({
@@ -81,10 +78,16 @@ const FileUpload = ({
81
78
  // eslint-disable-next-line no-param-reassign
82
79
  event.target.value = null;
83
80
  };
84
- const handleDelete = fileIndex => {
85
- const updatedFiles = value.filter((_, i) => i !== fileIndex);
81
+ const handleDelete = ({
82
+ fileIndex,
83
+ identifier
84
+ }) => {
85
+ const updatedFiles = value?.filter((_, i) => i !== fileIndex);
86
86
  setValue(updatedFiles);
87
- onDelete?.(fileIndex);
87
+ handleFileDelete?.({
88
+ fileIndex,
89
+ identifier
90
+ });
88
91
  };
89
92
  const acceptOptions = Array.isArray(accept) ? accept?.join(',') : accept;
90
93
  return /*#__PURE__*/React.createElement("div", {
@@ -95,7 +98,7 @@ const FileUpload = ({
95
98
  className: "s-1",
96
99
  description: description,
97
100
  name: name
98
- }), !disabled && /*#__PURE__*/React.createElement(FormLabel, {
101
+ }), !viewOnly && /*#__PURE__*/React.createElement(FormLabel, {
99
102
  name: name,
100
103
  color: labelColor,
101
104
  optional: optional
@@ -113,12 +116,20 @@ const FileUpload = ({
113
116
  className: "attached-files"
114
117
  }, /*#__PURE__*/React.createElement("p", null, "Attached files:"), /*#__PURE__*/React.createElement("div", {
115
118
  className: "files"
116
- }, value.map((file, indx) => /*#__PURE__*/React.createElement(FilePreview, {
117
- file: file,
118
- key: file.name,
119
- disabled: disabled,
120
- handleDelete: () => handleDelete(indx)
121
- })))));
119
+ }, value.map((file, indx) => {
120
+ const isFileObject = file instanceof File;
121
+ return /*#__PURE__*/React.createElement(FilePreview, {
122
+ file: file,
123
+ key: isFileObject ? file.name : file,
124
+ disabled: disabled,
125
+ handleDelete: () => handleDelete({
126
+ fileIndex: indx,
127
+ identifier: isFileObject ? file.name : file?.id
128
+ }),
129
+ uploadStatus: uploadStatus?.[file?.name],
130
+ viewOnly: viewOnly
131
+ });
132
+ }))));
122
133
  };
123
134
  FileUpload.propTypes = {
124
135
  /**
@@ -189,30 +200,24 @@ FileUpload.propTypes = {
189
200
  /**
190
201
  * The function to handle file delete events
191
202
  */
192
- onDelete: PropTypes.func,
193
- /**
194
- * The function to handle file download events
195
- */
196
- // onDownload:PropTypes.func,
197
-
203
+ handleFileDelete: PropTypes.func,
198
204
  /**
199
- * The function to handle file preview events
205
+ * The upload status of the file with the file name as the key
200
206
  */
201
- // onPreview:PropTypes.func,
202
-
207
+ uploadStatus: PropTypes.objectOf(PropTypes.string),
203
208
  /**
204
- * The upload status of the file if being sent to an external service (e.g., 'uploading', 'done')
209
+ * The alignment for file previews WRT the upload input
205
210
  */
206
- // uploadStatus:PropTypes.oneOf(['uploading', 'done', 'failed']),
207
-
211
+ filePreviewAlignment: PropTypes.oneOf(['left', 'right', 'top', 'bottom']),
208
212
  /**
209
- * The alignment for file previews WRT the upload input
213
+ * Whether the file upload is in view only mode
210
214
  */
211
- filePreviewAlignment: PropTypes.oneOf(['left', 'right', 'top', 'bottom'])
215
+ viewOnly: PropTypes.bool
212
216
  };
213
217
  FileUpload.defaultProps = {
214
218
  disabled: false,
215
219
  color: 'paragraph',
216
- filePreviewAlignment: 'bottom'
220
+ filePreviewAlignment: 'bottom',
221
+ viewOnly: false
217
222
  };
218
223
  export default FileUpload;
@@ -2,21 +2,21 @@
2
2
  import * as React from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import styleNames from '@pareto-engineering/bem/exports';
5
+ import { LoadingCircle, ProgressBar } from "../../../../../a";
5
6
 
6
7
  // Local Definitions
7
8
 
8
9
  import "./styles.scss";
9
- import { ProgressBar } from "../../../../../a";
10
10
  import { Button } from "../../../../../b";
11
- import { fileUploadOptions } from "../../fileUploadOptions";
11
+ import { getFileType, getFileTypeFromUrl } from "../../utils";
12
12
  const baseClassName = styleNames.base;
13
13
  const componentClassName = 'file-preview';
14
- const getFileType = file => {
15
- const mimeType = file.type;
16
- const extension = file.name.split('.').pop().toLowerCase();
17
- const fileType = fileUploadOptions.find(option => option.value.includes(mimeType) || option.value.includes(extension));
18
- return fileType ? fileType.key : 'unknown';
14
+ const statusColorMap = {
15
+ pending: 'yellow',
16
+ error: 'red',
17
+ success: 'green'
19
18
  };
19
+ const FILE_UPLOAD_COMPLETE_PROGRESS = 100;
20
20
 
21
21
  /**
22
22
  * This is the component description.
@@ -27,10 +27,25 @@ const FilePreview = ({
27
27
  style,
28
28
  file,
29
29
  disabled,
30
- handleDelete
30
+ handleDelete,
31
+ uploadStatus,
32
+ color,
33
+ uploadProgress
31
34
  // ...otherProps
32
35
  }) => {
33
- const type = getFileType(file);
36
+ const isFileObject = file instanceof File;
37
+ const type = isFileObject ? getFileType(file) : getFileTypeFromUrl(file?.url);
38
+ const status = uploadStatus?.status;
39
+ const statusColor = statusColorMap[status] ?? color;
40
+ const isPending = status === 'pending';
41
+ // isPreview means the file is uploaded and previewed while other files can still be uploaded
42
+ const isSuccess = status === 'success' || file?.isPreview;
43
+ const handlePreview = () => {
44
+ if (!isFileObject) {
45
+ window.open(file.url, '_blank');
46
+ }
47
+ };
48
+ const canDelete = file?.isPreview || isFileObject;
34
49
  return /*#__PURE__*/React.createElement("div", {
35
50
  id: id,
36
51
  className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
@@ -45,18 +60,22 @@ const FilePreview = ({
45
60
  }, file.name), /*#__PURE__*/React.createElement(Button, {
46
61
  isCompact: true,
47
62
  isSimple: true,
48
- onClick: handleDelete
63
+ onClick: () => canDelete ? handleDelete() : handlePreview()
49
64
  }, /*#__PURE__*/React.createElement("span", {
50
65
  className: "icon x-ui-icons c-x"
51
- }, "Y"))), !disabled && /*#__PURE__*/React.createElement("div", {
52
- className: "progress-status"
66
+ }, canDelete ? 'Y' : '9'))), !disabled && /*#__PURE__*/React.createElement("div", {
67
+ className: `progress-status x-${statusColor}`
53
68
  }, /*#__PURE__*/React.createElement("div", {
54
69
  className: "status"
55
- }, /*#__PURE__*/React.createElement("span", {
70
+ }, isPending ? /*#__PURE__*/React.createElement(LoadingCircle, {
71
+ className: `x-${statusColor}`,
72
+ heightWidth: "1rem",
73
+ color: statusColor
74
+ }) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
56
75
  className: "icon"
57
- }, "I"), /*#__PURE__*/React.createElement("span", null, "Uploaded")), /*#__PURE__*/React.createElement(ProgressBar, {
58
- color: "green",
59
- progress: 100,
76
+ }, isSuccess ? 'I' : 'Y'), /*#__PURE__*/React.createElement("span", null, isSuccess ? 'Uploaded' : 'Error'))), /*#__PURE__*/React.createElement(ProgressBar, {
77
+ color: statusColor,
78
+ progress: isPending ? uploadProgress : FILE_UPLOAD_COMPLETE_PROGRESS,
60
79
  height: "3px"
61
80
  })));
62
81
  };
@@ -72,9 +91,18 @@ FilePreview.propTypes = {
72
91
  /**
73
92
  * The React-written, css properties for this element.
74
93
  */
75
- style: PropTypes.objectOf(PropTypes.string)
94
+ style: PropTypes.objectOf(PropTypes.string),
95
+ /**
96
+ * The base color of the file preview
97
+ */
98
+ color: PropTypes.string,
99
+ /**
100
+ * The upload progress of the file
101
+ */
102
+ uploadProgress: PropTypes.number
76
103
  };
77
104
  FilePreview.defaultProps = {
78
- // someProp:false
105
+ color: 'green',
106
+ uploadProgress: 45
79
107
  };
80
108
  export default FilePreview;
@@ -3,6 +3,7 @@
3
3
  @use "@pareto-engineering/bem";
4
4
 
5
5
  $default-padding: 1rem;
6
+ $default-margin: 1rem;
6
7
  $files-per-row: 3;
7
8
  $total-gaps: $files-per-row - 1;
8
9
  $combined-gap: calc(var(--gap) * $total-gaps);
@@ -75,15 +76,15 @@ $default-file-width: calc($width-without-gaps / $files-per-row);
75
76
  > .progress-status {
76
77
  > .status {
77
78
  align-items: center;
78
- // TODO handle as a prop
79
- color: var(--green);
79
+ color: var(--x);
80
80
  display: flex;
81
81
  gap: calc(var(--gap) / 2);
82
+ margin-bottom: calc($default-margin / 4);
82
83
 
83
84
  > .icon {
84
- background-color: var(--green);
85
+ background-color: var(--x);
85
86
  border-radius: 50%;
86
- color: var(--on-green);
87
+ color: var(--on-x);
87
88
  font-size: calc(var(--s-2) * 1rem);
88
89
  padding: calc($default-padding / 4);
89
90
  }
@@ -1,3 +1,3 @@
1
1
  /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
2
  export { default as FileUpload } from "./FileUpload";
3
- export { fileUploadOptions } from "./fileUploadOptions";
3
+ export { fileUploadOptions, getFileType, getFileTypeFromUrl } from "./utils";
@@ -22,4 +22,16 @@ export const fileUploadOptions = [{
22
22
  key: 'AUD',
23
23
  value: '.mp3,.ogg,.wav,audio/mpeg,audio/ogg,audio/wav',
24
24
  label: 'Audio'
25
- }];
25
+ }];
26
+ export const getFileType = file => {
27
+ const mimeType = file?.type;
28
+ const extension = file?.name?.split('.').pop().toLowerCase();
29
+ const fileType = fileUploadOptions.find(option => option.value.includes(mimeType) || option.value.includes(extension));
30
+ return fileType ? fileType.key : 'unknown';
31
+ };
32
+ export const getFileTypeFromUrl = url => {
33
+ const urlWithoutParams = url.split('?')[0];
34
+ const extension = urlWithoutParams.split('.').pop().toLowerCase();
35
+ const fileType = fileUploadOptions.find(option => option.value.includes(extension));
36
+ return fileType ? fileType.key : 'unknown';
37
+ };
@@ -9,4 +9,4 @@ export { Checkbox } from "./Checkbox";
9
9
  export { QueryChoices } from "./QueryChoices";
10
10
  export { LinkInput } from "./LinkInput";
11
11
  export { EditorInput } from "./EditorInput";
12
- export { FileUpload, fileUploadOptions } from "./FileUpload";
12
+ export { FileUpload, fileUploadOptions, getFileType, getFileTypeFromUrl } from "./FileUpload";
@@ -27,7 +27,9 @@ const FormBuilder = ({
27
27
  onRendererError,
28
28
  onRendererFormSave,
29
29
  onBuilderValidate,
30
- initialBuilderValues
30
+ initialBuilderValues,
31
+ fileUploadStatus,
32
+ handleFileDelete
31
33
  // ...otherProps
32
34
  }) => /*#__PURE__*/React.createElement("div", {
33
35
  id: id,
@@ -45,7 +47,9 @@ const FormBuilder = ({
45
47
  onSave: onRendererFormSave,
46
48
  readOnly: readOnly,
47
49
  shouldSubmit: shouldSubmit,
48
- onError: onRendererError
50
+ onError: onRendererError,
51
+ fileUploadStatus: fileUploadStatus,
52
+ handleFileDelete: handleFileDelete
49
53
  }));
50
54
  FormBuilder.propTypes = {
51
55
  /**
@@ -87,7 +91,11 @@ FormBuilder.propTypes = {
87
91
  /**
88
92
  * Whether the form builder in renderer mode should submit the form values itself
89
93
  */
90
- shouldSubmit: PropTypes.bool
94
+ shouldSubmit: PropTypes.bool,
95
+ /**
96
+ * The upload status of files if any
97
+ */
98
+ fileUploadStatus: PropTypes.objectOf(PropTypes.string)
91
99
  };
92
100
  FormBuilder.defaultProps = {
93
101
  mode: 'build',
@@ -51,7 +51,9 @@ const Renderer = ({
51
51
  readOnly,
52
52
  onSave,
53
53
  onError,
54
- shouldSubmit
54
+ shouldSubmit,
55
+ fileUploadStatus,
56
+ handleFileDelete
55
57
  // ...otherProps
56
58
  }) => {
57
59
  const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
@@ -124,7 +126,9 @@ const Renderer = ({
124
126
  key: `${section.title}`
125
127
  }, section, {
126
128
  readOnly: readOnly,
127
- setUpdatedFormData: setUpdatedFormData
129
+ setUpdatedFormData: setUpdatedFormData,
130
+ fileUploadStatus: fileUploadStatus,
131
+ handleFileDelete: handleFileDelete
128
132
  }))), /*#__PURE__*/React.createElement("div", {
129
133
  className: "navigator-container"
130
134
  }, /*#__PURE__*/React.createElement(Button, {
@@ -22,7 +22,9 @@ const Section = ({
22
22
  title,
23
23
  description,
24
24
  inputs,
25
- readOnly
25
+ readOnly,
26
+ fileUploadStatus,
27
+ handleFileDelete
26
28
  // ...otherProps
27
29
  }) => /*#__PURE__*/React.createElement("div", {
28
30
  id: id,
@@ -36,7 +38,9 @@ const Section = ({
36
38
  }), inputs?.map(input => /*#__PURE__*/React.createElement(FormInput, _extends({
37
39
  key: input.name
38
40
  }, input, {
39
- disabled: readOnly
41
+ disabled: readOnly,
42
+ uploadStatus: fileUploadStatus,
43
+ handleFileDelete: handleFileDelete
40
44
  }))));
41
45
  Section.propTypes = {
42
46
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pareto-engineering/design-system",
3
- "version": "4.2.3",
3
+ "version": "4.3.0",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/es/index.js",
@@ -82,5 +82,5 @@
82
82
  "relay-test-utils": "^15.0.0"
83
83
  },
84
84
  "browserslist": "> 2%",
85
- "gitHead": "77c5790a1e998600f0f61931a8fcbd2177f53efc"
85
+ "gitHead": "f9d0eb4bf3a4d825b2da863d3a27c8d4d25ee818"
86
86
  }
@@ -37,16 +37,13 @@ const FileUpload = ({
37
37
  maxSize,
38
38
  maxSizeError,
39
39
  onChange,
40
- onDelete,
41
- // TODO: TBD when connecting with BE
42
- // onPreview,
43
- // progress,
44
- // percent,
45
- // uploadStatus,
40
+ uploadStatus,
46
41
  filePreviewAlignment,
47
42
  optional,
48
43
  labelColor,
49
44
  color,
45
+ viewOnly,
46
+ handleFileDelete,
50
47
  // ...otherProps
51
48
  }) => {
52
49
  const [field, , helpers] = useField({ name })
@@ -92,11 +89,11 @@ const FileUpload = ({
92
89
  event.target.value = null
93
90
  }
94
91
 
95
- const handleDelete = (fileIndex) => {
96
- const updatedFiles = value.filter((_, i) => i !== fileIndex)
92
+ const handleDelete = ({ fileIndex, identifier }) => {
93
+ const updatedFiles = value?.filter((_, i) => i !== fileIndex)
97
94
  setValue(updatedFiles)
98
95
 
99
- onDelete?.(fileIndex)
96
+ handleFileDelete?.({ fileIndex, identifier })
100
97
  }
101
98
 
102
99
  const acceptOptions = Array.isArray(accept) ? accept?.join(',') : accept
@@ -119,7 +116,7 @@ const FileUpload = ({
119
116
  >
120
117
  <p>{label}</p>
121
118
  <FormDescription className="s-1" description={description} name={name} />
122
- {!disabled && (
119
+ {!viewOnly && (
123
120
  <FormLabel
124
121
  name={name}
125
122
  color={labelColor}
@@ -146,14 +143,23 @@ const FileUpload = ({
146
143
  <div className="attached-files">
147
144
  <p>Attached files:</p>
148
145
  <div className="files">
149
- {value.map((file, indx) => (
150
- <FilePreview
151
- file={file}
152
- key={file.name}
153
- disabled={disabled}
154
- handleDelete={() => handleDelete(indx)}
155
- />
156
- ))}
146
+ {value.map((file, indx) => {
147
+ const isFileObject = file instanceof File
148
+
149
+ return (
150
+ <FilePreview
151
+ file={file}
152
+ key={isFileObject ? file.name : file}
153
+ disabled={disabled}
154
+ handleDelete={() => handleDelete({
155
+ fileIndex :indx,
156
+ identifier:isFileObject ? file.name : file?.id,
157
+ })}
158
+ uploadStatus={uploadStatus?.[file?.name]}
159
+ viewOnly={viewOnly}
160
+ />
161
+ )
162
+ })}
157
163
  </div>
158
164
  </div>
159
165
  )}
@@ -245,33 +251,29 @@ FileUpload.propTypes = {
245
251
  /**
246
252
  * The function to handle file delete events
247
253
  */
248
- onDelete:PropTypes.func,
254
+ handleFileDelete:PropTypes.func,
249
255
 
250
256
  /**
251
- * The function to handle file download events
257
+ * The upload status of the file with the file name as the key
252
258
  */
253
- // onDownload:PropTypes.func,
259
+ uploadStatus:PropTypes.objectOf(PropTypes.string),
254
260
 
255
261
  /**
256
- * The function to handle file preview events
257
- */
258
- // onPreview:PropTypes.func,
259
-
260
- /**
261
- * The upload status of the file if being sent to an external service (e.g., 'uploading', 'done')
262
+ * The alignment for file previews WRT the upload input
262
263
  */
263
- // uploadStatus:PropTypes.oneOf(['uploading', 'done', 'failed']),
264
+ filePreviewAlignment:PropTypes.oneOf(['left', 'right', 'top', 'bottom']),
264
265
 
265
266
  /**
266
- * The alignment for file previews WRT the upload input
267
+ * Whether the file upload is in view only mode
267
268
  */
268
- filePreviewAlignment:PropTypes.oneOf(['left', 'right', 'top', 'bottom']),
269
+ viewOnly:PropTypes.bool,
269
270
  }
270
271
 
271
272
  FileUpload.defaultProps = {
272
273
  disabled :false,
273
274
  color :'paragraph',
274
275
  filePreviewAlignment:'bottom',
276
+ viewOnly :false,
275
277
  }
276
278
 
277
279
  export default FileUpload
@@ -5,29 +5,28 @@ import PropTypes from 'prop-types'
5
5
 
6
6
  import styleNames from '@pareto-engineering/bem/exports'
7
7
 
8
+ import { LoadingCircle, ProgressBar } from 'ui/a'
9
+
8
10
  // Local Definitions
9
11
 
10
12
  import './styles.scss'
11
13
 
12
- import { ProgressBar } from 'ui/a'
13
-
14
14
  import { Button } from 'ui/b'
15
15
 
16
- import { fileUploadOptions } from '../../fileUploadOptions'
16
+ import { getFileType, getFileTypeFromUrl } from '../../utils'
17
17
 
18
18
  const baseClassName = styleNames.base
19
19
 
20
20
  const componentClassName = 'file-preview'
21
21
 
22
- const getFileType = (file) => {
23
- const mimeType = file.type
24
- const extension = file.name.split('.').pop().toLowerCase()
25
- const fileType = fileUploadOptions.find(
26
- (option) => option.value.includes(mimeType) || option.value.includes(extension))
27
-
28
- return fileType ? fileType.key : 'unknown'
22
+ const statusColorMap = {
23
+ pending:'yellow',
24
+ error :'red',
25
+ success:'green',
29
26
  }
30
27
 
28
+ const FILE_UPLOAD_COMPLETE_PROGRESS = 100
29
+
31
30
  /**
32
31
  * This is the component description.
33
32
  */
@@ -38,9 +37,28 @@ const FilePreview = ({
38
37
  file,
39
38
  disabled,
40
39
  handleDelete,
40
+ uploadStatus,
41
+ color,
42
+ uploadProgress,
41
43
  // ...otherProps
42
44
  }) => {
43
- const type = getFileType(file)
45
+ const isFileObject = file instanceof File
46
+ const type = isFileObject ? getFileType(file) : getFileTypeFromUrl(file?.url)
47
+
48
+ const status = uploadStatus?.status
49
+ const statusColor = statusColorMap[status] ?? color
50
+
51
+ const isPending = status === 'pending'
52
+ // isPreview means the file is uploaded and previewed while other files can still be uploaded
53
+ const isSuccess = status === 'success' || file?.isPreview
54
+
55
+ const handlePreview = () => {
56
+ if (!isFileObject) {
57
+ window.open(file.url, '_blank')
58
+ }
59
+ }
60
+
61
+ const canDelete = file?.isPreview || isFileObject
44
62
 
45
63
  return (
46
64
  <div
@@ -70,19 +88,35 @@ const FilePreview = ({
70
88
  {type}
71
89
  </span>
72
90
  <span title={file.name} className="name">{file.name}</span>
73
- <Button isCompact isSimple onClick={handleDelete}>
74
- <span className="icon x-ui-icons c-x">Y</span>
91
+ <Button
92
+ isCompact
93
+ isSimple
94
+ onClick={() => (canDelete ? handleDelete() : handlePreview())}
95
+ >
96
+ <span className="icon x-ui-icons c-x">{canDelete ? 'Y' : '9'}</span>
75
97
  </Button>
76
98
  </div>
77
99
  {!disabled && (
78
- <div className="progress-status">
100
+ <div className={`progress-status x-${statusColor}`}>
79
101
  <div className="status">
80
- <span className="icon">I</span>
81
- <span>Uploaded</span>
102
+ {isPending ? (
103
+ <LoadingCircle
104
+ className={`x-${statusColor}`}
105
+ heightWidth="1rem"
106
+ color={statusColor}
107
+ />
108
+ ) : (
109
+ <>
110
+ <span className="icon">
111
+ {isSuccess ? 'I' : 'Y'}
112
+ </span>
113
+ <span>{isSuccess ? 'Uploaded' : 'Error'}</span>
114
+ </>
115
+ )}
82
116
  </div>
83
117
  <ProgressBar
84
- color="green"
85
- progress={100}
118
+ color={statusColor}
119
+ progress={isPending ? uploadProgress : FILE_UPLOAD_COMPLETE_PROGRESS}
86
120
  height="3px"
87
121
  />
88
122
  </div>
@@ -106,10 +140,21 @@ FilePreview.propTypes = {
106
140
  * The React-written, css properties for this element.
107
141
  */
108
142
  style:PropTypes.objectOf(PropTypes.string),
143
+
144
+ /**
145
+ * The base color of the file preview
146
+ */
147
+ color:PropTypes.string,
148
+
149
+ /**
150
+ * The upload progress of the file
151
+ */
152
+ uploadProgress:PropTypes.number,
109
153
  }
110
154
 
111
155
  FilePreview.defaultProps = {
112
- // someProp:false
156
+ color :'green',
157
+ uploadProgress:45,
113
158
  }
114
159
 
115
160
  export default FilePreview
@@ -3,6 +3,7 @@
3
3
  @use "@pareto-engineering/bem";
4
4
 
5
5
  $default-padding: 1rem;
6
+ $default-margin: 1rem;
6
7
  $files-per-row: 3;
7
8
  $total-gaps: $files-per-row - 1;
8
9
  $combined-gap: calc(var(--gap) * $total-gaps);
@@ -75,15 +76,15 @@ $default-file-width: calc($width-without-gaps / $files-per-row);
75
76
  > .progress-status {
76
77
  > .status {
77
78
  align-items: center;
78
- // TODO handle as a prop
79
- color: var(--green);
79
+ color: var(--x);
80
80
  display: flex;
81
81
  gap: calc(var(--gap) / 2);
82
+ margin-bottom: calc($default-margin / 4);
82
83
 
83
84
  > .icon {
84
- background-color: var(--green);
85
+ background-color: var(--x);
85
86
  border-radius: 50%;
86
- color: var(--on-green);
87
+ color: var(--on-x);
87
88
  font-size: calc(var(--s-2) * 1rem);
88
89
  padding: calc($default-padding / 4);
89
90
  }
@@ -1,3 +1,3 @@
1
1
  /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
2
  export { default as FileUpload } from './FileUpload'
3
- export { fileUploadOptions } from './fileUploadOptions'
3
+ export { fileUploadOptions, getFileType, getFileTypeFromUrl } from './utils'
@@ -30,3 +30,20 @@ export const fileUploadOptions = [
30
30
  label:'Audio',
31
31
  },
32
32
  ]
33
+
34
+ export const getFileType = (file) => {
35
+ const mimeType = file?.type
36
+ const extension = file?.name?.split('.').pop().toLowerCase()
37
+ const fileType = fileUploadOptions.find(
38
+ (option) => option.value.includes(mimeType) || option.value.includes(extension))
39
+
40
+ return fileType ? fileType.key : 'unknown'
41
+ }
42
+
43
+ export const getFileTypeFromUrl = (url) => {
44
+ const urlWithoutParams = url.split('?')[0]
45
+ const extension = urlWithoutParams.split('.').pop().toLowerCase()
46
+ const fileType = fileUploadOptions.find((option) => option.value.includes(extension))
47
+
48
+ return fileType ? fileType.key : 'unknown'
49
+ }
@@ -9,4 +9,9 @@ export { Checkbox } from './Checkbox'
9
9
  export { QueryChoices } from './QueryChoices'
10
10
  export { LinkInput } from './LinkInput'
11
11
  export { EditorInput } from './EditorInput'
12
- export { FileUpload, fileUploadOptions } from './FileUpload'
12
+ export {
13
+ FileUpload,
14
+ fileUploadOptions,
15
+ getFileType,
16
+ getFileTypeFromUrl,
17
+ } from './FileUpload'
@@ -33,6 +33,8 @@ const FormBuilder = ({
33
33
  onRendererFormSave,
34
34
  onBuilderValidate,
35
35
  initialBuilderValues,
36
+ fileUploadStatus,
37
+ handleFileDelete,
36
38
  // ...otherProps
37
39
  }) => (
38
40
  <div
@@ -65,6 +67,8 @@ const FormBuilder = ({
65
67
  readOnly={readOnly}
66
68
  shouldSubmit={shouldSubmit}
67
69
  onError={onRendererError}
70
+ fileUploadStatus={fileUploadStatus}
71
+ handleFileDelete={handleFileDelete}
68
72
  />
69
73
  )}
70
74
  </div>
@@ -119,6 +123,11 @@ FormBuilder.propTypes = {
119
123
  * Whether the form builder in renderer mode should submit the form values itself
120
124
  */
121
125
  shouldSubmit:PropTypes.bool,
126
+
127
+ /**
128
+ * The upload status of files if any
129
+ */
130
+ fileUploadStatus:PropTypes.objectOf(PropTypes.string),
122
131
  }
123
132
 
124
133
  FormBuilder.defaultProps = {
@@ -62,6 +62,8 @@ const Renderer = ({
62
62
  onSave,
63
63
  onError,
64
64
  shouldSubmit,
65
+ fileUploadStatus,
66
+ handleFileDelete,
65
67
  // ...otherProps
66
68
  }) => {
67
69
  const [currentSectionIndex, setCurrentSectionIndex] = useState(0)
@@ -154,6 +156,8 @@ const Renderer = ({
154
156
  {...section}
155
157
  readOnly={readOnly}
156
158
  setUpdatedFormData={setUpdatedFormData}
159
+ fileUploadStatus={fileUploadStatus}
160
+ handleFileDelete={handleFileDelete}
157
161
  />
158
162
  )
159
163
  ))}
@@ -27,6 +27,8 @@ const Section = ({
27
27
  description,
28
28
  inputs,
29
29
  readOnly,
30
+ fileUploadStatus,
31
+ handleFileDelete,
30
32
  // ...otherProps
31
33
  }) => (
32
34
  <div
@@ -52,6 +54,8 @@ const Section = ({
52
54
  key={input.name}
53
55
  {...input}
54
56
  disabled={readOnly}
57
+ uploadStatus={fileUploadStatus}
58
+ handleFileDelete={handleFileDelete}
55
59
  />
56
60
  ))}
57
61
  </div>
@@ -32908,6 +32908,28 @@ exports[`Storyshots g/FormBuilder Renderer With Disabled 1`] = `
32908
32908
  <p>
32909
32909
  The file upload
32910
32910
  </p>
32911
+ <label
32912
+ className="base form-label x-paragraph"
32913
+ htmlFor="section_0_input_0"
32914
+ >
32915
+ <input
32916
+ accept=".mp4,.ogg,.webm,video/mp4,video/ogg,video/webm,.pdf,application/pdf"
32917
+ className="file"
32918
+ disabled={true}
32919
+ id="section_0_input_0"
32920
+ multiple={true}
32921
+ onChange={[Function]}
32922
+ type="file"
32923
+ />
32924
+ <span
32925
+ className="ai-icon"
32926
+ >
32927
+ U
32928
+ </span>
32929
+ <span>
32930
+ Attach file
32931
+ </span>
32932
+ </label>
32911
32933
  </div>
32912
32934
  </div>
32913
32935
  <div