web based infinite canvas
at main 58 lines 1.5 kB view raw
1import type { Action } from "../actions"; 2import { createId, ShapeRecord } from "../model"; 3import type { EditorState, ToolId } from "../reactivity"; 4import { getCurrentPage } from "../reactivity"; 5import type { Tool } from "./base"; 6 7export class MarkdownTool implements Tool { 8 readonly id: ToolId = "markdown"; 9 10 onEnter(state: EditorState): EditorState { 11 return state; 12 } 13 14 onExit(state: EditorState): EditorState { 15 return state; 16 } 17 18 onAction(state: EditorState, action: Action): EditorState { 19 switch (action.type) { 20 case "pointer-down": { 21 return this.handlePointerDown(state, action); 22 } 23 default: { 24 return state; 25 } 26 } 27 } 28 29 private handlePointerDown(state: EditorState, action: Action): EditorState { 30 if (action.type !== "pointer-down") return state; 31 32 const currentPage = getCurrentPage(state); 33 if (!currentPage) return state; 34 35 const shapeId = createId("shape"); 36 37 const shape = ShapeRecord.createMarkdown(currentPage.id, action.world.x, action.world.y, { 38 md: "# Markdown\n\nEdit me...", 39 w: 300, 40 h: 200, 41 fontSize: 16, 42 fontFamily: "Inter", 43 color: "#1f2933", 44 }, shapeId); 45 46 const newPage = { ...currentPage, shapeIds: [...currentPage.shapeIds, shapeId] }; 47 48 return { 49 ...state, 50 doc: { 51 ...state.doc, 52 shapes: { ...state.doc.shapes, [shapeId]: shape }, 53 pages: { ...state.doc.pages, [currentPage.id]: newPage }, 54 }, 55 ui: { ...state.ui, selectionIds: [shapeId] }, 56 }; 57 } 58}