@rjsf/core 6.0.0-beta.8 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +2 -0
  2. package/dist/core.umd.js +2042 -1987
  3. package/dist/index.cjs +4909 -0
  4. package/dist/index.cjs.map +7 -0
  5. package/dist/index.esm.js +2509 -2389
  6. package/dist/index.esm.js.map +4 -4
  7. package/lib/components/Form.d.ts +137 -34
  8. package/lib/components/Form.d.ts.map +1 -1
  9. package/lib/components/Form.js +318 -173
  10. package/lib/components/fields/ArrayField.d.ts +2 -187
  11. package/lib/components/fields/ArrayField.d.ts.map +1 -1
  12. package/lib/components/fields/ArrayField.js +526 -492
  13. package/lib/components/fields/BooleanField.d.ts.map +1 -1
  14. package/lib/components/fields/BooleanField.js +8 -3
  15. package/lib/components/fields/FallbackField.d.ts +7 -0
  16. package/lib/components/fields/FallbackField.d.ts.map +1 -0
  17. package/lib/components/fields/FallbackField.js +72 -0
  18. package/lib/components/fields/LayoutGridField.d.ts +109 -186
  19. package/lib/components/fields/LayoutGridField.d.ts.map +1 -1
  20. package/lib/components/fields/LayoutGridField.js +426 -426
  21. package/lib/components/fields/LayoutHeaderField.d.ts +1 -1
  22. package/lib/components/fields/LayoutHeaderField.js +3 -3
  23. package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -1
  24. package/lib/components/fields/LayoutMultiSchemaField.js +6 -6
  25. package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
  26. package/lib/components/fields/MultiSchemaField.js +16 -10
  27. package/lib/components/fields/NullField.js +3 -3
  28. package/lib/components/fields/NumberField.d.ts.map +1 -1
  29. package/lib/components/fields/NumberField.js +3 -3
  30. package/lib/components/fields/ObjectField.d.ts +2 -68
  31. package/lib/components/fields/ObjectField.d.ts.map +1 -1
  32. package/lib/components/fields/ObjectField.js +163 -163
  33. package/lib/components/fields/OptionalDataControlsField.d.ts +8 -0
  34. package/lib/components/fields/OptionalDataControlsField.d.ts.map +1 -0
  35. package/lib/components/fields/OptionalDataControlsField.js +43 -0
  36. package/lib/components/fields/SchemaField.d.ts.map +1 -1
  37. package/lib/components/fields/SchemaField.js +52 -30
  38. package/lib/components/fields/StringField.d.ts.map +1 -1
  39. package/lib/components/fields/StringField.js +8 -3
  40. package/lib/components/fields/index.d.ts.map +1 -1
  41. package/lib/components/fields/index.js +4 -0
  42. package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts +1 -1
  43. package/lib/components/templates/ArrayFieldDescriptionTemplate.js +3 -3
  44. package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts +3 -3
  45. package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts.map +1 -1
  46. package/lib/components/templates/ArrayFieldItemButtonsTemplate.js +3 -8
  47. package/lib/components/templates/ArrayFieldItemTemplate.d.ts +3 -3
  48. package/lib/components/templates/ArrayFieldItemTemplate.d.ts.map +1 -1
  49. package/lib/components/templates/ArrayFieldItemTemplate.js +1 -1
  50. package/lib/components/templates/ArrayFieldTemplate.d.ts +1 -1
  51. package/lib/components/templates/ArrayFieldTemplate.d.ts.map +1 -1
  52. package/lib/components/templates/ArrayFieldTemplate.js +4 -5
  53. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +1 -1
  54. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts.map +1 -1
  55. package/lib/components/templates/ArrayFieldTitleTemplate.js +3 -3
  56. package/lib/components/templates/BaseInputTemplate.js +2 -2
  57. package/lib/components/templates/ButtonTemplates/AddButton.d.ts +1 -1
  58. package/lib/components/templates/ButtonTemplates/AddButton.d.ts.map +1 -1
  59. package/lib/components/templates/ButtonTemplates/AddButton.js +2 -2
  60. package/lib/components/templates/FallbackFieldTemplate.d.ts +7 -0
  61. package/lib/components/templates/FallbackFieldTemplate.d.ts.map +1 -0
  62. package/lib/components/templates/FallbackFieldTemplate.js +12 -0
  63. package/lib/components/templates/FieldErrorTemplate.js +2 -2
  64. package/lib/components/templates/FieldHelpTemplate.js +2 -2
  65. package/lib/components/templates/MultiSchemaFieldTemplate.d.ts +8 -0
  66. package/lib/components/templates/MultiSchemaFieldTemplate.d.ts.map +1 -0
  67. package/lib/components/templates/MultiSchemaFieldTemplate.js +10 -0
  68. package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -1
  69. package/lib/components/templates/ObjectFieldTemplate.js +3 -2
  70. package/lib/components/templates/OptionalDataControlsTemplate.d.ts +11 -0
  71. package/lib/components/templates/OptionalDataControlsTemplate.d.ts.map +1 -0
  72. package/lib/components/templates/OptionalDataControlsTemplate.js +20 -0
  73. package/lib/components/templates/TitleField.d.ts.map +1 -1
  74. package/lib/components/templates/TitleField.js +2 -2
  75. package/lib/components/templates/UnsupportedField.js +3 -3
  76. package/lib/components/templates/WrapIfAdditionalTemplate.js +2 -2
  77. package/lib/components/templates/index.d.ts.map +1 -1
  78. package/lib/components/templates/index.js +6 -0
  79. package/lib/components/widgets/AltDateWidget.d.ts +1 -1
  80. package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
  81. package/lib/components/widgets/AltDateWidget.js +5 -46
  82. package/lib/components/widgets/CheckboxWidget.d.ts +1 -1
  83. package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
  84. package/lib/components/widgets/CheckboxWidget.js +2 -2
  85. package/lib/components/widgets/CheckboxesWidget.d.ts +1 -1
  86. package/lib/components/widgets/CheckboxesWidget.d.ts.map +1 -1
  87. package/lib/components/widgets/CheckboxesWidget.js +4 -4
  88. package/lib/components/widgets/FileWidget.d.ts.map +1 -1
  89. package/lib/components/widgets/FileWidget.js +7 -87
  90. package/lib/components/widgets/HiddenWidget.d.ts +1 -1
  91. package/lib/components/widgets/HiddenWidget.d.ts.map +1 -1
  92. package/lib/components/widgets/HiddenWidget.js +2 -2
  93. package/lib/components/widgets/RadioWidget.d.ts +1 -1
  94. package/lib/components/widgets/RadioWidget.d.ts.map +1 -1
  95. package/lib/components/widgets/RadioWidget.js +2 -2
  96. package/lib/components/widgets/RatingWidget.d.ts +1 -1
  97. package/lib/components/widgets/RatingWidget.d.ts.map +1 -1
  98. package/lib/components/widgets/RatingWidget.js +2 -2
  99. package/lib/components/widgets/SelectWidget.d.ts +1 -1
  100. package/lib/components/widgets/SelectWidget.d.ts.map +1 -1
  101. package/lib/components/widgets/SelectWidget.js +2 -2
  102. package/lib/components/widgets/TextareaWidget.d.ts +1 -1
  103. package/lib/components/widgets/TextareaWidget.d.ts.map +1 -1
  104. package/lib/components/widgets/TextareaWidget.js +2 -2
  105. package/lib/getDefaultRegistry.d.ts.map +1 -1
  106. package/lib/getDefaultRegistry.js +6 -1
  107. package/lib/getTestRegistry.d.ts +5 -0
  108. package/lib/getTestRegistry.d.ts.map +1 -0
  109. package/lib/getTestRegistry.js +23 -0
  110. package/lib/index.d.ts +2 -1
  111. package/lib/index.d.ts.map +1 -1
  112. package/lib/index.js +2 -1
  113. package/lib/tsconfig.tsbuildinfo +1 -1
  114. package/package.json +35 -20
  115. package/src/components/Form.tsx +468 -206
  116. package/src/components/fields/ArrayField.tsx +871 -723
  117. package/src/components/fields/BooleanField.tsx +14 -5
  118. package/src/components/fields/FallbackField.tsx +157 -0
  119. package/src/components/fields/LayoutGridField.tsx +626 -603
  120. package/src/components/fields/LayoutHeaderField.tsx +3 -3
  121. package/src/components/fields/LayoutMultiSchemaField.tsx +9 -10
  122. package/src/components/fields/MultiSchemaField.tsx +57 -36
  123. package/src/components/fields/NullField.tsx +3 -3
  124. package/src/components/fields/NumberField.tsx +11 -3
  125. package/src/components/fields/ObjectField.tsx +308 -239
  126. package/src/components/fields/OptionalDataControlsField.tsx +84 -0
  127. package/src/components/fields/SchemaField.tsx +75 -94
  128. package/src/components/fields/StringField.tsx +14 -5
  129. package/src/components/fields/index.ts +4 -0
  130. package/src/components/templates/ArrayFieldDescriptionTemplate.tsx +3 -3
  131. package/src/components/templates/ArrayFieldItemButtonsTemplate.tsx +16 -21
  132. package/src/components/templates/ArrayFieldItemTemplate.tsx +3 -3
  133. package/src/components/templates/ArrayFieldTemplate.tsx +11 -18
  134. package/src/components/templates/ArrayFieldTitleTemplate.tsx +4 -3
  135. package/src/components/templates/BaseInputTemplate.tsx +5 -5
  136. package/src/components/templates/ButtonTemplates/AddButton.tsx +2 -0
  137. package/src/components/templates/FallbackFieldTemplate.tsx +28 -0
  138. package/src/components/templates/FieldErrorTemplate.tsx +2 -2
  139. package/src/components/templates/FieldHelpTemplate.tsx +2 -2
  140. package/src/components/templates/MultiSchemaFieldTemplate.tsx +20 -0
  141. package/src/components/templates/ObjectFieldTemplate.tsx +12 -7
  142. package/src/components/templates/OptionalDataControlsTemplate.tsx +43 -0
  143. package/src/components/templates/TitleField.tsx +6 -1
  144. package/src/components/templates/UnsupportedField.tsx +3 -3
  145. package/src/components/templates/WrapIfAdditionalTemplate.tsx +5 -5
  146. package/src/components/templates/index.ts +6 -0
  147. package/src/components/widgets/AltDateWidget.tsx +8 -126
  148. package/src/components/widgets/CheckboxWidget.tsx +4 -3
  149. package/src/components/widgets/CheckboxesWidget.tsx +5 -4
  150. package/src/components/widgets/FileWidget.tsx +11 -102
  151. package/src/components/widgets/HiddenWidget.tsx +2 -1
  152. package/src/components/widgets/RadioWidget.tsx +3 -2
  153. package/src/components/widgets/RatingWidget.tsx +2 -1
  154. package/src/components/widgets/SelectWidget.tsx +3 -2
  155. package/src/components/widgets/TextareaWidget.tsx +3 -2
  156. package/src/getDefaultRegistry.ts +14 -1
  157. package/src/getTestRegistry.tsx +38 -0
  158. package/src/index.ts +2 -1
  159. package/dist/index.js +0 -4834
  160. package/dist/index.js.map +0 -7
@@ -2,7 +2,6 @@ import {
2
2
  getTemplate,
3
3
  getUiOptions,
4
4
  ArrayFieldTemplateProps,
5
- ArrayFieldItemTemplateType,
6
5
  FormContextType,
7
6
  RJSFSchema,
8
7
  StrictRJSFSchema,
@@ -11,7 +10,7 @@ import {
11
10
 
12
11
  /** The `ArrayFieldTemplate` component is the template used to render all items in an array.
13
12
  *
14
- * @param props - The `ArrayFieldItemTemplateType` props for the component
13
+ * @param props - The `ArrayFieldTemplateProps` props for the component
15
14
  */
16
15
  export default function ArrayFieldTemplate<
17
16
  T = any,
@@ -22,9 +21,10 @@ export default function ArrayFieldTemplate<
22
21
  canAdd,
23
22
  className,
24
23
  disabled,
25
- idSchema,
24
+ fieldPathId,
26
25
  uiSchema,
27
26
  items,
27
+ optionalDataControl,
28
28
  onAddClick,
29
29
  readonly,
30
30
  registry,
@@ -38,46 +38,39 @@ export default function ArrayFieldTemplate<
38
38
  registry,
39
39
  uiOptions,
40
40
  );
41
- const ArrayFieldItemTemplate = getTemplate<'ArrayFieldItemTemplate', T, S, F>(
42
- 'ArrayFieldItemTemplate',
43
- registry,
44
- uiOptions,
45
- );
46
41
  const ArrayFieldTitleTemplate = getTemplate<'ArrayFieldTitleTemplate', T, S, F>(
47
42
  'ArrayFieldTitleTemplate',
48
43
  registry,
49
44
  uiOptions,
50
45
  );
51
46
  // Button templates are not overridden in the uiSchema
47
+ const showOptionalDataControlInTitle = !readonly && !disabled;
52
48
  const {
53
49
  ButtonTemplates: { AddButton },
54
50
  } = registry.templates;
55
51
  return (
56
- <fieldset className={className} id={idSchema.$id}>
52
+ <fieldset className={className} id={fieldPathId.$id}>
57
53
  <ArrayFieldTitleTemplate
58
- idSchema={idSchema}
54
+ fieldPathId={fieldPathId}
59
55
  title={uiOptions.title || title}
60
56
  required={required}
61
57
  schema={schema}
62
58
  uiSchema={uiSchema}
63
59
  registry={registry}
60
+ optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined}
64
61
  />
65
62
  <ArrayFieldDescriptionTemplate
66
- idSchema={idSchema}
63
+ fieldPathId={fieldPathId}
67
64
  description={uiOptions.description || schema.description}
68
65
  schema={schema}
69
66
  uiSchema={uiSchema}
70
67
  registry={registry}
71
68
  />
72
- <div className='row array-item-list'>
73
- {items &&
74
- items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType<T, S, F>) => (
75
- <ArrayFieldItemTemplate key={key} {...itemProps} />
76
- ))}
77
- </div>
69
+ {!showOptionalDataControlInTitle ? optionalDataControl : undefined}
70
+ <div className='row array-item-list'>{items}</div>
78
71
  {canAdd && (
79
72
  <AddButton
80
- id={buttonId<T>(idSchema, 'add')}
73
+ id={buttonId(fieldPathId, 'add')}
81
74
  className='rjsf-array-item-add'
82
75
  onClick={onAddClick}
83
76
  disabled={disabled || readonly}
@@ -10,7 +10,7 @@ import {
10
10
  } from '@rjsf/utils';
11
11
 
12
12
  /** The `ArrayFieldTitleTemplate` component renders a `TitleFieldTemplate` with an `id` derived from
13
- * the `idSchema`.
13
+ * the `fieldPathId`.
14
14
  *
15
15
  * @param props - The `ArrayFieldTitleProps` for the component
16
16
  */
@@ -19,7 +19,7 @@ export default function ArrayFieldTitleTemplate<
19
19
  S extends StrictRJSFSchema = RJSFSchema,
20
20
  F extends FormContextType = any,
21
21
  >(props: ArrayFieldTitleProps<T, S, F>) {
22
- const { idSchema, title, schema, uiSchema, required, registry } = props;
22
+ const { fieldPathId, title, schema, uiSchema, required, registry, optionalDataControl } = props;
23
23
  const options = getUiOptions<T, S, F>(uiSchema, registry.globalUiOptions);
24
24
  const { label: displayLabel = true } = options;
25
25
  if (!title || !displayLabel) {
@@ -32,12 +32,13 @@ export default function ArrayFieldTitleTemplate<
32
32
  );
33
33
  return (
34
34
  <TitleFieldTemplate
35
- id={titleId<T>(idSchema)}
35
+ id={titleId(fieldPathId)}
36
36
  title={title}
37
37
  required={required}
38
38
  schema={schema}
39
39
  uiSchema={uiSchema}
40
40
  registry={registry}
41
+ optionalDataControl={optionalDataControl}
41
42
  />
42
43
  );
43
44
  }
@@ -23,6 +23,7 @@ export default function BaseInputTemplate<
23
23
  const {
24
24
  id,
25
25
  name, // remove this from ...rest
26
+ htmlName,
26
27
  value,
27
28
  readonly,
28
29
  disabled,
@@ -34,7 +35,6 @@ export default function BaseInputTemplate<
34
35
  options,
35
36
  schema,
36
37
  uiSchema,
37
- formContext,
38
38
  registry,
39
39
  rawErrors,
40
40
  type,
@@ -78,21 +78,21 @@ export default function BaseInputTemplate<
78
78
  <>
79
79
  <input
80
80
  id={id}
81
- name={id}
81
+ name={htmlName || id}
82
82
  className='form-control'
83
83
  readOnly={readonly}
84
84
  disabled={disabled}
85
85
  autoFocus={autofocus}
86
86
  value={inputValue}
87
87
  {...inputProps}
88
- list={schema.examples ? examplesId<T>(id) : undefined}
88
+ list={schema.examples ? examplesId(id) : undefined}
89
89
  onChange={onChangeOverride || _onChange}
90
90
  onBlur={_onBlur}
91
91
  onFocus={_onFocus}
92
- aria-describedby={ariaDescribedByIds<T>(id, !!schema.examples)}
92
+ aria-describedby={ariaDescribedByIds(id, !!schema.examples)}
93
93
  />
94
94
  {Array.isArray(schema.examples) && (
95
- <datalist key={`datalist_${id}`} id={examplesId<T>(id)}>
95
+ <datalist key={`datalist_${id}`} id={examplesId(id)}>
96
96
  {(schema.examples as string[])
97
97
  .concat(schema.default && !schema.examples.includes(schema.default) ? ([schema.default] as string[]) : [])
98
98
  .map((example: any) => {
@@ -5,6 +5,7 @@ import IconButton from './IconButton';
5
5
  /** The `AddButton` renders a button that represent the `Add` action on a form
6
6
  */
7
7
  export default function AddButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
8
+ id,
8
9
  className,
9
10
  onClick,
10
11
  disabled,
@@ -15,6 +16,7 @@ export default function AddButton<T = any, S extends StrictRJSFSchema = RJSFSche
15
16
  <div className='row'>
16
17
  <p className={`col-xs-3 col-xs-offset-9 text-right ${className}`}>
17
18
  <IconButton
19
+ id={id}
18
20
  iconType='info'
19
21
  icon='plus'
20
22
  className='btn-add col-xs-12'
@@ -0,0 +1,28 @@
1
+ import { FallbackFieldTemplateProps, FormContextType, getTemplate, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+
3
+ /**
4
+ * The `FallbackFieldTemplate` is used to render a field when no field matches. The field renders a type selector and
5
+ * the schema field for the form data.
6
+ */
7
+ export default function FallbackFieldTemplate<
8
+ T = any,
9
+ S extends StrictRJSFSchema = RJSFSchema,
10
+ F extends FormContextType = any,
11
+ >(props: FallbackFieldTemplateProps<T, S, F>) {
12
+ const { schema, registry, typeSelector, schemaField } = props;
13
+
14
+ // By default, use the MultiSchemaFieldTemplate, which handles the same basic requirements.
15
+ const MultiSchemaFieldTemplate = getTemplate<'MultiSchemaFieldTemplate', T, S, F>(
16
+ 'MultiSchemaFieldTemplate',
17
+ registry,
18
+ );
19
+
20
+ return (
21
+ <MultiSchemaFieldTemplate
22
+ selector={typeSelector}
23
+ optionSchemaField={schemaField}
24
+ schema={schema}
25
+ registry={registry}
26
+ />
27
+ );
28
+ }
@@ -9,11 +9,11 @@ export default function FieldErrorTemplate<
9
9
  S extends StrictRJSFSchema = RJSFSchema,
10
10
  F extends FormContextType = any,
11
11
  >(props: FieldErrorProps<T, S, F>) {
12
- const { errors = [], idSchema } = props;
12
+ const { errors = [], fieldPathId } = props;
13
13
  if (errors.length === 0) {
14
14
  return null;
15
15
  }
16
- const id = errorId<T>(idSchema);
16
+ const id = errorId(fieldPathId);
17
17
 
18
18
  return (
19
19
  <div>
@@ -9,11 +9,11 @@ export default function FieldHelpTemplate<
9
9
  S extends StrictRJSFSchema = RJSFSchema,
10
10
  F extends FormContextType = any,
11
11
  >(props: FieldHelpProps<T, S, F>) {
12
- const { idSchema, help } = props;
12
+ const { fieldPathId, help } = props;
13
13
  if (!help) {
14
14
  return null;
15
15
  }
16
- const id = helpId<T>(idSchema);
16
+ const id = helpId(fieldPathId);
17
17
  if (typeof help === 'string') {
18
18
  return (
19
19
  <p id={id} className='help-block'>
@@ -0,0 +1,20 @@
1
+ import { FormContextType, MultiSchemaFieldTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+
3
+ /** The `MultiSchemaFieldTemplate` component renders the layout for the MultiSchemaField, which supports choosing
4
+ * a schema from a list of schemas defined using `anyOf` or `oneOf`.
5
+ *
6
+ * @param props - The `MultiSchemaFieldTemplate` to be rendered
7
+ */
8
+ export default function MultiSchemaFieldTemplate<
9
+ T = any,
10
+ S extends StrictRJSFSchema = RJSFSchema,
11
+ F extends FormContextType = any,
12
+ >(props: MultiSchemaFieldTemplateProps<T, S, F>) {
13
+ const { selector, optionSchemaField } = props;
14
+ return (
15
+ <div className='panel panel-default panel-body'>
16
+ <div className='form-group'>{selector}</div>
17
+ {optionSchemaField}
18
+ </div>
19
+ );
20
+ }
@@ -24,11 +24,13 @@ export default function ObjectFieldTemplate<
24
24
  F extends FormContextType = any,
25
25
  >(props: ObjectFieldTemplateProps<T, S, F>) {
26
26
  const {
27
+ className,
27
28
  description,
28
29
  disabled,
29
30
  formData,
30
- idSchema,
31
- onAddClick,
31
+ fieldPathId,
32
+ onAddProperty,
33
+ optionalDataControl,
32
34
  properties,
33
35
  readonly,
34
36
  registry,
@@ -44,37 +46,40 @@ export default function ObjectFieldTemplate<
44
46
  registry,
45
47
  options,
46
48
  );
49
+ const showOptionalDataControlInTitle = !readonly && !disabled;
47
50
  // Button templates are not overridden in the uiSchema
48
51
  const {
49
52
  ButtonTemplates: { AddButton },
50
53
  } = registry.templates;
51
54
  return (
52
- <fieldset id={idSchema.$id}>
55
+ <fieldset className={className} id={fieldPathId.$id}>
53
56
  {title && (
54
57
  <TitleFieldTemplate
55
- id={titleId<T>(idSchema)}
58
+ id={titleId(fieldPathId)}
56
59
  title={title}
57
60
  required={required}
58
61
  schema={schema}
59
62
  uiSchema={uiSchema}
60
63
  registry={registry}
64
+ optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined}
61
65
  />
62
66
  )}
63
67
  {description && (
64
68
  <DescriptionFieldTemplate
65
- id={descriptionId<T>(idSchema)}
69
+ id={descriptionId(fieldPathId)}
66
70
  description={description}
67
71
  schema={schema}
68
72
  uiSchema={uiSchema}
69
73
  registry={registry}
70
74
  />
71
75
  )}
76
+ {!showOptionalDataControlInTitle ? optionalDataControl : undefined}
72
77
  {properties.map((prop: ObjectFieldTemplatePropertyType) => prop.content)}
73
78
  {canExpand<T, S, F>(schema, uiSchema, formData) && (
74
79
  <AddButton
75
- id={buttonId<T>(idSchema, 'add')}
80
+ id={buttonId(fieldPathId, 'add')}
76
81
  className='rjsf-object-property-expand'
77
- onClick={onAddClick(schema)}
82
+ onClick={onAddProperty}
78
83
  disabled={disabled || readonly}
79
84
  uiSchema={uiSchema}
80
85
  registry={registry}
@@ -0,0 +1,43 @@
1
+ import { FormContextType, OptionalDataControlsTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+
3
+ import IconButton from './ButtonTemplates/IconButton';
4
+
5
+ /** The OptionalDataControlsTemplate renders one of three different states. If
6
+ * there is an `onAddClick()` function, it renders the "Add" button. If there is
7
+ * an `onRemoveClick()` function, it renders the "Remove" button. Otherwise it
8
+ * renders the "No data found" section. All of them use the `label` as either
9
+ * the `title` of buttons or simply outputting it.
10
+ *
11
+ * @param props - The `OptionalDataControlsTemplateProps` for the template
12
+ */
13
+ export default function OptionalDataControlsTemplate<
14
+ T = any,
15
+ S extends StrictRJSFSchema = RJSFSchema,
16
+ F extends FormContextType = any,
17
+ >(props: OptionalDataControlsTemplateProps<T, S, F>) {
18
+ const { id, registry, label, onAddClick, onRemoveClick } = props;
19
+ if (onAddClick) {
20
+ return (
21
+ <IconButton
22
+ id={id}
23
+ registry={registry}
24
+ icon='plus'
25
+ className='rjsf-add-optional-data btn-sm'
26
+ onClick={onAddClick}
27
+ title={label}
28
+ />
29
+ );
30
+ } else if (onRemoveClick) {
31
+ return (
32
+ <IconButton
33
+ id={id}
34
+ registry={registry}
35
+ icon='remove'
36
+ className='rjsf-remove-optional-data btn-sm'
37
+ onClick={onRemoveClick}
38
+ title={label}
39
+ />
40
+ );
41
+ }
42
+ return <em id={id}>{label}</em>;
43
+ }
@@ -9,11 +9,16 @@ const REQUIRED_FIELD_SYMBOL = '*';
9
9
  export default function TitleField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
10
10
  props: TitleFieldProps<T, S, F>,
11
11
  ) {
12
- const { id, title, required } = props;
12
+ const { id, title, required, optionalDataControl } = props;
13
13
  return (
14
14
  <legend id={id}>
15
15
  {title}
16
16
  {required && <span className='required'>{REQUIRED_FIELD_SYMBOL}</span>}
17
+ {optionalDataControl && (
18
+ <span className='pull-right' style={{ marginBottom: '2px' }}>
19
+ {optionalDataControl}
20
+ </span>
21
+ )}
17
22
  </legend>
18
23
  );
19
24
  }
@@ -9,13 +9,13 @@ import Markdown from 'markdown-to-jsx';
9
9
  function UnsupportedField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
10
10
  props: UnsupportedFieldProps<T, S, F>,
11
11
  ) {
12
- const { schema, idSchema, reason, registry } = props;
12
+ const { schema, fieldPathId, reason, registry } = props;
13
13
  const { translateString } = registry;
14
14
  let translateEnum: TranslatableString = TranslatableString.UnsupportedField;
15
15
  const translateParams: string[] = [];
16
- if (idSchema && idSchema.$id) {
16
+ if (fieldPathId && fieldPathId.$id) {
17
17
  translateEnum = TranslatableString.UnsupportedFieldWithId;
18
- translateParams.push(idSchema.$id);
18
+ translateParams.push(fieldPathId.$id);
19
19
  }
20
20
  if (reason) {
21
21
  translateEnum =
@@ -26,8 +26,8 @@ export default function WrapIfAdditionalTemplate<
26
26
  style,
27
27
  disabled,
28
28
  label,
29
- onKeyChange,
30
- onDropPropertyClick,
29
+ onKeyRenameBlur,
30
+ onRemoveProperty,
31
31
  readonly,
32
32
  required,
33
33
  schema,
@@ -67,7 +67,7 @@ export default function WrapIfAdditionalTemplate<
67
67
  className='form-control'
68
68
  type='text'
69
69
  id={`${id}-key`}
70
- onBlur={({ target }) => onKeyChange(target && target.value)}
70
+ onBlur={onKeyRenameBlur}
71
71
  defaultValue={label}
72
72
  />
73
73
  </div>
@@ -75,11 +75,11 @@ export default function WrapIfAdditionalTemplate<
75
75
  <div className='form-additional form-group col-xs-5'>{children}</div>
76
76
  <div className='col-xs-2'>
77
77
  <RemoveButton
78
- id={buttonId<T>(id, 'remove')}
78
+ id={buttonId(id, 'remove')}
79
79
  className='rjsf-object-property-remove btn-block'
80
80
  style={{ border: '0' }}
81
81
  disabled={disabled || readonly}
82
- onClick={onDropPropertyClick(label)}
82
+ onClick={onRemoveProperty}
83
83
  uiSchema={uiSchema}
84
84
  registry={registry}
85
85
  />
@@ -9,11 +9,14 @@ import BaseInputTemplate from './BaseInputTemplate';
9
9
  import ButtonTemplates from './ButtonTemplates';
10
10
  import DescriptionField from './DescriptionField';
11
11
  import ErrorList from './ErrorList';
12
+ import FallbackFieldTemplate from './FallbackFieldTemplate';
12
13
  import FieldTemplate from './FieldTemplate';
13
14
  import FieldErrorTemplate from './FieldErrorTemplate';
14
15
  import FieldHelpTemplate from './FieldHelpTemplate';
15
16
  import GridTemplate from './GridTemplate';
17
+ import MultiSchemaFieldTemplate from './MultiSchemaFieldTemplate';
16
18
  import ObjectFieldTemplate from './ObjectFieldTemplate';
19
+ import OptionalDataControlsTemplate from './OptionalDataControlsTemplate';
17
20
  import TitleField from './TitleField';
18
21
  import UnsupportedField from './UnsupportedField';
19
22
  import WrapIfAdditionalTemplate from './WrapIfAdditionalTemplate';
@@ -33,11 +36,14 @@ function templates<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends F
33
36
  BaseInputTemplate,
34
37
  DescriptionFieldTemplate: DescriptionField,
35
38
  ErrorListTemplate: ErrorList,
39
+ FallbackFieldTemplate,
36
40
  FieldTemplate,
37
41
  FieldErrorTemplate,
38
42
  FieldHelpTemplate,
39
43
  GridTemplate,
44
+ MultiSchemaFieldTemplate,
40
45
  ObjectFieldTemplate,
46
+ OptionalDataControlsTemplate,
41
47
  TitleFieldTemplate: TitleField,
42
48
  UnsupportedFieldTemplate: UnsupportedField,
43
49
  WrapIfAdditionalTemplate,
@@ -1,144 +1,26 @@
1
- import { MouseEvent, useCallback, useEffect, useReducer, useState } from 'react';
2
1
  import {
3
- ariaDescribedByIds,
4
- dateRangeOptions,
5
- parseDateString,
6
- toDateString,
7
- DateObject,
8
- type DateElementFormat,
2
+ DateElement,
9
3
  FormContextType,
10
4
  RJSFSchema,
11
5
  StrictRJSFSchema,
12
6
  TranslatableString,
13
7
  WidgetProps,
14
- getDateElementProps,
8
+ useAltDateWidgetProps,
15
9
  } from '@rjsf/utils';
16
10
 
17
- function readyForChange(state: DateObject) {
18
- return Object.values(state).every((value) => value !== -1);
19
- }
20
-
21
- type DateElementProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = Pick<
22
- WidgetProps<T, S, F>,
23
- 'value' | 'name' | 'disabled' | 'readonly' | 'autofocus' | 'registry' | 'onBlur' | 'onFocus'
24
- > & {
25
- rootId: string;
26
- select: (property: keyof DateObject, value: any) => void;
27
- type: string;
28
- range: [number, number];
29
- };
30
-
31
- function DateElement<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
32
- type,
33
- range,
34
- value,
35
- select,
36
- rootId,
37
- name,
38
- disabled,
39
- readonly,
40
- autofocus,
41
- registry,
42
- onBlur,
43
- onFocus,
44
- }: DateElementProps<T, S, F>) {
45
- const id = rootId + '_' + type;
46
- const { SelectWidget } = registry.widgets;
47
- return (
48
- <SelectWidget
49
- schema={{ type: 'integer' } as S}
50
- id={id}
51
- name={name}
52
- className='form-control'
53
- options={{ enumOptions: dateRangeOptions<S>(range[0], range[1]) }}
54
- placeholder={type}
55
- value={value}
56
- disabled={disabled}
57
- readonly={readonly}
58
- autofocus={autofocus}
59
- onChange={(value: any) => select(type as keyof DateObject, value)}
60
- onBlur={onBlur}
61
- onFocus={onFocus}
62
- registry={registry}
63
- label=''
64
- aria-describedby={ariaDescribedByIds<T>(rootId)}
65
- />
66
- );
67
- }
68
-
69
11
  /** The `AltDateWidget` is an alternative widget for rendering date properties.
70
12
  * @param props - The `WidgetProps` for this component
71
13
  */
72
- function AltDateWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
73
- time = false,
74
- disabled = false,
75
- readonly = false,
76
- autofocus = false,
77
- options,
78
- id,
79
- name,
80
- registry,
81
- onBlur,
82
- onFocus,
83
- onChange,
84
- value,
85
- }: WidgetProps<T, S, F>) {
14
+ function AltDateWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
15
+ props: WidgetProps<T, S, F>,
16
+ ) {
17
+ const { disabled = false, readonly = false, autofocus = false, options, id, name, registry, onBlur, onFocus } = props;
86
18
  const { translateString } = registry;
87
- const [lastValue, setLastValue] = useState(value);
88
- const [state, setState] = useReducer(
89
- (state: DateObject, action: Partial<DateObject>) => {
90
- return { ...state, ...action };
91
- },
92
- parseDateString(value, time),
93
- );
94
-
95
- useEffect(() => {
96
- const stateValue = toDateString(state, time);
97
- if (readyForChange(state) && stateValue !== value) {
98
- // The user changed the date to a new valid data via the comboboxes, so call onChange
99
- onChange(stateValue);
100
- } else if (lastValue !== value) {
101
- // We got a new value in the props
102
- setLastValue(value);
103
- setState(parseDateString(value, time));
104
- }
105
- }, [time, value, onChange, state, lastValue]);
106
-
107
- const handleChange = useCallback((property: keyof DateObject, value: string) => {
108
- setState({ [property]: value });
109
- }, []);
110
-
111
- const handleSetNow = useCallback(
112
- (event: MouseEvent<HTMLAnchorElement>) => {
113
- event.preventDefault();
114
- if (disabled || readonly) {
115
- return;
116
- }
117
- const nextState = parseDateString(new Date().toJSON(), time);
118
- onChange(toDateString(nextState, time));
119
- },
120
- [disabled, readonly, time],
121
- );
122
-
123
- const handleClear = useCallback(
124
- (event: MouseEvent<HTMLAnchorElement>) => {
125
- event.preventDefault();
126
- if (disabled || readonly) {
127
- return;
128
- }
129
- onChange(undefined);
130
- },
131
- [disabled, readonly, onChange],
132
- );
19
+ const { elements, handleChange, handleClear, handleSetNow } = useAltDateWidgetProps(props);
133
20
 
134
21
  return (
135
22
  <ul className='list-inline'>
136
- {getDateElementProps(
137
- state,
138
- time,
139
- options.yearsRange as [number, number] | undefined,
140
- options.format as DateElementFormat | undefined,
141
- ).map((elemProps, i) => (
23
+ {elements.map((elemProps, i) => (
142
24
  <li className='list-inline-item' key={i}>
143
25
  <DateElement
144
26
  rootId={id}
@@ -31,6 +31,7 @@ function CheckboxWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
31
31
  onFocus,
32
32
  onChange,
33
33
  registry,
34
+ htmlName,
34
35
  }: WidgetProps<T, S, F>) {
35
36
  const DescriptionFieldTemplate = getTemplate<'DescriptionFieldTemplate', T, S, F>(
36
37
  'DescriptionFieldTemplate',
@@ -62,7 +63,7 @@ function CheckboxWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
62
63
  <div className={`checkbox ${disabled || readonly ? 'disabled' : ''}`}>
63
64
  {!hideLabel && description && (
64
65
  <DescriptionFieldTemplate
65
- id={descriptionId<T>(id)}
66
+ id={descriptionId(id)}
66
67
  description={description}
67
68
  schema={schema}
68
69
  uiSchema={uiSchema}
@@ -73,7 +74,7 @@ function CheckboxWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
73
74
  <input
74
75
  type='checkbox'
75
76
  id={id}
76
- name={id}
77
+ name={htmlName || id}
77
78
  checked={typeof value === 'undefined' ? false : value}
78
79
  required={required}
79
80
  disabled={disabled || readonly}
@@ -81,7 +82,7 @@ function CheckboxWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
81
82
  onChange={handleChange}
82
83
  onBlur={handleBlur}
83
84
  onFocus={handleFocus}
84
- aria-describedby={ariaDescribedByIds<T>(id)}
85
+ aria-describedby={ariaDescribedByIds(id)}
85
86
  />
86
87
  {labelValue(<span>{label}</span>, hideLabel)}
87
88
  </label>