165 lines
4.4 KiB
TypeScript
165 lines
4.4 KiB
TypeScript
import type { CSSProperties } from "react";
|
|
import type { DividerBlockProps } from "@/features/editor/state/editorStore";
|
|
|
|
export interface DividerEscapers {
|
|
escapeAttr: (value: string) => string;
|
|
}
|
|
|
|
export interface DividerExportTokens {
|
|
style: string;
|
|
}
|
|
|
|
export const computeDividerExportTokens = (
|
|
props: DividerBlockProps,
|
|
escapers: DividerEscapers,
|
|
): DividerExportTokens => {
|
|
const { escapeAttr } = escapers;
|
|
|
|
const thickness = props.thickness === "medium" ? "2px" : "1px";
|
|
const colorRaw = typeof props.colorHex === "string" ? props.colorHex.trim() : "";
|
|
const color = colorRaw !== "" ? colorRaw : "#475569";
|
|
const marginY = typeof props.marginYPx === "number" && props.marginYPx > 0 ? props.marginYPx : 16;
|
|
const marginEm = pxToEm(marginY);
|
|
|
|
const widthMode = props.widthMode ?? "full";
|
|
const align = props.align ?? "left";
|
|
|
|
const styleParts: string[] = [];
|
|
styleParts.push("border:0");
|
|
styleParts.push(`border-bottom:${thickness} solid ${escapeAttr(color)}`);
|
|
styleParts.push(`margin:${marginEm} 0`);
|
|
|
|
if (widthMode === "auto") {
|
|
styleParts.push("width:50%");
|
|
} else if (widthMode === "fixed") {
|
|
const widthPx =
|
|
typeof props.widthPx === "number" && props.widthPx > 0 ? props.widthPx : 320;
|
|
styleParts.push(`width:${pxToEm(widthPx)}`);
|
|
}
|
|
|
|
if (widthMode === "auto" || widthMode === "fixed") {
|
|
if (align === "center") {
|
|
styleParts.push("margin-left:auto");
|
|
styleParts.push("margin-right:auto");
|
|
} else if (align === "right") {
|
|
styleParts.push("margin-left:auto");
|
|
styleParts.push("margin-right:0");
|
|
}
|
|
}
|
|
|
|
const style = `${styleParts.join(";")};`;
|
|
|
|
return { style };
|
|
};
|
|
|
|
export interface DividerEditorTokens {
|
|
thicknessClass: string;
|
|
innerWidthClass: string;
|
|
widthPx?: number;
|
|
borderColor: string;
|
|
marginPx: number;
|
|
}
|
|
|
|
export const computeDividerEditorTokens = (props: DividerBlockProps): DividerEditorTokens => {
|
|
const thicknessClass = props.thickness === "medium" ? "border-t-2" : "border-t";
|
|
|
|
const colorRaw = typeof props.colorHex === "string" ? props.colorHex.trim() : "";
|
|
const borderColor = colorRaw !== "" ? colorRaw : "#475569";
|
|
|
|
const widthMode = props.widthMode ?? "full";
|
|
let innerWidthClass = "w-full";
|
|
let widthPx: number | undefined;
|
|
|
|
if (widthMode === "auto") {
|
|
innerWidthClass = "w-1/2";
|
|
} else if (widthMode === "fixed") {
|
|
innerWidthClass = "";
|
|
if (typeof props.widthPx === "number" && props.widthPx > 0) {
|
|
widthPx = props.widthPx;
|
|
} else {
|
|
widthPx = 320;
|
|
}
|
|
}
|
|
|
|
const marginPx =
|
|
typeof props.marginYPx === "number"
|
|
? props.marginYPx
|
|
: props.marginY === "sm"
|
|
? 8
|
|
: props.marginY === "lg"
|
|
? 24
|
|
: 16;
|
|
|
|
return {
|
|
thicknessClass,
|
|
innerWidthClass,
|
|
widthPx,
|
|
borderColor,
|
|
marginPx,
|
|
};
|
|
};
|
|
|
|
export interface DividerPublicTokens {
|
|
alignClass: string;
|
|
thicknessClass: string;
|
|
innerWidthClass: string;
|
|
wrapperMarginEm: string;
|
|
innerStyle: CSSProperties;
|
|
lineStyle: CSSProperties;
|
|
}
|
|
|
|
const pxToEm = (px: number, base = 16) => `${px / base}em`;
|
|
|
|
export const computeDividerPublicTokens = (props: DividerBlockProps): DividerPublicTokens => {
|
|
const alignClass =
|
|
props.align === "center"
|
|
? "items-center"
|
|
: props.align === "right"
|
|
? "items-end"
|
|
: "items-start";
|
|
|
|
const thicknessClass = props.thickness === "medium" ? "h-[2px]" : "h-px";
|
|
|
|
const marginPx =
|
|
typeof props.marginYPx === "number"
|
|
? props.marginYPx
|
|
: props.marginY === "sm"
|
|
? 8
|
|
: props.marginY === "lg"
|
|
? 24
|
|
: 16;
|
|
const wrapperMarginEm = pxToEm(marginPx);
|
|
|
|
const colorRaw = typeof props.colorHex === "string" ? props.colorHex.trim() : "";
|
|
const backgroundColor = colorRaw !== "" ? colorRaw : "#475569";
|
|
|
|
const widthMode = props.widthMode ?? "full";
|
|
const innerStyle: CSSProperties = {};
|
|
let innerWidthClass = "w-full";
|
|
const lineStyle: CSSProperties = {
|
|
backgroundColor,
|
|
};
|
|
|
|
if (widthMode === "auto") {
|
|
innerWidthClass = "w-1/2";
|
|
} else if (widthMode === "fixed") {
|
|
innerWidthClass = "";
|
|
innerStyle.width = "auto";
|
|
|
|
if (typeof props.widthPx === "number" && props.widthPx > 0) {
|
|
lineStyle.width = pxToEm(props.widthPx);
|
|
} else {
|
|
lineStyle.width = pxToEm(320);
|
|
}
|
|
}
|
|
|
|
return {
|
|
alignClass,
|
|
thicknessClass,
|
|
innerWidthClass,
|
|
wrapperMarginEm,
|
|
innerStyle,
|
|
lineStyle,
|
|
};
|
|
};
|