import { AffineTransform, Point, Size } from "@noya-app/noya-geometry"; import React from "react"; import { BaseMode, Plugin, PluginSystem } from "./PluginSystem"; import { BaseContextProperties } from "./contextProperties"; import { PointerData } from "./pointerPlugin"; export type BaseCanvasData = { size: Size; zoom: number; origin: Point }; export type AnyCanvasPlugin = Plugin< BaseMode, BaseCanvasData & PointerData, any, ReactEventHandlerMap >; export type AnyCanvasPluginSystem = PluginSystem< BaseMode, BaseCanvasData & PointerData, any, ReactEventHandlerMap >; export const initialBaseCanvasData: BaseCanvasData = { size: { width: 0, height: 0 }, zoom: 1, origin: { x: 0, y: 0 }, }; export const initialPointerData: PointerData = { pointer: undefined, pointerDown: undefined, clickCount: 0, lastClickTime: 0, rawPointer: undefined, }; export type ReactEventHandlerMap = { onWheel: (event: React.WheelEvent) => void; onPointerEnter: (event: React.PointerEvent) => void; onPointerLeave: (event: React.PointerEvent) => void; onPointerDown: (event: React.PointerEvent) => void; onPointerMove: (event: React.PointerEvent) => void; onPointerUp: (event: React.PointerEvent) => void; onPointerCancel: (event: React.PointerEvent) => void; onGotPointerCapture: (event: React.PointerEvent) => void; onLostPointerCapture: (event: React.PointerEvent) => void; onKeyDown: (event: React.KeyboardEvent) => void; onKeyUp: (event: React.KeyboardEvent) => void; // Special, not handled by React's event system // TODO: Move this elsewhere? onBeforeInput: (event: InputEvent) => void; }; export function createCanvasPlugin< Mode extends BaseMode, Data extends object, ContextProperties extends object, >( plugin: Omit< Plugin< Mode, Data, ContextProperties & BaseContextProperties, ReactEventHandlerMap >, "getCursor" > & { getCursor?: ({ data, mode, }: { data: Data; mode: Mode; }) => string | undefined; } ) { return { ...(plugin as Plugin< Mode, Data, ContextProperties & BaseContextProperties, ReactEventHandlerMap >), data: { ...initialBaseCanvasData, ...plugin.data, }, }; } export function getCanvasTransform(data: { origin: { x: number; y: number }; zoom: number; }) { return AffineTransform.translate(data.origin.x, data.origin.y).scale( data.zoom ); }