From bf264815a08decf9ee81da3608218dd69cc87d86 Mon Sep 17 00:00:00 2001 From: Jeffrey Go Date: Mon, 3 Aug 2026 16:24:24 +0800 Subject: [PATCH] Add canvas zoom and Spacebar pan (SP-024). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ship viewport camera in react-canvas-designer@1.2.0 (wheel zoom, Space+drag pan) - Keep sticker pinch aligned under zoom/pan; expose getViewport/zoomBy/resetViewport - Demo Zoom −/%/+/Reset on docs /stickpak; update phase-1 and engineering notes Co-authored-by: Cursor --- .cursor/rules/ls-foundry-core.mdc | 2 +- .../src/components/StickPakCanvasSection.tsx | 44 ++- docs/stickpak/engineering-notes.md | 17 + docs/stickpak/phase-1.md | 4 +- packages/react-canvas-designer/README.md | 7 +- packages/react-canvas-designer/package.json | 2 +- .../src/CanvasDesigner.test.tsx | 61 ++++ .../src/CanvasDesigner.tsx | 292 +++++++++++++++++- .../src/canvasViewport.test.ts | 115 +++++++ .../src/canvasViewport.ts | 169 ++++++++++ packages/react-canvas-designer/src/index.ts | 10 + .../src/selectedStickerPinch.test.ts | 21 ++ .../src/selectedStickerPinch.ts | 34 ++ .../src/stagePointer.test.ts | 16 + .../react-canvas-designer/src/stagePointer.ts | 8 +- 15 files changed, 774 insertions(+), 28 deletions(-) create mode 100644 packages/react-canvas-designer/src/canvasViewport.test.ts create mode 100644 packages/react-canvas-designer/src/canvasViewport.ts diff --git a/.cursor/rules/ls-foundry-core.mdc b/.cursor/rules/ls-foundry-core.mdc index 959857d..4e43d4b 100644 --- a/.cursor/rules/ls-foundry-core.mdc +++ b/.cursor/rules/ls-foundry-core.mdc @@ -43,7 +43,7 @@ Also update the pin table below, `docs/stickpak/phase-1.md` version table + inst | Package | Version | |---------|---------| | `@jeffgo10/shared-types` | 1.0.0 | -| `@jeffgo10/react-canvas-designer` | 1.1.1 | +| `@jeffgo10/react-canvas-designer` | 1.2.0 | | `@jeffgo10/canvas-upscaler` | 1.0.0 | Always bump `shared-types` first when changing layout/DPI APIs; keep dependent package pins in sync. diff --git a/apps/docs/src/components/StickPakCanvasSection.tsx b/apps/docs/src/components/StickPakCanvasSection.tsx index f70a4c2..b4e2e10 100644 --- a/apps/docs/src/components/StickPakCanvasSection.tsx +++ b/apps/docs/src/components/StickPakCanvasSection.tsx @@ -53,6 +53,7 @@ function StickPakCanvasSection() { const [isArranging, setIsArranging] = useState(false); const [canUndo, setCanUndo] = useState(false); const [canRedo, setCanRedo] = useState(false); + const [viewportZoom, setViewportZoom] = useState(1); const [selectedCutLineOffset, setSelectedCutLineOffset] = useState(false); const [selectedCutLineOffsetMm, setSelectedCutLineOffsetMm] = useState(5); const [selectedCutLineOffsetFill, setSelectedCutLineOffsetFill] = useState< @@ -503,6 +504,9 @@ function StickPakCanvasSection() { setCanUndo(undoAvailable); setCanRedo(redoAvailable); }} + onViewportChange={({ zoom }) => { + setViewportZoom(zoom); + }} onAutoArrange={({ allPlaced }) => { setDuplicateMessage(""); setOverlapMessage(""); @@ -518,15 +522,45 @@ function StickPakCanvasSection() {

{isInspectMode ? hasSelection - ? "Inspect: sticker selected — blue border and size labels only (no drag, resize, or rotate). Click empty canvas to deselect." - : "Inspect: click a sticker to select it. Click empty canvas to clear selection. Move, resize, rotate, and marquee stay off." + ? "Inspect: sticker selected — blue border and size labels only (no drag, resize, or rotate). Click empty canvas to deselect. Scroll to zoom; hold Space and drag to pan." + : "Inspect: click a sticker to select it. Click empty canvas to clear selection. Move, resize, rotate, and marquee stay off. Scroll to zoom; hold Space and drag to pan." : hasSelection ? selectedIds.length > 1 - ? `${selectedIds.length} stickers selected — duplicate fills the whole selection together. Use the transform box to move, resize, or rotate (hold Shift while rotating to snap to 45°). [ / ] rotate 90°.` - : "Selected sticker — duplicate to fill a row or column. Hold Shift while dragging the rotate handle to snap to 45°. [ / ] rotate 90° left/right." - : "Click a sticker to select it. Shift-click to multi-select, or drag on empty canvas to marquee-select."} + ? `${selectedIds.length} stickers selected — duplicate fills the whole selection together. Use the transform box to move, resize, or rotate (hold Shift while rotating to snap to 45°). [ / ] rotate 90°. Scroll to zoom; Space + drag to pan.` + : "Selected sticker — duplicate to fill a row or column. Hold Shift while dragging the rotate handle to snap to 45°. [ / ] rotate 90° left/right. Scroll to zoom; Space + drag to pan." + : "Click a sticker to select it. Shift-click to multi-select, or drag on empty canvas to marquee-select. Scroll to zoom; hold Space and drag to pan."}

+ + + {Math.round(viewportZoom * 100)}% + + +