'use client'; import type { ReactNode } from 'react'; type GridOverride = { columns?: number; gap?: number }; const NUMBER_INPUT_STYLE = { padding: '8px 12px', borderRadius: '6px', flex: 1, fontSize: '0.9rem', } as const; /** * The override editor for one grid: a column count and a gap, both optional, * both falling back to a wider setting when left empty. * * Giving the album covers their own grid (#523) was implemented by copying this * block — fifty-eight lines whose entire diff was the bounds it clamps to and * the key it writes (#533). Two editors that have to behave identically had two * implementations, which is how they drift apart. * * A value outside the bounds is discarded rather than clamped, which is what * the copies did: the field then reads as empty and the setting falls back, * instead of silently saving a number nobody typed. */ export default function GridOverrideFields({ label, hint, columnsMin, columnsMax, gapMax, value, onChange, }: { label: string; hint: ReactNode; columnsMin: number; columnsMax: number; gapMax: number; value: GridOverride | undefined; /** Receives the whole next override; the caller normalises and stores it. */ onChange: (next: GridOverride) => void; }) { const patch = (key: 'columns' | 'gap', raw: string, min: number, max: number) => { const n = raw === '' ? undefined : Number(raw); onChange({ ...(value || {}), [key]: n != null && n >= min && n <= max ? n : undefined, }); }; return (
{hint}