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

@theemel/editor

v0.16.2

Published

Interactive design system editor — pick colors, enforce WCAG AA contrast, export CSS custom properties

Readme

@theemel/editor

Interactive design system editor for React apps. Pick colors, generate harmony palettes, enforce WCAG AA contrast, customize typography and interaction states, and export CSS custom properties — all in real time. Fully responsive — works on desktop, tablet, and mobile.

Early Access: All features are currently unlocked for free — no license key or account required.

Install

npm install @theemel/editor

Peer Dependencies

| Package | Version | Required | |---------|---------|----------| | react | ^18.0.0 \|\| ^19.0.0 | Yes | | react-dom | ^18.0.0 \|\| ^19.0.0 | Yes | | axe-core | >=4.0.0 | Optional — enables accessibility auditing | | lucide-react | >=0.294.0 | Optional — enables icon previews |

Install optional peers for full functionality:

npm install axe-core lucide-react

Quick Start

import { DesignSystemEditor } from '@theemel/editor';
import '@theemel/editor/style.css';

function App() {
  return <DesignSystemEditor />;
}

The editor writes CSS custom properties (HSL values) to :root, so it works with any framework that consumes CSS variables.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | licenseKey | string | — | License key to unlock premium features. | | upgradeUrl | string | "/pricing" | URL shown in premium gate upgrade prompts. | | signInUrl | string | — | URL shown in premium gate sign-in prompts. | | prEndpointUrl | string | — | URL for PR creation endpoint. PR button hidden if omitted. | | accessibilityAudit | boolean | true | Enable axe-core color contrast auditing. | | onChange | (colors: Record<string, string>) => void | — | Callback on every color change with the full color map. | | onExport | (css: string) => void | — | Override built-in CSS modal. Receives the generated CSS string. | | className | string | — | Additional CSS class for the wrapper element. | | showHeader | boolean | true | Show the editor header with logo and navigation. | | showNavLinks | boolean | true | Show page navigation links in the header and mobile menu. | | headerRight | React.ReactNode | — | Custom content rendered on the right side of the header (e.g. auth buttons). | | aboutUrl | string | — | URL for the About page link in the header navigation. |

Premium Features

The following features require a valid license key:

| Feature | Description | |---------|-------------| | Harmony schemes | Generate palettes using complementary, analogous, triadic, or split-complementary color relationships. | | Color locks | Lock up to 4 colors to preserve them during palette regeneration. | | PR integration | Create design system pull requests directly from the editor. | | Undo/redo | History management for color changes. | | Image palette extraction | Extract color palettes from uploaded images with preview confirmation. | | Palette export | Download palette as SVG/PNG, or copy as HEX/RGB/RGBA text. | | Interaction states | Style hover, focus, and active states for buttons and components. | | Typography interactions | Customize hover, active, and underline behavior for links and headings. | | Custom fonts | Add any Google Font by name — validated, loaded, and persisted across sessions. |

License Key Format

Keys follow the format THEEMEL-XXXX-XXXX-XXXX with a checksum-validated third segment. Use generateLicenseKey() to create valid keys.

PremiumGate Component

Wrap any feature in PremiumGate to gate it behind a license key. Clicking a gated feature opens a modal with upgrade and sign-in options:

import { PremiumGate } from '@theemel/editor';

<PremiumGate feature="harmony-schemes" upgradeUrl="/pricing" signInUrl="/sign-in">
  <HarmonyControls />
</PremiumGate>

| Prop | Type | Default | Description | |------|------|---------|-------------| | feature | string | — | Name of the premium feature being gated. | | variant | "section" \| "inline" | "section" | "section" dims content with a lock overlay; "inline" shows a lock icon inline. Both open a modal on click. | | upgradeUrl | string | "/pricing" | URL for the upgrade prompt. | | signInUrl | string | — | URL for the sign-in prompt. |

LicenseProvider

If using PremiumGate or useLicense outside of DesignSystemEditor, wrap your tree in LicenseProvider:

import { LicenseProvider } from '@theemel/editor';

<LicenseProvider licenseKey="THEEMEL-XXXX-XXXX-XXXX">
  <App />
</LicenseProvider>

Usage Examples

Basic — color picker only

<DesignSystemEditor accessibilityAudit={false} />

With PR creation

<DesignSystemEditor prEndpointUrl="/api/create-design-pr" />

With premium features

<DesignSystemEditor
  licenseKey="THEEMEL-XXXX-XXXX-XXXX"
  upgradeUrl="/pricing"
  signInUrl="/sign-in"
/>

With custom header content

<DesignSystemEditor
  headerRight={<button onClick={handleSignIn}>Sign In</button>}
  aboutUrl="/about"
/>

Listen for changes

<DesignSystemEditor
  onChange={(colors) => {
    console.log('Brand color:', colors['--brand']);
  }}
/>

Custom export handler

<DesignSystemEditor
  onExport={(css) => {
    navigator.clipboard.writeText(css);
  }}
/>

Embedded / headless

<DesignSystemEditor
  showHeader={false}
  showNavLinks={false}
/>

Exported Utilities

import {
  // Color utilities
  hslStringToHex,    // "210 50% 40%" -> "#336699"
  hexToHslString,    // "#336699" -> "210.0 50.0% 40.0%"
  contrastRatio,     // WCAG contrast ratio between two HSL strings
  fgForBg,           // Best foreground (black/white) for a background HSL
  EDITABLE_VARS,     // Array of { key, label } token definitions
  HARMONY_SCHEMES,   // ['Complementary', 'Analogous', 'Triadic', 'Split-Complementary']
  applyStoredThemeColors, // Restore persisted theme from localStorage

  // localStorage key constants
  CARD_STYLE_KEY,            // Key for card style storage
  TYPOGRAPHY_KEY,            // Key for typography storage
  ALERT_STYLE_KEY,           // Key for dialog alert style storage
  TOAST_STYLE_KEY,           // Key for toast style storage
  INTERACTION_STYLE_KEY,     // Key for interaction style storage

  // Card, typography & interaction style utilities
  applyStoredCardStyle,           // Restore card style from localStorage
  applyStoredTypography,          // Restore typography from localStorage
  applyStoredAlertStyle,          // Restore dialog alert style from localStorage
  applyStoredToastStyle,          // Restore toast style from localStorage
  applyStoredInteractionStyle,    // Restore button interaction style from localStorage

  // Shareable URL utilities
  serializeThemeState,            // Encode full theme state as base64 string
  deserializeThemeState,          // Decode base64 string back to theme state

  // Export utilities
  generateDesignTokens,           // Generate W3C Design Token JSON from theme state
  exportPaletteAsText,            // Export palette as HEX, RGB, or RGBA text
  exportPaletteAsSvg,             // Export palette as SVG string
  exportPaletteAsPng,             // Export palette as PNG Blob

  // Custom font utilities
  getCustomFonts,       // Load custom fonts from localStorage
  addCustomFont,        // Validate & add a Google Font by name
  removeCustomFont,     // Remove a custom font by label
  initCustomFonts,      // Re-register all custom fonts on startup

  // License utilities
  validateLicenseKey,   // Validate a THEEMEL-XXXX-XXXX-XXXX key
  generateLicenseKey,   // Generate a valid license key

  // Premium components & hooks
  LicenseProvider,      // Context provider for license state
  useLicense,           // Hook: { isValid, isPremium }
  PremiumGate,          // Gate component for premium features
} from '@theemel/editor';

Exported Types

import type {
  DesignSystemEditorProps,
  TokenDefinition,
  HarmonyScheme,
  CardStyleState,
  TypographyState,
  AlertStyleState,
  ToastStyleState,
  InteractionStyleState,
  TypoInteractionStyleState,
  CustomFontEntry,
  PremiumFeature,
  LicenseValidation,
  LicenseProviderProps,
  PremiumGateProps,
} from '@theemel/editor';

How It Works

  1. Color picking — Click any swatch to open the native color picker. Changing a key color (brand, secondary, accent, background) automatically derives related tokens.
  2. Harmony schemes (Pro) — Generate palettes using complementary, analogous, triadic, or split-complementary color relationships.
  3. Contrast enforcement — Every foreground/background pair is checked against WCAG AA (4.5:1). Failing pairs are auto-corrected by adjusting lightness.
  4. Typography — Choose heading and body fonts (including custom Google Fonts), adjust sizes, weights, line height, and letter spacing with live preview. Five built-in presets (System, Modern, Classic, Compact, Editorial).
  5. Button interactions (Pro) — Fine-tune hover opacity, hover/active scale, transition duration, and focus ring width with presets (Subtle, Elevated, Bold).
  6. Typography interactions (Pro) — Customize link hover/active behavior (opacity, scale, underline) and heading hover effects with live preview.
  7. Persistence — All settings (colors, typography, card styles, dialog styles, toast styles, interactions) are saved to localStorage and restored on reload.
  8. Per-section export — Every section header includes a CSS | Tokens split button to export CSS custom properties with Tailwind config, or W3C Design Token JSON, for that section.
  9. Shareable URLs — Encode your full theme state in the URL hash and share it with anyone via a single link.
  10. Palette export (Pro) — Download your palette as SVG or PNG, or copy as a HEX/RGB/RGBA text list.
  11. Custom fonts (Pro) — Add any Google Font by name. The editor validates the font exists, loads all weights, adds it to heading/body dropdowns, and persists it across sessions.
  12. Mobile friendly — Fully responsive UI with mobile-optimized dropdowns, compact swatch labels, and stacked layouts for smaller screens.

Package Architecture

The editor is built with Vite in library mode and published as an ES module:

@theemel/editor
├── dist/index.js      # ESM bundle (all components + utilities)
├── dist/index.d.ts    # TypeScript declarations
└── dist/style.css     # Pre-compiled, scoped Tailwind styles

Exports Map

{
  ".":            { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
  "./style.css":  "./dist/style.css"
}

Import the main entry point for components and utilities, and style.css separately for styles. This keeps CSS opt-in and avoids side effects during tree-shaking.

Tailwind Scoping

The editor ships pre-compiled CSS via @theemel/editor/style.css. Styles are scoped using Tailwind's important: '.ds-editor' so they don't conflict with your app's styles. The root element is automatically wrapped in <div className="ds-editor">.

Development

# From the repo root
npm install

# Build the package
cd packages/editor
npm run build

# Watch mode
npm run dev

Testing

The project includes automated accessibility testing:

# Run all tests (includes axe-core a11y checks)
npm run test:run

# Lint for accessibility issues
npm run lint

The test suite uses vitest-axe to run axe-core against rendered components, catching WCAG violations automatically. ESLint with eslint-plugin-jsx-a11y provides static analysis for common accessibility anti-patterns.

Publishing to npm

The package is published as @theemel/editor on npm. To publish a new version:

# 1. Build
cd packages/editor
npm run build

# 2. Verify the tarball contents (should only include dist/)
npm pack --dry-run

# 3. Bump the version
npm version patch   # or minor / major

# 4. Publish (scoped packages require --access public on first publish)
npm publish --access public

You must be logged in to npm (npm login) with publish access to the @theemel scope.

License

MIT