UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

151 lines (150 loc) 7.04 kB
export type TMouseWheelBehavior = "zoom" | "scroll"; /** Explicit wheel input device; `"auto"` uses gesture-shape heuristics. */ export type TWheelInputDevice = "auto" | "mouse" | "trackpad"; /** * Wheel input classification for camera routing. * * The library resolves **intent** (pan vs zoom), not device type. This boundary prepares * for a future input event bus where raw DOM events (`wheel`, `pointerdown`, …) are * normalized into semantic graph events (`camera:pan`, `camera:zoom`, …) before Camera * handles them. */ /** Wheel input intent for camera routing (pan vs zoom). */ export declare enum EWheelIntent { Pan = "pan", Zoom = "zoom" } /** Debug rule ids for {@link createWheelIntentResolver} (see `docs/system/wheel-intent.md`). */ export declare const WHEEL_INTENT_RULE: { readonly I1_PINCH: "I1:pinch"; readonly I2_HORIZONTAL_OR_DIAGONAL: "I2:horizontal-or-diagonal"; readonly I3_INPUT_DEVICE_TRACKPAD: "I3:input-device-trackpad"; readonly I3_INTEGER_TRACKPAD: "I3:integer-trackpad"; readonly I3_INTEGER_TRACKPAD_SLOW: "I3:integer-trackpad-slow"; readonly I3_RAPID_SMALL: "I3:rapid-small"; readonly I4_MOUSE_WHEEL_STEP: "I4:mouse-wheel-step"; readonly I4_LARGE_STEP: "I4:large-step"; readonly I4_FRACTIONAL_MOUSE: "I4:fractional-mouse"; readonly I4_BURST_SMOOTHING: "I4-burst:smoothing"; readonly I4_INPUT_DEVICE_MOUSE: "I4:input-device-mouse"; readonly I5_LAST_INTENT: "I5:last-intent"; readonly I5_STICKY_STREAM: "I5:sticky-stream"; }; export type TWheelIntentRule = (typeof WHEEL_INTENT_RULE)[keyof typeof WHEEL_INTENT_RULE]; /** Returns true when the rule id belongs to trackpad classification (I3). */ export declare function isI3WheelIntentRule(rule: TWheelIntentRule): boolean; /** Returns true when the rule id belongs to mouse-wheel classification (I4). */ export declare function isI4WheelIntentRule(rule: TWheelIntentRule): boolean; /** * Camera wheel policy passed to {@link TResolveWheelIntent} (from graph constants). */ export type TResolveWheelIntentOptions = { mouseWheelBehavior: TMouseWheelBehavior; wheelInputDevice?: TWheelInputDevice; }; /** * Classifies a wheel event as pan or zoom intent. * Configured as `resolveWheelIntent` on graph settings (`TGraphSettingsConfig`). */ export type TResolveWheelIntent = (event: WheelEvent, options: TResolveWheelIntentOptions) => EWheelIntent; /** Snapshot of resolver inputs, derived signals, session state, and the winning rule. */ export type TWheelIntentDebugEntry = { /** {@link TResolveWheelIntentOptions.mouseWheelBehavior}. */ mouseWheelBehavior: TMouseWheelBehavior; /** {@link TResolveWheelIntentOptions.wheelInputDevice} (defaults to `"auto"`). */ inputDevice: TWheelInputDevice; /** Raw {@link WheelEvent} fields passed into the resolver. */ input: { deltaX: number; deltaY: number; deltaMode: number; deltaModeLabel: string; ctrlKey: boolean; metaKey: boolean; shiftKey: boolean; altKey: boolean; }; /** Pixel-equivalent deltas after {@link normalizeWheelDelta}. */ normalized: { deltaX: number; deltaY: number; /** min(|x|, |y|) / max(|x|, |y|); null when both axes are ~0. */ diagonalAxisRatio: number | null; }; /** Timing and resolver session state at classification time. */ session: { timeSinceLastMs: number; isRapidStream: boolean; isInMouseWheelBurst: boolean; mouseWheelBurstRemainingMs: number | null; lastIntentBefore: EWheelIntent; }; /** Boolean predicates evaluated for I1–I5 (see `docs/system/wheel-intent.md`). */ signals: { isPinchZoom: boolean; isDiagonalScroll: boolean; isPredominantHorizontalScroll: boolean; isClassicMouseWheelStep: boolean; isDominantAxisLargeWheel: boolean; isVerticalOnly: boolean; hasFractionalDelta: boolean; isSmallDelta: boolean; /** Trackpads always emit `deltaMode === DOM_DELTA_PIXEL` (0); mice use LINE/PAGE or PIXEL. */ isPixelDeltaMode: boolean; /** Deprecated `wheelDelta(Y)` ≈ ±120 on Chromium mechanical mouse wheels (Mac Chrome 3× ratio excluded). */ hasLegacyMouseWheelDelta: boolean; }; /** Winning rule id and resolved intent. */ rule: TWheelIntentRule; result: EWheelIntent; }; export type TWheelIntentDebugLogger = (entry: TWheelIntentDebugEntry) => void; /** * Enables per-event debug logging for {@link createWheelIntentResolver}. * * Stored on `globalThis` so it works even when webpack loads duplicate module copies * (e.g. Storybook preview vs story bundle). * * @example * ```typescript * import { enableWheelIntentDebug } from "@gravity-ui/graph"; * enableWheelIntentDebug(); // default console.log: summary + JSON string * enableWheelIntentDebug(entry => myTelemetry.record(entry)); // custom logger * enableWheelIntentDebug(null); // disable * ``` */ export declare function enableWheelIntentDebug(logger?: TWheelIntentDebugLogger | null): void; /** * Returns true when a trackpad modifier-zoom gesture is active (PIXEL mode + ctrl/meta). * Used by Camera for {@link PINCH_ZOOM_SPEED}; mechanical wheels (LINE/PAGE) are excluded. */ export declare function isPinchZoomGesture(event: WheelEvent): boolean; /** * Creates the default wheel intent resolver (`TGraphSettingsConfig.resolveWheelIntent`). * * Classifies **intent** from gesture shape — not from inferred device type: * * | Signal | Intent | * |---------------------------------------|-----------------| * | ctrlKey / metaKey + PIXEL scroll | Zoom (I1) | * | Horizontal or diagonal movement | Pan (I2) | * | Integer PIXEL delta (trackpad, auto) | Pan (I3) | * | wheelInputDevice `"trackpad"` | Pan (I3:input-device-trackpad) | * | wheelInputDevice `"mouse"` | Zoom/Pan (I4:* per behavior) | * | Large isolated integer PIXEL step | Zoom/Pan (I4)* | * | Classic mouse wheel step (fractional) | Zoom/Pan (I4)* | * | Rapid stream + small delta (fractional)| Pan (I3) | * | Anything else | Last intent (I5)| * | Rapid stream + confident-rule flip | Sticky prior (I5:sticky-stream) | * * *I4 respects `mouseWheelBehavior`: `"scroll"` → Pan, `"zoom"` → Zoom. * * Trackpad: small integer PIXEL ticks, or large integer PIXEL inside a rapid stream → pan (I3). * Isolated large integer PIXEL (Chromium mouse on Windows) → I4 per `mouseWheelBehavior`. * LINE/PAGE mode (`deltaMode !== 0`) is never trackpad — always mouse (I4). * See `docs/system/wheel-intent.md` for rationale. * * Pass `wheelInputDevice` at resolve time (camera constant `WHEEL_INPUT_DEVICE`) when the app * knows the primary wheel device and Mac Chrome/YaBrowser heuristics are ambiguous. */ export declare function createWheelIntentResolver(): TResolveWheelIntent;