Add initial app

This commit is contained in:
2025-02-10 10:19:20 -05:00
parent a75b27f19f
commit db5fb7ca61
19 changed files with 4338 additions and 0 deletions

222
src/utils/colors.ts Normal file
View File

@@ -0,0 +1,222 @@
// Color conversion utilities
export function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null
}
export function rgbToHex(r: number, g: number, b: number): string {
return '#' + [r, g, b].map(x => {
const hex = x.toString(16)
return hex.length === 1 ? '0' + hex : hex
}).join('')
}
export function rgbToHsl(r: number, g: number, b: number): { h: number; s: number; l: number } {
r /= 255
g /= 255
b /= 255
const max = Math.max(r, g, b)
const min = Math.min(r, g, b)
let h = 0
let s
const l = (max + min) / 2
if (max === min) {
h = s = 0
} else {
const d = max - min
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0)
break
case g:
h = (b - r) / d + 2
break
case b:
h = (r - g) / d + 4
break
}
h /= 6
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100),
}
}
export function hslToRgb(h: number, s: number, l: number): { r: number; g: number; b: number } {
h /= 360
s /= 100
l /= 100
let r: number
let g: number
let b: number
if (s === 0) {
r = g = b = l
} else {
const hue2rgb = (p: number, q: number, t: number) => {
if (t < 0) t += 1
if (t > 1) t -= 1
if (t < 1/6) return p + (q - p) * 6 * t
if (t < 1/2) return q
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6
return p
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s
const p = 2 * l - q
r = hue2rgb(p, q, h + 1/3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1/3)
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255),
}
}
export function rgbToHsb(r: number, g: number, b: number): { h: number; s: number; b: number } {
r /= 255
g /= 255
b /= 255
const max = Math.max(r, g, b)
const min = Math.min(r, g, b)
let h = 0
const s = max === 0 ? 0 : (max - min) / max
const v = max
if (max !== min) {
switch (max) {
case r:
h = (g - b) / (max - min) + (g < b ? 6 : 0)
break
case g:
h = (b - r) / (max - min) + 2
break
case b:
h = (r - g) / (max - min) + 4
break
}
h /= 6
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
b: Math.round(v * 100),
}
}
export function hsbToRgb(h: number, s: number, v: number): { r: number; g: number; b: number } {
h /= 360
s /= 100
v /= 100
let r: number
let g: number
let b: number
const i = Math.floor(h * 6)
const f = h * 6 - i
const p = v * (1 - s)
const q = v * (1 - f * s)
const t = v * (1 - (1 - f) * s)
switch (i % 6) {
case 0:
r = v
g = t
b = p
break
case 1:
r = q
g = v
b = p
break
case 2:
r = p
g = v
b = t
break
case 3:
r = p
g = q
b = v
break
case 4:
r = t
g = p
b = v
break
case 5:
r = v
g = p
b = q
break
default:
r = g = b = 0
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255),
}
}
// 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'
let closestColor = ''
let minDistance = Infinity
Object.entries(tailwindColors).forEach(([name, colorHex]) => {
const currentRgb = hexToRgb(colorHex)
if (!currentRgb) return
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)
)
if (distance < minDistance) {
minDistance = distance
closestColor = name
}
})
return closestColor
}