Files
windwiderstand/src/lib/block-layout.ts
T
Peter Meier 2fef91a548
Deploy / verify (push) Failing after 32s
Deploy / deploy (push) Has been skipped
Initial SvelteKit frontend port of windwiderstand.de
Full parity with Astro site: content rows, post/tag routes, pagination,
event badges + OSM map, comments, Live-Search via /api/search-index,
CMS image proxy, RSS, sitemap.

Deploy: Dockerfile + docker-compose.prod.yml + Gitea Actions workflow
to build + push to git.pm86.de registry and ssh-deploy to Contabo.
2026-04-17 22:01:30 +02:00

164 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Layout für Content-Blöcke (z. B. Markdown): Grid-Spalten (112) und Abstand.
* Entspricht component_layout im CMS (desktop/tablet/mobile = Breite in 12tel, spaceBottom = rem).
*/
export type BlockLayout = {
/** Breite auf Desktop (112), z. B. "8" = 8/12. */
desktop?:
| "1"
| "2"
| "3"
| "4"
| "5"
| "6"
| "7"
| "8"
| "9"
| "10"
| "11"
| "12";
/** Breite auf Tablet (112). */
tablet?:
| "1"
| "2"
| "3"
| "4"
| "5"
| "6"
| "7"
| "8"
| "9"
| "10"
| "11"
| "12";
/** Breite auf Mobile (112), Default 12. */
mobile?:
| "1"
| "2"
| "3"
| "4"
| "5"
| "6"
| "7"
| "8"
| "9"
| "10"
| "11"
| "12";
/** Abstand nach unten (rem): 0, 0.5, 1, 1.5, 2. */
spaceBottom?: 0 | 0.5 | 1 | 1.5 | 2;
/** true = Block fullwidth aus dem Grid ausbrechen (viewport-breit). */
breakout?: boolean;
};
const COL_SPAN: Record<string, string> = {
"1": "col-span-1",
"2": "col-span-2",
"3": "col-span-3",
"4": "col-span-4",
"5": "col-span-5",
"6": "col-span-6",
"7": "col-span-7",
"8": "col-span-8",
"9": "col-span-9",
"10": "col-span-10",
"11": "col-span-11",
"12": "col-span-12",
};
const MD_COL_SPAN: Record<string, string> = {
"1": "md:col-span-1",
"2": "md:col-span-2",
"3": "md:col-span-3",
"4": "md:col-span-4",
"5": "md:col-span-5",
"6": "md:col-span-6",
"7": "md:col-span-7",
"8": "md:col-span-8",
"9": "md:col-span-9",
"10": "md:col-span-10",
"11": "md:col-span-11",
"12": "md:col-span-12",
};
const LG_COL_SPAN: Record<string, string> = {
"1": "lg:col-span-1",
"2": "lg:col-span-2",
"3": "lg:col-span-3",
"4": "lg:col-span-4",
"5": "lg:col-span-5",
"6": "lg:col-span-6",
"7": "lg:col-span-7",
"8": "lg:col-span-8",
"9": "lg:col-span-9",
"10": "lg:col-span-10",
"11": "lg:col-span-11",
"12": "lg:col-span-12",
};
const SPACE_BOTTOM: Record<number, string> = {
0: "mb-0",
0.5: "mb-2", // 0.5rem
1: "mb-4", // 1rem
1.5: "mb-6", // 1.5rem
2: "mb-8", // 2rem
};
/**
* Gibt Tailwind-Klassen für das Block-Layout zurück (12-Spalten-Grid + Abstand).
* Parent muss grid grid-cols-12 haben.
*/
/**
* Gibt Tailwind-Klassen für den Block-Inhalt zurück.
* Bei breakout: true nur w-full + Abstand (Spalten/Wrapper kommen von außen).
*/
export function getBlockLayoutClasses(
layout: BlockLayout | undefined | null,
): string {
if (!layout || typeof layout !== "object") {
return "col-span-12 mb-4";
}
const breakout = layout.breakout === true;
const sb =
typeof layout.spaceBottom === "number"
? layout.spaceBottom
: Number(layout.spaceBottom);
const spaceClass = SPACE_BOTTOM[sb as keyof typeof SPACE_BOTTOM] ?? "mb-4";
if (breakout) {
return "w-full";
}
const mobile = String(layout.mobile ?? "12");
const tablet = layout.tablet != null ? String(layout.tablet) : undefined;
const desktop = layout.desktop != null ? String(layout.desktop) : undefined;
const parts: string[] = [
COL_SPAN[mobile] ?? "col-span-12",
tablet ? (MD_COL_SPAN[tablet] ?? "") : "",
desktop ? (LG_COL_SPAN[desktop] ?? "") : "",
spaceClass,
];
return parts.filter(Boolean).join(" ");
}
/** Tailwind-Klasse für spaceBottom (z. B. am Breakout-Wrapper). */
export function getSpaceBottomClass(
layout: BlockLayout | undefined | null,
): string {
if (!layout || typeof layout !== "object") return "mb-4";
const sb =
typeof layout.spaceBottom === "number"
? layout.spaceBottom
: Number(layout.spaceBottom);
return SPACE_BOTTOM[sb as keyof typeof SPACE_BOTTOM] ?? "mb-4";
}
/** Prüft, ob das Layout breakout (fullwidth) haben soll. */
export function isBlockLayoutBreakout(
layout: BlockLayout | undefined | null,
): boolean {
return !!(layout && typeof layout === "object" && layout.breakout === true);
}