39 lines
1.5 KiB
TypeScript
39 lines
1.5 KiB
TypeScript
|
|
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)})`;
|
||
|
|
}
|