Files

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} />
);
});
}