/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ import type { TLPage, TLUser, TLPageState, TLBinding, TLBoundsCorner, TLBoundsEdge, TLShape, TLHandle, TLSnapLine, TLPinchEventHandler, TLKeyboardEventHandler, TLPointerEventHandler, TLWheelEventHandler, TLCanvasEventHandler, TLBoundsEventHandler, TLBoundsHandleEventHandler, TLShapeBlurHandler, TLShapeCloneHandler, TLAsset, } from '@tldraw/core' import { TDLanguage } from '~translations' /* -------------------------------------------------- */ /* App */ /* -------------------------------------------------- */ // A base class for all classes that handle events from the Renderer, // including TDApp and all Tools. export class TDEventHandler { onPinchStart?: TLPinchEventHandler onPinchEnd?: TLPinchEventHandler onPinch?: TLPinchEventHandler onKeyDown?: TLKeyboardEventHandler onKeyUp?: TLKeyboardEventHandler onPointerMove?: TLPointerEventHandler onPointerUp?: TLPointerEventHandler onPan?: TLWheelEventHandler onZoom?: TLWheelEventHandler onPointerDown?: TLPointerEventHandler onPointCanvas?: TLCanvasEventHandler onDoubleClickCanvas?: TLCanvasEventHandler onRightPointCanvas?: TLCanvasEventHandler onDragCanvas?: TLCanvasEventHandler onReleaseCanvas?: TLCanvasEventHandler onPointShape?: TLPointerEventHandler onDoubleClickShape?: TLPointerEventHandler onRightPointShape?: TLPointerEventHandler onDragShape?: TLPointerEventHandler onHoverShape?: TLPointerEventHandler onUnhoverShape?: TLPointerEventHandler onReleaseShape?: TLPointerEventHandler onPointBounds?: TLBoundsEventHandler onDoubleClickBounds?: TLBoundsEventHandler onRightPointBounds?: TLBoundsEventHandler onDragBounds?: TLBoundsEventHandler onHoverBounds?: TLBoundsEventHandler onUnhoverBounds?: TLBoundsEventHandler onReleaseBounds?: TLBoundsEventHandler onPointBoundsHandle?: TLBoundsHandleEventHandler onDoubleClickBoundsHandle?: TLBoundsHandleEventHandler onRightPointBoundsHandle?: TLBoundsHandleEventHandler onDragBoundsHandle?: TLBoundsHandleEventHandler onHoverBoundsHandle?: TLBoundsHandleEventHandler onUnhoverBoundsHandle?: TLBoundsHandleEventHandler onReleaseBoundsHandle?: TLBoundsHandleEventHandler onPointHandle?: TLPointerEventHandler onDoubleClickHandle?: TLPointerEventHandler onRightPointHandle?: TLPointerEventHandler onDragHandle?: TLPointerEventHandler onHoverHandle?: TLPointerEventHandler onUnhoverHandle?: TLPointerEventHandler onReleaseHandle?: TLPointerEventHandler onShapeBlur?: TLShapeBlurHandler onShapeClone?: TLShapeCloneHandler } export type TDDockPosition = 'bottom' | 'left' | 'right' | 'top' // The shape of the TldrawApp's React (zustand) store export interface TDSnapshot { settings: { isCadSelectMode: boolean isDarkMode: boolean isDebugMode: boolean isPenMode: boolean isReadonlyMode: boolean isZoomSnap: boolean keepStyleMenuOpen: boolean nudgeDistanceSmall: number nudgeDistanceLarge: number isFocusMode: boolean isSnapping: boolean showRotateHandles: boolean showBindingHandles: boolean showCloneHandles: boolean showGrid: boolean language: TDLanguage dockPosition: TDDockPosition exportBackground: TDExportBackground } appState: { currentStyle: ShapeStyles currentPageId: string hoveredId?: string activeTool: TDToolType isToolLocked: boolean isEmptyCanvas: boolean isMenuOpen: boolean status: string snapLines: TLSnapLine[] eraseLine: number[][] isLoading: boolean disableAssets: boolean selectByContain?: boolean } document: TDDocument room?: { id: string userId: string users: Record } } export type TldrawPatch = Patch export type TldrawCommand = Command // The shape of the files stored in JSON export interface TDFile { name: string fileHandle: FileSystemHandle | null document: TDDocument assets: Record } // The shape of the Tldraw document export interface TDDocument { id: string name: string version: number pages: Record pageStates: Record assets: TDAssets } // The shape of a single page in the Tldraw document export type TDPage = TLPage // A partial of a TDPage, used for commands / patches export type PagePartial = { shapes: Patch bindings: Patch } // The meta information passed to TDShapeUtil components export interface TDMeta { isDarkMode: boolean } // The type of info given to shapes when transforming export interface TransformInfo { type: TLBoundsEdge | TLBoundsCorner initialShape: T scaleX: number scaleY: number transformOrigin: number[] } // The status of a TDUser export enum TDUserStatus { Idle = 'idle', Connecting = 'connecting', Connected = 'connected', Disconnected = 'disconnected', } // A TDUser, for multiplayer rooms export interface TDUser extends TLUser { activeShapes: TDShape[] status: TDUserStatus session?: boolean } export type Theme = 'dark' | 'light' export enum SessionType { Transform = 'transform', Translate = 'translate', TransformSingle = 'transformSingle', Brush = 'brush', Arrow = 'arrow', Draw = 'draw', Erase = 'erase', Rotate = 'rotate', Handle = 'handle', Grid = 'grid', Edit = 'edit', } export enum TDStatus { Idle = 'idle', PointingHandle = 'pointingHandle', PointingBounds = 'pointingBounds', PointingBoundsHandle = 'pointingBoundsHandle', TranslatingLabel = 'translatingLabel', TranslatingHandle = 'translatingHandle', Translating = 'translating', Transforming = 'transforming', Rotating = 'rotating', Pinching = 'pinching', Brushing = 'brushing', Creating = 'creating', EditingText = 'editing-text', } export type TDToolType = | 'select' | 'erase' | TDShapeType.Text | TDShapeType.Draw | TDShapeType.Ellipse | TDShapeType.Rectangle | TDShapeType.Triangle | TDShapeType.Line | TDShapeType.Arrow | TDShapeType.Sticky export type Easing = | 'linear' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInQuint' | 'easeOutQuint' | 'easeInOutQuint' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInExpo' | 'easeOutExpo' | 'easeInOutExpo' export enum MoveType { Backward = 'backward', Forward = 'forward', ToFront = 'toFront', ToBack = 'toBack', } export enum AlignType { Top = 'top', CenterVertical = 'centerVertical', Bottom = 'bottom', Left = 'left', CenterHorizontal = 'centerHorizontal', Right = 'right', } export enum StretchType { Horizontal = 'horizontal', Vertical = 'vertical', } export enum DistributeType { Horizontal = 'horizontal', Vertical = 'vertical', } export enum FlipType { Horizontal = 'horizontal', Vertical = 'vertical', } /* -------------------------------------------------- */ /* Shapes */ /* -------------------------------------------------- */ export enum TDShapeType { Sticky = 'sticky', Ellipse = 'ellipse', Rectangle = 'rectangle', Triangle = 'triangle', Draw = 'draw', Arrow = 'arrow', Line = 'line', Text = 'text', Group = 'group', Image = 'image', Video = 'video', } export enum Decoration { Arrow = 'arrow', } export interface TDBaseShape extends TLShape { style: ShapeStyles type: TDShapeType label?: string handles?: Record } export interface DrawShape extends TDBaseShape { type: TDShapeType.Draw points: number[][] isComplete: boolean } // The extended handle (used for arrows) export interface TDHandle extends TLHandle { canBind?: boolean bindingId?: string } export interface RectangleShape extends TDBaseShape { type: TDShapeType.Rectangle size: number[] label?: string labelPoint?: number[] } export interface EllipseShape extends TDBaseShape { type: TDShapeType.Ellipse radius: number[] label?: string labelPoint?: number[] } export interface TriangleShape extends TDBaseShape { type: TDShapeType.Triangle size: number[] label?: string labelPoint?: number[] } // The shape created with the arrow tool export interface ArrowShape extends TDBaseShape { type: TDShapeType.Arrow bend: number handles: { start: TDHandle bend: TDHandle end: TDHandle } decorations?: { start?: Decoration end?: Decoration middle?: Decoration } label?: string labelPoint?: number[] } export interface ArrowBinding extends TLBinding { handleId: keyof ArrowShape['handles'] distance: number point: number[] } export type TDBinding = ArrowBinding export interface ImageShape extends TDBaseShape { type: TDShapeType.Image size: number[] assetId: string } export interface VideoShape extends TDBaseShape { type: TDShapeType.Video size: number[] assetId: string isPlaying: boolean currentTime: number } // The shape created by the text tool export interface TextShape extends TDBaseShape { type: TDShapeType.Text text: string } // The shape created by the sticky tool export interface StickyShape extends TDBaseShape { type: TDShapeType.Sticky size: number[] text: string } // The shape created when multiple shapes are grouped export interface GroupShape extends TDBaseShape { type: TDShapeType.Group size: number[] children: string[] } // A union of all shapes export type TDShape = | RectangleShape | EllipseShape | TriangleShape | DrawShape | ArrowShape | TextShape | GroupShape | StickyShape | ImageShape | VideoShape /* ------------------ Shape Styles ------------------ */ export enum ColorStyle { White = 'white', LightGray = 'lightGray', Gray = 'gray', Black = 'black', Green = 'green', Cyan = 'cyan', Blue = 'blue', Indigo = 'indigo', Violet = 'violet', Red = 'red', Orange = 'orange', Yellow = 'yellow', } export enum SizeStyle { Small = 'small', Medium = 'medium', Large = 'large', } export enum DashStyle { Draw = 'draw', Solid = 'solid', Dashed = 'dashed', Dotted = 'dotted', } export enum FontSize { Small = 'small', Medium = 'medium', Large = 'large', ExtraLarge = 'extraLarge', } export enum AlignStyle { Start = 'start', Middle = 'middle', End = 'end', Justify = 'justify', } export enum FontStyle { Script = 'script', Sans = 'sans', Serif = 'erif', Mono = 'mono', } export type ShapeStyles = { color: ColorStyle size: SizeStyle dash: DashStyle font?: FontStyle textAlign?: AlignStyle isFilled?: boolean scale?: number } export enum TDAssetType { Image = 'image', Video = 'video', } export interface TDImageAsset extends TLAsset { type: TDAssetType.Image fileName: string src: string size: number[] } export interface TDVideoAsset extends TLAsset { type: TDAssetType.Video fileName: string src: string size: number[] } export type TDAsset = TDImageAsset | TDVideoAsset export type TDAssets = Record /* -------------------------------------------------- */ /* Export */ /* -------------------------------------------------- */ export enum TDExportType { PNG = 'png', JPG = 'jpeg', WEBP = 'webp', SVG = 'svg', JSON = 'json', } export interface TDExport { name: string type: string blob: Blob } export enum TDExportBackground { Transparent = 'transparent', Auto = 'auto', Light = 'light', Dark = 'dark', } /* -------------------------------------------------- */ /* Type Helpers */ /* -------------------------------------------------- */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export type ParametersExceptFirst = F extends (arg0: any, ...rest: infer R) => any ? R : never export type ExceptFirst = T extends [any, ...infer U] ? U : never export type ExceptFirstTwo = T extends [any, any, ...infer U] ? U : never export type PropsOfType = { // eslint-disable-next-line @typescript-eslint/no-explicit-any [K in keyof TDShape]: TDShape[K] extends any ? (TDShape[K] extends U ? K : never) : never }[keyof TDShape] export type Difference = A extends B ? never : C export type Intersection = A extends B ? C : never export type FilteredKeys = { [P in keyof T]: T[P] extends U ? P : never }[keyof T] export type RequiredKeys = { [K in keyof T]-?: Difference, Pick, K> }[keyof T] export type MembersWithRequiredKey = { [P in keyof T]: Intersection, T[P]> }[keyof T] export type MappedByType = { [P in T['type']]: T extends any ? (P extends T['type'] ? T : never) : never } export type ShapesWithProp = MembersWithRequiredKey, U> export type Patch = Partial<{ [P in keyof T]: Patch }> export interface Command { id?: string before: Patch after: Patch } export interface FileWithHandle extends File { handle?: FileSystemHandle } export interface FileWithDirectoryHandle extends File { directoryHandle?: FileSystemHandle } // The following typings implement the relevant parts of the File System Access // API. This can be removed once the specification reaches the Candidate phase // and is implemented as part of microsoft/TSJS-lib-generator. export interface FileSystemHandlePermissionDescriptor { mode?: 'read' | 'readwrite' } export interface FileSystemHandle { readonly kind: 'file' | 'directory' readonly name: string isSameEntry: (other: FileSystemHandle) => Promise queryPermission: (descriptor?: FileSystemHandlePermissionDescriptor) => Promise requestPermission: (descriptor?: FileSystemHandlePermissionDescriptor) => Promise }