79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
import type { ComponentType } from 'react';
|
|
import type { ArticlesBlock as ArticlesBlockData, BannerBlock as BannerBlockData, ContentBlock as ContentBlockData, FaqBlock as FaqBlockData, MediaBlock as MediaBlockData, MediaContentBlock as MediaContentBlockData, PageBlock } from '#web-runtime/types';
|
|
import ArticlesBlock from './components/ArticlesBlock';
|
|
import BannerBlock from './components/BannerBlock';
|
|
import ContentBlock from './components/ContentBlock';
|
|
import FaqBlock from './components/FaqBlock';
|
|
import MediaBlock from './components/MediaBlock';
|
|
import MediaContentBlock from './components/MediaContentBlock';
|
|
import UnsupportedBlock from './components/UnsupportedBlock';
|
|
|
|
interface BlockRendererProps {
|
|
block: PageBlock;
|
|
}
|
|
|
|
type BlockRenderer = ComponentType<BlockRendererProps>;
|
|
|
|
function isContentBlock(block: PageBlock): block is ContentBlockData {
|
|
return block.type === 'content' && 'columns' in block;
|
|
}
|
|
|
|
function isFaqBlock(block: PageBlock): block is FaqBlockData {
|
|
return block.type === 'faq' && 'items' in block;
|
|
}
|
|
|
|
function isMediaContentBlock(block: PageBlock): block is MediaContentBlockData {
|
|
return block.type === 'media-content' && 'content' in block;
|
|
}
|
|
|
|
function isArticlesBlock(block: PageBlock): block is ArticlesBlockData {
|
|
return block.type === 'articles' && 'items' in block;
|
|
}
|
|
|
|
function isBannerBlock(block: PageBlock): block is BannerBlockData {
|
|
return block.type === 'banner' && 'style' in block;
|
|
}
|
|
|
|
function isMediaBlock(block: PageBlock): block is MediaBlockData {
|
|
return block.type === 'media' && !('data' in block);
|
|
}
|
|
|
|
const ContentBlockRenderer: BlockRenderer = ({ block }) =>
|
|
isContentBlock(block) ? <ContentBlock block={block} /> : null;
|
|
|
|
const FaqBlockRenderer: BlockRenderer = ({ block }) =>
|
|
isFaqBlock(block) ? <FaqBlock block={block} /> : null;
|
|
|
|
const MediaContentBlockRenderer: BlockRenderer = ({ block }) =>
|
|
isMediaContentBlock(block) ? <MediaContentBlock block={block} /> : null;
|
|
|
|
const ArticlesBlockRenderer: BlockRenderer = ({ block }) =>
|
|
isArticlesBlock(block) ? <ArticlesBlock block={block} /> : null;
|
|
|
|
const BannerBlockRenderer: BlockRenderer = ({ block }) =>
|
|
isBannerBlock(block) ? <BannerBlock block={block} /> : null;
|
|
|
|
const MediaBlockRenderer: BlockRenderer = ({ block }) =>
|
|
isMediaBlock(block) ? <MediaBlock block={block} /> : null;
|
|
|
|
export const PAGE_BLOCK_REGISTRY: Readonly<Record<string, BlockRenderer>> = {
|
|
'content': ContentBlockRenderer,
|
|
'faq': FaqBlockRenderer,
|
|
'media-content': MediaContentBlockRenderer,
|
|
'articles': ArticlesBlockRenderer,
|
|
'banner': BannerBlockRenderer,
|
|
'media': MediaBlockRenderer
|
|
};
|
|
|
|
export function PageBlocks({ blocks }: { blocks: PageBlock[] }) {
|
|
return blocks.map((block) => {
|
|
const Renderer = PAGE_BLOCK_REGISTRY[block.type];
|
|
|
|
return Renderer ? (
|
|
<Renderer key={block.id} block={block} />
|
|
) : (
|
|
<UnsupportedBlock key={block.id} block={block} />
|
|
);
|
|
});
|
|
}
|