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

@runsnative/components

v0.11.2

Published

RunsNative component library - web components for context-first experiences

Readme

@runsnative/components

RunsNative web components — context-first UI primitives built as native custom elements.

Installation

npm install @runsnative/components

CDN Usage

@runsnative/components is published to npm and automatically available via jsdelivr within minutes of each release. No manual cache invalidation required.

Load all components (single script tag)

<script type="module"
  src="https://cdn.jsdelivr.net/npm/@runsnative/components@latest/dist/runsnative.min.js">
</script>
<link rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@runsnative/components@latest/dist/tokens.css">

Pin to a specific version (recommended for production)

<script type="module"
  src="https://cdn.jsdelivr.net/npm/@runsnative/[email protected]/dist/runsnative.min.js">
</script>
<link rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@runsnative/[email protected]/dist/tokens.css">

Using @latest always resolves to the newest published version. For production, pin to a specific version to avoid unexpected changes.

URL pattern

| Asset | URL | |---|---| | All components bundle | https://cdn.jsdelivr.net/npm/@runsnative/components@{version}/dist/runsnative.min.js | | Design tokens CSS (default theme) | https://cdn.jsdelivr.net/npm/@runsnative/components@{version}/dist/tokens.css | | A canonical theme | https://cdn.jsdelivr.net/npm/@runsnative/components@{version}/dist/tokens-{theme}.css |

Replace {version} with a semver tag (e.g. 0.5.0) or latest. Replace {theme} with a canonical theme slug (see below).

Loading a canonical theme

tokens.css ships the neutral default theme. To render components in one of the canonical themes instead, load its theme CSS after tokens.css (its :root tokens override the default by cascade order) and set data-run-theme on <html>:

<link rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@runsnative/[email protected]/dist/tokens.css">
<link rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@runsnative/[email protected]/dist/tokens-arctic-frost.css">
<html data-run-theme="arctic-frost" data-run-mode="dark">

Theme slugs match the published dist/tokens-<slug>.css filenames (e.g. arctic-frost, botanical-garden, dotorg-site) — one per brand config in brand-configs/. Each theme CSS supports data-run-mode="light"|"dark" and data-run-contrast="high" (see docs/decisions/brand-theme-terminology-correction-v1.md for the theme/skin/brand terminology).

Preventing a flash of unstyled theme (FOUC)

Because the theme override CSS loads as a stylesheet, a page that sets data-run-theme via JavaScript after load will flash the default theme first. Stamp the attributes synchronously in <head>, before the stylesheets, so the browser never paints the default:

<script>
  (function () {
    var html = document.documentElement;
    var theme = localStorage.getItem('run-theme');
    var mode = localStorage.getItem('run-mode') || (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
    var skin = localStorage.getItem('run-skin');
    if (theme) html.setAttribute('data-run-theme', theme);
    html.setAttribute('data-run-mode', mode);
    if (skin) html.setAttribute('data-run-skin', skin);
  })();
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@runsnative/[email protected]/dist/tokens.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@runsnative/[email protected]/dist/tokens-arctic-frost.css">

Adjust the localStorage keys to whatever your app persists the user's theme/mode/skin choice under — the snippet only needs to run before the stylesheet <link> tags.

Skin Authoring

@runsnative/components exposes three sub-path entrypoints for authors building custom image-based or SVG-based skins.

Importing the skin authoring modules

import { nineSlice, tileAndCaps, generateTintFilter, measureBaseLum }
  from '@runsnative/components/image-skin';

import { sanitizeSvg, composeSvgSkin }
  from '@runsnative/components/svg-skin';

import { createSkinLoader, registerSkinLoaders, loadSkinModule }
  from '@runsnative/components/skin-loader';

TypeScript declarations (.d.ts) ship alongside each module.

image-skin — bitmap renderers

Provides the slicing and tinting math for CSS-tier image skins. The author supplies asset URLs (via CSS custom properties), slice coordinates, and a measured base luminance; this module emits the CSS declarations.

  • nineSlice({ slice, width, srcVar, repeat?, fill? }) — CSS declarations for a 9-slice border-image (corners + tileable edges + center fill). Returns a CSS declaration block string.
  • tileAndCaps({ capSlice, capWidth, srcVar, repeat?, fill? }) — Fixed-width end caps with a seamlessly tileable middle band. A degenerate 9-slice with zero top/bottom slice.
  • generateTintFilter({ color?, brandToken?, baseLum, scope? }) — Computes a feColorMatrix that tints a neutral (grayscale) asset toward a brand color, normalized by the asset's measured luminance. Returns { matrix, values, color, svgFilter(), cssFilter() }.
  • measureBaseLum(imageData) — Alpha-weighted mean luma of a neutral asset, in [0, 1]. Feed this to generateTintFilter as baseLum.

svg-skin — SVG-layer composition

Composes a complete skin module from a multi-layer SVG and a component-DOM render function. Handles sanitization, per-layer fill token wiring, and @keyframes animation generation — gated behind prefers-reduced-motion: no-preference.

  • composeSvgSkin({ svg, render, styles?, layers?, meta? }) — Returns a frozen { styles, render } skin module compatible with defineSkin(). The layers map accepts selectors into the SVG with optional fill (token name or { token, fallback }) and animation config.
  • sanitizeSvg(svg) — Strips <script>, <foreignObject>, on* attributes, and javascript: URLs. Called automatically by composeSvgSkin; exported for tooling and tests.

skin-loader — lazy-load wiring

Centralises the dynamic-import pattern needed to prevent Vite from pre-bundling PNG assets (which hangs vitest). Use createSkinLoader in component classes:

import { createSkinLoader } from '@runsnative/components/skin-loader';

// In your component class body:
const _myCustomSkin = createSkinLoader('my-skin', 'button');

// In updated():
if (_myCustomSkin.loaded) {
  this.shadowRoot.adoptedStyleSheets = [_myCustomSkin.styles];
  _myCustomSkin.module.render(this);
} else {
  _myCustomSkin.load().then(() => this.requestUpdate());
}
  • createSkinLoader(skinName, component) — Returns { loaded, styles, module, meta, load() }. meta exposes the skin's rendering tier for C+ dispatch.
  • loadSkinModule(skinName, component) — Returns Promise<unknown> for the raw skin module. Use as a static skinLoaders value.
  • registerSkinLoaders(map) — Register literal () => import('./…') thunks so bundlers can see them. Call once as a side-effect import from your skin registry file.

Registration with a component

The static skinLoaders map in each component file — which wires skin names to their loader functions — is generated automatically by the factory from .js files in the component's skins/ directory. Skin authors do not edit the component file directly; the factory regenerates it on every promote.


Testing

Unit tests run in two environments (full contract + the curated allowlist live in the header of vitest.browser.config.js — read that before authoring or moving tests):

| Invocation | Config | Environment | CI runner | |---|---|---|---| | npm test | vitest.config.js | jsdom | components-jsdom-test.yml (nightly) | | npm run test:wc | vitest.browser.config.js | Chromium (Playwright) | components-browser-test.yml (nightly) |

  • Every design-system/**/*.test.js file runs in both environments; *.browser.test.js files run in Chromium only.
  • The Chromium suite is green by construction via an explicit EXCLUDED allowlist block in its config — each exclusion carries a reason and a graduation ticket. Never exclude silently.
  • Environment-specific expectations use the canonical marker pattern (PR #1155): navigator.userAgent.includes('jsdom') ? it.fails : it (or it.skip), always with a WHY comment.
  • The browser config does not load vitest.setup.js (jsdom polyfills/location patch) — real-platform fidelity is the point. Tests must not navigate the page or assume jsdom API shapes.
  • Fast local loop: scope the browser run, e.g. npx vitest run --config vitest.browser.config.js design-system/text-motion/.

Publishing

Releases are human-initiated via the Publish @runsnative/components GitHub Actions workflow (workflow_dispatch). To publish a new version:

  1. Go to Actions → Publish @runsnative/components → Run workflow
  2. Select bump type: patch (bug fixes), minor (new components), major (breaking changes)
  3. The workflow builds, verifies, bumps the version, publishes to npm, and pushes a git tag

Prerequisite: NPM_TOKEN must be set as a GitHub Actions secret with publish access to the @runsnative npm org.

The jsdelivr CDN serves the new version within minutes of the npm publish completing.