ERP-node/frontend/components/report/designer/renderers/TextRenderer.tsx

86 lines
2.8 KiB
TypeScript

"use client";
import { useMemo } from "react";
import type { TextRendererProps } from "./types";
const VERTICAL_ALIGN_MAP: Record<string, string> = {
top: "flex-start",
middle: "center",
bottom: "flex-end",
};
interface ConditionalStyleRule {
value: string;
backgroundColor?: string;
fontColor?: string;
}
function resolveConditionalStyles(
component: TextRendererProps["component"],
displayValue: string,
): { backgroundColor?: string; fontColor?: string } {
const rules = component.conditionalStyles as ConditionalStyleRule[] | undefined;
if (!rules || !Array.isArray(rules) || rules.length === 0) {
return {};
}
const normalizedValue = displayValue.trim();
const matched = rules.find((r) => r.value === normalizedValue);
if (!matched) return {};
return {
backgroundColor: matched.backgroundColor,
fontColor: matched.fontColor,
};
}
export function TextRenderer({ component, displayValue }: TextRendererProps) {
const isOverflowHidden =
component.textOverflow === "clip" || component.textOverflow === "ellipsis";
const conditionalOverrides = useMemo(
() => resolveConditionalStyles(component, displayValue),
[component, displayValue],
);
const bgColor = conditionalOverrides.backgroundColor || component.backgroundColor || undefined;
const fgColor = conditionalOverrides.fontColor || component.fontColor || "#000000";
return (
<div
className="h-full w-full"
style={{
display: "flex",
alignItems: VERTICAL_ALIGN_MAP[component.verticalAlign || "top"] || "flex-start",
backgroundColor: bgColor,
border:
(component.borderWidth ?? 0) > 0
? `${component.borderWidth}px solid ${component.borderColor || "#d1d5db"}`
: undefined,
borderRadius: component.borderRadius ? `${component.borderRadius}px` : undefined,
overflow: "hidden",
}}
>
<div
className="w-full"
style={{
fontSize: `${component.fontSize || 12}px`,
fontFamily: component.fontFamily || "Malgun Gothic",
color: fgColor,
fontWeight: component.fontWeight || "normal",
fontStyle: component.fontStyle || "normal",
textAlign: (component.textAlign as "left" | "center" | "right") || "left",
textDecoration: component.textDecoration || "none",
lineHeight: component.lineHeight || 1.4,
letterSpacing: component.letterSpacing ? `${component.letterSpacing}px` : undefined,
whiteSpace: isOverflowHidden ? "nowrap" : "pre-wrap",
overflow: "hidden",
textOverflow: component.textOverflow === "ellipsis" ? "ellipsis" : undefined,
wordBreak: !isOverflowHidden ? "break-word" : undefined,
maxHeight: "100%",
}}
>
{displayValue}
</div>
</div>
);
}