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

@moali1071/mini-framework

v1.0.3

Published

my mini framework

Readme

🧩 Mini Framework

A minimal, TypeScript-based reactive framework for building lightweight web applications using component functions, simple state management, declarative DOM event binding, and client-side routing — with no external dependencies.


📆 Installation

npm install @moali1071/mini-framework

🚀 Quick Overview

This framework enables you to:

  • Build apps using function-based components that return HTML strings.
  • Manage reactive state scoped to a specific root.
  • Attach event listeners declaratively using data-on<event> attributes.
  • Handle routing with a simple route-to-component map.

🏗️ App Structure

A typical setup involves:

  1. An HTML container where your app will be mounted:

    <div id="app"></div>
  2. Function-based components that return template strings:

    // components/Home.ts
    export function Home(state) {
      return `<button data-onclick="increment">Count: ${state.count}</button>`;
    }
  3. An initial state object that includes all data tied to your root:

    const initialState = { count: 0 };
  4. **Calling **``, passing in your state and root element:

    const { state, mount, setHandlers } = render(initialState, document.getElementById("app"));
  5. Mounting components and setting event handlers:

    import { Home } from "./components/Home";
    import { handlers } from "./handlers/homeHandlers";
    
    mount(Home);
    setHandlers(handlers);

📘 API Reference

createDOMFromString(template: string): DocumentFragment

Converts an HTML string into a DocumentFragment you can insert into the DOM.

Used internally by render, but can also be used manually for DOM manipulation.


setupEvents(root: Element, handlers: { [key: string]: (e: Event) => void })

Scans the DOM for attributes like data-onclick="handlerName" and binds the relevant function from the handlers object.

  • The event type is derived from the attribute (data-onclick, data-oninput, etc.).
  • The handler name must match a key in the handlers object.
  • Used internally whenever a component mounts or rerenders.

createState<T>(initialState, onChange)

Creates a reactive state object.

Returns an object with:

  • getState() – returns the current state
  • setState(state) – updates the state
  • subscribe(callback) – runs the callback on every state change
  • state – the current state value (for reference only; prefer getState())

Used internally by render.


render<T>(initialState, rootElement)

Binds the given initialState to the specified DOM root.

Returns an object with:

  1. state – a state object containing:

    • getState() – fetches the latest state snapshot.
    • setState(partialState) – updates state properties and re-renders.
    • subscribe(callback) – run side effects when state changes.
    • state – a reference to the state object (avoid direct mutation).
  2. mount(component) – renders a component to the root. The component must be a function that accepts the state and returns a string.

  3. setHandlers(handlers) – sets all event handlers used by this root. Each key is the handler name, and the value is the function to run.


📝 Component Structure

A component must be a pure function that accepts a state object and returns a string.

function Counter(state) {
  return `
    <div>
      <p>Count: ${state.count}</p>
      <button data-onclick="increment">+</button>
    </div>
  `;
}

It is recommended (but not required) to place all components in a components/ directory for better organization.


🎯 Event Binding

You can declaratively add event listeners in templates using data-on<event> attributes:

<button data-onclick="increment">+</button>

These are mapped to handler functions via setHandlers():

setHandlers({
  increment: () => state.setState({ count: state.getState().count + 1 }),
});

It’s recommended to organize handler functions in files such as:

handlers/
  homeHandlers.ts
  profileHandlers.ts

initRouter<T>(routes, mount)

Sets up client-side routing using history.pushState.

Parameters:

  1. routes – An object where:

    • Keys are route paths (e.g., /, /about)
    • Values are the component functions to mount.

    Optionally, include a "404" key to render when the path isn't found.

  2. mount – The mount function returned from render(), used to display the component for the current route.

Returns:

  • navigate(path: string) – navigates to a route and renders the appropriate component.

Example:

const routes = {
  "/": Home,
  "/about": About,
  "404": NotFound,
};

const router = initRouter(routes, mount);

router.navigate("/about"); // navigates to /about and renders <About />

📂 Recommended Directory Structure

/my-app
  ├── index.html
  ├── main.ts
  ├── components/
  │   ├── Home.ts
  │   └── About.ts
  └── handlers/
      ├── homeHandlers.ts
      └── aboutHandlers.ts

📐 TypeScript Types

The framework includes the following helpful types:

EventHandlers

type EventHandlers = {
  [key: string]: (e: Event) => void;
};

Used with setupEvents() and render().setHandlers() to define your DOM event handlers.


StateObject<T>

type StateObject<T> = {
  state: T;
  setState: (newState: Partial<T>) => void;
  getState: () => T;
  subscribe: (fn: (state: T) => void) => void;
};

Returned from createState<T>() and from render().state. It represents your app's reactive state.


ComponentFn<T>

type ComponentFn<T> = (state: T) => string;

A function that returns an HTML string representation of the UI based on current state.


Routes<T>

type Routes<T> = {
  [path: string]: ComponentFn<T>;
};

Used in initRouter() to define your app's routes.