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 🙏

© 2025 – Pkg Stats / Ryan Hefner

r9x_js

v4.0.9

Published

Reactive Library to SPA.

Readme

R9X

R9x é uma estrutura para criação de componentes reativos através de funções fábricas.

Documentação completa: r9x_io

Componentes

Criar um componente é muito fácil. Veja o exemplo abaixo:


const appHello = () => {

    const state = {
        title:'Hello World!'
    }

    const template = ({props, state}) => {
        return /*html*/`<h1 class="title">${state.title}</h1>`
    }


    const styles = () => {
        return /*css*/`
            app-hello .title {
                color: blue;
                text-align:center;
            }
        `
    }

    return {
        state,
        template,
        styles
    }
}

export { appHello }

Dentro da função fábrica acima declaramos o state o template e os estilos css do componente appHello. Em seguida os retornamos dentro de um objeto literal.

    return {
        state,
        template,
        styles
    }

Embora declarados dentro do escopo da função fábrica, o template, os estilos e o próprio state do componente, poderiam rer importados de outros arquivos. Veja abaixo:


import helloTemplate from 'another/place'
import helloStyles from 'anhother/place'
import helloState from 'another/place'

const appHello = () => {

    const state = helloState
    const template = helloTemplate
    const styles = helloStyles

    return {
        state,
        template,
        styles
    }
}

export { appHello }

Ainda poderia ficar mais simples:


import template from 'another/place'
import styles from 'anhother/place'
import state from 'another/place'

const appHello = () => {

    return {
        state,
        template,
        styles
    }
}

export { appHello }

Comoponentes interativos

É possível criar interatividade nos componentes através de eventos e metodos simples. Veja abaixo:


import template from 'another/place'
import styles from 'anhother/place'
import state from 'another/place'

const appHello = () => {

    const events = ({on, query, methods}) => ({

        onClickTitle: () => {
            const titleElement = query('.title')
            on('click', [titleElement], ({target}) => methods.logger(target))
        }

    })

    const methods = ({props, state}) => ({

        logger: (...params) => console.log( ...params )

    })

    return {
        state,
        template,
        styles,
        events,
        methods
    }
}

export { appHello }

Os recursos introduzidos acima garantem que ao clicar no título, o elemento alvo do clique seja logado no console.

hooks

Ainda é possível definir comportamentos automáticos através dos hooks.

Atualmente existes 4 hooks observáveis:

  • beforeOnInit - executado apenas uma vez antes do componente ser inicializado
  • afterOnInit - executado apenas uma vez depois do componente ser inicializado
  • beforeOnRender - executado antes da renderização sempre que o componente renderiza o template
  • afterOnRender - executado após a renderização sempre que o componente é renderizado.

Veja o exemplo abaixo:


import template from 'another/place'
import styles from 'anhother/place'
import state from 'another/place'

const appHello = () => {


    const hooks = ({methods}) => ({

        beforeOnInit () {
            methods.logger('antes de appHello ser inicializado')
        },
        afterOnInit () {
            methods.logger('depois de appHello ser inicializado')
        },
        beforeOnRender () {
            methods.logger('antes de appHello ser renderizado')
        },
        afterOnRender () {
            methods.logger('depois de appHello ser renderizado')
        },

    })

    return {
        state,
        template,
        styles,
        hooks
    }
}

export { appHello }

O recurso incluído acima exibiria no console as mensagens dispostas em beforeOnInit e afterOnInit apenas uma vez, enquanto exibiria multiplas vezes as mensagens em beforeOnRender e afterOnRender.

Directives

As diretivas em r9x são apenas funções simples que manipulam os fragmentos do DOM presentes no componente com base no estado e nos eventos do próprio componente.

Veja o exemplo abaixo:


import template from 'another/place'
import styles from 'anhother/place'
import state from 'another/place'

const appHello = () => {

    const events = ({on, query, directives}) => ({

        onClickTitle: () => {
            const input = query('#name')
            on('keyup', [input], ({target}) => directives.changeColor(target))
        }

    })

    const directives = ({query}) => ({

        changeColor: (target) => {
            
            if(!target || !target.value) return

            target.value.length <= 3 ? 
                target.style.color = 'red' : 
                target.style.color = 'blue'
        }

    })

    return {
        state,
        template,
        styles,
        events,
        directives
    }
}

export { appHello }

No exemplo acima, sempre que o evento onkeyup ocorrer, a diretiva changeColor será executada alterando o aspecto visual do input com base na quantidade de caracteres encontrada na propriedade value do mesmo.

Reactive State

Fazer os componentes criados com R9X reajam a mudanças no estado também é algo bem simples e atualmente existem 2 estratégias:

1 . Scoped State - Nessa estratégia o componente possui um estado local que só reflete os efeitos colaterais de alteração dos dados para o próprio componente.

2 . Stored State - Nessa estratégia os efeitos colaterais são desencadeados em todos os componentes inscritos na store de dados.

Scoped State


const appHello = () => {

    const state = {
        title: 'Hello World!'
    }

    const events = ({on, query, methods}) => ({

        onClickTitle: () => {
            const titleElement = query('.title')
            on('click', [titleElement], methods.changeTitle)
        }

    })

    const methods = ({props, state}) => ({

        changeTitle: () => state.set({title: 'Hello crazy world!'})

    })

    return {
        state,
        events,
        methods
    }
}

export { appHello }

Observe que o evento de click no elemento de título do componente executará a função changeTitle que modificará o estado atribuindo o valor Hello crazy world! a propriedade title do state. Isso fará com que o template do componente seja renderizado exibindo o novo título.

Stored State


import store from 'anoter/place/store`'

const appHello = () => {

    const state = {
        title: store.get().title
    }

    const hooks = ({methods}) => ({

        beforeOnInit () {
            store.subscribe((data) => state.set(data)
        }

    })

    const events = ({on, query, methods}) => ({

        onClickTitle: () => {
            const titleElement = query('.title')
            on('click', [titleElement], methods.changeTitle)
        }

    })

    const methods = ({props, state}) => ({

        changeTitle: () => store.update({title:'Another title crazy world!'}))

    })

    return {
        state,
        hooks
        events,
        methods
    }
}

export { appHello }

Note que importamos a store de dados e que a propriedade title do state foi inicializada com o valor equivalente presente na store.


    const state = {
        title: store.get().title
    }

Depois adicionamos um observador à store para atualizar o state local assim que a store for modificada.


    const hooks = ({methods}) => ({

        beforeOnInit () {
            store.subscribe((data) => state.set(data)
        }

    })

Por fim, o método changeTitle atualiza a store através da função update disponibilizada pela própria store para alterar seus dados e notificar os observadores sobre as modificações.



    const methods = ({props, state}) => ({

        changeTitle: () => store.update({title:'Another title crazy world!'}))

    })

Dessa forma, todo e qualquer componente observando a store receberá os novos dados e uma notificação de que os dados presentes na store foram alterados e poderão decidir programaticamente sobre qual comportamento reativo adotar.

Reactive properties

Propriedades reativas devem ser usadas para passar informação para componentes filhos.

Essas propriedaes são obaservadas assim como o state e a cada alteração geram um efeito colateral observado pelo componente que culminará em uma nova renderização do template do mesmo.

As propriedades reativas também estão acessíveis ao template e aos metodos do componente.

appName.component.js


const appName = () => {

    const state = {}

    const template = ({props, state}) => /*html*/`
        <p>${props.name}</p>
    `

    return {
        state,
        template,
    }
}

export { appHello }

appHello.component.js


import appName from 'anhother/place/appName.component'

const appHello = () => {

    const state = {
        title:'Hello World!',
        name: 'Alfred',
    }

    const children = () => ({
        appName
    })

    const template = ({props, state}) => /*html*/`
        <h1 class="title">${state.title}</h1>
        <app-name data-props="{'name':`${state.name}`}"></app-name>
        `

    return {
        state,
        template,
        children,
    }
}

export { appHello }

O componente appName está configurado para receber por propriedade o valor de name e exibir dentro da tag p do template.

Observe que appName foi importado e anexado como filho de appHello através da função children. Veja também, que o componente appHello passa o valor (name) esperado em appName para o mesmo através da propriedade html data-props presente na tag do componente filho.