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

@stealthscale/pandacss-naming

v0.2.0

Published

Writes the class names of a Panda CSS design system in one readable scheme, for the stylesheet and for the browser alike.

Downloads

122

Readme

@stealthscale/pandacss-naming

@stealthscale/pandacss-naming writes the class names of a Panda CSS design system in one readable scheme. The same functions run in the browser, where the generated runtime writes a class, and on the compiled stylesheet, where the selectors are renamed, so the two sides agree by construction.

| Kind | The compiler writes | The scheme writes | | ------------------------- | ------------------------------------------------- | ------------------------------------------------ | | Variant on a string axis | button--size_lg | button--lg | | Variant on a boolean axis | card__content--bleed_true, …--bleed_false | card__content--bleed, and no class for false | | Slot | card__root | card__root | | Compound | button--compound__size_lg__variant_solid | button--expose, the name the author gave it | | Atomic | grid-ar_{sizes.32}, md:grid-tc_repeat(3,_1fr) | grid-ar-sizes-32, md:grid-tc-repeat-3-1fr | | Value with a capital | bg_colorPalette.solid, ff_Segoe_UI | bg-color-palette-solid, ff-segoe-ui | | Custom property | --stagger_0 | stagger-0 | | Negative value | m_-4 | m--4 | | Condition | focusVisible:c_red, [&_>_*]:c_red | focus-visible:c-red, [&_>_*]:c-red |

The compiler's separator, _ by default, sits between an axis and its value and between a property's class and its value. The scheme reads it on both sides and writes a hyphen, and it takes the separator the compiler was configured with, _, - or =.

Install

pnpm add @stealthscale/pandacss-naming

Usage

A recipe author names a compound, and a specification derives the class it expects:

import { compoundClass, slotClass, variantClass } from "@stealthscale/pandacss-naming";

variantClass("button", "size", "lg"); // "button--lg"
variantClass("button", "loading", true); // "button--loading"
variantClass("button", "loading", false); // ""
slotClass("card", "content"); // "card__content"
compoundClass("button", "expose"); // "button--expose"

A build step reads a class the compiler wrote and returns the class of the scheme:

import { type CompilerConfig, rename } from "@stealthscale/pandacss-naming";

const config: CompilerConfig = {
  recipes: [{ axes: ["loading", "size"], className: "button" }],
  separator: "_",
};

rename("button--size_lg", config); // "button--lg"
rename("button--loading_false", config); // ""
rename("md:grid-tc_repeat(3,_minmax(0,_1fr))", config); // "md:grid-tc-repeat-3-minmax-0-1fr"

The rules

The scheme is sound under three rules, which a gate holds and this package trusts:

  • The values of one recipe are unique across its axes, and no value equals a boolean axis's name or a compound's name. size: lg and radius: lg in one recipe would both read button--lg.
  • A compound carries a name. The name is unique in its recipe, is not a value of any axis, and does not start with an axis and the separator.
  • An axis name does not contain the separator. Where one axis name prefixes another, rename reads the longest axis that fits, so on-off wins over on for card--on-off_true.
  • Two different classes of one stylesheet never sanitise to one name. The stylesheet rewrite checks this and reports a collision.

The scheme reads a class as the compiler writes it with hash off and no prefix. A hashed class has no structure to read, and a prefix is not read from a recipe's class.

Reference

| Export | Returns | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | variantClass(className, axis, value) | <class>--<value> for a string or a number, <class>--<axis> for true, and an empty string for false | | slotClass(className, slot) | <class>__<slot> | | compoundClass(className, name) | <class>--<name> | | atomicClass(pandaClass, separator) | The class with each named condition and the property's class in kebab-case, without the hyphens a custom property opens with, the separator written as a hyphen, and the value sanitised and in lower kebab-case. A raw selector or at-rule condition in brackets is kept as written | | rename(pandaClass, config) | The class as a variant where one of config.recipes claims it, with config.separator between axis and value, and as an atomic class otherwise | | conditionsOf(pandaClass) | The conditions of a class, outer to inner, as the compiler wrote them, with a raw one in its brackets | | sanitise(segment) | The segment with a letter, a digit, a hyphen, %, /, ! and the slot separator __ kept, each run of other characters replaced by one hyphen, and a run at the start dropped. The case is kept, and atomicClass lowers it | | kebab(name) | The name with a hyphen at each boundary between a lower-case letter or a digit and a capital, in lower case |

Licence

MIT. See LICENSE.