kopia lustrzana https://github.com/Tldraw/Tldraw
128 wiersze
2.8 KiB
TypeScript
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)
|
|
}
|
|
}
|