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

@cueplusplus/theme-base

v1.1.0

Published

The blank abstract theme every CUE++ theme extends: the neutral base palette, the token contracts, the manifest schema, and the resolver that turns a theme's deltas into a complete token map.

Readme

@cueplusplus/theme-base

The blank abstract theme every CUE++ theme extends, and the contract that makes "a palette is a package" work — addressed to the two people who need it by name: whoever writes a theme package by hand, and whoever writes a tool that reads one.

Most apps never reach for it by name. @cueplusplus/ui re-exports the types, @cueplusplus/ui/styles.css already imports base.css, and every @cueplusplus/theme-* preset declares this package as a peer — so it is usually in the tree before you think about it.

Install

The @cueplusplus scope is public on npm and resolves there by default, so there is nothing to configure and no credential to supply — it installs like any other package.

pnpm add @cueplusplus/theme-base @cueplusplus/tokens

@cueplusplus/tokens is the one peer this package declares (>=0.9.0 <1): the density and type axes this package does not own. It is a peer rather than a dependency because a tree with two copies of the token layer in it has two token vocabularies, and only one of them is the one the stylesheets on the page were built against. culori comes along as a dependency; nothing else does.

Quick start

Four things live here, and every one of them is a fact more than one package has to agree on.

The blank base

base.css is every --cue-* colour at a neutral default, declared on a bare :root, with @cueplusplus/tokens/axes.css imported for the density and type axes. It is what @cueplusplus/ui/styles.css brings in, so a page that registers no theme still paints something legible: greys, one desaturated accent, and the platform monospace.

Import it yourself only when you are assembling the stylesheet without @cueplusplus/ui/styles.css — a theme configurator, a token playground, an email template that wants the vocabulary and not the components:

The second line below is a palette, and this package ships none: install one preset beside the base (pnpm add @cueplusplus/theme-cue, or any other @cueplusplus/theme-*) before that import resolves.

@import "@cueplusplus/theme-base/base.css";
@import "@cueplusplus/theme-cue/theme.css"; /* any installed palette, and it must come after */

The order is not decorative. A theme declares its colours under [data-theme="cue"], which ties with this bare :root at the same specificity, so the one declared later wins.

The contract a theme package satisfies

A theme package is a manifest plus the stylesheet that paints it. The manifest has eleven required fields — schemaVersion, name, package, extends, mode, supportsLight, colors, fonts, densities, fontPairings, contrast — and assertManifest is what says so at runtime; manifest.schema.json is the same statement for a validator that is not JavaScript. mode is complete when theme.css stands on its own and delta when it holds only what differs from the base. extends carries the theme-base range the manifest was resolved against, and it is the package's own peerDependencies entry rather than a second copy of it.

The typed half is ThemeRegistry, which a theme package augments with declare module in its index.d.ts. ThemeName is the keys of that interface, so it widens with each theme a consumer installs rather than naming a list compiled in here.

Reading a theme

resolve() turns a theme's deltas into a complete token map, and is what a tool that has to know a theme's effective colours calls instead of parsing CSS:

import { assertManifest, resolve } from "@cueplusplus/theme-base";

export function darkColors(manifest: unknown) {
  assertManifest(manifest); // throws, listing every problem, if it is not one
  return resolve(manifest, { mode: "dark" }).colors;
}

assertManifest is an assertion function rather than a returning one — it narrows manifest in place and gives back void, so it is a statement of its own and not an argument to resolve. validateManifest is the same check as a list of problems, for a caller that wants to report them all rather than throw on the first.

resolve(null, …) answers the same question about the blank base itself. resolveDensities() and resolveFonts() are the two axes on their own.

The contrast report

@cueplusplus/theme-base/contrast is the WCAG measurement cue-theme build refuses a theme on — contrastReport() over CONTRAST_REQUIREMENTS, with contrastRatio() and relativeLuminance() underneath and WCAG_AA_NON_TEXT (3), WCAG_AA_TEXT (4.5) and WCAG_AAA_TEXT (7) as the floors.

To build a theme rather than read one, use @cueplusplus/theme-tools — cue-theme init scaffolds a package that peers on this one and builds before it is edited.

What it ships

| Subpath | What it is | | --- | --- | | @cueplusplus/theme-base | the contract (ThemeManifest, ThemeRegistry, ThemeName, the colour and geometry token lists), assertManifest / validateManifest, and resolve / resolveDensities / resolveFonts | | @cueplusplus/theme-base/contrast | contrastReport, contrastRatio, relativeLuminance, CONTRAST_REQUIREMENTS and the three WCAG floors | | @cueplusplus/theme-base/base.css | the blank base, importing @cueplusplus/tokens/axes.css | | @cueplusplus/theme-base/manifest.schema.json | the manifest contract as JSON Schema, for a validator that is not TypeScript | | @cueplusplus/theme-base/package.json | |

ESM only, Node 22 or newer, types beside every entry.

Where the rest is

  • The theming guide — https://ui.cueplusplus.com/docs/theming. The token vocabulary, the density and mode axes, the shipped presets, and createTheme() for a palette of your own.
  • docs/CONSUMING.md — registry access in full, the peer matrix per subpath, and the table of what a failed install means.
  • CHANGELOG.md, in this package — one entry per release, addressed to you rather than to the diff, with a Migrating section on anything that needs an edit. Read it before an upgrade; the version number alone does not say what moved.