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

@protoyard/themes

v1.9.4

Published

Protoyard theme engine: token presets, light/dark/system resolution and scoped CSS variable application.

Readme

@protoyard/themes

Theme engine for Protoyard prototypes: six AA-checked built-in presets, a theme library of 204 themes (Texuli's 64 port themes, the catalog, and its 140 expand themes; 210 with the six built-ins), light/dark/system resolution, scoped CSS-variable application and a no-flash boot script.

It wraps @texuli/tokens (docs/TEXULI.md): library tokens and seed palettes are built by Texuli and converted with fromTexuliTheme. applyAppearance() writes canonical --tx-* tokens; pages that call enableTexuliAppearance() also get Texuli's extended roles and data-tx-* attributes. The 140-theme expanded set (204 in all) is on by default: it loads only through a dynamic import (metadata when a picker shows the whole library, each theme's definition when the theme is used).

import { applyAppearance, BUILTIN_THEMES, getTheme, resolveMode } from '@protoyard/themes';

applyAppearance(document.documentElement, {
  theme: getTheme('ocean'),
  resolvedMode: resolveMode('system'),
  reducedMotion: false,
  density: 'default', // 'compact' | 'comfortable' | 0.75–1.25
});

| Export | Purpose | | --- | --- | | BUILTIN_THEMES, violetTheme … monochromeTheme | Core six presets (every token for light and dark) | | THEME_LIBRARY_META, listThemeLibrary, searchThemeLibrary, listCollections | The 64-theme catalog: eager metadata (@texuli/tokens/library) | | loadFullLibraryMeta, listFullThemeLibrary, searchFullThemeLibrary, listFullCollections, findLibraryThemeMeta | Async, all 204 library themes (the catalog, then @texuli/tokens/library-expand, loaded on demand; the catalog where it cannot load) | | ALL_LIBRARY_THEME_IDS, isLibraryThemeId, isCatalogThemeId, isExpandedLibraryThemeId | Synchronous id checks over all 204 (no metadata load) | | loadLibraryTheme(id), loadLibraryThemeDefinition(id) | Any library theme's tokens (built by @texuli/tokens, converted with fromTexuliTheme) or definition, one lazy chunk per theme | | createThemeFromSeed({ id, name, seed, secondary?, neutral?, style? }) | Build an AA light/dark theme from brand hex colors with @texuli/tokens' generator; neutral picks a family from NEUTRAL_FAMILIES (zinc, slate, stone, gray, warm, cool, tinted) | | generateThemeHarmonies(seed, neutral?) | Deterministic OKLCH complementary, analogous, triadic, split-complementary and monochrome secondary suggestions, filtered to AA-safe light/dark themes | | DENSITY_PRESETS, RADIUS_PRESETS, ELEVATION_PRESETS, FONT_PRESETS, MOTION_PRESETS, stylePresetInput(selection), applyStylePresets(theme, selection) | Named density, radius, elevation, font and motion presets as data, resolved to validated theme fields | | FONT_CATALOG, getFontPairing, loadVariableFont | System-first font pairings (no network) | | getTheme(id, extra?) / findTheme / mergeThemes | Lookup with Violet fallback; prototype themes override by id | | resolveMode(mode, matchMedia?) | system → light/dark | | applyAppearance(el, input) / clearAppearance(el) | Writes canonical --tx-* vars (including focus-ring tokens and Texuli's link family, --tx-link with its -hover, -active, -focus, -disabled and -visited states, derived by linkStates(palette): the primary when it reads at 4.5:1 on background, surface, muted and elevated, else the foreground), data-py-theme, data-py-mode, data-py-motion, data-py-surface, the @protoyard/ui component profiles from themeComponentProfile, the dark class and color-scheme; with enableTexuliAppearance() also Texuli's extended roles and data-tx-* attributes | | themeComponentProfile(theme) | The data-py-*-style profiles a theme's style implies, only where it departs from today's look: a non-default focus ring → focus-ring, surface: glass → card: glass, elevation: flat → card: bordered, radius 0 → button: square, radius ≥ 999px → button: pill. Input and navigation profiles have no theme field and stay consumer-set. The button and card profiles style .ui-button / .ui-card; the Texuli Button and Card that @protoyard/ui re-exports follow the --tx-* tokens instead. The no-flash script replays these (allowlisted values only) | | themeVariables(input) | The same variables as a plain object | | cacheAppearance(namespace, applied) / readCachedAppearance | localStorage cache at protoyard.<namespace>.appearance (try/catch) | | noFlashScript(namespace) | Inline <head> script body that replays the cache (including data-py-surface) before first paint | | contrastRatio, relativeLuminance, parseHex, TEXT_CONTRAST_PAIRS, UI_CONTRAST_PAIRS | WCAG helpers used by the preset tests and the UI Kit theme lab | | DEFAULT_THEME_ID, prefersDark(matchMedia?), densityScale(density, theme?) | Small helpers behind getTheme / resolveMode / applyAppearance | | appearanceCacheKey(namespace), APPEARANCE_CACHE_VERSION | Cache key/version shared by cacheAppearance and the inline script |

Subpath exports: @protoyard/themes/presets, @protoyard/themes/library, @protoyard/themes/no-flash, @protoyard/themes/base.css, @protoyard/themes/fonts.css (optional font-stack variables), plus:

| Subpath | Exports | | --- | --- | | @protoyard/themes/library-full | disableFullThemeLibrary() limits a page to the 64-theme catalog; enableFullThemeLibrary() restores the default (all 204), kept for compatibility | | @protoyard/themes/texuli | enableTexuliAppearance() / disableTexuliAppearance() (from then on applyAppearance also writes Texuli's extended roles and data-tx-*), writeTexuliAppearance, toTexuliTheme, deriveTexuliRoles, fromTexuliTheme, SHARED_PALETTE_ROLES. It imports @texuli/tokens/css and @texuli/tokens/contract, never the package root. The renderer enables it in bindAppearance |

CSS

@import 'tailwindcss';
@import '@protoyard/themes/base.css';

base.css maps every token from canonical --tx-* names into Tailwind 4 (bg-primary text-primary-foreground border-border bg-surface bg-elevated text-muted-foreground ring-ring bg-sidebar bg-chart-1 …), derives rounded-sm…2xl from --tx-radius, scales spacing by --tx-density, defines dark: as .dark class based, and adds a base layer (body colors, focus ring, selection, scrollbars, reduced motion via the OS or data-py-motion="reduce") plus pt-safe/pb-safe/px-safe/min-h-touch utilities.

Contrast rules (tested): all text pairs ≥ 4.5:1, primary/destructive/ success/info as text on surfaces ≥ 4.5:1, focus ring ≥ 3:1. Use warning as a fill with warning-foreground text, not as text color.

Package output

The manifest keeps TypeScript source exports for workspace development. pnpm build:packages --filter engine creates the ESM and declaration files under dist/ that the packed manifest exposes.