@springmicro/forms 0.7.0 → 0.7.1

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 (78) hide show
  1. package/.eslintrc.cjs +22 -22
  2. package/README.md +11 -11
  3. package/dist/index.d.ts +0 -0
  4. package/dist/index.js +0 -0
  5. package/dist/index.umd.cjs +0 -0
  6. package/package.json +3 -3
  7. package/src/builder/bottom-drawer.tsx +429 -429
  8. package/src/builder/form-builder.tsx +256 -256
  9. package/src/builder/modal.tsx +39 -39
  10. package/src/builder/nodes/node-base.tsx +94 -94
  11. package/src/builder/nodes/node-child-helpers.tsx +273 -273
  12. package/src/builder/nodes/node-parent.tsx +187 -187
  13. package/src/builder/nodes/node-types/array-node.tsx +134 -134
  14. package/src/builder/nodes/node-types/date-node.tsx +60 -60
  15. package/src/builder/nodes/node-types/file-node.tsx +67 -67
  16. package/src/builder/nodes/node-types/integer-node.tsx +60 -60
  17. package/src/builder/nodes/node-types/object-node.tsx +67 -67
  18. package/src/builder/nodes/node-types/text-node.tsx +66 -66
  19. package/src/fields/ArrayField.tsx +875 -875
  20. package/src/fields/BooleanField.tsx +110 -110
  21. package/src/fields/MultiSchemaField.tsx +236 -236
  22. package/src/fields/NullField.tsx +22 -22
  23. package/src/fields/NumberField.tsx +87 -87
  24. package/src/fields/ObjectField.tsx +338 -338
  25. package/src/fields/SchemaField.tsx +402 -402
  26. package/src/fields/StringField.tsx +67 -67
  27. package/src/fields/index.ts +24 -24
  28. package/src/index.tsx +26 -26
  29. package/src/interfaces/MessagesProps.interface.ts +5 -5
  30. package/src/interfaces/Option.interface.ts +4 -4
  31. package/src/styles/select.styles.ts +28 -28
  32. package/src/templates/ArrayFieldDescriptionTemplate.tsx +42 -42
  33. package/src/templates/ArrayFieldItemTemplate.tsx +78 -78
  34. package/src/templates/ArrayFieldTemplate.tsx +90 -90
  35. package/src/templates/ArrayFieldTitleTemplate.tsx +44 -44
  36. package/src/templates/BaseInputTemplate.tsx +94 -94
  37. package/src/templates/ButtonTemplates/AddButton.tsx +29 -29
  38. package/src/templates/ButtonTemplates/IconButton.tsx +49 -49
  39. package/src/templates/ButtonTemplates/SubmitButton.tsx +29 -29
  40. package/src/templates/ButtonTemplates/index.ts +16 -16
  41. package/src/templates/DescriptionField.tsx +29 -29
  42. package/src/templates/ErrorList.tsx +25 -25
  43. package/src/templates/FieldTemplate/FieldTemplate.tsx +39 -39
  44. package/src/templates/FieldTemplate/Label.tsx +29 -29
  45. package/src/templates/FieldTemplate/WrapIfAdditional.tsx +85 -85
  46. package/src/templates/FieldTemplate/index.ts +3 -3
  47. package/src/templates/ObjectFieldTemplate.tsx +79 -79
  48. package/src/templates/TitleField.tsx +20 -20
  49. package/src/templates/UnsupportedField.tsx +29 -29
  50. package/src/templates/index.ts +32 -32
  51. package/src/types/Message.type.ts +6 -6
  52. package/src/types/RawMessage.type.ts +15 -15
  53. package/src/types/form-builder.ts +135 -135
  54. package/src/types/utils.type.ts +1 -1
  55. package/src/utils/form-builder.ts +424 -424
  56. package/src/utils/processSelectValue.ts +50 -50
  57. package/src/widgets/AltDateTimeWidget.tsx +17 -17
  58. package/src/widgets/AltDateWidget.tsx +216 -216
  59. package/src/widgets/CheckboxWidget.tsx +80 -80
  60. package/src/widgets/CheckboxesWidget.tsx +74 -74
  61. package/src/widgets/ColorWidget.tsx +26 -26
  62. package/src/widgets/DateTimeWidget.tsx +28 -28
  63. package/src/widgets/DateWidget.tsx +36 -36
  64. package/src/widgets/EmailWidget.tsx +19 -19
  65. package/src/widgets/FileWidget.tsx +144 -144
  66. package/src/widgets/HiddenWidget.tsx +22 -22
  67. package/src/widgets/PasswordWidget.tsx +20 -20
  68. package/src/widgets/RadioWidget.tsx +87 -87
  69. package/src/widgets/RangeWidget.tsx +24 -24
  70. package/src/widgets/SelectWidget.tsx +99 -99
  71. package/src/widgets/TextWidget.tsx +19 -19
  72. package/src/widgets/TextareaWidget.tsx +64 -64
  73. package/src/widgets/URLWidget.tsx +19 -19
  74. package/src/widgets/UpDownWidget.tsx +20 -20
  75. package/src/widgets/index.ts +43 -43
  76. package/tsconfig.json +24 -24
  77. package/tsconfig.node.json +10 -10
  78. package/vite.config.ts +25 -25
@@ -1,236 +1,236 @@
1
- import React, { Component } from "react";
2
- import type { FieldProps, RJSFSchema, GenericObjectType } from "@rjsf/utils";
3
- import { getUiOptions, getWidget, guessType, deepEquals } from "@rjsf/utils";
4
- import unset from "lodash/unset";
5
-
6
- /** Type used for the state of the `AnyOfField` component */
7
- type AnyOfFieldState = {
8
- /** The currently selected option */
9
- selectedOption: number;
10
- };
11
-
12
- /** The `AnyOfField` component is used to render a field in the schema that is an `anyOf`, `allOf` or `oneOf`. It tracks
13
- * the currently selected option and cleans up any irrelevant data in `formData`.
14
- *
15
- * @param props - The `FieldProps` for this template
16
- */
17
- class AnyOfField<T = any, F extends GenericObjectType = any> extends Component<
18
- FieldProps<T, F>
19
- // AnyOfFieldState
20
- > {
21
- /** Constructs an `AnyOfField` with the given `props` to initialize the initially selected option in state
22
- *
23
- * @param props - The `FieldProps` for this template
24
- */
25
- constructor(props: FieldProps<T, F>) {
26
- super(props);
27
-
28
- const { formData, options } = this.props;
29
-
30
- this.state = {
31
- selectedOption: this.getMatchingOption(
32
- 0,
33
- formData as unknown as T,
34
- options
35
- ),
36
- };
37
- }
38
-
39
- /** React lifecycle methos that is called when the props and/or state for this component is updated. It recomputes the
40
- * currently selected option based on the overall `formData`
41
- *
42
- * @param prevProps - The previous `FieldProps` for this template
43
- * @param prevState - The previous `AnyOfFieldState` for this template
44
- */
45
- componentDidUpdate(
46
- prevProps: Readonly<FieldProps<T, F>>,
47
- prevState: Readonly<AnyOfFieldState>
48
- ) {
49
- const { formData, options, idSchema } = this.props;
50
- // @ts-ignore
51
- const { selectedOption } = this.state;
52
- if (
53
- !deepEquals(formData, prevProps.formData) &&
54
- idSchema.$id === prevProps.idSchema.$id
55
- ) {
56
- const matchingOption = this.getMatchingOption(
57
- selectedOption,
58
- // @ts-ignore
59
- formData,
60
- options
61
- );
62
-
63
- if (!prevState || matchingOption === selectedOption) {
64
- return;
65
- }
66
-
67
- this.setState({
68
- selectedOption: matchingOption,
69
- });
70
- }
71
- }
72
-
73
- /** Determines the best matching option for the given `formData` and `options`.
74
- *
75
- * @param formData - The new formData
76
- * @param options - The list of options to choose from
77
- * @return - The index of the `option` that best matches the `formData`
78
- */
79
- getMatchingOption(
80
- selectedOption: number,
81
- formData: T,
82
- options: RJSFSchema[]
83
- ) {
84
- const { schemaUtils } = this.props.registry;
85
- // @ts-ignore
86
- const option = schemaUtils.getMatchingOption(formData, options);
87
- if (option !== 0) {
88
- return option;
89
- }
90
- // If the form data matches none of the options, use the currently selected
91
- // option, assuming it's available; otherwise use the first option
92
- return selectedOption || 0;
93
- }
94
-
95
- /** Callback handler to remember what the currently selected option is. In addition to that the `formData` is updated
96
- * to remove properties that are not part of the newly selected option schema, and then the updated data is passed to
97
- * the `onChange` handler.
98
- *
99
- * @param option -
100
- */
101
- onOptionChange = (option: any) => {
102
- const selectedOption = parseInt(option, 10);
103
- const { formData, onChange, options, registry } = this.props;
104
- const { schemaUtils } = registry;
105
- const newOption = schemaUtils.retrieveSchema(
106
- options[selectedOption],
107
- formData
108
- );
109
-
110
- // If the new option is of type object and the current data is an object,
111
- // discard properties added using the old option.
112
- let newFormData: T | undefined = undefined;
113
- if (
114
- guessType(formData) === "object" &&
115
- (newOption.type === "object" || newOption.properties)
116
- ) {
117
- newFormData = Object.assign({}, formData);
118
-
119
- const optionsToDiscard = options.slice();
120
- optionsToDiscard.splice(selectedOption, 1);
121
-
122
- // Discard any data added using other options
123
- for (const option of optionsToDiscard) {
124
- if (option.properties) {
125
- for (const key in option.properties) {
126
- // @ts-ignore
127
- if (key in newFormData) {
128
- unset(newFormData, key);
129
- }
130
- }
131
- }
132
- }
133
- }
134
- // Call getDefaultFormState to make sure defaults are populated on change.
135
- onChange(
136
- schemaUtils.getDefaultFormState(options[selectedOption], newFormData) as T
137
- );
138
-
139
- this.setState({
140
- selectedOption: parseInt(option, 10),
141
- });
142
- };
143
-
144
- /** Renders the `AnyOfField` selector along with a `SchemaField` for the value of the `formData`
145
- */
146
- render() {
147
- const {
148
- name,
149
- baseType,
150
- disabled = false,
151
- readonly = false,
152
- hideError = false,
153
- errorSchema = {},
154
- formData,
155
- formContext,
156
- idPrefix,
157
- idSeparator,
158
- idSchema,
159
- onBlur,
160
- onChange,
161
- onFocus,
162
- options,
163
- registry,
164
- uiSchema,
165
- schema,
166
- } = this.props;
167
-
168
- const { widgets, fields } = registry;
169
- const { SchemaField: _SchemaField } = fields;
170
- // @ts-ignore
171
- const { selectedOption } = this.state;
172
- const { widget = "select", ...uiOptions } = getUiOptions<T, F>(uiSchema);
173
- const Widget = getWidget<T, F>({ type: "number" }, widget, widgets);
174
-
175
- const option = options[selectedOption] || null;
176
- let optionSchema;
177
-
178
- if (option) {
179
- // If the subschema doesn't declare a type, infer the type from the
180
- // parent schema
181
- optionSchema = option.type
182
- ? option
183
- : Object.assign({}, option, { type: baseType });
184
- }
185
-
186
- const enumOptions = options.map((option: RJSFSchema, index: number) => ({
187
- label: option.title || `Option ${index + 1}`,
188
- value: index,
189
- }));
190
-
191
- return (
192
- <div className="panel panel-default panel-body">
193
- <div className="form-group">
194
- <Widget
195
- id={`${idSchema.$id}${
196
- schema.oneOf ? "__oneof_select" : "__anyof_select"
197
- }`}
198
- // @ts-ignore
199
- schema={{ type: "number", default: 0 }}
200
- onChange={this.onOptionChange}
201
- onBlur={onBlur}
202
- onFocus={onFocus}
203
- value={selectedOption}
204
- options={{ enumOptions }}
205
- registry={registry}
206
- formContext={formContext}
207
- {...uiOptions}
208
- label=""
209
- />
210
- </div>
211
- {option !== null && (
212
- <_SchemaField
213
- name={name}
214
- schema={optionSchema}
215
- uiSchema={uiSchema}
216
- errorSchema={errorSchema}
217
- idSchema={idSchema}
218
- idPrefix={idPrefix}
219
- idSeparator={idSeparator}
220
- formData={formData}
221
- formContext={formContext}
222
- onChange={onChange}
223
- onBlur={onBlur}
224
- onFocus={onFocus}
225
- registry={registry}
226
- disabled={disabled}
227
- readonly={readonly}
228
- hideError={hideError}
229
- />
230
- )}
231
- </div>
232
- );
233
- }
234
- }
235
-
236
- export default AnyOfField;
1
+ import React, { Component } from "react";
2
+ import type { FieldProps, RJSFSchema, GenericObjectType } from "@rjsf/utils";
3
+ import { getUiOptions, getWidget, guessType, deepEquals } from "@rjsf/utils";
4
+ import unset from "lodash/unset";
5
+
6
+ /** Type used for the state of the `AnyOfField` component */
7
+ type AnyOfFieldState = {
8
+ /** The currently selected option */
9
+ selectedOption: number;
10
+ };
11
+
12
+ /** The `AnyOfField` component is used to render a field in the schema that is an `anyOf`, `allOf` or `oneOf`. It tracks
13
+ * the currently selected option and cleans up any irrelevant data in `formData`.
14
+ *
15
+ * @param props - The `FieldProps` for this template
16
+ */
17
+ class AnyOfField<T = any, F extends GenericObjectType = any> extends Component<
18
+ FieldProps<T, F>
19
+ // AnyOfFieldState
20
+ > {
21
+ /** Constructs an `AnyOfField` with the given `props` to initialize the initially selected option in state
22
+ *
23
+ * @param props - The `FieldProps` for this template
24
+ */
25
+ constructor(props: FieldProps<T, F>) {
26
+ super(props);
27
+
28
+ const { formData, options } = this.props;
29
+
30
+ this.state = {
31
+ selectedOption: this.getMatchingOption(
32
+ 0,
33
+ formData as unknown as T,
34
+ options
35
+ ),
36
+ };
37
+ }
38
+
39
+ /** React lifecycle methos that is called when the props and/or state for this component is updated. It recomputes the
40
+ * currently selected option based on the overall `formData`
41
+ *
42
+ * @param prevProps - The previous `FieldProps` for this template
43
+ * @param prevState - The previous `AnyOfFieldState` for this template
44
+ */
45
+ componentDidUpdate(
46
+ prevProps: Readonly<FieldProps<T, F>>,
47
+ prevState: Readonly<AnyOfFieldState>
48
+ ) {
49
+ const { formData, options, idSchema } = this.props;
50
+ // @ts-ignore
51
+ const { selectedOption } = this.state;
52
+ if (
53
+ !deepEquals(formData, prevProps.formData) &&
54
+ idSchema.$id === prevProps.idSchema.$id
55
+ ) {
56
+ const matchingOption = this.getMatchingOption(
57
+ selectedOption,
58
+ // @ts-ignore
59
+ formData,
60
+ options
61
+ );
62
+
63
+ if (!prevState || matchingOption === selectedOption) {
64
+ return;
65
+ }
66
+
67
+ this.setState({
68
+ selectedOption: matchingOption,
69
+ });
70
+ }
71
+ }
72
+
73
+ /** Determines the best matching option for the given `formData` and `options`.
74
+ *
75
+ * @param formData - The new formData
76
+ * @param options - The list of options to choose from
77
+ * @return - The index of the `option` that best matches the `formData`
78
+ */
79
+ getMatchingOption(
80
+ selectedOption: number,
81
+ formData: T,
82
+ options: RJSFSchema[]
83
+ ) {
84
+ const { schemaUtils } = this.props.registry;
85
+ // @ts-ignore
86
+ const option = schemaUtils.getMatchingOption(formData, options);
87
+ if (option !== 0) {
88
+ return option;
89
+ }
90
+ // If the form data matches none of the options, use the currently selected
91
+ // option, assuming it's available; otherwise use the first option
92
+ return selectedOption || 0;
93
+ }
94
+
95
+ /** Callback handler to remember what the currently selected option is. In addition to that the `formData` is updated
96
+ * to remove properties that are not part of the newly selected option schema, and then the updated data is passed to
97
+ * the `onChange` handler.
98
+ *
99
+ * @param option -
100
+ */
101
+ onOptionChange = (option: any) => {
102
+ const selectedOption = parseInt(option, 10);
103
+ const { formData, onChange, options, registry } = this.props;
104
+ const { schemaUtils } = registry;
105
+ const newOption = schemaUtils.retrieveSchema(
106
+ options[selectedOption],
107
+ formData
108
+ );
109
+
110
+ // If the new option is of type object and the current data is an object,
111
+ // discard properties added using the old option.
112
+ let newFormData: T | undefined = undefined;
113
+ if (
114
+ guessType(formData) === "object" &&
115
+ (newOption.type === "object" || newOption.properties)
116
+ ) {
117
+ newFormData = Object.assign({}, formData);
118
+
119
+ const optionsToDiscard = options.slice();
120
+ optionsToDiscard.splice(selectedOption, 1);
121
+
122
+ // Discard any data added using other options
123
+ for (const option of optionsToDiscard) {
124
+ if (option.properties) {
125
+ for (const key in option.properties) {
126
+ // @ts-ignore
127
+ if (key in newFormData) {
128
+ unset(newFormData, key);
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ // Call getDefaultFormState to make sure defaults are populated on change.
135
+ onChange(
136
+ schemaUtils.getDefaultFormState(options[selectedOption], newFormData) as T
137
+ );
138
+
139
+ this.setState({
140
+ selectedOption: parseInt(option, 10),
141
+ });
142
+ };
143
+
144
+ /** Renders the `AnyOfField` selector along with a `SchemaField` for the value of the `formData`
145
+ */
146
+ render() {
147
+ const {
148
+ name,
149
+ baseType,
150
+ disabled = false,
151
+ readonly = false,
152
+ hideError = false,
153
+ errorSchema = {},
154
+ formData,
155
+ formContext,
156
+ idPrefix,
157
+ idSeparator,
158
+ idSchema,
159
+ onBlur,
160
+ onChange,
161
+ onFocus,
162
+ options,
163
+ registry,
164
+ uiSchema,
165
+ schema,
166
+ } = this.props;
167
+
168
+ const { widgets, fields } = registry;
169
+ const { SchemaField: _SchemaField } = fields;
170
+ // @ts-ignore
171
+ const { selectedOption } = this.state;
172
+ const { widget = "select", ...uiOptions } = getUiOptions<T, F>(uiSchema);
173
+ const Widget = getWidget<T, F>({ type: "number" }, widget, widgets);
174
+
175
+ const option = options[selectedOption] || null;
176
+ let optionSchema;
177
+
178
+ if (option) {
179
+ // If the subschema doesn't declare a type, infer the type from the
180
+ // parent schema
181
+ optionSchema = option.type
182
+ ? option
183
+ : Object.assign({}, option, { type: baseType });
184
+ }
185
+
186
+ const enumOptions = options.map((option: RJSFSchema, index: number) => ({
187
+ label: option.title || `Option ${index + 1}`,
188
+ value: index,
189
+ }));
190
+
191
+ return (
192
+ <div className="panel panel-default panel-body">
193
+ <div className="form-group">
194
+ <Widget
195
+ id={`${idSchema.$id}${
196
+ schema.oneOf ? "__oneof_select" : "__anyof_select"
197
+ }`}
198
+ // @ts-ignore
199
+ schema={{ type: "number", default: 0 }}
200
+ onChange={this.onOptionChange}
201
+ onBlur={onBlur}
202
+ onFocus={onFocus}
203
+ value={selectedOption}
204
+ options={{ enumOptions }}
205
+ registry={registry}
206
+ formContext={formContext}
207
+ {...uiOptions}
208
+ label=""
209
+ />
210
+ </div>
211
+ {option !== null && (
212
+ <_SchemaField
213
+ name={name}
214
+ schema={optionSchema}
215
+ uiSchema={uiSchema}
216
+ errorSchema={errorSchema}
217
+ idSchema={idSchema}
218
+ idPrefix={idPrefix}
219
+ idSeparator={idSeparator}
220
+ formData={formData}
221
+ formContext={formContext}
222
+ onChange={onChange}
223
+ onBlur={onBlur}
224
+ onFocus={onFocus}
225
+ registry={registry}
226
+ disabled={disabled}
227
+ readonly={readonly}
228
+ hideError={hideError}
229
+ />
230
+ )}
231
+ </div>
232
+ );
233
+ }
234
+ }
235
+
236
+ export default AnyOfField;
@@ -1,22 +1,22 @@
1
- import { useEffect } from "react";
2
- import type { FieldProps, GenericObjectType } from "@rjsf/utils";
3
-
4
- /** The `NullField` component is used to render a field in the schema is null. It also ensures that the `formData` is
5
- * also set to null if it has no value.
6
- *
7
- * @param props - The `FieldProps` for this template
8
- */
9
- function NullField<T = any, F extends GenericObjectType = any>(
10
- props: FieldProps<T, F>
11
- ) {
12
- const { formData, onChange } = props;
13
- useEffect(() => {
14
- if (formData === undefined) {
15
- onChange(null as unknown as T);
16
- }
17
- }, [formData, onChange]);
18
-
19
- return null;
20
- }
21
-
22
- export default NullField;
1
+ import { useEffect } from "react";
2
+ import type { FieldProps, GenericObjectType } from "@rjsf/utils";
3
+
4
+ /** The `NullField` component is used to render a field in the schema is null. It also ensures that the `formData` is
5
+ * also set to null if it has no value.
6
+ *
7
+ * @param props - The `FieldProps` for this template
8
+ */
9
+ function NullField<T = any, F extends GenericObjectType = any>(
10
+ props: FieldProps<T, F>
11
+ ) {
12
+ const { formData, onChange } = props;
13
+ useEffect(() => {
14
+ if (formData === undefined) {
15
+ onChange(null as unknown as T);
16
+ }
17
+ }, [formData, onChange]);
18
+
19
+ return null;
20
+ }
21
+
22
+ export default NullField;