Skip to content

Commit 739cc2f

Browse files
committed
Split generic scrollable paper component Paper from diagram-specific state and logic:
* Replace `reactodia-paper-area` CSS class by `reactodia-canvas-area` and `reactodia-paper`. * Deprecate `CanvasMetrics.area` in favor of `CanvasMetrics.pane`. * Allow to move elements and manipulate link vertices on touchscreen. * Allow to select multiple elements with `Selection` with touch when `CanvasApi.pointerMode` is `selection`. * Enable `showPointerModeToggle` on `ZoomControl` by default (can be disabled by passing `false`). * Provide `onlySelected` property to link templates the same way as for element templates.
1 parent 960941d commit 739cc2f

44 files changed

Lines changed: 2159 additions & 1808 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ All notable changes to the Reactodia will be documented in this document.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
7+
#### 🚀 New Features
8+
- Support proper graph manipulation on touchscreen devices:
9+
* Allow to move and resize elements, manipulate link vertices on touchscreen;
10+
* Allow to select multiple elements with `Selection` with touch when `CanvasApi.pointerMode` is `selection`;
11+
* Allow to establish new links with `SelectionActionEstablishLink` on touchscreen;
12+
* Enable `showPointerModeToggle` on `ZoomControl` by default (can be disabled by passing `false`).
13+
14+
#### 💅 Polish
15+
- Provide `onlySelected` property to link templates the same way as for element templates.
16+
17+
#### 🔧 Maintenance
18+
- Preparations to extract generic scrollable paper component `Paper` from diagram-specific state and logic:
19+
* Replace `reactodia-paper-area` CSS class by `reactodia-canvas-area` and `reactodia-paper`.
20+
* Deprecate `CanvasMetrics.area` in favor of `CanvasMetrics.pane`.
721

822
## [0.33.0] - 2026-03-16
923
#### 🚀 New Features

src/coreUtils/scheduler.ts

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -103,57 +103,3 @@ export class BufferingQueue<Key extends string> {
103103
onFetch(keys);
104104
};
105105
}
106-
107-
/**
108-
* Runs specified callback on each rendered frame for the `duration` interval
109-
* using [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame).
110-
*
111-
* @category Utilities
112-
*/
113-
export function animateInterval(
114-
duration: number,
115-
onProgress: (progress: number) => void,
116-
signal?: AbortSignal
117-
): Promise<void> {
118-
return new Promise(resolve => {
119-
let animationFrameId: number;
120-
let start: number;
121-
let cleanupAbort: (() => void) | undefined;
122-
123-
const animate = (time: number) => {
124-
if (signal && signal.aborted) { return; }
125-
126-
start = start || time;
127-
let timePassed = time - start;
128-
if (timePassed > duration) { timePassed = duration; }
129-
130-
onProgress(timePassed / duration);
131-
132-
if (timePassed < duration) {
133-
animationFrameId = requestAnimationFrame(animate);
134-
} else {
135-
cleanupAbort?.();
136-
resolve();
137-
}
138-
};
139-
140-
if (signal) {
141-
const onAbort = () => {
142-
cancelAnimationFrame(animationFrameId);
143-
cleanupAbort?.();
144-
resolve();
145-
};
146-
cleanupAbort = () => {
147-
signal.removeEventListener('abort', onAbort);
148-
};
149-
signal.addEventListener('abort', onAbort);
150-
}
151-
animationFrameId = requestAnimationFrame(animate);
152-
});
153-
}
154-
155-
export function easeInOutBezier(t: number) {
156-
if (t < 0) { return 0; }
157-
if (t > 1) { return 1; }
158-
return t * t * (3.0 - 2.0 * t);
159-
}

src/diagram/canvasApi.ts

Lines changed: 9 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ import * as React from 'react';
22

33
import { Events, PropertyChange } from '../coreUtils/events';
44

5+
import type {
6+
CanvasMetrics, CanvasPaneMetrics, CenterToOptions, ScaleOptions, ViewportOptions,
7+
} from '../paper/paperApi';
8+
import type { PaperTransform } from '../paper/paperLayers';
9+
import type { ToDataURLOptions } from '../paper/toSvg';
10+
511
import type { RenderingState } from './renderingState';
612
import type { Cell } from './elements';
7-
import type { Vector, Rect, Size } from './geometry';
13+
import type { Vector, Rect } from './geometry';
814
import type { DiagramModel } from './model';
9-
import type { PaperTransform } from './paper';
10-
import type { ToDataURLOptions } from './toSvg';
15+
16+
export type { CanvasMetrics, CanvasPaneMetrics, CenterToOptions, ScaleOptions, ViewportOptions };
1117

1218
/**
1319
* Describes an API to interact with a scrollable graph canvas.
@@ -356,93 +362,6 @@ export interface CanvasKeyboardEvent {
356362
readonly sourceEvent: React.KeyboardEvent;
357363
}
358364

359-
/**
360-
* Represents canvas viewport size and transformation.
361-
*
362-
* Allows to convert between different canvas coordinate types.
363-
*/
364-
export interface CanvasMetrics {
365-
/**
366-
* Sizes and offsets for the canvas area DOM element.
367-
*/
368-
readonly area: CanvasAreaMetrics;
369-
/**
370-
* Returns transformation data between paper and scrollable pane coordinates.
371-
*/
372-
getTransform(): PaperTransform;
373-
/**
374-
* Returns a immutable instance of this metrics which is guaranteed to
375-
* never change even if original canvas viewport changes.
376-
*/
377-
snapshot(): CanvasMetrics;
378-
/**
379-
* Returns paper size in paper coordinates.
380-
*/
381-
getPaperSize(): Size;
382-
/**
383-
* Returns viewport bounds in page coordinates.
384-
*/
385-
getViewportPageRect(): Rect;
386-
/**
387-
* Translates page to paper coordinates.
388-
*/
389-
pageToPaperCoords(pageX: number, pageY: number): Vector;
390-
/**
391-
* Translates paper to page coordinates.
392-
*/
393-
paperToPageCoords(paperX: number, paperY: number): Vector;
394-
/**
395-
* Translates client (viewport) to paper coordinates.
396-
*/
397-
clientToPaperCoords(areaClientX: number, areaClientY: number): Vector;
398-
/**
399-
* Translates client (viewport) to scrollable pane coordinates.
400-
*/
401-
clientToScrollablePaneCoords(areaClientX: number, areaClientY: number): Vector;
402-
/**
403-
* Translates scrollable pane to client (viewport) coordinates.
404-
*/
405-
scrollablePaneToClientCoords(paneX: number, paneY: number): Vector;
406-
/**
407-
* Translates scrollable pane to paper coordinates.
408-
*/
409-
scrollablePaneToPaperCoords(paneX: number, paneY: number): Vector;
410-
/**
411-
* Translates paper to scrollable pane coordinates.
412-
*/
413-
paperToScrollablePaneCoords(paperX: number, paperY: number): Vector;
414-
}
415-
416-
/**
417-
* Contains sizes and offsets for the canvas area DOM element.
418-
*/
419-
export interface CanvasAreaMetrics {
420-
/**
421-
* Canvas area [client width](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth).
422-
*/
423-
readonly clientWidth: number;
424-
/**
425-
* Canvas area [client height](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight).
426-
*/
427-
readonly clientHeight: number;
428-
/**
429-
* Canvas area [offset width](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth).
430-
*/
431-
readonly offsetWidth: number;
432-
/**
433-
* Canvas area [offset height](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight).
434-
*/
435-
readonly offsetHeight: number;
436-
/**
437-
* Canvas area [scroll width](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth).
438-
*/
439-
readonly scrollLeft: number;
440-
/**
441-
* Canvas area [scroll height](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight).
442-
*/
443-
readonly scrollTop: number;
444-
}
445-
446365
/**
447366
* Action on moving pointer with pressed main button:
448367
* - `panning` - pans the viewport over canvas;
@@ -454,47 +373,6 @@ export interface CanvasAreaMetrics {
454373
*/
455374
export type CanvasPointerMode = 'panning' | 'selection';
456375

457-
/**
458-
* Options for {@link CanvasApi} methods affecting the viewport.
459-
*/
460-
export interface ViewportOptions {
461-
/**
462-
* True if operation should be animated.
463-
*
464-
* If duration is provided and greater than zero then defaults to `true`,
465-
* otherwise it is set to `false`.
466-
*/
467-
animate?: boolean;
468-
/**
469-
* Animation duration in milliseconds.
470-
*
471-
* Implicitly sets `animate: true` if greater than zero.
472-
*
473-
* @default 500
474-
*/
475-
duration?: number;
476-
}
477-
478-
/**
479-
* Options for {@link CanvasApi.centerTo} method.
480-
*/
481-
export interface CenterToOptions extends ViewportOptions {
482-
/**
483-
* Scale to set when changing the viewport.
484-
*/
485-
scale?: number;
486-
}
487-
488-
/**
489-
* Options for {@link CanvasApi} methods affecting canvas scale.
490-
*/
491-
export interface ScaleOptions extends ViewportOptions {
492-
/**
493-
* Scale pivot position in paper coordinates.
494-
*/
495-
pivot?: Vector;
496-
}
497-
498376
/**
499377
* Options for the behavior of operation affecting scale on the canvas.
500378
*/

0 commit comments

Comments
 (0)