diff --git a/app/app.ts b/app/app.ts index 187b077..e85fe0b 100644 --- a/app/app.ts +++ b/app/app.ts @@ -1,3 +1,4 @@ +import { documentCommands } from "@commands/document"; import { createCommandRegistry } from "@commands/registry"; import { selectionCommands } from "@commands/selection"; import { viewportCommands } from "@commands/viewport"; @@ -7,7 +8,7 @@ import { createAppStore } from "@editor/store"; export type ImageStudioApp = ReturnType; export function createImageStudioApp(options?: { documentName?: string }) { - const registry = createCommandRegistry([...viewportCommands, ...selectionCommands]); + const registry = createCommandRegistry([...viewportCommands, ...selectionCommands, ...documentCommands]); const store = createAppStore(createInitialAppState(options?.documentName), registry); return { diff --git a/commands/document.test.ts b/commands/document.test.ts new file mode 100644 index 0000000..2da946d --- /dev/null +++ b/commands/document.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, test } from "bun:test"; +import { createInitialAppState } from "@editor/initial-state"; +import { documentAddArtboardCommand } from "./document"; + +describe("document commands", () => { + test("adds transparent artboard", () => { + const next = documentAddArtboardCommand.execute( + { state: createInitialAppState("Test") }, + { id: "a1", name: "Artboard 1", bounds: { x: 0, y: 0, w: 320, h: 240 } }, + ); + + expect(next.document.artboards).toEqual([ + { + id: "a1", + name: "Artboard 1", + bounds: { x: 0, y: 0, w: 320, h: 240 }, + backgroundColor: "transparent", + layers: [], + }, + ]); + }); +}); diff --git a/commands/document.ts b/commands/document.ts new file mode 100644 index 0000000..698cedf --- /dev/null +++ b/commands/document.ts @@ -0,0 +1,34 @@ +import type { Rect } from "@core/geometry"; +import type { ArtboardId } from "@core/id"; +import type { Command } from "./command"; + +export type DocumentAddArtboardPayload = { + id: ArtboardId; + name: string; + bounds: Rect; +}; + +export const documentAddArtboardCommand: Command = { + id: "document.addArtboard", + name: "Add artboard", + execute({ state }, payload) { + return { + ...state, + document: { + ...state.document, + artboards: [ + ...state.document.artboards, + { + id: payload.id, + name: payload.name, + bounds: payload.bounds, + backgroundColor: "transparent", + layers: [], + }, + ], + }, + }; + }, +}; + +export const documentCommands = [documentAddArtboardCommand] satisfies Command[]; diff --git a/commands/index.ts b/commands/index.ts index b3853e5..c105f56 100644 --- a/commands/index.ts +++ b/commands/index.ts @@ -1,4 +1,6 @@ export type { Command, CommandContext } from "./command"; +export { documentAddArtboardCommand, documentCommands } from "./document"; +export type { DocumentAddArtboardPayload } from "./document"; export type { CommandDispatcher, Dispatch } from "./dispatcher"; export type { CommandId, CommandPayloads } from "./payloads"; export { createCommandDispatcher } from "./dispatcher"; diff --git a/commands/payloads.ts b/commands/payloads.ts index abefd3c..4244b13 100644 --- a/commands/payloads.ts +++ b/commands/payloads.ts @@ -1,3 +1,4 @@ +import type { DocumentAddArtboardPayload } from "./document"; import type { SelectionAddLayerPayload, SelectionSetPayload } from "./selection"; import type { ViewportPanPayload, @@ -7,6 +8,7 @@ import type { } from "./viewport"; export type CommandPayloads = { + "document.addArtboard": DocumentAddArtboardPayload; "selection.set": SelectionSetPayload; "selection.clear": void; "selection.addLayer": SelectionAddLayerPayload;