Add react color picker, show tailwind colors all the time
This commit is contained in:
@@ -182,41 +182,225 @@ export function hsbToRgb(h: number, s: number, v: number): { r: number; g: numbe
|
||||
}
|
||||
}
|
||||
|
||||
// Function to find the closest Tailwind color
|
||||
export function findClosestTailwindColor(hex: string): string {
|
||||
// This is a simplified version - we'll expand this with actual Tailwind colors
|
||||
const tailwindColors = {
|
||||
'red-500': '#EF4444',
|
||||
'blue-500': '#3B82F6',
|
||||
'green-500': '#22C55E',
|
||||
'yellow-500': '#EAB308',
|
||||
'purple-500': '#A855F7',
|
||||
'pink-500': '#EC4899',
|
||||
'indigo-500': '#6366F1',
|
||||
// Add more colors as needed
|
||||
}
|
||||
|
||||
const targetRgb = hexToRgb(hex)
|
||||
if (!targetRgb) return 'Invalid color'
|
||||
// Function to find the closest Tailwind color using CIELAB color space
|
||||
export function findClosestTailwindColor(hex: string): { name: string; hex: string } {
|
||||
const rgb1 = hexToRgb(hex)
|
||||
if (!rgb1) return { name: 'Invalid color', hex }
|
||||
|
||||
let closestColor = ''
|
||||
let closestHex = ''
|
||||
let minDistance = Infinity
|
||||
|
||||
Object.entries(tailwindColors).forEach(([name, colorHex]) => {
|
||||
const currentRgb = hexToRgb(colorHex)
|
||||
if (!currentRgb) return
|
||||
// Convert RGB to Lab
|
||||
const lab1 = rgbToLab(rgb1.r, rgb1.g, rgb1.b)
|
||||
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(targetRgb.r - currentRgb.r, 2) +
|
||||
Math.pow(targetRgb.g - currentRgb.g, 2) +
|
||||
Math.pow(targetRgb.b - currentRgb.b, 2)
|
||||
)
|
||||
Object.entries(TAILWIND_COLORS).forEach(([colorName, shades]) => {
|
||||
Object.entries(shades).forEach(([shade, colorHex]) => {
|
||||
const rgb2 = hexToRgb(colorHex)
|
||||
if (!rgb2) return
|
||||
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance
|
||||
closestColor = name
|
||||
}
|
||||
const lab2 = rgbToLab(rgb2.r, rgb2.g, rgb2.b)
|
||||
const distance = deltaE(lab1, lab2)
|
||||
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance
|
||||
closestColor = `${colorName}-${shade}`
|
||||
closestHex = colorHex
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return closestColor
|
||||
}
|
||||
return { name: closestColor, hex: closestHex }
|
||||
}
|
||||
|
||||
// CIELAB color space conversion functions
|
||||
function rgbToLab(r: number, g: number, b: number) {
|
||||
let x, y, z
|
||||
|
||||
r = r / 255
|
||||
g = g / 255
|
||||
b = b / 255
|
||||
|
||||
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92
|
||||
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92
|
||||
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92
|
||||
|
||||
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047
|
||||
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000
|
||||
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883
|
||||
|
||||
x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + 16/116
|
||||
y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + 16/116
|
||||
z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + 16/116
|
||||
|
||||
return {
|
||||
l: (116 * y) - 16,
|
||||
a: 500 * (x - y),
|
||||
b: 200 * (y - z)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate color difference using CIEDE2000
|
||||
function deltaE(lab1: { l: number; a: number; b: number }, lab2: { l: number; a: number; b: number }) {
|
||||
const deltaL = lab2.l - lab1.l
|
||||
const deltaA = lab2.a - lab1.a
|
||||
const deltaB = lab2.b - lab1.b
|
||||
const c1 = Math.sqrt(lab1.a * lab1.a + lab1.b * lab1.b)
|
||||
const c2 = Math.sqrt(lab2.a * lab2.a + lab2.b * lab2.b)
|
||||
const deltaC = c2 - c1
|
||||
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC
|
||||
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH)
|
||||
const sc = 1.0 + 0.045 * c1
|
||||
const sh = 1.0 + 0.015 * c1
|
||||
const deltaLKlsl = deltaL / (1.0)
|
||||
const deltaCkcsc = deltaC / (sc)
|
||||
const deltaHkhsh = deltaH / (sh)
|
||||
return Math.sqrt(deltaLKlsl * deltaLKlsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh)
|
||||
}
|
||||
|
||||
// Export Tailwind colors for use in other components
|
||||
export const TAILWIND_COLORS = {
|
||||
slate: {
|
||||
50: '#f8fafc',
|
||||
100: '#f1f5f9',
|
||||
200: '#e2e8f0',
|
||||
300: '#cbd5e1',
|
||||
400: '#94a3b8',
|
||||
500: '#64748b',
|
||||
600: '#475569',
|
||||
700: '#334155',
|
||||
800: '#1e293b',
|
||||
900: '#0f172a',
|
||||
950: '#020617',
|
||||
},
|
||||
gray: {
|
||||
50: '#f9fafb',
|
||||
100: '#f3f4f6',
|
||||
200: '#e5e7eb',
|
||||
300: '#d1d5db',
|
||||
400: '#9ca3af',
|
||||
500: '#6b7280',
|
||||
600: '#4b5563',
|
||||
700: '#374151',
|
||||
800: '#1f2937',
|
||||
900: '#111827',
|
||||
950: '#030712',
|
||||
},
|
||||
zinc: {
|
||||
50: '#fafafa',
|
||||
100: '#f4f4f5',
|
||||
200: '#e4e4e7',
|
||||
300: '#d4d4d8',
|
||||
400: '#a1a1aa',
|
||||
500: '#71717a',
|
||||
600: '#52525b',
|
||||
700: '#3f3f46',
|
||||
800: '#27272a',
|
||||
900: '#18181b',
|
||||
950: '#09090b',
|
||||
},
|
||||
red: {
|
||||
50: '#fef2f2',
|
||||
100: '#fee2e2',
|
||||
200: '#fecaca',
|
||||
300: '#fca5a5',
|
||||
400: '#f87171',
|
||||
500: '#ef4444',
|
||||
600: '#dc2626',
|
||||
700: '#b91c1c',
|
||||
800: '#991b1b',
|
||||
900: '#7f1d1d',
|
||||
950: '#450a0a',
|
||||
},
|
||||
orange: {
|
||||
50: '#fff7ed',
|
||||
100: '#ffedd5',
|
||||
200: '#fed7aa',
|
||||
300: '#fdba74',
|
||||
400: '#fb923c',
|
||||
500: '#f97316',
|
||||
600: '#ea580c',
|
||||
700: '#c2410c',
|
||||
800: '#9a3412',
|
||||
900: '#7c2d12',
|
||||
950: '#431407',
|
||||
},
|
||||
yellow: {
|
||||
50: '#fefce8',
|
||||
100: '#fef9c3',
|
||||
200: '#fef08a',
|
||||
300: '#fde047',
|
||||
400: '#facc15',
|
||||
500: '#eab308',
|
||||
600: '#ca8a04',
|
||||
700: '#a16207',
|
||||
800: '#854d0e',
|
||||
900: '#713f12',
|
||||
950: '#422006',
|
||||
},
|
||||
green: {
|
||||
50: '#f0fdf4',
|
||||
100: '#dcfce7',
|
||||
200: '#bbf7d0',
|
||||
300: '#86efac',
|
||||
400: '#4ade80',
|
||||
500: '#22c55e',
|
||||
600: '#16a34a',
|
||||
700: '#15803d',
|
||||
800: '#166534',
|
||||
900: '#14532d',
|
||||
950: '#052e16',
|
||||
},
|
||||
blue: {
|
||||
50: '#eff6ff',
|
||||
100: '#dbeafe',
|
||||
200: '#bfdbfe',
|
||||
300: '#93c5fd',
|
||||
400: '#60a5fa',
|
||||
500: '#3b82f6',
|
||||
600: '#2563eb',
|
||||
700: '#1d4ed8',
|
||||
800: '#1e40af',
|
||||
900: '#1e3a8a',
|
||||
950: '#172554',
|
||||
},
|
||||
indigo: {
|
||||
50: '#eef2ff',
|
||||
100: '#e0e7ff',
|
||||
200: '#c7d2fe',
|
||||
300: '#a5b4fc',
|
||||
400: '#818cf8',
|
||||
500: '#6366f1',
|
||||
600: '#4f46e5',
|
||||
700: '#4338ca',
|
||||
800: '#3730a3',
|
||||
900: '#312e81',
|
||||
950: '#1e1b4b',
|
||||
},
|
||||
purple: {
|
||||
50: '#faf5ff',
|
||||
100: '#f3e8ff',
|
||||
200: '#e9d5ff',
|
||||
300: '#d8b4fe',
|
||||
400: '#c084fc',
|
||||
500: '#a855f7',
|
||||
600: '#9333ea',
|
||||
700: '#7e22ce',
|
||||
800: '#6b21a8',
|
||||
900: '#581c87',
|
||||
950: '#3b0764',
|
||||
},
|
||||
pink: {
|
||||
50: '#fdf2f8',
|
||||
100: '#fce7f3',
|
||||
200: '#fbcfe8',
|
||||
300: '#f9a8d4',
|
||||
400: '#f472b6',
|
||||
500: '#ec4899',
|
||||
600: '#db2777',
|
||||
700: '#be185d',
|
||||
800: '#9d174d',
|
||||
900: '#831843',
|
||||
950: '#500724',
|
||||
},
|
||||
} as const
|
||||
Reference in New Issue
Block a user