87 lines
2.9 KiB
Markdown
87 lines
2.9 KiB
Markdown
# blocks
|
|
|
|
`RenderBlocks` — generyczny, serwerowy silnik renderowania bloków. Plugin nie
|
|
zna Twoich bloków: iteruje po danych, mapuje `blockType` → komponent przez
|
|
registry (prop), obsługuje zagnieżdżanie i rozszerzenia per-blok. Bloki
|
|
(schemat + komponenty) definiujesz u siebie.
|
|
|
|
## Config
|
|
|
|
Brak opcji w payload.config — bloki definiujesz w swoich kolekcjach
|
|
(pole typu `blocks`). Plugin dostarcza tylko silnik renderujący.
|
|
|
|
## ⚠️ NIE pisz własnego renderera bloków (switch)
|
|
|
|
**Renderer bloków to `RenderBlocks` z pluginu — NIGDY własny `switch`/`if`.**
|
|
Częsty błąd: projekt pisze własny `BlockRenderer` z `switch (block.blockType)`
|
|
i 20 case'ami. To łamie A0 — plugin ma silnik, projekt dostarcza tylko MAPĘ
|
|
komponentów.
|
|
|
|
```tsx
|
|
// ŹLE — własny switch w projekcie (gadatliwy, bez enhanceProps, rośnie liniowo)
|
|
switch (block.blockType) {
|
|
case 'hero': return <Hero {...block} />
|
|
case 'faq': return <FAQ {...block} />
|
|
// ...20 case'ów
|
|
}
|
|
|
|
// DOBRZE — mapa + RenderBlocks (silnik z pluginu)
|
|
const registry = { hero: Hero, faq: FAQ, /* ... */ }
|
|
<RenderBlocks blocks={page.layout} components={registry} />
|
|
```
|
|
|
|
Dlaczego RenderBlocks, nie switch: enhanceProps (anchory nav, itp.), guardy,
|
|
obsługa zagnieżdżeń, spójność między projektami. Switch tego nie ma i rośnie
|
|
z każdym blokiem. Mapa jest płaska i deklaratywna.
|
|
|
|
## Front — RenderBlocks
|
|
|
|
Import z `@intecion/ipal-kit/rsc` (to komponent serwerowy):
|
|
|
|
```tsx
|
|
import { RenderBlocks } from '@intecion/ipal-kit/rsc'
|
|
|
|
// Twój registry: blockType → komponent (komponenty są Twoje)
|
|
import { Hero } from '@/blocks/Hero'
|
|
import { FormBlock } from '@/blocks/FormBlock'
|
|
|
|
const registry = { hero: Hero, formBlock: FormBlock }
|
|
|
|
export default async function Page() {
|
|
const page = await payload.findByID({ collection: 'pages', id })
|
|
return <RenderBlocks blocks={page.layout} components={registry} />
|
|
}
|
|
```
|
|
|
|
- nieznany `blockType` → pomijany (null), nie crashuje
|
|
- każdy blok dostaje `_components` (mapę) — do rekursji zagnieżdżonych bloków
|
|
bez React Context (wymóg RSC)
|
|
|
|
## enhanceProps — logika per-blok bez wiedzy pluginu
|
|
|
|
Gdy blok potrzebuje danych z innych bloków (np. nawigacja zbierająca kotwice
|
|
z sekcji), podaj `enhanceProps`. Plugin go wywołuje, nie znając Twoich bloków:
|
|
|
|
```tsx
|
|
const enhanceProps = ({ block, allBlocks }) => {
|
|
if (block.blockType !== 'sectionNav') return {}
|
|
const sections = allBlocks
|
|
.filter((b) => b.blockType === 'anchoredSection')
|
|
.map((b) => ({ anchor: b.anchor, label: b.navLabel }))
|
|
return { _sections: sections }
|
|
}
|
|
|
|
<RenderBlocks blocks={page.layout} components={registry} enhanceProps={enhanceProps} />
|
|
```
|
|
|
|
## Komponent bloku
|
|
|
|
Każdy komponent dostaje dane bloku jako propsy (plus `_components`, plus to co
|
|
zwróci `enhanceProps`). Spacing/layout należą do Ciebie — silnik nie owija
|
|
bloków żadnym markupem.
|
|
|
|
```tsx
|
|
export function Hero(props) {
|
|
return <section className="py-16">{/* ... */}</section>
|
|
}
|
|
``` |