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

@digitalbooting/jsx

v1.0.32

Published

Custom JSX runtime for Web components

Readme

DBJSX

DBJSX is a modern, lightweight micro-framework for building modular web components using JSX, hooks, and a React-like API. It provides a simple system for building custom web components, Shadow DOM, scoped styles, and advanced state management.


Table of Contents


Goal

This documentation shows how to build custom web components using JSX, hooks, and a React-like API.

With this guide, you can build either individual components or your own installable library of custom web components via npm or yarn.


Installation

Install the package directly from npm or yarn:

yarn add @digitalbooting/jsx
# or
npm install @digitalbooting/jsx

This will add DBJSX as a dependency to your project. You do not need to clone the repository manually.

Your package.json should look something like this:

{
  "name": "jsxui",
  "version": "1.0.0",
  "description": "",
  "source": "./src/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build:prod": "webpack --mode production --config=webpack.config.js",
    "start": "webpack-dev-server --mode development --open --port 8888",
    "build": "webpack --config=webpack.config.js"
  },
  "author": "Your name",
  "license": "MIT",
  "devDependencies": {
    "@digitalbooting/jsx": "^1.0.3",
    "@babel/core": "^7.22.9",
    "@babel/plugin-proposal-class-properties": "^7.18.6",
    "@babel/plugin-proposal-decorators": "^7.22.7",
    "@babel/plugin-proposal-object-rest-spread": "7.20.7",
    "@babel/plugin-syntax-jsx": "^7.22.5",
    "@babel/plugin-transform-react-jsx": "^7.22.5",
    "@babel/preset-env": "^7.22.9",
    "@babel/preset-react": "^7.22.5",
    "@types/node": "20.4.6",
    "babel-loader": "9.1.3",
    "babel-plugin-module-alias": "^1.6.0",
    "babel-plugin-syntax-decorators": "^6.13.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.5",
    "html-webpack-plugin": "^5.5.3",
    "prettier": "^3.0.0",
    "svg-url-loader": "^8.0.0",
    "transform-class-properties": "^1.0.0-beta",
    "webpack": "5.88.2",
    "webpack-cli": "5.1.4",
    "webpack-dev-server": "^4.15.1",
    "yarn": "^1.22.19"
  }
}

You need to add this to your babel.config.json:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "plugins": [
    [
      "@babel/plugin-transform-react-jsx",
      {
        "throwIfNamespace": false,
        "runtime": "automatic",
        "allowSyntheticDefaultImports": true,
        "importSource": "@digitalbooting/jsx"
      }
    ],
    [
      "@babel/plugin-proposal-decorators",
      { "legacy": true }
    ],
    "@babel/plugin-proposal-class-properties",
    "@babel/proposal-object-rest-spread",
    "babel-plugin-module-alias"
  ]
}

Also, don't forget to configure your webpack.config.js:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development",
  watchOptions: {
    ignored: "**/node_modules",
    aggregateTimeout: 600,
  },
  entry: path.resolve(__dirname, "src"),
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "dist"),
  },
  resolve: {
    alias: {
      "@src/*": path.resolve(__dirname, "src/*.js"),
      "@components": path.resolve(__dirname, "src/components/index.js"),
      "@modules": path.resolve(__dirname, "src/modules/index.js"),
    },
    extensions: [".js", ".jsx", ".json"],
  },
  module: {
    rules: [
      {
        test: /\.(js)x?$/,
        loader: "babel-loader",
        exclude: /node_modules/,
      },
      {
        test: /\.svg$/,
        use: [
          {
            loader: "svg-url-loader",
            options: { limit: 10000 },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "webpack-dev-server",
      template: path.resolve(__dirname, "index.html"),
    }),
  ],
};

I've also configured the jsconfig.json file so you can use aliases in your project:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "NodeNext",
    "rootDir": "./",
    "moduleResolution": "NodeNext",
    "resolvePackageJsonExports": true,
    "resolvePackageJsonImports": true,
    "resolveJsonModule": true,
    "importHelpers": true,
    "strict": true,
    "allowSyntheticDefaultImports": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noImplicitAny": true,
    "baseUrl": "./",
    "paths": {
      "@src": ["src"],
      "@components": ["src/components/index.js"],
      "@modules": ["src/modules/index.js"]
    }
  },
  "exclude": ["node_modules", "dist"]
}

Suggested Project Structure

./
  src/
    components/       # Main components for registration
      HelloWorld.js     # Simple component
      index.js          # Entry point to export your components
  index.js            # Application entry point
  index.html          # Application entry point
  babel.config.json   # Babel configuration
  webpack.config.js   # Webpack configuration
  jsconfig.json       # jsconfig configuration

Once everything is configured, you can start building your components.

Getting Started

1. Register Your First Component

Create a simple component in src/components/HelloWorld.js:

import { connect } from "@digitalbooting/jsx";

function HelloWorld() {
  return <div>Hello, World!</div>;
}

connect(HelloWorld, { component: "hello-world" });

This allows you to create a custom element using JSX as the rendering engine.

No need for tagged template literals, as @digitalbooting/jsx uses JSX to render your components.

This is made possible by @babel/plugin-transform-react-jsx and other packages.

Register your component (usually in your app entry point):

import "./components/HelloWorld";

Now you can use <hello-world></hello-world> in your HTML!

The base project configuration includes an index.html so you can test your component using webpack-dev-server.


Core Concepts

Component Registration

  • Use connect from @digitalbooting/jsx to register any function as a custom element.
  • connect is a function that takes two arguments: the function you want to register and an object with the custom element configuration.
{
  "component": string, // custom element name
  "observerProps": string[], // list of observed attributes
  "stylesheet": string // css for the custom element
}
  • Supports Shadow DOM, attribute-to-prop mapping, and hook context.
  • Example:
import { connect } from "@digitalbooting/jsx";

const MyButton = (props) => {
  return <button>{props.label}</button>;
};

export default connect(MyButton, { component: "my-button" });

You can specify the custom element name in config.component or omit it to generate a default name based on the function name.

In config.observerProps, you can specify a list of attributes you want to observe, which will become props of the component.

In config.stylesheet, you can specify CSS for the custom element.

Runtime Rendering

Internally, connect uses createElement.

  • The createElement function in @digitalbooting/jsx/runtime handles transpiling JSX and creating the DOM node with its attributes, props, and internal events.
  • connect registers the custom element and manages its lifecycle, returning a class that extends HTMLElement and builds the native component.
  • Supports functional components, virtual components, and fragment syntax.

@digitalbooting/jsx provides a render method that renders JSX into the DOM without the need for AngularJS or React. It's mainly for use with Vanilla JS, and if you've used ReactJS, it will feel familiar to React DOM.

import { render, connect } from "@digitalbooting/jsx";

function MyButton(props) {
  return <button>{props.label}</button>;
}

// Additional step to register the custom element *(V-DOM)*
const element = connect(MyButton, { component: "my-button" });
// Render the component into the real DOM
render(element, document.body.getElementById("root"));

It's recommended to insert the custom element directly in the HTML:

<my-button label="Click me"></my-button>

Hooks

DBJSX offers React-style hooks for state, effects, refs, context, and more. All hooks are in @digitalbooting/jsx and can be used directly in your components:


Examples

Basic Component

import { connect } from "@digitalbooting/jsx";

function BasicGreeting() {
  return <span>Hello, World!</span>;
}

export default connect(BasicGreeting, { component: "basic-greeting" });

Intermediate Component (Props & Styles)

import { connect } from "@digitalbooting/jsx";
import { useProp, useStyles } from "@digitalbooting/jsx";

function FancyButton(props) {
  const [label, setLabel] = useProp("label", "Click me");
  useStyles(
    () =>
      `button {
        color: white;
        background: #007bff;
        padding: 8px 16px;
        border: none;
        border-radius: 4px;
      }`,
    []
  );

  return <button onclick={() => setLabel("Clicked!")}>{label}</button>;
}

export default connect(FancyButton, { component: "fancy-button" });

Advanced Component (Hooks & State)

import { connect } from "@digitalbooting/jsx";
import { useState, useEffect, useAttributes } from "@digitalbooting/jsx";

function Timer(props) {
  const [attrs, setAttrs] = useAttributes({ start: 0 });
  const [count, setCount] = useState(attrs.start);

  useEffect(() => {
    const interval = setInterval(() => setCount((c) => c + 1), 1000);
    return () => clearInterval(interval);
  }, []);

  return <div>Timer: {count}</div>;
}

export default connect(Timer, { component: "timer-widget" });

Advanced Example: Modal <ui-modal>

Below is how to create a reusable modal component and how to integrate it into projects with different frameworks.

1. Building the Modal (with useModel and useExpose)

import {
  connect,
  useModel,
  useExpose,
  useEvent,
  useEffect
} from "@digitalbooting/jsx";

function UIModal({ open, onClose, children }) {
  // Sync the 'open' attribute with the modal state (two-way binding)
  const [isOpen, setIsOpen] = useModel("open", false);

  // Expose public methods to control the modal from outside
  useExpose({
    open: () => setIsOpen(true),
    close: () => setIsOpen(false),
    toggle: () => setIsOpen((prev) => !prev),
  });

  // Dispatch custom "close" event when closing
  const dispatch = useEvent();
  const handleClose = () => {
    setIsOpen(false);
    dispatch("close");
    onClose?.();
  };

  useEffect(() => {
    // Side effects when modal opens/closes
    if (isOpen) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
    return () => (document.body.style.overflow = "");
  }, [isOpen]);

  return (
    <dialog open={isOpen ? "open" : undefined} onclose={handleClose}>
      <div style="background: white; margin: 10% auto; padding: 2rem; border-radius: 8px; min-width: 300px; max-width: 90vw; position: relative;">
        <button
          style="position: absolute; top: 10px; right: 10px;"
          onclick={handleClose}
        >
          ✕
        </button>
        {children}
      </div>
    </dialog>
  );
}

export default connect(UIModal, {
  component: "ui-modal",
  observerProps: ["open"],
  stylesheet: `
    dialog {
      background: white;
      margin: 10% auto;
      padding: 2rem;
      border-radius: 8px;
      min-width: 300px;
      max-width: 90vw;
      position: relative;
    }
    button {
      position: absolute;
      top: 10px;
      right: 10px;
    }
  `,
});

Advanced usage:

You can control the modal from outside using JavaScript:

const modal = document.querySelector("ui-modal");
modal.api.open(); // Open the modal
modal.api.close(); // Close the modal
modal.api.toggle(); // Toggle the state

Debugging and Debug Mode

DBJSX includes visual debugging tools and hooks/render tracking.

  • debug attribute: If you add the debug attribute to any custom element generated with DBJSX, you'll see detailed information in the console about hooks, renders, and state changes.
<ui-modal debug></ui-modal>
  • What does it show?

    • Number of component renders
    • State of each hook (useState, useEffect, etc.)
    • Changes to props and attributes
    • Render times
  • How does it work?

    • Internally uses the debugHooks hook, which logs useful information to the console whenever the component renders or state changes.
  • Tip: Use it only in development, as it can generate a lot of console output.


Basic HTML usage:

<ui-modal open="true"></ui-modal>

You can control visibility by changing the open attribute and react to the custom close event.


Integrating <ui-modal> with Popular Frameworks

React (SPA and SSR)

  1. Import and wrap the custom element in React:
import React, { useState, useEffect } from "react";

function ModalWrapper() {
  const [open, setOpen] = useState(false);
  const [mounted, setMounted] = useState(false);

  const fetchModal = async () => {
    try {
      await import("https://unpkg.com/tulibreria/@1.0.0/dist/v1/ui-modal");
      setMounted(true);
    } catch (error) {
      console.error("Error loading custom element:", error);
    }
  };

  useEffect(() => {
    fetchModal();
  }, []);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Modal</button>
      {mounted && (
        <ui-modal
          open={open ? "true" : undefined}
          onclose={() => setOpen(false)}
        >
          <h2>Modal Content</h2>
          <p>Hello from the modal!</p>
        </ui-modal>
      )}
    </>
  );
}
  • SSR (Next.js, Remix): Make sure to import the custom element only on the client (use useEffect or lazy load)

Angular (Standalone Components, Angular 16+ / 19 recommended)

  1. Import the custom element once (in main.ts or the main entry):
import "tulibreria/dist/v1/ui-modal";
  1. Declare your standalone component:
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";

@Component({
  selector: "app-root",
  standalone: true,
  template: `
    <button (click)="modalOpen = true">Open Modal</button>
    <ui-modal
      [attr.open]="modalOpen ? 'true' : null"
      (close)="modalOpen = false"
    >
      <h2>Modal Content</h2>
    </ui-modal>
  `,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppComponent {
  modalOpen = false;
}
  1. No need for NgModule, just bootstrap your standalone component:
import { bootstrapApplication } from "@angular/platform-browser";
import { AppComponent } from "./app.component";

bootstrapApplication(AppComponent);

Note: Custom elements work natively in Angular standalone. Just remember to import the web component script once at the start of the app (main.ts).

Vue

  1. Import the custom element in your entry (main.js):
import "tulibreria/dist/v1/ui-modal";
  1. Use the tag in your components:
<ui-modal :open="modalOpen" @close="modalOpen = false">
  <h2>Modal Content</h2>
</ui-modal>

Astro

  1. Import the custom element globally in your layout or page:
import "tulibreria/dist/v1/ui-modal";
  1. Use the tag in your .astro files or components:
<ui-modal open="true">
  <h2>Modal in Astro</h2>
</ui-modal>

HTML5 (Vanilla JS)

  1. Include the custom element script:
<script
  type="module"
  src="https://unpkg.com/tulibreria/@1.0.0/dist/v1/ui-modal.js"
></script>
  1. Use the tag directly:
<ui-modal open="true">
  <h2>Vanilla Modal</h2>
</ui-modal>

Notes:

  • You can customize the modal with slots, styles, and custom events.
  • The <ui-modal> component is framework-agnostic and works the same in any modern environment.
  • For SSR, make sure to import the custom element only on the client (when the DOM is available).

Documentation


Author


Contributors


Contribution

The project is open for contributions. If you have any ideas or suggestions, please open an issue or pull request.


License

MIT

function FancyButton(props) { const [label, setLabel] = useProp('label', 'Click Me'); useStyles(() => button { color: white; background: #007bff; padding: 8px 16px; border: none; border-radius: 4px; });

return <button onclick={() => setLabel('Clicked!')}>{label}; }

connect(FancyButton, { component: 'fancy-button' });


---

### Advanced Component (Hooks & State)
```js
import { connect } from '../core/component';
import { useState, useEffect } from '../hooks';
import { useAttributes } from '../hooks/useAttributes';

function Timer(props) {
  const [attrs, setAttrs] = useAttributes({ start: 0 });
  const [count, setCount] = useState(attrs.start);

  useEffect(() => {
    const interval = setInterval(() => setCount((c) => c + 1), 1000);
    return () => clearInterval(interval);
  }, []);

  return <div>Timer: {count}</div>;
}

connect(Timer, { component: 'timer-widget' });

License

MIT

DBJSX is not a React or Preact clone, it is a light -runtime JSX Runtime, based on Ecmascript 2023, the objective is to allow the construction of web -based modularized interfaces components.Taking advantage of the flexibility that JSX provides to build the templates of your web components.

Getting Started

Create a new project based with npm

npm init

Add index.js in your root project folder

--project_folder
    -- components
        index.js
    -- modules
        --index.js  
    -- index.js
    -- index.html
    -- babel.config.js
    -- jsconfig.json
    --webpack.config.js
	-- package.json  (this file generated with npm init command)

Modify your package.json for install dependencies Babel, Webpack and others. Your Package.json file must be similar to this:

{
    "name":  "yourpackage",
    "version":  "1.0.0",
    "description":  "",
    "source":  "./src/index.js",
    "scripts":  {
	    "test":  "echo \"Error: no test specified\" && exit 1",
	    "build:prod":  "webpack --mode production --config=webpack.config.js",
	    "start":  "webpack-dev-server --mode development --open --port 8888",
	    "build":  "webpack --config=webpack.config.js"
    },
    "author":  "Your name",
    "license":  "MIT",
    "devDependencies":  {
	    "@babel/core":  "^7.22.9",
	    "@babel/plugin-proposal-class-properties":  "^7.18.6",
	    "@babel/plugin-proposal-decorators":  "^7.22.7",
	    "@babel/plugin-proposal-object-rest-spread":  "7.20.7",
	    "@babel/plugin-syntax-jsx":  "^7.22.5",
	    "@babel/plugin-transform-react-jsx":  "^7.22.5",
	    "@babel/preset-env":  "^7.22.9",
	    "@babel/preset-react":  "^7.22.5",
	    "@types/node":  "20.4.6",
	    "babel-loader":  "9.1.3",
	    "babel-plugin-module-alias":  "^1.6.0",
	    "babel-plugin-syntax-decorators":  "^6.13.0",
	    "babel-plugin-transform-class-properties":  "^6.24.1",
	    "babel-plugin-transform-decorators-legacy":  "^1.3.5",
	    "html-webpack-plugin":  "^5.5.3",
	    "prettier":  "^3.0.0",
	    "svg-url-loader":  "^8.0.0",
	    "transform-class-properties":  "^1.0.0-beta",
	    "webpack":  "5.88.2",
	    "webpack-cli":  "5.1.4",
	    "webpack-dev-server":  "^4.15.1",
	    "yarn":  "^1.22.19"
    }
}

Add this module in your proyect with yarn or npm:

yarn add -D dbjsx
npm install --save-dev dbjsx

Your Package.json file updated with added dbjsx:

 {
     "devDependencies":  {
        "dbjsx":  "^1.0.0"
     }
 }

Execute install command with yarn or npm:

yarn install
npm install

Now we will configure Babel to be able to compile our JSX code

{
    "presets":  [
	    "@babel/preset-env",
	    ""babel/preset-react"
    ],
    "plugins":  [
	    [
		    "@babel/plugin-transform-react-jsx",
		    {
			    "throwIfNamespace":  false,
			    "runtime":  "automatic", //set the automatic runtime
			    "allowSyntheticDefaultImports":  true,
			    "importSource":  "dbjsx" //set the dbjsx package
		    }
	    ],
	    [
		    "@babel/plugin-proposal-decorators",
		    {
			    "legacy":  true
		    }
	    ],
	    "@babel/plugin-proposal-class-properties",
	    "@babel/proposal-object-rest-spread",
	    "babel-plugin-module-alias"
    ]
}

Now add the jsconfig.json file into root project folder

{
    "compilerOptions":  {
	    "target":  "ESNext",
	    "module":  "ESNext",
	    "rootDir":  "./",
	    "moduleResolution":  "NodeNext",
	    "resolvePackageJsonExports":  true,
	    "resolvePackageJsonImports":  true,
	    "resolveJsonModule":  true,
	    "importHelpers":  true,
	    "strict":  true,
	    "allowSyntheticDefaultImports":  true,
	    "noUnusedParameters":  true,
	    "noImplicitReturns":  true,
	    "noUnusedLocals":  true,
	    "noImplicitAny":  true,
	    "baseUrl":  "./", // define base url for relative routes
	    "paths":  { // add relative paths
		    "@src":  [
			    "src"
		    ],
		    "@components":  [
			    "src/components/index.js"
		    ],
		    "@modules":  [
			    "src/modules/index.js"
		    ]
	    }
    },
    "exclude":  [
	    "node_modules",
	    "dist"
    ]
}

Finally Rest Configure Webpack to compile our code

const path =  require('path')
const HtmlWebpackPlugin =  require('html-webpack-plugin')

module.exports  = {
	mode:  'development',
	watchOptions: {
		ignored:  '**/node_modules',
		poll:  1000,
		aggregateTimeout:  600,
	},
	entry: path.resolve(__dirname, 'src'),
	output: {
		filename:  '[name].js',
		path: path.resolve(__dirname, 'dist'),
	},
	resolve: {
    	// Here also configures the alias of relative routes
		alias: {
			'@src/*': path.resolve(__dirname, 'src/*.js'),
			'@components': path.resolve(__dirname, 'src/components/index.js'),
			'@modules': path.resolve(__dirname, 'src/modules/index.js'),
		},
		extensions: ['.js', '.jsx', '.json'],
	},
	module: {
	rules: [
		{
			test: /\.(js)x?$/,
			loader:  'babel-loader',
			exclude: /node_modules/,
		},
		{
			test: /\.svg$/,
			use: [
				{
				loader:  'svg-url-loader',
				options: {
					limit:  10000,
				},
				},
			],
		},
	],
	},
	plugins: [
		new  HtmlWebpackPlugin({
		title:  'webpack-dev-server',
		template: path.resolve(__dirname, 'index.html'),
		}),
	],
}

Lets create a index.html with this code:

<!DOCTYPE  html>
<html  lang="en">
    <head>
	    <meta  charset="UTF-8">
	    <meta  name="viewport"  content="width=device-width, initial-scale=1.0">
	    <title>DBJSX Runtime developed by Digital Booting</title>
    </head>
    <body>
	    <div id="root"></div>
    </body>
</html>

Now edit your index.js and add this code example:

import { css, jsx, createElement, render } from  'dbjsx'

const styles =  css`
    font-size:  50px;
    background-color:  aliceblue;
    color:  blanchedalmond;
`
const  App  =  ()  => {
    return (
	    <div  className="hola">
		    <h2>titulo generado mediante jsx</h2>
	    </div>
    )
}

const $jsx =  App()
const element =  createElement($jsx)
render(element, document.getElementById('root')) 

Now init the project with yarn or npm

yarn start
npm start

NOTE: This example only serves to show the compilation JSX rendering in the Dom a Div with an H2 element, in next version we will add examples of web rendering components.

It is important to understand the concept of JSX rendering before creating complex applications, this will allow you a greater learning curve

CONTRIBUTION

Feel free to contribute and contribute to this project, you can send an email to [email protected] and know the Road map we have in mind.

OBJETIVES

Our goal is to create a JSX rendering core that can be used both in large projects and small projects and personal modules, it has happened to me that I sometimes want to create some basic components that I use a lot and I do not want to be developing them in each novel JavaScript framework,And much less have a large alject with many units.

With DBJSX, the only thing you need is to create the main environment, develop your applications, modules or components once and use any project.The objective is to take advantage of all the benefits of the web components and of course as personnel developer personally there is nothing more great than using JSX to handle templates without depending on large compilations or React.

If you have experience in the management of JSX, all your contribution is welcome!