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

@poly-ds/theme-manager

v0.2.3

Published

Runtime de temas: os 3 eixos, persistencia, matchMedia e o snippet anti-FOUC. TS puro, zero dependencia.

Readme

@poly-ds/theme-manager

Runtime de temas: os tres eixos, persistencia, matchMedia, escritores externos e o snippet anti-FOUC. TypeScript puro, zero dependencia, sem tocar o DOM no import.

O guia de integracao — o que instalar e em que ordem — esta em docs/TROCANDO-DE-TEMA.md. Este arquivo e a referencia da API.

API

const manager = createThemeManager({
  themes,              // obrigatorio: lista de marcas (use THEMES de @poly-ds/tokens)
  defaultTheme,        // default: themes[0]
  defaultScheme,       // default: 'system'
  defaultDensity,      // default: 'comfortable'
  storageKey,          // default: 'poly-ds-theme'
  root,                // default: document.documentElement — `null` para headless/SSR
  disableTransitions,  // default: true
  persist,             // default: true
});

| Metodo | | | --- | --- | | getState() | Estado atual. Referencia estavel entre mudancas — useSyncExternalStore exige. | | setTheme / setScheme / setDensity | Muda um eixo e persiste. | | toggleScheme() | Alterna a partir do que esta na tela (system resolvido como escuro vai para light). | | cycleTheme() | Proxima marca de themes, circular. | | subscribe(fn) | Notifica a cada mudanca. Devolve o cancelador. | | applyTo(el) | Espelha os eixos num elemento alem do root, agora e depois. Devolve o disposer. | | destroy() | Solta listeners, observer e espelhos. |

inlineScript(options): string       // o snippet, ~506 B
inlineScriptTag(options): string    // ja embrulhado em <script>
dsThemeScript(options)              // plugin de bundler, em '@poly-ds/theme-manager/bundler'

Passe o mesmo objeto de opcoes para createThemeManager e para o snippet. Os defaults sao resolvidos pela mesma funcao (resolveDefaults), e um teste roda os dois contra o mesmo localStorage e falha se os atributos divergirem.

Como isto e testado

tests/ roda em happy-dom, e nao num DOM de mentira escrito a mao. Tres APIs aqui tem semantica sutil — MutationObserver (callback em microtask), matchMedia (MediaQueryList com evento) e localStorage (que pode lancar so de ser acessado) — e um duble caseiro de MutationObserver seria sincrono. O teste passaria por um comportamento que o browser nao tem, que e o pior resultado possivel.

O que happy-dom nao cobre — ordem de flush de estilo, primeiro paint, o SO mudando de verdade — esta em e2e/specs/theme-runtime.spec.ts, em Chromium, nos tres frameworks.

Os dois testes que justificam o pacote:

  • equivalencia snippet ↔ manager (tests/inline-script.test.ts): as duas implementacoes recebem o mesmo localStorage e tem que aplicar os mesmos atributos. Sem ele, um rename de campo viraria um flash no carregamento em vez de um erro.
  • sem flash no primeiro paint (e2e): cada escrita nos eixos e gravada com o document.readyState do momento. A primeira tem que acontecer em loading — ou seja, durante o parse do <head>, antes do primeiro paint.

Os dois foram verificados por quebra deliberada: sem o snippet o segundo falha com readyState: "interactive"; com um campo renomeado, o primeiro falha em 6 casos.