0.1.1 • Published 4 years ago

@kelmscott/forme v0.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
4 years ago

@kelmscott/forme

A configurable React factory component for generating a component tree from a JSON specification.

Install

$ npm i @kelmscott/forme

Usage

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)