JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4
  • Score
    100M100P100Q27048F
  • License MIT

Functionally create elements and compose them to a tree quickly

Package Exports

  • elementx

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (elementx) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

logo

npm version build status test coverage dependency status license js standard style downloads per month

โ€‹โšกโ€‹ Functionally create DOM elements and compose them quickly.

This module is an alternative to jsx or template strings for those who want to build up their DOM trees using plain function composition.

div([
  h1('.bold', 'elementx'),
  h2('#subtitle', 'Create a DOM tree with ease'),
  button({ href: 'http://ghub.io/elementx' }, 'Open'),
  ul(['simple', 'functional', 'fast'].map(key => li(key)))
])

Features

  • Supports creating SVG Elements
  • Convenient element event handling
  • Boolean attributes (like autofocus: true)
  • Pluggable API for hooking into specific attributes and modifying them
  • Functional utilities can be used since it's just function composition
  • Weights only ~3 kB minified and gzipped
  • Can be used with diffing libraries like morphdom or nanomorph for a unidirectional architecture

Installation

> npm install elementx

Usage

const { div, h1, a } = require('elementx')

const tree = div('.container.p2#js-root', [
  h1('.title', 'This is a title'),
  div({ style: 'background-color: red;' }, [
    a({ href: 'http://github.com' }, 'Github')
  ])
])

console.log(tree.outerHTML)
/*
 * ->
 * <div class="full-width p2">
 *   <h1>Some text</h1>
 *   <div style="background-color: red;">
 *     <a href="http://github.com">Github</a>
 *   </div>
 * </div>
 */

Getting Started

Each element in the DOM is exposed as a function when requiring elementx.

const { div, h1, p, button } = require('elementx')

These functions have the following syntax:

tag(selector, attributes, children)

All arguments are optional with at least one argument needing to be present. This kind of function overloading allows you to iterate on your DOM structure really fast and reduce visual noise.

  • selector can be .title to append a class or #id to give the element an id. These can be mixed as you might expect: #id.title.pad.red
  • attributes is an object of dom attributes: { href: '#header' }
  • children can be a string for a text node or an array of nodes

Lifecycle hooks

This module aims to be just the element creation layer. It can be used with any view framework using DOM as their base element abstraction for diffing. Some libraries like this include choo or inu.

SVG

SVG works as expected. Sets the appropriate namespace for both elements and attributes. All SVG tags can only be created with the h-helper:

const { svg, h } = require('elementx')

const node = svg({
  viewBox: '0 0 0 32 32',
  fill: 'currentColor',
  height: '32px',
  width: '32px'
}, [
  h('use', { 'xlink:href': '#my-id' })
])

document.body.appendChild(node)

Use without helper functions

Sometimes you need to fall back to the traditional createElement(tag, attributes, children) (aliased to h), for example svg tags.

const { h } = require('elementx')
// -> or { createElement }

const node = h('h1', 'text')

console.log(node.outerHTML)
/*
 * ->
 * <h1>text</h1>
 */

Events

All HTML DOM Events can be attached. The casing of the event name doesn't matter (onClick, onclick, ONCLICK etc.)

const node = button({ onClick: () => console.log('button has been clicked') })
document.body.appendChild(node)

Built-in Sugar

This module includes some sugar which is essential to most single page applications today. If you feel like they add to much weight, you can always opt-out and require elementx/decorate for the barebones implementation.

Classes

Conditionally joins class names together. It utilizes JedWatson's awesome classnames. Visit the usage docs for more information.

Inline styles

Converts style objects to an inline string. CSS declarations are written camelcased (text-decoration becomes textDecoration).

const style = {
  textDecoration: 'underline',
  fontSize: '56px'
}

const node = h1({ style }, 'hello!')
// -> <h1 style='text-decoration:underline;font-size:56px;'>hello!</h1>

Decorating attributes

To add custom behaviour to an attibute, you can create your own set of element functions using createElementx(decorator). decorator is a function which receives both the attributes key and value. You need to return a tuple of [key, val] in all cases.

Here for example we'll modify the attributes style property, stringifying each style object and keeping String values. Imagine toInlineStyle as a functions which does the convertion.

const { createElementx } = require('elementx')

// automatically inlines style objects. Make sure to return the original value
// if you don't modify anything.
const { h1, div } = createElementx((key, val) => {
  case 'style':
    return [
      key,
        typeof val !== 'string'
          ? toInlineStyle(val)
          : val
    ]
    default:
      return [key, val]
})

const render = ({ backgroundColor }) =>
  h1({ style: { color: 'red', backgroundColor } })

External tools

Tests

Tests are written using JSDOM.

> npm test

License

MIT