@springmicro/forms 0.1.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.
- package/.eslintrc.cjs +18 -0
- package/README.md +11 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +24760 -0
- package/dist/index.umd.cjs +105 -0
- package/package.json +46 -0
- package/src/fields/ArrayField.tsx +875 -0
- package/src/fields/BooleanField.tsx +110 -0
- package/src/fields/MultiSchemaField.tsx +236 -0
- package/src/fields/NullField.tsx +22 -0
- package/src/fields/NumberField.tsx +87 -0
- package/src/fields/ObjectField.tsx +338 -0
- package/src/fields/SchemaField.tsx +402 -0
- package/src/fields/StringField.tsx +67 -0
- package/src/fields/index.ts +24 -0
- package/src/index.tsx +17 -0
- package/src/interfaces/MessagesProps.interface.ts +5 -0
- package/src/interfaces/Option.interface.ts +4 -0
- package/src/styles/select.styles.ts +28 -0
- package/src/templates/ArrayFieldDescriptionTemplate.tsx +42 -0
- package/src/templates/ArrayFieldItemTemplate.tsx +78 -0
- package/src/templates/ArrayFieldTemplate.tsx +90 -0
- package/src/templates/ArrayFieldTitleTemplate.tsx +44 -0
- package/src/templates/BaseInputTemplate.tsx +94 -0
- package/src/templates/ButtonTemplates/AddButton.tsx +29 -0
- package/src/templates/ButtonTemplates/IconButton.tsx +49 -0
- package/src/templates/ButtonTemplates/SubmitButton.tsx +29 -0
- package/src/templates/ButtonTemplates/index.ts +16 -0
- package/src/templates/DescriptionField.tsx +29 -0
- package/src/templates/ErrorList.tsx +25 -0
- package/src/templates/FieldTemplate/FieldTemplate.tsx +39 -0
- package/src/templates/FieldTemplate/Label.tsx +29 -0
- package/src/templates/FieldTemplate/WrapIfAdditional.tsx +85 -0
- package/src/templates/FieldTemplate/index.ts +3 -0
- package/src/templates/ObjectFieldTemplate.tsx +79 -0
- package/src/templates/TitleField.tsx +20 -0
- package/src/templates/UnsupportedField.tsx +29 -0
- package/src/templates/index.ts +32 -0
- package/src/types/Message.type.ts +6 -0
- package/src/types/RawMessage.type.ts +15 -0
- package/src/utils/processSelectValue.ts +50 -0
- package/src/widgets/AltDateTimeWidget.tsx +17 -0
- package/src/widgets/AltDateWidget.tsx +216 -0
- package/src/widgets/CheckboxWidget.tsx +80 -0
- package/src/widgets/CheckboxesWidget.tsx +74 -0
- package/src/widgets/ColorWidget.tsx +26 -0
- package/src/widgets/DateTimeWidget.tsx +28 -0
- package/src/widgets/DateWidget.tsx +36 -0
- package/src/widgets/EmailWidget.tsx +19 -0
- package/src/widgets/FileWidget.tsx +144 -0
- package/src/widgets/HiddenWidget.tsx +22 -0
- package/src/widgets/PasswordWidget.tsx +20 -0
- package/src/widgets/RadioWidget.tsx +87 -0
- package/src/widgets/RangeWidget.tsx +24 -0
- package/src/widgets/SelectWidget.tsx +99 -0
- package/src/widgets/TextWidget.tsx +19 -0
- package/src/widgets/TextareaWidget.tsx +64 -0
- package/src/widgets/URLWidget.tsx +19 -0
- package/src/widgets/UpDownWidget.tsx +20 -0
- package/src/widgets/index.ts +43 -0
- package/tsconfig.json +24 -0
- package/tsconfig.node.json +10 -0
- package/vite.config.ts +25 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type {
|
|
3
|
+
FieldProps,
|
|
4
|
+
FieldTemplateProps,
|
|
5
|
+
IdSchema,
|
|
6
|
+
Registry,
|
|
7
|
+
RJSFSchema,
|
|
8
|
+
UIOptionsType,
|
|
9
|
+
GenericObjectType,
|
|
10
|
+
} from "@rjsf/utils";
|
|
11
|
+
import {
|
|
12
|
+
mergeObjects,
|
|
13
|
+
deepEquals,
|
|
14
|
+
getUiOptions,
|
|
15
|
+
getSchemaType,
|
|
16
|
+
getTemplate,
|
|
17
|
+
ID_KEY,
|
|
18
|
+
} from "@rjsf/utils";
|
|
19
|
+
import isObject from "lodash/isObject";
|
|
20
|
+
import omit from "lodash/omit";
|
|
21
|
+
|
|
22
|
+
/** The map of component type to FieldName */
|
|
23
|
+
const COMPONENT_TYPES: { [key: string]: string } = {
|
|
24
|
+
array: "ArrayField",
|
|
25
|
+
boolean: "BooleanField",
|
|
26
|
+
integer: "NumberField",
|
|
27
|
+
number: "NumberField",
|
|
28
|
+
object: "ObjectField",
|
|
29
|
+
string: "StringField",
|
|
30
|
+
null: "NullField",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** Computes and returns which `Field` implementation to return in order to render the field represented by the
|
|
34
|
+
* `schema`. The `uiOptions` are used to alter what potential `Field` implementation is actually returned. If no
|
|
35
|
+
* appropriate `Field` implementation can be found then a wrapper around `UnsupportedFieldTemplate` is used.
|
|
36
|
+
*
|
|
37
|
+
* @param schema - The schema from which to obtain the type
|
|
38
|
+
* @param uiOptions - The UI Options that may affect the component decision
|
|
39
|
+
* @param idSchema - The id that is passed to the `UnsupportedFieldTemplate`
|
|
40
|
+
* @param registry - The registry from which fields and templates are obtained
|
|
41
|
+
* @returns - The `Field` component that is used to render the actual field data
|
|
42
|
+
*/
|
|
43
|
+
function getFieldComponent<T, F extends GenericObjectType = any>(
|
|
44
|
+
schema: F,
|
|
45
|
+
uiOptions: UIOptionsType<T, F>,
|
|
46
|
+
idSchema: IdSchema<T>,
|
|
47
|
+
registry: Registry<T, F>
|
|
48
|
+
) {
|
|
49
|
+
const field = uiOptions.field;
|
|
50
|
+
const { fields } = registry;
|
|
51
|
+
if (typeof field === "function") {
|
|
52
|
+
return field;
|
|
53
|
+
}
|
|
54
|
+
if (typeof field === "string" && field in fields) {
|
|
55
|
+
return fields[field];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const schemaType = getSchemaType(schema);
|
|
59
|
+
const type: string = Array.isArray(schemaType)
|
|
60
|
+
? schemaType[0]
|
|
61
|
+
: schemaType || "";
|
|
62
|
+
const componentName = COMPONENT_TYPES[type];
|
|
63
|
+
|
|
64
|
+
// If the type is not defined and the schema uses 'anyOf' or 'oneOf', don't
|
|
65
|
+
// render a field and let the MultiSchemaField component handle the form display
|
|
66
|
+
if (!componentName && (schema.anyOf || schema.oneOf)) {
|
|
67
|
+
return () => null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return componentName in fields
|
|
71
|
+
? fields[componentName]
|
|
72
|
+
: () => {
|
|
73
|
+
const UnsupportedFieldTemplate = getTemplate<
|
|
74
|
+
"UnsupportedFieldTemplate",
|
|
75
|
+
T,
|
|
76
|
+
F
|
|
77
|
+
>("UnsupportedFieldTemplate", registry, uiOptions);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<UnsupportedFieldTemplate
|
|
81
|
+
schema={schema}
|
|
82
|
+
idSchema={idSchema}
|
|
83
|
+
reason={`Unknown field type ${schema.type}`}
|
|
84
|
+
registry={registry}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The `Help` component renders any help desired for a field
|
|
91
|
+
*
|
|
92
|
+
* @param props - The id and help information to be rendered
|
|
93
|
+
*/
|
|
94
|
+
function Help(props: { id: string; help?: string | React.ReactElement }) {
|
|
95
|
+
const { id, help } = props;
|
|
96
|
+
if (!help) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
if (typeof help === "string") {
|
|
100
|
+
return (
|
|
101
|
+
<p id={id} className="help-block">
|
|
102
|
+
{help}
|
|
103
|
+
</p>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return (
|
|
107
|
+
<div id={id} className="help-block">
|
|
108
|
+
{help}
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** The `ErrorList` component renders the errors local to the particular field
|
|
114
|
+
*
|
|
115
|
+
* @param props - The list of errors to show
|
|
116
|
+
*/
|
|
117
|
+
function ErrorList(props: { errors?: string[] }) {
|
|
118
|
+
const { errors = [] } = props;
|
|
119
|
+
if (errors.length === 0) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div>
|
|
125
|
+
<ul className="error-detail bs-callout bs-callout-info">
|
|
126
|
+
{errors
|
|
127
|
+
.filter((elem) => !!elem)
|
|
128
|
+
.map((error, index) => {
|
|
129
|
+
return (
|
|
130
|
+
<li className="text-danger" key={index}>
|
|
131
|
+
{error}
|
|
132
|
+
</li>
|
|
133
|
+
);
|
|
134
|
+
})}
|
|
135
|
+
</ul>
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** The `SchemaFieldRender` component is the work-horse of react-jsonschema-form, determining what kind of real field to
|
|
141
|
+
* render based on the `schema`, `uiSchema` and all the other props. It also deals with rendering the `anyOf` and
|
|
142
|
+
* `oneOf` fields.
|
|
143
|
+
*
|
|
144
|
+
* @param props - The `FieldProps` for this component
|
|
145
|
+
*/
|
|
146
|
+
function SchemaFieldRender<T, F extends GenericObjectType = any>(
|
|
147
|
+
props: FieldProps<T, F>
|
|
148
|
+
) {
|
|
149
|
+
const {
|
|
150
|
+
schema: _schema,
|
|
151
|
+
idSchema: _idSchema,
|
|
152
|
+
uiSchema,
|
|
153
|
+
formData,
|
|
154
|
+
errorSchema,
|
|
155
|
+
idPrefix,
|
|
156
|
+
idSeparator,
|
|
157
|
+
name,
|
|
158
|
+
onChange,
|
|
159
|
+
onKeyChange,
|
|
160
|
+
onDropPropertyClick,
|
|
161
|
+
required,
|
|
162
|
+
registry,
|
|
163
|
+
wasPropertyKeyModified = false,
|
|
164
|
+
} = props;
|
|
165
|
+
const { formContext, schemaUtils } = registry;
|
|
166
|
+
const uiOptions = getUiOptions<T, F>(uiSchema);
|
|
167
|
+
const FieldTemplate = getTemplate<"FieldTemplate", T, F>(
|
|
168
|
+
"FieldTemplate",
|
|
169
|
+
registry,
|
|
170
|
+
uiOptions
|
|
171
|
+
);
|
|
172
|
+
const DescriptionFieldTemplate = getTemplate<
|
|
173
|
+
"DescriptionFieldTemplate",
|
|
174
|
+
T,
|
|
175
|
+
F
|
|
176
|
+
>("DescriptionFieldTemplate", registry, uiOptions);
|
|
177
|
+
const schema = schemaUtils.retrieveSchema(_schema, formData);
|
|
178
|
+
const idSchema = mergeObjects(
|
|
179
|
+
schemaUtils.toIdSchema(
|
|
180
|
+
schema,
|
|
181
|
+
_idSchema.$id,
|
|
182
|
+
formData,
|
|
183
|
+
idPrefix,
|
|
184
|
+
idSeparator
|
|
185
|
+
),
|
|
186
|
+
_idSchema
|
|
187
|
+
) as IdSchema<T>;
|
|
188
|
+
// @ts-ignore
|
|
189
|
+
const FieldComponent = getFieldComponent(
|
|
190
|
+
schema,
|
|
191
|
+
uiOptions,
|
|
192
|
+
idSchema,
|
|
193
|
+
registry
|
|
194
|
+
);
|
|
195
|
+
const disabled = Boolean(props.disabled || uiOptions.disabled);
|
|
196
|
+
const readonly = Boolean(
|
|
197
|
+
props.readonly ||
|
|
198
|
+
uiOptions.readonly ||
|
|
199
|
+
props.schema.readOnly ||
|
|
200
|
+
schema.readOnly
|
|
201
|
+
);
|
|
202
|
+
const uiSchemaHideError = uiOptions.hideError;
|
|
203
|
+
// Set hideError to the value provided in the uiSchema, otherwise stick with the prop to propagate to children
|
|
204
|
+
const hideError =
|
|
205
|
+
uiSchemaHideError === undefined
|
|
206
|
+
? props.hideError
|
|
207
|
+
: Boolean(uiSchemaHideError);
|
|
208
|
+
const autofocus = Boolean(props.autofocus || uiOptions.autofocus);
|
|
209
|
+
if (Object.keys(schema).length === 0) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema);
|
|
214
|
+
|
|
215
|
+
const { __errors, ...fieldErrorSchema } = errorSchema || {};
|
|
216
|
+
// See #439: uiSchema: Don't pass consumed class names to child components
|
|
217
|
+
const fieldUiSchema = omit(uiSchema, ["ui:classNames", "classNames"]);
|
|
218
|
+
if ("ui:options" in fieldUiSchema) {
|
|
219
|
+
fieldUiSchema["ui:options"] = omit(fieldUiSchema["ui:options"], [
|
|
220
|
+
"classNames",
|
|
221
|
+
]);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const field = (
|
|
225
|
+
// @ts-ignore
|
|
226
|
+
<FieldComponent
|
|
227
|
+
{...props}
|
|
228
|
+
idSchema={idSchema}
|
|
229
|
+
schema={schema}
|
|
230
|
+
uiSchema={fieldUiSchema}
|
|
231
|
+
disabled={disabled}
|
|
232
|
+
readonly={readonly}
|
|
233
|
+
hideError={hideError}
|
|
234
|
+
autofocus={autofocus}
|
|
235
|
+
errorSchema={fieldErrorSchema}
|
|
236
|
+
formContext={formContext}
|
|
237
|
+
rawErrors={__errors}
|
|
238
|
+
/>
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const id = idSchema[ID_KEY];
|
|
242
|
+
|
|
243
|
+
// If this schema has a title defined, but the user has set a new key/label, retain their input.
|
|
244
|
+
let label;
|
|
245
|
+
if (wasPropertyKeyModified) {
|
|
246
|
+
label = name;
|
|
247
|
+
} else {
|
|
248
|
+
label = uiOptions.title || props.schema.title || schema.title || name;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const description =
|
|
252
|
+
uiOptions.description ||
|
|
253
|
+
props.schema.description ||
|
|
254
|
+
schema.description ||
|
|
255
|
+
"";
|
|
256
|
+
const errors = __errors;
|
|
257
|
+
const help = uiOptions.help;
|
|
258
|
+
const hidden = uiOptions.widget === "hidden";
|
|
259
|
+
|
|
260
|
+
const classNames = ["form-control", "mb-2", "field", `field-${schema.type}`];
|
|
261
|
+
if (!hideError && errors && errors.length > 0) {
|
|
262
|
+
classNames.push("field-error has-error has-danger");
|
|
263
|
+
}
|
|
264
|
+
if (uiSchema?.classNames) {
|
|
265
|
+
if (import.meta.env.NODE_ENV !== "production") {
|
|
266
|
+
console.warn(
|
|
267
|
+
"'uiSchema.classNames' is deprecated and may be removed in a major release; Use 'ui:classNames' instead."
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
classNames.push(uiSchema.classNames);
|
|
271
|
+
}
|
|
272
|
+
if (uiOptions.classNames) {
|
|
273
|
+
classNames.push(uiOptions.classNames);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const fieldProps: Omit<FieldTemplateProps<T, F>, "children"> = {
|
|
277
|
+
description: (
|
|
278
|
+
<DescriptionFieldTemplate
|
|
279
|
+
schema={schema}
|
|
280
|
+
id={`${id}__description`}
|
|
281
|
+
description={description}
|
|
282
|
+
registry={registry}
|
|
283
|
+
/>
|
|
284
|
+
),
|
|
285
|
+
rawDescription: description,
|
|
286
|
+
help: <Help id={`${id}__help`} help={help} />,
|
|
287
|
+
rawHelp: typeof help === "string" ? help : undefined,
|
|
288
|
+
errors: hideError ? undefined : <ErrorList errors={errors} />,
|
|
289
|
+
rawErrors: hideError ? undefined : errors,
|
|
290
|
+
id,
|
|
291
|
+
label,
|
|
292
|
+
hidden,
|
|
293
|
+
onChange,
|
|
294
|
+
onKeyChange,
|
|
295
|
+
onDropPropertyClick,
|
|
296
|
+
required,
|
|
297
|
+
disabled,
|
|
298
|
+
readonly,
|
|
299
|
+
hideError,
|
|
300
|
+
displayLabel,
|
|
301
|
+
classNames: classNames.join(" ").trim(),
|
|
302
|
+
formContext,
|
|
303
|
+
formData,
|
|
304
|
+
schema,
|
|
305
|
+
uiSchema,
|
|
306
|
+
registry,
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const _AnyOfField = registry.fields.AnyOfField;
|
|
310
|
+
const _OneOfField = registry.fields.OneOfField;
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<FieldTemplate {...fieldProps}>
|
|
314
|
+
<>
|
|
315
|
+
{field}
|
|
316
|
+
{/*
|
|
317
|
+
If the schema `anyOf` or 'oneOf' can be rendered as a select control, don't
|
|
318
|
+
render the selection and let `StringField` component handle
|
|
319
|
+
rendering
|
|
320
|
+
*/}
|
|
321
|
+
{schema.anyOf &&
|
|
322
|
+
!uiSchema?.["ui:field"] &&
|
|
323
|
+
!schemaUtils.isSelect(schema) && (
|
|
324
|
+
<_AnyOfField
|
|
325
|
+
name={name}
|
|
326
|
+
disabled={disabled}
|
|
327
|
+
readonly={readonly}
|
|
328
|
+
hideError={hideError}
|
|
329
|
+
errorSchema={errorSchema}
|
|
330
|
+
formData={formData}
|
|
331
|
+
formContext={formContext}
|
|
332
|
+
idPrefix={idPrefix}
|
|
333
|
+
idSchema={idSchema}
|
|
334
|
+
idSeparator={idSeparator}
|
|
335
|
+
onBlur={props.onBlur}
|
|
336
|
+
onChange={props.onChange}
|
|
337
|
+
onFocus={props.onFocus}
|
|
338
|
+
options={schema.anyOf.map((_schema: any) =>
|
|
339
|
+
schemaUtils.retrieveSchema(
|
|
340
|
+
// @ts-ignore
|
|
341
|
+
isObject(_schema) ? _schema : {},
|
|
342
|
+
formData
|
|
343
|
+
)
|
|
344
|
+
)}
|
|
345
|
+
baseType={schema.type}
|
|
346
|
+
registry={registry}
|
|
347
|
+
schema={schema}
|
|
348
|
+
uiSchema={uiSchema}
|
|
349
|
+
/>
|
|
350
|
+
)}
|
|
351
|
+
{schema.oneOf &&
|
|
352
|
+
!uiSchema?.["ui:field"] &&
|
|
353
|
+
!schemaUtils.isSelect(schema) && (
|
|
354
|
+
<_OneOfField
|
|
355
|
+
name={name}
|
|
356
|
+
disabled={disabled}
|
|
357
|
+
readonly={readonly}
|
|
358
|
+
hideError={hideError}
|
|
359
|
+
errorSchema={errorSchema}
|
|
360
|
+
formData={formData}
|
|
361
|
+
formContext={formContext}
|
|
362
|
+
idPrefix={idPrefix}
|
|
363
|
+
idSchema={idSchema}
|
|
364
|
+
idSeparator={idSeparator}
|
|
365
|
+
onBlur={props.onBlur}
|
|
366
|
+
onChange={props.onChange}
|
|
367
|
+
onFocus={props.onFocus}
|
|
368
|
+
options={schema.oneOf.map((_schema: any) =>
|
|
369
|
+
schemaUtils.retrieveSchema(
|
|
370
|
+
// @ts-ignore
|
|
371
|
+
isObject(_schema) ? _schema : {},
|
|
372
|
+
formData
|
|
373
|
+
)
|
|
374
|
+
)}
|
|
375
|
+
baseType={schema.type}
|
|
376
|
+
registry={registry}
|
|
377
|
+
schema={schema}
|
|
378
|
+
uiSchema={uiSchema}
|
|
379
|
+
/>
|
|
380
|
+
)}
|
|
381
|
+
</>
|
|
382
|
+
</FieldTemplate>
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** The `SchemaField` component determines whether it is necessary to rerender the component based on any props changes
|
|
387
|
+
* and if so, calls the `SchemaFieldRender` component with the props.
|
|
388
|
+
*/
|
|
389
|
+
class SchemaField<
|
|
390
|
+
T = any,
|
|
391
|
+
F extends GenericObjectType = any,
|
|
392
|
+
> extends React.Component<FieldProps<T, F>> {
|
|
393
|
+
shouldComponentUpdate(nextProps: Readonly<FieldProps<T, F>>) {
|
|
394
|
+
return !deepEquals(this.props, nextProps);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
render() {
|
|
398
|
+
return <SchemaFieldRender<T, F> {...this.props} />;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export default SchemaField;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { FieldProps, GenericObjectType } from "@rjsf/utils";
|
|
3
|
+
import { getWidget, getUiOptions, optionsList, hasWidget } from "@rjsf/utils";
|
|
4
|
+
|
|
5
|
+
/** The `StringField` component is used to render a schema field that represents a string type
|
|
6
|
+
*
|
|
7
|
+
* @param props - The `FieldProps` for this template
|
|
8
|
+
*/
|
|
9
|
+
function StringField<T = any, F extends GenericObjectType = any>(
|
|
10
|
+
props: FieldProps<T, F>
|
|
11
|
+
) {
|
|
12
|
+
const {
|
|
13
|
+
schema,
|
|
14
|
+
name,
|
|
15
|
+
uiSchema,
|
|
16
|
+
idSchema,
|
|
17
|
+
formData,
|
|
18
|
+
required,
|
|
19
|
+
disabled = false,
|
|
20
|
+
readonly = false,
|
|
21
|
+
autofocus = false,
|
|
22
|
+
onChange,
|
|
23
|
+
onBlur,
|
|
24
|
+
onFocus,
|
|
25
|
+
registry,
|
|
26
|
+
rawErrors,
|
|
27
|
+
} = props;
|
|
28
|
+
const { title, format } = schema;
|
|
29
|
+
const { widgets, formContext, schemaUtils } = registry;
|
|
30
|
+
const enumOptions = schemaUtils.isSelect(schema)
|
|
31
|
+
? optionsList(schema)
|
|
32
|
+
: undefined;
|
|
33
|
+
let defaultWidget = enumOptions ? "select" : "text";
|
|
34
|
+
if (format && hasWidget<T, F>(schema, format, widgets)) {
|
|
35
|
+
defaultWidget = format;
|
|
36
|
+
}
|
|
37
|
+
const {
|
|
38
|
+
widget = defaultWidget,
|
|
39
|
+
placeholder = "",
|
|
40
|
+
...options
|
|
41
|
+
} = getUiOptions<T, F>(uiSchema);
|
|
42
|
+
const Widget = getWidget<T, F>(schema, widget, widgets);
|
|
43
|
+
return (
|
|
44
|
+
<Widget
|
|
45
|
+
name={name}
|
|
46
|
+
options={{ ...options, enumOptions }}
|
|
47
|
+
schema={schema}
|
|
48
|
+
uiSchema={uiSchema}
|
|
49
|
+
id={idSchema && idSchema.$id}
|
|
50
|
+
label={title === undefined ? name : title}
|
|
51
|
+
value={formData}
|
|
52
|
+
onChange={onChange}
|
|
53
|
+
onBlur={onBlur}
|
|
54
|
+
onFocus={onFocus}
|
|
55
|
+
required={required}
|
|
56
|
+
disabled={disabled}
|
|
57
|
+
readonly={readonly}
|
|
58
|
+
formContext={formContext}
|
|
59
|
+
autofocus={autofocus}
|
|
60
|
+
registry={registry}
|
|
61
|
+
placeholder={placeholder}
|
|
62
|
+
rawErrors={rawErrors}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default StringField;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RegistryFieldsType } from "@rjsf/utils";
|
|
2
|
+
|
|
3
|
+
import ArrayField from "./ArrayField";
|
|
4
|
+
import BooleanField from "./BooleanField";
|
|
5
|
+
import MultiSchemaField from "./MultiSchemaField";
|
|
6
|
+
import NumberField from "./NumberField";
|
|
7
|
+
import ObjectField from "./ObjectField";
|
|
8
|
+
import SchemaField from "./SchemaField";
|
|
9
|
+
import StringField from "./StringField";
|
|
10
|
+
import NullField from "./NullField";
|
|
11
|
+
|
|
12
|
+
const fields: RegistryFieldsType = {
|
|
13
|
+
AnyOfField: MultiSchemaField,
|
|
14
|
+
ArrayField,
|
|
15
|
+
BooleanField,
|
|
16
|
+
NumberField,
|
|
17
|
+
ObjectField,
|
|
18
|
+
OneOfField: MultiSchemaField,
|
|
19
|
+
SchemaField,
|
|
20
|
+
StringField,
|
|
21
|
+
NullField,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default fields;
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import widgets from "./widgets";
|
|
2
|
+
import templates from "./templates";
|
|
3
|
+
import fields from "./fields";
|
|
4
|
+
import { ThemeProps, withTheme } from "@rjsf/core";
|
|
5
|
+
import type { IChangeEvent } from "@rjsf/core";
|
|
6
|
+
import type { RJSFSchema } from "@rjsf/utils";
|
|
7
|
+
import validator from "@rjsf/validator-ajv8";
|
|
8
|
+
|
|
9
|
+
const rjsfDaisyUiTheme: ThemeProps = {
|
|
10
|
+
fields,
|
|
11
|
+
templates,
|
|
12
|
+
widgets,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const BaseForm = withTheme(rjsfDaisyUiTheme);
|
|
16
|
+
|
|
17
|
+
export { rjsfDaisyUiTheme, IChangeEvent, RJSFSchema, validator, BaseForm };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { GroupBase, StylesConfig } from "react-select";
|
|
2
|
+
import { Option } from "../interfaces/Option.interface";
|
|
3
|
+
|
|
4
|
+
export const selectStyles: StylesConfig<Option, boolean, GroupBase<Option>> = {
|
|
5
|
+
option: (provided, state) => ({
|
|
6
|
+
...provided,
|
|
7
|
+
}),
|
|
8
|
+
control: (provided) => ({
|
|
9
|
+
...provided,
|
|
10
|
+
borderRadius: "0.5rem",
|
|
11
|
+
height: "3rem",
|
|
12
|
+
}),
|
|
13
|
+
singleValue: (provided, state) => {
|
|
14
|
+
const opacity = state.isDisabled ? 0.5 : 1;
|
|
15
|
+
const transition = "opacity 300ms";
|
|
16
|
+
|
|
17
|
+
return { ...provided, opacity, transition };
|
|
18
|
+
},
|
|
19
|
+
multiValue: (styles, { data }) => ({
|
|
20
|
+
...styles,
|
|
21
|
+
backgroundColor: "#560DF8",
|
|
22
|
+
color: "white",
|
|
23
|
+
}),
|
|
24
|
+
multiValueLabel: (styles, { data }) => ({
|
|
25
|
+
...styles,
|
|
26
|
+
color: "white",
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type {
|
|
3
|
+
ArrayFieldDescriptionProps,
|
|
4
|
+
GenericObjectType,
|
|
5
|
+
UiSchema,
|
|
6
|
+
Registry,
|
|
7
|
+
} from "@rjsf/utils";
|
|
8
|
+
import { getTemplate, getUiOptions } from "@rjsf/utils";
|
|
9
|
+
|
|
10
|
+
/** The `ArrayFieldDescriptionTemplate` component renders a `DescriptionFieldTemplate` with an `id` derived from
|
|
11
|
+
* the `idSchema`.
|
|
12
|
+
*
|
|
13
|
+
* @param props - The `ArrayFieldDescriptionProps` for the component
|
|
14
|
+
*/
|
|
15
|
+
export default function ArrayFieldDescriptionTemplate<
|
|
16
|
+
T = any,
|
|
17
|
+
F extends GenericObjectType = any
|
|
18
|
+
>(props: ArrayFieldDescriptionProps) {
|
|
19
|
+
const { schema, idSchema, description, registry, uiSchema } = props;
|
|
20
|
+
if (!description || !uiSchema) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const options = getUiOptions<T, F>(uiSchema as UiSchema<T, F, any>);
|
|
24
|
+
const DescriptionFieldTemplate = getTemplate<
|
|
25
|
+
"DescriptionFieldTemplate",
|
|
26
|
+
T,
|
|
27
|
+
F
|
|
28
|
+
>(
|
|
29
|
+
"DescriptionFieldTemplate",
|
|
30
|
+
registry as unknown as Registry<T, F, any>,
|
|
31
|
+
options
|
|
32
|
+
);
|
|
33
|
+
const id = `${idSchema.$id}__description`;
|
|
34
|
+
return (
|
|
35
|
+
<DescriptionFieldTemplate
|
|
36
|
+
schema={schema as F}
|
|
37
|
+
id={id}
|
|
38
|
+
description={description}
|
|
39
|
+
registry={registry as unknown as Registry<T, F, any>}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React, { CSSProperties } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
ArrayFieldTemplateItemType,
|
|
4
|
+
GenericObjectType,
|
|
5
|
+
} from "@rjsf/utils";
|
|
6
|
+
|
|
7
|
+
/** The `ArrayFieldItemTemplate` component is the template used to render an items of an array.
|
|
8
|
+
*
|
|
9
|
+
* @param props - The `ArrayFieldTemplateItemType` props for the component
|
|
10
|
+
*/
|
|
11
|
+
export default function ArrayFieldItemTemplate<
|
|
12
|
+
T = any,
|
|
13
|
+
F extends GenericObjectType = any
|
|
14
|
+
>(props: ArrayFieldTemplateItemType<T, F>) {
|
|
15
|
+
const {
|
|
16
|
+
children,
|
|
17
|
+
className,
|
|
18
|
+
disabled,
|
|
19
|
+
hasToolbar,
|
|
20
|
+
hasMoveDown,
|
|
21
|
+
hasMoveUp,
|
|
22
|
+
hasRemove,
|
|
23
|
+
index,
|
|
24
|
+
onDropIndexClick,
|
|
25
|
+
onReorderClick,
|
|
26
|
+
readonly,
|
|
27
|
+
registry,
|
|
28
|
+
} = props;
|
|
29
|
+
const { MoveDownButton, MoveUpButton, RemoveButton } =
|
|
30
|
+
registry.templates.ButtonTemplates;
|
|
31
|
+
const btnStyle: CSSProperties = {
|
|
32
|
+
flex: 1,
|
|
33
|
+
paddingLeft: 6,
|
|
34
|
+
paddingRight: 6,
|
|
35
|
+
fontWeight: "bold",
|
|
36
|
+
};
|
|
37
|
+
return (
|
|
38
|
+
<div className={className}>
|
|
39
|
+
<div className={hasToolbar ? "col-xs-9" : "col-xs-12"}>{children}</div>
|
|
40
|
+
{hasToolbar && (
|
|
41
|
+
<div className="col-xs-3 array-item-toolbox">
|
|
42
|
+
<div
|
|
43
|
+
className="btn-group"
|
|
44
|
+
style={{
|
|
45
|
+
display: "flex",
|
|
46
|
+
justifyContent: "space-around",
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
{(hasMoveUp || hasMoveDown) && (
|
|
50
|
+
<MoveUpButton
|
|
51
|
+
registry={registry}
|
|
52
|
+
style={btnStyle}
|
|
53
|
+
disabled={disabled || readonly || !hasMoveUp}
|
|
54
|
+
onClick={onReorderClick(index, index - 1)}
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
{(hasMoveUp || hasMoveDown) && (
|
|
58
|
+
<MoveDownButton
|
|
59
|
+
registry={registry}
|
|
60
|
+
style={btnStyle}
|
|
61
|
+
disabled={disabled || readonly || !hasMoveDown}
|
|
62
|
+
onClick={onReorderClick(index, index + 1)}
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
65
|
+
{hasRemove && (
|
|
66
|
+
<RemoveButton
|
|
67
|
+
registry={registry}
|
|
68
|
+
style={btnStyle}
|
|
69
|
+
disabled={disabled || readonly}
|
|
70
|
+
onClick={onDropIndexClick(index)}
|
|
71
|
+
/>
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|