color-picker
cult-ui/color-pickerUnverifiedComponent
Interactive color picker component with HSL support and preset colors
Install it
npx shadcn@latest add https://raw.githubusercontent.com/nolly-studio/cult-ui/HEAD/apps/www/color-picker.jsonSource
1"use client"23import React, { useEffect, useState } from "react"4import { Check, ChevronDown } from "lucide-react"5import { AnimatePresence, motion } from "motion/react"67import { Button } from "@/components/ui/button"8import { Input } from "@/components/ui/input"9import { Label } from "@/components/ui/label"10import {11 Popover,12 PopoverContent,13 PopoverTrigger,14} from "@/components/ui/popover"1516// Helper functions for color conversion17const hslToHex = (h: number, s: number, l: number) => {18 l /= 10019 const a = (s * Math.min(l, 1 - l)) / 10020 const f = (n: number) => {21 const k = (n + h / 30) % 1222 const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)23 return Math.round(255 * color)24 .toString(16)25 .padStart(2, "0")26 }27 return `#${f(0)}${f(8)}${f(4)}`28}2930const hexToHsl = (hex: string): [number, number, number] => {31 const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)32 if (!result) return [0, 0, 0]3334 let r = parseInt(result[1], 16) / 25535 let g = parseInt(result[2], 16) / 25536 let b = parseInt(result[3], 16) / 2553738 const max = Math.max(r, g, b)39 const min = Math.min(r, g, b)40 let h = 041 let s = 042 let l = (max + min) / 24344 if (max !== min) {45 const d = max - min46 s = l > 0.5 ? d / (2 - max - min) : d / (max + min)47 switch (max) {48 case r:49 h = (g - b) / d + (g < b ? 6 : 0)50 break51 case g:52 h = (b - r) / d + 253 break54 case b:55 h = (r - g) / d + 456 break57 }58 h /= 659 }6061 return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)]62}6364const normalizeColor = (color: string): string => {65 if (color.startsWith("#")) {66 return color.toUpperCase()67 } else if (color.startsWith("hsl")) {68 const [h, s, l] = color.match(/\d+(\.\d+)?/g)?.map(Number) || [0, 0, 0]69 return `hsl(${Math.round(h)}, ${Math.round(s)}%, ${Math.round(l)}%)`70 }71 return color72}7374const trimColorString = (color: string, maxLength: number = 20): string => {75 if (color.length <= maxLength) return color76 return `${color.slice(0, maxLength - 3)}...`77}7879export function ColorPicker({80 color,81 onChange,82}: {83 color: string84 onChange: (color: string) => void85}) {86 const [hsl, setHsl] = useState<[number, number, number]>([0, 0, 0])87 const [colorInput, setColorInput] = useState(color)88 const [isOpen, setIsOpen] = useState(false)8990 useEffect(() => {91 handleColorChange(color)92 }, [color])9394 const handleColorChange = (newColor: string) => {95// … truncated
What it pulls in
npm packages
Files it writes
More from cult/ui
All 157 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-instructionsai-instructions | cult/ui | Components | Unverified | 2 deps | |
| ai-instructions-demoai-instructions-demo | cult/ui | Components | Unverified | no deps | |
| animated-numberanimated-number | cult/ui | Components | Unverified | 1 dep | |
| animated-number-demoanimated-number-demo | cult/ui | Components | Unverified | no deps | |
| bg-animate-buttonbg-animate-button | cult/ui | Components | Unverified | no deps | |
| bg-animate-button-demobg-animate-button-demo | cult/ui | Components | Unverified | no deps | |
| bg-animated-fractal-dot-gridbg-animated-fractal-dot-grid | cult/ui | Components | Unverified | 1 dep | |
| bg-animated-fractal-dot-grid-demobg-animated-fractal-dot-grid-demo | cult/ui | Components | Unverified | no deps |
