diff --git a/CHANGELOG.md b/CHANGELOG.md index 21d0d3fbf8..798d3a6eec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,10 @@ return (); - Fixed a faulty check of the `isMultiple` option in `MultiSchemaField`. It no longer offers multiple choice inside a select field in a `oneOf` case in Chakra UI, fixing [#3848](https://github.com/rjsf-team/react-jsonschema-form/issues/3848) +## Dev / docs / playground + +- Fixed custom validation playground example ([#3856](https://github.com/rjsf-team/react-jsonschema-form/issues/3856)) + # 5.12.1 ## @rjsf/validator-ajv8 diff --git a/package-lock.json b/package-lock.json index 57a03a22fb..17d47dcde6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13304,8 +13304,7 @@ "node_modules/deep-freeze-es6": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/deep-freeze-es6/-/deep-freeze-es6-1.4.1.tgz", - "integrity": "sha512-WnyM4ZCzpHtziy7LxnpQPGS+mfZDQvFpmH3LGqmyUfzwBLkvNTwbn+mTwSNTQoLQTHiN85qZqprRZdYwU3xN/Q==", - "dev": true + "integrity": "sha512-WnyM4ZCzpHtziy7LxnpQPGS+mfZDQvFpmH3LGqmyUfzwBLkvNTwbn+mTwSNTQoLQTHiN85qZqprRZdYwU3xN/Q==" }, "node_modules/deep-is": { "version": "0.1.4", @@ -32827,6 +32826,7 @@ "chakra-react-select": "^4.7.0", "core-js": "^3.32.2", "dayjs": "^1.11.9", + "deep-freeze-es6": "^1.4.1", "framer-motion": "^5.6.0", "jss": "^10.10.0", "lodash": "^4.17.21", diff --git a/packages/docs/docs/usage/validation.md b/packages/docs/docs/usage/validation.md index dbe6f76813..14be6f4318 100644 --- a/packages/docs/docs/usage/validation.md +++ b/packages/docs/docs/usage/validation.md @@ -90,9 +90,11 @@ const validator = createPrecompiledValidator(precompiledValidator as ValidatorFu render(
, document.getElementById('app')); ``` + ### Dynamically pre-compiling validators For more advanced cases when schema needs to be precompiled on request - `compileSchemaValidatorsCode` can be used. + ```ts import { compileSchemaValidatorsCode } from '@rjsf/validator-ajv8/dist/compileSchemaValidators'; @@ -103,7 +105,7 @@ For the most part it is the same as `compileSchemaValidators`, but instead of wr To use it on browser side - some modifications are needed to provide runtime dependencies in generated code needs to be provided. -Example implementation of it: +Example implementation of it: ```tsx import type { ValidatorFunctions } from '@rjsf/validator-ajv8'; @@ -121,19 +123,13 @@ import ajvRuntimeUcs2length from 'ajv/dist/runtime/ucs2length'; import ajvRuntimeUri from 'ajv/dist/runtime/uri'; import * as ajvFormats from 'ajv-formats/dist/formats'; -// dependencies to replace in generated code, to be provided by at runtime +// dependencies to replace in generated code, to be provided by at runtime const validatorsBundleReplacements: Record = { - // '': ['', ], + // '': ['', ], 'require("ajv/dist/runtime/equal").default': ['ajvRuntimeEqual', ajvRuntimeEqual], 'require("ajv/dist/runtime/parseJson").parseJson': ['ajvRuntimeparseJson', ajvRuntimeparseJson], - 'require("ajv/dist/runtime/parseJson").parseJsonNumber': [ - 'ajvRuntimeparseJsonNumber', - ajvRuntimeparseJsonNumber, - ], - 'require("ajv/dist/runtime/parseJson").parseJsonString': [ - 'ajvRuntimeparseJsonString', - ajvRuntimeparseJsonString, - ], + 'require("ajv/dist/runtime/parseJson").parseJsonNumber': ['ajvRuntimeparseJsonNumber', ajvRuntimeparseJsonNumber], + 'require("ajv/dist/runtime/parseJson").parseJsonString': ['ajvRuntimeparseJsonString', ajvRuntimeparseJsonString], 'require("ajv/dist/runtime/quote").default': ['ajvRuntimeQuote', ajvRuntimeQuote], // re2 by default is not in dependencies for ajv and so is likely not normally used // 'require("ajv/dist/runtime/re2").default': ['ajvRuntimeRe2', ajvRuntimeRe2], @@ -167,10 +163,7 @@ const schemas = new Map< >(); if (typeof window !== 'undefined') { // @ts-ignore - window[windowValidatorOnLoad] = ( - loadedId: string, - fn: (...args: unknown[]) => ValidatorFunctions - ) => { + window[windowValidatorOnLoad] = (loadedId: string, fn: (...args: unknown[]) => ValidatorFunctions) => { const validator = fn(...Object.values(validatorsBundleReplacements).map(([, dep]) => dep)); let validatorLoader = schemas.get(loadedId); if (validatorLoader) { @@ -207,28 +200,26 @@ export function evaluateValidator(id: string, code: string, nonce: string): Prom document.body.appendChild(scriptElement); return validatorPromise; } - ``` -From React component this can be used as following: +From React component this can be used as following: ```tsx let [precompiledValidator, setPrecompiledValidator] = React.useState(); React.useEffect(() => { - evaluateValidator( - schemaId, // some schema id to avoid evaluating it multiple times - code, // result of compileSchemaValidatorsCode returned from the server - nonce // nonce script tag attribute to allow this ib content security policy for the page - ).then(setPrecompiledValidator); + evaluateValidator( + schemaId, // some schema id to avoid evaluating it multiple times + code, // result of compileSchemaValidatorsCode returned from the server + nonce // nonce script tag attribute to allow this ib content security policy for the page + ).then(setPrecompiledValidator); }, [entityType.id]); if (!precompiledValidator) { - // render loading screen + // render loading screen } const validator = createPrecompiledValidator(precompiledValidator, schema); ``` - ## Live validation By default, form data are only validated when the form is submitted or when a new `formData` prop is passed to the `Form` component. @@ -526,7 +517,7 @@ const validator = customizeValidator({ customFormats }); render(, document.getElementById('app')); ``` -Format values can be anything AJV’s [`addFormat` method](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv) accepts. +Format values can be anything AJV's [`addFormat` method](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv) accepts. ### Async validation diff --git a/packages/docs/versioned_docs/version-3.2.1/usage/validation.md b/packages/docs/versioned_docs/version-3.2.1/usage/validation.md index 5e8cd19042..ed87961d6e 100644 --- a/packages/docs/versioned_docs/version-3.2.1/usage/validation.md +++ b/packages/docs/versioned_docs/version-3.2.1/usage/validation.md @@ -224,7 +224,7 @@ render(( ), document.getElementById("app")); ``` -Format values can be anything AJV’s [`addFormat` method](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv) accepts. +Format values can be anything AJV's [`addFormat` method](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv) accepts. ## Async validation diff --git a/packages/docs/versioned_docs/version-4.2.3/usage/validation.md b/packages/docs/versioned_docs/version-4.2.3/usage/validation.md index 5e8cd19042..ed87961d6e 100644 --- a/packages/docs/versioned_docs/version-4.2.3/usage/validation.md +++ b/packages/docs/versioned_docs/version-4.2.3/usage/validation.md @@ -224,7 +224,7 @@ render(( ), document.getElementById("app")); ``` -Format values can be anything AJV’s [`addFormat` method](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv) accepts. +Format values can be anything AJV's [`addFormat` method](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv) accepts. ## Async validation diff --git a/packages/playground/package.json b/packages/playground/package.json index d075423e6c..8029801560 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -60,6 +60,7 @@ "chakra-react-select": "^4.7.0", "core-js": "^3.32.2", "dayjs": "^1.11.9", + "deep-freeze-es6": "^1.4.1", "framer-motion": "^5.6.0", "jss": "^10.10.0", "lodash": "^4.17.21", diff --git a/packages/playground/src/components/Playground.tsx b/packages/playground/src/components/Playground.tsx index 9560acdff1..2f7a8d7840 100644 --- a/packages/playground/src/components/Playground.tsx +++ b/packages/playground/src/components/Playground.tsx @@ -1,6 +1,6 @@ -import { useCallback, useState, useRef, useEffect, ComponentType, FormEvent } from 'react'; -import { withTheme, IChangeEvent, FormProps } from '@rjsf/core'; -import { ErrorSchema, RJSFSchema, RJSFValidationError, TemplatesType, UiSchema, ValidatorType } from '@rjsf/utils'; +import { ComponentType, FormEvent, useCallback, useEffect, useRef, useState } from 'react'; +import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; +import { ErrorSchema, RJSFSchema, RJSFValidationError, UiSchema, ValidatorType } from '@rjsf/utils'; import { samples } from '../samples'; import Header, { LiveSettings } from './Header'; @@ -10,6 +10,7 @@ import GeoPosition from './GeoPosition'; import { ThemesType } from './ThemeSelector'; import Editors from './Editors'; import SpecialInput from './SpecialInput'; +import { Sample } from '../samples/Sample'; export interface PlaygroundProps { themes: { [themeName: string]: ThemesType }; @@ -39,7 +40,7 @@ export default function Playground({ themes, validators }: PlaygroundProps) { experimental_defaultFormStateBehavior: { arrayMinItems: 'populate', emptyObjectFields: 'populateAllDefaults' }, }); const [FormComponent, setFormComponent] = useState>(withTheme({})); - const [templates, setTemplates] = useState>(); + const [otherFormProps, setOtherFormProps] = useState>({}); const playGroundFormRef = useRef(null); @@ -54,12 +55,21 @@ export default function Playground({ themes, validators }: PlaygroundProps) { ); const load = useCallback( - (data: any) => { - // Reset the ArrayFieldTemplate whenever you load new data - const { templates = {}, extraErrors, liveSettings } = data; - // uiSchema is missing on some examples. Provide a default to - // clear the field in all cases. - const { schema, uiSchema = {}, formData, theme: dataTheme = theme } = data; + (data: Sample & { theme: string; liveSettings: LiveSettings }) => { + const { + schema, + // uiSchema is missing on some examples. Provide a default to + // clear the field in all cases. + uiSchema = {}, + // Always reset templates and fields + templates = {}, + fields = {}, + formData, + theme: dataTheme = theme, + extraErrors, + liveSettings, + ...rest + } = data; onThemeSelected(dataTheme, themes[dataTheme]); @@ -70,9 +80,9 @@ export default function Playground({ themes, validators }: PlaygroundProps) { setFormData(formData); setExtraErrors(extraErrors); setTheme(dataTheme); - setTemplates(templates); setShowForm(true); setLiveSettings(liveSettings); + setOtherFormProps({ fields, templates, ...rest }); }, [theme, onThemeSelected, themes] ); @@ -166,8 +176,8 @@ export default function Playground({ themes, validators }: PlaygroundProps) { theme={theme} > ; diff --git a/packages/playground/src/samples/additionalProperties.ts b/packages/playground/src/samples/additionalProperties.ts index 6da539f47c..fd173b48c3 100644 --- a/packages/playground/src/samples/additionalProperties.ts +++ b/packages/playground/src/samples/additionalProperties.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const additionalProperties: Sample = { schema: { title: 'A customizable registration form', description: 'A simple form with additional properties example.', @@ -30,3 +32,5 @@ export default { assKickCount: 'infinity', }, }; + +export default additionalProperties; diff --git a/packages/playground/src/samples/allOf.ts b/packages/playground/src/samples/allOf.ts index e8a8ffaf19..23c11e1b4b 100644 --- a/packages/playground/src/samples/allOf.ts +++ b/packages/playground/src/samples/allOf.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const allOf: Sample = { schema: { type: 'object', allOf: [ @@ -24,3 +26,5 @@ export default { }, formData: {}, }; + +export default allOf; diff --git a/packages/playground/src/samples/alternatives.ts b/packages/playground/src/samples/alternatives.ts index d10e6bf373..36d42f5e9c 100644 --- a/packages/playground/src/samples/alternatives.ts +++ b/packages/playground/src/samples/alternatives.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const alternatives: Sample = { schema: { definitions: { Color: { @@ -90,3 +92,5 @@ export default { blendMode: 'screen', }, }; + +export default alternatives; diff --git a/packages/playground/src/samples/anyOf.ts b/packages/playground/src/samples/anyOf.ts index b3d6786199..40c41b9da4 100644 --- a/packages/playground/src/samples/anyOf.ts +++ b/packages/playground/src/samples/anyOf.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const anyOf: Sample = { schema: { type: 'object', properties: { @@ -57,3 +59,5 @@ export default { }, formData: {}, }; + +export default anyOf; diff --git a/packages/playground/src/samples/arrays.ts b/packages/playground/src/samples/arrays.ts index 32e65da863..2f06d98007 100644 --- a/packages/playground/src/samples/arrays.ts +++ b/packages/playground/src/samples/arrays.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const arrays: Sample = { schema: { definitions: { Thing: { @@ -189,3 +191,5 @@ export default { fixedNoToolbar: [42, true, 'additional item one', 'additional item two'], }, }; + +export default arrays; diff --git a/packages/playground/src/samples/custom.ts b/packages/playground/src/samples/custom.ts index 939fa4ab77..48320a60d6 100644 --- a/packages/playground/src/samples/custom.ts +++ b/packages/playground/src/samples/custom.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const custom: Sample = { schema: { title: 'A localisation form', type: 'object', @@ -20,3 +22,5 @@ export default { lon: 0, }, }; + +export default custom; diff --git a/packages/playground/src/samples/customArray.tsx b/packages/playground/src/samples/customArray.tsx index 26dad35646..ca4297c630 100644 --- a/packages/playground/src/samples/customArray.tsx +++ b/packages/playground/src/samples/customArray.tsx @@ -1,9 +1,8 @@ -const ArrayFieldTemplate: React.FC<{ className: string; items?: any[]; canAdd?: boolean; onAddClick: () => void }> = ({ - className, - items, - canAdd, - onAddClick, -}) => { +import { Sample } from './Sample'; +import { ArrayFieldTemplateProps } from '@rjsf/utils'; + +function ArrayFieldTemplate(props: ArrayFieldTemplateProps) { + const { className, items, canAdd, onAddClick } = props; return (
{items && @@ -32,9 +31,9 @@ const ArrayFieldTemplate: React.FC<{ className: string; items?: any[]; canAdd?: )}
); -}; +} -export default { +export const customArray: Sample = { schema: { title: 'Custom array of strings', type: 'array', @@ -45,3 +44,5 @@ export default { formData: ['react', 'jsonschema', 'form'], templates: { ArrayFieldTemplate }, }; + +export default customArray; diff --git a/packages/playground/src/samples/customField.ts b/packages/playground/src/samples/customField.ts index 40c07fb9b2..e2eea973f1 100644 --- a/packages/playground/src/samples/customField.ts +++ b/packages/playground/src/samples/customField.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const customField: Sample = { schema: { title: 'A registration form', description: 'A custom-field form example.', @@ -26,3 +28,5 @@ export default { mySpecialStringField: 'special-text', }, }; + +export default customField; diff --git a/packages/playground/src/samples/customFieldAnyOf.tsx b/packages/playground/src/samples/customFieldAnyOf.tsx index 2211246fbe..42f4e07a3c 100644 --- a/packages/playground/src/samples/customFieldAnyOf.tsx +++ b/packages/playground/src/samples/customFieldAnyOf.tsx @@ -1,10 +1,12 @@ -const UiField: React.FC<{ - schema?: any; - idSchema: { $id: string }; - formData?: any; - onChange: (...args: any[]) => void; - [key: string]: any; -}> = ({ idSchema: { $id }, formData, onChange }) => { +import { Sample } from './Sample'; +import { FieldProps } from '@rjsf/utils'; + +function UiField(props: FieldProps) { + const { + idSchema: { $id }, + formData, + onChange, + } = props; const changeHandlerFactory = (fieldName: string) => (event: any) => { onChange(formData ? { ...formData, [fieldName]: event.target.value } : { [fieldName]: event.target.value }); }; @@ -71,9 +73,9 @@ const UiField: React.FC<{ ); -}; +} -export default { +const customFieldAnyOf: Sample = { schema: { title: 'Location', type: 'object', @@ -106,3 +108,5 @@ export default { }, formData: {}, }; + +export default customFieldAnyOf; diff --git a/packages/playground/src/samples/customObject.tsx b/packages/playground/src/samples/customObject.tsx index fcd420d4f0..3dd95121c0 100644 --- a/packages/playground/src/samples/customObject.tsx +++ b/packages/playground/src/samples/customObject.tsx @@ -6,7 +6,9 @@ import { RJSFSchema, FormContextType, ObjectFieldTemplateProps, + ObjectFieldTemplatePropertyType, } from '@rjsf/utils'; +import { Sample } from './Sample'; function ObjectFieldTemplate( props: ObjectFieldTemplateProps @@ -28,7 +30,7 @@ function ObjectFieldTemplate - {properties.map((prop) => ( + {properties.map((prop: ObjectFieldTemplatePropertyType) => (
{prop.content}
@@ -38,7 +40,7 @@ function ObjectFieldTemplate = { Blank: { schema: {}, uiSchema: {}, formData: {} }, Simple: simple, 'UI Options': options, @@ -67,6 +69,6 @@ export const samples = Object.freeze({ ErrorSchema: errorSchema, Defaults: defaults, 'Custom Field': customField, -} as const); +}; -export type Sample = keyof typeof samples; +export const samples = deepFreeze(_samples); diff --git a/packages/playground/src/samples/large.ts b/packages/playground/src/samples/large.ts index 87b984d0f6..ebceccae6c 100644 --- a/packages/playground/src/samples/large.ts +++ b/packages/playground/src/samples/large.ts @@ -1,3 +1,5 @@ +import { Sample } from './Sample'; + function largeEnum(n: number) { const list = []; for (let i = 0; i < n; i++) { @@ -6,7 +8,7 @@ function largeEnum(n: number) { return list; } -export default { +const large: Sample = { schema: { definitions: { largeEnum: { type: 'string', enum: largeEnum(100) }, @@ -37,3 +39,5 @@ export default { }, formData: {}, }; + +export default large; diff --git a/packages/playground/src/samples/nested.ts b/packages/playground/src/samples/nested.ts index 1c72d254f1..cc534942ec 100644 --- a/packages/playground/src/samples/nested.ts +++ b/packages/playground/src/samples/nested.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const nested: Sample = { schema: { title: 'A list of tasks', type: 'object', @@ -62,3 +64,5 @@ export default { ], }, }; + +export default nested; diff --git a/packages/playground/src/samples/null.ts b/packages/playground/src/samples/null.ts index 7f0d891214..61ca768a65 100644 --- a/packages/playground/src/samples/null.ts +++ b/packages/playground/src/samples/null.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const nullField: Sample = { schema: { title: 'Null field example', description: 'A short form with a null field', @@ -25,3 +27,5 @@ export default { }, formData: {}, }; + +export default nullField; diff --git a/packages/playground/src/samples/nullable.ts b/packages/playground/src/samples/nullable.ts index 66663fee91..d11409ee32 100644 --- a/packages/playground/src/samples/nullable.ts +++ b/packages/playground/src/samples/nullable.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const nullable: Sample = { schema: { title: 'A registration form (nullable)', description: 'A simple form example using nullable types', @@ -70,3 +72,5 @@ export default { password: 'noneed', }, }; + +export default nullable; diff --git a/packages/playground/src/samples/numbers.ts b/packages/playground/src/samples/numbers.ts index 449c513b2e..f7dc479779 100644 --- a/packages/playground/src/samples/numbers.ts +++ b/packages/playground/src/samples/numbers.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const numbers: Sample = { schema: { type: 'object', title: 'Number fields & widgets', @@ -61,3 +63,5 @@ export default { integerRangeSteps: 80, }, }; + +export default numbers; diff --git a/packages/playground/src/samples/oneOf.ts b/packages/playground/src/samples/oneOf.ts index e3cffc32b2..fc1091a241 100644 --- a/packages/playground/src/samples/oneOf.ts +++ b/packages/playground/src/samples/oneOf.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const oneOf: Sample = { schema: { type: 'object', oneOf: [ @@ -22,3 +24,5 @@ export default { }, formData: {}, }; + +export default oneOf; diff --git a/packages/playground/src/samples/options.ts b/packages/playground/src/samples/options.ts index 452610db8c..566636c00a 100644 --- a/packages/playground/src/samples/options.ts +++ b/packages/playground/src/samples/options.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const optionsSample: Sample = { schema: { title: 'A registration form', description: 'A simple form example. Demonstrating ui options', @@ -68,3 +70,5 @@ export default { password: 'noneed', }, }; + +export default optionsSample; diff --git a/packages/playground/src/samples/ordering.ts b/packages/playground/src/samples/ordering.ts index 096b4def1f..655e162217 100644 --- a/packages/playground/src/samples/ordering.ts +++ b/packages/playground/src/samples/ordering.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const ordering: Sample = { schema: { title: 'A registration form', type: 'object', @@ -46,3 +48,5 @@ export default { password: 'noneed', }, }; + +export default ordering; diff --git a/packages/playground/src/samples/propertyDependencies.ts b/packages/playground/src/samples/propertyDependencies.ts index b1136b07ca..de175b2566 100644 --- a/packages/playground/src/samples/propertyDependencies.ts +++ b/packages/playground/src/samples/propertyDependencies.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const propertyDependencies: Sample = { schema: { title: 'Property dependencies', description: 'These samples are best viewed without live validation.', @@ -6,7 +8,6 @@ export default { properties: { unidirectional: { title: 'Unidirectional', - src: 'https://spacetelescope.github.io/understanding-json-schema/reference/object.html#dependencies', type: 'object', properties: { name: { @@ -26,7 +27,6 @@ export default { }, bidirectional: { title: 'Bidirectional', - src: 'https://spacetelescope.github.io/understanding-json-schema/reference/object.html#dependencies', description: 'Dependencies are not bidirectional, you can, of course, define the bidirectional dependencies explicitly.', type: 'object', @@ -55,7 +55,7 @@ export default { 'ui:help': 'If you enter anything here then billing_address will become required.', }, billing_address: { - 'ui:help': 'It’s okay to have a billing address without a credit card number.', + 'ui:help': "It's okay to have a billing address without a credit card number.", }, }, bidirectional: { @@ -76,3 +76,5 @@ export default { }, }, }; + +export default propertyDependencies; diff --git a/packages/playground/src/samples/references.ts b/packages/playground/src/samples/references.ts index 429407e7ec..c05ceac622 100644 --- a/packages/playground/src/samples/references.ts +++ b/packages/playground/src/samples/references.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const references: Sample = { schema: { definitions: { address: { @@ -59,3 +61,5 @@ export default { }, }, }; + +export default references; diff --git a/packages/playground/src/samples/schemaDependencies.ts b/packages/playground/src/samples/schemaDependencies.ts index 3af80c6980..b9ddea7005 100644 --- a/packages/playground/src/samples/schemaDependencies.ts +++ b/packages/playground/src/samples/schemaDependencies.ts @@ -1,11 +1,12 @@ -export default { +import { Sample } from './Sample'; + +const schemaDependencies: Sample = { schema: { title: 'Schema dependencies', description: 'These samples are best viewed without live validation.', type: 'object', properties: { simple: { - src: 'https://spacetelescope.github.io/understanding-json-schema/reference/object.html#dependencies', title: 'Simple', type: 'object', properties: { @@ -167,3 +168,5 @@ export default { ], }, }; + +export default schemaDependencies; diff --git a/packages/playground/src/samples/simple.ts b/packages/playground/src/samples/simple.ts index 4efa351a68..dace4ac6ee 100644 --- a/packages/playground/src/samples/simple.ts +++ b/packages/playground/src/samples/simple.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const simple: Sample = { schema: { title: 'A registration form', description: 'A simple form example.', @@ -76,3 +78,5 @@ export default { telephone: '1-800-KICKASS', }, }; + +export default simple; diff --git a/packages/playground/src/samples/single.ts b/packages/playground/src/samples/single.ts index 3f3b020746..0a28405cab 100644 --- a/packages/playground/src/samples/single.ts +++ b/packages/playground/src/samples/single.ts @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const single: Sample = { schema: { title: 'A single-field form', type: 'string', @@ -6,3 +8,5 @@ export default { formData: 'initial value', uiSchema: {}, }; + +export default single; diff --git a/packages/playground/src/samples/validation.ts b/packages/playground/src/samples/validation.ts index 2c897f56a8..adfd06b020 100644 --- a/packages/playground/src/samples/validation.ts +++ b/packages/playground/src/samples/validation.ts @@ -1,25 +1,29 @@ -function validate({ pass1, pass2 }: { pass1: string; pass2: string }, errors: any) { +import { Sample } from './Sample'; +import { ErrorTransformer } from '@rjsf/utils'; + +function customValidate({ pass1, pass2 }: { pass1: string; pass2: string }, errors: any) { if (pass1 !== pass2) { errors.pass2.addError("Passwords don't match."); } return errors; } -function transformErrors(errors: { name: string; property: string }[]) { +const transformErrors: ErrorTransformer = (errors) => { return errors.map((error) => { - if (error.name === 'minimum' && error.property === 'instance.age') { + if (error.name === 'minimum' && error.schemaPath === '#/properties/age/minimum') { return Object.assign({}, error, { message: 'You need to be 18 because of some legal thing', }); } return error; }); -} +}; -export default { +const validation: Sample = { schema: { title: 'Custom validation', - description: 'This form defines custom validation rules checking that the two passwords match.', + description: + 'This form defines custom validation rules checking that the two passwords match. There is also a custom validation message when submitting an age < 18, which can only be seen if HTML5 validation is turned off.', type: 'object', properties: { pass1: { @@ -44,6 +48,8 @@ export default { pass2: { 'ui:widget': 'password' }, }, formData: {}, - validate, + customValidate, transformErrors, }; + +export default validation; diff --git a/packages/playground/src/samples/widgets.tsx b/packages/playground/src/samples/widgets.tsx index 663a9ecffd..a93b2362a5 100644 --- a/packages/playground/src/samples/widgets.tsx +++ b/packages/playground/src/samples/widgets.tsx @@ -1,4 +1,6 @@ -export default { +import { Sample } from './Sample'; + +const widgets: Sample = { schema: { title: 'Widgets', type: 'object', @@ -212,3 +214,5 @@ export default { secret: "I'm a hidden string.", }, }; + +export default widgets; diff --git a/packages/utils/src/schema/getDefaultFormState.ts b/packages/utils/src/schema/getDefaultFormState.ts index de7402dd8e..d7a45239ca 100644 --- a/packages/utils/src/schema/getDefaultFormState.ts +++ b/packages/utils/src/schema/getDefaultFormState.ts @@ -307,7 +307,7 @@ export function computeDefaults( objectDefaults as GenericObjectType, key,