Skip to content

geotrev/snabbdom-transform-jsx-props

Repository files navigation

♻ snabbdom-transform-jsx-props

Adds React-style prop support for Snabbdom JSX


Version License CI status bundle size dependency status

Install

NPM

$ npm i snabbdom snabbdom-transform-jsx-props

Usage

Add the jsxPropsModule export to Snabbdom's init function. It must be the first module as the JSX props will be forwarded to the appropriate Snabbdom module object.

import { classModule, styleModule } from "snabbdom"
import { jsxPropsModule } from "snabbdom-transform-jsx-props"

const patch = init([jsxPropsModule, classModule, styleModule])

The below example demonstrates the new JSX prop signature when using this module:

Vanilla JSX:

<div props={{ className: "my-component" }} hook={{ insert: () => {} }}>
  <h1 dataset={{ fooHeading: true }}>Hello world</h1>
  <p attrs={{ "aria-hidden": "true" }}>And good day</p>
  <a
    attrs={{ href: "#", style: "color: blue" }}
    props={{ tabIndex: 0 }}
    on={{ click: () => {} }}
  >
    Try me!
  </a>
</div>

With jsxPropsModule:

<div className="my-component" hook-insert={() => {}}>
  <h1 data-foo-heading={true}>Hello world</h1>
  <p aria-hidden="true">And good day</p>
  <a href="#" attr-style="color: blue" tabIndex="0" on-click={() => {}}></a>
</div>

Features

At its core, this module forwards most props to the attributes module. Otherwise, here's what to expect:

  • key prop is left as-is

  • All module props are unaffected (to prevent regressions on vanilla behavior)

  • Some props, such as className or tabIndex, are always moved to the props module to be set as DOM properties

  • Shorthands (prefixed module props) can be used to direct a JSX prop into a specific module. This flattens props (useful for hooks and listeners especially). These are the supported module prefixes:

    Prop pattern Module Example
    hook- Hooks hook-insert={() => {}}
    on- Event handlers on-click={() => {}}
    data- Dataset data-el-id="123"
    attrs- Attributes attrs-role="region"
    props- Properties props-dir="rtl

Why

By default, Snabbdom won't handle attributes/properties unless declared in a module object. While functional and concise, that module-driven prop signature is awkward given the prevalence of HTML-like JSX prop signatures in tools like React.

This module aims to improve that developer experience while retaining the great performance already present in Snabbdom.

Performance

Like Snabbdom itself, a top priority of this module is performance. As a result, it runs linearly by detecting modules present in a given vnode, then going over the props themselves. This allows specific application of certain props to their appropriate module, then immediately iterating to the next prop.

Like all code, I wouldn't claim this to be perfect, so contributions are welcome if you suspect improvements can be made.