import * as monaco from 'monaco-editor/esm/vs/editor/editor.api' /* -------------------------------------------------- */ /* Client State */ /* -------------------------------------------------- */ export interface Data { isReadOnly: boolean settings: { fontSize: number isDarkMode: boolean isCodeOpen: boolean isStyleOpen: boolean nudgeDistanceSmall: number nudgeDistanceLarge: number isToolLocked: boolean isPenLocked: boolean } currentStyle: ShapeStyles & TextStyles activeTool: ShapeType | 'select' brush?: Bounds boundsRotation: number pointedId?: string hoveredId?: string editingId?: string currentPageId: string currentParentId: string currentCodeFileId: string codeControls: Record document: TLDocument pageStates: Record } /* -------------------------------------------------- */ /* Document */ /* -------------------------------------------------- */ export interface TLDocument { id: string name: string pages: Record code: Record } export interface Page { id: string type: 'page' childIndex: number name: string shapes: Record } export interface PageState { id: string selectedIds: Set camera: { point: number[] zoom: number } } export enum ShapeType { Dot = 'dot', Circle = 'circle', Ellipse = 'ellipse', Line = 'line', Ray = 'ray', Polyline = 'polyline', Rectangle = 'rectangle', Draw = 'draw', Arrow = 'arrow', Text = 'text', Group = 'group', } 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 { Solid = 'Solid', Dashed = 'Dashed', Dotted = 'Dotted', } export enum FontSize { Small = 'Small', Medium = 'Medium', Large = 'Large', ExtraLarge = 'ExtraLarge', } export type ShapeStyles = { color: ColorStyle size: SizeStyle dash: DashStyle isFilled: boolean } export type TextStyles = { fontSize: FontSize } export interface BaseShape { id: string seed: number type: ShapeType parentId: string childIndex: number isGenerated: boolean name: string point: number[] style: ShapeStyles rotation: number children?: string[] bindings?: Record handles?: Record isLocked: boolean isHidden: boolean isAspectRatioLocked: boolean } export interface DotShape extends BaseShape { type: ShapeType.Dot } export interface CircleShape extends BaseShape { type: ShapeType.Circle radius: number } export interface EllipseShape extends BaseShape { type: ShapeType.Ellipse radiusX: number radiusY: number } export interface LineShape extends BaseShape { type: ShapeType.Line direction: number[] } export interface RayShape extends BaseShape { type: ShapeType.Ray direction: number[] } export interface PolylineShape extends BaseShape { type: ShapeType.Polyline points: number[][] } export interface RectangleShape extends BaseShape { type: ShapeType.Rectangle size: number[] radius: number } export interface DrawShape extends BaseShape { type: ShapeType.Draw points: number[][] } export interface ArrowShape extends BaseShape { type: ShapeType.Arrow points: number[][] handles: Record bend: number decorations?: { start: Decoration end: Decoration middle: Decoration } } export interface TextShape extends BaseShape { type: ShapeType.Text text: string size: number[] | 'auto' scale: number fontSize: FontSize } export interface GroupShape extends BaseShape { type: ShapeType.Group children: string[] size: number[] } export type MutableShape = | DotShape | CircleShape | EllipseShape | LineShape | RayShape | PolylineShape | DrawShape | RectangleShape | ArrowShape | TextShape | GroupShape export interface Shapes { [ShapeType.Dot]: Readonly [ShapeType.Circle]: Readonly [ShapeType.Ellipse]: Readonly [ShapeType.Line]: Readonly [ShapeType.Ray]: Readonly [ShapeType.Polyline]: Readonly [ShapeType.Draw]: Readonly [ShapeType.Rectangle]: Readonly [ShapeType.Arrow]: Readonly [ShapeType.Text]: Readonly [ShapeType.Group]: Readonly } export type Shape = Readonly export type ShapeByType = Shapes[T] export interface CodeFile { id: string name: string code: string } export enum Decoration { Arrow = 'Arrow', } export interface ShapeBinding { id: string index: number point: number[] } export interface ShapeHandle { id: string index: number point: number[] } /* -------------------------------------------------- */ /* Editor UI */ /* -------------------------------------------------- */ export interface PointerInfo { target: string pointerId: number origin: number[] point: number[] pressure: number shiftKey: boolean ctrlKey: boolean metaKey: boolean altKey: boolean } export enum Edge { Top = 'top_edge', Right = 'right_edge', Bottom = 'bottom_edge', Left = 'left_edge', } export enum Corner { TopLeft = 'top_left_corner', TopRight = 'top_right_corner', BottomRight = 'bottom_right_corner', BottomLeft = 'bottom_left_corner', } export interface Bounds { minX: number minY: number maxX: number maxY: number width: number height: number rotation?: number } export interface RotatedBounds extends Bounds { rotation: number } export interface ShapeBounds extends Bounds { id: string } export interface PointSnapshot extends Bounds { nx: number nmx: number ny: number nmy: number } export interface BoundsSnapshot extends PointSnapshot { nw: number nh: number } export type Difference = A extends B ? never : A export type ShapeSpecificProps = Pick< T, Difference > export type ShapeIndicatorProps = ShapeSpecificProps export type ShapeUtil = { create(props: Partial): K getBounds(shape: K): Bounds hitTest(shape: K, test: number[]): boolean hitTestBounds(shape: K, bounds: Bounds): boolean rotate(shape: K): K translate(shape: K, delta: number[]): K scale(shape: K, scale: number): K stretch(shape: K, scaleX: number, scaleY: number): K render(shape: K): JSX.Element } export enum MoveType { Backward, Forward, ToFront, ToBack, } export enum AlignType { Top, CenterVertical, Bottom, Left, CenterHorizontal, Right, } export enum StretchType { Horizontal, Vertical, } export enum DistributeType { Horizontal, Vertical, } /* -------------------------------------------------- */ /* Code Editor */ /* -------------------------------------------------- */ export type IMonaco = typeof monaco export type IMonacoEditor = monaco.editor.IStandaloneCodeEditor export enum ControlType { Number = 'number', Vector = 'vector', Text = 'text', Select = 'select', } export interface BaseCodeControl { id: string type: ControlType label: string } export interface NumberCodeControl extends BaseCodeControl { type: ControlType.Number min?: number max?: number value: number step: number format?: (value: number) => number } export interface VectorCodeControl extends BaseCodeControl { type: ControlType.Vector value: number[] isNormalized: boolean format?: (value: number[]) => number[] } export interface TextCodeControl extends BaseCodeControl { type: ControlType.Text value: string format?: (value: string) => string } export interface SelectCodeControl extends BaseCodeControl { type: ControlType.Select value: T options: T[] format?: (string: T) => string } export type CodeControl = | NumberCodeControl | VectorCodeControl | TextCodeControl | SelectCodeControl export type PropsOfType = { [K in keyof T]: T[K] extends boolean ? K : never }[keyof T] export type Mutable = { -readonly [K in keyof T]: T[K] }