feat(canvas): add persistent node favorites with toolbar star and glow

This commit is contained in:
2026-04-09 14:12:43 +02:00
parent e4d39a21fd
commit b08e448be0
18 changed files with 625 additions and 76 deletions

View File

@@ -0,0 +1,54 @@
import { describe, expect, it } from "vitest";
import {
preserveNodeFavorite,
readNodeFavorite,
setNodeFavorite,
} from "@/lib/canvas-node-favorite";
describe("canvas node favorite helpers", () => {
it("reads favorite from object data", () => {
expect(readNodeFavorite({ isFavorite: true })).toBe(true);
});
it("returns false when favorite flag is missing", () => {
expect(readNodeFavorite({})).toBe(false);
});
it("persists favorite when enabled", () => {
expect(setNodeFavorite(true, { label: "Frame" })).toEqual({
label: "Frame",
isFavorite: true,
});
});
it("removes favorite key when disabled", () => {
expect(setNodeFavorite(false, { label: "Frame", isFavorite: true })).toEqual({
label: "Frame",
});
});
it("preserves favorite after strict normalization", () => {
expect(
preserveNodeFavorite(
{
crop: {
x: 0,
y: 0,
width: 1,
height: 1,
},
},
{ isFavorite: true },
),
).toEqual({
crop: {
x: 0,
y: 0,
width: 1,
height: 1,
},
isFavorite: true,
});
});
});

View File

@@ -4,6 +4,7 @@ import {
DEFAULT_CROP_NODE_DATA,
normalizeCropNodeData,
} from "@/lib/image-pipeline/crop-node-data";
import { preserveNodeFavorite } from "@/lib/canvas-node-favorite";
describe("crop node data validation", () => {
it("normalizes and clamps crop rectangle data", () => {
@@ -81,4 +82,24 @@ describe("crop node data validation", () => {
),
).toThrow("Crop node accepts parameter data only. 'imageData' is not allowed in data.");
});
it("preserves favorite after strict crop normalization", () => {
const normalized = normalizeCropNodeData(
{
...DEFAULT_CROP_NODE_DATA,
isFavorite: true,
},
{ rejectDisallowedPayloadFields: true },
);
expect(
preserveNodeFavorite(normalized, {
...DEFAULT_CROP_NODE_DATA,
isFavorite: true,
}),
).toEqual({
...DEFAULT_CROP_NODE_DATA,
isFavorite: true,
});
});
});