Files
moteva/frontend/src/ui/pages/CanvasWorkspace/canvas/frameStyle.ts
T

39 lines
1.5 KiB
TypeScript
Raw Normal View History

import type { CSSProperties } from "react";
import type { CanvasNode } from "@/domain/design";
export const defaultFrameFillColor = "#ffffff";
export const defaultFrameStrokeColor = "#2f80ff";
export const defaultFrameStrokeWidth = 1;
export const defaultFrameStrokeStyle = "solid";
export function framePreviewStyle(node: CanvasNode): CSSProperties {
const opacity = typeof node.opacity === "number" ? node.opacity : 1;
return {
background: colorWithOpacity(node.fillColor || defaultFrameFillColor, opacity),
borderColor: node.strokeColor || defaultFrameStrokeColor,
borderWidth: `${node.strokeWidth || defaultFrameStrokeWidth}px`,
borderStyle: normalizeStrokeStyle(node.strokeStyle)
};
}
export function normalizeStrokeStyle(value: string | undefined) {
if (value === "dashed" || value === "dotted") return value;
return defaultFrameStrokeStyle;
}
export function normalizeHexColor(value: string, fallback: string) {
const trimmed = value.trim();
if (/^#[0-9a-f]{6}$/i.test(trimmed)) return trimmed.toUpperCase();
if (/^[0-9a-f]{6}$/i.test(trimmed)) return `#${trimmed.toUpperCase()}`;
return fallback;
}
function colorWithOpacity(color: string, opacity: number) {
if (color === "transparent") return color;
const normalized = normalizeHexColor(color, defaultFrameFillColor);
const r = Number.parseInt(normalized.slice(1, 3), 16);
const g = Number.parseInt(normalized.slice(3, 5), 16);
const b = Number.parseInt(normalized.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${Math.min(Math.max(opacity, 0), 1)})`;
}