js-draw 1.3.1 → 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/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 +1 -1
- 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/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/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 +1 -1
- 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/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
@@ -29,6 +29,11 @@ export default abstract class BaseWidget {
|
|
29
29
|
private toplevel;
|
30
30
|
protected readonly localizationTable: ToolbarLocalization;
|
31
31
|
constructor(editor: Editor, id: string, localizationTable?: ToolbarLocalization);
|
32
|
+
/**
|
33
|
+
* Should return a constant true or false value. If true (the default),
|
34
|
+
* this widget must be automatically disabled when its editor is read-only.
|
35
|
+
*/
|
36
|
+
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
32
37
|
getId(): string;
|
33
38
|
/**
|
34
39
|
* Note: Tags should be set *before* a tool widget is added to a toolbar.
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
11
11
|
};
|
12
|
-
var _BaseWidget_hasDropdown, _BaseWidget_tags;
|
12
|
+
var _BaseWidget_hasDropdown, _BaseWidget_disabledDueToReadOnlyEditor, _BaseWidget_tags, _BaseWidget_readOnlyListener;
|
13
13
|
import ToolbarShortcutHandler from '../../tools/ToolbarShortcutHandler.mjs';
|
14
14
|
import { keyPressEventFromHTMLEvent, keyUpEventFromHTMLEvent } from '../../inputEvents.mjs';
|
15
15
|
import { toolbarCSSPrefix } from '../constants.mjs';
|
@@ -30,11 +30,16 @@ class BaseWidget {
|
|
30
30
|
this.id = id;
|
31
31
|
this.dropdown = null;
|
32
32
|
_BaseWidget_hasDropdown.set(this, void 0);
|
33
|
+
// True iff this widget is disabled.
|
33
34
|
this.disabled = false;
|
35
|
+
// True iff this widget is currently disabled because the editor is read only
|
36
|
+
_BaseWidget_disabledDueToReadOnlyEditor.set(this, false);
|
34
37
|
_BaseWidget_tags.set(this, []);
|
35
38
|
// Maps subWidget IDs to subWidgets.
|
36
39
|
this.subWidgets = {};
|
37
40
|
this.toplevel = true;
|
41
|
+
// Listens for changes in whether the editor is read-only
|
42
|
+
_BaseWidget_readOnlyListener.set(this, null);
|
38
43
|
this.localizationTable = localizationTable ?? editor.localization;
|
39
44
|
// Default layout manager
|
40
45
|
const defaultLayoutManager = new DropdownLayoutManager((text) => this.editor.announceForAccessibility(text), this.localizationTable);
|
@@ -62,6 +67,13 @@ class BaseWidget {
|
|
62
67
|
toolbarShortcutHandlers[0].registerListener(event => this.onKeyPress(event));
|
63
68
|
}
|
64
69
|
}
|
70
|
+
/**
|
71
|
+
* Should return a constant true or false value. If true (the default),
|
72
|
+
* this widget must be automatically disabled when its editor is read-only.
|
73
|
+
*/
|
74
|
+
shouldAutoDisableInReadOnlyEditor() {
|
75
|
+
return true;
|
76
|
+
}
|
65
77
|
getId() {
|
66
78
|
return this.id;
|
67
79
|
}
|
@@ -256,6 +268,19 @@ class BaseWidget {
|
|
256
268
|
if (this.container.parentElement) {
|
257
269
|
this.container.remove();
|
258
270
|
}
|
271
|
+
__classPrivateFieldSet(this, _BaseWidget_readOnlyListener, this.editor.isReadOnlyReactiveValue().onUpdateAndNow(readOnly => {
|
272
|
+
if (readOnly && this.shouldAutoDisableInReadOnlyEditor() && !this.disabled) {
|
273
|
+
this.setDisabled(true);
|
274
|
+
__classPrivateFieldSet(this, _BaseWidget_disabledDueToReadOnlyEditor, true, "f");
|
275
|
+
if (__classPrivateFieldGet(this, _BaseWidget_hasDropdown, "f")) {
|
276
|
+
this.dropdown?.requestHide();
|
277
|
+
}
|
278
|
+
}
|
279
|
+
else if (!readOnly && __classPrivateFieldGet(this, _BaseWidget_disabledDueToReadOnlyEditor, "f")) {
|
280
|
+
__classPrivateFieldSet(this, _BaseWidget_disabledDueToReadOnlyEditor, false, "f");
|
281
|
+
this.setDisabled(false);
|
282
|
+
}
|
283
|
+
}), "f");
|
259
284
|
parent.appendChild(this.container);
|
260
285
|
return this.container;
|
261
286
|
}
|
@@ -273,6 +298,8 @@ class BaseWidget {
|
|
273
298
|
}
|
274
299
|
remove() {
|
275
300
|
this.container.remove();
|
301
|
+
__classPrivateFieldGet(this, _BaseWidget_readOnlyListener, "f")?.remove();
|
302
|
+
__classPrivateFieldSet(this, _BaseWidget_readOnlyListener, null, "f");
|
276
303
|
}
|
277
304
|
updateIcon() {
|
278
305
|
let newIcon = this.createIcon();
|
@@ -289,6 +316,7 @@ class BaseWidget {
|
|
289
316
|
}
|
290
317
|
setDisabled(disabled) {
|
291
318
|
this.disabled = disabled;
|
319
|
+
__classPrivateFieldSet(this, _BaseWidget_disabledDueToReadOnlyEditor, false, "f");
|
292
320
|
if (this.disabled) {
|
293
321
|
this.button.classList.add('disabled');
|
294
322
|
this.button.setAttribute('aria-disabled', 'true');
|
@@ -409,5 +437,5 @@ class BaseWidget {
|
|
409
437
|
}
|
410
438
|
}
|
411
439
|
}
|
412
|
-
_BaseWidget_hasDropdown = new WeakMap(), _BaseWidget_tags = new WeakMap();
|
440
|
+
_BaseWidget_hasDropdown = new WeakMap(), _BaseWidget_disabledDueToReadOnlyEditor = new WeakMap(), _BaseWidget_tags = new WeakMap(), _BaseWidget_readOnlyListener = new WeakMap();
|
413
441
|
export default BaseWidget;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import Erase from '../../commands/Erase.mjs';
|
2
2
|
import uniteCommands from '../../commands/uniteCommands.mjs';
|
3
3
|
import BackgroundComponent, { BackgroundType } from '../../components/BackgroundComponent.mjs';
|
4
|
-
import { EditorImageEventType } from '../../EditorImage.mjs';
|
4
|
+
import { EditorImageEventType } from '../../image/EditorImage.mjs';
|
5
5
|
import { Rect2 } from '@js-draw/math';
|
6
6
|
import { EditorEventType } from '../../types.mjs';
|
7
7
|
import { toolbarCSSPrefix } from '../constants.mjs';
|
@@ -7,6 +7,7 @@ export default class HandToolWidget extends BaseToolWidget {
|
|
7
7
|
protected overridePanZoomTool: PanZoom;
|
8
8
|
private allowTogglingBaseTool;
|
9
9
|
constructor(editor: Editor, overridePanZoomTool: PanZoom, localizationTable: ToolbarLocalization);
|
10
|
+
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
10
11
|
private static getPrimaryHandTool;
|
11
12
|
protected getTitle(): string;
|
12
13
|
protected createIcon(): Element;
|
@@ -75,6 +75,9 @@ class HandModeWidget extends BaseWidget {
|
|
75
75
|
});
|
76
76
|
this.setSelected(false);
|
77
77
|
}
|
78
|
+
shouldAutoDisableInReadOnlyEditor() {
|
79
|
+
return false;
|
80
|
+
}
|
78
81
|
setModeFlag(enabled) {
|
79
82
|
this.tool.setModeEnabled(this.flag, enabled);
|
80
83
|
}
|
@@ -113,6 +116,9 @@ export default class HandToolWidget extends BaseToolWidget {
|
|
113
116
|
this.addSubWidget(touchPanningWidget);
|
114
117
|
this.addSubWidget(rotationLockWidget);
|
115
118
|
}
|
119
|
+
shouldAutoDisableInReadOnlyEditor() {
|
120
|
+
return false;
|
121
|
+
}
|
116
122
|
static getPrimaryHandTool(toolController) {
|
117
123
|
const primaryPanZoomToolList = toolController.getPrimaryTools().filter(tool => tool instanceof PanZoom);
|
118
124
|
const primaryPanZoomTool = primaryPanZoomToolList[0];
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import ImageComponent from '../../components/ImageComponent.mjs';
|
2
2
|
import Erase from '../../commands/Erase.mjs';
|
3
|
-
import EditorImage from '../../EditorImage.mjs';
|
3
|
+
import EditorImage from '../../image/EditorImage.mjs';
|
4
4
|
import uniteCommands from '../../commands/uniteCommands.mjs';
|
5
5
|
import SelectionTool from '../../tools/SelectionTool/SelectionTool.mjs';
|
6
6
|
import { Mat33 } from '@js-draw/math';
|
@@ -5,6 +5,7 @@ export default class OverflowWidget extends BaseWidget {
|
|
5
5
|
private overflowChildren;
|
6
6
|
private overflowContainer;
|
7
7
|
constructor(editor: Editor, localizationTable?: ToolbarLocalization);
|
8
|
+
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
8
9
|
protected getTitle(): string;
|
9
10
|
protected createIcon(): Element | null;
|
10
11
|
protected handleClick(): void;
|
@@ -8,6 +8,9 @@ export default class OverflowWidget extends BaseWidget {
|
|
8
8
|
this.container.classList.add('dropdownShowable');
|
9
9
|
this.overflowContainer ??= document.createElement('div');
|
10
10
|
}
|
11
|
+
shouldAutoDisableInReadOnlyEditor() {
|
12
|
+
return false;
|
13
|
+
}
|
11
14
|
getTitle() {
|
12
15
|
return this.localizationTable.toggleOverflow;
|
13
16
|
}
|
@@ -4,6 +4,7 @@ import { ToolbarLocalization } from '../localization';
|
|
4
4
|
import ActionButtonWidget from './ActionButtonWidget';
|
5
5
|
declare class SaveActionWidget extends ActionButtonWidget {
|
6
6
|
constructor(editor: Editor, localization: ToolbarLocalization, saveCallback: () => void);
|
7
|
+
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
7
8
|
protected onKeyPress(event: KeyPressEvent): boolean;
|
8
9
|
mustBeInToplevelMenu(): boolean;
|
9
10
|
}
|
@@ -6,6 +6,9 @@ class SaveActionWidget extends ActionButtonWidget {
|
|
6
6
|
super(editor, 'save-button', editor.icons.makeSaveIcon, localization.save, saveCallback);
|
7
7
|
this.setTags([ToolbarWidgetTag.Save]);
|
8
8
|
}
|
9
|
+
shouldAutoDisableInReadOnlyEditor() {
|
10
|
+
return false;
|
11
|
+
}
|
9
12
|
onKeyPress(event) {
|
10
13
|
if (this.editor.shortcuts.matchesShortcut(saveKeyboardShortcut, event)) {
|
11
14
|
this.clickAction();
|
@@ -8,6 +8,8 @@ export default abstract class BaseTool implements InputEventListener {
|
|
8
8
|
private notifier;
|
9
9
|
readonly description: string;
|
10
10
|
protected constructor(notifier: EditorNotifier, description: string);
|
11
|
+
/** Override this to allow this tool to be enabled in a read-only editor */
|
12
|
+
canReceiveInputInReadOnlyEditor(): boolean;
|
11
13
|
setInputMapper(mapper: InputMapper | null): void;
|
12
14
|
getInputMapper(): InputMapper | null;
|
13
15
|
private dispatchEventToCallback;
|
@@ -54,4 +56,5 @@ export default abstract class BaseTool implements InputEventListener {
|
|
54
56
|
enabledValue(): ReactiveValue<boolean>;
|
55
57
|
setToolGroup(group: ToolEnabledGroup): void;
|
56
58
|
getToolGroup(): ToolEnabledGroup | null;
|
59
|
+
onDestroy(): void;
|
57
60
|
}
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
11
11
|
};
|
12
|
-
var _BaseTool_enabled, _BaseTool_group, _BaseTool_inputMapper;
|
12
|
+
var _BaseTool_enabled, _BaseTool_group, _BaseTool_inputMapper, _BaseTool_readOnlyEditorChangeListener;
|
13
13
|
import { EditorEventType } from '../types.mjs';
|
14
14
|
import { InputEvtType } from '../inputEvents.mjs';
|
15
15
|
import { ReactiveValue } from '../util/ReactiveValue.mjs';
|
@@ -20,6 +20,7 @@ class BaseTool {
|
|
20
20
|
_BaseTool_enabled.set(this, void 0);
|
21
21
|
_BaseTool_group.set(this, null);
|
22
22
|
_BaseTool_inputMapper.set(this, null);
|
23
|
+
_BaseTool_readOnlyEditorChangeListener.set(this, null);
|
23
24
|
__classPrivateFieldSet(this, _BaseTool_enabled, ReactiveValue.fromInitialValue(true), "f");
|
24
25
|
__classPrivateFieldGet(this, _BaseTool_enabled, "f").onUpdate(enabled => {
|
25
26
|
// Ensure that at most one tool in the group is enabled.
|
@@ -38,6 +39,10 @@ class BaseTool {
|
|
38
39
|
}
|
39
40
|
});
|
40
41
|
}
|
42
|
+
/** Override this to allow this tool to be enabled in a read-only editor */
|
43
|
+
canReceiveInputInReadOnlyEditor() {
|
44
|
+
return false;
|
45
|
+
}
|
41
46
|
setInputMapper(mapper) {
|
42
47
|
__classPrivateFieldSet(this, _BaseTool_inputMapper, mapper, "f");
|
43
48
|
if (mapper) {
|
@@ -155,6 +160,12 @@ class BaseTool {
|
|
155
160
|
}
|
156
161
|
return null;
|
157
162
|
}
|
163
|
+
// Called when the tool is removed/when the editor is destroyed.
|
164
|
+
// Subclasses that override this method **must call super.onDestroy()**.
|
165
|
+
onDestroy() {
|
166
|
+
__classPrivateFieldGet(this, _BaseTool_readOnlyEditorChangeListener, "f")?.remove();
|
167
|
+
__classPrivateFieldSet(this, _BaseTool_readOnlyEditorChangeListener, null, "f");
|
168
|
+
}
|
158
169
|
}
|
159
|
-
_BaseTool_enabled = new WeakMap(), _BaseTool_group = new WeakMap(), _BaseTool_inputMapper = new WeakMap();
|
170
|
+
_BaseTool_enabled = new WeakMap(), _BaseTool_group = new WeakMap(), _BaseTool_inputMapper = new WeakMap(), _BaseTool_readOnlyEditorChangeListener = new WeakMap();
|
160
171
|
export default BaseTool;
|
@@ -16,6 +16,9 @@ export default class FindTool extends BaseTool {
|
|
16
16
|
this.overlay.style.display = 'none';
|
17
17
|
this.overlay.classList.add(`${cssPrefix}-overlay`);
|
18
18
|
}
|
19
|
+
canReceiveInputInReadOnlyEditor() {
|
20
|
+
return true;
|
21
|
+
}
|
19
22
|
getMatches(searchFor) {
|
20
23
|
searchFor = searchFor.toLocaleLowerCase();
|
21
24
|
const allTextComponents = this.editor.image.getAllElements()
|
@@ -108,7 +111,7 @@ export default class FindTool extends BaseTool {
|
|
108
111
|
}
|
109
112
|
setEnabled(enabled) {
|
110
113
|
super.setEnabled(enabled);
|
111
|
-
if (
|
114
|
+
if (this.isEnabled()) {
|
112
115
|
this.setVisible(false);
|
113
116
|
}
|
114
117
|
}
|
@@ -32,6 +32,7 @@ export default class PanZoom extends BaseTool {
|
|
32
32
|
private inertialScroller;
|
33
33
|
private velocity;
|
34
34
|
constructor(editor: Editor, mode: PanZoomMode, description: string);
|
35
|
+
canReceiveInputInReadOnlyEditor(): boolean;
|
35
36
|
computePinchData(p1: Pointer, p2: Pointer): PinchData;
|
36
37
|
private allPointersAreOfType;
|
37
38
|
onPointerDown({ allPointers: pointers, current: currentPointer }: PointerEvt): boolean;
|
@@ -74,6 +74,10 @@ export default class PanZoom extends BaseTool {
|
|
74
74
|
this.inertialScroller = null;
|
75
75
|
this.velocity = null;
|
76
76
|
}
|
77
|
+
// The pan/zoom tool can be used in a read-only editor.
|
78
|
+
canReceiveInputInReadOnlyEditor() {
|
79
|
+
return true;
|
80
|
+
}
|
77
81
|
// Returns information about the pointers in a gesture
|
78
82
|
computePinchData(p1, p2) {
|
79
83
|
// Swap the pointers to ensure consistent ordering.
|
package/dist/mjs/tools/Pen.d.ts
CHANGED
package/dist/mjs/tools/Pen.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Color4 } from '@js-draw/math';
|
2
|
-
import EditorImage from '../EditorImage.mjs';
|
2
|
+
import EditorImage from '../image/EditorImage.mjs';
|
3
3
|
import { PointerDevice } from '../Pointer.mjs';
|
4
4
|
import { makeFreehandLineBuilder } from '../components/builders/FreehandLineBuilder.mjs';
|
5
5
|
import { EditorEventType } from '../types.mjs';
|
@@ -200,9 +200,6 @@ export default class Pen extends BaseTool {
|
|
200
200
|
getColor() { return this.style.color; }
|
201
201
|
getStrokeFactory() { return this.style.factory; }
|
202
202
|
getStyleValue() { return this.styleValue; }
|
203
|
-
setEnabled(enabled) {
|
204
|
-
super.setEnabled(enabled);
|
205
|
-
}
|
206
203
|
onKeyPress(event) {
|
207
204
|
const shortcuts = this.editor.shortcuts;
|
208
205
|
// Ctrl+Z: End the stroke so that it can be undone/redone.
|
@@ -16,6 +16,7 @@ export default class PipetteTool extends BaseTool {
|
|
16
16
|
private colorPreviewListener;
|
17
17
|
private colorSelectListener;
|
18
18
|
constructor(editor: Editor, description: string);
|
19
|
+
canReceiveInputInReadOnlyEditor(): boolean;
|
19
20
|
private updateSelectingStatus;
|
20
21
|
setColorListener(colorPreviewListener: ColorListener, colorSelectListener: ColorListener): void;
|
21
22
|
clearColorListener(): void;
|
@@ -18,6 +18,9 @@ export default class PipetteTool extends BaseTool {
|
|
18
18
|
this.updateSelectingStatus();
|
19
19
|
});
|
20
20
|
}
|
21
|
+
canReceiveInputInReadOnlyEditor() {
|
22
|
+
return true;
|
23
|
+
}
|
21
24
|
// Ensures that the root editor element correctly reflects whether color selection
|
22
25
|
// is in progress.
|
23
26
|
updateSelectingStatus() {
|
@@ -7,6 +7,9 @@ export default class SelectAllShortcutHandler extends BaseTool {
|
|
7
7
|
super(editor.notifier, editor.localization.selectAllTool);
|
8
8
|
this.editor = editor;
|
9
9
|
}
|
10
|
+
canReceiveInputInReadOnlyEditor() {
|
11
|
+
return true;
|
12
|
+
}
|
10
13
|
// @internal
|
11
14
|
onKeyPress(event) {
|
12
15
|
if (this.editor.shortcuts.matchesShortcut(selectAllKeyboardShortcut, event)) {
|
@@ -11,6 +11,7 @@ export default class Selection {
|
|
11
11
|
private editor;
|
12
12
|
private handles;
|
13
13
|
private originalRegion;
|
14
|
+
private selectionTightBoundingBox;
|
14
15
|
private transformers;
|
15
16
|
private transform;
|
16
17
|
private selectedElems;
|
@@ -39,6 +40,7 @@ export default class Selection {
|
|
39
40
|
private previewTransformCmds;
|
40
41
|
resolveToObjects(): boolean;
|
41
42
|
recomputeRegion(): boolean;
|
43
|
+
padRegion(): void;
|
42
44
|
getMinCanvasSize(): number;
|
43
45
|
getSelectedItemCount(): number;
|
44
46
|
updateUI(): void;
|
@@ -5,20 +5,23 @@
|
|
5
5
|
var _a;
|
6
6
|
import SerializableCommand from '../../commands/SerializableCommand.mjs';
|
7
7
|
import { Mat33, Rect2, Vec2 } from '@js-draw/math';
|
8
|
-
import SelectionHandle, {
|
8
|
+
import SelectionHandle, { HandleAction, handleSize } from './SelectionHandle.mjs';
|
9
9
|
import { cssPrefix } from './SelectionTool.mjs';
|
10
10
|
import Viewport from '../../Viewport.mjs';
|
11
11
|
import Erase from '../../commands/Erase.mjs';
|
12
12
|
import Duplicate from '../../commands/Duplicate.mjs';
|
13
13
|
import { DragTransformer, ResizeTransformer, RotateTransformer } from './TransformMode.mjs';
|
14
14
|
import { ResizeMode } from './types.mjs';
|
15
|
-
import EditorImage from '../../EditorImage.mjs';
|
15
|
+
import EditorImage from '../../image/EditorImage.mjs';
|
16
16
|
const updateChunkSize = 100;
|
17
17
|
const maxPreviewElemCount = 500;
|
18
18
|
// @internal
|
19
19
|
class Selection {
|
20
20
|
constructor(startPoint, editor) {
|
21
21
|
this.editor = editor;
|
22
|
+
// The last-computed bounding box of selected content
|
23
|
+
// @see getTightBoundingBox
|
24
|
+
this.selectionTightBoundingBox = null;
|
22
25
|
this.transform = Mat33.identity;
|
23
26
|
this.selectedElems = [];
|
24
27
|
this.hasParent = true;
|
@@ -37,10 +40,23 @@ class Selection {
|
|
37
40
|
this.backgroundElem = document.createElement('div');
|
38
41
|
this.backgroundElem.classList.add(`${cssPrefix}selection-background`);
|
39
42
|
this.container.appendChild(this.backgroundElem);
|
40
|
-
const resizeHorizontalHandle = new SelectionHandle(
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
const resizeHorizontalHandle = new SelectionHandle({
|
44
|
+
action: HandleAction.ResizeX,
|
45
|
+
side: Vec2.of(1, 0.5),
|
46
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.resize.onDragStart(startPoint, ResizeMode.HorizontalOnly), (currentPoint) => this.transformers.resize.onDragUpdate(currentPoint), () => this.transformers.resize.onDragEnd());
|
47
|
+
const resizeVerticalHandle = new SelectionHandle({
|
48
|
+
action: HandleAction.ResizeY,
|
49
|
+
side: Vec2.of(0.5, 1),
|
50
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.resize.onDragStart(startPoint, ResizeMode.VerticalOnly), (currentPoint) => this.transformers.resize.onDragUpdate(currentPoint), () => this.transformers.resize.onDragEnd());
|
51
|
+
const resizeBothHandle = new SelectionHandle({
|
52
|
+
action: HandleAction.ResizeXY,
|
53
|
+
side: Vec2.of(1, 1),
|
54
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.resize.onDragStart(startPoint, ResizeMode.Both), (currentPoint) => this.transformers.resize.onDragUpdate(currentPoint), () => this.transformers.resize.onDragEnd());
|
55
|
+
const rotationHandle = new SelectionHandle({
|
56
|
+
action: HandleAction.Rotate,
|
57
|
+
side: Vec2.of(0.5, 0),
|
58
|
+
icon: this.editor.icons.makeRotateIcon(),
|
59
|
+
}, this, this.editor.viewport, (startPoint) => this.transformers.rotate.onDragStart(startPoint), (currentPoint) => this.transformers.rotate.onDragUpdate(currentPoint), () => this.transformers.rotate.onDragEnd());
|
44
60
|
this.handles = [
|
45
61
|
resizeBothHandle,
|
46
62
|
resizeHorizontalHandle,
|
@@ -167,18 +183,26 @@ class Selection {
|
|
167
183
|
// Returns false if the selection is empty.
|
168
184
|
recomputeRegion() {
|
169
185
|
const newRegion = this.computeTightBoundingBox();
|
186
|
+
this.selectionTightBoundingBox = newRegion;
|
170
187
|
if (!newRegion) {
|
171
188
|
this.cancelSelection();
|
172
189
|
return false;
|
173
190
|
}
|
174
191
|
this.originalRegion = newRegion;
|
192
|
+
this.padRegion();
|
193
|
+
return true;
|
194
|
+
}
|
195
|
+
// Applies padding to the current region if it is too small.
|
196
|
+
// @internal
|
197
|
+
padRegion() {
|
198
|
+
const sourceRegion = this.selectionTightBoundingBox ?? this.originalRegion;
|
175
199
|
const minSize = this.getMinCanvasSize();
|
176
|
-
if (
|
200
|
+
if (sourceRegion.w < minSize || sourceRegion.h < minSize) {
|
177
201
|
// Add padding
|
178
202
|
const padding = minSize / 2;
|
179
|
-
this.originalRegion = Rect2.bboxOf(
|
203
|
+
this.originalRegion = Rect2.bboxOf(sourceRegion.corners, padding);
|
204
|
+
this.updateUI();
|
180
205
|
}
|
181
|
-
return true;
|
182
206
|
}
|
183
207
|
getMinCanvasSize() {
|
184
208
|
const canvasHandleSize = handleSize / this.editor.viewport.getScaleFactor();
|
@@ -202,6 +226,14 @@ class Selection {
|
|
202
226
|
const rotationDeg = this.screenRegionRotation * 180 / Math.PI;
|
203
227
|
this.backgroundElem.style.transform = `rotate(${rotationDeg}deg)`;
|
204
228
|
this.backgroundElem.style.transformOrigin = 'center';
|
229
|
+
// If closer to perpendicular, apply different CSS
|
230
|
+
const perpendicularClassName = `${cssPrefix}rotated-near-perpendicular`;
|
231
|
+
if (Math.abs(Math.sin(this.screenRegionRotation)) > 0.5) {
|
232
|
+
this.container.classList.add(perpendicularClassName);
|
233
|
+
}
|
234
|
+
else {
|
235
|
+
this.container.classList.remove(perpendicularClassName);
|
236
|
+
}
|
205
237
|
for (const handle of this.handles) {
|
206
238
|
handle.updatePosition();
|
207
239
|
}
|
@@ -373,6 +405,7 @@ class Selection {
|
|
373
405
|
}
|
374
406
|
setToPoint(point) {
|
375
407
|
this.originalRegion = this.originalRegion.grownToPoint(point);
|
408
|
+
this.selectionTightBoundingBox = null;
|
376
409
|
this.updateUI();
|
377
410
|
}
|
378
411
|
cancelSelection() {
|
@@ -380,12 +413,15 @@ class Selection {
|
|
380
413
|
this.container.remove();
|
381
414
|
}
|
382
415
|
this.originalRegion = Rect2.empty;
|
416
|
+
this.selectionTightBoundingBox = null;
|
383
417
|
this.hasParent = false;
|
384
418
|
}
|
385
419
|
setSelectedObjects(objects, bbox) {
|
386
420
|
this.addRemoveSelectionFromImage(true);
|
387
421
|
this.originalRegion = bbox;
|
422
|
+
this.selectionTightBoundingBox = bbox;
|
388
423
|
this.selectedElems = objects.filter(object => object.isSelectable());
|
424
|
+
this.padRegion();
|
389
425
|
this.updateUI();
|
390
426
|
}
|
391
427
|
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,16 +1,22 @@
|
|
1
1
|
import { assertUnreachable } from '../../util/assertions.mjs';
|
2
2
|
import { Rect2, Vec2 } from '@js-draw/math';
|
3
3
|
import { cssPrefix } from './SelectionTool.mjs';
|
4
|
-
|
4
|
+
var HandleShape;
|
5
5
|
(function (HandleShape) {
|
6
6
|
HandleShape[HandleShape["Circle"] = 0] = "Circle";
|
7
7
|
HandleShape[HandleShape["Square"] = 1] = "Square";
|
8
8
|
})(HandleShape || (HandleShape = {}));
|
9
|
+
export var HandleAction;
|
10
|
+
(function (HandleAction) {
|
11
|
+
HandleAction["ResizeXY"] = "resize-xy";
|
12
|
+
HandleAction["Rotate"] = "rotate";
|
13
|
+
HandleAction["ResizeX"] = "resize-x";
|
14
|
+
HandleAction["ResizeY"] = "resize-y";
|
15
|
+
})(HandleAction || (HandleAction = {}));
|
9
16
|
export const handleSize = 30;
|
10
17
|
export default class SelectionHandle {
|
11
|
-
constructor(
|
12
|
-
this.
|
13
|
-
this.parentSide = parentSide;
|
18
|
+
constructor(presentation, parent, viewport, onDragStart, onDragUpdate, onDragEnd) {
|
19
|
+
this.presentation = presentation;
|
14
20
|
this.parent = parent;
|
15
21
|
this.viewport = viewport;
|
16
22
|
this.onDragStart = onDragStart;
|
@@ -18,8 +24,20 @@ export default class SelectionHandle {
|
|
18
24
|
this.onDragEnd = onDragEnd;
|
19
25
|
this.dragLastPos = null;
|
20
26
|
this.element = document.createElement('div');
|
21
|
-
this.element.classList.add(`${cssPrefix}handle`);
|
22
|
-
|
27
|
+
this.element.classList.add(`${cssPrefix}handle`, `${cssPrefix}${presentation.action}`);
|
28
|
+
this.parentSide = presentation.side;
|
29
|
+
const icon = presentation.icon;
|
30
|
+
if (icon) {
|
31
|
+
this.element.appendChild(icon);
|
32
|
+
icon.classList.add('icon');
|
33
|
+
}
|
34
|
+
if (presentation.action === HandleAction.Rotate) {
|
35
|
+
this.shape = HandleShape.Circle;
|
36
|
+
}
|
37
|
+
else {
|
38
|
+
this.shape = HandleShape.Square;
|
39
|
+
}
|
40
|
+
switch (this.shape) {
|
23
41
|
case HandleShape.Circle:
|
24
42
|
this.element.classList.add(`${cssPrefix}circle`);
|
25
43
|
break;
|
@@ -27,7 +45,7 @@ export default class SelectionHandle {
|
|
27
45
|
this.element.classList.add(`${cssPrefix}square`);
|
28
46
|
break;
|
29
47
|
default:
|
30
|
-
assertUnreachable(shape);
|
48
|
+
assertUnreachable(this.shape);
|
31
49
|
}
|
32
50
|
this.updatePosition();
|
33
51
|
}
|
@@ -27,6 +27,11 @@ class SelectionTool extends BaseTool {
|
|
27
27
|
// The selection box could be using the wet ink display if its transformation
|
28
28
|
// hasn't been finalized yet. Clear before updating the UI.
|
29
29
|
this.editor.clearWetInk();
|
30
|
+
// If not currently selecting, ensure that the selection box
|
31
|
+
// is large enough.
|
32
|
+
if (!this.expandingSelectionBox) {
|
33
|
+
this.selectionBox?.padRegion();
|
34
|
+
}
|
30
35
|
this.selectionBox?.updateUI();
|
31
36
|
});
|
32
37
|
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;
|
@@ -100,6 +100,9 @@ export default class SoundUITool extends BaseTool {
|
|
100
100
|
this.updateToggleButtonText();
|
101
101
|
editor.createHTMLOverlay(this.toggleButtonContainer);
|
102
102
|
}
|
103
|
+
canReceiveInputInReadOnlyEditor() {
|
104
|
+
return true;
|
105
|
+
}
|
103
106
|
updateToggleButtonText() {
|
104
107
|
const containerEnabledClass = 'sound-ui-tool-enabled';
|
105
108
|
if (this.isEnabled()) {
|
@@ -113,7 +116,7 @@ export default class SoundUITool extends BaseTool {
|
|
113
116
|
}
|
114
117
|
setEnabled(enabled) {
|
115
118
|
super.setEnabled(enabled);
|
116
|
-
if (!
|
119
|
+
if (!this.isEnabled()) {
|
117
120
|
this.soundFeedback?.close();
|
118
121
|
this.soundFeedback = null;
|
119
122
|
}
|