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

@aphexcms/plugin-color-picker

v0.1.0

Published

Color picker field widget for AphexCMS — a rich color input (hex, optional alpha) registered as a plugin field component

Readme

@aphexcms/plugin-color-picker

A color field for AphexCMS — a swatch + popover picker (hex / RGB / HSL, optional alpha). Color is a plugin, not a built-in field type: the engine ships the primitives, color composes on top of them.

Install

pnpm add @aphexcms/plugin-color-picker

Register it once in your client-safe plugin registry (src/lib/plugins.ts):

import { colorPickerPlugin } from '@aphexcms/plugin-color-picker';

export const plugins = [colorPickerPlugin()];

That single registration does three things: adds the picker widget, registers the type: 'color' field type (so it's type-safe with no extra import), and installs the transform that expands it.

Those land on both planes, so plugins.ts has to reach both: aphex.config.ts imports it (the engine needs the transform) and the admin passes it to <AdminApp {plugins} /> (the browser needs the widget). Scaffolded projects are already wired this way, so there's nothing further to do — but in a hand-rolled setup, registering on only one side leaves you with either a color field the engine can't expand, or an expanded field with no picker.

Two ways to store a color

The plugin supports two storage shapes. Pick per field by the shape you want to read.

Rich object — type: 'color'

Stores the full { hex, alpha, rgb, hsl, hsv } object (the same model as Sanity's @sanity/color-input), so you can read the color in any format without converting.

// In a schema — no import needed; registering the plugin makes `type: 'color'`
// available and fully type-safe (autocomplete, typos caught).
{ name: 'brand', type: 'color', title: 'Brand color' }

// Allow an alpha channel:
{ name: 'overlay', type: 'color', title: 'Overlay', alpha: true }

Stored value:

{
	"hex": "#9D2F2F",
	"alpha": 1,
	"rgb": { "r": 157, "g": 47, "b": 47, "a": 1 },
	"hsl": { "h": 0, "s": 53.9, "l": 40, "a": 1 },
	"hsv": { "h": 0, "s": 70.1, "v": 61.6, "a": 1 }
}

Read .hex for a CSS value:

<div style:--accent={settings.brand?.hex}>…</div>

type: 'color' generates a fully-typed nested interface in generated-types.ts — not unknown — because the plugin's schema-transform runs during type generation too (see How type: 'color' works).

Plain string — type: 'string', input: 'color'

Stores just a CSS color string ("#9D2F2F"). Simplest to consume — it drops straight into CSS — ideal for theme tokens where you never need the other formats.

{ name: 'accent', type: 'string', input: 'color' }

// Works per-item in arrays too:
{ name: 'palette', type: 'array', of: [{ type: 'string', input: 'color' }] }

Hex-only (no rgb/hsl formats in the picker):

{ name: 'accent', type: 'string', input: 'color', inputOptions: { hexOnly: true } }

The color() helper (alternative to type: 'color')

Equivalent to type: 'color', for when you'd rather import a builder than rely on the ambient type (e.g. to avoid depending on plugin registration order). It accepts the same field properties the literal does — access, validation, group (including multiple) — so neither way is more expressive. Import from the server-safe /schema entry:

import { color } from '@aphexcms/plugin-color-picker/schema';

// in a schema's fields:
color({ name: 'brand', title: 'Brand color', group: 'design', alpha: true });

Which should I use?

| Want | Use | | ----------------------------------------------------- | ---------------------------------------------- | | A CSS value that drops straight into style/tokens | type: 'string', input: 'color'"#…" | | The color in multiple formats (hex + rgb + hsl + hsv) | type: 'color' → the object, read .hex etc. | | A builder instead of the ambient type | color({ … }) |

Type generation

type: 'color' only desugars into its object shape during codegen if the type generator is told about your plugins. Pass your plugin registry as the third argument:

// package.json
"generate:types": "aphex generate:types ./src/lib/schemaTypes/index.ts ./src/lib/generated-types.ts ./src/lib/plugins.ts"

The aphex() Vite plugin does this automatically in dev (it passes src/lib/plugins.ts by default; override with the typegen.plugins option). Without the plugins argument, type: 'color' fields generate as unknown.

How type: 'color' works

Color is not a new storage primitive — the engine only knows built-in field types. type: 'color' is sugar in two halves:

  • Compile-time: the plugin augments core's FieldTypeMap (via declare module), so { type: 'color' } is a first-class, type-safe field wherever the plugin is imported.
  • Runtime + codegen: the plugin's aphex/schema/transform part rewrites every { type: 'color' } into the rich object field before the engine, admin, and type generator see it. So the stored data is a plain object — portable and interpretable by core alone, even if the plugin is later removed.

This is why type: 'color' reads like a native type while keeping full type safety and Aphex's "documents are portable" guarantee.

Exports

| Import | From | What | | -------------------------- | -------------------------------------- | -------------------------------------- | | colorPickerPlugin() | @aphexcms/plugin-color-picker | The plugin (register in plugins.ts) | | ColorPicker | @aphexcms/plugin-color-picker | The standalone picker Svelte component | | color() | @aphexcms/plugin-color-picker/schema | Rich-color field builder | | ColorValue, ColorField | @aphexcms/plugin-color-picker/schema | Types |