Skip to content
/ dom Public

Fusor is a simple JavaScript library that helps declaratively create and update DOM elements

License

Notifications You must be signed in to change notification settings

fusorjs/dom

Repository files navigation

Fusor

Fusor is a simple JavaScript library that helps create and update DOM elements.

It is:

  • Simple ― two API methods: create & update DOM
  • Concise ― less verbose than anything else
  • Explicit ― what you see is what you get, no black box magic
  • Flexible ― as using pure functions, both declarative and imperative
  • Small/Performant ― size ~3kB, no dependencies
  • W3C Standards Compliant

Install

npm install @fusorjs/dom

Or:

Examples

Create & Update DOM

import {getElement, update} from '@fusorjs/dom';
import {section, div} from '@fusorjs/dom/html';

let count = 0;

const block = section(
  {class: () => (count % 2 ? 'odd' : 'even')},

  div('Seconds ', () => count, ' elapsed'),
  div('Minutes ', () => Math.floor(count / 60), ' elapsed'),
);

document.body.append(getElement(block));

setInterval(() => {
  count++;
  update(block);
}, 1000);

> run this example

Only tiny portions of the block DOM tree are updated if they differ from the current values.

JSX Support

import {getElement, update} from '@fusorjs/dom';

let count = 0;

const block = (
  <section class={() => (count % 2 ? 'odd' : 'even')}>
    <div>Seconds {() => count} elapsed</div>
    <div>Minutes {() => Math.floor(count / 60)} elapsed</div>
  </section>
);

document.body.append(getElement(block));

setInterval(() => {
  count++;
  update(block);
}, 1000);

> run this example

Parameters & Children Syntax

import {getElement, update} from '@fusorjs/dom';
import {section} from '@fusorjs/dom/html';

let count = 0;

const block = section(
  {
    id: 'set attribute or property automatically',
    title_a: 'set attribute',
    style_p: 'set property',

    focus_e: () => 'set bubbling event handler',
    blur_e_capture_once: () => 'set capturing event handler once',

    // update dynamic values in this DOM node:
    click_e_update: () => count++, // same as
    click_e: () => {count++; update(block);}, // same as
    click_e: (event, self) => {count++; update(self);},

    class: count % 2 ? 'odd' : 'even', // static
    class: () => (count % 2 ? 'odd' : 'even'), // dynamic
  },

  'Static child ', count, ' never changes.',
  'Dynamic child ', () => count, ' is wrapped in a function.',
);

document.body.append(getElement(block));

> run this example

Stateful Component

import {getElement} from '@fusorjs/dom';
import {button, div} from '@fusorjs/dom/html';

const ClickCounter = (count = 0) =>
  button({click_e_update: () => count++}, 'Clicked ', () => count, ' times');

const App = () => div(ClickCounter(), ClickCounter(22), ClickCounter(333));

document.body.append(getElement(App()));

> run this example

JSX Version

import {getElement} from '@fusorjs/dom';

const ClickCounter = ({count = 0}) => (
  <button click_e_update={() => count++}>Clicked {() => count} times</button>
);

const App = () => (
  <div>
    <ClickCounter />
    <ClickCounter count={22} />
    <ClickCounter count={333} />
  </div>
);

document.body.append(getElement(<App />));

> run this example

Components in both versions are interoperable.

Controlled Input Component

import {getElement} from '@fusorjs/dom';
import {input, div} from '@fusorjs/dom/html';

const UppercaseInput = (value = '') =>
  input({
    value: () => value.toUpperCase(),
    input_e_update: (event) => (value = event.target.value),
  });

document.body.append(
  getElement(
    div(UppercaseInput(), UppercaseInput('two'), UppercaseInput('three')),
  ),
);

> run this example

Documentation

Applications

Contributing

Your suggestions and contributions are always welcome!

Please see CONTRIBUTING for details and CHANGELOG for agenda.