@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.
Files changed (63) hide show
  1. package/.eslintrc.cjs +18 -0
  2. package/README.md +11 -0
  3. package/dist/index.d.ts +27 -0
  4. package/dist/index.js +24760 -0
  5. package/dist/index.umd.cjs +105 -0
  6. package/package.json +46 -0
  7. package/src/fields/ArrayField.tsx +875 -0
  8. package/src/fields/BooleanField.tsx +110 -0
  9. package/src/fields/MultiSchemaField.tsx +236 -0
  10. package/src/fields/NullField.tsx +22 -0
  11. package/src/fields/NumberField.tsx +87 -0
  12. package/src/fields/ObjectField.tsx +338 -0
  13. package/src/fields/SchemaField.tsx +402 -0
  14. package/src/fields/StringField.tsx +67 -0
  15. package/src/fields/index.ts +24 -0
  16. package/src/index.tsx +17 -0
  17. package/src/interfaces/MessagesProps.interface.ts +5 -0
  18. package/src/interfaces/Option.interface.ts +4 -0
  19. package/src/styles/select.styles.ts +28 -0
  20. package/src/templates/ArrayFieldDescriptionTemplate.tsx +42 -0
  21. package/src/templates/ArrayFieldItemTemplate.tsx +78 -0
  22. package/src/templates/ArrayFieldTemplate.tsx +90 -0
  23. package/src/templates/ArrayFieldTitleTemplate.tsx +44 -0
  24. package/src/templates/BaseInputTemplate.tsx +94 -0
  25. package/src/templates/ButtonTemplates/AddButton.tsx +29 -0
  26. package/src/templates/ButtonTemplates/IconButton.tsx +49 -0
  27. package/src/templates/ButtonTemplates/SubmitButton.tsx +29 -0
  28. package/src/templates/ButtonTemplates/index.ts +16 -0
  29. package/src/templates/DescriptionField.tsx +29 -0
  30. package/src/templates/ErrorList.tsx +25 -0
  31. package/src/templates/FieldTemplate/FieldTemplate.tsx +39 -0
  32. package/src/templates/FieldTemplate/Label.tsx +29 -0
  33. package/src/templates/FieldTemplate/WrapIfAdditional.tsx +85 -0
  34. package/src/templates/FieldTemplate/index.ts +3 -0
  35. package/src/templates/ObjectFieldTemplate.tsx +79 -0
  36. package/src/templates/TitleField.tsx +20 -0
  37. package/src/templates/UnsupportedField.tsx +29 -0
  38. package/src/templates/index.ts +32 -0
  39. package/src/types/Message.type.ts +6 -0
  40. package/src/types/RawMessage.type.ts +15 -0
  41. package/src/utils/processSelectValue.ts +50 -0
  42. package/src/widgets/AltDateTimeWidget.tsx +17 -0
  43. package/src/widgets/AltDateWidget.tsx +216 -0
  44. package/src/widgets/CheckboxWidget.tsx +80 -0
  45. package/src/widgets/CheckboxesWidget.tsx +74 -0
  46. package/src/widgets/ColorWidget.tsx +26 -0
  47. package/src/widgets/DateTimeWidget.tsx +28 -0
  48. package/src/widgets/DateWidget.tsx +36 -0
  49. package/src/widgets/EmailWidget.tsx +19 -0
  50. package/src/widgets/FileWidget.tsx +144 -0
  51. package/src/widgets/HiddenWidget.tsx +22 -0
  52. package/src/widgets/PasswordWidget.tsx +20 -0
  53. package/src/widgets/RadioWidget.tsx +87 -0
  54. package/src/widgets/RangeWidget.tsx +24 -0
  55. package/src/widgets/SelectWidget.tsx +99 -0
  56. package/src/widgets/TextWidget.tsx +19 -0
  57. package/src/widgets/TextareaWidget.tsx +64 -0
  58. package/src/widgets/URLWidget.tsx +19 -0
  59. package/src/widgets/UpDownWidget.tsx +20 -0
  60. package/src/widgets/index.ts +43 -0
  61. package/tsconfig.json +24 -0
  62. package/tsconfig.node.json +10 -0
  63. package/vite.config.ts +25 -0
@@ -0,0 +1,90 @@
1
+ import React from "react";
2
+ import type {
3
+ ArrayFieldTemplateProps,
4
+ ArrayFieldTemplateItemType,
5
+ GenericObjectType,
6
+ } from "@rjsf/utils";
7
+ import { getTemplate, getUiOptions } from "@rjsf/utils";
8
+
9
+ /** The `ArrayFieldTemplate` component is the template used to render all items in an array.
10
+ *
11
+ * @param props - The `ArrayFieldTemplateItemType` props for the component
12
+ */
13
+ export default function ArrayFieldTemplate<
14
+ T = any,
15
+ F extends GenericObjectType = any
16
+ >(props: ArrayFieldTemplateProps<T, F>) {
17
+ const {
18
+ canAdd,
19
+ className,
20
+ disabled,
21
+ idSchema,
22
+ uiSchema,
23
+ items,
24
+ onAddClick,
25
+ readonly,
26
+ registry,
27
+ required,
28
+ schema,
29
+ title,
30
+ } = props;
31
+ const uiOptions = getUiOptions<T, F>(uiSchema);
32
+ const ArrayFieldDescriptionTemplate = getTemplate<
33
+ "ArrayFieldDescriptionTemplate",
34
+ T,
35
+ F
36
+ >("ArrayFieldDescriptionTemplate", registry, uiOptions);
37
+ const ArrayFieldItemTemplate = getTemplate<"ArrayFieldItemTemplate", T, F>(
38
+ "ArrayFieldItemTemplate",
39
+ registry,
40
+ uiOptions
41
+ );
42
+ const ArrayFieldTitleTemplate = getTemplate<"ArrayFieldTitleTemplate", T, F>(
43
+ "ArrayFieldTitleTemplate",
44
+ registry,
45
+ uiOptions
46
+ );
47
+ // Button templates are not overridden in the uiSchema
48
+ const {
49
+ ButtonTemplates: { AddButton },
50
+ } = registry.templates;
51
+ return (
52
+ <fieldset className={className} id={idSchema.$id}>
53
+ <ArrayFieldTitleTemplate
54
+ schema={schema}
55
+ idSchema={idSchema}
56
+ title={uiOptions.title || title}
57
+ required={required}
58
+ uiSchema={uiSchema}
59
+ registry={registry}
60
+ />
61
+ {(uiOptions.description || schema.description) && (
62
+ <ArrayFieldDescriptionTemplate
63
+ schema={schema}
64
+ idSchema={idSchema}
65
+ description={(uiOptions.description || schema.description)!}
66
+ uiSchema={uiSchema}
67
+ registry={registry}
68
+ />
69
+ )}
70
+ <div className="row array-item-list">
71
+ {items &&
72
+ items.map(
73
+ // @ts-ignore
74
+ ({ key, ...itemProps }: ArrayFieldTemplateItemType) => (
75
+ // @ts-ignore
76
+ <ArrayFieldItemTemplate key={key} {...itemProps} />
77
+ )
78
+ )}
79
+ </div>
80
+ {canAdd && (
81
+ <AddButton
82
+ registry={registry}
83
+ className="array-item-add"
84
+ onClick={onAddClick}
85
+ disabled={disabled || readonly}
86
+ />
87
+ )}
88
+ </fieldset>
89
+ );
90
+ }
@@ -0,0 +1,44 @@
1
+ import React from "react";
2
+ import type {
3
+ ArrayFieldTitleProps,
4
+ TemplatesType,
5
+ GenericObjectType,
6
+ Registry,
7
+ UiSchema,
8
+ } from "@rjsf/utils";
9
+ import { getTemplate, getUiOptions } from "@rjsf/utils";
10
+
11
+ /** The `ArrayFieldTitleTemplate` component renders a `TitleFieldTemplate` with an `id` derived from
12
+ * the `idSchema`.
13
+ *
14
+ * @param props - The `ArrayFieldTitleProps` for the component
15
+ */
16
+ export default function ArrayFieldTitleTemplate<
17
+ T = any,
18
+ F extends GenericObjectType = any
19
+ >(props: ArrayFieldTitleProps) {
20
+ const { schema, idSchema, title, uiSchema, required, registry } = props;
21
+ if (!title) {
22
+ return null;
23
+ }
24
+ const options = getUiOptions<T, F>(
25
+ uiSchema as unknown as UiSchema<T, F, any>
26
+ );
27
+ const TitleFieldTemplate: TemplatesType<T, F>["TitleFieldTemplate"] =
28
+ getTemplate<"TitleFieldTemplate", T, F>(
29
+ "TitleFieldTemplate",
30
+ registry as unknown as Registry<T, F, any>,
31
+ options
32
+ );
33
+ const id = `${idSchema.$id}__title`;
34
+ return (
35
+ <TitleFieldTemplate
36
+ schema={schema as unknown as F}
37
+ id={id}
38
+ title={title}
39
+ required={required}
40
+ uiSchema={uiSchema as unknown as UiSchema<T, F, any>}
41
+ registry={registry as unknown as Registry<T, F, any>}
42
+ />
43
+ );
44
+ }
@@ -0,0 +1,94 @@
1
+ import React, { useCallback } from "react";
2
+ import type { WidgetProps, GenericObjectType } from "@rjsf/utils";
3
+ import { getInputProps } from "@rjsf/utils";
4
+
5
+ /** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
6
+ * It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only.
7
+ * It can be customized/overridden for other themes or individual implementations as needed.
8
+ *
9
+ * @param props - The `WidgetProps` for this template
10
+ */
11
+ export default function BaseInputTemplate<
12
+ T = any,
13
+ F extends GenericObjectType = any
14
+ >(props: WidgetProps<T, F>) {
15
+ const {
16
+ id,
17
+ value,
18
+ readonly,
19
+ disabled,
20
+ autofocus,
21
+ onBlur,
22
+ onFocus,
23
+ onChange,
24
+ options,
25
+ schema,
26
+ uiSchema,
27
+ formContext,
28
+ registry,
29
+ rawErrors,
30
+ type,
31
+ ...rest
32
+ } = props;
33
+
34
+ // Note: since React 15.2.0 we can't forward unknown element attributes, so we
35
+ // exclude the "options" and "schema" ones here.
36
+ if (!id) {
37
+ console.log("No id for", props);
38
+ throw new Error(`no id for props ${JSON.stringify(props)}`);
39
+ }
40
+ const inputProps = { ...rest, ...getInputProps<T, F>(schema, type, options) };
41
+
42
+ let inputValue;
43
+ if (inputProps.type === "number" || inputProps.type === "integer") {
44
+ inputValue = value || value === 0 ? value : "";
45
+ } else {
46
+ inputValue = value == null ? "" : value;
47
+ }
48
+
49
+ const _onChange = useCallback(
50
+ ({ target: { value } }: React.ChangeEvent<HTMLInputElement>) =>
51
+ onChange(value === "" ? options.emptyValue : value),
52
+ [onChange, options]
53
+ );
54
+ const _onBlur = useCallback(
55
+ ({ target: { value } }: React.FocusEvent<HTMLInputElement>) =>
56
+ onBlur(id, value),
57
+ [onBlur, id]
58
+ );
59
+ const _onFocus = useCallback(
60
+ ({ target: { value } }: React.FocusEvent<HTMLInputElement>) =>
61
+ onFocus(id, value),
62
+ [onFocus, id]
63
+ );
64
+
65
+ return (
66
+ <>
67
+ <input
68
+ key={id}
69
+ id={id}
70
+ className="input input-bordered"
71
+ readOnly={readonly}
72
+ disabled={disabled}
73
+ autoFocus={autofocus}
74
+ value={inputValue}
75
+ {...inputProps}
76
+ list={schema.examples ? `examples_${id}` : undefined}
77
+ onChange={_onChange}
78
+ onBlur={_onBlur}
79
+ onFocus={_onFocus}
80
+ />
81
+ {Array.isArray(schema.examples) && (
82
+ <datalist key={`datalist_${id}`} id={`examples_${id}`}>
83
+ {[
84
+ ...new Set(
85
+ schema.examples.concat(schema.default ? [schema.default] : [])
86
+ ),
87
+ ].map((example: any) => (
88
+ <option key={example} value={example} />
89
+ ))}
90
+ </datalist>
91
+ )}
92
+ </>
93
+ );
94
+ }
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { IconButtonProps } from "@rjsf/utils";
3
+
4
+ import IconButton from "./IconButton";
5
+
6
+ /** The `AddButton` renders a button that represent the `Add` action on a form
7
+ */
8
+ export default function AddButton({
9
+ registry,
10
+ className,
11
+ onClick,
12
+ disabled,
13
+ }: IconButtonProps) {
14
+ return (
15
+ <div className="row">
16
+ <p className={`col-xs-3 col-xs-offset-9 text-right ${className}`}>
17
+ <IconButton
18
+ registry={registry}
19
+ iconType="info"
20
+ icon="plus"
21
+ className="btn-add col-xs-12"
22
+ title="Add"
23
+ onClick={onClick}
24
+ disabled={disabled}
25
+ />
26
+ </p>
27
+ </div>
28
+ );
29
+ }
@@ -0,0 +1,49 @@
1
+ import React from "react";
2
+ import { IconButtonProps } from "@rjsf/utils";
3
+
4
+ export default function IconButton(props: IconButtonProps) {
5
+ const { iconType = "default", icon, className, ...otherProps } = props;
6
+ return (
7
+ <button
8
+ type="button"
9
+ className={`btn btn-${iconType} ${className}`}
10
+ {...otherProps}
11
+ >
12
+ <i className={`glyphicon glyphicon-${icon}`} />
13
+ </button>
14
+ );
15
+ }
16
+
17
+ export function MoveDownButton(props: IconButtonProps) {
18
+ return (
19
+ <IconButton
20
+ title="Move down"
21
+ className="array-item-move-down"
22
+ {...props}
23
+ icon="arrow-down"
24
+ />
25
+ );
26
+ }
27
+
28
+ export function MoveUpButton(props: IconButtonProps) {
29
+ return (
30
+ <IconButton
31
+ title="Move up"
32
+ className="array-item-move-up"
33
+ {...props}
34
+ icon="arrow-up"
35
+ />
36
+ );
37
+ }
38
+
39
+ export function RemoveButton(props: IconButtonProps) {
40
+ return (
41
+ <IconButton
42
+ title="Remove"
43
+ className="array-item-remove"
44
+ {...props}
45
+ iconType="danger"
46
+ icon="remove"
47
+ />
48
+ );
49
+ }
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { SubmitButtonProps, GenericObjectType } from "@rjsf/utils";
3
+ import { getSubmitButtonOptions } from "@rjsf/utils";
4
+
5
+ /** The `SubmitButton` renders a button that represent the `Submit` action on a form
6
+ */
7
+ export default function SubmitButton<T, F extends GenericObjectType = any>({
8
+ uiSchema,
9
+ }: SubmitButtonProps<T, F>) {
10
+ const {
11
+ submitText,
12
+ norender,
13
+ props: submitButtonProps = {},
14
+ } = getSubmitButtonOptions(uiSchema);
15
+ if (norender) {
16
+ return null;
17
+ }
18
+ return (
19
+ <div>
20
+ <button
21
+ type="submit"
22
+ {...submitButtonProps}
23
+ className={`btn btn-primary ${submitButtonProps.className}`}
24
+ >
25
+ {submitText}
26
+ </button>
27
+ </div>
28
+ );
29
+ }
@@ -0,0 +1,16 @@
1
+ import { TemplatesType } from "@rjsf/utils";
2
+
3
+ import SubmitButton from "./SubmitButton";
4
+ import AddButton from "./AddButton";
5
+ import { RemoveButton, MoveDownButton, MoveUpButton } from "./IconButton";
6
+
7
+ // @ts-ignore
8
+ const buttonTemplates: TemplatesType["ButtonTemplates"] = {
9
+ SubmitButton,
10
+ AddButton,
11
+ MoveDownButton,
12
+ MoveUpButton,
13
+ RemoveButton,
14
+ };
15
+
16
+ export default buttonTemplates;
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { DescriptionFieldProps, GenericObjectType } from "@rjsf/utils";
3
+
4
+ /** The `DescriptionField` is the template to use to render the description of a field
5
+ *
6
+ * @param props - The `DescriptionFieldProps` for this component
7
+ */
8
+ export default function DescriptionField<
9
+ T = any,
10
+ F extends GenericObjectType = any
11
+ >(props: DescriptionFieldProps<T, F>) {
12
+ const { id, description } = props;
13
+ if (!description) {
14
+ return null;
15
+ }
16
+ if (typeof description === "string") {
17
+ return (
18
+ <p id={id} className="field-description">
19
+ {description}
20
+ </p>
21
+ );
22
+ } else {
23
+ return (
24
+ <div id={id} className="field-description">
25
+ {description}
26
+ </div>
27
+ );
28
+ }
29
+ }
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import { ErrorListProps, RJSFValidationError } from "@rjsf/utils";
3
+
4
+ /** The `ErrorList` component is the template that renders the all the errors associated with the fields in the `Form`
5
+ *
6
+ * @param props - The `ErrorListProps` for this component
7
+ */
8
+ export default function ErrorList<T = any>({ errors }: ErrorListProps<T>) {
9
+ return (
10
+ <div className="panel panel-danger errors">
11
+ <div className="panel-heading">
12
+ <h3 className="panel-title">Errors</h3>
13
+ </div>
14
+ <ul className="list-group">
15
+ {errors.map((error: RJSFValidationError, i: number) => {
16
+ return (
17
+ <li key={i} className="list-group-item text-danger">
18
+ {error.stack}
19
+ </li>
20
+ );
21
+ })}
22
+ </ul>
23
+ </div>
24
+ );
25
+ }
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+ import { FieldTemplateProps, GenericObjectType } from "@rjsf/utils";
3
+
4
+ import Label from "./Label";
5
+ import WrapIfAdditional from "./WrapIfAdditional";
6
+
7
+ /** The `FieldTemplate` component is the template used by `SchemaField` to render any field. It renders the field
8
+ * content, (label, description, children, errors and help) inside of a `WrapIfAdditional` component.
9
+ *
10
+ * @param props - The `FieldTemplateProps` for this component
11
+ */
12
+ export default function FieldTemplate<
13
+ T = any,
14
+ F extends GenericObjectType = any
15
+ >(props: FieldTemplateProps<T, F>) {
16
+ const {
17
+ id,
18
+ label,
19
+ children,
20
+ errors,
21
+ help,
22
+ description,
23
+ hidden,
24
+ required,
25
+ displayLabel,
26
+ } = props;
27
+ if (hidden) {
28
+ return <div className="hidden">{children}</div>;
29
+ }
30
+ return (
31
+ <WrapIfAdditional<T, F> {...props}>
32
+ {displayLabel && <Label label={label} required={required} id={id} />}
33
+ {displayLabel && description ? description : null}
34
+ {children}
35
+ {errors}
36
+ {help}
37
+ </WrapIfAdditional>
38
+ );
39
+ }
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+
3
+ const REQUIRED_FIELD_SYMBOL = "*";
4
+
5
+ export type LabelProps = {
6
+ /** The label for the field */
7
+ label?: string;
8
+ /** A boolean value stating if the field is required */
9
+ required?: boolean;
10
+ /** The id of the input field being labeled */
11
+ id?: string;
12
+ };
13
+
14
+ /** Renders a label for a field
15
+ *
16
+ * @param props - The `LabelProps` for this component
17
+ */
18
+ export default function Label(props: LabelProps) {
19
+ const { label, required, id } = props;
20
+ if (!label) {
21
+ return null;
22
+ }
23
+ return (
24
+ <label className="justify-start gap-1 label" htmlFor={id}>
25
+ <span className="label-text">{label}</span>
26
+ {required && <span className="required">{REQUIRED_FIELD_SYMBOL}</span>}
27
+ </label>
28
+ );
29
+ }
@@ -0,0 +1,85 @@
1
+ import React from "react";
2
+ import { FieldTemplateProps, GenericObjectType } from "@rjsf/utils";
3
+ import { ADDITIONAL_PROPERTY_FLAG } from "@rjsf/utils";
4
+
5
+ import Label from "./Label";
6
+
7
+ /** The properties that are passed to a WrapIfAdditionalTemplate implementation */
8
+ export type WrapIfAdditionalProps<
9
+ T = any,
10
+ F extends GenericObjectType = any
11
+ > = {
12
+ children: React.ReactNode;
13
+ } & Pick<
14
+ FieldTemplateProps<T, F>,
15
+ | "classNames"
16
+ | "disabled"
17
+ | "id"
18
+ | "label"
19
+ | "onDropPropertyClick"
20
+ | "onKeyChange"
21
+ | "readonly"
22
+ | "required"
23
+ | "schema"
24
+ | "registry"
25
+ >;
26
+
27
+ /** The `WrapIfAdditional` component is used by the `FieldTemplate` to rename, or remove properties that are
28
+ * part of an `additionalProperties` part of a schema.
29
+ *
30
+ * @param props - The `WrapIfAdditionalProps` for this component
31
+ */
32
+ export default function WrapIfAdditional<
33
+ T = any,
34
+ F extends GenericObjectType = any
35
+ >(props: WrapIfAdditionalProps<T, F>) {
36
+ const {
37
+ id,
38
+ classNames,
39
+ disabled,
40
+ label,
41
+ onKeyChange,
42
+ onDropPropertyClick,
43
+ readonly,
44
+ required,
45
+ schema,
46
+ children,
47
+ registry,
48
+ } = props;
49
+ const { RemoveButton } = registry.templates.ButtonTemplates;
50
+ const keyLabel = `${label} Key`; // i18n ?
51
+ const additional = ADDITIONAL_PROPERTY_FLAG in schema;
52
+
53
+ if (!additional) {
54
+ return <div className={classNames}>{children}</div>;
55
+ }
56
+
57
+ return (
58
+ <div className={classNames}>
59
+ <div className="row">
60
+ <div className="form-additional">
61
+ <div className="form-control">
62
+ <Label label={keyLabel} required={required} id={`${id}-key`} />
63
+ <input
64
+ className="form-control"
65
+ type="text"
66
+ id={`${id}-key`}
67
+ onBlur={(event) => onKeyChange(event.target.value)}
68
+ defaultValue={label}
69
+ />
70
+ </div>
71
+ </div>
72
+ <div className="form-additional form-control">{children}</div>
73
+ <div className="col-xs-2">
74
+ <RemoveButton
75
+ registry={registry}
76
+ className="array-item-remove btn-block"
77
+ style={{ border: "0" }}
78
+ disabled={disabled || readonly}
79
+ onClick={onDropPropertyClick(label)}
80
+ />
81
+ </div>
82
+ </div>
83
+ </div>
84
+ );
85
+ }
@@ -0,0 +1,3 @@
1
+ import FieldTemplate from "./FieldTemplate";
2
+
3
+ export default FieldTemplate;
@@ -0,0 +1,79 @@
1
+ import React from "react";
2
+ import {
3
+ GenericObjectType,
4
+ ObjectFieldTemplatePropertyType,
5
+ ObjectFieldTemplateProps,
6
+ } from "@rjsf/utils";
7
+ import { canExpand, getTemplate, getUiOptions } from "@rjsf/utils";
8
+
9
+ /** The `ObjectFieldTemplate` is the template to use to render all the inner properties of an object along with the
10
+ * title and description if available. If the object is expandable, then an `AddButton` is also rendered after all
11
+ * the properties.
12
+ *
13
+ * @param props - The `ObjectFieldTemplateProps` for this component
14
+ */
15
+ export default function ObjectFieldTemplate<
16
+ T = any,
17
+ F extends GenericObjectType = any
18
+ >(props: ObjectFieldTemplateProps<T, F>) {
19
+ const {
20
+ description,
21
+ disabled,
22
+ formData,
23
+ idSchema,
24
+ onAddClick,
25
+ properties,
26
+ readonly,
27
+ registry,
28
+ required,
29
+ schema,
30
+ title,
31
+ uiSchema,
32
+ } = props;
33
+ const options = getUiOptions<T, F>(uiSchema);
34
+ const TitleFieldTemplate = getTemplate<"TitleFieldTemplate", T, F>(
35
+ "TitleFieldTemplate",
36
+ registry,
37
+ options
38
+ );
39
+ const DescriptionFieldTemplate = getTemplate<
40
+ "DescriptionFieldTemplate",
41
+ T,
42
+ F
43
+ >("DescriptionFieldTemplate", registry, options);
44
+ // Button templates are not overridden in the uiSchema
45
+ const {
46
+ ButtonTemplates: { AddButton },
47
+ } = registry.templates;
48
+ return (
49
+ <fieldset id={idSchema.$id}>
50
+ {(options.title || title) && (
51
+ <TitleFieldTemplate
52
+ schema={schema}
53
+ id={`${idSchema.$id}__title`}
54
+ title={options.title || title}
55
+ required={required}
56
+ uiSchema={uiSchema}
57
+ registry={registry}
58
+ />
59
+ )}
60
+ {(options.description || description) && (
61
+ <DescriptionFieldTemplate
62
+ schema={schema}
63
+ id={`${idSchema.$id}__description`}
64
+ description={options.description || description!}
65
+ registry={registry}
66
+ />
67
+ )}
68
+ {properties.map((prop: ObjectFieldTemplatePropertyType) => prop.content)}
69
+ {canExpand(schema, uiSchema, formData) && (
70
+ <AddButton
71
+ registry={registry}
72
+ className="object-property-expand"
73
+ onClick={onAddClick(schema)}
74
+ disabled={disabled || readonly}
75
+ />
76
+ )}
77
+ </fieldset>
78
+ );
79
+ }
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import { GenericObjectType, TitleFieldProps } from "@rjsf/utils";
3
+
4
+ const REQUIRED_FIELD_SYMBOL = "*";
5
+
6
+ /** The `TitleField` is the template to use to render the title of a field
7
+ *
8
+ * @param props - The `TitleFieldProps` for this component
9
+ */
10
+ export default function TitleField<T = any, F extends GenericObjectType = any>(
11
+ props: TitleFieldProps<T, F>
12
+ ) {
13
+ const { id, title, required } = props;
14
+ return (
15
+ <legend id={id}>
16
+ {title}
17
+ {required && <span className="required">{REQUIRED_FIELD_SYMBOL}</span>}
18
+ </legend>
19
+ );
20
+ }