Files
windwiderstand/src/lib/components/ContentRows.svelte
T
Peter Meier 8575572183 refactor: consolidate block dispatch into BlockRenderer
ContentRows now delegates to BlockRenderer instead of maintaining its
own parallel if-else chain. Single source of truth for all block types.
Adds internal_component support (ContactFormComponent via /api/contact).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:12:49 +02:00

94 lines
3.2 KiB
Svelte

<script lang="ts">
import BlockRenderer from "./BlockRenderer.svelte";
import { isBlockLayoutBreakout, getSpaceBottomClass } from "$lib/block-layout";
import type { BlockLayout } from "$lib/block-layout";
import type { Translations } from "$lib/translations";
import type { RowContentLayout, ResolvedBlock } from "$lib/block-types";
let { layout, class: className = "", translations = {} }: { layout: RowContentLayout; class?: string; translations?: Translations | null } = $props();
function isResolvedBlock(item: unknown): item is ResolvedBlock {
return typeof item === "object" && item !== null;
}
function blockType(item: ResolvedBlock): string {
return (item._type as string) ?? "unknown";
}
function justifyToClass(j?: string): string {
switch (j) {
case "end": return "justify-end";
case "center": return "justify-center";
case "between": return "justify-between";
case "around": return "justify-around";
case "evenly": return "justify-evenly";
default: return "justify-start";
}
}
function alignToClass(a?: string): string {
switch (a) {
case "end": return "items-end";
case "center": return "items-center";
case "baseline": return "items-baseline";
case "stretch": return "items-stretch";
default: return "items-start";
}
}
const rows = $derived([
{
content: layout.row1Content ?? [],
justify: justifyToClass(layout.row1JustifyContent),
align: alignToClass(layout.row1AlignItems),
},
{
content: layout.row2Content ?? [],
justify: justifyToClass(layout.row2JustifyContent),
align: alignToClass(layout.row2AlignItems),
},
{
content: layout.row3Content ?? [],
justify: justifyToClass(layout.row3JustifyContent),
align: alignToClass(layout.row3AlignItems),
},
]);
</script>
<div class="content mb-6 {className}">
{#each rows as row}
{#if row.content.length > 0}
<div
class="content-row grid grid-cols-12 gap-4 {row.justify} {row.align}"
role="region"
data-cf-type="grid-row"
>
{#each row.content as item}
{#if isResolvedBlock(item)}
{#if isBlockLayoutBreakout((item as { layout?: BlockLayout }).layout)}
{@const type = blockType(item)}
<div class="col-span-12">
<div
class="component-breakout--{type} {getSpaceBottomClass((item as { layout?: BlockLayout }).layout)} w-screen relative left-1/2 -translate-x-1/2 max-w-none {type === 'quote'
? 'bg-wald-50'
: '[background:var(--color-container-breakout)]'}"
>
{#if type === 'deadline_banner'}
<BlockRenderer block={item} {translations} />
{:else}
<div class="container-custom py-8">
<BlockRenderer block={item} {translations} />
</div>
{/if}
</div>
</div>
{:else}
<BlockRenderer block={item} {translations} />
{/if}
{/if}
{/each}
</div>
{/if}
{/each}
</div>