import type { LayerProps } from "@/lib/studio-types"; export type ShapeKind = "rect" | "circle" | "line" | "arrow"; export type TextAlign = "left" | "center" | "right"; export type TextAnimation = | "none" | "fadeIn" | "slideUp" | "zoomIn" | "typewriter"; export const FONT_FAMILY_OPTIONS = [ { label: "Inter", value: "Inter, sans-serif" }, { label: "Roboto", value: "Roboto, sans-serif" }, { label: "Playfair", value: "Playfair Display, serif" }, { label: "Montserrat", value: "Montserrat, sans-serif" }, { label: "Oswald", value: "Oswald, sans-serif" }, ] as const; export const TEXT_ANIMATION_OPTIONS: { label: string; value: TextAnimation }[] = [ { label: "None", value: "none" }, { label: "Fade In", value: "fadeIn" }, { label: "Slide Up", value: "slideUp" }, { label: "Zoom In", value: "zoomIn" }, { label: "Typewriter", value: "typewriter" }, ]; function asNumber(value: unknown, fallback: number): number { return typeof value === "number" && !Number.isNaN(value) ? value : fallback; } function asString(value: unknown, fallback: string): string { return typeof value === "string" ? value : fallback; } function asBoolean(value: unknown): boolean { return value === true; } export function buildKonvaFontStyle(bold: boolean, italic: boolean): string { if (bold && italic) return "bold italic"; if (bold) return "bold"; if (italic) return "italic"; return "normal"; } export function getTextProps(props: LayerProps) { const bold = asBoolean(props.bold); const italic = asBoolean(props.italic); const alignRaw = props.align; const align: TextAlign = alignRaw === "center" || alignRaw === "right" ? alignRaw : "left"; const animationRaw = props.animation; const animation: TextAnimation = animationRaw === "fadeIn" || animationRaw === "slideUp" || animationRaw === "zoomIn" || animationRaw === "typewriter" ? animationRaw : "none"; return { text: asString(props.text, "Text"), fontSize: asNumber(props.fontSize, 48), fill: asString(props.fill, "#111827"), fontFamily: asString(props.fontFamily, "Inter, sans-serif"), bold, italic, underline: asBoolean(props.underline), align, letterSpacing: asNumber(props.letterSpacing, 0), lineHeight: asNumber(props.lineHeight, 1.2), animation, fontStyle: buildKonvaFontStyle(bold, italic), }; } export function getImageProps(props: LayerProps) { return { src: typeof props.src === "string" && props.src.length > 0 ? props.src : undefined, flipHorizontal: asBoolean(props.flipHorizontal), flipVertical: asBoolean(props.flipVertical), cornerRadius: asNumber(props.cornerRadius, 0), }; } export function getImageSrc(props: LayerProps): string | undefined { return getImageProps(props).src; } export function getShapeProps(props: LayerProps) { const shapeRaw = props.shape; const shape: ShapeKind = shapeRaw === "circle" || shapeRaw === "line" || shapeRaw === "arrow" ? shapeRaw : "rect"; return { shape, fill: asString(props.fill, "#2563EB"), stroke: asString(props.stroke, "#1E3A8A"), strokeWidth: asNumber(props.strokeWidth, 0), cornerRadius: asNumber(props.cornerRadius, 0), }; } export function mergeLayerProps( current: LayerProps, updates: LayerProps ): LayerProps { return { ...current, ...updates }; }