import { useEffect, useRef, useState } from 'react';
import { Input } from '@/components/ui/input';
/**
* A colour, chosen without leaving the panel.
*
* ── Why not `` ──
*
* It was one, and the browser's own picker is a window-level popup positioned by the browser. In a
* panel near the right edge it opened off the side of the window and was simply unreachable — nothing
* in CSS can move it, because it is not in the document.
*
* ── What replaces it ──
*
* Swatches and a hex field, in a panel anchored to the RIGHT of its trigger so it grows inward. Text
* over a photograph is white or black almost every time; the field is there for the times it is not.
*
* Deliberately not a gradient area and a hue strip. That is what the native control already does well,
* and rebuilding it badly to fix a positioning problem would be a worse control than the one being
* replaced.
*/
/** Enough to cover a photograph, and short enough to read as choices rather than as a palette. */
const PRESETS = [
'#ffffff',
'#f5f5f5',
'#cccccc',
'#888888',
'#333333',
'#000000',
'#f0c808',
'#e05a3a',
];
export const ColorField = ({ value, onChange }: { value: string; onChange: (color: string) => void }) => {
const [open, setOpen] = useState(false);
const [draft, setDraft] = useState(value);
const wrapper = useRef(null);
// Follows the value when it changes elsewhere — a different block being selected, or a load.
useEffect(() => setDraft(value), [value]);
/*
Close on a press anywhere else.
`pointerdown` rather than `click`, so it closes on the way down and a press meant for something
behind the panel does not land twice. Capture, because a control inside a panel below may stop
propagation for its own reasons.
*/
useEffect(() => {
if (!open) return;
const onDown = (event: PointerEvent) => {
if (!wrapper.current?.contains(event.target as Node)) setOpen(false);
};
document.addEventListener('pointerdown', onDown, true);
return () => document.removeEventListener('pointerdown', onDown, true);
}, [open]);
const commit = (next: string) => {
const trimmed = next.trim();
const full = /^#?[0-9a-fA-F]{6}$/.test(trimmed) ? `#${trimmed.replace('#', '')}`.toLowerCase() : null;
if (full) onChange(full);
};
return (