@kelmscott/forme v0.1.1
@kelmscott/forme
A configurable React factory component for generating a component tree from a JSON specification.
Install
$ npm i @kelmscott/formeUsage
import forme from '@kelmscott/forme'Configuration Map
Forme uses a simple configuration map to resolve any components referenced in the JSON specification.
const Card = (props) => (
<div className="card" {...props} />
)
const CardImg = (props) => (
<img className="cardImg" {...props} />
)
const configMap = {
card: Card,
img: CardImg,
}Component Specification
The JSON specification would be:
const spec = [
{
component: "card",
children: [
{
component: "img",
src:
"https://images.pexels.com/photos/2877188.jpeg"
}
]
}
]Using Forme to render a React component tree:
const renderer = forme(configMap)
renderer(spec)
// returns ...
///
// <Fragment>
// <Card>
// <CardImg src="https://images.pexels.com/photos/2877188.jpeg" />
// </CardImg>
// </Fragment>The component specification is a simple JSON tree.
Root element
The root of the specification must be an array, containing zero or more objects.
Component key
Each object must contain a component key with a value that corresponds to a component key specified in the configuration map.
Children key
Each object may optionally specify children.
If children is an array, Forme assumes these are child components and recursively walks them, attempting to construct a Component from the configuration map for each.
Props
All other key/value pairs defined in the specification are treated as React props and passed as such, when Forme creates each Component.
Typical Usage
The typical use-case for Forme is with a static site generator, such as Next.js, Gatsby, Nuxt or VuePress.
The following example assumes Next.js.
// ./src/pages/index.js
import BodyContent from '../components/BodyContent'
const Page = ({ entry }) => {
const { heroImage, bodyContent } = entry
return (
<Fragment>
<div>
<h1>{entry.title}</h1>
<img src={heroImage.src} />
</div>
{/* Assume `bodyContent` is a JSON spec object
* generated via GraphQL from a headless CMS.*/}
<BodyContent>{bodyContent}</BodyContent>
</Fragment>
)
}<BodyContent> is a pre-configured instance of forme, wrapped as a reusable React component.
// ./src/components/BodyContent.js
import forme from '@kelmscott/forme'
import { Heading, Subheading, Text, Image, PullQuote } from '.'
const componentMap = {
heading: Heading,
subhead: Subheading,
text: Text,
image: Image,
pull-quote: PullQuote,
}
const renderer = forme(componentMap)
export default ({ children }) => renderer(children)5 years ago