Tldraw/packages/tldraw/src/state/tools/BaseTool.ts

128 wiersze
2.8 KiB
TypeScript

import {
TLKeyboardEventHandler,
TLPinchEventHandler,
TLPointerEventHandler,
Utils,
} from '@tldraw/core'
import type { TldrawApp } from '../internal'
import { TDEventHandler, TDToolType } from '~types'
export enum Status {
Idle = 'idle',
Creating = 'creating',
Pinching = 'pinching',
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export abstract class BaseTool<T extends string = any> extends TDEventHandler {
type: TDToolType = 'select' as const
previous?: TDToolType
status: Status | T = Status.Idle
constructor(public app: TldrawApp) {
super()
}
protected readonly setStatus = (status: Status | T) => {
this.status = status as Status | T
this.app.setStatus(this.status as string)
}
onEnter = () => {
this.setStatus(Status.Idle)
}
onExit = () => {
this.setStatus(Status.Idle)
}
onCancel = () => {
if (this.status === Status.Idle) {
this.app.selectTool('select')
} else {
this.setStatus(Status.Idle)
}
this.app.cancelSession()
}
getNextChildIndex = () => {
const {
shapes,
appState: { currentPageId },
} = this.app
return shapes.length === 0
? 1
: shapes
.filter((shape) => shape.parentId === currentPageId)
.sort((a, b) => b.childIndex - a.childIndex)[0].childIndex + 1
}
/* --------------------- Camera --------------------- */
onPinchStart: TLPinchEventHandler = () => {
this.app.cancelSession()
this.setStatus(Status.Pinching)
}
onPinchEnd: TLPinchEventHandler = () => {
if (Utils.isMobileSafari()) {
this.app.undoSelect()
}
this.setStatus(Status.Idle)
}
onPinch: TLPinchEventHandler = (info, e) => {
if (this.status !== 'pinching') return
if (isNaN(info.delta[0]) || isNaN(info.delta[1])) return
this.app.pinchZoom(info.point, info.delta, info.delta[2])
this.onPointerMove?.(info, e as unknown as React.PointerEvent)
}
/* ---------------------- Keys ---------------------- */
onKeyDown: TLKeyboardEventHandler = (key) => {
if (key === 'Escape') {
this.onCancel()
return
}
if (key === 'Meta' || key === 'Control' || key === 'Alt') {
this.app.updateSession()
return
}
}
onKeyUp: TLKeyboardEventHandler = (key) => {
if (key === 'Meta' || key === 'Control' || key === 'Alt') {
this.app.updateSession()
return
}
}
/* --------------------- Pointer -------------------- */
onPointerMove: TLPointerEventHandler = () => {
if (this.status === Status.Creating) {
this.app.updateSession()
}
}
onPointerUp: TLPointerEventHandler = () => {
if (this.status === Status.Creating) {
this.app.completeSession()
const { isToolLocked } = this.app.appState
if (!isToolLocked) {
this.app.selectTool('select')
}
}
this.setStatus(Status.Idle)
}
}