diff --git a/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx b/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx
index ca7bef6c..ff845387 100644
--- a/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx
+++ b/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx
@@ -21,181 +21,193 @@ import {
JSONSchemaCyclesContext,
} from "../../context"
-const JSONSchema = forwardRef(({ schema, name, 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 isCircular = useIsCircular(schema)
- const renderedSchemas = useRenderedSchemas(schema)
- const constraints = fn.stringifyConstraints(schema)
- const Accordion = useComponent("Accordion")
- const Keyword$schema = useComponent("Keyword$schema")
- const Keyword$vocabulary = useComponent("Keyword$vocabulary")
- const Keyword$id = useComponent("Keyword$id")
- const Keyword$anchor = useComponent("Keyword$anchor")
- const Keyword$dynamicAnchor = useComponent("Keyword$dynamicAnchor")
- const Keyword$ref = useComponent("Keyword$ref")
- const Keyword$dynamicRef = useComponent("Keyword$dynamicRef")
- const Keyword$defs = useComponent("Keyword$defs")
- const Keyword$comment = useComponent("Keyword$comment")
- const KeywordAllOf = useComponent("KeywordAllOf")
- const KeywordAnyOf = useComponent("KeywordAnyOf")
- const KeywordOneOf = useComponent("KeywordOneOf")
- const KeywordNot = useComponent("KeywordNot")
- const KeywordIf = useComponent("KeywordIf")
- const KeywordThen = useComponent("KeywordThen")
- const KeywordElse = useComponent("KeywordElse")
- const KeywordDependentSchemas = useComponent("KeywordDependentSchemas")
- const KeywordPrefixItems = useComponent("KeywordPrefixItems")
- const KeywordItems = useComponent("KeywordItems")
- const KeywordContains = useComponent("KeywordContains")
- const KeywordProperties = useComponent("KeywordProperties")
- const KeywordPatternProperties = useComponent("KeywordPatternProperties")
- const KeywordAdditionalProperties = useComponent(
- "KeywordAdditionalProperties"
- )
- const KeywordPropertyNames = useComponent("KeywordPropertyNames")
- const KeywordUnevaluatedItems = useComponent("KeywordUnevaluatedItems")
- const KeywordUnevaluatedProperties = useComponent(
- "KeywordUnevaluatedProperties"
- )
- const KeywordType = useComponent("KeywordType")
- const KeywordEnum = useComponent("KeywordEnum")
- const KeywordConst = useComponent("KeywordConst")
- const KeywordConstraint = useComponent("KeywordConstraint")
- const KeywordFormat = useComponent("KeywordFormat")
- const KeywordTitle = useComponent("KeywordTitle")
- const KeywordDescription = useComponent("KeywordDescription")
- const ExpandDeepButton = useComponent("ExpandDeepButton")
+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) || dependentRequired.length > 0
+ const isCircular = useIsCircular(schema)
+ const renderedSchemas = useRenderedSchemas(schema)
+ const constraints = fn.stringifyConstraints(schema)
+ const Accordion = useComponent("Accordion")
+ const Keyword$schema = useComponent("Keyword$schema")
+ const Keyword$vocabulary = useComponent("Keyword$vocabulary")
+ const Keyword$id = useComponent("Keyword$id")
+ const Keyword$anchor = useComponent("Keyword$anchor")
+ const Keyword$dynamicAnchor = useComponent("Keyword$dynamicAnchor")
+ const Keyword$ref = useComponent("Keyword$ref")
+ const Keyword$dynamicRef = useComponent("Keyword$dynamicRef")
+ const Keyword$defs = useComponent("Keyword$defs")
+ const Keyword$comment = useComponent("Keyword$comment")
+ const KeywordAllOf = useComponent("KeywordAllOf")
+ const KeywordAnyOf = useComponent("KeywordAnyOf")
+ const KeywordOneOf = useComponent("KeywordOneOf")
+ const KeywordNot = useComponent("KeywordNot")
+ const KeywordIf = useComponent("KeywordIf")
+ const KeywordThen = useComponent("KeywordThen")
+ const KeywordElse = useComponent("KeywordElse")
+ const KeywordDependentSchemas = useComponent("KeywordDependentSchemas")
+ const KeywordPrefixItems = useComponent("KeywordPrefixItems")
+ const KeywordItems = useComponent("KeywordItems")
+ const KeywordContains = useComponent("KeywordContains")
+ const KeywordProperties = useComponent("KeywordProperties")
+ const KeywordPatternProperties = useComponent("KeywordPatternProperties")
+ const KeywordAdditionalProperties = useComponent(
+ "KeywordAdditionalProperties"
+ )
+ const KeywordPropertyNames = useComponent("KeywordPropertyNames")
+ const KeywordUnevaluatedItems = useComponent("KeywordUnevaluatedItems")
+ const KeywordUnevaluatedProperties = useComponent(
+ "KeywordUnevaluatedProperties"
+ )
+ const KeywordType = useComponent("KeywordType")
+ 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")
+ const ExpandDeepButton = useComponent("ExpandDeepButton")
- /**
- * Effects handlers.
- */
- useEffect(() => {
- setExpandedDeeply(isExpandedDeeply)
- }, [isExpandedDeeply])
+ /**
+ * Effects handlers.
+ */
+ useEffect(() => {
+ setExpandedDeeply(isExpandedDeeply)
+ }, [isExpandedDeeply])
- useEffect(() => {
- setExpandedDeeply(expandedDeeply)
- }, [expandedDeeply])
+ useEffect(() => {
+ setExpandedDeeply(expandedDeeply)
+ }, [expandedDeeply])
- /**
- * Event handlers.
- */
- const handleExpansion = useCallback(
- (e, expandedNew) => {
- setExpanded(expandedNew)
- !expandedNew && setExpandedDeeply(false)
- onExpand(e, expandedNew, false)
- },
- [onExpand]
- )
- const handleExpansionDeep = useCallback(
- (e, expandedDeepNew) => {
- setExpanded(expandedDeepNew)
- setExpandedDeeply(expandedDeepNew)
- onExpand(e, expandedDeepNew, true)
- },
- [onExpand]
- )
+ /**
+ * Event handlers.
+ */
+ const handleExpansion = useCallback(
+ (e, expandedNew) => {
+ setExpanded(expandedNew)
+ !expandedNew && setExpandedDeeply(false)
+ onExpand(e, expandedNew, false)
+ },
+ [onExpand]
+ )
+ const handleExpansionDeep = useCallback(
+ (e, expandedDeepNew) => {
+ setExpanded(expandedDeepNew)
+ setExpandedDeeply(expandedDeepNew)
+ onExpand(e, expandedDeepNew, true)
+ },
+ [onExpand]
+ )
- return (
-
-
-
-
-
- {isExpandable && !isCircular ? (
- <>
-
-
-
-
- >
- ) : (
-
- )}
-
-
- {constraints.length > 0 &&
- constraints.map((constraint) => (
-
- ))}
-
-
+
+
+
- {expanded && (
- <>
-
- {!isCircular && isExpandable && (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- )}
-
-
-
-
-
-
-
-
- {!isCircular && isExpandable && (
-
- )}
-
-
- >
- )}
-
-
-
-
-
- )
-})
+
+ {isExpandable && !isCircular ? (
+ <>
+
+
+
+
+ >
+ ) : (
+
+ )}
+
+
+ {constraints.length > 0 &&
+ constraints.map((constraint) => (
+
+ ))}
+
+
+ {expanded && (
+ <>
+
+ {!isCircular && isExpandable && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+
+
+
+
+ {!isCircular && isExpandable && (
+
+ )}
+
+
+ >
+ )}
+
+
+
+
+
+ )
+ }
+)
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: () => {},
}
diff --git a/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/DependentRequired.jsx b/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/DependentRequired.jsx
new file mode 100644
index 00000000..dcea3f2d
--- /dev/null
+++ b/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/DependentRequired.jsx
@@ -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 (
+
+
+ Required when defined
+
+
+ {dependentRequired.map((propertyName) => (
+ -
+
+ {propertyName}
+
+
+ ))}
+
+
+ )
+}
+
+DependentRequired.propTypes = {
+ schema: propTypes.schema.isRequired,
+ dependentRequired: PropTypes.arrayOf(PropTypes.string).isRequired,
+}
+
+export default DependentRequired
diff --git a/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/_dependent-required.scss b/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/_dependent-required.scss
new file mode 100644
index 00000000..3ad27aa4
--- /dev/null
+++ b/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/_dependent-required.scss
@@ -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;
+ }
+ }
+}
diff --git a/src/core/plugins/json-schema-2020-12/components/keywords/Properties/Properties.jsx b/src/core/plugins/json-schema-2020-12/components/keywords/Properties/Properties.jsx
index 457539c0..678f7a67 100644
--- a/src/core/plugins/json-schema-2020-12/components/keywords/Properties/Properties.jsx
+++ b/src/core/plugins/json-schema-2020-12/components/keywords/Properties/Properties.jsx
@@ -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 (
- {Object.entries(properties).map(([propertyName, schema]) => (
- -
-
-
- ))}
+ {Object.entries(properties).map(([propertyName, propertySchema]) => {
+ const isRequired = required.includes(propertyName)
+ const dependentRequired = fn.getDependentRequired(
+ propertyName,
+ schema
+ )
+
+ return (
+ -
+
+
+ )
+ })}
)
diff --git a/src/core/plugins/json-schema-2020-12/components/keywords/Properties/_properties.scss b/src/core/plugins/json-schema-2020-12/components/keywords/Properties/_properties.scss
index d6eceb89..0797b94e 100644
--- a/src/core/plugins/json-schema-2020-12/components/keywords/Properties/_properties.scss
+++ b/src/core/plugins/json-schema-2020-12/components/keywords/Properties/_properties.scss
@@ -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;
diff --git a/src/core/plugins/json-schema-2020-12/components/keywords/_all.scss b/src/core/plugins/json-schema-2020-12/components/keywords/_all.scss
index ed0c6b0c..18859905 100644
--- a/src/core/plugins/json-schema-2020-12/components/keywords/_all.scss
+++ b/src/core/plugins/json-schema-2020-12/components/keywords/_all.scss
@@ -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';
diff --git a/src/core/plugins/json-schema-2020-12/fn.js b/src/core/plugins/json-schema-2020-12/fn.js
index 1cacd3c3..1c23af37 100644
--- a/src/core/plugins/json-schema-2020-12/fn.js
+++ b/src/core/plugins/json-schema-2020-12/fn.js
@@ -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())
+ )
+}
diff --git a/src/core/plugins/json-schema-2020-12/hoc.jsx b/src/core/plugins/json-schema-2020-12/hoc.jsx
index 3ee0b93e..65af863a 100644
--- a/src/core/plugins/json-schema-2020-12/hoc.jsx
+++ b/src/core/plugins/json-schema-2020-12/hoc.jsx
@@ -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,
},
}
diff --git a/src/core/plugins/json-schema-2020-12/index.js b/src/core/plugins/json-schema-2020-12/index.js
index 1b0658a4..bcb0b0be 100644
--- a/src/core/plugins/json-schema-2020-12/index.js
+++ b/src/core/plugins/json-schema-2020-12/index.js
@@ -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,
diff --git a/src/core/plugins/oas31/wrap-components/models.jsx b/src/core/plugins/oas31/wrap-components/models.jsx
index 8c2314e6..9c5ec2dc 100644
--- a/src/core/plugins/oas31/wrap-components/models.jsx
+++ b/src/core/plugins/oas31/wrap-components/models.jsx
@@ -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,