feat(json-schema-2020-12): add support for dependentRequired keyword (#8633)
Refs #8513
This commit is contained in:
@@ -21,14 +21,15 @@ import {
|
||||
JSONSchemaCyclesContext,
|
||||
} from "../../context"
|
||||
|
||||
const JSONSchema = forwardRef(({ schema, name, onExpand }, ref) => {
|
||||
const JSONSchema = forwardRef(
|
||||
({ schema, name, dependentRequired, onExpand }, ref) => {
|
||||
const fn = useFn()
|
||||
const isExpandedDeeply = useIsExpandedDeeply()
|
||||
const [expanded, setExpanded] = useState(isExpandedDeeply)
|
||||
const [expandedDeeply, setExpandedDeeply] = useState(isExpandedDeeply)
|
||||
const [level, nextLevel] = useLevel()
|
||||
const isEmbedded = useIsEmbedded()
|
||||
const isExpandable = fn.isExpandable(schema)
|
||||
const isExpandable = fn.isExpandable(schema) || dependentRequired.length > 0
|
||||
const isCircular = useIsCircular(schema)
|
||||
const renderedSchemas = useRenderedSchemas(schema)
|
||||
const constraints = fn.stringifyConstraints(schema)
|
||||
@@ -67,6 +68,7 @@ const JSONSchema = forwardRef(({ schema, name, onExpand }, ref) => {
|
||||
const KeywordEnum = useComponent("KeywordEnum")
|
||||
const KeywordConst = useComponent("KeywordConst")
|
||||
const KeywordConstraint = useComponent("KeywordConstraint")
|
||||
const KeywordDependentRequired = useComponent("KeywordDependentRequired")
|
||||
const KeywordFormat = useComponent("KeywordFormat")
|
||||
const KeywordTitle = useComponent("KeywordTitle")
|
||||
const KeywordDescription = useComponent("KeywordDescription")
|
||||
@@ -133,7 +135,10 @@ const JSONSchema = forwardRef(({ schema, name, onExpand }, ref) => {
|
||||
<KeywordFormat schema={schema} />
|
||||
{constraints.length > 0 &&
|
||||
constraints.map((constraint) => (
|
||||
<KeywordConstraint key={constraint} constraint={constraint} />
|
||||
<KeywordConstraint
|
||||
key={constraint}
|
||||
constraint={constraint}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
@@ -167,6 +172,10 @@ const JSONSchema = forwardRef(({ schema, name, onExpand }, ref) => {
|
||||
)}
|
||||
<KeywordEnum schema={schema} />
|
||||
<KeywordConst schema={schema} />
|
||||
<KeywordDependentRequired
|
||||
schema={schema}
|
||||
dependentRequired={dependentRequired}
|
||||
/>
|
||||
<Keyword$schema schema={schema} />
|
||||
<Keyword$vocabulary schema={schema} />
|
||||
<Keyword$id schema={schema} />
|
||||
@@ -186,16 +195,19 @@ const JSONSchema = forwardRef(({ schema, name, onExpand }, ref) => {
|
||||
</JSONSchemaDeepExpansionContext.Provider>
|
||||
</JSONSchemaLevelContext.Provider>
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
JSONSchema.propTypes = {
|
||||
name: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
||||
schema: propTypes.schema.isRequired,
|
||||
dependentRequired: PropTypes.arrayOf(PropTypes.string),
|
||||
onExpand: PropTypes.func,
|
||||
}
|
||||
|
||||
JSONSchema.defaultProps = {
|
||||
name: "",
|
||||
dependentRequired: [],
|
||||
onExpand: () => {},
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @prettier
|
||||
*/
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
import * as propTypes from "../../../prop-types"
|
||||
|
||||
const DependentRequired = ({ dependentRequired }) => {
|
||||
if (dependentRequired.length === 0) return null
|
||||
|
||||
return (
|
||||
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--dependentRequired">
|
||||
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--primary">
|
||||
Required when defined
|
||||
</span>
|
||||
<ul>
|
||||
{dependentRequired.map((propertyName) => (
|
||||
<li key={propertyName}>
|
||||
<span className="json-schema-2020-12-keyword__value json-schema-2020-12-keyword__value--warning">
|
||||
{propertyName}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
DependentRequired.propTypes = {
|
||||
schema: propTypes.schema.isRequired,
|
||||
dependentRequired: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
}
|
||||
|
||||
export default DependentRequired
|
||||
@@ -0,0 +1,12 @@
|
||||
.json-schema-2020-12-keyword--dependentRequired {
|
||||
& > ul {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
display: inline;
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,10 @@ import React from "react"
|
||||
import classNames from "classnames"
|
||||
|
||||
import { schema } from "../../../prop-types"
|
||||
import { useComponent } from "../../../hooks"
|
||||
import { useFn, useComponent } from "../../../hooks"
|
||||
|
||||
const Properties = ({ schema }) => {
|
||||
const fn = useFn()
|
||||
const properties = schema?.properties || {}
|
||||
const required = Array.isArray(schema?.required) ? schema.required : []
|
||||
const JSONSchema = useComponent("JSONSchema")
|
||||
@@ -22,17 +23,28 @@ const Properties = ({ schema }) => {
|
||||
return (
|
||||
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--properties">
|
||||
<ul>
|
||||
{Object.entries(properties).map(([propertyName, schema]) => (
|
||||
{Object.entries(properties).map(([propertyName, propertySchema]) => {
|
||||
const isRequired = required.includes(propertyName)
|
||||
const dependentRequired = fn.getDependentRequired(
|
||||
propertyName,
|
||||
schema
|
||||
)
|
||||
|
||||
return (
|
||||
<li
|
||||
key={propertyName}
|
||||
className={classNames("json-schema-2020-12-property", {
|
||||
"json-schema-2020-12-property--required":
|
||||
required.includes(propertyName),
|
||||
"json-schema-2020-12-property--required": isRequired,
|
||||
})}
|
||||
>
|
||||
<JSONSchema name={propertyName} schema={schema} />
|
||||
<JSONSchema
|
||||
name={propertyName}
|
||||
schema={propertySchema}
|
||||
dependentRequired={dependentRequired}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
list-style-type: none;
|
||||
|
||||
&--required {
|
||||
.json-schema-2020-12__title:after {
|
||||
& > .json-schema-2020-12:first-of-type > .json-schema-2020-12-head .json-schema-2020-12__title:after {
|
||||
content: '*';
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -53,6 +53,12 @@
|
||||
border: 1px dashed #6b6b6b;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
@extend .json-schema-2020-12-keyword__value--const;
|
||||
color: red;
|
||||
border: 1px dashed red;
|
||||
}
|
||||
}
|
||||
}
|
||||
.json-schema-2020-12-keyword__name--secondary + .json-schema-2020-12-keyword__value--secondary::before {
|
||||
@@ -68,3 +74,4 @@
|
||||
@import './PatternProperties/pattern-properties';
|
||||
@import './Enum/enum';
|
||||
@import './Constraint/constraint';
|
||||
@import './DependentRequired/dependent-required';
|
||||
|
||||
@@ -294,3 +294,18 @@ export const stringifyConstraints = (schema) => {
|
||||
|
||||
return constraints
|
||||
}
|
||||
|
||||
export const getDependentRequired = (propertyName, schema) => {
|
||||
if (!schema?.dependentRequired) return []
|
||||
|
||||
return Array.from(
|
||||
Object.entries(schema.dependentRequired).reduce((acc, [prop, list]) => {
|
||||
if (!Array.isArray(list)) return acc
|
||||
if (!list.includes(propertyName)) return acc
|
||||
|
||||
acc.add(prop)
|
||||
|
||||
return acc
|
||||
}, new Set())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import KeywordType from "./components/keywords/Type/Type"
|
||||
import KeywordEnum from "./components/keywords/Enum/Enum"
|
||||
import KeywordConst from "./components/keywords/Const"
|
||||
import KeywordConstraint from "./components/keywords/Constraint/Constraint"
|
||||
import KeywordDependentRequired from "./components/keywords/DependentRequired/DependentRequired"
|
||||
import KeywordFormat from "./components/keywords/Format/Format"
|
||||
import KeywordTitle from "./components/keywords/Title/Title"
|
||||
import KeywordDescription from "./components/keywords/Description/Description"
|
||||
@@ -50,6 +51,7 @@ import {
|
||||
isExpandable,
|
||||
stringify,
|
||||
stringifyConstraints,
|
||||
getDependentRequired,
|
||||
} from "./fn"
|
||||
|
||||
export const withJSONSchemaContext = (Component, overrides = {}) => {
|
||||
@@ -86,6 +88,7 @@ export const withJSONSchemaContext = (Component, overrides = {}) => {
|
||||
KeywordEnum,
|
||||
KeywordConst,
|
||||
KeywordConstraint,
|
||||
KeywordDependentRequired,
|
||||
KeywordFormat,
|
||||
KeywordTitle,
|
||||
KeywordDescription,
|
||||
@@ -116,6 +119,7 @@ export const withJSONSchemaContext = (Component, overrides = {}) => {
|
||||
isExpandable,
|
||||
stringify,
|
||||
stringifyConstraints,
|
||||
getDependentRequired,
|
||||
...overrides.fn,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import KeywordType from "./components/keywords/Type/Type"
|
||||
import KeywordEnum from "./components/keywords/Enum/Enum"
|
||||
import KeywordConst from "./components/keywords/Const"
|
||||
import KeywordConstraint from "./components/keywords/Constraint/Constraint"
|
||||
import KeywordDependentRequired from "./components/keywords/DependentRequired/DependentRequired"
|
||||
import KeywordFormat from "./components/keywords/Format/Format"
|
||||
import KeywordTitle from "./components/keywords/Title/Title"
|
||||
import KeywordDescription from "./components/keywords/Description/Description"
|
||||
@@ -74,6 +75,7 @@ const JSONSchema202012Plugin = () => ({
|
||||
JSONSchema202012KeywordEnum: KeywordEnum,
|
||||
JSONSchema202012KeywordConst: KeywordConst,
|
||||
JSONSchema202012KeywordConstraint: KeywordConstraint,
|
||||
JSONSchema202012KeywordDependentRequired: KeywordDependentRequired,
|
||||
JSONSchema202012KeywordFormat: KeywordFormat,
|
||||
JSONSchema202012KeywordTitle: KeywordTitle,
|
||||
JSONSchema202012KeywordDescription: KeywordDescription,
|
||||
|
||||
@@ -59,6 +59,9 @@ const ModelsWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => {
|
||||
const KeywordEnum = getComponent("JSONSchema202012KeywordEnum")
|
||||
const KeywordConst = getComponent("JSONSchema202012KeywordConst")
|
||||
const KeywordConstraint = getComponent("JSONSchema202012KeywordConstraint")
|
||||
const KeywordDependentRequired = getComponent(
|
||||
"JSONSchema202012KeywordDependentRequired"
|
||||
)
|
||||
const KeywordFormat = getComponent("JSONSchema202012KeywordFormat")
|
||||
const KeywordTitle = getComponent("JSONSchema202012KeywordTitle")
|
||||
const KeywordDescription = getComponent(
|
||||
@@ -107,6 +110,7 @@ const ModelsWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => {
|
||||
KeywordEnum,
|
||||
KeywordConst,
|
||||
KeywordConstraint,
|
||||
KeywordDependentRequired,
|
||||
KeywordFormat,
|
||||
KeywordTitle,
|
||||
KeywordDescription,
|
||||
|
||||
Reference in New Issue
Block a user