import { useEffect, useRef, useState } from 'react'; import { Input } from '@/components/ui/input'; import { useClient } from 'hooks/useClient'; import { readableError } from '../errors'; import { useAutosave } from '../useAutosave'; import { useFlash } from '../useFlash'; /** * A block's own heading. Optional, and above whatever editor the block has. * * ── Why it is not inside the free text ── * * Typing a heading into the text works for one kind of block and no others. A gallery, a video and a * partner row all want to announce themselves and have nowhere to put the words — so the heading is a * property of the BLOCK rather than of its contents, and every kind gets one. * * That is also why this is announced for every selected block, including the ones with no editor of * their own: `canEditComponent` answers "is there content to type", and a heading is not content. */ export const BlockSettings = ({ pageId, sectionId, block, onSaved, }: { pageId: number; sectionId: number; block: { id: number; title?: string | null }; onSaved: () => void; }) => { const client = useClient(); const clientRef = useRef(client); clientRef.current = client; const [draft, setDraft] = useState(block.title ?? ''); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const [saved, flashSaved] = useFlash(); // Keyed on the id, so re-reading the same block after a save does not throw away what is being typed. useEffect(() => setDraft(block.title ?? ''), [block.id]); const save = async () => { setBusy(true); setError(null); try { // Empty is sent as an empty string, which the API reads as "take the heading off". await clientRef.current.patch( `/fofos-admin/pages/${pageId}/sections/${sectionId}/components/${block.id}`, { title: draft }, ); flashSaved(); onSaved(); } catch (failure) { setError(readableError(failure)); } finally { setBusy(false); } }; useAutosave(draft !== (block.title ?? '') ? draft : null, busy, save); return (
setDraft(event.currentTarget.value)} /> {saved &&

Saved

} {error &&

{error}

}
); };