feat: add crop and canvas resize workflows
This commit is contained in:
@@ -18,11 +18,13 @@ import {
|
||||
documentRenameArtboardCommand,
|
||||
documentRenameLayerCommand,
|
||||
documentSetArtboardBoundsCommand,
|
||||
documentResizeArtboardCommand,
|
||||
documentSetArtboardLockedCommand,
|
||||
documentSetArtboardVisibleCommand,
|
||||
documentSetLayerClippingMaskCommand,
|
||||
documentSetLayerLockedCommand,
|
||||
documentSetLayerOpacityCommand,
|
||||
documentSetLayerSourceRectCommand,
|
||||
documentSetLayerVisibleCommand,
|
||||
documentUpdateAssetSourceCommand,
|
||||
documentUngroupLayerCommand,
|
||||
@@ -59,6 +61,32 @@ describe("document commands", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test("crops a raster layer non-destructively and clamps the crop to its asset", () => {
|
||||
const state = documentWithRaster();
|
||||
const next = documentSetLayerSourceRectCommand.execute({ state }, { layerId: "r1", sourceRect: { x: 20, y: 10, w: 200, h: 100 } });
|
||||
expect(next.document.artboards[0]?.layers[0]).toMatchObject({ sourceRect: { x: 20, y: 10, w: 80, h: 40 } });
|
||||
expect(next.document.assets[0]?.intrinsicSize).toEqual({ w: 100, h: 50 });
|
||||
|
||||
const reset = documentSetLayerSourceRectCommand.execute({ state: next }, { layerId: "r1" });
|
||||
expect(reset.document.artboards[0]?.layers[0]).not.toHaveProperty("sourceRect");
|
||||
});
|
||||
|
||||
test("resizes artboard bounds without scaling contents", () => {
|
||||
const state = documentWithRaster();
|
||||
const next = documentResizeArtboardCommand.execute({ state }, { id: "a1", bounds: { x: 5, y: 10, w: 640, h: 480 }, scaleContents: false });
|
||||
expect(next.document.artboards[0]?.bounds).toEqual({ x: 5, y: 10, w: 640, h: 480 });
|
||||
expect(next.document.artboards[0]?.layers[0]?.transform).toEqual(state.document.artboards[0]?.layers[0]?.transform);
|
||||
});
|
||||
|
||||
test("resizes an artboard and scales nested contents including masks", () => {
|
||||
const state = documentWithRaster();
|
||||
const leaf = state.document.artboards[0]!.layers[0]!;
|
||||
state.document.artboards[0]!.layers = [{ ...group("g", "Group"), children: [leaf] }];
|
||||
const next = documentResizeArtboardCommand.execute({ state }, { id: "a1", bounds: { x: 10, y: 20, w: 640, h: 120 }, scaleContents: true });
|
||||
const nested = next.document.artboards[0]?.layers[0];
|
||||
expect(nested?.type === "group" ? nested.children[0]?.transform : undefined).toEqual({ position: { x: 30, y: 30 }, scale: { x: 2, y: 0.5 }, rotation: 0 });
|
||||
});
|
||||
|
||||
test("updates asset sources", () => {
|
||||
const state = documentAddAssetCommand.execute(
|
||||
{ state: createInitialAppState("Test") },
|
||||
@@ -403,6 +431,12 @@ function documentWithLayers(layers: Layer[]) {
|
||||
};
|
||||
}
|
||||
|
||||
function documentWithRaster() {
|
||||
const state = documentWithLayers([{ ...raster("r1", "Raster", "asset-1"), transform: { position: { x: 10, y: 20 }, scale: { x: 1, y: 1 }, rotation: 0 } }]);
|
||||
state.document.assets = [{ id: "asset-1", name: "Raster", mimeType: "image/png", source: "asset://raster", intrinsicSize: { w: 100, h: 50 } }];
|
||||
return state;
|
||||
}
|
||||
|
||||
function group(id: string, name: string) {
|
||||
return {
|
||||
id,
|
||||
|
||||
Reference in New Issue
Block a user