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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@zzro/z-color-picker

v2.2.0

Published

An enhanced, performant, and cross-device compatible React color picker with HSV color space, eyedropper support, and flexible format output

Downloads

36

Readme

Z Color Picker

An enhanced, performant, and cross-device compatible React color picker with HSV color space, eyedropper support, and flexible format output.

Z Color Picker Demo TypeScript License

✨ Features

  • 🎨 HSV Color Space: More intuitive color selection with hue, saturation, and value
  • 🎯 Cross-Device Eyedropper: Native EyeDropper API with fallbacks for all devices
  • 📱 Touch-Friendly: Optimized for desktop, mobile, tablets, and stylus input
  • 🔥 High Performance: Canvas-based rendering with high-DPI support and anti-aliasing
  • 📦 Flexible Output: Support for multiple color formats (hex, rgb, hsl, hsv, with alpha)
  • 🎭 Professional Layout: Eyedropper + color rings + brightness bar
  • 🌈 Color Presets: Built-in color palette with active state highlighting
  • TypeScript: Full TypeScript support with comprehensive type definitions
  • 🎨 Customizable: Background colors, palettes, and layout options

📦 Installation

npm install @zzro/z-color-picker

🚀 Quick Start

import { ZColorPicker, type ZColorResult } from "@zzro/z-color-picker";
import "@zzro/z-color-picker/styles"; // Import the CSS styles

function App() {
  const handleColorChange = (color: ZColorResult<["rgba"]>) => {
    // You get exactly what you specify in formats prop
    console.log("RGBA:", color.rgba); // { r: 255, g: 100, b: 50, a: 1 }
  };

  return (
    <ZColorPicker
      size={300}
      initialColor={{ r: 255, g: 100, b: 50, a: 1 }}
      formats={["rgba"]} // ✅ Required: explicitly specify what you want
      onChange={handleColorChange}
      showEyedropper={true}
      showBrightnessBar={true}
      showColorRings={true}
    />
  );
}

CSS Import

The component requires CSS styles to work properly. Import them using one of these methods:

// Method 1: Package export (recommended)
import "@zzro/z-color-picker/styles";

// Method 2: Direct CSS import
import "@zzro/z-color-picker/dist/z-color-picker.css";
/* Method 3: In your CSS file */
@import "@zzro/z-color-picker/styles";

📚 API Reference

Props

| Prop | Type | Default | Description | | ------------------- | ---------------------------------- | ------------------------------ | ---------------------------------- | | size | number | 300 | Size of the color picker in pixels | | initialColor | RGBAColor | { r: 255, g: 0, b: 0, a: 1 } | Initial color value | | onChange | (color: ZColorResult<T>) => void | - | Callback fired when color changes | | showEyedropper | boolean | false | Show eyedropper tool | | showBrightnessBar | boolean | false | Show brightness/value slider | | showColorRings | boolean | false | Show color preset rings | | pickerBgColor | string | "#ffffff" | Background color of the picker | | colorRingsPalette | string[] | Default palette | Custom color palette for rings | | formats | ColorFormatType[] | Required | Output color formats |

Types

// Essential types exported by the library
type ColorFormatType = "rgba" | "rgb" | "hex" | "hsl" | "hsla" | "hsv" | "hsva";

// ZColorResult provides type-safe results based on formats
// Always returns object format for consistency
type ZColorResult<T extends ColorFormatType[]> = {
  [K in T[number]]: ColorFormatResults[K];
};

// Component props type with required formats
interface ZColorPickerProps<T extends ColorFormatType[]> = {
  size?: number;
  onChange?: (color: ZColorResult<T>) => void;
  initialColor?: { r: number; g: number; b: number; a: number };
  formats: T; // Required - you must specify what formats you want
  // ... other props
};

🎨 Usage Examples

Importing Types

import {
  ZColorPicker,
  type ZColorResult,
  type ZColorPickerProps,
  type ColorFormatType,
} from "@zzro/z-color-picker";

Basic Usage

// Specify exactly what format(s) you want - no guessing!
<ZColorPicker
  formats={["rgba"]}
  onChange={(color: ZColorResult<["rgba"]>) => {
    console.log(color.rgba); // { r: 255, g: 100, b: 50, a: 1 }
  }}
/>

// Multiple formats
<ZColorPicker
  formats={["rgba", "hsv"]}
  onChange={(color: ZColorResult<["rgba", "hsv"]>) => {
    console.log(color.rgba); // { r: 255, g: 100, b: 50, a: 1 }
    console.log(color.hsv);  // { h: 15, s: 80, v: 100 }
  }}
/>

// With TypeScript for perfect type safety
const handleColorChange = (color: ZColorResult<["rgba", "hsv"]>) => {
  console.log("RGBA:", color.rgba);
  console.log("HSV:", color.hsv);
};

<ZColorPicker formats={["rgba", "hsv"]} onChange={handleColorChange} />

Single Format Output

// Hex string output
<ZColorPicker
  formats={["hex"]}
  onChange={(result: ZColorResult<["hex"]>) => console.log(result.hex)} // "#ff6432"
/>

// RGB object output
<ZColorPicker
  formats={["rgb"]}
  onChange={(result: ZColorResult<["rgb"]>) => {
    console.log(`RGB: ${result.rgb.r}, ${result.rgb.g}, ${result.rgb.b}`);
  }}
/>

// RGBA with alpha
<ZColorPicker
  formats={["rgba"]}
  onChange={(result: ZColorResult<["rgba"]>) => {
    const { r, g, b, a } = result.rgba;
    console.log(`RGBA: ${r}, ${g}, ${b}, ${a}`);
  }}
/>

Multiple Format Output

<ZColorPicker
  formats={["hex", "rgb", "hsl"]}
  onChange={(result: ZColorResult<["hex", "rgb", "hsl"]>) => {
    console.log(result.hex); // "#ff6432"
    console.log(result.rgb); // { r: 255, g: 100, b: 50 }
    console.log(result.hsl); // { h: 15, s: 80, l: 60 }
  }}
/>

Type-Safe Usage

import { ZColorPicker, type ZColorResult } from "@zzro/z-color-picker";

function TypeSafeExample() {
  const [color, setColor] = useState<{
    r: number;
    g: number;
    b: number;
    a: number;
  }>({
    r: 255,
    g: 100,
    b: 50,
    a: 1,
  });

  // Type-safe handler for multiple formats
  const handleChange = (result: ZColorResult<["hex", "rgba"]>) => {
    console.log(result.hex); // string
    console.log(result.rgba); // { r: number; g: number; b: number; a: number }
    setColor(result.rgba);
  };

  return (
    <ZColorPicker
      initialColor={color}
      formats={["hex", "rgba"]}
      onChange={handleChange}
    />
  );
}

Generic Component with Type Constraints

interface ColorPickerWrapperProps<T extends ColorFormatType[]> {
  formats: T;
  onColorChange: (color: ZColorResult<T>) => void;
  label: string;
}

function ColorPickerWrapper<T extends ColorFormatType[]>({
  formats,
  onColorChange,
  label,
}: ColorPickerWrapperProps<T>) {
  return (
    <div>
      <label>{label}</label>
      <ZColorPicker
        formats={formats}
        onChange={onColorChange}
        showBrightnessBar={true}
      />
    </div>
  );
}

// Usage with full type safety
const handleHexColor = (result: ZColorResult<["hex"]>) => {
  console.log(result.hex); // TypeScript knows this is a string
};

<ColorPickerWrapper
  formats={["hex"]}
  onColorChange={handleHexColor}
  label="Hex Color Picker"
/>;

Professional Layout

<ZColorPicker
  size={280}
  initialColor={{ r: 255, g: 100, b: 50, a: 0.8 }}
  formats={["hex", "rgba"]}
  onChange={(color: ZColorResult<["hex", "rgba"]>) => {
    console.log("Hex:", color.hex);
    console.log("RGBA:", color.rgba);
  }}
  showEyedropper={true}
  showBrightnessBar={true}
  showColorRings={true}
  pickerBgColor="#f8f9fa"
/>

Custom Color Palette

const customPalette = [
  "#FF6B6B",
  "#4ECDC4",
  "#45B7D1",
  "#96CEB4",
  "#FFEAA7",
  "#DDA0DD",
  "#98D8C8",
  "#F7DC6F",
];

<ZColorPicker
  showColorRings={true}
  colorRingsPalette={customPalette}
  formats={["rgba"]}
  onChange={(color: ZColorResult<["rgba"]>) => console.log(color)}
/>;

React State Integration

import { useState } from "react";
import { ZColorPicker, type RGBAColor } from "@zzro/z-color-picker";

function ColorDemo() {
  const [color, setColor] = useState<RGBAColor>({
    r: 255,
    g: 100,
    b: 50,
    a: 1,
  });

  return (
    <div
      style={{
        backgroundColor: `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`,
        minHeight: "100vh",
        padding: "2rem",
      }}
    >
      <ZColorPicker
        initialColor={color}
        formats={["rgba"]}
        onChange={(newColor: ZColorResult<["rgba"]>) => setColor(newColor.rgba)}
        showEyedropper={true}
        showBrightnessBar={true}
        showColorRings={true}
      />

      <div style={{ marginTop: "1rem", color: "white" }}>
        <p>
          R: {color.r}, G: {color.g}, B: {color.b}, A: {color.a.toFixed(2)}
        </p>
      </div>
    </div>
  );
}

🌈 Color Format Guide

| Format | Output Type | Example | Description | | -------- | ---------------- | ----------------------------------- | ------------------------ | | "hex" | string | "#ff6432" | Hexadecimal color string | | "rgb" | { r, g, b } | { r: 255, g: 100, b: 50 } | RGB values (0-255) | | "rgba" | { r, g, b, a } | { r: 255, g: 100, b: 50, a: 0.8 } | RGB with alpha (0-1) | | "hsl" | { h, s, l } | { h: 15, s: 80, l: 60 } | HSL values | | "hsla" | { h, s, l, a } | { h: 15, s: 80, l: 60, a: 0.8 } | HSL with alpha | | "hsv" | { h, s, v } | { h: 15, s: 80, v: 100 } | HSV values | | "hsva" | { h, s, v, a } | { h: 15, s: 80, v: 100, a: 0.8 } | HSV with alpha |

📱 Cross-Device Support

The eyedropper feature works across all devices with intelligent fallbacks:

Desktop Browsers

  • Chrome/Edge: Native EyeDropper API for system-wide color picking
  • Firefox/Safari: Screen capture with canvas-based pixel sampling

Mobile & Tablet

  • Touch Events: Optimized touch interaction for mobile devices
  • Pointer Events: Full stylus and pen support for tablets
  • Fallback: Native color input as final fallback

Keyboard Support

  • Enter: Pick color from screen center
  • Escape: Cancel eyedropper mode

🎨 Styling & Customization

Background Colors

// Light theme
<ZColorPicker pickerBgColor="#ffffff" />

// Dark theme
<ZColorPicker pickerBgColor="#1a1a1a" />

// Transparent
<ZColorPicker pickerBgColor="transparent" />

CSS Customization

Override component styles with higher specificity:

/* Custom picker size */
.z-color-picker canvas {
  border: 2px solid #e2e8f0;
}

/* Custom button styles */
.z-color-picker button {
  border-radius: 8px;
}

/* Custom color rings */
.z-color-picker .w-6.h-6 {
  width: 2rem;
  height: 2rem;
}

⚡ TypeScript Usage

Type-Safe Color Handling

import { ZColorPicker, type ZColorResult, type RGBAColor } from "@zzro/z-color-picker";

// Single format - still returns object format
const handleHexChange = (color: ZColorResult<["hex"]>) => {
  console.log("Hex color:", color.hex); // Access .hex property
};

// Multiple formats - object type
const handleMultipleFormats = (color: ZColorResult<["hex", "rgba"]>) => {
  console.log(color.hex);   // string
  console.log(color.rgba);  // RGBAColor
};

// Component usage
<ZColorPicker
  formats={["hex"]}
  onChange={handleHexChange}
/>

<ZColorPicker
  formats={["hex", "rgba"]}
  onChange={handleMultipleFormats}
/>

Generic Type Constraints

// Constrain formats to specific types
function ColorPicker<T extends ["hex"] | ["rgba"] | ["hex", "rgba"]>({
  formats,
  onChange,
}: {
  formats: T;
  onChange: (color: ZColorResult<T>) => void;
}) {
  return <ZColorPicker formats={formats} onChange={onChange} />;
}

🏗️ Architecture

No Framework Dependencies

  • Vanilla CSS: No Tailwind, Bootstrap, or other CSS frameworks required
  • Pure React: Only React as peer dependency
  • Lightweight: Minimal bundle size with tree-shakeable exports

Performance Optimizations

  • Canvas Rendering: High-performance color wheel with anti-aliasing
  • Memoized Calculations: Optimized re-renders with React.useMemo
  • High-DPI Support: Crisp rendering on retina displays
  • Touch Optimized: Responsive interaction for all input types

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

git clone https://github.com/nikhilswain/z-color-picker.git
cd z-color-picker
npm install
npm run dev

Build Library

npm run build:lib

📄 License

MIT © nikhilswain


Made with ❤️ for the React community