import { useEffect, useState } from "react"; import Input from "@moduletrace/twui/form/Input"; import Row from "@moduletrace/twui/layout/Row"; import Span from "@moduletrace/twui/layout/Span"; import Stack from "@moduletrace/twui/layout/Stack"; import { BotHues, type BotStoneShape } from "@/src/dict/bot-dict"; import { normalizeBotColor, paletteColorTitle } from "@/src/utils/bot-color"; import BotColourOption from "./bot-colour-option"; import BotColourSwatch from "./bot-colour-swatch"; type Props = { /** * The bot's colour as `#rrggbb`. */ color: string; /** * Which stone shape it's drawn on. Picking a palette tile sets both, so a * palette bot looks exactly as it always did. */ stone: BotStoneShape; disabled?: boolean; onChange: (picked: { color: string; stone: BotStoneShape }) => void; }; /** * Picks a bot's colour: the palette tiles (each on its own stone), or any * colour at all from the swatch or the hex field. A custom colour keeps the * stone the bot already has, so its shape stays its own. */ export default function BotColourPicker({ color, stone, disabled, onChange }: Props) { const [hex, setHex] = useState(color); const [invalid, setInvalid] = useState(false); const picked = paletteValueFor({ color }); const palette_title = paletteColorTitle({ color }); useEffect(() => setHex(color), [color]); const commitHex = (value: string) => { setHex(value); const normalized = normalizeBotColor({ color: value }); setInvalid(Boolean(value.trim()) && !normalized); if (normalized) onChange({ color: normalized, stone }); }; return ( Colour {BotHues.map((option) => ( onChange({ color: option.color, stone: option.value }) } /> ))} Any colour onChange({ color: next, stone })} /> commitHex(e.target.value)} onBlur={() => !invalid && setHex(color)} /> {palette_title ? "A palette colour. Pick any colour, or type a hex, to make it its own." : "Its own colour. Its stone keeps its shape."} ); } /** * The palette entry a colour is, by comparing hexes. */ function paletteValueFor({ color }: { color: string }): string | null { const normalized = normalizeBotColor({ color }); if (!normalized) return null; return BotHues.find((entry) => entry.color == normalized)?.value || null; }