diff --git a/components/canvas/bounds/bounding-box.tsx b/components/canvas/bounds/bounding-box.tsx index e8ab0293e..d488d539c 100644 --- a/components/canvas/bounds/bounding-box.tsx +++ b/components/canvas/bounds/bounding-box.tsx @@ -7,7 +7,6 @@ import CenterHandle from './center-handle' import CornerHandle from './corner-handle' import EdgeHandle from './edge-handle' import RotateHandle from './rotate-handle' -import Selected from '../selected' export default function Bounds() { const isBrushing = useSelector((s) => s.isIn('brushSelecting')) @@ -32,7 +31,6 @@ export default function Bounds() { ${(bounds.minY + bounds.maxY) / 2}) translate(${bounds.minX},${bounds.minY})`} > - diff --git a/components/canvas/canvas.tsx b/components/canvas/canvas.tsx index fd4240927..528a1e9ac 100644 --- a/components/canvas/canvas.tsx +++ b/components/canvas/canvas.tsx @@ -1,5 +1,5 @@ import styled from 'styles' -import state from 'state' +import state, { useSelector } from 'state' import inputs from 'state/inputs' import React, { useCallback, useRef } from 'react' import useZoomEvents from 'hooks/useZoomEvents' @@ -9,6 +9,7 @@ import Page from './page' import Brush from './brush' import Bounds from './bounds/bounding-box' import BoundsBg from './bounds/bounds-bg' +import Selected from './selected' export default function Canvas() { const rCanvas = useRef(null) @@ -17,6 +18,8 @@ export default function Canvas() { useCamera(rGroup) + const isReady = useSelector((s) => s.isIn('ready')) + const handlePointerDown = useCallback((e: React.PointerEvent) => { rCanvas.current.setPointerCapture(e.pointerId) state.send('POINTED_CANVAS', inputs.pointerDown(e, 'canvas')) @@ -40,12 +43,15 @@ export default function Canvas() { onPointerUp={handlePointerUp} > - - - - - - + {isReady && ( + + + + + + + + )} ) } @@ -63,5 +69,3 @@ const MainSVG = styled('svg', { userSelect: 'none', }, }) - -const MainGroup = styled('g', {}) diff --git a/components/canvas/defs.tsx b/components/canvas/defs.tsx index 35df99467..c5cb14392 100644 --- a/components/canvas/defs.tsx +++ b/components/canvas/defs.tsx @@ -1,6 +1,6 @@ -import { getShapeUtils } from "lib/shape-utils" -import { useSelector } from "state" -import { deepCompareArrays, getPage } from "utils/utils" +import { getShapeUtils } from 'lib/shape-utils' +import { useSelector } from 'state' +import { deepCompareArrays, getPage } from 'utils/utils' export default function Defs() { const currentPageShapeIds = useSelector(({ data }) => { @@ -20,6 +20,6 @@ export default function Defs() { export function Def({ id }: { id: string }) { const shape = useSelector(({ data }) => getPage(data).shapes[id]) - + if (!shape) return null return getShapeUtils(shape).render(shape) } diff --git a/components/canvas/selected.tsx b/components/canvas/selected.tsx index 4d5570c79..fb232d275 100644 --- a/components/canvas/selected.tsx +++ b/components/canvas/selected.tsx @@ -1,48 +1,48 @@ import styled from 'styles' import { useSelector } from 'state' -import { - deepCompareArrays, - getBoundsCenter, - getPage, - getSelectedShapes, -} from 'utils/utils' -import * as vec from 'utils/vec' +import { deepCompareArrays, getPage } from 'utils/utils' import { getShapeUtils } from 'lib/shape-utils' -import { Bounds } from 'types' import useShapeEvents from 'hooks/useShapeEvents' import { useRef } from 'react' -export default function Selected({ bounds }: { bounds: Bounds }) { +export default function Selected() { const currentPageShapeIds = useSelector(({ data }) => { return Array.from(data.selectedIds.values()) }, deepCompareArrays) + const isSelecting = useSelector((s) => s.isIn('selecting')) + + if (!isSelecting) return null + return ( {currentPageShapeIds.map((id) => ( - + ))} ) } -export function ShapeOutline({ id, bounds }: { id: string; bounds: Bounds }) { +export function ShapeOutline({ id }: { id: string }) { const rIndicator = useRef(null) const shape = useSelector(({ data }) => getPage(data).shapes[id]) - const shapeBounds = getShapeUtils(shape).getBounds(shape) - const events = useShapeEvents(id, rIndicator) + if (!shape) return null + + const transform = ` + rotate(${shape.rotation * (180 / Math.PI)}, + ${getShapeUtils(shape).getCenter(shape)}) + translate(${shape.point})` + return ( ) diff --git a/components/canvas/shape.tsx b/components/canvas/shape.tsx index 4d553c9f9..5c1096d49 100644 --- a/components/canvas/shape.tsx +++ b/components/canvas/shape.tsx @@ -1,10 +1,10 @@ -import React, { useCallback, useRef, memo } from 'react' -import state, { useSelector } from 'state' -import inputs from 'state/inputs' +import React, { useRef, memo } from 'react' +import { useSelector } from 'state' import styled from 'styles' import { getShapeUtils } from 'lib/shape-utils' import { getPage } from 'utils/utils' import { ShapeStyles } from 'types' +import useShapeEvents from 'hooks/useShapeEvents' function Shape({ id, isSelecting }: { id: string; isSelecting: boolean }) { const isHovered = useSelector((state) => state.data.hoveredId === id) @@ -15,42 +15,7 @@ function Shape({ id, isSelecting }: { id: string; isSelecting: boolean }) { const rGroup = useRef(null) - const handlePointerDown = useCallback( - (e: React.PointerEvent) => { - e.stopPropagation() - rGroup.current.setPointerCapture(e.pointerId) - state.send('POINTED_SHAPE', inputs.pointerDown(e, id)) - }, - [id] - ) - - const handlePointerUp = useCallback( - (e: React.PointerEvent) => { - e.stopPropagation() - rGroup.current.releasePointerCapture(e.pointerId) - state.send('STOPPED_POINTING', inputs.pointerUp(e)) - }, - [id] - ) - - const handlePointerEnter = useCallback( - (e: React.PointerEvent) => { - state.send('HOVERED_SHAPE', inputs.pointerEnter(e, id)) - }, - [id, shape] - ) - - const handlePointerMove = useCallback( - (e: React.PointerEvent) => { - state.send('MOVED_OVER_SHAPE', inputs.pointerEnter(e, id)) - }, - [id, shape] - ) - - const handlePointerLeave = useCallback( - () => state.send('UNHOVERED_SHAPE', { target: id }), - [id] - ) + const events = useShapeEvents(id, rGroup) // This is a problem with deleted shapes. The hooks in this component // may sometimes run before the hook in the Page component, which means @@ -58,19 +23,18 @@ function Shape({ id, isSelecting }: { id: string; isSelecting: boolean }) { // detects the change and pulls this component. if (!shape) return null + const transform = ` + rotate(${shape.rotation * (180 / Math.PI)}, + ${getShapeUtils(shape).getCenter(shape)}) + translate(${shape.point})` + return ( {isSelecting && } diff --git a/hooks/useZoomEvents.ts b/hooks/useZoomEvents.ts index f93871f51..2032b9ad3 100644 --- a/hooks/useZoomEvents.ts +++ b/hooks/useZoomEvents.ts @@ -1,8 +1,8 @@ -import React, { useEffect, useRef } from "react" -import state from "state" -import inputs from "state/inputs" -import * as vec from "utils/vec" -import { usePinch } from "react-use-gesture" +import React, { useEffect, useRef } from 'react' +import state from 'state' +import inputs from 'state/inputs' +import * as vec from 'utils/vec' +import { usePinch } from 'react-use-gesture' /** * Capture zoom gestures (pinches, wheels and pans) and send to the state. @@ -21,16 +21,17 @@ export default function useZoomEvents( function handleWheel(e: WheelEvent) { e.preventDefault() + e.stopPropagation() if (e.ctrlKey) { - state.send("ZOOMED_CAMERA", { + state.send('ZOOMED_CAMERA', { delta: e.deltaY, ...inputs.wheel(e), }) return } - state.send("PANNED_CAMERA", { + state.send('PANNED_CAMERA', { delta: [e.deltaX, e.deltaY], ...inputs.wheel(e), }) @@ -38,6 +39,7 @@ export default function useZoomEvents( function handleTouchMove(e: TouchEvent) { e.preventDefault() + e.stopPropagation() if (e.touches.length === 2) { const { clientX: x0, clientY: y0 } = e.touches[0] @@ -46,7 +48,7 @@ export default function useZoomEvents( const dist = vec.dist([x0, y0], [x1, y1]) const point = vec.med([x0, y0], [x1, y1]) - state.send("WHEELED", { + state.send('WHEELED', { delta: dist - rTouchDist.current, point, }) @@ -55,38 +57,37 @@ export default function useZoomEvents( } } - element.addEventListener("wheel", handleWheel) - element.addEventListener("touchstart", handleTouchMove) - element.addEventListener("touchmove", handleTouchMove) + element.addEventListener('wheel', handleWheel, { passive: false }) + element.addEventListener('touchstart', handleTouchMove, { passive: false }) + element.addEventListener('touchmove', handleTouchMove, { passive: false }) return () => { - element.removeEventListener("wheel", handleWheel) - element.removeEventListener("touchstart", handleTouchMove) - element.removeEventListener("touchmove", handleTouchMove) + element.removeEventListener('wheel', handleWheel) + element.removeEventListener('touchstart', handleTouchMove) + element.removeEventListener('touchmove', handleTouchMove) } }, [ref]) const rPinchDa = useRef(undefined) - const rPinchAngle = useRef(undefined) const rPinchPoint = useRef(undefined) const bind = usePinch(({ pinching, da, origin }) => { if (!pinching) { - state.send("STOPPED_PINCHING") + state.send('STOPPED_PINCHING') rPinchDa.current = undefined rPinchPoint.current = undefined return } if (rPinchPoint.current === undefined) { - state.send("STARTED_PINCHING") + state.send('STARTED_PINCHING') rPinchDa.current = da rPinchPoint.current = origin } const [distanceDelta, angleDelta] = vec.sub(rPinchDa.current, da) - state.send("PINCHED", { + state.send('PINCHED', { delta: vec.sub(rPinchPoint.current, origin), point: origin, distanceDelta, diff --git a/lib/shape-utils/draw.tsx b/lib/shape-utils/draw.tsx index 60f74a3d7..10df69ea5 100644 --- a/lib/shape-utils/draw.tsx +++ b/lib/shape-utils/draw.tsx @@ -7,11 +7,10 @@ import { boundsContainPolygon } from 'utils/bounds' import getStroke from 'perfect-freehand' import { getBoundsFromPoints, + getRotatedCorners, getSvgPathFromStroke, translateBounds, } from 'utils/utils' -import { DotCircle } from 'components/canvas/misc' -import { shades } from 'lib/colors' const pathCache = new WeakMap([]) @@ -43,12 +42,17 @@ const draw = registerShapeUtils({ render(shape) { const { id, point, points } = shape - if (points.length < 2) { - return - } - if (!pathCache.has(points)) { - pathCache.set(points, getSvgPathFromStroke(getStroke(points))) + if (points.length < 2) { + const left = vec.add(point, [6, 0]) + let d: number[][] = [] + for (let i = 0; i < 10; i++) { + d.push(vec.rotWith(left, point, i * ((Math.PI * 2) / 8))) + } + pathCache.set(points, getSvgPathFromStroke(d)) + } else { + pathCache.set(points, getSvgPathFromStroke(getStroke(points))) + } } return @@ -69,11 +73,13 @@ const draw = registerShapeUtils({ }, getRotatedBounds(shape) { - return this.getBounds(shape) + return getBoundsFromPoints( + getRotatedCorners(this.getBounds(shape), shape.rotation) + ) }, getCenter(shape) { - const bounds = this.getBounds(shape) + const bounds = this.getRotatedBounds(shape) return [bounds.minX + bounds.width / 2, bounds.minY + bounds.height / 2] }, @@ -114,6 +120,10 @@ const draw = registerShapeUtils({ rotateTo(shape, rotation) { shape.rotation = rotation + // console.log(shape.points.map(([x, y]) => [x, y])) + // const bounds = this.getBounds(shape) + // const center = [bounds.width / 2, bounds.height / 2] + // shape.points = shape.points.map((pt) => vec.rotWith(pt, center, rotation)) return this }, diff --git a/package.json b/package.json index c5c31558d..ddcc1944a 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "framer-motion": "^4.1.16", "ismobilejs": "^1.1.1", "next": "10.2.0", - "perfect-freehand": "^0.4.71", + "perfect-freehand": "^0.4.8", "prettier": "^2.3.0", "react": "17.0.2", "react-dom": "17.0.2", diff --git a/state/sessions/rotate-session.ts b/state/sessions/rotate-session.ts index 77b3a2ca9..f576c88e0 100644 --- a/state/sessions/rotate-session.ts +++ b/state/sessions/rotate-session.ts @@ -1,8 +1,8 @@ -import { Data } from "types" -import * as vec from "utils/vec" -import BaseSession from "./base-session" -import commands from "state/commands" -import { current } from "immer" +import { Data } from 'types' +import * as vec from 'utils/vec' +import BaseSession from './base-session' +import commands from 'state/commands' +import { current } from 'immer' import { clampToRotationToSegments, getBoundsCenter, @@ -10,8 +10,8 @@ import { getPage, getSelectedShapes, getShapeBounds, -} from "utils/utils" -import { getShapeUtils } from "lib/shape-utils" +} from 'utils/utils' +import { getShapeUtils } from 'lib/shape-utils' const PI2 = Math.PI * 2 diff --git a/state/state.ts b/state/state.ts index ec88ee2f0..f35028ab1 100644 --- a/state/state.ts +++ b/state/state.ts @@ -1,13 +1,13 @@ -import { createSelectorHook, createState } from "@state-designer/react" -import * as vec from "utils/vec" -import inputs from "./inputs" -import { defaultDocument } from "./data" -import { shades } from "lib/colors" -import { createShape, getShapeUtils } from "lib/shape-utils" -import history from "state/history" -import * as Sessions from "./sessions" -import commands from "./commands" -import { updateFromCode } from "lib/code/generate" +import { createSelectorHook, createState } from '@state-designer/react' +import * as vec from 'utils/vec' +import inputs from './inputs' +import { defaultDocument } from './data' +import { shades } from 'lib/colors' +import { createShape, getShapeUtils } from 'lib/shape-utils' +import history from 'state/history' +import * as Sessions from './sessions' +import commands from './commands' +import { updateFromCode } from 'lib/code/generate' import { clamp, getChildren, @@ -18,7 +18,7 @@ import { getShape, screenToWorld, setZoomCSS, -} from "utils/utils" +} from 'utils/utils' import { Data, PointerInfo, @@ -32,7 +32,7 @@ import { DistributeType, AlignType, StretchType, -} from "types" +} from 'types' const initialData: Data = { isReadOnly: false, @@ -55,8 +55,8 @@ const initialData: Data = { pointedId: null, hoveredId: null, selectedIds: new Set([]), - currentPageId: "page0", - currentCodeFileId: "file0", + currentPageId: 'page0', + currentCodeFileId: 'file0', codeControls: {}, document: defaultDocument, } @@ -65,109 +65,116 @@ const state = createState({ data: initialData, on: { ZOOMED_CAMERA: { - do: "zoomCamera", + do: 'zoomCamera', }, PANNED_CAMERA: { - do: "panCamera", + do: 'panCamera', }, - SELECTED_SELECT_TOOL: { to: "selecting" }, - SELECTED_DRAW_TOOL: { unless: "isReadOnly", to: "draw" }, - SELECTED_DOT_TOOL: { unless: "isReadOnly", to: "dot" }, - SELECTED_CIRCLE_TOOL: { unless: "isReadOnly", to: "circle" }, - SELECTED_ELLIPSE_TOOL: { unless: "isReadOnly", to: "ellipse" }, - SELECTED_RAY_TOOL: { unless: "isReadOnly", to: "ray" }, - SELECTED_LINE_TOOL: { unless: "isReadOnly", to: "line" }, - SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" }, - SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" }, - TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel", - TOGGLED_STYLE_PANEL_OPEN: "toggleStylePanel", - CHANGED_STYLE: ["updateStyles", "applyStylesToSelection"], - RESET_CAMERA: "resetCamera", - ZOOMED_TO_FIT: "zoomCameraToFit", + SELECTED_SELECT_TOOL: { to: 'selecting' }, + SELECTED_DRAW_TOOL: { unless: 'isReadOnly', to: 'draw' }, + SELECTED_DOT_TOOL: { unless: 'isReadOnly', to: 'dot' }, + SELECTED_CIRCLE_TOOL: { unless: 'isReadOnly', to: 'circle' }, + SELECTED_ELLIPSE_TOOL: { unless: 'isReadOnly', to: 'ellipse' }, + SELECTED_RAY_TOOL: { unless: 'isReadOnly', to: 'ray' }, + SELECTED_LINE_TOOL: { unless: 'isReadOnly', to: 'line' }, + SELECTED_POLYLINE_TOOL: { unless: 'isReadOnly', to: 'polyline' }, + SELECTED_RECTANGLE_TOOL: { unless: 'isReadOnly', to: 'rectangle' }, + TOGGLED_CODE_PANEL_OPEN: 'toggleCodePanel', + TOGGLED_STYLE_PANEL_OPEN: 'toggleStylePanel', + CHANGED_STYLE: ['updateStyles', 'applyStylesToSelection'], + RESET_CAMERA: 'resetCamera', + ZOOMED_TO_FIT: 'zoomCameraToFit', ZOOMED_TO_SELECTION: { - if: "hasSelection", - do: "zoomCameraToSelection", + if: 'hasSelection', + do: 'zoomCameraToSelection', }, ZOOMED_TO_ACTUAL: { - if: "hasSelection", - do: "zoomCameraToSelectionActual", - else: "zoomCameraToActual", + if: 'hasSelection', + do: 'zoomCameraToSelectionActual', + else: 'zoomCameraToActual', }, - SELECTED_ALL: { to: "selecting", do: "selectAll" }, + SELECTED_ALL: { to: 'selecting', do: 'selectAll' }, }, - initial: "loading", + initial: 'loading', states: { loading: { on: { - MOUNTED: { - do: ["restoreSavedData", "zoomCameraToFit"], - to: "ready", - }, + MOUNTED: [ + 'restoreSavedData', + { + if: 'hasSelection', + do: 'zoomCameraToSelectionActual', + else: ['zoomCameraToFit', 'zoomCameraToActual'], + }, + { + to: 'ready', + }, + ], }, }, ready: { on: { UNMOUNTED: [ - { unless: "isReadOnly", do: "forceSave" }, - { to: "loading" }, + { unless: 'isReadOnly', do: 'forceSave' }, + { to: 'loading' }, ], }, - initial: "selecting", + initial: 'selecting', states: { selecting: { on: { - SAVED: "forceSave", - UNDO: { do: "undo" }, - REDO: { do: "redo" }, - CANCELLED: { do: "clearSelectedIds" }, - DELETED: { do: "deleteSelectedIds" }, - SAVED_CODE: "saveCode", - GENERATED_FROM_CODE: ["setCodeControls", "setGeneratedShapes"], - INCREASED_CODE_FONT_SIZE: "increaseCodeFontSize", - DECREASED_CODE_FONT_SIZE: "decreaseCodeFontSize", - CHANGED_CODE_CONTROL: "updateControls", - ALIGNED: "alignSelection", - STRETCHED: "stretchSelection", - DISTRIBUTED: "distributeSelection", - MOVED: "moveSelection", - STARTED_PINCHING: { to: "pinching" }, + SAVED: 'forceSave', + UNDO: { do: 'undo' }, + REDO: { do: 'redo' }, + CANCELLED: { do: 'clearSelectedIds' }, + DELETED: { do: 'deleteSelectedIds' }, + SAVED_CODE: 'saveCode', + GENERATED_FROM_CODE: ['setCodeControls', 'setGeneratedShapes'], + INCREASED_CODE_FONT_SIZE: 'increaseCodeFontSize', + DECREASED_CODE_FONT_SIZE: 'decreaseCodeFontSize', + CHANGED_CODE_CONTROL: 'updateControls', + ALIGNED: 'alignSelection', + STRETCHED: 'stretchSelection', + DISTRIBUTED: 'distributeSelection', + MOVED: 'moveSelection', + STARTED_PINCHING: { to: 'pinching' }, }, - initial: "notPointing", + initial: 'notPointing', states: { notPointing: { on: { - POINTED_CANVAS: { to: "brushSelecting" }, - POINTED_BOUNDS: { to: "pointingBounds" }, + POINTED_CANVAS: { to: 'brushSelecting' }, + POINTED_BOUNDS: { to: 'pointingBounds' }, POINTED_BOUNDS_HANDLE: { - if: "isPointingRotationHandle", - to: "rotatingSelection", - else: { to: "transformingSelection" }, + if: 'isPointingRotationHandle', + to: 'rotatingSelection', + else: { to: 'transformingSelection' }, }, MOVED_OVER_SHAPE: { - if: "pointHitsShape", + if: 'pointHitsShape', then: { - unless: "shapeIsHovered", - do: "setHoveredId", + unless: 'shapeIsHovered', + do: 'setHoveredId', }, - else: { if: "shapeIsHovered", do: "clearHoveredId" }, + else: { if: 'shapeIsHovered', do: 'clearHoveredId' }, }, - UNHOVERED_SHAPE: "clearHoveredId", + UNHOVERED_SHAPE: 'clearHoveredId', POINTED_SHAPE: [ { - if: "isPressingMetaKey", - to: "brushSelecting", + if: 'isPressingMetaKey', + to: 'brushSelecting', }, - "setPointedId", + 'setPointedId', { - unless: "isPointedShapeSelected", + unless: 'isPointedShapeSelected', then: { - if: "isPressingShiftKey", - do: ["pushPointedIdToSelectedIds", "clearPointedId"], - else: ["clearSelectedIds", "pushPointedIdToSelectedIds"], + if: 'isPressingShiftKey', + do: ['pushPointedIdToSelectedIds', 'clearPointedId'], + else: ['clearSelectedIds', 'pushPointedIdToSelectedIds'], }, }, { - to: "pointingBounds", + to: 'pointingBounds', }, ], }, @@ -176,151 +183,153 @@ const state = createState({ on: { STOPPED_POINTING: [ { - if: "isPressingShiftKey", + if: 'isPressingShiftKey', then: { - if: "isPointedShapeSelected", - do: "pullPointedIdFromSelectedIds", + if: 'isPointedShapeSelected', + do: 'pullPointedIdFromSelectedIds', }, else: { - unless: "isPointingBounds", - do: ["clearSelectedIds", "pushPointedIdToSelectedIds"], + unless: 'isPointingBounds', + do: ['clearSelectedIds', 'pushPointedIdToSelectedIds'], }, }, - { to: "notPointing" }, + { to: 'notPointing' }, ], MOVED_POINTER: { - unless: "isReadOnly", - if: "distanceImpliesDrag", - to: "draggingSelection", + unless: 'isReadOnly', + if: 'distanceImpliesDrag', + to: 'draggingSelection', }, }, }, rotatingSelection: { - onEnter: "startRotateSession", - onExit: "clearBoundsRotation", + onEnter: 'startRotateSession', + onExit: 'clearBoundsRotation', on: { - MOVED_POINTER: "updateRotateSession", - PANNED_CAMERA: "updateRotateSession", - PRESSED_SHIFT_KEY: "keyUpdateRotateSession", - RELEASED_SHIFT_KEY: "keyUpdateRotateSession", - STOPPED_POINTING: { do: "completeSession", to: "selecting" }, - CANCELLED: { do: "cancelSession", to: "selecting" }, + MOVED_POINTER: 'updateRotateSession', + PANNED_CAMERA: 'updateRotateSession', + PRESSED_SHIFT_KEY: 'keyUpdateRotateSession', + RELEASED_SHIFT_KEY: 'keyUpdateRotateSession', + STOPPED_POINTING: { do: 'completeSession', to: 'selecting' }, + CANCELLED: { do: 'cancelSession', to: 'selecting' }, }, }, transformingSelection: { - onEnter: "startTransformSession", + onEnter: 'startTransformSession', on: { - MOVED_POINTER: "updateTransformSession", - PANNED_CAMERA: "updateTransformSession", - PRESSED_SHIFT_KEY: "keyUpdateTransformSession", - RELEASED_SHIFT_KEY: "keyUpdateTransformSession", - STOPPED_POINTING: { do: "completeSession", to: "selecting" }, - CANCELLED: { do: "cancelSession", to: "selecting" }, + MOVED_POINTER: 'updateTransformSession', + PANNED_CAMERA: 'updateTransformSession', + PRESSED_SHIFT_KEY: 'keyUpdateTransformSession', + RELEASED_SHIFT_KEY: 'keyUpdateTransformSession', + STOPPED_POINTING: { do: 'completeSession', to: 'selecting' }, + CANCELLED: { do: 'cancelSession', to: 'selecting' }, }, }, draggingSelection: { - onEnter: "startTranslateSession", + onEnter: 'startTranslateSession', on: { - MOVED_POINTER: "updateTranslateSession", - PANNED_CAMERA: "updateTranslateSession", - PRESSED_SHIFT_KEY: "keyUpdateTranslateSession", - RELEASED_SHIFT_KEY: "keyUpdateTranslateSession", - PRESSED_ALT_KEY: "keyUpdateTranslateSession", - RELEASED_ALT_KEY: "keyUpdateTranslateSession", - STOPPED_POINTING: { do: "completeSession", to: "selecting" }, - CANCELLED: { do: "cancelSession", to: "selecting" }, + MOVED_POINTER: 'updateTranslateSession', + PANNED_CAMERA: 'updateTranslateSession', + PRESSED_SHIFT_KEY: 'keyUpdateTranslateSession', + RELEASED_SHIFT_KEY: 'keyUpdateTranslateSession', + PRESSED_ALT_KEY: 'keyUpdateTranslateSession', + RELEASED_ALT_KEY: 'keyUpdateTranslateSession', + STOPPED_POINTING: { do: 'completeSession', to: 'selecting' }, + CANCELLED: { do: 'cancelSession', to: 'selecting' }, }, }, brushSelecting: { onEnter: [ { - unless: ["isPressingMetaKey", "isPressingShiftKey"], - do: "clearSelectedIds", + unless: ['isPressingMetaKey', 'isPressingShiftKey'], + do: 'clearSelectedIds', }, - "clearBoundsRotation", - "startBrushSession", + 'clearBoundsRotation', + 'startBrushSession', ], on: { - MOVED_POINTER: "updateBrushSession", - PANNED_CAMERA: "updateBrushSession", - STOPPED_POINTING: { do: "completeSession", to: "selecting" }, - CANCELLED: { do: "cancelSession", to: "selecting" }, + MOVED_POINTER: 'updateBrushSession', + PANNED_CAMERA: 'updateBrushSession', + STOPPED_POINTING: { do: 'completeSession', to: 'selecting' }, + CANCELLED: { do: 'cancelSession', to: 'selecting' }, }, }, }, }, pinching: { on: { - STOPPED_PINCHING: { to: "selecting" }, - PINCHED: { do: "pinchCamera" }, + STOPPED_PINCHING: { to: 'selecting' }, + PINCHED: { do: 'pinchCamera' }, }, }, draw: { - initial: "creating", + initial: 'creating', states: { creating: { on: { + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - get: "newDraw", - do: "createShape", - to: "draw.editing", + get: 'newDraw', + do: 'createShape', + to: 'draw.editing', }, - UNDO: { do: "undo" }, - REDO: { do: "redo" }, + UNDO: { do: 'undo' }, + REDO: { do: 'redo' }, }, }, editing: { - onEnter: "startDrawSession", + onEnter: 'startDrawSession', on: { STOPPED_POINTING: { - do: "completeSession", - to: "draw.creating", + do: 'completeSession', + to: 'draw.creating', }, CANCELLED: { - do: ["cancelSession", "deleteSelectedIds"], - to: "selecting", + do: ['cancelSession', 'deleteSelectedIds'], + to: 'selecting', }, - MOVED_POINTER: "updateDrawSession", - PANNED_CAMERA: "updateDrawSession", + MOVED_POINTER: 'updateDrawSession', + PANNED_CAMERA: 'updateDrawSession', }, }, }, }, dot: { - initial: "creating", + initial: 'creating', states: { creating: { on: { + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - get: "newDot", - do: "createShape", - to: "dot.editing", + get: 'newDot', + do: 'createShape', + to: 'dot.editing', }, }, }, editing: { on: { - STOPPED_POINTING: { do: "completeSession", to: "selecting" }, + STOPPED_POINTING: { do: 'completeSession', to: 'selecting' }, CANCELLED: { - do: ["cancelSession", "deleteSelectedIds"], - to: "selecting", + do: ['cancelSession', 'deleteSelectedIds'], + to: 'selecting', }, }, - initial: "inactive", + initial: 'inactive', states: { inactive: { on: { MOVED_POINTER: { - if: "distanceImpliesDrag", - to: "dot.editing.active", + if: 'distanceImpliesDrag', + to: 'dot.editing.active', }, }, }, active: { - onEnter: "startTranslateSession", + onEnter: 'startTranslateSession', on: { - MOVED_POINTER: "updateTranslateSession", - PANNED_CAMERA: "updateTranslateSession", + MOVED_POINTER: 'updateTranslateSession', + PANNED_CAMERA: 'updateTranslateSession', }, }, }, @@ -328,25 +337,26 @@ const state = createState({ }, }, circle: { - initial: "creating", + initial: 'creating', states: { creating: { on: { + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - to: "circle.editing", + to: 'circle.editing', }, }, }, editing: { on: { - STOPPED_POINTING: { to: "selecting" }, - CANCELLED: { to: "selecting" }, + STOPPED_POINTING: { to: 'selecting' }, + CANCELLED: { to: 'selecting' }, MOVED_POINTER: { - if: "distanceImpliesDrag", + if: 'distanceImpliesDrag', then: { - get: "newCircle", - do: "createShape", - to: "drawingShape.bounds", + get: 'newCircle', + do: 'createShape', + to: 'drawingShape.bounds', }, }, }, @@ -354,26 +364,26 @@ const state = createState({ }, }, ellipse: { - initial: "creating", + initial: 'creating', states: { creating: { on: { - CANCELLED: { to: "selecting" }, + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - to: "ellipse.editing", + to: 'ellipse.editing', }, }, }, editing: { on: { - STOPPED_POINTING: { to: "selecting" }, - CANCELLED: { to: "selecting" }, + STOPPED_POINTING: { to: 'selecting' }, + CANCELLED: { to: 'selecting' }, MOVED_POINTER: { - if: "distanceImpliesDrag", + if: 'distanceImpliesDrag', then: { - get: "newEllipse", - do: "createShape", - to: "drawingShape.bounds", + get: 'newEllipse', + do: 'createShape', + to: 'drawingShape.bounds', }, }, }, @@ -381,26 +391,26 @@ const state = createState({ }, }, rectangle: { - initial: "creating", + initial: 'creating', states: { creating: { on: { - CANCELLED: { to: "selecting" }, + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - to: "rectangle.editing", + to: 'rectangle.editing', }, }, }, editing: { on: { - STOPPED_POINTING: { to: "selecting" }, - CANCELLED: { to: "selecting" }, + STOPPED_POINTING: { to: 'selecting' }, + CANCELLED: { to: 'selecting' }, MOVED_POINTER: { - if: "distanceImpliesDrag", + if: 'distanceImpliesDrag', then: { - get: "newRectangle", - do: "createShape", - to: "drawingShape.bounds", + get: 'newRectangle', + do: 'createShape', + to: 'drawingShape.bounds', }, }, }, @@ -408,50 +418,50 @@ const state = createState({ }, }, ray: { - initial: "creating", + initial: 'creating', states: { creating: { on: { - CANCELLED: { to: "selecting" }, + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - get: "newRay", - do: "createShape", - to: "ray.editing", + get: 'newRay', + do: 'createShape', + to: 'ray.editing', }, }, }, editing: { on: { - STOPPED_POINTING: { to: "selecting" }, - CANCELLED: { to: "selecting" }, + STOPPED_POINTING: { to: 'selecting' }, + CANCELLED: { to: 'selecting' }, MOVED_POINTER: { - if: "distanceImpliesDrag", - to: "drawingShape.direction", + if: 'distanceImpliesDrag', + to: 'drawingShape.direction', }, }, }, }, }, line: { - initial: "creating", + initial: 'creating', states: { creating: { on: { - CANCELLED: { to: "selecting" }, + CANCELLED: { to: 'selecting' }, POINTED_CANVAS: { - get: "newLine", - do: "createShape", - to: "line.editing", + get: 'newLine', + do: 'createShape', + to: 'line.editing', }, }, }, editing: { on: { - STOPPED_POINTING: { to: "selecting" }, - CANCELLED: { to: "selecting" }, + STOPPED_POINTING: { to: 'selecting' }, + CANCELLED: { to: 'selecting' }, MOVED_POINTER: { - if: "distanceImpliesDrag", - to: "drawingShape.direction", + if: 'distanceImpliesDrag', + to: 'drawingShape.direction', }, }, }, @@ -463,28 +473,28 @@ const state = createState({ drawingShape: { on: { STOPPED_POINTING: { - do: "completeSession", - to: "selecting", + do: 'completeSession', + to: 'selecting', }, CANCELLED: { - do: ["cancelSession", "deleteSelectedIds"], - to: "selecting", + do: ['cancelSession', 'deleteSelectedIds'], + to: 'selecting', }, }, - initial: "drawingShapeBounds", + initial: 'drawingShapeBounds', states: { bounds: { - onEnter: "startDrawTransformSession", + onEnter: 'startDrawTransformSession', on: { - MOVED_POINTER: "updateTransformSession", - PANNED_CAMERA: "updateTransformSession", + MOVED_POINTER: 'updateTransformSession', + PANNED_CAMERA: 'updateTransformSession', }, }, direction: { - onEnter: "startDirectionSession", + onEnter: 'startDirectionSession', on: { - MOVED_POINTER: "updateDirectionSession", - PANNED_CAMERA: "updateDirectionSession", + MOVED_POINTER: 'updateDirectionSession', + PANNED_CAMERA: 'updateDirectionSession', }, }, }, @@ -515,7 +525,7 @@ const state = createState({ }, conditions: { isPointingBounds(data, payload: PointerInfo) { - return payload.target === "bounds" + return payload.target === 'bounds' }, isReadOnly(data) { return data.isReadOnly @@ -545,9 +555,9 @@ const state = createState({ }, isPointingRotationHandle( data, - payload: { target: Edge | Corner | "rotate" } + payload: { target: Edge | Corner | 'rotate' } ) { - return payload.target === "rotate" + return payload.target === 'rotate' }, hasSelection(data) { return data.selectedIds.size > 0 @@ -753,7 +763,7 @@ const state = createState({ data.camera.zoom = 1 data.camera.point = [window.innerWidth / 2, window.innerHeight / 2] - document.documentElement.style.setProperty("--camera-zoom", "1") + document.documentElement.style.setProperty('--camera-zoom', '1') }, zoomCameraToActual(data) { const { camera } = data @@ -983,7 +993,7 @@ const state = createState({ if (selectedIds.size === 1) { if (!shapes[0]) { - console.error("Could not find that shape! Clearing selected IDs.") + console.error('Could not find that shape! Clearing selected IDs.') data.selectedIds.clear() return null } diff --git a/yarn.lock b/yarn.lock index 82b9cfc62..9443e0838 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6392,10 +6392,10 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -perfect-freehand@^0.4.71: - version "0.4.71" - resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-0.4.71.tgz#b98ffc3cbc4e3cd930528e8d74a8849ee77475fb" - integrity sha512-bJ3w2E6WcUfZJTXWPlS7DI6FIT9rRIYSCXgDYjvST8sAe/c+zNnJnlfJp3q8Hk1uPt9dH7bFuj8Sico6CKZw7A== +perfect-freehand@^0.4.8: + version "0.4.8" + resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-0.4.8.tgz#0054995322fdd9939c0c38c260d96a9d0f22eb4f" + integrity sha512-zU0hvTh0ctjb/h5+nwFhb+/5ZnqS8Z16mn7lY2tYy3NwTkjrEKZ8CJvQ2phlOV5kk+BnCDFGVz7tkKrl9+Mr9w== performance-now@^2.1.0: version "2.1.0"