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

@paulperigault/dataviz

v0.1.0

Published

Contrat de données, formatage fr et palettes accessibles dérivées de l'accent, pour les graphiques statiques.

Readme

@paulperigault/dataviz

Contrat de données, formatage français et palettes de graphiques accessibles, dérivées de la couleur d'accent. TypeScript pur : aucun rendu, aucune dépendance d'exécution hors @paulperigault/tokens. Les composants Astro qui l'utilisent viennent avec V2a.

Statut : en construction (0.0.0). Décisions : ADR-0007.

Usage

import tokens from '@paulperigault/tokens/tokens.json' with { type: 'json' };
import {
  createFormatter,
  derivePalettes,
  parseDataset,
  themeBaseFromTokens,
} from '@paulperigault/dataviz';

const dataset = parseDataset(json); // { ok: true, value } ou { ok: false, error: { code, message, path } }
const fr = createFormatter(); // locale « fr » ; fr.value.number(1234.5, '€') → « 1 234,5 € »

const base = themeBaseFromTokens(tokens, 'light');
if (base.ok) {
  const palettes = derivePalettes(270.7, 'light', base.value);
  // palettes.value.categorical : 6 couleurs OKLCH, l'accent en tête
}

Aucune fonction publique ne lève d'exception : toute erreur est un Result typé (errors.ts).

Géométrie pure (V2a-1)

  • linearScale, verticalScale (axe Y SVG inversé), bandScale, timeDomain, timeScale : domaine vers étendue.
  • niceTicks (pas 1, 2, 5 × 10^n, domaine élargi) et timeTicks (jour, semaine, mois, année, alignés UTC).
  • lttb(xs, values, cible) : indices retenus ; premier et dernier points gardés, null jamais inventés.
  • linePath (d interrompu aux null, points isolés signalés) et barRects / rectsPath (barres groupées).
  • Toutes renvoient un Result typé (scale.*, geometry.bad-input, downsample.bad-target, stats.*).

Aires et jauges (V2b-1)

  • areaPath(points, base) : aire sous la courbe jusqu'à la base, un sous-chemin fermé par segment, rompue aux null.
  • stackSeries(colonnes) : couches empilées (lower, upper). Valeur manquante : elle compte pour zéro dans le cumul, donc les couches du dessus reposent sur celles du dessous, mais sa propre couche est rompue (null) : le vide se voit et n'est jamais dessiné comme un zéro. Valeur négative : stack.negative-value.
  • sectorPath, radialLine, polar : secteur d'anneau et aiguille (0° en haut, sens horaire) ; un tour entier devient un anneau.
  • gaugeReading : valeur bornée à l'intervalle avec clamped (below ou above), gauge.bad-range si l'intervalle est nul ou inversé.
  • gaugeZones et zoneIndex : n seuils strictement croissants donnent n + 1 zones ; gauge.bad-thresholds sinon.

Changer l'accent en une variable

--pp-accent-hue : un nombre, la teinte OKLCH en degrés (270.7 par défaut). Elle ne règle que la teinte : la clarté et le chroma restent ceux du système (clair oklch(47% 0.19 h), sombre oklch(78% 0.1 h)), pour garder les contrastes AA. La typographie se règle par --pp-font-stack (pile du texte, dont dérive --pp-font-family-sans ; --pp-font-family-mono reste à part). Sorties inchangées : --pp-color-accent, --pp-chart-*, --pp-font-family-*. Ces deux variables sont nommées ici ; leur branchement dans le build de tokens et dans create est une étape à part.

Ce que garantit la dérivation

Pour chaque thème et chaque teinte, derivePalettes refuse (erreur typée) toute palette qui rate :

  • catégorielle de 6 couleurs : ΔE00 ≥ 10 entre toute paire, en vision normale et après simulation de la protanopie, de la deutéranopie et de la tritanopie (Machado, Oliveira et Fernandes, 2009) ;
  • séquentielle et divergente de 7 pas : ΔE00 ≥ 3 entre pas voisins ;
  • tracés ≥ 3:1 contre le fond (WCAG 1.4.11) et texte sur l'accent ≥ 4,5:1 (1.4.3).

Un accent hors gamut sRGB à la clarté du système (par exemple teinte 30) voit son chroma réduit. La dérivation est un échantillonnage du point le plus éloigné (farthest-point sampling) : l'accent d'abord, puis la candidate la plus distincte des couleurs déjà prises.

Structure

src/domain (contrat, dates ISO, échelles, LTTB, géométrie : pur, sans E/S ; la dérivation de palettes vit dans @paulperigault/tokens/palette, réexportée ici), src/application (ports), src/infrastructure (validation à la frontière, Intl, lecture de tokens.json), src/errors.ts.