npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

xatto

v1.4.3

Published

xatto is View Layer Library based on Function and Context using VirtualDOM. This is developed by forking from jorgebucaran/superfine.

Downloads

394

Readme

xatto

xatto is View Layer Library based on Function and Context using VirtualDOM.
This is developed by forking from jorgebucaran/superfine.

Getting Started

Note: The example in this document assumes that you are using a JavaScript compiler such as Babel or TypeScript, a JSX (TSX) transpiler, and a module bundle such as Parcel, Webpack.

The main APIs of xatto are two.
The first one is xatto.x. It returns a new virtual DOM node tree.
The other is xatto.atto. It returns a function that mount (or update) a component in the specified DOM element. (mutate function)

example: A counter that can be incremented or decremented.

import { x, atto } from "xatto"

const down = context => ({ count: context.count - 1 })
const up = context => ({ count: context.count + 1 })

const Component = (props, children, context) => (
  <div>
    <h1>{context.count}</h1>
    <button onclick={down}>-</button>
    <button onclick={up}>+</button>
  </div>
)

atto(Component, document.getElementById("app"))({
  count: 10
})

Installation

xatto is available as a package on npm.

npm install xatto
import { x, atto } from "xatto"

It is also available on a CDN.

<script src="https://unpkg.com/xatto"></script>
<script>
  var x = window.xatto.x;
  var atto = window.xatto.atto;
  // ...
</script>

Easier

git clone https://github.com/atomita/xatto-starter-kit.git project
cd project
npm install
npm run serve

Overview

Context

A context is a JavaScript object that describes a component.
It consists of dynamic data that moves within a component during execution.
To change the context you need to use the mutate function (or event handler in the components).

Mutate function

It is a function returned by xatto.atto.

Passing the context mount the component specified by xatto.atto on the specified container together.
From the second time on, it update.

Components

The component returns the specification in the form of a plain JavaScript object called virtual DOM, and xatto is updates the actual DOM accordingly.
Each time the context changes the component is invoked so you can specify the appearance of the DOM based on the new context.

The context can be referenced in the third arguments.

import { x, atto } from "xatto"

const Component = (props, children, context) => (
  <div>{context.name}</div>
)

atto(Component, document.getElementById("app"))({
  name: "foo"
})

Fragments supported

const Component = (props, children) => (
  <>
    <div>foo</div>
    <div>bar</div>
  </>
)

Sliced context and fill

The child component can treat a part of the context as if it were the root context by using <Context slice="path"> in the parent component.

Also, the fill attribute can specify a value to use if part of the sliced context is undefined.

import { x, atto, Context } from "xatto"

const Parent = (props, children, context) => (
  <div>
    <span>{context.name}</span>
    <ul>
      <li><Context slice="children.0"><Child /></Context></li>
      <li><Context slice="children.1" fill={{ name: "baz" }}><Child /></Context></li>
    </ul>
  </div>
)

const Child = (props, children, context) => (
  <span>{context.name}</span>
)

atto(Parent, document.getElementById("app"))({
  name: "foo",
  children: {
    0: {
      name: "bar"
    }
  }
})

Events

Event handlers are wrapped by xatto.
Usually, the event object passed in the first argument is the fourth argument.
The return value is passed to the mutate function.

Event handler arguments:

  1. context
  2. { ...extra, ...detail, dispatch }
  3. props
  4. event

Lifecycle Events

Lifecycle events can be used to be notified when an element managed by the virtual DOM is created, updated, or deleted.
It can be used for animation, data fetching, third party library wrapping, resource cleanup, etc.

oncreate

This event occurs after an element is created and attached to the DOM.

onupdate

This event will occur each time you update an element's attributes.

onremove

This event occurs before an element is dettached from the DOM.
detail.done is passed a function to detach the element.

ondestroy

This event occurs just before an element is dettached from the DOM.

onlifecycle

This event occurs just before each life cycle event occurs.
detail.type is passed the life cycle event name.

Keys

The key helps to identify the node each time xatto update the DOM.
This allows you to rearrange the elements to a new position if you change the position.

The key must be unique among sibling nodes.

Extra

If you want to pass values from the parent component to all descendant components, try using Extra. You can refer to the same value regardless of context.

import { x, atto, Context, Extra } from "xatto"

const Parent = (props, children, context) => (
  <div>
    <span>{context.name}</span>
    <Extra parentName={context.name}>
      <ul>
        <li><Context slice="children.child1"><Child /></Context></li>
        <li><Context slice="children.child2" fill={{ name: "baz" }}><Child /></Context></li>
      </ul>
    </Extra>
  </div>
)

const Child = (props, children, context, extra) => (
  <div>
    <p>{extra.parentName + ' - ' + context.name}</p>
    {context.children && Object.entries(context.children).map(([k, child]) => (
      <Context slice={'children.' + k}>
        <Grandchild />
      </Context>
    ))}
  </div>
)

const Grandchild = (props, children, context, extra) => (
  <p>{extra.parentName + ' - ' + context.name}</p>
)

atto(Parent, document.getElementById("app"))({
  name: "foo",
  children: {
    child1: {
      name: "bar",
      children: {
        grandChild1: {
          name: "barbaz"
        }
      }
    }
  }
})

Polyfill which may be needed

License

xatto is MIT licensed. See LICENSE.

Other examples

The counters.

import { x, atto, Context } from "xatto"

const down = context => ({ count: context.count - 1 })
const up = context => ({ count: context.count + 1 })

const Counter = (props, children, context) => (
  <div>
    <h1>{context.count}</h1>
    <button onclick={down}>-</button>
    <button onclick={up}>+</button>
  </div>
)

let idx = 2

const add = context => ({
  counters: { ...context.counters, ...(Object.fromEntries([[idx++, {count: 0}]])) }
})

const cut = context => {
  const entry = Object.entries(context.counters).slice(-1)[0]
  if (entry == null) {
    return
  }
  delete context.counters[entry[0]]
  return {
    counters: { ...context.counters }
  }
}

const Main = (props, children, context) => (
  <div>
    <button onclick={add}>add</button>
    <button onclick={cut}>cut</button>

    {Object.entries(context.counters)
      .map(([i, v]) => (<Context slice={'counters.' + i}><Counter /></Context>))}

    <pre>{JSON.stringify(context, null, '  ')}</pre>
  </div>
)

atto(Main, document.getElementById("app"))({
  counters: {
    0: { count: 0 },
    1: { count: 10 }
  }
})

https://codepen.io/atomita/pen/OaLxwP