164 lines
3.8 KiB
TypeScript
164 lines
3.8 KiB
TypeScript
/**
|
||
* Layout für Content-Blöcke (z. B. Markdown): Grid-Spalten (1–12) und Abstand.
|
||
* Entspricht component_layout im CMS (desktop/tablet/mobile = Breite in 12tel, spaceBottom = rem).
|
||
*/
|
||
|
||
export type BlockLayout = {
|
||
/** Breite auf Desktop (1–12), z. B. "8" = 8/12. */
|
||
desktop?:
|
||
| "1"
|
||
| "2"
|
||
| "3"
|
||
| "4"
|
||
| "5"
|
||
| "6"
|
||
| "7"
|
||
| "8"
|
||
| "9"
|
||
| "10"
|
||
| "11"
|
||
| "12";
|
||
/** Breite auf Tablet (1–12). */
|
||
tablet?:
|
||
| "1"
|
||
| "2"
|
||
| "3"
|
||
| "4"
|
||
| "5"
|
||
| "6"
|
||
| "7"
|
||
| "8"
|
||
| "9"
|
||
| "10"
|
||
| "11"
|
||
| "12";
|
||
/** Breite auf Mobile (1–12), 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);
|
||
}
|