Skip to content

Commit

Permalink
feat(json-schema-2020-12): add support for expandable behavior
Browse files Browse the repository at this point in the history
Refs #8513
  • Loading branch information
char0n committed Apr 14, 2023
1 parent c5ac88f commit 962abd5
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ const Accordion = ({ expanded, children, onChange }) => {
return (
<button className="json-schema-2020-12-accordion" onClick={handleExpansion}>
<div className="json-schema-2020-12-accordion__children">{children}</div>
<div
<span
className={classNames("json-schema-2020-12-accordion__icon", {
"json-schema-2020-12-accordion__icon--expanded": expanded,
"json-schema-2020-12-accordion__icon--collapsed": !expanded,
})}
>
<ChevronRightIcon />
</div>
</span>
</button>
)
}

Accordion.propTypes = {
expanded: PropTypes.bool,
children: PropTypes.node.isRequired,
onClick: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
}

Accordion.defaultProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
.json-schema-2020-12-accordion {
outline: none;
border: none;
display: flex;
align-items: center;
padding-left: 0;

&__children {
display: inline-block;
}

&__icon {
width: 20px;
height: 20px;
width: 18px;
height: 18px;
display: inline-block;
vertical-align: center;
vertical-align: bottom;

&--expanded {
transition: transform .15s ease-in;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
*/
import React, { useState, useCallback } from "react"
import PropTypes from "prop-types"
import classNames from "classnames"

import * as propTypes from "../../prop-types"
import { useComponent, useFn } from "../../hooks"
import { useComponent, useFn, useLevel, useIsEmbedded } from "../../hooks"
import { JSONSchemaLevelContext } from "../../context"

const JSONSchema = ({ schema, name }) => {
const [expanded, setExpanded] = useState(false)

const fn = useFn()
const [level, nextLevel] = useLevel()
const isEmbedded = useIsEmbedded()
const BooleanJSONSchema = useComponent("BooleanJSONSchema")
const Accordion = useComponent("Accordion")
const KeywordProperties = useComponent("KeywordProperties")

const handleExpansion = useCallback(() => {
setExpanded((prev) => !prev)
Expand All @@ -23,76 +28,27 @@ const JSONSchema = ({ schema, name }) => {
}

return (
<article className="json-schema-2020-12">
<div className="json-schema-2020-12-head">
<Accordion expanded={expanded} onChange={handleExpansion}>
<div className="json-schema-2020-12__title">
{name || fn.getTitle(schema)}
</div>
</Accordion>
</div>
{expanded && (
<div className="json-schema-2020-12-body">
<div className="json-schema-2020-12-property">
<article className="json-schema-2020-12 json-schema-2020-12--embedded">
<div className="json-schema-2020-12-head">
<span className="json-schema-2020-12__title">property1</span>
<span className="json-schema-2020-12__type">Object</span>
<span className="json-schema-2020-12__format">int64</span>
<span className="json-schema-2020-12__limit">[0...100]</span>
<div className="json-schema-2020-12__description">
Whether to turn on or off the light.
</div>
</div>
<div className="json-schema-2020-12-body">
<div className="json-schema-2020-12-property">
<article className="json-schema-2020-12 json-schema-2020-12--embedded">
<div className="json-schema-2020-12-head">
<span className="json-schema-2020-12__title">
property11
</span>
<span className="json-schema-2020-12__type">Object</span>
</div>
</article>
</div>
<div className="json-schema-2020-12-property">
<article className="json-schema-2020-12 json-schema-2020-12--embedded">
<div className="json-schema-2020-12-head">
<span className="json-schema-2020-12__title">
property22
</span>
<span className="json-schema-2020-12__type">Object</span>
</div>
</article>
</div>
<div className="json-schema-2020-12-note">
Additional properties are allowed.
</div>
</div>
</article>
</div>
<div className="json-schema-2020-12-property">
<article className="json-schema-2020-12 json-schema-2020-12--embedded">
<div className="json-schema-2020-12-head">
<span className="json-schema-2020-12__title">property2</span>
<span className="json-schema-2020-12__type">Object</span>
</div>
</article>
</div>
<div className="json-schema-2020-12-property">
<article className="json-schema-2020-12 json-schema-2020-12--embedded">
<div className="json-schema-2020-12-head">
<span className="json-schema-2020-12__title">property3</span>
<span className="json-schema-2020-12__type">Object</span>
</div>
</article>
</div>
<div className="json-schema-2020-12-note">
Additional properties are allowed.
</div>
<JSONSchemaLevelContext.Provider value={nextLevel}>
<article
data-json-schema-level={level}
className={classNames("json-schema-2020-12", {
"json-schema-2020-12--embedded": isEmbedded,
})}
>
<div className="json-schema-2020-12-head">
<Accordion expanded={expanded} onChange={handleExpansion}>
<div className="json-schema-2020-12__title">
{name || fn.getTitle(schema)}
</div>
</Accordion>
</div>
)}
</article>
{expanded && (
<div className="json-schema-2020-12-body">
<KeywordProperties schema={schema} />
</div>
)}
</article>
</JSONSchemaLevelContext.Provider>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

&__title {
@include text_headline($section-models-model-title-font-color);
display: inline-block;
font-weight: bold;
}

Expand All @@ -31,8 +32,9 @@
margin: 7px 0;

.json-schema-2020-12__title {
font-size: 12px;
@include text_code();
font-size: 12px;
vertical-align: bottom;
}
}

Expand All @@ -42,7 +44,6 @@
font-size: 12px;
text-transform: capitalize;
font-weight: bold;
margin-left: 10px;

&:before {
content: "{";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* @prettier
*/
import React from "react"

import { schema } from "../../prop-types"
import { useFn, useComponent } from "../../hooks"

const Properties = ({ schema }) => {
const fn = useFn()
const JSONSchema = useComponent("JSONSchema")

if (fn.isBooleanJSONSchema(schema)) {
return null
}

const properties = schema.properties || {}

if (Object.keys(properties).length === 0) {
return null
}

return (
<>
{Object.entries(properties).map(([propertyName, propertyValue]) => (
<div key={propertyName} className="json-schema-2020-12-property">
<JSONSchema name={propertyName} schema={propertyValue} />
</div>
))}
</>
)
}

Properties.propTypes = {
schema: schema.isRequired,
}

export default Properties
3 changes: 2 additions & 1 deletion src/core/plugins/json-schema-2020-12/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import { createContext } from "react"
export const JSONSchemaContext = createContext(null)
JSONSchemaContext.displayName = "JSONSchemaContext"

export default JSONSchemaContext
export const JSONSchemaLevelContext = createContext(0)
JSONSchemaLevelContext.displayName = "JSONSchemaLevelContext"
4 changes: 3 additions & 1 deletion src/core/plugins/json-schema-2020-12/hoc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import React from "react"

import JSONSchema from "./components/JSONSchema/JSONSchema"
import BooleanJSONSchema from "./components/BooleanJSONSchema/BooleanJSONSchema"
import KeywordProperties from "./components/keywords/Properties"
import Accordion from "./components/Accordion/Accordion"
import ChevronRightIcon from "./components/icons/ChevronRight"
import JSONSchemaContext from "./context"
import { JSONSchemaContext } from "./context"
import { getTitle, isBooleanJSONSchema, upperFirst } from "./fn"

export const withJSONSchemaContext = (Component, overrides = {}) => {
const value = {
components: {
JSONSchema,
BooleanJSONSchema,
KeywordProperties,
Accordion,
ChevronRightIcon,
...overrides.components,
Expand Down
14 changes: 13 additions & 1 deletion src/core/plugins/json-schema-2020-12/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import { useContext } from "react"

import JSONSchemaContext from "./context"
import { JSONSchemaContext, JSONSchemaLevelContext } from "./context"

export const useConfig = () => {
const { config } = useContext(JSONSchemaContext)
Expand All @@ -20,3 +20,15 @@ export const useFn = (fnName = undefined) => {

return typeof fnName !== "undefined" ? fn[fnName] : fn
}

export const useLevel = () => {
const level = useContext(JSONSchemaLevelContext)

return [level, level + 1]
}

export const useIsEmbedded = () => {
const [level] = useLevel()

return level > 0
}
2 changes: 2 additions & 0 deletions src/core/plugins/json-schema-2020-12/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import JSONSchema from "./components/JSONSchema/JSONSchema"
import BooleanJSONSchema from "./components/BooleanJSONSchema/BooleanJSONSchema"
import JSONSchemaKeywordProperties from "./components/keywords/Properties"
import Accordion from "./components/Accordion/Accordion"
import ChevronRightIcon from "./components/icons/ChevronRight"
import { upperFirst } from "./fn"
Expand All @@ -12,6 +13,7 @@ const JSONSchema202012Plugin = () => ({
components: {
JSONSchema202012: JSONSchema,
BooleanJSONSchema202012: BooleanJSONSchema,
JSONSchema202012KeywordProperties: JSONSchemaKeywordProperties,
JSONSchema202012Accordion: Accordion,
JSONSchema202012ChevronRightIcon: ChevronRightIcon,
withJSONSchema202012Context: withJSONSchemaContext,
Expand Down
2 changes: 2 additions & 0 deletions src/core/plugins/oas31/wrap-components/models.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const ModelsWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => {
const Models = getComponent("OAS31Models", true)
const JSONSchema = getComponent("JSONSchema202012")
const BooleanJSONSchema = getComponent("BooleanJSONSchema202012")
const KeywordProperties = getComponent("JSONSchema202012KeywordProperties")
const Accordion = getComponent("JSONSchema202012Accordion")
const ChevronRightIcon = getComponent("JSONSchema202012ChevronRightIcon")
const withSchemaContext = getComponent("withJSONSchema202012Context")
Expand All @@ -20,6 +21,7 @@ const ModelsWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => {
components: {
JSONSchema,
BooleanJSONSchema,
KeywordProperties,
Accordion,
ChevronRightIcon,
},
Expand Down

0 comments on commit 962abd5

Please sign in to comment.