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

@jasonshimmy/custom-elements-runtime

v3.7.4

Published

A powerful, modern, and lightweight runtime for creating reactive web components with TypeScript

Downloads

3,152

Readme

🧩 Custom Elements Runtime

Patreon

The Complete Web Components Framework

Build modern components with strict TypeScript, zero dependencies, and a clean functional API. Designed for speed, standards compliance, and productivity.

✨ Why You'll Love It

  • Blazing Fast: Minimal runtime, instant updates, zero dependencies.
  • 🎨 JIT CSS: On-demand, utility-first styling directly in your HTML at runtime.
  • 💪 No Build Necessary: Instant development feedback, no bundling required.
  • 🧑‍💻 TypeScript First: Strict types, intellisense, and safety everywhere.
  • 🧩 Functional API: No classes, no boilerplate—just pure functions.
  • 🛠️ SSR & HMR Ready: Universal rendering and instant hot reloads.
  • 🔌 Extensible: Directives, event bus, store, and more for advanced use cases.
  • 🏆 Developer Friendly: Clean docs, examples, and a welcoming community.

⏱️ Getting Started

  1. Install: npm install @jasonshimmy/custom-elements-runtime
  2. Create a Component:
import {
  component,
  defineModel,
  html,
} from '@jasonshimmy/custom-elements-runtime';
import { useJITCSS } from '@jasonshimmy/custom-elements-runtime/jit-css';

component('my-counter', () => {
  useJITCSS();

  const count = defineModel('count', 0);

  const handleClick = () => {
    count.value++;
  };

  return html`
    <button
      type="button"
      class="px-4 py-2 bg-primary-500 text-white rounded"
      @click.prevent="${handleClick}"
    >
      Count: ${count.value}
    </button>
  `;
});
  1. Use in HTML:
<my-counter count="5"></my-counter>

<script>
  const myCounter = document.querySelector('my-counter');
  myCounter.addEventListener('update:count', (event) => {
    myCounter.setAttribute('count', event.detail);
    console.log('Count updated to:', event.detail);
  });
</script>
  1. Enjoy instant reactivity and type safety!

📦 Complete API Reference

Below is the complete list of public symbols exported by the runtime and its named subpaths (root entry + subpath entries).

Root Entry

Package: @jasonshimmy/custom-elements-runtime

| Export | Description | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | component | Define a custom element with the functional component API. | | html | Template tag function producing runtime VNodes from template literals. | | css | Define component-scoped/JIT styles or register stylesheets. | | ref | Create a reactive reference object with a .value property. | | computed | Create a memoized, derived read-only value from other reactive sources. | | watch | Register watchers reacting to changes in reactive values. | | watchEffect | Auto-track reactive reads and re-run a side-effect whenever dependencies change. | | nextTick | Returns a Promise resolving after all pending DOM updates are flushed. | | flushDOMUpdates | Synchronously flush all pending DOM update tasks (useful in tests). | | scheduleWithPriority | Schedule a callback at a given UpdatePriority level. | | provide | Store a value on the current component for descendant injection. | | inject | Retrieve a value provided by an ancestor component. | | createComposable | Package reusable stateful logic (hooks, reactive state) into a composable. | | getCurrentComponentContext | Access the active component context from within a composable or render function. | | useProps | Hook to declare/consume typed component props with defaults. | | defineModel | Declare a two-way model binding prop; combines useProps + useEmit in one ergonomic hook. | | useEmit | Hook returning an emit function for dispatching custom events. | | useOnConnected | Hook that runs a callback when the component connects. | | useOnDisconnected | Hook that runs a callback when the component disconnects. | | useOnAttributeChanged | Hook observing host attribute changes. | | useOnError | Hook to register a component-level error handler. | | useStyle | Hook to register or compute component styles at runtime. | | useDesignTokens | Apply typed design token overrides to :host as CSS custom properties. | | useGlobalStyle | Inject CSS into document.adoptedStyleSheets, escaping Shadow DOM encapsulation. Use sparingly. | | useExpose | Publish methods and properties onto the host element as an imperative public API. | | useSlots | Inspect which named slots have been filled by the component consumer. | | useTeleport | Render virtual DOM content into any DOM node outside the shadow root. | | registerKeepAlive | Register <cer-keep-alive> to preserve component state across DOM removals. | | registerSuspense | Register the <cer-suspense> built-in component. | | registerErrorBoundary | Register the <cer-error-boundary> built-in component. | | registerBuiltinComponents | Register <cer-keep-alive>, <cer-suspense> and <cer-error-boundary> in one call. | | unsafeHTML | Insert raw HTML into a template (unsafe; use carefully). | | decodeEntities | Utility to decode HTML entities in strings. | | setDevMode | Toggle dev-mode logging on or off at runtime. | | devLog | Log a message to the console in dev mode only (no-op in production). | | isReactiveState | Type-guard returning true when a value is a ReactiveState instance. | | createHealthMonitor | Create a new health monitor instance (factory; each call returns an independent instance). | | getHealthMonitor | Return the global singleton health monitor instance (lazily created). | | updateHealthMetric | Update a named metric on the global singleton health monitor. | | getHealthStatus | Return the current HealthReport from the global singleton health monitor. | | hydrateApp | Trigger hydration of all DSD-rendered custom elements within a root (call after registering all components on the client). | | Types | ModelRef, HealthMonitorInstance, HealthReport, UpdatePriority, TeleportHandle, ReactiveState, VNode, JITCSSOptions, DesignTokens, ComponentOptions, HydrateStrategy |


Directives

Package: @jasonshimmy/custom-elements-runtime/directives

| Export | Description | | ------------- | ------------------------------------------------------------------ | | when | Conditional rendering: render children when the condition is true. | | each | Iterate arrays and render a VNode per item with stable keys. | | match | Fluent branching API (when/otherwise/done) returning VNodes. | | anchorBlock | Create a stable anchor VNode used as block boundaries. |


Directive Enhancements

Package: @jasonshimmy/custom-elements-runtime/directive-enhancements

| Export | Description | | ------------------ | ------------------------------------------------------------------------ | | unless | Inverse of when (render when condition is false). | | whenEmpty | Render content when a collection is empty or null. | | whenNotEmpty | Render content when a collection has items. | | eachWhere | Filter + iterate; render only items matching a predicate. | | switchOnLength | Render different content based on array length cases. | | eachGroup | Group array items by a key and render per-group content. | | eachPage | Render a paginated subset (page) of items. | | switchOnPromise | Render loading/success/error/idle states for async data. | | whenMedia | Render content when a CSS media query matches. | | mediaVariants | Map of responsive media queries (sm, md, lg, xl, 2xl, dark). | | responsiveOrder | Ordered breakpoint keys used by responsive helpers. | | responsive | Per-breakpoint helpers (sm/md/lg/xl/2xl/dark). | | whenVariants | Compose multiple variants (e.g., dark + lg) into one media query. | | responsiveSwitch | Render different content for different breakpoints. | | switchOn | Fluent switch/case API matching a value to content. |


Transitions

Package: @jasonshimmy/custom-elements-runtime/transitions

| Export | Description | | ------------------------- | ------------------------------------------------------------------------------------- | | Transition | Wrap content with enter/leave transition metadata consumed by the runtime. | | TransitionGroup | Animate lists with enter/leave/move transitions for children. | | transitionPresets | Built-in transition presets (fade, slide, scale, etc.). | | createTransitionPreset | Create a reusable transition preset programmatically. | | getTransitionStyleSheet | Obtain the CSSStyleSheet used by the transition runtime. | | Types | TransitionClasses, TransitionHooks, TransitionOptions, TransitionGroupOptions |


Event Bus

Package: @jasonshimmy/custom-elements-runtime/event-bus

| Export | Description | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ | | EventHandler | Type: callback signature used by the event bus. | | GlobalEventBus | Class: singleton implementing a global pub/sub event bus. | | eventBus | Proxy: lazy proxy to the singleton GlobalEventBus instance. | | emit | Emit a global event with an optional payload. | | on | Register a handler for a global event (returns unsubscribe function). | | off | Remove a handler for a global event. | | once | One-time listener. Callback form once(name, handler)void. Promise form once(name)Promise<T>. Do not mix. | | listen | Listen for native CustomEvent on the global event bus (returns unsubscribe). |


Store

Package: @jasonshimmy/custom-elements-runtime/store

| Export | Description | | ------------- | ----------------------------------------------------------- | | Store | Interface describing subscribe / getState / setState. | | createStore | Create a simple observable store that notifies subscribers. |


Router

Package: @jasonshimmy/custom-elements-runtime/router

| Export | Description | | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | useRouter | Create and use a router instance configured with routes (client & SSR). | | initRouter | Initialize the router and register router-view / router-link. | | matchRoute | Match a path against configured routes and extract params. | | matchRouteSSR | SSR-friendly wrapper for route matching. Automatically strips query strings and URL fragments before matching, so req.url can be passed directly. | | findMatchedRoute | Find the first matching route entry from an array of routes (lower-level helper). | | parseQuery | Parse a query string into a key/value map. | | serializeQuery | Serialize a key/value map into a query string (e.g. ?a=b). | | normalizePathForRoute | Normalize a path string for consistent route matching (strips trailing slashes, etc.). | | DEFAULT_SCROLL_CONFIG | Default scroll-to-fragment configuration object used by the router. | | isDangerousScheme | Returns true for dangerous URL schemes (e.g. javascript:). | | isAbsoluteUrl | Returns true when a URL string is absolute (has a protocol). | | safeDecode | Decode a URI component, returning the original string on error. | | canonicalizeBase | Normalize a router base path string (strips trailing slashes, ensures leading slash). | | resolveRouteComponent | Resolve/load a route's component (supports async loaders + caching). | | clearComponentCache | Clear the resolved route component cache (useful for testing and HMR). | | activeRouterProxy | Stable proxy to the currently active router; forwards subscriptions and method calls (advanced/testing use). | | Types | Route, RouteState, RouteComponent, GuardResult, RouterLinkProps, RouterLinkComputed, RouterConfig, Router |


SSR

Package: @jasonshimmy/custom-elements-runtime/ssr

| Export | Description | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | renderToString | Render a VNode tree to HTML for server-side rendering (backwards-compatible baseline). | | renderToStringWithJITCSS | Render to HTML + pre-generate JIT CSS. Pass dsd: true for Declarative Shadow DOM output with full per-shadow-root CSS stack. | | renderToStringWithJITCSSDSD | Recommended. Convenience alias: renderToStringWithJITCSS(vnode, { dsd: true, ... }). Full DSD output, hydration-ready, zero FOUC. Requires a single root VNode — wrap multi-element templates in one container. | | renderToStringDSD | Render to DSD HTML string (no JIT CSS pipeline). Appends DSD polyfill by default. | | renderToStream | Render to a ReadableStream<string> for streaming SSR / chunked transfer encoding. | | DSD_POLYFILL_SCRIPT | Minified inline <script> that implements DSD for Firefox < 123. Injected automatically; export it for manual placement. | | registerEntityMap | Register a custom named-entity map for SSR decodeEntities. | | loadEntityMap | Async loader for the full HTML5 named-entity map. | | clearRegisteredEntityMap | Reset the entity map to the built-in minimal set. | | VNode (type) | The runtime VNode shape used by renderers and SSR. | | RenderOptions (type) | Options for renderToString (injectSvgNamespace, injectKnownNamespaces). | | DSDRenderOptions (type) | Options for DSD rendering (dsd, dsdPolyfill, plus all RenderOptions). | | SSRJITResult (type) | Result of renderToStringWithJITCSS: { html, css, globalStyles, htmlWithStyles }. |

SSR Middleware

Package: @jasonshimmy/custom-elements-runtime/ssr-middleware

Framework-agnostic handler factories for Express, Fastify, Hono, and raw Node.js.

| Export | Description | | ----------------------------- | --------------------------------------------------------------------------------------------------------- | | createSSRHandler | Returns an async (req, res) handler that SSR-renders a VNode and sends the full HTML document response. | | createStreamingSSRHandler | Returns an async (req, res) handler that streams the rendered HTML using chunked transfer encoding. | | MinimalRequest (type) | Minimal { url?, method?, headers? } interface compatible with all major Node.js HTTP frameworks. | | MinimalResponse (type) | Minimal { setHeader, write?, end } interface compatible with all major Node.js HTTP frameworks. | | SSRMiddlewareOptions (type) | Options for createSSRHandler and createStreamingSSRHandler. |

Global Styles (CSS)

Package: @jasonshimmy/custom-elements-runtime/css or @jasonshimmy/custom-elements-runtime/css/style.css

| Export | Description | | ----------- | -------------------------------------------------------- | | style.css | CSS export that contains CSS variables and a base reset. |

Variables (CSS)

Package: @jasonshimmy/custom-elements-runtime/css/variables.css

| Export | Description | | --------------- | ------------------------------------------------------------- | | variables.css | CSS export that contains design tokens (colors, fonts, etc.). |

Reset (CSS)

Package: @jasonshimmy/custom-elements-runtime/css/reset.css

| Export | Description | | ----------- | ------------------------------------------------- | | reset.css | CSS export that contains a base reset for styles. |

Extended Color Palette (TypeScript)

Package: @jasonshimmy/custom-elements-runtime/css/colors

Opt-in extended color palette with full Tailwind-compatible color names (slate, gray, zinc, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose) with shades 50–950.

import { extendedColors } from '@jasonshimmy/custom-elements-runtime/css/colors';

// Use individual color scales
const blueShades = extendedColors.blue; // { '50': '#eff6ff', '100': '...', ... }

// Use in a component
component('branded-card', () => {
  useStyle(
    () => css`
      :host {
        --card-accent: ${extendedColors.violet['500']};
      }
    `,
  );
  return html`<slot></slot>`;
});

| Export | Description | | ---------------- | -------------------------------------------------------------------------------------- | | extendedColors | Full extended palette — Record<string, Record<string, string>> (name → shade → hex). | | ColorScale | Type: single color scale with shade keys 50950. |


JIT CSS Engine

Package: @jasonshimmy/custom-elements-runtime/jit-css

Opt-in JIT CSS engine with hooks, global control, and the cls() helper for IDE tooling.

| Export | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------- | | useJITCSS | Enable JIT CSS for the current component (per-component opt-in). Pass JITCSSOptions to configure colors/variants. | | useDesignTokens | Apply typed design token overrides to :host as CSS custom properties. | | useGlobalStyle | Inject CSS into document.adoptedStyleSheets, escaping Shadow DOM encapsulation. | | enableJITCSS | Enable JIT CSS globally for all components. | | disableJITCSS | Disable JIT CSS globally. | | isJITCSSEnabled | Returns true when JIT CSS is globally active. | | isJITCSSEnabledFor | Returns true when JIT CSS is active for a specific ShadowRoot. | | jitCSS | Generate CSS from an HTML string (low-level engine). | | extractClassesFromHTML | Extract unique class names from an HTML string. | | cls | Identity function that signals JIT class names to IDE tooling and static scanners (no-op at runtime). | | parseColorClass | Parse a color utility class name to its CSS declaration. | | parseColorWithOpacity | Parse a color class with an optional /opacity modifier into its CSS declaration. | | parseGradientColorStop | Parse a gradient color stop utility (from-*, via-*, to-*) to its CSS declaration. | | parseSpacing | Parse a spacing utility class name to its CSS declaration. | | parseArbitrary | Parse an arbitrary value utility class name. | | utilityMap | Complete mapping of all static utility class names to their CSS declarations. | | selectorVariants | State and pseudo-class variant selector map (hover:, focus:, disabled:, inert:, etc.). | | mediaVariants | Responsive breakpoint media query map (sm:, md:, lg:, xl:, 2xl:, dark:). | | containerVariants | Container query breakpoint map (@sm:, @md:, @lg:, @xl:, @2xl:). | | colors | Semantic color palette object (neutral, primary, secondary, success, info, warning, error). | | Types | JITCSSOptions, DesignTokens |


DOM JIT CSS

Package: @jasonshimmy/custom-elements-runtime/dom-jit-css

Runtime DOM scanner for non-Shadow DOM contexts (React, Svelte, Vue, plain HTML).

import { createDOMJITCSS } from '@jasonshimmy/custom-elements-runtime/dom-jit-css';

const jit = createDOMJITCSS({ extendedColors: true });
jit.mount(); // start watching
jit.destroy(); // tear down

| Export | Description | | ----------------- | --------------------------------------------------------------------------------------------------- | | createDOMJITCSS | Create a DOM JIT CSS instance that watches class changes and injects utility CSS into the document. | | Types | DOMJITCSSOptions, DOMJITCSSHandle |


Vite Plugin

Package: @jasonshimmy/custom-elements-runtime/vite-plugin

Build-time plugins for JIT CSS, SSR config, and per-page component code splitting. Three exports are available:

  • cerPlugin — All-in-one: JIT CSS + SSR configuration. Recommended for SSR apps.
  • cerJITCSS — JIT CSS only.
  • cerComponentImports — Per-page component code splitting: injects static import statements for custom elements used in `html`` templates so Rollup can chunk components per page.
// vite.config.ts — SSR app (recommended)
import { cerPlugin } from '@jasonshimmy/custom-elements-runtime/vite-plugin';

export default defineConfig({
  plugins: [
    cerPlugin({
      content: ['./src/**/*.{ts,tsx,html}'],
      ssr: { dsd: true, jit: { extendedColors: true } },
    }),
  ],
});
// vite.config.ts — JIT CSS only
import { cerJITCSS } from '@jasonshimmy/custom-elements-runtime/vite-plugin';

export default defineConfig({
  plugins: [
    cerJITCSS({
      content: ['./src/**/*.{ts,tsx,html}'],
      output: 'src/generated-jit.css',
      extendedColors: true,
    }),
  ],
});
// vite.config.ts — per-page component code splitting
import { cerComponentImports } from '@jasonshimmy/custom-elements-runtime/vite-plugin';

export default defineConfig({
  plugins: [
    cerComponentImports({
      componentsDir: '/absolute/path/to/app/components',
      appRoot: '/absolute/path/to/app',
    }),
  ],
});

| Export | Description | | ------------------------------- | ------------------------------------------------------------------------------------------------------------ | | cerPlugin | Combined plugin: JIT CSS + SSR config (virtual:cer-ssr-config). Returns a Plugin[] array. | | cerJITCSS | JIT CSS-only Vite plugin that scans source files at build time and emits pre-generated CSS. | | cerComponentImports | Transform plugin that injects per-file static imports for custom elements, enabling per-page code splitting. | | resolveTagName | Normalize a component name to its kebab-case custom-element tag name (prefixes with cer- if no hyphen). | | extractTemplateTagNames | Extract hyphenated custom-element tag names from a source string's html\`` templates. | | extractComponentRegistrations| Extract resolved tag names from allcomponent('name', …)calls in a source string. | | **Types** |CerPluginOptions, CerSSROptions, CerJITCSSPluginOptions, CerComponentImportsOptions` |


📖 Documentation Index

Explore the complete documentation for every runtime feature:

🚀 Getting Started

🏗️ Core Features

  • 🧩 Template - Template syntax and html function
  • 🧭 Directives - Conditional rendering with when, each, and match
  • 🛠️ Directive Enhancements - Advanced directive utilities:
    • unless - Inverse of when
    • whenEmpty / whenNotEmpty - Collection checks
    • eachWhere - Filtered iteration
    • switchOnLength - Render based on array length
    • eachGroup - Group and render items
    • eachPage - Pagination support
    • switchOnPromise - Async state rendering
    • whenMedia - Media query responsive rendering
    • responsive - Responsive utilities
  • 🔗 Bindings - Data binding with :prop, @event, :model, :class, :style
  • 🔔 Events Deep Dive - Custom event emission and handling patterns
  • 🎬 Transitions Guide - Animation and transition effects

🎨 Styling

  • 🎨 JIT CSS - On-demand utility-first styling system (opt-in architecture, all utilities, useJITCSS, useDesignTokens, useGlobalStyle, cls)
  • ⚡ DOM JIT CSS - Runtime DOM scanner for non-Shadow DOM contexts (React, Svelte, Vue, plain HTML)
  • 🔧 Vite Plugin - cerPlugin (JIT CSS + SSR config), cerJITCSS (JIT CSS only), and cerComponentImports (per-page code splitting) build-time plugins
  • 🔌 cerComponentImports - Per-page component code splitting: auto-inject imports from `html`` templates
  • 📏 Space Utilities - Tailwind-style space-x-* and space-y-* spacing utilities
  • 📝 Prose Typography - Beautiful typography for long-form content
  • 🎨 Colors - Extended Tailwind-compatible color palette (/css/colors subpath)

🔗 Communication & State

Advanced Features

  • ⚡ Reactive API - watch() targeted watchers, computed() memoization, watchEffect() auto-tracking, and nextTick()
  • 🏝️ Provide / Inject - Ancestor-to-descendant dependency injection without prop-drilling
  • 🧩 Composables - Reusable stateful logic with createComposable()
  • 🚀 Teleport - Render content outside the shadow root with useTeleport()
  • ♻️ Keep-Alive - Preserve component state across DOM removals with <cer-keep-alive>
  • 🩺 Health Monitor - Track runtime metrics and receive periodic health reports with createHealthMonitor()
  • 🔮 Virtual DOM - VDOM implementation and performance details
  • 🌐 SSR - Complete SSR guide: Declarative Shadow DOM output, hydration, streaming, partial hydration (island architecture), useStyle in SSR, routing with SSR, and framework integration
  • 🌐 SSR Middleware - createSSRHandler and createStreamingSSRHandler for Express, Fastify, Hono, raw Node.js, and router integration
  • ♻️ HMR - Hot module replacement
  • 🛡️ Infinite Loop Protection - Runtime safeguards against infinite loops
  • 🔒 Secure Expression Evaluator - Safe evaluation of dynamic expressions in templates

🔧 Integration Guides

🛡️ Security & Quality

  • 🔒 Security - XSS prevention, unsafeHTML, CSP guidance, and safe input handling
  • 🧪 Testing - Testing components with Vitest + happy-dom, reactive state, events, and async components
  • ⚡ Performance - Update scheduler, computed memoization, avoiding re-renders, profiling
  • 🔧 Troubleshooting - Common issues and solutions

🔄 Upgrading

📖 Reference

  • 📚 Glossary - Definitions for library-specific and web-components terms

For examples and implementation details, explore the source code in src/lib/.

🧑‍🔬 Real-World Examples

🌟 Showcase & Community

Community Gallery

💖 Support This Project

Custom Elements Runtime is a labor of love built to make modern web development faster and more expressive. If it's helping you build better components, learn more about me or consider supporting me on Patreon to help keep the momentum going.

Your support helps fund continued development, documentation, and community engagement. Every bit helps—thank you!