feat(canvas): fix rotation, clarify frame membership and load icons on demand

This commit is contained in:
2026-11-06 13:56:15 +08:00
parent 77d1b3ec86
commit 83021d0f6c
120 changed files with 817 additions and 100 deletions
+18 -7
View File
@@ -4,17 +4,28 @@ import type { CanvasNode } from "./canvas-elements.ts";
import { nodeCenter, nodeSize } from "./canvas-geometry.ts";
/** Membership changes only on content drops, never on frame movement or resize. */
export function containingFrame(node: CanvasNode, nodes: CanvasNode[]) {
if (node.data.kind === "frame") return undefined;
const center = nodeCenter(node);
return nodes.filter((frame) => {
if (frame.data.kind !== "frame") return false;
const { width, height } = nodeSize(frame);
return center.x >= frame.position.x && center.x <= frame.position.x + width && center.y >= frame.position.y && center.y <= frame.position.y + height;
}).sort((a, b) => nodeSize(a).width * nodeSize(a).height - nodeSize(b).width * nodeSize(b).height)[0];
}
export function frameDropFeedback(nodes: CanvasNode[], droppedIds: string[]) {
const ids = new Set(droppedIds);
return nodes.filter((node) => ids.has(node.id) && node.data.kind !== "frame").map((node) => ({
id: node.id, from: node.data.frameId, to: containingFrame(node, nodes)?.id,
}));
}
export function assignFrameMembership(nodes: CanvasNode[], droppedIds: string[]): CanvasNode[] {
const dropped = new Set(droppedIds);
const frames = nodes.filter((node) => node.data.kind === "frame");
return nodes.map((node) => {
if (!dropped.has(node.id) || node.data.kind === "frame") return node;
const center = nodeCenter(node);
const candidates = frames.filter((frame) => {
const { width, height } = nodeSize(frame);
return center.x >= frame.position.x && center.x <= frame.position.x + width && center.y >= frame.position.y && center.y <= frame.position.y + height;
}).sort((a, b) => nodeSize(a).width * nodeSize(a).height - nodeSize(b).width * nodeSize(b).height);
const frameId = candidates[0]?.id;
const frameId = containingFrame(node, nodes)?.id;
if (frameId === node.data.frameId) return node;
const { frameId: _old, ...data } = node.data;
return { ...node, data: { ...data, ...(frameId ? { frameId } : {}) } };