@rjsf/core 6.2.5 → 6.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rjsf/core",
3
- "version": "6.2.5",
3
+ "version": "6.3.0",
4
4
  "description": "A simple React component capable of building HTML forms out of a JSON schema.",
5
5
  "scripts": {
6
6
  "compileReplacer": "tsc -p tsconfig.replacer.json && move-file lodashReplacer.js lodashReplacer.cjs",
@@ -70,17 +70,17 @@
70
70
  "react": ">=18"
71
71
  },
72
72
  "dependencies": {
73
- "lodash": "^4.17.21",
74
- "lodash-es": "^4.17.21",
73
+ "lodash": "^4.17.23",
74
+ "lodash-es": "^4.17.23",
75
75
  "markdown-to-jsx": "^8.0.0",
76
76
  "prop-types": "^15.8.1"
77
77
  },
78
78
  "devDependencies": {
79
- "@rjsf/snapshot-tests": "^6.2.0",
80
- "@rjsf/utils": "^6.2.0",
81
- "@rjsf/validator-ajv8": "^6.2.0",
79
+ "@rjsf/snapshot-tests": "^6.2.5",
80
+ "@rjsf/utils": "^6.2.5",
81
+ "@rjsf/validator-ajv8": "^6.2.5",
82
82
  "@testing-library/jest-dom": "^6.9.1",
83
- "@testing-library/react": "^16.3.0",
83
+ "@testing-library/react": "^16.3.2",
84
84
  "@testing-library/user-event": "^14.6.1",
85
85
  "@types/react-portal": "^4.0.7",
86
86
  "ajv": "^8.17.1",
@@ -6,6 +6,7 @@ import {
6
6
  ErrorSchema,
7
7
  ErrorSchemaBuilder,
8
8
  ErrorTransformer,
9
+ expandUiSchemaDefinitions,
9
10
  FieldPathId,
10
11
  FieldPathList,
11
12
  FormContextType,
@@ -28,6 +29,7 @@ import {
28
29
  toErrorList,
29
30
  toFieldPathId,
30
31
  UiSchema,
32
+ UI_DEFINITIONS_KEY,
31
33
  UI_GLOBAL_OPTIONS_KEY,
32
34
  UI_OPTIONS_KEY,
33
35
  ValidationData,
@@ -311,11 +313,14 @@ export interface FormState<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
311
313
  /** The event data passed when changes have been made to the form, includes everything from the `FormState` except
312
314
  * the schema validation errors. An additional `status` is added when returned from `onSubmit`
313
315
  */
314
- export interface IChangeEvent<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
315
- extends Pick<
316
- FormState<T, S, F>,
317
- 'schema' | 'uiSchema' | 'fieldPathId' | 'schemaUtils' | 'formData' | 'edit' | 'errors' | 'errorSchema'
318
- > {
316
+ export interface IChangeEvent<
317
+ T = any,
318
+ S extends StrictRJSFSchema = RJSFSchema,
319
+ F extends FormContextType = any,
320
+ > extends Pick<
321
+ FormState<T, S, F>,
322
+ 'schema' | 'uiSchema' | 'fieldPathId' | 'schemaUtils' | 'formData' | 'edit' | 'errors' | 'errorSchema'
323
+ > {
319
324
  /** The status of the form when submitted */
320
325
  status?: 'submitted';
321
326
  }
@@ -620,6 +625,12 @@ export default class Form<
620
625
  // Only store a new registry when the props cause a different one to be created
621
626
  const newRegistry = this.getRegistry(props, rootSchema, schemaUtils);
622
627
  const registry = deepEquals(state.registry, newRegistry) ? state.registry : newRegistry;
628
+
629
+ // Pre-expand ui:definitions into the uiSchema structure (must happen after registry is created)
630
+ const expandedUiSchema: UiSchema<T, S, F> = registry.uiSchemaDefinitions
631
+ ? expandUiSchemaDefinitions<T, S, F>(rootSchema, uiSchema, registry)
632
+ : uiSchema;
633
+
623
634
  // Only compute a new `fieldPathId` when the `idPrefix` is different than the existing fieldPathId's ID_KEY
624
635
  const fieldPathId =
625
636
  state.fieldPathId && state.fieldPathId?.[ID_KEY] === registry.globalFormOptions.idPrefix
@@ -628,7 +639,7 @@ export default class Form<
628
639
  const nextState: FormState<T, S, F> = {
629
640
  schemaUtils,
630
641
  schema: rootSchema,
631
- uiSchema,
642
+ uiSchema: expandedUiSchema,
632
643
  fieldPathId,
633
644
  formData,
634
645
  edit,
@@ -1149,6 +1160,7 @@ export default class Form<
1149
1160
  translateString: customTranslateString || translateString,
1150
1161
  globalUiOptions: uiSchema[UI_GLOBAL_OPTIONS_KEY],
1151
1162
  globalFormOptions: this.getGlobalFormOptions(props),
1163
+ uiSchemaDefinitions: uiSchema[UI_DEFINITIONS_KEY] ?? {},
1152
1164
  };
1153
1165
  }
1154
1166
 
@@ -0,0 +1,36 @@
1
+ import { examplesId, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+
3
+ export interface SchemaExamplesProps<S extends StrictRJSFSchema = RJSFSchema> {
4
+ /** The id of the input element this datalist is for */
5
+ id: string;
6
+ /** The JSON schema object containing examples and default value */
7
+ schema: S;
8
+ }
9
+
10
+ /** Renders a `<datalist>` element containing options from schema examples and default value.
11
+ * Normalizes types to prevent duplicate keys when examples and default have different types.
12
+ * For example, if examples are strings ["5432"] and default is number 5432, the default
13
+ * will not be added as a duplicate option.
14
+ *
15
+ * @param props - The `SchemaExamplesProps` for this component
16
+ */
17
+ export default function SchemaExamples<S extends StrictRJSFSchema = RJSFSchema>(props: SchemaExamplesProps<S>) {
18
+ const { id, schema } = props;
19
+ const { examples, default: schemaDefault } = schema;
20
+ if (!Array.isArray(examples)) {
21
+ return null;
22
+ }
23
+ return (
24
+ <datalist key={`datalist_${id}`} id={examplesId(id)}>
25
+ {(examples as string[])
26
+ .concat(
27
+ schemaDefault !== undefined && !examples.map(String).includes(String(schemaDefault))
28
+ ? ([schemaDefault] as string[])
29
+ : [],
30
+ )
31
+ .map((example: any) => {
32
+ return <option key={String(example)} value={example} />;
33
+ })}
34
+ </datalist>
35
+ );
36
+ }
@@ -166,8 +166,11 @@ function getNewFormDataRow<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
166
166
  }
167
167
 
168
168
  /** Props used for ArrayAsXxxx type components*/
169
- interface ArrayAsFieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
170
- extends FieldProps<T, S, F> {
169
+ interface ArrayAsFieldProps<
170
+ T = any,
171
+ S extends StrictRJSFSchema = RJSFSchema,
172
+ F extends FormContextType = any,
173
+ > extends FieldProps<T, S, F> {
171
174
  /** The callback used to update the array when the selector changes */
172
175
  onSelectChange: (value: T) => void;
173
176
  }
@@ -522,8 +525,11 @@ function ArrayFieldItem<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
522
525
  }
523
526
 
524
527
  /** The properties required by the stateless components that render the items using the `ArrayFieldItem` */
525
- interface InternalArrayFieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
526
- extends FieldProps<T[], S, F> {
528
+ interface InternalArrayFieldProps<
529
+ T = any,
530
+ S extends StrictRJSFSchema = RJSFSchema,
531
+ F extends FormContextType = any,
532
+ > extends FieldProps<T[], S, F> {
527
533
  /** The keyedFormData from the `ArrayField` state */
528
534
  keyedFormData: KeyedFormDataType<T>[];
529
535
  /** The callback used to handle the adding of an item at the given index (or the end, if missing) */
@@ -83,8 +83,11 @@ export type GridSchemaType = {
83
83
  */
84
84
  export type LayoutGridSchemaType = GridSchemaType | ConfigObject | string;
85
85
 
86
- export interface LayoutGridFieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
87
- extends FieldProps<T, S, F> {
86
+ export interface LayoutGridFieldProps<
87
+ T = any,
88
+ S extends StrictRJSFSchema = RJSFSchema,
89
+ F extends FormContextType = any,
90
+ > extends FieldProps<T, S, F> {
88
91
  /** Optional string or object used to describe the current level of the `LayoutGridField`
89
92
  */
90
93
  layoutGridSchema?: LayoutGridSchemaType;
@@ -69,8 +69,11 @@ function getDefaultValue<T = any, S extends StrictRJSFSchema = RJSFSchema, F ext
69
69
  }
70
70
 
71
71
  /** Props for the `ObjectFieldProperty` component */
72
- interface ObjectFieldPropertyProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
73
- extends Omit<FieldProps<T, S, F>, 'name'> {
72
+ interface ObjectFieldPropertyProps<
73
+ T = any,
74
+ S extends StrictRJSFSchema = RJSFSchema,
75
+ F extends FormContextType = any,
76
+ > extends Omit<FieldProps<T, S, F>, 'name'> {
74
77
  /** The name of the property within the parent object */
75
78
  propertyName: string;
76
79
  /** Flag indicating whether this property was added by the additionalProperties UI */
@@ -17,6 +17,7 @@ import {
17
17
  isFormDataAvailable,
18
18
  ONE_OF_KEY,
19
19
  Registry,
20
+ resolveUiSchema,
20
21
  RJSFSchema,
21
22
  shouldRender,
22
23
  shouldRenderOptionalField,
@@ -93,7 +94,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
93
94
  const {
94
95
  schema: _schema,
95
96
  fieldPathId,
96
- uiSchema,
97
+ uiSchema: _uiSchema,
97
98
  formData,
98
99
  errorSchema,
99
100
  name,
@@ -107,6 +108,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
107
108
  } = props;
108
109
  const { schemaUtils, globalFormOptions, globalUiOptions, fields } = registry;
109
110
  const { AnyOfField: _AnyOfField, OneOfField: _OneOfField } = fields;
111
+ const uiSchema = resolveUiSchema<T, S, F>(_schema, _uiSchema, registry);
110
112
  const uiOptions = getUiOptions<T, S, F>(uiSchema, globalUiOptions);
111
113
  const FieldTemplate = getTemplate<'FieldTemplate', T, S, F>('FieldTemplate', registry, uiOptions);
112
114
  const DescriptionFieldTemplate = getTemplate<'DescriptionFieldTemplate', T, S, F>(
@@ -9,6 +9,8 @@ import {
9
9
  StrictRJSFSchema,
10
10
  } from '@rjsf/utils';
11
11
 
12
+ import SchemaExamples from '../SchemaExamples';
13
+
12
14
  /** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
13
15
  * It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only.
14
16
  * It can be customized/overridden for other themes or individual implementations as needed.
@@ -103,15 +105,7 @@ export default function BaseInputTemplate<
103
105
  {options.allowClearTextInputs && !readonly && !disabled && inputValue && (
104
106
  <ClearButton registry={registry} onClick={_onClear} />
105
107
  )}
106
- {Array.isArray(schema.examples) && (
107
- <datalist key={`datalist_${id}`} id={examplesId(id)}>
108
- {(schema.examples as string[])
109
- .concat(schema.default && !schema.examples.includes(schema.default) ? ([schema.default] as string[]) : [])
110
- .map((example: any) => {
111
- return <option key={example} value={example} />;
112
- })}
113
- </datalist>
114
- )}
108
+ <SchemaExamples id={id} schema={schema} />
115
109
  </>
116
110
  );
117
111
  }
package/src/index.ts CHANGED
@@ -1,11 +1,20 @@
1
1
  import Form, { FormProps, FormState, IChangeEvent } from './components/Form';
2
2
  import RichDescription, { RichDescriptionProps } from './components/RichDescription';
3
3
  import RichHelp, { RichHelpProps } from './components/RichHelp';
4
+ import SchemaExamples, { SchemaExamplesProps } from './components/SchemaExamples';
4
5
  import withTheme, { ThemeProps } from './withTheme';
5
6
  import getDefaultRegistry from './getDefaultRegistry';
6
7
  import getTestRegistry from './getTestRegistry';
7
8
 
8
- export type { FormProps, FormState, IChangeEvent, ThemeProps, RichDescriptionProps, RichHelpProps };
9
+ export type {
10
+ FormProps,
11
+ FormState,
12
+ IChangeEvent,
13
+ ThemeProps,
14
+ RichDescriptionProps,
15
+ RichHelpProps,
16
+ SchemaExamplesProps,
17
+ };
9
18
 
10
- export { withTheme, getDefaultRegistry, getTestRegistry, RichDescription, RichHelp };
19
+ export { withTheme, getDefaultRegistry, getTestRegistry, RichDescription, RichHelp, SchemaExamples };
11
20
  export default Form;