Coder Social home page Coder Social logo

htm-ally's Introduction

htm-ally brotli size

500 bytes web app micro-framework with a syntax you already know

  • Just HTML, nothing new to learn
  • No need for transpiler or compiler
  • Components, mount, unmount, and update hooks
  • Element refs, event handlers, attributes, and styles
  • Class helper
  • Fragments and arrays
  • XSS safe

Install

npm install --save htm-ally

yarn add htm-ally

and then:

import { html } from "htm-ally";

// or directly from unpkg

import { html } from "https://unpkg.com/htm-ally?module";

Usage

The output of html is just an HTMLFragment, so you can use it anywhere you can use a fragment:

const fragment = html`<div>hello</div>`;

document.getElementById("app").append(fragment);

Nesting fragments (or arrays of fragments) are supported:

const makeNested = (number) => html`
  <h1>hello</h1>
  <div>
    <p>${number}</p>
  </div>
`;

const nested = makeNested(100);

const fragment = html`
  <div>
    ${nested}
    ${[1, 2, 3].map(makeNested)}
  </div>
`;

Just insert interpolation with an object to define attributes and event handlers. Other attributes of the element are preserved:

const onclick = () => alert("clicked");

const fragment = html`
  <button id="button" ${{ onclick, class: "btn", disabled: false }}>
    Click me
  </button>
`;

Classes can also be defined as arrays or objects:

const primary = true;
const isDisabled = false;

const classNames = ["btn", primary && "primary", { disabled: isDisabled }];

const fragment = html`
  <button ${{ class: classNames }}>Click</button>
`;

Styles are defined as an object (with camelCase):

const fragment = html`
  <button ${{ style: { color: "red", fontWeight: "bold" } }}>Click</button>
`;

Refs can be defined with a function:

const inputRef = (el) => (inputRef.el = el);

const onChange = () => {
  console.log(inputRef.el.value);
};

const fragment = html`
  <input type="text" ${{ ref: inputRef, onchange: onChange }} />
`;

Components are just functions that return a fragment

const Component = () => html`<div>hello</div>`;

const fragment = html`<div>${Component}</div>`;

Components have access to an element it's mounted to (a slot element). The element contains update, mount, and unmount functions:

let count = 0;

const Counter = (parent) => {
  const onClick = () => {
    count += 1;
    parent.update();
  };

  return html`<button ${{ onclick: onClick }}>Count: ${count}</button>`;
};

document.getElementById("app").append(html`${Counter}`);

For the mount and unmount hooks, see the Timer example.

Note: text input components cannot be updated with the parent.update() as the cursor position will be reset.

Components can have a local state in a closure or on the parent node:

const Counter = (initialValue) => {
  let count = initialValue;

  return (parent) => {
    const onClick = () => {
      count += 1;
      parent.update();
    };

    return html`<button ${{ onclick: onClick }}>Count: ${count}</button>`;
  }
};

document.getElementById("app").append(html`${Counter(100)}`);

The state isn't preserved when the parent component updates (as there is no reconciliation), so it's recommended to use a global state to store states for each component.

Examples

All examples can be found in the CodeSandbox: link

Counter

Shows event handlers, attributes, component update

import { html } from "htm-ally";

let count = 0;

const Counter = (parent) => {
  const inc = () => {
    count += 1;
    parent.update();
  };

  const dec = () => {
    count -= 1;
    parent.update();
  };

  return html`
    <button ${{ onclick: dec, disabled: count <= 0 }}>-</button>
    ${count}
    <button ${{ onclick: inc, disabled: count >= 10 }}>+</button>
  `;
};

document.getElementById("app").append(html`${Counter}`);

Todo list

Shows ref usage, array map, and component update.

let todos = [];

const TodoList = () => {
  let inputRef = (el) => (inputRef.el = el);

  return (parent) => {
    const addTodo = () => {
      const text = inputRef.el.value;
      inputRef.el.value = "";
      todos.push(text);
      parent.update();
    };

    return html`
      <input type="text" ${{ ref: inputRef }} />
      <button ${{ onclick: addTodo }}>Add</button>
      <ul>
        ${todos.map((text) => html`<li>${text}</li>`)}
      </ul>
    `;
  };
};

document.getElementById("app").append(html`${TodoList()}`);

Timer

Shows mount and unmount hooks

let show = false;

const TimerToggle = (parent) => {
  const toggleShow = () => {
    show = !show;
    parent.update();
  };

  return html`
    <button ${{ onclick: toggleShow }}>${show ? "Hide" : "Show"}</button>
    ${showTimer && Timer}
  `;
};

let interval;
let time = 0;

const Timer = (parent) => {
  // start timer on mount
  parent.mount = () => {
    interval = setInterval(() => {
      time += 1;
      parent.update();
    }, 1000);

    time = 0;
    parent.update();
  };

  // stop timer on unmount
  parent.unmount = () => {
    clearInterval(interval);
  };

  return html`Timer: ${time}s`;
};

document.getElementById("app").append(html`${TimerToggle}`);

Advanced Todo list

See the CodeSanbox

Author

Eugene Daragan

License

MIT

htm-ally's People

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.