UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

218 lines (217 loc) 7.23 kB
import { Graph } from "../../../../graph"; import { Layer, LayerContext, LayerProps } from "../../../../services/Layer"; import { EventedComponent } from "../../EventedComponent/EventedComponent"; /** * All supported CSS cursor types for the CursorLayer. * Includes standard CSS cursor values and additional browser-specific cursors. */ export type CursorLayerCursorTypes = "auto" | "default" | "pointer" | "crosshair" | "move" | "text" | "wait" | "help" | "e-resize" | "n-resize" | "ne-resize" | "nw-resize" | "s-resize" | "se-resize" | "sw-resize" | "w-resize" | "ew-resize" | "ns-resize" | "nesw-resize" | "nwse-resize" | "grab" | "grabbing" | "not-allowed" | "no-drop" | "copy" | "alias" | "context-menu" | "cell" | "col-resize" | "row-resize" | "progress" | "vertical-text" | "zoom-in" | "zoom-out"; /** * Operating modes for the CursorLayer. * - "auto": Automatically sets cursor based on component under mouse * - "manual": Uses manually set cursor, ignoring component cursors */ export type CursorLayerMode = "auto" | "manual"; /** * Properties for CursorLayer configuration. */ export type TCursorLayerProps = LayerProps & { graph: Graph; }; /** * Context provided to CursorLayer during rendering. */ export type TCursorLayerContext = LayerContext & { graph: Graph; }; /** * CursorLayer provides cursor management for graph components. * * This layer manages cursor changes by applying cursor styles directly to the * graph root element, avoiding event blocking issues while maintaining * performance. * * ## Features: * - **Automatic mode**: Dynamically sets cursor based on component under mouse * - **Manual mode**: Allows explicit cursor control that overrides automatic behavior * * ## Usage: * ```typescript * // Automatic mode (default) * graph.getCursorLayer().isAuto(); // true * * // Manual mode * graph.lockCursor("grabbing"); * graph.unlockCursor(); // returns to auto mode * ``` * * @example * ```typescript * // The layer is automatically created and managed by the Graph * const cursorLayer = graph.getCursorLayer(); * * // Check current mode * console.log(cursorLayer.getMode()); // "auto" | "manual" * * // Set manual cursor * cursorLayer.lockCursor("wait"); * * // Return to automatic behavior * cursorLayer.unlockCursor(); * ``` */ export declare class CursorLayer extends Layer<TCursorLayerProps, TCursorLayerContext> { /** Current operating mode of the cursor layer */ private mode; /** Currently set manual cursor type (only used in manual mode) */ private manualCursor?; /** Component currently under the mouse cursor */ private currentTarget?; /** * Creates a new CursorLayer instance. * * @param props - Configuration props for the layer */ constructor(props: TCursorLayerProps); /** * Lifecycle method called after layer initialization. * Sets up event listeners for mouse tracking. */ protected afterInit(): void; /** * Subscribes to graph mouse events for cursor management. * Always tracks mouse position to maintain accurate state * when switching between manual and auto modes. * * @private */ private subscribeToGraphEvents; /** * Updates the cursor based on the target component's cursor property. * * @param target - The component under the mouse cursor * @private */ private updateCursorForTarget; /** * Applies the specified cursor to the graph root element. * * @param cursor - The cursor type to apply * @private */ private applyCursor; protected unmountLayer(): void; /** * Locks the cursor to a specific type, disabling automatic cursor changes. * * When locked, the cursor will not change automatically based on * component interactions until unlockCursor() is called. This effectively * "freezes" the cursor state until manually unlocked. * * @param cursor - The cursor type to lock to * * @example * ```typescript * // Lock to loading cursor during async operation * cursorLayer.lockCursor("wait"); * * // Lock to grabbing cursor during drag * cursorLayer.lockCursor("grabbing"); * ``` * * @see {@link unlockCursor} to return to automatic behavior */ lockCursor(cursor: CursorLayerCursorTypes): void; /** * Unlocks the cursor and returns to automatic cursor management. * * The cursor will immediately update to reflect the current state * based on the component under the mouse (if any). This removes the * "lock" and allows the cursor to respond to component interactions again. * * @example * ```typescript * // Unlock to return to automatic behavior * cursorLayer.unlockCursor(); * * // If mouse is over a block, cursor will immediately show "grab" * // If mouse is over empty space, cursor will show "auto" * ``` * * @see {@link lockCursor} to disable automatic behavior */ unlockCursor(): void; /** * Returns the current operating mode of the cursor layer. * * @returns The current mode ("auto" or "manual") * * @example * ```typescript * if (cursorLayer.getMode() === "manual") { * console.log("Cursor is manually controlled"); * } * ``` */ getMode(): CursorLayerMode; /** * Returns the currently set manual cursor type. * * @returns The manual cursor type, or undefined if not in manual mode * * @example * ```typescript * const manualCursor = cursorLayer.getManualCursor(); * if (manualCursor) { * console.log(`Manual cursor: ${manualCursor}`); * } * ``` */ getManualCursor(): CursorLayerCursorTypes | undefined; /** * Checks if the cursor layer is currently in manual mode. * * @returns True if in manual mode, false otherwise * * @example * ```typescript * if (cursorLayer.isManual()) { * // Manual cursor is active * console.log("Manual cursor:", cursorLayer.getManualCursor()); * } * ``` */ isManual(): boolean; /** * Checks if the cursor layer is currently in automatic mode. * * @returns True if in automatic mode, false otherwise * * @example * ```typescript * if (cursorLayer.isAuto()) { * // Cursor changes automatically based on components * console.log("Current target:", cursorLayer.getCurrentTarget()); * } * ``` */ isAuto(): boolean; /** * Returns the component currently under the mouse cursor. * * This method is primarily intended for debugging and development. * The value is tracked regardless of the current mode. * * @returns The component under the cursor, or undefined if none * * @example * ```typescript * const target = cursorLayer.getCurrentTarget(); * if (target) { * console.log("Mouse over:", target.constructor.name); * console.log("Component cursor:", target.cursor); * } * ``` */ getCurrentTarget(): EventedComponent | undefined; }