@pareto-engineering/design-system 4.2.1-alpha.0 → 4.2.3

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 (73) hide show
  1. package/dist/cjs/a/XMLEditor/XMLEditor.js +3 -15
  2. package/dist/cjs/f/FormInput/FormInput.js +6 -0
  3. package/dist/cjs/f/common/utils/index.js +8 -1
  4. package/dist/cjs/f/common/utils/validators.js +17 -0
  5. package/dist/cjs/f/fields/ChoicesInput/common/Choice/Choice.js +3 -2
  6. package/dist/cjs/f/fields/EditorInput/EditorInput.js +2 -15
  7. package/dist/cjs/f/fields/EditorInput/common/StopPropagationPlugin.js +2 -7
  8. package/dist/cjs/f/fields/FileUpload/FileUpload.js +228 -0
  9. package/dist/cjs/f/fields/FileUpload/common/FilePreview/FilePreview.js +90 -0
  10. package/dist/cjs/f/fields/FileUpload/common/FilePreview/index.js +13 -0
  11. package/dist/cjs/f/fields/FileUpload/common/FilePreview/styles.scss +92 -0
  12. package/dist/cjs/f/fields/FileUpload/common/index.js +12 -0
  13. package/dist/cjs/f/fields/FileUpload/fileUploadOptions.js +31 -0
  14. package/dist/cjs/f/fields/FileUpload/index.js +20 -0
  15. package/dist/cjs/f/fields/FileUpload/styles.scss +73 -0
  16. package/dist/cjs/f/fields/SelectInput/common/Menu/Menu.js +1 -1
  17. package/dist/cjs/f/fields/SelectInput/common/Multiple/Multiple.js +1 -1
  18. package/dist/cjs/f/fields/SelectInput/styles.scss +1 -1
  19. package/dist/cjs/f/fields/index.js +14 -1
  20. package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +34 -7
  21. package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +11 -0
  22. package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +9 -3
  23. package/dist/cjs/g/FormBuilder/common/Renderer/common/Section/Section.js +2 -2
  24. package/dist/es/a/XMLEditor/XMLEditor.js +3 -15
  25. package/dist/es/f/FormInput/FormInput.js +7 -1
  26. package/dist/es/f/common/utils/index.js +2 -1
  27. package/dist/es/f/common/utils/validators.js +10 -0
  28. package/dist/es/f/fields/ChoicesInput/common/Choice/Choice.js +3 -2
  29. package/dist/es/f/fields/EditorInput/EditorInput.js +2 -15
  30. package/dist/es/f/fields/EditorInput/common/StopPropagationPlugin.js +2 -6
  31. package/dist/es/f/fields/FileUpload/FileUpload.js +218 -0
  32. package/dist/es/f/fields/FileUpload/common/FilePreview/FilePreview.js +80 -0
  33. package/dist/es/f/fields/FileUpload/common/FilePreview/index.js +2 -0
  34. package/dist/es/f/fields/FileUpload/common/FilePreview/styles.scss +92 -0
  35. package/dist/es/f/fields/FileUpload/common/index.js +2 -0
  36. package/dist/es/f/fields/FileUpload/fileUploadOptions.js +25 -0
  37. package/dist/es/f/fields/FileUpload/index.js +3 -0
  38. package/dist/es/f/fields/FileUpload/styles.scss +73 -0
  39. package/dist/es/f/fields/SelectInput/common/Menu/Menu.js +1 -1
  40. package/dist/es/f/fields/SelectInput/common/Multiple/Multiple.js +1 -1
  41. package/dist/es/f/fields/SelectInput/styles.scss +1 -1
  42. package/dist/es/f/fields/index.js +2 -1
  43. package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +35 -8
  44. package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +11 -0
  45. package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +9 -3
  46. package/dist/es/g/FormBuilder/common/Renderer/common/Section/Section.js +2 -1
  47. package/package.json +4 -4
  48. package/src/stories/f/FileUpload.stories.jsx +55 -0
  49. package/src/stories/g/FormBuilder.stories.jsx +19 -97
  50. package/src/ui/a/XMLEditor/XMLEditor.jsx +1 -15
  51. package/src/ui/f/FormInput/FormInput.jsx +11 -0
  52. package/src/ui/f/common/utils/index.js +1 -0
  53. package/src/ui/f/common/utils/validators.js +10 -0
  54. package/src/ui/f/fields/ChoicesInput/common/Choice/Choice.jsx +2 -0
  55. package/src/ui/f/fields/EditorInput/EditorInput.jsx +1 -15
  56. package/src/ui/f/fields/EditorInput/common/StopPropagationPlugin.jsx +2 -6
  57. package/src/ui/f/fields/FileUpload/FileUpload.jsx +277 -0
  58. package/src/ui/f/fields/FileUpload/common/FilePreview/FilePreview.jsx +115 -0
  59. package/src/ui/f/fields/FileUpload/common/FilePreview/index.js +2 -0
  60. package/src/ui/f/fields/FileUpload/common/FilePreview/styles.scss +92 -0
  61. package/src/ui/f/fields/FileUpload/common/index.js +2 -0
  62. package/src/ui/f/fields/FileUpload/fileUploadOptions.js +32 -0
  63. package/src/ui/f/fields/FileUpload/index.js +3 -0
  64. package/src/ui/f/fields/FileUpload/styles.scss +73 -0
  65. package/src/ui/f/fields/SelectInput/common/Menu/Menu.jsx +1 -0
  66. package/src/ui/f/fields/SelectInput/common/Multiple/Multiple.jsx +1 -1
  67. package/src/ui/f/fields/SelectInput/styles.scss +1 -1
  68. package/src/ui/f/fields/index.js +1 -0
  69. package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.jsx +53 -11
  70. package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +11 -0
  71. package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +13 -3
  72. package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +7 -2
  73. package/tests/__snapshots__/Storyshots.test.js.snap +163 -159
@@ -0,0 +1,73 @@
1
+ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
+
3
+ @use "@pareto-engineering/bem";
4
+
5
+ $default-padding: 1rem;
6
+ $default-margin: 1rem;
7
+
8
+ .#{bem.$base}.file-upload {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--gap);
12
+
13
+
14
+ > p {
15
+ color: var(--y);
16
+ margin: 0;
17
+ }
18
+
19
+ > .#{bem.$base}.description {
20
+ height: auto;
21
+ }
22
+
23
+ > .#{bem.$base}.form-label {
24
+ align-items: center;
25
+ border: var(--theme-default-border-style) var(--ui-lines);
26
+ border-radius: calc(var(--theme-default-border-radius) / 2);
27
+ color: var(--heading);
28
+ cursor: pointer;
29
+ display: flex;
30
+ gap: calc(var(--gap) / 2);
31
+ padding: $default-padding;
32
+ width: fit-content;
33
+
34
+ &:has(>input:disabled) {
35
+ --icon-color: var(--hard-disabled);
36
+ color: var(--hard-disabled);
37
+ cursor: not-allowed;
38
+ }
39
+
40
+ &:has(>input:not(:disabled)) {
41
+ &:hover,
42
+ &:active {
43
+ border: var(--theme-hover-input-border);
44
+ }
45
+ }
46
+
47
+ > .ai-icon {
48
+ color: var(--icon-color, var(--interactive));
49
+ font-size: calc(var(--s2) * 1rem);
50
+ }
51
+
52
+ > input[type="file"] {
53
+ display: none;
54
+ }
55
+ }
56
+
57
+ > .attached-files {
58
+ display: flex;
59
+ gap: var(--gap);
60
+
61
+ > p {
62
+ margin: 0;
63
+ }
64
+
65
+ > .files {
66
+ align-items: center;
67
+ display: flex;
68
+ flex-wrap: wrap;
69
+ gap: var(--gap);
70
+ width: 100%;
71
+ }
72
+ }
73
+ }
@@ -41,7 +41,7 @@ const Menu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
41
41
  item,
42
42
  index
43
43
  }), {
44
- className: ['item', highlightedIndex === index && _exports.default.modifierActive].filter(Boolean).join(' ')
44
+ className: ['item', item.disabled && _exports.default.modifierDisabled, highlightedIndex === index && _exports.default.modifierActive].filter(Boolean).join(' ')
45
45
  }), /*#__PURE__*/React.createElement("p", null, item.label))));
46
46
  });
47
47
  Menu.propTypes = {
@@ -136,7 +136,7 @@ const Multiple = _ref => {
136
136
  case _downshift.useCombobox.stateChangeTypes.InputKeyDownEnter:
137
137
  case _downshift.useCombobox.stateChangeTypes.ItemClick:
138
138
  case _downshift.useCombobox.stateChangeTypes.InputBlur:
139
- if (selectedItem) {
139
+ if (selectedItem && !selectedItem?.disabled) {
140
140
  setSearchInputValue('');
141
141
  addSelectedItem(selectedItem);
142
142
  }
@@ -122,7 +122,7 @@ $default-gap: var(--gap);
122
122
  margin: 0;
123
123
  }
124
124
 
125
- &.#{bem.$modifier-active} {
125
+ &.#{bem.$modifier-active}:not(.disabled) {
126
126
  background-color: var(--y);
127
127
 
128
128
  > p {
@@ -21,6 +21,12 @@ Object.defineProperty(exports, "EditorInput", {
21
21
  return _EditorInput.EditorInput;
22
22
  }
23
23
  });
24
+ Object.defineProperty(exports, "FileUpload", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _FileUpload.FileUpload;
28
+ }
29
+ });
24
30
  Object.defineProperty(exports, "LinkInput", {
25
31
  enumerable: true,
26
32
  get: function () {
@@ -69,6 +75,12 @@ Object.defineProperty(exports, "TextareaInput", {
69
75
  return _TextareaInput.TextareaInput;
70
76
  }
71
77
  });
78
+ Object.defineProperty(exports, "fileUploadOptions", {
79
+ enumerable: true,
80
+ get: function () {
81
+ return _FileUpload.fileUploadOptions;
82
+ }
83
+ });
72
84
  var _TextInput = require("./TextInput");
73
85
  var _SelectInput = require("./SelectInput");
74
86
  var _ChoicesInput = require("./ChoicesInput");
@@ -79,4 +91,5 @@ var _QuerySelect = require("./QuerySelect");
79
91
  var _Checkbox = require("./Checkbox");
80
92
  var _QueryChoices = require("./QueryChoices");
81
93
  var _LinkInput = require("./LinkInput");
82
- var _EditorInput = require("./EditorInput");
94
+ var _EditorInput = require("./EditorInput");
95
+ var _FileUpload = require("./FileUpload");
@@ -22,6 +22,9 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
22
22
 
23
23
  const baseClassName = _exports.default.base;
24
24
  const componentClassName = 'input-builder';
25
+ const getToggleSwitchStyles = condition => condition ? {
26
+ '--slider-background-color': 'var(--disabled)'
27
+ } : {};
25
28
 
26
29
  /**
27
30
  * This is the component description.
@@ -45,11 +48,6 @@ const InputBuilder = _ref => {
45
48
  const handleToggleRequired = () => {
46
49
  setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.required`, !input?.required);
47
50
  };
48
- const toggleSwitchStyles = {
49
- ...(!input?.required ? {
50
- '--slider-background-color': 'var(--disabled)'
51
- } : {})
52
- };
53
51
  const [hasDescription, setHasDescription] = (0, _react.useState)(false);
54
52
 
55
53
  // TODO: handle nav logic
@@ -69,6 +67,10 @@ const InputBuilder = _ref => {
69
67
  } = e.target;
70
68
  setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.options.${optionIndex}.label`, value);
71
69
  };
70
+ const isFile = input?.type === 'file';
71
+ const handleToggleShowSpecificFileTypes = () => {
72
+ setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.showSpecificFileTypes`, !input.showSpecificFileTypes);
73
+ };
72
74
  return /*#__PURE__*/React.createElement("div", {
73
75
  id: id,
74
76
  className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
@@ -102,6 +104,9 @@ const InputBuilder = _ref => {
102
104
  }, {
103
105
  value: 'choices',
104
106
  label: 'Radio buttons'
107
+ }, {
108
+ value: 'file',
109
+ label: 'File upload'
105
110
  }]
106
111
  }), /*#__PURE__*/React.createElement("div", {
107
112
  className: "controls"
@@ -117,7 +122,7 @@ const InputBuilder = _ref => {
117
122
  }, "Required"), /*#__PURE__*/React.createElement(_a.ToggleSwitch, {
118
123
  handleOnChange: handleToggleRequired,
119
124
  checked: input?.required,
120
- style: toggleSwitchStyles,
125
+ style: getToggleSwitchStyles(!input?.required),
121
126
  inputId: `sections_${sectionIndex}_inputs.${inputIndex}_toggle`
122
127
  })), /*#__PURE__*/React.createElement(_ActionsContainer.ActionsContainer, null, /*#__PURE__*/React.createElement("p", null, "Show"), /*#__PURE__*/React.createElement("ul", null, /*#__PURE__*/React.createElement("li", {
123
128
  className: `option ${hasDescription ? 'with-check-mark' : ''}`
@@ -181,7 +186,29 @@ const InputBuilder = _ref => {
181
186
  }, "+")), /*#__PURE__*/React.createElement("span", {
182
187
  className: "text x-paragraph c-x"
183
188
  }, "Add Option")));
184
- })));
189
+ }), isFile && /*#__PURE__*/React.createElement("div", {
190
+ className: "input-file-options"
191
+ }, /*#__PURE__*/React.createElement(_f.TextInput, {
192
+ label: "Maximum number of files",
193
+ name: `sections.${sectionIndex}.inputs.${inputIndex}.maxCount`,
194
+ placeholder: "1",
195
+ type: "number",
196
+ min: "0",
197
+ validate: _f.integerAndGreaterThanZero
198
+ }), /*#__PURE__*/React.createElement("div", {
199
+ className: "specific-file-types"
200
+ }, /*#__PURE__*/React.createElement(_a.ToggleSwitch, {
201
+ handleOnChange: handleToggleShowSpecificFileTypes,
202
+ checked: input?.showSpecificFileTypes,
203
+ style: getToggleSwitchStyles(!input?.showSpecificFileTypes),
204
+ inputId: `sections_${sectionIndex}_inputs.${inputIndex}_show_specific_file_types`
205
+ }), /*#__PURE__*/React.createElement("span", {
206
+ className: "s0"
207
+ }, "Allow only specific file types")), input?.showSpecificFileTypes && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_f.ChoicesInput, {
208
+ name: `sections.${sectionIndex}.inputs.${inputIndex}.accept`,
209
+ options: _f.fileUploadOptions,
210
+ multiple: true
211
+ })))));
185
212
  };
186
213
  InputBuilder.propTypes = {
187
214
  /**
@@ -137,6 +137,17 @@ $default-list-width: var(--action-button-width, 18rem);
137
137
  }
138
138
  }
139
139
  }
140
+
141
+ > .input-file-options {
142
+ display: flex;
143
+ flex-direction: column;
144
+ gap: var(--gap);
145
+ margin-bottom: $default-margin;
146
+
147
+ > .specific-file-types {
148
+ display: flex;
149
+ }
150
+ }
140
151
  }
141
152
  }
142
153
 
@@ -22,9 +22,14 @@ const reconstructFormDataWithValues = (formData, values) => {
22
22
  const newData = {
23
23
  ...formData
24
24
  };
25
- Object.keys(values).forEach(key => {
25
+ Object.keys(values).forEach(async key => {
26
26
  const [sectionIdx, inputIdx] = key.match(/\d+/g).map(Number);
27
- newData.sections[sectionIdx].inputs[inputIdx].value = values[key];
27
+ if (key.includes('files')) {
28
+ const files = values[key].map(file => URL.createObjectURL(file));
29
+ newData.sections[sectionIdx].inputs[inputIdx].files = files;
30
+ } else {
31
+ newData.sections[sectionIdx].inputs[inputIdx].value = values[key];
32
+ }
28
33
  });
29
34
  return newData;
30
35
  };
@@ -125,7 +130,8 @@ const Renderer = _ref => {
125
130
  return /*#__PURE__*/React.createElement(_formik.Form, null, updatedFormData.sections.map((section, sectionIndex) => sectionIndex === currentSectionIndex && /*#__PURE__*/React.createElement(_common.Section, _extends({
126
131
  key: `${section.title}`
127
132
  }, section, {
128
- readOnly: readOnly
133
+ readOnly: readOnly,
134
+ setUpdatedFormData: setUpdatedFormData
129
135
  }))), /*#__PURE__*/React.createElement("div", {
130
136
  className: "navigator-container"
131
137
  }, /*#__PURE__*/React.createElement(_b.Button, {
@@ -12,7 +12,7 @@ var _exports = _interopRequireDefault(require("@pareto-engineering/bem/exports")
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
  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); }
14
14
  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; }
15
- function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /* @pareto-engineering/generator-front 1.1.1-alpha.2 */ // Local Definitions
15
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /* eslint-disable no-alert */ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */ // Local Definitions
16
16
  const baseClassName = _exports.default.base;
17
17
  const componentClassName = 'section';
18
18
 
@@ -39,7 +39,7 @@ const Section = _ref => {
39
39
  }, title), /*#__PURE__*/React.createElement(_.ExpandableLexicalPreview, {
40
40
  nodes: description,
41
41
  name: "instructions"
42
- }), inputs.map(input => /*#__PURE__*/React.createElement(_f.FormInput, _extends({
42
+ }), inputs?.map(input => /*#__PURE__*/React.createElement(_f.FormInput, _extends({
43
43
  key: input.name
44
44
  }, input, {
45
45
  disabled: readOnly
@@ -27,9 +27,7 @@ const XMLEditor = ({
27
27
  gutterWidth,
28
28
  config,
29
29
  onChange,
30
- onBlur,
31
- stopAllPropagation,
32
- stopPropagationKeys
30
+ onBlur
33
31
  }) => {
34
32
  const editorRef = useRef();
35
33
  useEffect(() => {
@@ -44,9 +42,7 @@ const XMLEditor = ({
44
42
  }
45
43
  }), EditorView.domEventHandlers({
46
44
  keydown(e) {
47
- if (stopPropagationKeys?.includes(e.key) || stopAllPropagation) {
48
- e.stopPropagation();
49
- }
45
+ e.stopPropagation();
50
46
  }
51
47
  })]
52
48
  });
@@ -102,18 +98,10 @@ XMLEditor.propTypes = {
102
98
  * The width of the gutter.
103
99
  */
104
100
  gutterWidth: PropTypes.string,
105
- /**
106
- * The keys to stop propagation on.
107
- */
108
- stopPropagationKeys: PropTypes.arrayOf(PropTypes.string),
109
101
  /**
110
102
  * The callback for when the editor loses focus.
111
103
  */
112
- onBlur: PropTypes.func,
113
- /**
114
- * Whether to stop all propagation of keys to keep focus on the editor.
115
- */
116
- stopAllPropagation: PropTypes.bool
104
+ onBlur: PropTypes.func
117
105
  };
118
106
  XMLEditor.defaultProps = {
119
107
  config: `<View>
@@ -3,7 +3,7 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
3
3
  import * as React from 'react';
4
4
  import { memo } from 'react';
5
5
  import PropTypes from 'prop-types';
6
- import { TextInput, TextareaInput, ChoicesInput, SelectInput, QueryCombobox, QuerySelect, RatingsInput, Checkbox, QueryChoices, LinkInput, EditorInput } from "../fields";
6
+ import { TextInput, TextareaInput, ChoicesInput, SelectInput, QueryCombobox, QuerySelect, RatingsInput, Checkbox, QueryChoices, LinkInput, EditorInput, FileUpload } from "../fields";
7
7
  import "./styles.scss";
8
8
 
9
9
  // Local Definitions
@@ -89,6 +89,12 @@ const FormInput = ({
89
89
  disabled: disabled
90
90
  }, otherProps));
91
91
  }
92
+ if (type === 'file') {
93
+ return /*#__PURE__*/React.createElement(FileUpload, _extends({
94
+ className: newClassName,
95
+ disabled: disabled
96
+ }, otherProps));
97
+ }
92
98
  if (extraTypes?.[type]) {
93
99
  const Component = extraTypes[type];
94
100
  return /*#__PURE__*/React.createElement(Component, _extends({
@@ -1 +1,2 @@
1
- export { lookUpInputValueFromFetchedOptions } from "./lookUpInputValueFromFetchedOptions";
1
+ export { lookUpInputValueFromFetchedOptions } from "./lookUpInputValueFromFetchedOptions";
2
+ export { integerAndGreaterThanZero } from "./validators";
@@ -0,0 +1,10 @@
1
+ export const integerAndGreaterThanZero = value => {
2
+ let error = '';
3
+ if (value && value <= 0 || value === 0) {
4
+ error = 'Value must be greator than zero.';
5
+ }
6
+ if (value && value % 1 !== 0) {
7
+ error = 'You must enter a whole number.';
8
+ }
9
+ return error;
10
+ };
@@ -23,7 +23,8 @@ const Choice = ({
23
23
  value,
24
24
  multiple,
25
25
  validate,
26
- disabled
26
+ disabled,
27
+ ...otherProps
27
28
  }) => {
28
29
  const type = multiple ? 'checkbox' : 'radio';
29
30
  const [field] = useField({
@@ -39,7 +40,7 @@ const Choice = ({
39
40
  type: type,
40
41
  id: id,
41
42
  name: name
42
- }, field, {
43
+ }, field, otherProps, {
43
44
  value: value,
44
45
  disabled: disabled
45
46
  })), /*#__PURE__*/React.createElement("label", {
@@ -48,7 +48,6 @@ const EditorInput = ({
48
48
  style,
49
49
  name,
50
50
  label,
51
- // validate,
52
51
  resize,
53
52
  color,
54
53
  rows,
@@ -57,7 +56,6 @@ const EditorInput = ({
57
56
  description,
58
57
  disabled,
59
58
  showDebugger,
60
- stopPropagationKeys,
61
59
  setEditorState
62
60
  // ...otherProps
63
61
  }) => {
@@ -145,9 +143,7 @@ const EditorInput = ({
145
143
  onChange: onChange
146
144
  }), /*#__PURE__*/React.createElement(LinkPlugin, null), /*#__PURE__*/React.createElement(LexicalClickableLinkPlugin, null), /*#__PURE__*/React.createElement(TabIndentationPlugin, null), setEditorState && /*#__PURE__*/React.createElement(ExposeEditorStatePlugin, {
147
145
  setEditorState: setEditorState
148
- }), /*#__PURE__*/React.createElement(HistoryPlugin, null), stopPropagationKeys && /*#__PURE__*/React.createElement(StopPropagationPlugin, {
149
- stopPropagationKeys: stopPropagationKeys
150
- }), /*#__PURE__*/React.createElement(FormDescription, {
146
+ }), /*#__PURE__*/React.createElement(HistoryPlugin, null), /*#__PURE__*/React.createElement(StopPropagationPlugin, null), /*#__PURE__*/React.createElement(FormDescription, {
151
147
  className: "s-1",
152
148
  description: description,
153
149
  name: name
@@ -174,11 +170,6 @@ EditorInput.propTypes = {
174
170
  * The input label
175
171
  */
176
172
  label: PropTypes.string.isRequired,
177
- /**
178
- * The input value validator function
179
- */
180
- // validate:PropTypes.func,
181
-
182
173
  /**
183
174
  * The number of rows int the text area
184
175
  */
@@ -210,11 +201,7 @@ EditorInput.propTypes = {
210
201
  /**
211
202
  * Whether to show the debugger or not
212
203
  */
213
- showDebugger: PropTypes.bool,
214
- /**
215
- * Map to stop propagation of the given keys
216
- */
217
- stopPropagationKeys: PropTypes.arrayOf(PropTypes.string)
204
+ showDebugger: PropTypes.bool
218
205
  };
219
206
  EditorInput.defaultProps = {
220
207
  rows: 10,
@@ -1,14 +1,10 @@
1
1
  import { useInsertionEffect } from 'react';
2
2
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
3
- const StopPropagationPlugin = ({
4
- stopPropagationKeys
5
- }) => {
3
+ const StopPropagationPlugin = () => {
6
4
  const [editor] = useLexicalComposerContext();
7
5
  useInsertionEffect(() => {
8
6
  const onKeyDown = e => {
9
- if (stopPropagationKeys?.includes(e.key)) {
10
- e.stopPropagation();
11
- }
7
+ e.stopPropagation();
12
8
  };
13
9
  return editor.registerRootListener((rootElement, prevRootElement) => {
14
10
  if (prevRootElement !== null) {
@@ -0,0 +1,218 @@
1
+ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
+ import * as React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { useField } from 'formik';
5
+ import styleNames from '@pareto-engineering/bem/exports';
6
+ import "./styles.scss";
7
+ import { FilePreview } from "./common";
8
+ import { FormLabel, FormDescription } from "../../common";
9
+
10
+ // Local Definitions
11
+
12
+ const baseClassName = styleNames.base;
13
+ const componentClassName = 'file-upload';
14
+
15
+ /**
16
+ * This is the component description.
17
+ */
18
+ const FileUpload = ({
19
+ id,
20
+ className: userClassName,
21
+ style,
22
+ label,
23
+ description,
24
+ accept,
25
+ multiple,
26
+ name,
27
+ disabled,
28
+ maxCount,
29
+ maxCountError,
30
+ maxSize,
31
+ maxSizeError,
32
+ onChange,
33
+ onDelete,
34
+ // TODO: TBD when connecting with BE
35
+ // onPreview,
36
+ // progress,
37
+ // percent,
38
+ // uploadStatus,
39
+ filePreviewAlignment,
40
+ optional,
41
+ labelColor,
42
+ color
43
+ // ...otherProps
44
+ }) => {
45
+ const [field,, helpers] = useField({
46
+ name
47
+ });
48
+ const {
49
+ value
50
+ } = field;
51
+ const {
52
+ setError,
53
+ setValue,
54
+ setTouched
55
+ } = helpers;
56
+ const handleChange = event => {
57
+ setTouched(true, false);
58
+ const newFiles = Array.from(event.currentTarget.files);
59
+ const currentFiles = value || [];
60
+ const currentCount = currentFiles.length + newFiles.length;
61
+ if (maxCount && currentCount > maxCount) {
62
+ setError(maxCountError || `Maximum of ${maxCount} files allowed`);
63
+ return;
64
+ }
65
+ const duplicateFiles = newFiles.filter(newFile => currentFiles.some(currentFile => currentFile.name === newFile.name));
66
+ if (duplicateFiles.length > 0) {
67
+ setError('You cannot upload the same file twice.');
68
+ return;
69
+ }
70
+ if (maxSize) {
71
+ const oversizedFiles = newFiles.filter(file => file.size > maxSize);
72
+ if (oversizedFiles.length > 0) {
73
+ setError(maxSizeError || `File size exceeds the limit of ${maxSize} bytes`);
74
+ return;
75
+ }
76
+ }
77
+ const updatedFiles = [...currentFiles, ...newFiles];
78
+ setValue(updatedFiles);
79
+ onChange?.(updatedFiles);
80
+
81
+ // eslint-disable-next-line no-param-reassign
82
+ event.target.value = null;
83
+ };
84
+ const handleDelete = fileIndex => {
85
+ const updatedFiles = value.filter((_, i) => i !== fileIndex);
86
+ setValue(updatedFiles);
87
+ onDelete?.(fileIndex);
88
+ };
89
+ const acceptOptions = Array.isArray(accept) ? accept?.join(',') : accept;
90
+ return /*#__PURE__*/React.createElement("div", {
91
+ id: id,
92
+ className: [baseClassName, componentClassName, userClassName, `preview-${filePreviewAlignment}`, `y-${color}`].filter(e => e).join(' '),
93
+ style: style
94
+ }, /*#__PURE__*/React.createElement("p", null, label), /*#__PURE__*/React.createElement(FormDescription, {
95
+ className: "s-1",
96
+ description: description,
97
+ name: name
98
+ }), !disabled && /*#__PURE__*/React.createElement(FormLabel, {
99
+ name: name,
100
+ color: labelColor,
101
+ optional: optional
102
+ }, /*#__PURE__*/React.createElement("input", {
103
+ id: name,
104
+ className: "file",
105
+ type: "file",
106
+ accept: acceptOptions,
107
+ multiple: multiple || maxCount && maxCount > 0,
108
+ disabled: disabled,
109
+ onChange: handleChange
110
+ }), /*#__PURE__*/React.createElement("span", {
111
+ className: "ai-icon"
112
+ }, "U"), /*#__PURE__*/React.createElement("span", null, "Attach file")), value?.length > 0 && /*#__PURE__*/React.createElement("div", {
113
+ className: "attached-files"
114
+ }, /*#__PURE__*/React.createElement("p", null, "Attached files:"), /*#__PURE__*/React.createElement("div", {
115
+ 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
+ })))));
122
+ };
123
+ FileUpload.propTypes = {
124
+ /**
125
+ * The HTML id for this element
126
+ */
127
+ id: PropTypes.string,
128
+ /**
129
+ * The HTML class names for this element
130
+ */
131
+ className: PropTypes.string,
132
+ /**
133
+ * The React-written, css properties for this element.
134
+ */
135
+ style: PropTypes.objectOf(PropTypes.string),
136
+ /**
137
+ * The label text for the file input
138
+ */
139
+ label: PropTypes.string,
140
+ /**
141
+ * The description text below the label
142
+ */
143
+ description: PropTypes.string,
144
+ /**
145
+ * The color of the text
146
+ */
147
+ color: PropTypes.string,
148
+ /**
149
+ * The accepted file types (e.g., 'image/*')
150
+ */
151
+ accept: PropTypes.string,
152
+ /**
153
+ * Whether to allow multiple file uploads
154
+ */
155
+ multiple: PropTypes.bool,
156
+ /**
157
+ * The name attribute for the input
158
+ */
159
+ name: PropTypes.string.isRequired,
160
+ /**
161
+ * Whether the the input should be disabled
162
+ */
163
+ disabled: PropTypes.bool,
164
+ /**
165
+ * The maximum number of files allowed
166
+ */
167
+ maxCount: PropTypes.number,
168
+ /**
169
+ * The error message when max count is exceeded
170
+ */
171
+ maxCountError: PropTypes.string,
172
+ /**
173
+ * The maximum size of files allowed (in bytes)
174
+ */
175
+ maxSize: PropTypes.number,
176
+ /**
177
+ * The error message when file size exceeds max size
178
+ */
179
+ maxSizeError: PropTypes.string,
180
+ /**
181
+ * The upload progress value (0-100)
182
+ */
183
+ // progress:PropTypes.number,
184
+
185
+ /**
186
+ * The function to handle file change events
187
+ */
188
+ onChange: PropTypes.func,
189
+ /**
190
+ * The function to handle file delete events
191
+ */
192
+ onDelete: PropTypes.func,
193
+ /**
194
+ * The function to handle file download events
195
+ */
196
+ // onDownload:PropTypes.func,
197
+
198
+ /**
199
+ * The function to handle file preview events
200
+ */
201
+ // onPreview:PropTypes.func,
202
+
203
+ /**
204
+ * The upload status of the file if being sent to an external service (e.g., 'uploading', 'done')
205
+ */
206
+ // uploadStatus:PropTypes.oneOf(['uploading', 'done', 'failed']),
207
+
208
+ /**
209
+ * The alignment for file previews WRT the upload input
210
+ */
211
+ filePreviewAlignment: PropTypes.oneOf(['left', 'right', 'top', 'bottom'])
212
+ };
213
+ FileUpload.defaultProps = {
214
+ disabled: false,
215
+ color: 'paragraph',
216
+ filePreviewAlignment: 'bottom'
217
+ };
218
+ export default FileUpload;