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

arsnl

v1.1.0

Published

Tools to build an single-page web-app in javascript

Downloads

10

Readme

App Router & Stateful Node Library (ARSNL)

The simplest framework for powerful javascript apps

  • App
  • Node
  • State
    • subscribe
    • extract
  • Router
    • Link
  • All html tag functions

... Usage:

Example index.html:

<!doctype html>
<html>
    <body>
        <div id="app-root"></div>
        <script src="index.js"></script>
    </body>
</html>

Example index.js:

import { App } from 'arsnl'
import AppComponent from './App'
import routes from './routes'

new App({
    id: 'app-root',
    title: "My App",
    component: AppComponent,
    router: new Router(routes, {}),
})

Example routes.js:

import Dashboard from './Dashboard'
import Profile from './Profile'

const routes = {
    "/": Dashboard,
    "/profile/:id": Profile,
    "/404": ({ redirect }) => redirect('/'),
}

export default routes

Example AppComponent.js:

import { div } from 'arsnl'

export default app => {
    return (
        div({
            render: [
                app.renderRoutes(),
            ],
        })
    )
}

And just like that, you've set up an ARSNL app!

Note: In order to render the routes provided to the app, you may call the Router's render method attached to the app provided to the top-level app component.


App

App({})

This function provides a method of attaching your app component to the root html element with the given id.

Only Argument:

| Key | Description | Type | | :-----------: |:------------------------------------------------:| :------:| | id | ID selector to look for in the document as a root element | string | | routes | Configures the App level Router | Routes Object (see below) | | component | The ARSNL Component to be injected into the html | object |


DomNode

This function builds a basic ARSNL component. Really it's just a wrapper around code that generates a vanilla DOM element and knows how to decorate it based on what you've provided.

Domdiv(object | function, array of State objects to watch)

First Argument (required): The first argument is an object of attributes describing the Node OR it's a function that returns said configuration.

| Key | Required | Description | Value Type | | :----------: |:--------:|:--------------------------------------------:|:------:| | tagName | No | dom element (div by default) | String | | render | Yes | DomNode, string, number, Array of DomNodes/strings/numbers, ARSNL State (if only one property is present, it will attempt to render its value) | | style | No | object of css properties (recommend using some css-in-js solution instead... See Jetpak-css) | object | | onLoad | No | fires during tick after node has rendered | function |

Config Object also will take any properties supported by standard JS DOM Elements.

...

Second Argument (optional):

The second argument is an array of ARSNL State objects. Whenever a property is updated on one of the state objects, the node will re-render itself. (Note: Using the second argument requires the first one to be a function that returns the config.)

Minimal usage example:

import { div } from 'arsnl'

export default () => div({ render: "Hello world!" })

Minimal usage example:

import { div, State } from 'arsnl'

export default () => {
    const statefulStyle = State({ background: 'none' })
    return div(() => ({
        t: 'p',
        className: 'toggleable-background',
        s: { background: statefulStyle.background },
        render: [
            'Wutang ',
            div({
                t: 'strong',
                render: 'FOREVER'
            }),
        ],
        onLoad: () => alert('component has loaded'),
        onclick: () => {
            (statefulStyle.background === 'blue')
                ? statefulStyle.background = 'red'
                : statefulStyle.background = 'blue',
    }), [ statefulStyle ])
}

(Note: This component will re-render when the background is changed by clicking the component because it's tracking the state of 'background' in it's array of tracked states.)

(Note: I put the function properties outside the config method so they aren't re-defined with every re-render.)


State

State() allows you to enhance an object with proxy so subscribers can listen for changes.

State(obj, onChange)

First Argument (required):

Object of default values.

Second Argument (optional):

Function you want to fire every time state changes. (This onChange is the first subscriber to changes added. You can use the subscribe() function to add additional listeners.)

(Note: This onChange function will receive two arguments: 'name' of changed field, and the updated 'value' of changed field respectively.)

(Note: In order to trigger an update to occur, you must set the entire top-level property on the state object.)

... Usage:

An example of user being able to update state:

import { div, State } from 'arsnl'

export default () => {
    const counter = State({ value: 0 })    
    return div({
        render: [
            div({
                t: 'button',
                onclick: () => counter.value++,
                render: 'Add it up',
            }),
            div(() => ({
                render: `clicked ${counter.value} times`
            }), [ counter ])
        ],
    })
}

(Note: Because the second child Node has "counter" in it's second argument, it will re-render when the value updates.)


subscribe

subscribe(State, function)

This function adds an onChange listener to a given State object.

First Argument (required): A reference to an ARSNL State Object.

Second Argument (required): A method to call whenever state changes.

(Note: This onChange function will receive two arguments: 'name' of changed field, and the updated 'value' of changed field, respectively.)

... Usage:

import { div, State, subscribe } from 'arsnl'

export default () => {
    const counter = State({ value: 0 })  
    const counterButton = div({
        t: 'button',
        render: 'Add it up',
        onclick: () => counter.value++,
    })
    subscribe(counter, (key, value) => {
        alert(`Clicked ${value} times!`)
    })
    return counterButton
}

extract

extract(State)

This function sanitizes the ARSNL State object by removing the ARSNL-specific meta-fields that were added to it on initialization.

Only Argument:

Required: A reference to an ARSNL State Object.

This example is a button that auto-saves a counter State on every change using some imaginary post API call.

... Usage:

import { div, State, extract } from 'arsnl'

const counter = State({ value: 0 })
const data = extract(counter)
// counter would be {"value": 0, __ARSNL_STATE__: {...}}
// data would be {"value": 0}

Router

new Router(object)

This function returns an instance of a Router object. This object subscribes to navigation changes in the app, and when a change occurs, attempts to render the appropriate route provided to it by the configuration object.

Call the router's render method wherever you want the route to be displayed. It will automatically update itself based on the current url in the browser.

It always provides any path variables in the window.location.pathname as specified by the name of the route in the config, as well as any data in the query params of the url.

THIS ONLY LISTENS to location changes made using the ARSNL Link component - see below...

Only Argument:

Required: A configuration object representing the routes you wish to render. Key names on the object are strings representing the url of the given page, and the values are functions representing something that will be rendered based on the current url.

... Usage:

import { div, Router } from 'arsnl'

import Home from './routes/Home'
import Work from './routes/Work'

const routes = {
    "/": Home,
    "/work": Work,
    "/sports/:sport": ({ params, search }) => {
        // For example: if the url is www.example.com/sports/baseball?field="Wrigley"
        return (
            div({
                render: `hello ${search.field} Field! Someone likes ${params.sport}!`
                // So this route component would render:
                // <div>hello Wrigley Field! Someone likes baseball!</div>
            })
        )
    }
}

const router = new Router(routes)

export default () => (
    div({
        render: router.render()
    })
)

(Note: The key names of the routes object may contain path variables.)

(Note: Path variables and query params flow into the rendered route component.)


Link

Link(object)

This function builds a link component that ties into the navigation provided by ARSNL Router (see above).

Only Argument:

Required: Object of ARSNL Node configuration with a special "path" property.

... Usage:

import { div, Router } from 'arsnl'

export default () => (
    Link({
        path: '/sports/baseball',
        render: 'Visit Baseball',
    })
)
// this will render as: <a href="/sports/baseball">Visit Baseball</a>

(Note: This component does not support a custom onclick attribute.)


Third-Party Dependencies:

classname, query-string, lodash, webpack