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 🙏

© 2026 – Pkg Stats / Ryan Hefner

pawajs

v1.4.7

Published

pawajs library (html runtime) for easily building web ui, enhancing html element, micro frontend etc

Readme

pawajs

pawajs - power the web (reactivity and html runtime)

PawaJS

A lightweight and reactive JavaScript library for building modern web interfaces with a simple, declarative syntax.

PawaJS is a JavaScript library designed for building dynamic user interfaces. It combines a component-based architecture and progressive enhancement with a powerful reactivity system no v-dom. Its intuitive, directive-based templating feels familiar and makes it easy to create interactive applications, from simple widgets to complex single-page apps. With built-in support for server-side rendering, PawaJS is equipped for performance and scalability.


Features

  • Declarative Rendering: Use a clean, HTML-based template syntax with powerful directives (if, for-each, on-event, etc.) to describe your UI.
  • Reactive State Management: Effortlessly create reactive state that automatically updates the DOM when it changes using the $state utility.
  • Component-Based Architecture: Build encapsulated components that manage their own state, making your code more reusable and maintainable.
  • Async Components: First-class support for asynchronous components, allowing you to fetch data directly within your component definition.
  • Efficient List Rendering: Render lists of data with the for-each directive, including support for keyed updates for optimal performance.
  • Lifecycle Hooks: Tap into a component's lifecycle with mount and unmount directives, or the runEffect hook for more complex side effects.
  • Context API: Pass data through the component tree without having to pass props down manually at every level.
  • Server-Side Rendering (SSR) Isomorphic architecture: PawaJS is built with SSR in mind, featuring a "resuming" mechanism to efficiently continue server-rendered HTML on the client.
  • Plugin System: Extend PawaJS's core functionality with custom directives and lifecycle behaviors.

Installation

Install PawaJS into your project using npm:

npm install pawajs

CDN

    <head>
        </head>
    <body>
        <div id="app"></div>
        <script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/cdn/index.js"></script>
        <script type="module">
            window.$pawa.pawaStartApp(document.getElementById('app'));
        </script>
    </body>

OR

Then, you can import it into your application: through npm

import { pawaStartApp, $state, RegisterComponent, html } from 'pawajs';

Getting Started: A Simple Counter

Here's a basic example to show you how PawaJS works.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>PawaJS Counter</title>
</head>
<body>
    <div id="app">
        <h1 state-name="'PAWAJS'">@{name.value}</h1>
        <!-- The component will be rendered here -->
        <counter-app></counter-app>
    </div>
    <script type="module" src="app.js"></script>
</body>
</html>

app.js

import { pawaStartApp, $state, useInsert, RegisterComponent, html } from './pawajs/index.js';

// 1. Define a component
const CounterApp = () => {
    // 2. Create reactive state
    const count = $state(0);

    // 3. Define methods to modify the state
    const increment = () => {
        count.value++;
    };
    const decrement = () => {
        count.value--;
    };

    // 4. Expose state and methods to the template
    useInsert({ count, increment, decrement });

    // 5. Return the component's template
    return html`
        <div>
            <h1>PawaJS Counter</h1>
            <p>Current count: <strong>@{count.value}</strong></p>
            <button on-click="increment()">Increment +</button>
            <button on-click="decrement()">Decrement -</button>
        </div>
    `;
}

// 6. Register the component
// PawaJS converts PascalCase component names to kebab-case for use in HTML.
RegisterComponent(CounterApp);

// 7. Start the PawaJS application
const appElement = document.getElementById('app');
pawaStartApp(appElement);

Core Concepts

State Management with $state

The $state function is the heart of PawaJS's reactivity. It creates a reactive object whose value property can be read and written to. Any changes to .value will automatically trigger updates in the parts of your application that depend on it (fine-granded) no component re-rendering or diffing. $state can be global when used outside a component. Also inline state in the html or template state-*="any js types"

    <!--- number-->
    <div state-count="0">@{count.value}<div>
    <!--- string-->
    <div state-name="'PAWAJS'">@{name.value}<div>
    <!--- object-->
    <div state-object="{name:'pawajs'}">@{object.value.name}<div>
    <!--- boolean-->
    <div state-login="false">@{login.value? 'Welcome back!':'Please login'}<div>
    <!--- array-->
    <span state-splitname="['P','A','W','A','J','S']" for="item in splitname.value">@{item}<div>
// Create a simple state
const name = $state('Pawa');
console.log(name.value); // "Pawa"
name.value = 'PawaJS'; // The UI will update automatically

// State can hold any data type
const user = $state({ name: 'Alex', loggedIn: false });
user.value.loggedIn = true; // This is also reactive

// Persist state to localStorage
// The state will be saved under the key 'session' and reloaded on page refresh.
const session = $state({ id: null }, 'session');

// Compute state - must be used inside a component
// when ever count changes the state update
const doubleCount=$state(()=>count.value * 2,[count])

//AutoCompute
// Any function that uses any reactive state for reactive bindings or direcives becomes computed function
const doubleCount=()=>count.value * 2

Components

Components are the building blocks of your application. In PawaJS, a component is a JavaScript function that returns an HTML template string or not.

  • Defining: Create a function that returns a template or not.
  • Registering: Use RegisterComponent(MyComponent) to make it available globally. In HTML, you can then use it as <my-component>.
  • useInsert: To make variables, state, and functions from your component's setup available in its template, pass them in an object to useInsert().

Asynchronous Components

PawaJS supports async components ( useAsync() hook) out of the box. You can define a component as an async function, allowing you to perform asynchronous operations (like fetching data) before the component renders. wrap any pawajs hook with $async after any await call

const UserProfile = async () => {
    // Async hook store the current component instance for $async to use
    const {$async}=useAsync()
    // The component will wait for this promise to resolve before rendering
    const data = await fetch('/api/user').then(res => res.json());
    const user = $async(()=>$state(data);)
    $async(()=>useInsert({user}))

    return html`
        <div class="profile">
            <h1>@{user.value.name}</h1>
        </div>
    `;
}

Templating

PawaJS uses a simple @{...} syntax to embed dynamic JavaScript expressions directly into your HTML.

<!-- Bind to text content -->
<p>@{user.name}</p>

<!-- Bind to attributes -->
<div class="user-card @{user.value.isActive ? 'active' : 'inactive'}">
    <input value="@{user.value.name}" on-input="user.value.name = e.target.value">
</div>

Directives

Directives are special attributes that apply reactive behavior to DOM elements.

state-*

create inline state for the element and children

    <div state-count="0">
        <button on-click="count.value++">@{count.value}</button>
    </div>

if / else / else-if

For conditional rendering.

<div if="user.value.loggedIn">
    Welcome back, @{user.name.value}!
</div>
<div else-if="user.value.isGuest">
    You are browsing as a guest.
</div>
<div else>
    Please log in to continue.
</div>

switch / case / default

switch conditional rendering.

<div switch="user.value.type" case="'admin'">
    Welcome back, @{user.name.value}!
</div>
<div case="'guest">
    You are browsing as a guest.
</div>
<div default>
    Please log in to continue.
</div>

key

re-renders the element/component when the reactivity changes

<user-component key="user.value.type"></user-component>

is-exit

makes pawajs engine to wait before removing the element until the animation/transition is done.

<div if="user.value.loggedIn" class="user-card @{user.value.isActive ? 'active' : 'inactive'}" is-exit>
    <input value="@{user.value.name}" on-input="user.value.value = e.target.value">
</div>

for-each

For rendering lists from an array. Use for-key to give each element a unique identity, which helps PawaJS optimize rendering.

<ul>
    <li for-each="todo, i in todos.value" for-key="{{todo.id}}">
        <span>@{i + 1}. @{todo.text}</span>
    </li>
</ul>

on-<event>

For handling DOM events.

<button on-click="addTodo()">Add Todo</button>
<input on-input="newTodoText.value = e.target.value" />

out-<event>

For handling DOM events.

<button out-click="console.log('outside')">Add Todo</button>

Component Props

You can pass data from a parent component to a child component using props. To declare a prop, prefix the attribute with a colon (:). Children are passed by default in pawajs, they are not functional prop. For rest props pass -- to the element that needs the attributes. Parent Component (app.js)

// ...
const message = $state('This is a message from the parent!');
useInsert({ message });

return html`
    <todo-list :title="'My Todo List'" :message="message.value" class="to the rest prop">Children in here</todo-list>
`;

Child Component (todo-list.js)

export const TodoList = ({ title, message,children }) => {
    // Props are passed as functions that return the reactive value
    useInsert({ title, message });

    return html`
        <div -->
            <h2>@{title()}</h2>
            <p>@{message()}</p>
            ${children}
        </div>
    `;
}

// You can also validate props
useValidateComponent(TodoList, {
    title: {
        type: String,
        strict: true // This prop is required
    },
    message: {
        type: String,
        default: 'Default message'
    }
});

API Reference

Core Functions

  • pawaStartApp(rootElement, initialContext): Initializes the PawaJS application on a given root DOM element.
  • RegisterComponent(...components): Registers one or more components to be used in templates.
  • $state(initialValue, localStorageKey?): Creates a new reactive state object.
  • html: A tagged template literal for syntax highlighting and potential future optimizations.

Component Hooks

  • useInsert(object): Exposes data and functions from a component's setup to its template.
  • runEffect(callback, dependencies?): Runs a side effect after or before the component renders, and re-runs it when its dependencies change .
  • useContext(contextObject) & setContext(): A mechanism for providing and consuming data throughout a component tree.
  • useRef(): Creates a reference object that can be attached to a DOM element using the ref directive.
  • useValidateComponent(Component, rules): Defines validation rules for a component's props.
  • useServer(): Returns { setServerData, getServerData } for handling server-side data serialization and client-side retrieval in SSR applications.

Contributing

Contributions are welcome! If you have a feature request, bug report, or want to contribute to the code, please feel free to open an issue or pull request on the GitHub repository.

License

This project is licensed under the MIT License.