// Swatches for the picker's "Swatches" tab: a built-in palette for lights, the
// last colours you applied, and your own saved ones. Colours are { r, g, b } at
// full drive (brightest channel = 1); applying one keeps the slot's brightness.
// Pure functions, tested in test/swatches.test.js.
//
// Recent and saved swatches live in this browser for now; phase 3 moves the
// saved ones into the rig's shared state (docs/DESIGN-collab.md).
// Values are LED drive levels (linear), not screen colours: "warm white" here
// is what looks warm on the fixtures, which is redder than the same RGB on a
// monitor.
export const PALETTE = [
{ name: 'White', r: 1, g: 1, b: 1 },
{ name: 'Warm white', r: 1, g: 0.75, b: 0.45 },
{ name: 'Cool white', r: 0.75, g: 0.85, b: 1 },
{ name: 'Candle', r: 1, g: 0.5, b: 0.15 },
{ name: 'Amber', r: 1, g: 0.6, b: 0 },
{ name: 'Orange', r: 1, g: 0.35, b: 0 },
{ name: 'Red', r: 1, g: 0, b: 0 },
{ name: 'Pink', r: 1, g: 0.3, b: 0.6 },
{ name: 'Magenta', r: 1, g: 0, b: 1 },
{ name: 'Purple', r: 0.6, g: 0, b: 1 },
{ name: 'Indigo', r: 0.3, g: 0, b: 1 },
{ name: 'Blue', r: 0, g: 0, b: 1 },
{ name: 'Sky', r: 0, g: 0.6, b: 1 },
{ name: 'Cyan', r: 0, g: 1, b: 1 },
{ name: 'Teal', r: 0, g: 1, b: 0.6 },
{ name: 'Green', r: 0, g: 1, b: 0 },
{ name: 'Lime', r: 0.5, g: 1, b: 0 },
{ name: 'Yellow', r: 1, g: 1, b: 0 }
]
export const RECENT_MAX = 8
const strip = (c) => ({ r: c.r, g: c.g, b: c.b })
// Within one 8-bit step: colours that look the same are the same swatch.
export function sameColor (a, b) {
const d = 1 / 255
return Math.abs(a.r - b.r) <= d && Math.abs(a.g - b.g) <= d && Math.abs(a.b - b.b) <= d
}
export function pushRecent (list, color) {
return [strip(color), ...list.filter((c) => !sameColor(c, color))].slice(0, RECENT_MAX)
}
export function addSwatch (list, color) {
return list.some((c) => sameColor(c, color)) ? list : [...list, strip(color)]
}
export function removeSwatch (list, index) {
return list.filter((_, i) => i !== index)
}