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

@webtaku/any-builder

v0.0.1

Published

A small, type-safe utility that enables **shared component APIs** using the same selector-based syntax across **HTML string builders** and **DOM element builders**.

Readme

@webtaku/any-builder

A small, type-safe utility that enables shared component APIs using the same selector-based syntax across HTML string builders and DOM element builders.

This allows you to write components once and reuse them with both @webtaku/h (HTML strings) and @webtaku/el (DOM elements).


Features

  • Component builder abstraction via AnyBuilder

  • Type-safe Selector syntax (div#id.class)

  • Write a component only once and use it for:

    • HTML string generation (h)
    • DOM element creation (el)
  • Supports attributes, DOM properties, dataset, ARIA attributes, and inline styles

  • Simple and composable API


Installation

yarn add @webtaku/any-builder

or

npm install @webtaku/any-builder

Note: You will typically use this together with @webtaku/h or @webtaku/el.


API

AnyBuilder

Represents a builder function such as h or el.

type AnyBuilder = <S extends Selector>(
  selector: S,
  ...args: (HTMLElement | string | ElementProps<S> | null | undefined)[]
) => ElementBySelector<S> | string;

Parameters

  • selector: A string such as div, span#my-id, p.my-class, section#id.class

  • ...args:

    • HTMLElement — appended as a child node (or rendered as outerHTML)
    • string — added as text or raw HTML
    • ElementProps<S> — sets properties, attributes, or inline styles

Returns

A union type:

| Builder | Return Type | | ------- | --------------------------- | | h | string (HTML string) | | el | HTMLElement (DOM element) |


Shared Types

The package exports shared selector, element inference, and props types:

type Selector =
  | Tag
  | `${Tag}#${string}`
  | `${Tag}.${string}`
  | `${Tag}#${string}.${string}`;

type ElementBySelector<S extends Selector> = /* inferred HTML element type */;

type ElementProps<S extends Selector> =
  & Partial<Omit<ElementBySelector<S>, 'style'>>
  & {
    style?: Partial<CSSStyleDeclaration> | string;
    class?: string;
    dataset?: Record<string, string | number | boolean | null | undefined>;
    role?: string;
  }
  & DataAttributes
  & AriaAttributes;

| Supported Attribute Types | | | | | ----------------------------------------- | -------- | ------ | --------- | | DOM properties | | | | | HTML attributes | | | | | inline styles (object or string form) | | | | | data-* | aria-* | role | dataset |


Usage

Writing a Shared Component

// components/Button.ts
import type { AnyBuilder } from '@webtaku/any-builder';

type ButtonProps = {
  label: string;
  href?: string;
};

export function Button(b: AnyBuilder, { label, href }: ButtonProps) {
  if (href) {
    return b('a.button', label, { href, role: 'button' });
  }
  return b('button.button', label, { type: 'button' });
}

Rendering as HTML String (@webtaku/h)

import { h } from '@webtaku/h';
import { Button } from './Button';

console.log(Button(h, { label: 'Home', href: '/' }));
// <a class="button" href="/" role="button">Home</a>

Rendering as DOM Element (@webtaku/el)

import { el } from '@webtaku/el';
import { Button } from './Button';

document.body.appendChild(
  Button(el, { label: 'Home', href: '/' })
);

Selector Syntax

The same selector rules as in @webtaku/h and @webtaku/el.

| Selector String | Output / Meaning | | --------------------- | ----------------------------------- | | '' | <div> | | 'span' | <span> | | 'div#app' | <div id="app"> | | 'p.text' | <p class="text"> | | 'section#main.hero' | <section id="main" class="hero"> | | 'my-element' | <my-element> (custom element tag) |


ElementProps

Provides type-safe props based on the selector result.

{
  style?: Partial<CSSStyleDeclaration> | string;
  class?: string;
  dataset?: Record<string, string | number | boolean | null | undefined>;
  role?: string;
  [prop: string]: any;
}

Example

b('button.primary',
  'Save',
  {
    type: 'button',
    style: { color: 'white' },
    'data-type': 'primary',
    'aria-label': 'Save changes'
  }
);

Example: Layout Component

import type { AnyBuilder } from '@webtaku/any-builder';

export function Layout(b: AnyBuilder, title: string, body: string) {
  return b('div#app.container',
    b('header.header', b('h1', title)),
    b('main.content', body),
    b('footer.footer', '© 2025 Webtaku')
  );
}

HTML Rendering

import { h } from '@webtaku/h';
console.log(Layout(h, 'Hello', 'Rendered using h().'));

DOM Rendering

import { el } from '@webtaku/el';
document.body.appendChild(Layout(el, 'Hello', 'Rendered using el().'));

License

MIT OR Apache-2.0


Contributing

Contributions are welcome. Feel free to open issues or submit pull requests to improve the library.