0.1.4 • Published 3 months ago

umhi v0.1.4

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

umhi

A tiny UI library.

Install

npm install umhi

Usage

import { m, mount } from 'umai';

let count = 1;

const Counter = () => (
  m('div',
    m('h1', `Count: ${count}`),
    m('button', { onclick: () => count += 1 }, 'increment')
  )
);

mount(document.body, Counter);

umhi (pronounced "um, hi") is a refactored version of umai@0.1.7.

umhi is intended for usecases that require a declarative user interface API, but don't need any of the bells and whistles provided by larger frameworks. umhi is well-suited for userscripts due to its aggressively small size, and is used in enhanced-gog.

Mounting

mount will use your provided virtual DOM node factory to render on a root node.

import { m, mount } from 'umhi';
const root = document.getElementById('app');
const App = () => m('p', 'hello world');
mount(root, App);

When using mount, event handlers defined in your templates will automatically trigger full tree rerenders.

let input = '';

const TextInput = () => (
  m('div',
    m('input', {
      type: 'text',
      value: input,
      // this will trigger a full rerender on every event
      oninput: ({ target }) => input = target.value
    }),

    m('h1', input.toUpperCase())
  )
);

Manual rerenders can be triggered with the redraw utility.

import { m, redraw } from 'umhi';
import { fetchUsers } from './api.js';

const users = [];

// some async operation
fetchUsers()
  .then(res => users = [...users, ...res])
  .finally(redraw);

const Users = () => (
  m('div',
    // this will display while `fetchUsers` is pending
    !users.length && m('p', 'no users'),

    // once the `.finally` handler is called, `redraw` will execute
    // if users.length is truthy, it will render the list of users
    users.length && users.map(user =>
      m('p', user)
    )
  )
);

If you'd like more fine-grained control over rerenders, render can be used in place of mount.

import { m, render } from 'umhi';

let book = 'The Old Man and the Sea';

const Books = () => (
  m('div',
    m('p', book)
  )
);

const root = document.getElementById('app');
render(root, Books); // renders `<div><p>The Old Man and the Sea</p></div>`

book = 'Infinite Jest';
render(root, Books); // renders `<div><p>Infinite Jest</p></div>`

Components

While umhi has no concept of components, functions can be used to reduce duplication.

const User = ({ name }) => (
  m('div.user',
    m('h2', name)
  )
);

const List = () => (
  m('div.users',
    User({ name: 'kevin' }),
    User({ name: 'rafael' }),
    User({ name: 'mike' }),
  )
);

Passing children

const Layout = ({ title }, ...children) => (
  m('div.container',
    m('h1.page-title', title),
    children
  )
);

const UserPage = () => (
  Layout({ title: 'User Page' },
    m('p', 'Welcome to the user page!')
  )
);

Style Helper

The style prop can be a style attribute, or optionally, an object containing CSS style declarations. umhi will parse the style object and construct a string for you.

// using a style attribute
const Card = () => (
  m('div', { style: 'background-color: green; border: 1px solid black;' },
    '...'
  )
);

// using a style object
const Card = () => (
  m('div', { style: { backgroundColor: 'green', border: '1px solid black' } },
    '...'
  )
);

Class Helpers

Like umai, umhi features class string helpers, such as a class string builder and a hyperscript tag helper.

const Book = ({ isSelected = true }) => (
  m('div.book.bg-green', { class: { bold: false, selected: isSelected } },
    'Wind, Sand, And Stars'
  }
);

// renders `<div class="book bg-green selected">Wind, Sand, And Stars</div>`

Credits

The original virtual DOM algorithm was adapted from Oliver Russell's 33-line React.

Like umai, umhi is heavily influenced by Mithril.js.

0.1.4

3 months ago

0.1.3

10 months ago

0.1.2

10 months ago

0.1.0

10 months ago