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

@dloizides/design-tokens

v1.11.0

Published

Framework-agnostic design-token SOURCE for the dloizides.com portfolio. One typed token set per app (aml / erevna / katalogos), seeded byte-for-byte from each app's CURRENT values, emitted in three forms from one source: CSS custom properties (:root) for

Downloads

632

Readme

@dloizides/design-tokens

Framework-agnostic design-token source for the dloizides.com portfolio — the cross-stack unifier (task #78). One typed token set per app, seeded byte-for-byte from each app's current values, emitted in three forms from one source.

#1 rule — behaviour-preserving extraction, not a redesign. Every preset mirrors the app's existing look. Adopting this package changes nothing visually. Runtime tests assert the RN output deep-equals the app's current DEFAULT_THEME_CONFIG and the AML CSS reproduces ui.css's :root verbatim.

Values only — no components. (Shared React components live in @dloizides/ui-layout, ui-forms, ui-feedback, ui-icons, ui-tables.)

The four output forms

One DesignTokens object per app feeds four pure emitters:

| Form | Emitter | Consumer stack | Output | |------|---------|----------------|--------| | (a) CSS custom properties | toCssVars(tokens, names, opts?) | Stack-A vanilla-JS (AML console) | a :root { --…: …; } string (+ optional dark-mode block) | | (b) RN-web theme object | toRnTheme(tokens) | RN-web (erevna, katalogos) | a TenantThemeConfig-compatible object | | (c) Tailwind preset | toTailwindPreset(tokens) | DOM-React (SyncfusionThemeStudio) | { theme: { extend: { colors, borderRadius, boxShadow, fontFamily } } } | | (d) Shared UI kit theme | toUiTheme(tokens, mode?) | RN-web on the @dloizides/ui-* kit (ichnos, kefi) | a UiTheme for ui-feedback's UiProvider |

import {
  AML_TOKENS, EREVNA_TOKENS, KATALOGOS_TOKENS, PRESETS,
  toCssVars, toRnTheme, toTailwindPreset, toUiTheme,
  AML_CSS_VAR_NAMES, DEFAULT_CSS_VAR_NAMES,
} from '@dloizides/design-tokens';

// (a) AML console — reproduces wwwroot/shared/ui.css :root exactly
const css = toCssVars(AML_TOKENS, AML_CSS_VAR_NAMES);

// (b) RN-web — drop in as the tenant-theme fallback (deep-equals the current default)
const rnDefault = toRnTheme(EREVNA_TOKENS);

// (c) DOM-React ThemeStudio — spread into tailwind.config.presets
const tw = toTailwindPreset(KATALOGOS_TOKENS);

// (d) Shared UI kit — hand straight to <UiProvider theme={…}>
const uiTheme = toUiTheme(MY_TOKENS);

toUiTheme is a LOSSLESS carrier

toUiTheme exists because the naive projection an app writes by hand — value => ({ '100': v, '500': v, '700': v }) — collapses a scale to one value, silently discarding the deeper brand step and every status background tint. A provider fed that way cannot reproduce the palette it was built from, which is what stops a shared component (StatCard, ThemedTextInput, Field) from rendering on-brand in a consuming app.

Every token lands in an addressable slot, so an app can project its whole palette back out of the live provider rather than keeping a static parallel copy:

| Token | Slot | |-------|------| | primary / secondary / accent | palette.primary / .secondary / .accent at UI_MAIN_STEP | | onBrand | palette.onBrand | | light.surfaceMuted (or dark.*, per mode) | palette.surfaceMuted | | semantic.success … | semantic.success at UI_MAIN_STEP | | semantic.successBg … | semantic.success at UI_TINT_STEP |

The UiTheme shape is declared structurally in this package (as RnThemeConfig declares TenantThemeConfig), so the zero-dependency / zero-peer guarantee holds: the token source never depends on the kit it feeds.

The per-app presets

Each preset is seeded from that app's current source of truth:

| Preset | Seeded from | Notes | |--------|-------------|-------| | EREVNA_TOKENS | erevna-web/src/theme/presets/default.ts + theme/utils/palette.ts | primary #005f73, secondary #94d2bd, accent #008d5c; full light+dark mode | | KATALOGOS_TOKENS | katalogos-web/src/theme/presets/default.ts | currently identical to Erevna; kept separate so they can diverge | | AML_TOKENS | PROOViD/AMLService/.../wwwroot/shared/ui.css :root | brand #4f46e5; dark app-shell + light workspace + verdict palette + radii/shadows/fonts |

RN presets carry no typography/radii/shadows/extensions — the RN theme has no centralized tokens for those today, so they are omitted (nothing to emit → zero change). The AML preset carries the richer superset (dark app-shell, ink scale, verdict palette, radii, shadows, fonts) in its extensions group.

FINREG module colours (FINREG_MODULE_COLORS, 1.5.0)

FINREG is a multi-module product (Payments / Accounting / CRM). Its interim EDA logo binds a colour to each module — the three orbits are the three modules — so colour reads as module identity rather than as one app's brand primary. Those tokens therefore sit beside the per-app presets, not inside one:

| Module | base (fill) | on white | onWhite (AA text/icon) | on white | |--------|---------------|----------|--------------------------|----------| | Payments (cyan) | #4FD8F0 | 1.69:1 ✗ | #0C7D91 | 4.82:1 ✓ | | Accounting (magenta) | #E85FBF | 3.08:1 ✗ | #D11E9B | 4.81:1 ✓ | | CRM (violet) | #7B8FF7 | 2.95:1 ✗ | #4763F4 | 4.82:1 ✓ |

The base hexes are a decided design input (the logo), transcribed verbatim. They are light fills — none clears the WCAG AA 4.5:1 text floor on white — so anything painting a module colour as text or an icon on white uses onWhite, the darkened same-hue companion. The onWhite values were derived (lightest shade of the hue that still clears AA, carried a little past the floor) and both halves are pinned by finregModules.test.ts with their measured ratios, so a drift below AA fails the build. This is the SOURCE of these hexes — consumers read the token, they do not re-declare the literal (no-raw-color-literal).

Motion tokens (DEFAULT_MOTION, 1.7.0)

Motion is uniform across every portal, so — unlike colour — there is ONE shipped default rather than one per preset. DEFAULT_MOTION carries durations (ms) and easings:

| Duration | ms | Easing | control points | css | |----------|----|--------|----------------|-----| | instant | 0 | standard | [0.2,0,0,1] | cubic-bezier(0.2,0,0,1) | | fast | 140 | decelerate | [0,0,0,1] | cubic-bezier(0,0,0,1) | | base | 200 | accelerate | [0.3,0,1,1] | cubic-bezier(0.3,0,1,1) | | slow | 300 | | | |

instant (0) is the reduced-motion collapse target. Each easing carries both a web css cubic-bezier(...) string and the bezier [x1,y1,x2,y2] control points, so @dloizides/ui-motion can build a matching RN Easing.bezier(...) and web + native animate on the same curve. motion is an OPTIONAL field on DesignTokens (a preset MAY override it), so existing presets/emitters are byte-identical.

The token shape (aligned to TenantThemeConfig)

The core fields intentionally mirror @dloizides/tenant-theme-web's TenantThemeConfig (primary, secondary, accent, semantic, light, dark, typography, branding) so a per-tenant theme override layers cleanly on top of a preset — the tenant blob and the preset speak the same field names. Fields the core cannot express (a dark app-shell, an ink scale, sanctions verdict triads) live in an optional extensions group and are documented as Stack-A supersets, not part of the TenantThemeConfig contract.

Three additions (1.2.0) are core rather than extensions, because they are needed by any app with a status badge or a filled brand button — not by one stack:

| Field | Why it needs its own slot | |-------|---------------------------| | light.surfaceMuted / dark.surfaceMuted | The inset surface (table header rows, chips, wells) recedes; surface and surfaceElevated both lift. Neither substitutes. | | onBrand | The foreground on a primary fill. A contrast partner of primary, so it sits beside it, not in a mode block. Defaults to white; a pale primary must set it. | | semantic.successBg / warningBg / errorBg / infoBg | A status tint is hand-picked for contrast, not derivable from its base — so it cannot be computed and must be carried. |

All optional, and every emitter emits them only when a preset declares them, so presets that predate 1.2.0 produce byte-identical output.

The cross-stack naming contract (#78b)

Different stacks use different CSS-variable names for the same token. toCssVars takes a name map (CssVarNames) that says which CSS variable each token field emits as; a field mapped to undefined is skipped. Two maps ship:

  • DEFAULT_CSS_VAR_NAMES — canonical kebab names (--primary, --background, --radius, …), with a dark-mode block. Adopt these for a fresh consumer.
  • AML_CSS_VAR_NAMES — the AML console's existing ui.css names, so nothing there changes.

AML name-mapping table (core → ui.css variable)

| Token field | AML CSS var | Note | |-------------|-------------|------| | primary | --brand | | | secondary, accent | (skipped) | AML is single-brand; ui.css never reads them | | semantic.success/warning/error | (via --ok/--warn/--bad) | emitted from the verdict extension | | semantic.info | (skipped) | no AML variable | | light.background | --bg | | | light.surface | --surface | | | light.surfaceElevated | (via --surface-2) | emitted from workspace.surfaceAlt | | light.text | (via --ink) | emitted from ink.base | | light.textSecondary | (via --ink-soft) | emitted from ink.soft | | light.border | --line | | | light.divider | (skipped) | AML reuses --line | | dark.* | (skipped) | AML has no light/dark toggle; its dark shell is the shell extension in :root | | radii.{xs,sm,md,lg,pill} | --r-xs, --r-sm, --r, --r-lg, --r-pill | | | shadows.{sm,md,pop} | --sh-1, --sh-2, --sh-pop | | | typography.fontFamily / monoFamily | --font / --mono | | | extensions.shell.* | --shell, --shell-2, --shell-line, --on-shell, --on-shell-dim | | | extensions.brand.* | --brand-press, --brand-soft, --brand-ring | | | extensions.ink.* | --ink, --ink-soft, --ink-faint, --ink-2 | | | extensions.workspace.* | --surface-2, --line-strong | | | extensions.verdict.* | --ok*, --warn*, --bad* (base/soft/ink) | |

Open naming decisions (need a human call before wider adoption)

These were resolved conservatively to guarantee zero change, but a human should confirm the intended long-term semantics:

  1. AML secondary/accent — AML has a single brand. The preset mirrors --brand into both so the core shape is complete, but ui.css reads neither. If AML ever gains a real secondary brand, set it here.
  2. AML dark = the app-shell. AML has a dark shell over a light workspace, not a light/dark mode toggle. The preset seeds dark from the shell so the shape is complete, and the AML name map omits dark* so no dark-mode block is emitted (the shell is emitted from the shell extension in :root). If a real AML dark mode is introduced, this needs revisiting.
  3. semantic.info — AML has no info colour; it mirrors --brand. Confirm before relying on info in AML.
  4. RN radii/shadows. The RN apps have no centralized radius/shadow tokens today, so the RN presets omit them. If RN adopts a radius/shadow scale later, decide whether it should share AML's values or define its own.

Adoption (separate tasks — this package ships values only)

This package does not modify any consuming app. Adoption is tracked separately:

  • AML: replace the hand-written :root in ui.css with toCssVars(AML_TOKENS, AML_CSS_VAR_NAMES) output.
  • erevna/katalogos: import toRnTheme(EREVNA_TOKENS) as the defaultThemeConfig fallback.
  • ThemeStudio: spread toTailwindPreset(...) into tailwind.config's presets.

Scripts

npm run build (tsup → CJS+ESM+d.ts), npm test (jest, 100% coverage), npm run lint, npm run typecheck. Publish via ./publish.ps1 patch|minor|major.