js-draw 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/Editor.css +55 -13
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.d.ts +36 -3
- package/dist/cjs/Editor.js +63 -26
- package/dist/cjs/SVGLoader.js +37 -22
- package/dist/cjs/commands/Erase.js +1 -1
- package/dist/cjs/commands/UnresolvedCommand.d.ts +1 -1
- package/dist/cjs/components/AbstractComponent.d.ts +1 -1
- package/dist/cjs/components/AbstractComponent.js +1 -1
- package/dist/cjs/components/BackgroundComponent.d.ts +1 -1
- package/dist/cjs/components/BackgroundComponent.js +3 -2
- package/dist/cjs/{EditorImage.d.ts → image/EditorImage.d.ts} +30 -8
- package/dist/cjs/{EditorImage.js → image/EditorImage.js} +51 -7
- package/dist/cjs/image/export/editorImageToSVG.d.ts +8 -0
- package/dist/cjs/image/export/editorImageToSVG.js +49 -0
- package/dist/cjs/image/export/setExportedSVGSize.d.ts +6 -0
- package/dist/cjs/image/export/setExportedSVGSize.js +25 -0
- package/dist/cjs/image/lib.d.ts +1 -0
- package/dist/cjs/image/lib.js +8 -0
- package/dist/cjs/lib.d.ts +1 -1
- package/dist/cjs/lib.js +2 -3
- package/dist/cjs/localizations/comments.d.ts +6 -0
- package/dist/cjs/localizations/comments.js +10 -0
- package/dist/cjs/localizations/es.js +68 -48
- package/dist/cjs/rendering/caching/RenderingCache.d.ts +1 -1
- package/dist/cjs/rendering/caching/RenderingCacheNode.d.ts +1 -1
- package/dist/cjs/rendering/caching/RenderingCacheNode.js +4 -3
- package/dist/cjs/rendering/renderers/SVGRenderer.js +8 -19
- package/dist/cjs/rendering/renderers/SVGRenderer.test.d.ts +1 -0
- package/dist/cjs/toolbar/AbstractToolbar.d.ts +11 -3
- package/dist/cjs/toolbar/AbstractToolbar.js +20 -6
- package/dist/cjs/toolbar/EdgeToolbar.js +5 -6
- package/dist/cjs/toolbar/IconProvider.d.ts +1 -0
- package/dist/cjs/toolbar/IconProvider.js +43 -0
- package/dist/cjs/toolbar/widgets/ActionButtonWidget.d.ts +3 -1
- package/dist/cjs/toolbar/widgets/ActionButtonWidget.js +19 -1
- package/dist/cjs/toolbar/widgets/BaseToolWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/BaseToolWidget.js +3 -0
- package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +5 -0
- package/dist/cjs/toolbar/widgets/BaseWidget.js +30 -2
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +1 -1
- package/dist/cjs/toolbar/widgets/HandToolWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/HandToolWidget.js +6 -0
- package/dist/cjs/toolbar/widgets/InsertImageWidget.js +1 -1
- package/dist/cjs/toolbar/widgets/OverflowWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/OverflowWidget.js +3 -0
- package/dist/cjs/toolbar/widgets/SaveActionWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/SaveActionWidget.js +3 -0
- package/dist/cjs/tools/BaseTool.d.ts +3 -0
- package/dist/cjs/tools/BaseTool.js +13 -2
- package/dist/cjs/tools/FindTool.d.ts +1 -0
- package/dist/cjs/tools/FindTool.js +4 -1
- package/dist/cjs/tools/PanZoom.d.ts +1 -0
- package/dist/cjs/tools/PanZoom.js +4 -0
- package/dist/cjs/tools/Pen.d.ts +0 -1
- package/dist/cjs/tools/Pen.js +1 -4
- package/dist/cjs/tools/PipetteTool.d.ts +1 -0
- package/dist/cjs/tools/PipetteTool.js +3 -0
- package/dist/cjs/tools/SelectionTool/SelectAllShortcutHandler.d.ts +1 -0
- package/dist/cjs/tools/SelectionTool/SelectAllShortcutHandler.js +3 -0
- package/dist/cjs/tools/SelectionTool/Selection.d.ts +2 -0
- package/dist/cjs/tools/SelectionTool/Selection.js +44 -8
- package/dist/cjs/tools/SelectionTool/SelectionHandle.d.ts +14 -6
- package/dist/cjs/tools/SelectionTool/SelectionHandle.js +26 -8
- package/dist/cjs/tools/SelectionTool/SelectionTool.js +5 -0
- package/dist/cjs/tools/SoundUITool.d.ts +1 -0
- package/dist/cjs/tools/SoundUITool.js +4 -1
- package/dist/cjs/tools/TextTool.js +2 -2
- package/dist/cjs/tools/ToolController.d.ts +2 -0
- package/dist/cjs/tools/ToolController.js +13 -2
- package/dist/cjs/tools/ToolSwitcherShortcut.d.ts +1 -0
- package/dist/cjs/tools/ToolSwitcherShortcut.js +3 -0
- package/dist/cjs/types.d.ts +9 -4
- package/dist/cjs/types.js +4 -3
- package/dist/cjs/util/ReactiveValue.d.ts +1 -1
- package/dist/cjs/util/ReactiveValue.js +2 -2
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +36 -3
- package/dist/mjs/Editor.mjs +64 -27
- package/dist/mjs/Editor.toSVGAsync.test.d.ts +1 -0
- package/dist/mjs/SVGLoader.mjs +37 -22
- package/dist/mjs/commands/Erase.mjs +1 -1
- package/dist/mjs/commands/UnresolvedCommand.d.ts +1 -1
- package/dist/mjs/components/AbstractComponent.d.ts +1 -1
- package/dist/mjs/components/AbstractComponent.mjs +1 -1
- package/dist/mjs/components/BackgroundComponent.d.ts +1 -1
- package/dist/mjs/components/BackgroundComponent.mjs +3 -2
- package/dist/mjs/{EditorImage.d.ts → image/EditorImage.d.ts} +30 -8
- package/dist/mjs/{EditorImage.mjs → image/EditorImage.mjs} +51 -7
- package/dist/mjs/image/EditorImage.test.d.ts +1 -0
- package/dist/mjs/image/export/editorImageToSVG.d.ts +8 -0
- package/dist/mjs/image/export/editorImageToSVG.mjs +41 -0
- package/dist/mjs/image/export/setExportedSVGSize.d.ts +6 -0
- package/dist/mjs/image/export/setExportedSVGSize.mjs +23 -0
- package/dist/mjs/image/lib.d.ts +1 -0
- package/dist/mjs/image/lib.mjs +1 -0
- package/dist/mjs/lib.d.ts +1 -1
- package/dist/mjs/lib.mjs +1 -1
- package/dist/mjs/localizations/comments.d.ts +6 -0
- package/dist/mjs/localizations/comments.mjs +8 -0
- package/dist/mjs/localizations/es.mjs +68 -48
- package/dist/mjs/rendering/caching/RenderingCache.d.ts +1 -1
- package/dist/mjs/rendering/caching/RenderingCacheNode.d.ts +1 -1
- package/dist/mjs/rendering/caching/RenderingCacheNode.mjs +4 -3
- package/dist/mjs/rendering/renderers/SVGRenderer.mjs +8 -19
- package/dist/mjs/rendering/renderers/SVGRenderer.test.d.ts +1 -0
- package/dist/mjs/toolbar/AbstractToolbar.d.ts +11 -3
- package/dist/mjs/toolbar/AbstractToolbar.mjs +20 -6
- package/dist/mjs/toolbar/EdgeToolbar.mjs +5 -6
- package/dist/mjs/toolbar/IconProvider.d.ts +1 -0
- package/dist/mjs/toolbar/IconProvider.mjs +43 -0
- package/dist/mjs/toolbar/widgets/ActionButtonWidget.d.ts +3 -1
- package/dist/mjs/toolbar/widgets/ActionButtonWidget.mjs +21 -2
- package/dist/mjs/toolbar/widgets/BaseToolWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/BaseToolWidget.mjs +3 -0
- package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +5 -0
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +30 -2
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +1 -1
- package/dist/mjs/toolbar/widgets/HandToolWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +6 -0
- package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +1 -1
- package/dist/mjs/toolbar/widgets/OverflowWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/OverflowWidget.mjs +3 -0
- package/dist/mjs/toolbar/widgets/SaveActionWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/SaveActionWidget.mjs +3 -0
- package/dist/mjs/tools/BaseTool.d.ts +3 -0
- package/dist/mjs/tools/BaseTool.mjs +13 -2
- package/dist/mjs/tools/FindTool.d.ts +1 -0
- package/dist/mjs/tools/FindTool.mjs +4 -1
- package/dist/mjs/tools/PanZoom.d.ts +1 -0
- package/dist/mjs/tools/PanZoom.mjs +4 -0
- package/dist/mjs/tools/Pen.d.ts +0 -1
- package/dist/mjs/tools/Pen.mjs +1 -4
- package/dist/mjs/tools/PipetteTool.d.ts +1 -0
- package/dist/mjs/tools/PipetteTool.mjs +3 -0
- package/dist/mjs/tools/SelectionTool/SelectAllShortcutHandler.d.ts +1 -0
- package/dist/mjs/tools/SelectionTool/SelectAllShortcutHandler.mjs +3 -0
- package/dist/mjs/tools/SelectionTool/Selection.d.ts +2 -0
- package/dist/mjs/tools/SelectionTool/Selection.mjs +45 -9
- package/dist/mjs/tools/SelectionTool/SelectionHandle.d.ts +14 -6
- package/dist/mjs/tools/SelectionTool/SelectionHandle.mjs +25 -7
- package/dist/mjs/tools/SelectionTool/SelectionTool.mjs +5 -0
- package/dist/mjs/tools/SoundUITool.d.ts +1 -0
- package/dist/mjs/tools/SoundUITool.mjs +4 -1
- package/dist/mjs/tools/TextTool.mjs +2 -2
- package/dist/mjs/tools/ToolController.d.ts +2 -0
- package/dist/mjs/tools/ToolController.mjs +13 -2
- package/dist/mjs/tools/ToolSwitcherShortcut.d.ts +1 -0
- package/dist/mjs/tools/ToolSwitcherShortcut.mjs +3 -0
- package/dist/mjs/types.d.ts +9 -4
- package/dist/mjs/types.mjs +4 -3
- package/dist/mjs/util/ReactiveValue.d.ts +1 -1
- package/dist/mjs/util/ReactiveValue.mjs +2 -2
- package/dist/mjs/version.mjs +1 -1
- package/package.json +5 -5
- package/src/Editor.scss +6 -0
- package/src/toolbar/EdgeToolbar.scss +19 -2
- package/src/tools/SelectionTool/SelectionTool.scss +74 -0
- package/src/tools/tools.scss +1 -1
- package/src/tools/SelectionTool/SelectionTool.css +0 -35
- /package/dist/cjs/{EditorImage.test.d.ts → Editor.toSVGAsync.test.d.ts} +0 -0
- /package/dist/{mjs → cjs/image}/EditorImage.test.d.ts +0 -0
@@ -40,13 +40,16 @@ const Erase_1 = __importDefault(require("../../commands/Erase"));
|
|
40
40
|
const Duplicate_1 = __importDefault(require("../../commands/Duplicate"));
|
41
41
|
const TransformMode_1 = require("./TransformMode");
|
42
42
|
const types_1 = require("./types");
|
43
|
-
const EditorImage_1 = __importDefault(require("../../EditorImage"));
|
43
|
+
const EditorImage_1 = __importDefault(require("../../image/EditorImage"));
|
44
44
|
const updateChunkSize = 100;
|
45
45
|
const maxPreviewElemCount = 500;
|
46
46
|
// @internal
|
47
47
|
class Selection {
|
48
48
|
constructor(startPoint, editor) {
|
49
49
|
this.editor = editor;
|
50
|
+
// The last-computed bounding box of selected content
|
51
|
+
// @see getTightBoundingBox
|
52
|
+
this.selectionTightBoundingBox = null;
|
50
53
|
this.transform = math_1.Mat33.identity;
|
51
54
|
this.selectedElems = [];
|
52
55
|
this.hasParent = true;
|
@@ -65,10 +68,23 @@ class Selection {
|
|
65
68
|
this.backgroundElem = document.createElement('div');
|
66
69
|
this.backgroundElem.classList.add(`${SelectionTool_1.cssPrefix}selection-background`);
|
67
70
|
this.container.appendChild(this.backgroundElem);
|
68
|
-
const resizeHorizontalHandle = new SelectionHandle_1.default(
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
const resizeHorizontalHandle = new SelectionHandle_1.default({
|
72
|
+
action: SelectionHandle_1.HandleAction.ResizeX,
|
73
|
+
side: math_1.Vec2.of(1, 0.5),
|
74
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.resize.onDragStart(startPoint, types_1.ResizeMode.HorizontalOnly), (currentPoint) => this.transformers.resize.onDragUpdate(currentPoint), () => this.transformers.resize.onDragEnd());
|
75
|
+
const resizeVerticalHandle = new SelectionHandle_1.default({
|
76
|
+
action: SelectionHandle_1.HandleAction.ResizeY,
|
77
|
+
side: math_1.Vec2.of(0.5, 1),
|
78
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.resize.onDragStart(startPoint, types_1.ResizeMode.VerticalOnly), (currentPoint) => this.transformers.resize.onDragUpdate(currentPoint), () => this.transformers.resize.onDragEnd());
|
79
|
+
const resizeBothHandle = new SelectionHandle_1.default({
|
80
|
+
action: SelectionHandle_1.HandleAction.ResizeXY,
|
81
|
+
side: math_1.Vec2.of(1, 1),
|
82
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.resize.onDragStart(startPoint, types_1.ResizeMode.Both), (currentPoint) => this.transformers.resize.onDragUpdate(currentPoint), () => this.transformers.resize.onDragEnd());
|
83
|
+
const rotationHandle = new SelectionHandle_1.default({
|
84
|
+
action: SelectionHandle_1.HandleAction.Rotate,
|
85
|
+
side: math_1.Vec2.of(0.5, 0),
|
86
|
+
icon: this.editor.icons.makeRotateIcon(),
|
87
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.rotate.onDragStart(startPoint), (currentPoint) => this.transformers.rotate.onDragUpdate(currentPoint), () => this.transformers.rotate.onDragEnd());
|
72
88
|
this.handles = [
|
73
89
|
resizeBothHandle,
|
74
90
|
resizeHorizontalHandle,
|
@@ -195,18 +211,26 @@ class Selection {
|
|
195
211
|
// Returns false if the selection is empty.
|
196
212
|
recomputeRegion() {
|
197
213
|
const newRegion = this.computeTightBoundingBox();
|
214
|
+
this.selectionTightBoundingBox = newRegion;
|
198
215
|
if (!newRegion) {
|
199
216
|
this.cancelSelection();
|
200
217
|
return false;
|
201
218
|
}
|
202
219
|
this.originalRegion = newRegion;
|
220
|
+
this.padRegion();
|
221
|
+
return true;
|
222
|
+
}
|
223
|
+
// Applies padding to the current region if it is too small.
|
224
|
+
// @internal
|
225
|
+
padRegion() {
|
226
|
+
const sourceRegion = this.selectionTightBoundingBox ?? this.originalRegion;
|
203
227
|
const minSize = this.getMinCanvasSize();
|
204
|
-
if (
|
228
|
+
if (sourceRegion.w < minSize || sourceRegion.h < minSize) {
|
205
229
|
// Add padding
|
206
230
|
const padding = minSize / 2;
|
207
|
-
this.originalRegion = math_1.Rect2.bboxOf(
|
231
|
+
this.originalRegion = math_1.Rect2.bboxOf(sourceRegion.corners, padding);
|
232
|
+
this.updateUI();
|
208
233
|
}
|
209
|
-
return true;
|
210
234
|
}
|
211
235
|
getMinCanvasSize() {
|
212
236
|
const canvasHandleSize = SelectionHandle_1.handleSize / this.editor.viewport.getScaleFactor();
|
@@ -230,6 +254,14 @@ class Selection {
|
|
230
254
|
const rotationDeg = this.screenRegionRotation * 180 / Math.PI;
|
231
255
|
this.backgroundElem.style.transform = `rotate(${rotationDeg}deg)`;
|
232
256
|
this.backgroundElem.style.transformOrigin = 'center';
|
257
|
+
// If closer to perpendicular, apply different CSS
|
258
|
+
const perpendicularClassName = `${SelectionTool_1.cssPrefix}rotated-near-perpendicular`;
|
259
|
+
if (Math.abs(Math.sin(this.screenRegionRotation)) > 0.5) {
|
260
|
+
this.container.classList.add(perpendicularClassName);
|
261
|
+
}
|
262
|
+
else {
|
263
|
+
this.container.classList.remove(perpendicularClassName);
|
264
|
+
}
|
233
265
|
for (const handle of this.handles) {
|
234
266
|
handle.updatePosition();
|
235
267
|
}
|
@@ -401,6 +433,7 @@ class Selection {
|
|
401
433
|
}
|
402
434
|
setToPoint(point) {
|
403
435
|
this.originalRegion = this.originalRegion.grownToPoint(point);
|
436
|
+
this.selectionTightBoundingBox = null;
|
404
437
|
this.updateUI();
|
405
438
|
}
|
406
439
|
cancelSelection() {
|
@@ -408,12 +441,15 @@ class Selection {
|
|
408
441
|
this.container.remove();
|
409
442
|
}
|
410
443
|
this.originalRegion = math_1.Rect2.empty;
|
444
|
+
this.selectionTightBoundingBox = null;
|
411
445
|
this.hasParent = false;
|
412
446
|
}
|
413
447
|
setSelectedObjects(objects, bbox) {
|
414
448
|
this.addRemoveSelectionFromImage(true);
|
415
449
|
this.originalRegion = bbox;
|
450
|
+
this.selectionTightBoundingBox = bbox;
|
416
451
|
this.selectedElems = objects.filter(object => object.isSelectable());
|
452
|
+
this.padRegion();
|
417
453
|
this.updateUI();
|
418
454
|
}
|
419
455
|
getSelectedObjects() {
|
@@ -2,17 +2,23 @@ import { Point2, Vec2 } from '@js-draw/math';
|
|
2
2
|
import Selection from './Selection';
|
3
3
|
import Pointer from '../../Pointer';
|
4
4
|
import Viewport from '../../Viewport';
|
5
|
-
export declare enum
|
6
|
-
|
7
|
-
|
5
|
+
export declare enum HandleAction {
|
6
|
+
ResizeXY = "resize-xy",
|
7
|
+
Rotate = "rotate",
|
8
|
+
ResizeX = "resize-x",
|
9
|
+
ResizeY = "resize-y"
|
10
|
+
}
|
11
|
+
export interface HandlePresentation {
|
12
|
+
side: Vec2;
|
13
|
+
icon?: Element;
|
14
|
+
action: HandleAction;
|
8
15
|
}
|
9
16
|
export declare const handleSize = 30;
|
10
17
|
export type DragStartCallback = (startPoint: Point2) => void;
|
11
18
|
export type DragUpdateCallback = (canvasPoint: Point2) => void;
|
12
19
|
export type DragEndCallback = () => void;
|
13
20
|
export default class SelectionHandle {
|
14
|
-
readonly
|
15
|
-
private readonly parentSide;
|
21
|
+
readonly presentation: HandlePresentation;
|
16
22
|
private readonly parent;
|
17
23
|
private readonly viewport;
|
18
24
|
private readonly onDragStart;
|
@@ -20,7 +26,9 @@ export default class SelectionHandle {
|
|
20
26
|
private readonly onDragEnd;
|
21
27
|
private element;
|
22
28
|
private snapToGrid;
|
23
|
-
|
29
|
+
private shape;
|
30
|
+
private parentSide;
|
31
|
+
constructor(presentation: HandlePresentation, parent: Selection, viewport: Viewport, onDragStart: DragStartCallback, onDragUpdate: DragUpdateCallback, onDragEnd: DragEndCallback);
|
24
32
|
/**
|
25
33
|
* Adds this to `container`, where `conatiner` should be the background/selection
|
26
34
|
* element visible on the screen.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.handleSize = exports.
|
3
|
+
exports.handleSize = exports.HandleAction = void 0;
|
4
4
|
const assertions_1 = require("../../util/assertions");
|
5
5
|
const math_1 = require("@js-draw/math");
|
6
6
|
const SelectionTool_1 = require("./SelectionTool");
|
@@ -8,12 +8,18 @@ var HandleShape;
|
|
8
8
|
(function (HandleShape) {
|
9
9
|
HandleShape[HandleShape["Circle"] = 0] = "Circle";
|
10
10
|
HandleShape[HandleShape["Square"] = 1] = "Square";
|
11
|
-
})(HandleShape || (
|
11
|
+
})(HandleShape || (HandleShape = {}));
|
12
|
+
var HandleAction;
|
13
|
+
(function (HandleAction) {
|
14
|
+
HandleAction["ResizeXY"] = "resize-xy";
|
15
|
+
HandleAction["Rotate"] = "rotate";
|
16
|
+
HandleAction["ResizeX"] = "resize-x";
|
17
|
+
HandleAction["ResizeY"] = "resize-y";
|
18
|
+
})(HandleAction || (exports.HandleAction = HandleAction = {}));
|
12
19
|
exports.handleSize = 30;
|
13
20
|
class SelectionHandle {
|
14
|
-
constructor(
|
15
|
-
this.
|
16
|
-
this.parentSide = parentSide;
|
21
|
+
constructor(presentation, parent, viewport, onDragStart, onDragUpdate, onDragEnd) {
|
22
|
+
this.presentation = presentation;
|
17
23
|
this.parent = parent;
|
18
24
|
this.viewport = viewport;
|
19
25
|
this.onDragStart = onDragStart;
|
@@ -21,8 +27,20 @@ class SelectionHandle {
|
|
21
27
|
this.onDragEnd = onDragEnd;
|
22
28
|
this.dragLastPos = null;
|
23
29
|
this.element = document.createElement('div');
|
24
|
-
this.element.classList.add(`${SelectionTool_1.cssPrefix}handle`);
|
25
|
-
|
30
|
+
this.element.classList.add(`${SelectionTool_1.cssPrefix}handle`, `${SelectionTool_1.cssPrefix}${presentation.action}`);
|
31
|
+
this.parentSide = presentation.side;
|
32
|
+
const icon = presentation.icon;
|
33
|
+
if (icon) {
|
34
|
+
this.element.appendChild(icon);
|
35
|
+
icon.classList.add('icon');
|
36
|
+
}
|
37
|
+
if (presentation.action === HandleAction.Rotate) {
|
38
|
+
this.shape = HandleShape.Circle;
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
this.shape = HandleShape.Square;
|
42
|
+
}
|
43
|
+
switch (this.shape) {
|
26
44
|
case HandleShape.Circle:
|
27
45
|
this.element.classList.add(`${SelectionTool_1.cssPrefix}circle`);
|
28
46
|
break;
|
@@ -30,7 +48,7 @@ class SelectionHandle {
|
|
30
48
|
this.element.classList.add(`${SelectionTool_1.cssPrefix}square`);
|
31
49
|
break;
|
32
50
|
default:
|
33
|
-
(0, assertions_1.assertUnreachable)(shape);
|
51
|
+
(0, assertions_1.assertUnreachable)(this.shape);
|
34
52
|
}
|
35
53
|
this.updatePosition();
|
36
54
|
}
|
@@ -33,6 +33,11 @@ class SelectionTool extends BaseTool_1.default {
|
|
33
33
|
// The selection box could be using the wet ink display if its transformation
|
34
34
|
// hasn't been finalized yet. Clear before updating the UI.
|
35
35
|
this.editor.clearWetInk();
|
36
|
+
// If not currently selecting, ensure that the selection box
|
37
|
+
// is large enough.
|
38
|
+
if (!this.expandingSelectionBox) {
|
39
|
+
this.selectionBox?.padRegion();
|
40
|
+
}
|
36
41
|
this.selectionBox?.updateUI();
|
37
42
|
});
|
38
43
|
this.editor.handleKeyEventsFrom(this.handleOverlay);
|
@@ -14,6 +14,7 @@ export default class SoundUITool extends BaseTool {
|
|
14
14
|
private toggleButton;
|
15
15
|
private toggleButtonContainer;
|
16
16
|
constructor(editor: Editor, description: string);
|
17
|
+
canReceiveInputInReadOnlyEditor(): boolean;
|
17
18
|
private updateToggleButtonText;
|
18
19
|
setEnabled(enabled: boolean): void;
|
19
20
|
onKeyPress(event: KeyPressEvent): boolean;
|
@@ -105,6 +105,9 @@ class SoundUITool extends BaseTool_1.default {
|
|
105
105
|
this.updateToggleButtonText();
|
106
106
|
editor.createHTMLOverlay(this.toggleButtonContainer);
|
107
107
|
}
|
108
|
+
canReceiveInputInReadOnlyEditor() {
|
109
|
+
return true;
|
110
|
+
}
|
108
111
|
updateToggleButtonText() {
|
109
112
|
const containerEnabledClass = 'sound-ui-tool-enabled';
|
110
113
|
if (this.isEnabled()) {
|
@@ -118,7 +121,7 @@ class SoundUITool extends BaseTool_1.default {
|
|
118
121
|
}
|
119
122
|
setEnabled(enabled) {
|
120
123
|
super.setEnabled(enabled);
|
121
|
-
if (!
|
124
|
+
if (!this.isEnabled()) {
|
122
125
|
this.soundFeedback?.close();
|
123
126
|
this.soundFeedback = null;
|
124
127
|
}
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const TextComponent_1 = __importDefault(require("../components/TextComponent"));
|
7
|
-
const EditorImage_1 = __importDefault(require("../EditorImage"));
|
7
|
+
const EditorImage_1 = __importDefault(require("../image/EditorImage"));
|
8
8
|
const math_1 = require("@js-draw/math");
|
9
9
|
const Pointer_1 = require("../Pointer");
|
10
10
|
const types_1 = require("../types");
|
@@ -193,7 +193,7 @@ class TextTool extends BaseTool_1.default {
|
|
193
193
|
}
|
194
194
|
setEnabled(enabled) {
|
195
195
|
super.setEnabled(enabled);
|
196
|
-
if (!
|
196
|
+
if (!this.isEnabled()) {
|
197
197
|
this.flushInput();
|
198
198
|
}
|
199
199
|
this.textEditOverlay.style.display = enabled ? 'block' : 'none';
|
@@ -9,6 +9,7 @@ export default class ToolController implements InputEventListener {
|
|
9
9
|
private activeTool;
|
10
10
|
private primaryToolGroup;
|
11
11
|
private inputPipeline;
|
12
|
+
private isEditorReadOnly;
|
12
13
|
/** @internal */
|
13
14
|
constructor(editor: Editor, localization: ToolLocalization);
|
14
15
|
setTools(tools: BaseTool[], primaryToolGroup?: ToolEnabledGroup): void;
|
@@ -29,4 +30,5 @@ export default class ToolController implements InputEventListener {
|
|
29
30
|
*/
|
30
31
|
addInputMapper(mapper: InputMapper): void;
|
31
32
|
getMatchingTools<Type extends BaseTool>(type: new (...args: any[]) => Type): Type[];
|
33
|
+
onEditorDestroyed(): void;
|
32
34
|
}
|
@@ -51,6 +51,7 @@ class ToolController {
|
|
51
51
|
/** @internal */
|
52
52
|
constructor(editor, localization) {
|
53
53
|
this.activeTool = null;
|
54
|
+
this.isEditorReadOnly = editor.isReadOnlyReactiveValue();
|
54
55
|
this.inputPipeline = new InputPipeline_1.default();
|
55
56
|
this.inputPipeline.setEmitListener(event => this.onEventInternal(event));
|
56
57
|
const primaryToolGroup = new ToolEnabledGroup_1.default();
|
@@ -135,6 +136,10 @@ class ToolController {
|
|
135
136
|
}
|
136
137
|
// @internal use `dispatchEvent` rather than calling `onEvent` directly.
|
137
138
|
onEventInternal(event) {
|
139
|
+
const isEditorReadOnly = this.isEditorReadOnly.get();
|
140
|
+
const canToolReceiveInput = (tool) => {
|
141
|
+
return tool.isEnabled() && (!isEditorReadOnly || tool.canReceiveInputInReadOnlyEditor());
|
142
|
+
};
|
138
143
|
let handled = false;
|
139
144
|
if (event.kind === inputEvents_1.InputEvtType.PointerDownEvt) {
|
140
145
|
let canOnlySendToActiveTool = false;
|
@@ -145,7 +150,7 @@ class ToolController {
|
|
145
150
|
if (canOnlySendToActiveTool && tool !== this.activeTool) {
|
146
151
|
continue;
|
147
152
|
}
|
148
|
-
if (tool
|
153
|
+
if (canToolReceiveInput(tool) && tool.onEvent(event)) {
|
149
154
|
if (this.activeTool !== tool) {
|
150
155
|
this.activeTool?.onEvent({ kind: inputEvents_1.InputEvtType.GestureCancelEvt });
|
151
156
|
}
|
@@ -179,7 +184,7 @@ class ToolController {
|
|
179
184
|
}
|
180
185
|
else {
|
181
186
|
for (const tool of this.tools) {
|
182
|
-
if (!tool
|
187
|
+
if (!canToolReceiveInput(tool)) {
|
183
188
|
continue;
|
184
189
|
}
|
185
190
|
handled = tool.onEvent(event);
|
@@ -213,5 +218,11 @@ class ToolController {
|
|
213
218
|
getMatchingTools(type) {
|
214
219
|
return this.tools.filter(tool => tool instanceof type);
|
215
220
|
}
|
221
|
+
// @internal
|
222
|
+
onEditorDestroyed() {
|
223
|
+
for (const tool of this.tools) {
|
224
|
+
tool.onDestroy();
|
225
|
+
}
|
226
|
+
}
|
216
227
|
}
|
217
228
|
exports.default = ToolController;
|
@@ -17,6 +17,9 @@ class ToolSwitcherShortcut extends BaseTool_1.default {
|
|
17
17
|
super(editor.notifier, editor.localization.changeTool);
|
18
18
|
this.editor = editor;
|
19
19
|
}
|
20
|
+
canReceiveInputInReadOnlyEditor() {
|
21
|
+
return true;
|
22
|
+
}
|
20
23
|
// @internal
|
21
24
|
onKeyPress({ key }) {
|
22
25
|
const toolController = this.editor.toolController;
|
package/dist/cjs/types.d.ts
CHANGED
@@ -16,12 +16,13 @@ export declare enum EditorEventType {
|
|
16
16
|
ViewportChanged = 7,
|
17
17
|
DisplayResized = 8,
|
18
18
|
SelectionUpdated = 9,
|
19
|
+
ReadOnlyModeToggled = 10,
|
19
20
|
/** @internal */
|
20
|
-
ColorPickerToggled =
|
21
|
+
ColorPickerToggled = 11,
|
21
22
|
/** @internal */
|
22
|
-
ColorPickerColorSelected =
|
23
|
+
ColorPickerColorSelected = 12,
|
23
24
|
/** @deprecated @internal */
|
24
|
-
ToolbarDropdownShown =
|
25
|
+
ToolbarDropdownShown = 13
|
25
26
|
}
|
26
27
|
export declare enum UndoEventType {
|
27
28
|
CommandDone = 0,
|
@@ -66,6 +67,10 @@ export interface SelectionUpdated {
|
|
66
67
|
readonly selectedComponents: AbstractComponent[];
|
67
68
|
readonly tool: BaseTool;
|
68
69
|
}
|
70
|
+
export interface ReadOnlyToggled {
|
71
|
+
readonly kind: EditorEventType.ReadOnlyModeToggled;
|
72
|
+
readonly editorIsReadOnly: boolean;
|
73
|
+
}
|
69
74
|
export interface ColorPickerToggled {
|
70
75
|
readonly kind: EditorEventType.ColorPickerToggled;
|
71
76
|
readonly open: boolean;
|
@@ -79,7 +84,7 @@ export interface ToolbarDropdownShownEvent {
|
|
79
84
|
readonly fromToplevelDropdown: boolean;
|
80
85
|
readonly layoutManager: WidgetContentLayoutManager;
|
81
86
|
}
|
82
|
-
export type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | SelectionUpdated | ColorPickerToggled | ColorPickerColorSelected | ToolbarDropdownShownEvent;
|
87
|
+
export type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | SelectionUpdated | ReadOnlyToggled | ColorPickerToggled | ColorPickerColorSelected | ToolbarDropdownShownEvent;
|
83
88
|
export type OnProgressListener = (amountProcessed: number, totalToProcess: number) => Promise<void> | null | void;
|
84
89
|
export type ComponentAddedListener = (component: AbstractComponent) => Promise<void> | void;
|
85
90
|
export type OnDetermineExportRectListener = (exportRect: Rect2, options?: {
|
package/dist/cjs/types.js
CHANGED
@@ -14,12 +14,13 @@ var EditorEventType;
|
|
14
14
|
EditorEventType[EditorEventType["ViewportChanged"] = 7] = "ViewportChanged";
|
15
15
|
EditorEventType[EditorEventType["DisplayResized"] = 8] = "DisplayResized";
|
16
16
|
EditorEventType[EditorEventType["SelectionUpdated"] = 9] = "SelectionUpdated";
|
17
|
+
EditorEventType[EditorEventType["ReadOnlyModeToggled"] = 10] = "ReadOnlyModeToggled";
|
17
18
|
/** @internal */
|
18
|
-
EditorEventType[EditorEventType["ColorPickerToggled"] =
|
19
|
+
EditorEventType[EditorEventType["ColorPickerToggled"] = 11] = "ColorPickerToggled";
|
19
20
|
/** @internal */
|
20
|
-
EditorEventType[EditorEventType["ColorPickerColorSelected"] =
|
21
|
+
EditorEventType[EditorEventType["ColorPickerColorSelected"] = 12] = "ColorPickerColorSelected";
|
21
22
|
/** @deprecated @internal */
|
22
|
-
EditorEventType[EditorEventType["ToolbarDropdownShown"] =
|
23
|
+
EditorEventType[EditorEventType["ToolbarDropdownShown"] = 13] = "ToolbarDropdownShown";
|
23
24
|
})(EditorEventType || (exports.EditorEventType = EditorEventType = {}));
|
24
25
|
// Types of `EditorUndoStackUpdated` events.
|
25
26
|
var UndoEventType;
|
@@ -55,7 +55,7 @@ export declare abstract class ReactiveValue<T> {
|
|
55
55
|
}
|
56
56
|
export declare abstract class MutableReactiveValue<T> extends ReactiveValue<T> {
|
57
57
|
/**
|
58
|
-
* Changes the value of this and fires all update listeners.
|
58
|
+
* Changes the value of this and, if different, fires all update listeners.
|
59
59
|
*
|
60
60
|
* @see {@link onUpdate}
|
61
61
|
*/
|
@@ -59,7 +59,7 @@ class ReactiveValue {
|
|
59
59
|
*/
|
60
60
|
static fromCallback(callback, sourceValues) {
|
61
61
|
const result = new ReactiveValueImpl(callback());
|
62
|
-
const resultRef = window.WeakRef ? new WeakRef(result) : { deref: () => result };
|
62
|
+
const resultRef = window.WeakRef ? new window.WeakRef(result) : { deref: () => result };
|
63
63
|
for (const value of sourceValues) {
|
64
64
|
const listener = value.onUpdate(() => {
|
65
65
|
// Use resultRef to allow `result` to be garbage collected
|
@@ -98,7 +98,7 @@ exports.ReactiveValue = ReactiveValue;
|
|
98
98
|
class MutableReactiveValue extends ReactiveValue {
|
99
99
|
static fromProperty(sourceValue, propertyName) {
|
100
100
|
const child = ReactiveValue.fromInitialValue(sourceValue.get()[propertyName]);
|
101
|
-
const childRef = window.WeakRef ? new WeakRef(child) : { deref: () => child };
|
101
|
+
const childRef = window.WeakRef ? new window.WeakRef(child) : { deref: () => child };
|
102
102
|
// When the source is updated...
|
103
103
|
const sourceListener = sourceValue.onUpdate(newValue => {
|
104
104
|
const childValue = childRef.deref();
|
package/dist/cjs/version.js
CHANGED
package/dist/mjs/Editor.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import EditorImage from './EditorImage';
|
1
|
+
import EditorImage from './image/EditorImage';
|
2
2
|
import ToolController from './tools/ToolController';
|
3
3
|
import { EditorNotifier, ImageLoader } from './types';
|
4
4
|
import { HTMLPointerEventFilter, InputEvtType } from './inputEvents';
|
@@ -16,6 +16,7 @@ import KeyBinding from './shortcuts/KeyBinding';
|
|
16
16
|
import AbstractToolbar from './toolbar/AbstractToolbar';
|
17
17
|
import RenderablePathSpec from './rendering/RenderablePathSpec';
|
18
18
|
import { AboutDialogEntry } from './dialogs/makeAboutDialog';
|
19
|
+
import ReactiveValue, { MutableReactiveValue } from './util/ReactiveValue';
|
19
20
|
/**
|
20
21
|
* Provides settings to an instance of an editor. See the Editor {@link Editor.constructor}.
|
21
22
|
*
|
@@ -152,6 +153,7 @@ export declare class Editor {
|
|
152
153
|
private accessibilityAnnounceArea;
|
153
154
|
private accessibilityControlArea;
|
154
155
|
private eventListenerTargets;
|
156
|
+
private readOnly;
|
155
157
|
private settings;
|
156
158
|
/**
|
157
159
|
* @example
|
@@ -269,6 +271,13 @@ export declare class Editor {
|
|
269
271
|
* passed to the editor.
|
270
272
|
*/
|
271
273
|
handleKeyEventsFrom(elem: HTMLElement, filter?: (event: KeyboardEvent) => boolean): void;
|
274
|
+
/**
|
275
|
+
* Attempts to prevent **user-triggered** events from modifying
|
276
|
+
* the content of the image.
|
277
|
+
*/
|
278
|
+
setReadOnly(readOnly: boolean): void;
|
279
|
+
isReadOnlyReactiveValue(): ReactiveValue<boolean>;
|
280
|
+
isReadOnly(): MutableReactiveValue<boolean>;
|
272
281
|
/** `apply` a command. `command` will be announced for accessibility. */
|
273
282
|
dispatch(command: Command, addToHistory?: boolean): void | Promise<void>;
|
274
283
|
/**
|
@@ -386,10 +395,31 @@ export declare class Editor {
|
|
386
395
|
/**
|
387
396
|
* Converts the editor's content into an SVG image.
|
388
397
|
*
|
398
|
+
* If the output SVG has width or height less than `options.minDimension`, its size
|
399
|
+
* will be increased.
|
400
|
+
*
|
389
401
|
* @see
|
390
402
|
* {@link SVGRenderer}
|
391
403
|
*/
|
392
|
-
toSVG(
|
404
|
+
toSVG(options?: {
|
405
|
+
minDimension?: number;
|
406
|
+
}): SVGElement;
|
407
|
+
/**
|
408
|
+
* Converts the editor's content into an SVG image in an asynchronous,
|
409
|
+
* but **potentially lossy** way.
|
410
|
+
*
|
411
|
+
* **Warning**: If the image is being edited during an async rendering, edited components
|
412
|
+
* may not be rendered.
|
413
|
+
*
|
414
|
+
* Like {@link toSVG}, but can be configured to briefly pause after processing every
|
415
|
+
* `pauseAfterCount` items. This can prevent the editor from becoming unresponsive
|
416
|
+
* when saving very large images.
|
417
|
+
*/
|
418
|
+
toSVGAsync(options?: {
|
419
|
+
minDimension?: number;
|
420
|
+
pauseAfterCount?: number;
|
421
|
+
onProgress?: (processedCountInLayer: number, totalToProcessInLayer: number) => Promise<void | boolean>;
|
422
|
+
}): Promise<SVGElement>;
|
393
423
|
/**
|
394
424
|
* Load editor data from an `ImageLoader` (e.g. an {@link SVGLoader}).
|
395
425
|
*
|
@@ -435,7 +465,10 @@ export declare class Editor {
|
|
435
465
|
* Shows an information dialog with legal notices.
|
436
466
|
*/
|
437
467
|
showAboutDialog(): void;
|
438
|
-
/**
|
468
|
+
/**
|
469
|
+
* Removes and **destroys** the editor. The editor cannot be added to a parent
|
470
|
+
* again after calling this method.
|
471
|
+
*/
|
439
472
|
remove(): void;
|
440
473
|
}
|
441
474
|
export default Editor;
|