Client block registry now carries a renderer, edit form, palette label/icon, and defaults for all seven Wave 1 blocks (self-registering via client/src/blocks/types/*): heading, rich_text, image, two_column, cta, divider, quote. - BlockRenderer + BlockList render stored blocks via the registry (respect `visible`, tolerate unknown types), reading getBlock from ./registry to avoid the index -> twoColumn -> BlockRenderer cycle. - editorKit: shared Field/TextField/TextAreaField/SelectField styled with the existing admin form classes; rich_text editor reuses RichTextEditor (variant post), image editor reuses the shared uploader. - two_column editor is a mini per-column canvas (add from the leaf-only palette, edit via each block's registry editor, reorder, remove). - theme.css: public block styles (heading/image alignment/cta/quote/ two-column responsive grid) + column sub-block editor styles. Verified: all 11 modules transform cleanly under esbuild. Full visual verification comes with the builder UI (step 5) + public route (step 6). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
27 lines
1.3 KiB
JavaScript
27 lines
1.3 KiB
JavaScript
// Renders stored blocks via their registry component. Used by the public page
|
|
// route, the draft preview, and (recursively) the two_column block. Kept
|
|
// separate from the registry so both the renderer and the builder can import it.
|
|
// Import the lookup from the registry directly (not ./index) to avoid a cycle:
|
|
// index → types/twoColumn → BlockRenderer. The page route/builder import ./index,
|
|
// which registers every block before anything renders.
|
|
import { getBlock } from './registry.js'
|
|
|
|
/**
|
|
* Render one block. A block with `visible === false` renders nothing (admins
|
|
* hide blocks without deleting them). An unknown type also renders nothing —
|
|
* server validation prevents storing one, so this only guards a client/server
|
|
* registry skew rather than crashing the whole page.
|
|
*/
|
|
export default function BlockRenderer({ block }) {
|
|
if (!block || block.visible === false) return null
|
|
const def = getBlock(block.type)
|
|
if (!def || !def.component) return null
|
|
const Component = def.component
|
|
return <Component props={block.props || {}} block={block} />
|
|
}
|
|
|
|
/** Render an ordered array of blocks (array position = display order). */
|
|
export function BlockList({ blocks }) {
|
|
return (blocks || []).map((block) => <BlockRenderer key={block.id} block={block} />)
|
|
}
|