import React from 'react' import { RotateCcw, X } from 'lucide-react' import InfoTip from './InfoTip' // Shared storefront-style rows used by the Theme, Pages and Field Settings panels. // the reference builder idiom: label left; read-only hex + circle swatch + reset on the right; numbers as slider + number + unit + reset. export const inputBase = 'h-[34px] px-2.5 py-1.5 text-sm text-gray-900 border border-gray-200 rounded-md bg-white box-border focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500' const isSet = (v) => v !== undefined && v !== null && v !== '' export function SubHeading({ children, tip }) { return (

{children} {tip && }

) } /** * Colour row. `value` unset shows "Inherit" (the global theme colour applies). `onClear` (optional) writes null so the * key is really removed from the stored field (updateField merges); `onReset` (optional) restores a default. */ export function ColorRow({ label, value, placeholder = '#000000', onChange, onClear, onReset, tip, testId }) { const shown = isSet(value) ? String(value) : '' const swatch = isSet(value) ? String(value) : placeholder const pickerValue = /^#[0-9a-fA-F]{6}$/.test(swatch) ? swatch : (/^#[0-9a-fA-F]{3}$/.test(swatch) ? `#${swatch[1]}${swatch[1]}${swatch[2]}${swatch[2]}${swatch[3]}${swatch[3]}` : '#000000') return (
onChange(e.target.value)} aria-label={`${label} hex value`} className="w-[84px] h-[34px] px-2 text-xs font-mono uppercase placeholder:normal-case placeholder:font-sans border border-gray-200 rounded-md bg-gray-50 text-gray-700 focus:outline-none focus:ring-1 focus:ring-blue-500" /> onChange(e.target.value)} aria-label={`${label} colour picker`} className="absolute inset-0 w-full h-full opacity-0 cursor-pointer" /> {onClear ? ( ) : onReset ? ( ) : null}
) } /** Slider + number input + unit + reset (the reference builder "Small [n] px ⟲"). */ export function NumberRow({ label, value, min = 0, max = 100, step = 1, unit = 'px', onChange, onReset, tip, testId, slider = true }) { const num = isSet(value) ? Number(value) : '' return (
onChange(e.target.value === '' ? null : parseFloat(e.target.value))} aria-label={label} className="w-[68px] h-[34px] px-2 text-sm border border-gray-200 rounded-md bg-gray-50 text-gray-900 box-border focus:outline-none focus:ring-1 focus:ring-blue-500" /> {unit && {unit}} {onReset && ( )}
{slider && ( onChange(parseFloat(e.target.value))} aria-label={`${label} slider`} className="w-full mt-1.5 h-1.5 accent-blue-600 cursor-pointer" /> )}
) } export function SelectRow({ label, value, options, onChange, tip, testId, onReset }) { return (
{onReset && ( )}
) } export function TextRow({ label, value, onChange, placeholder, tip, testId, type = 'text' }) { return (
onChange(e.target.value)} aria-label={label} className={`${inputBase} w-full`} />
) } /** the reference builder toggle switch (peer checkbox). */ export function ToggleRow({ label, checked, onChange, tip, testId, disabled = false }) { return (
{label} {tip && }
) } /** Segmented buttons (e.g. 12h / 24h, left / center / right). */ export function Segmented({ label, value, options, onChange, tip, testId }) { return (
{label && ( )}
{options.map((o) => { const active = String(value) === String(o.value) return ( ) })}
) } /** Four numeric inputs (top/right/bottom/left or corners). */ export function FourSides({ label, values = {}, keys = ['top', 'right', 'bottom', 'left'], captions = ['Top', 'Right', 'Bottom', 'Left'], onChange, tip, testId }) { return (
{keys.map((k, i) => (
onChange(k, e.target.value === '' ? 0 : parseFloat(e.target.value))} aria-label={`${label} ${captions[i]}`} className="w-full h-[34px] px-1.5 text-sm text-center border border-gray-200 rounded-md bg-white box-border focus:outline-none focus:ring-1 focus:ring-blue-500" /> {captions[i]}
))}
) }