js-draw 1.23.1 → 1.24.1
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/dist/Editor.css +21 -0
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.d.ts +7 -1
- package/dist/cjs/Editor.js +71 -9
- package/dist/cjs/SVGLoader/SVGLoader.js +17 -7
- package/dist/cjs/Viewport.d.ts +2 -0
- package/dist/cjs/Viewport.js +0 -1
- package/dist/cjs/components/AbstractComponent.d.ts +1 -1
- package/dist/cjs/components/BackgroundComponent.js +17 -7
- package/dist/cjs/components/SVGGlobalAttributesObject.js +17 -7
- package/dist/cjs/components/UnknownSVGObject.js +17 -7
- package/dist/cjs/components/lib.js +17 -7
- package/dist/cjs/image/EditorImage.js +17 -7
- package/dist/cjs/testing/sendPenEvent.js +17 -7
- package/dist/cjs/testing/sendTouchEvent.js +17 -7
- package/dist/cjs/toolbar/EdgeToolbar.d.ts +1 -1
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +17 -7
- package/dist/cjs/toolbar/widgets/HandToolWidget.js +17 -7
- package/dist/cjs/tools/InputFilter/ContextMenuRecognizer.js +17 -7
- package/dist/cjs/tools/Pen.js +17 -7
- package/dist/cjs/tools/SelectionTool/Selection.js +17 -7
- package/dist/cjs/tools/SelectionTool/SelectionMenuShortcut.js +1 -1
- package/dist/cjs/tools/SelectionTool/util/makeClipboardErrorHandlers.d.ts +2 -2
- package/dist/cjs/tools/SelectionTool/util/makeClipboardErrorHandlers.js +1 -1
- package/dist/cjs/tools/SoundUITool.js +1 -1
- package/dist/cjs/tools/TextTool.d.ts +4 -4
- package/dist/cjs/tools/TextTool.js +45 -51
- package/dist/cjs/tools/ToolController.js +17 -7
- package/dist/cjs/tools/UndoRedoShortcut.js +2 -2
- package/dist/cjs/util/ClipboardHandler.js +1 -0
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +7 -1
- package/dist/mjs/Editor.mjs +54 -2
- package/dist/mjs/Viewport.d.ts +2 -0
- package/dist/mjs/Viewport.mjs +0 -1
- package/dist/mjs/components/AbstractComponent.d.ts +1 -1
- package/dist/mjs/toolbar/EdgeToolbar.d.ts +1 -1
- package/dist/mjs/tools/SelectionTool/SelectionMenuShortcut.mjs +1 -1
- package/dist/mjs/tools/SelectionTool/util/makeClipboardErrorHandlers.d.ts +2 -2
- package/dist/mjs/tools/SelectionTool/util/makeClipboardErrorHandlers.mjs +1 -1
- package/dist/mjs/tools/SoundUITool.mjs +1 -1
- package/dist/mjs/tools/TextTool.d.ts +4 -4
- package/dist/mjs/tools/TextTool.mjs +45 -51
- package/dist/mjs/tools/UndoRedoShortcut.mjs +2 -2
- package/dist/mjs/util/ClipboardHandler.mjs +1 -0
- package/dist/mjs/version.mjs +1 -1
- package/package.json +4 -4
- package/src/Editor.scss +31 -0
package/dist/mjs/Editor.mjs
CHANGED
@@ -25,7 +25,7 @@ import guessKeyCodeFromKey from './util/guessKeyCodeFromKey.mjs';
|
|
25
25
|
import makeAboutDialog from './dialogs/makeAboutDialog.mjs';
|
26
26
|
import version from './version.mjs';
|
27
27
|
import { editorImageToSVGSync, editorImageToSVGAsync } from './image/export/editorImageToSVG.mjs';
|
28
|
-
import { MutableReactiveValue } from './util/ReactiveValue.mjs';
|
28
|
+
import ReactiveValue, { MutableReactiveValue } from './util/ReactiveValue.mjs';
|
29
29
|
import listenForKeyboardEventsFrom from './util/listenForKeyboardEventsFrom.mjs';
|
30
30
|
import mitLicenseAttribution from './util/mitLicenseAttribution.mjs';
|
31
31
|
import ClipboardHandler from './util/ClipboardHandler.mjs';
|
@@ -473,7 +473,7 @@ export class Editor {
|
|
473
473
|
/** @internal */
|
474
474
|
async handleDrop(evt) {
|
475
475
|
evt.preventDefault();
|
476
|
-
this.handlePaste(evt);
|
476
|
+
await this.handlePaste(evt);
|
477
477
|
}
|
478
478
|
/** @internal */
|
479
479
|
async handlePaste(evt) {
|
@@ -884,6 +884,58 @@ export class Editor {
|
|
884
884
|
remove: () => overlay.remove(),
|
885
885
|
};
|
886
886
|
}
|
887
|
+
/**
|
888
|
+
* Anchors the given `element` to the canvas with a given position/transformation in canvas space.
|
889
|
+
*/
|
890
|
+
anchorElementToCanvas(element, canvasTransform) {
|
891
|
+
if (canvasTransform instanceof Mat33) {
|
892
|
+
canvasTransform = ReactiveValue.fromImmutable(canvasTransform);
|
893
|
+
}
|
894
|
+
// The element hierarchy looks like this:
|
895
|
+
// overlay > contentWrapper > content
|
896
|
+
//
|
897
|
+
// Both contentWrapper and overlay are present to:
|
898
|
+
// 1. overlay: Positions the content at the top left of the viewport. The overlay
|
899
|
+
// has `height: 0` to allow other overlays to also be aligned with the viewport's
|
900
|
+
// top left.
|
901
|
+
// 2. contentWrapper: Has the same width/height as the editor's visible region and
|
902
|
+
// has `overflow: hidden`. This prevents the anchored element from being visible
|
903
|
+
// when not in the visible region of the canvas.
|
904
|
+
const overlay = document.createElement('div');
|
905
|
+
overlay.classList.add('anchored-element-overlay');
|
906
|
+
const contentWrapper = document.createElement('div');
|
907
|
+
contentWrapper.classList.add('content-wrapper');
|
908
|
+
element.classList.add('content');
|
909
|
+
// Updates CSS variables that specify the position/rotation/scale of the content.
|
910
|
+
const updateElementPositioning = () => {
|
911
|
+
const transform = canvasTransform.get();
|
912
|
+
const canvasRotation = transform.transformVec3(Vec2.unitX).angle();
|
913
|
+
const screenRotation = canvasRotation + this.viewport.getRotationAngle();
|
914
|
+
const screenTransform = this.viewport.canvasToScreenTransform.rightMul(canvasTransform.get());
|
915
|
+
overlay.style.setProperty('--full-transform', screenTransform.toCSSMatrix());
|
916
|
+
const translation = screenTransform.transformVec2(Vec2.zero);
|
917
|
+
overlay.style.setProperty('--position-x', `${translation.x}px`);
|
918
|
+
overlay.style.setProperty('--position-y', `${translation.y}px`);
|
919
|
+
overlay.style.setProperty('--rotation', `${(screenRotation * 180) / Math.PI}deg`);
|
920
|
+
overlay.style.setProperty('--scale', `${screenTransform.getScaleFactor()}`);
|
921
|
+
};
|
922
|
+
updateElementPositioning();
|
923
|
+
// The anchored element needs to be updated both when the user moves the canvas
|
924
|
+
// and when the anchored element's transform changes.
|
925
|
+
const updateListener = canvasTransform.onUpdate(updateElementPositioning);
|
926
|
+
const viewportListener = this.notifier.on(EditorEventType.ViewportChanged, updateElementPositioning);
|
927
|
+
contentWrapper.appendChild(element);
|
928
|
+
overlay.appendChild(contentWrapper);
|
929
|
+
overlay.classList.add('overlay', 'js-draw-editor-overlay');
|
930
|
+
this.renderingRegion.insertAdjacentElement('afterend', overlay);
|
931
|
+
return {
|
932
|
+
remove: () => {
|
933
|
+
overlay.remove();
|
934
|
+
updateListener.remove();
|
935
|
+
viewportListener.remove();
|
936
|
+
},
|
937
|
+
};
|
938
|
+
}
|
887
939
|
/**
|
888
940
|
* Creates a CSS stylesheet with `content` and applies it to the document
|
889
941
|
* (and thus, to this editor).
|
package/dist/mjs/Viewport.d.ts
CHANGED
@@ -9,7 +9,9 @@ type TransformChangeCallback = (oldTransform: Mat33, newTransform: Mat33) => voi
|
|
9
9
|
export declare class Viewport {
|
10
10
|
private onTransformChangeCallback;
|
11
11
|
private static ViewportTransform;
|
12
|
+
/** Converts from canvas to screen coordinates */
|
12
13
|
private transform;
|
14
|
+
/** Converts from screen to canvas coordinates */
|
13
15
|
private inverseTransform;
|
14
16
|
private screenRect;
|
15
17
|
constructor(onTransformChangeCallback: TransformChangeCallback);
|
package/dist/mjs/Viewport.mjs
CHANGED
@@ -127,7 +127,6 @@ export class Viewport {
|
|
127
127
|
}
|
128
128
|
// The separate function type definition seems necessary here.
|
129
129
|
// See https://stackoverflow.com/a/58163623/17055750.
|
130
|
-
// eslint-disable-next-line no-dupe-class-members
|
131
130
|
static roundPoint(point, tolerance) {
|
132
131
|
const scaleFactor = 10 ** Math.floor(Math.log10(tolerance));
|
133
132
|
const roundComponent = (component) => {
|
@@ -163,5 +163,5 @@ export default abstract class AbstractComponent {
|
|
163
163
|
data: string | number | any[] | Record<string, any>;
|
164
164
|
};
|
165
165
|
private static isNotDeserializable;
|
166
|
-
static deserialize(json:
|
166
|
+
static deserialize(json: any): AbstractComponent;
|
167
167
|
}
|
@@ -49,7 +49,7 @@ export default class EdgeToolbar extends AbstractToolbar {
|
|
49
49
|
constructor(editor: Editor, parent: HTMLElement, localizationTable: ToolbarLocalization);
|
50
50
|
private listenForVisibilityChanges;
|
51
51
|
private onToolbarRowResize;
|
52
|
-
addSpacer(_options?: Partial<SpacerOptions>
|
52
|
+
addSpacer(_options?: Partial<SpacerOptions>): void;
|
53
53
|
addUndoRedoButtons(): void;
|
54
54
|
addDefaults(): void;
|
55
55
|
private updateWidgetCSSClasses;
|
@@ -10,7 +10,7 @@ export default class SelectionMenuShortcut {
|
|
10
10
|
this.element = document.createElement('div');
|
11
11
|
this.element.classList.add(`${cssPrefix}handle`, `${cssPrefix}selection-menu`);
|
12
12
|
this.element.style.setProperty('--vertical-offset', `${verticalOffset}px`);
|
13
|
-
this.onClick =
|
13
|
+
this.onClick = () => {
|
14
14
|
const anchor = this.getBBoxCanvasCoords().center;
|
15
15
|
showContextMenu(anchor);
|
16
16
|
};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import Editor from '../../../Editor';
|
2
2
|
declare const makeClipboardErrorHandlers: (editor: Editor) => {
|
3
|
-
onCopyError(error:
|
4
|
-
onPasteError(error:
|
3
|
+
onCopyError(error: unknown): void;
|
4
|
+
onPasteError(error: unknown): void;
|
5
5
|
};
|
6
6
|
export default makeClipboardErrorHandlers;
|
@@ -16,7 +16,7 @@ const makeClipboardErrorHandlers = (editor) => {
|
|
16
16
|
return dialog;
|
17
17
|
};
|
18
18
|
return {
|
19
|
-
|
19
|
+
onCopyError(error) {
|
20
20
|
const dialog = makeErrorDialog(error);
|
21
21
|
const textboxLabel = document.createElement('label');
|
22
22
|
textboxLabel.textContent = editor.localization.copyPasteError__copyRetry;
|
@@ -5,23 +5,22 @@ import BaseTool from './BaseTool';
|
|
5
5
|
import { ToolLocalization } from './localization';
|
6
6
|
import TextRenderingStyle from '../rendering/TextRenderingStyle';
|
7
7
|
import { MutableReactiveValue } from '../util/ReactiveValue';
|
8
|
+
/** A tool that allows users to enter and edit text. */
|
8
9
|
export default class TextTool extends BaseTool {
|
9
10
|
private editor;
|
10
11
|
private localizationTable;
|
11
12
|
private textStyleValue;
|
12
13
|
private textStyle;
|
14
|
+
private anchorControl;
|
15
|
+
private contentTransform;
|
13
16
|
private textEditOverlay;
|
14
17
|
private textInputElem;
|
15
|
-
private textTargetPosition;
|
16
18
|
private textMeasuringCtx;
|
17
|
-
private textRotation;
|
18
|
-
private textScale;
|
19
19
|
private removeExistingCommand;
|
20
20
|
constructor(editor: Editor, description: string, localizationTable: ToolLocalization);
|
21
21
|
private initTextMeasuringCanvas;
|
22
22
|
private getTextAscent;
|
23
23
|
private flushInput;
|
24
|
-
private getTextScaleMatrix;
|
25
24
|
private updateTextInput;
|
26
25
|
private startTextInput;
|
27
26
|
setEnabled(enabled: boolean): void;
|
@@ -33,4 +32,5 @@ export default class TextTool extends BaseTool {
|
|
33
32
|
getTextStyle(): TextRenderingStyle;
|
34
33
|
getStyleValue(): MutableReactiveValue<TextRenderingStyle>;
|
35
34
|
private setTextStyle;
|
35
|
+
onDestroy(): void;
|
36
36
|
}
|
@@ -8,15 +8,14 @@ import Erase from '../commands/Erase.mjs';
|
|
8
8
|
import uniteCommands from '../commands/uniteCommands.mjs';
|
9
9
|
import { ReactiveValue } from '../util/ReactiveValue.mjs';
|
10
10
|
const overlayCSSClass = 'textEditorOverlay';
|
11
|
+
/** A tool that allows users to enter and edit text. */
|
11
12
|
export default class TextTool extends BaseTool {
|
12
13
|
constructor(editor, description, localizationTable) {
|
13
14
|
super(editor.notifier, description);
|
14
15
|
this.editor = editor;
|
15
16
|
this.localizationTable = localizationTable;
|
16
17
|
this.textInputElem = null;
|
17
|
-
this.textTargetPosition = null;
|
18
18
|
this.textMeasuringCtx = null;
|
19
|
-
this.textScale = Vec2.of(1, 1);
|
20
19
|
this.removeExistingCommand = null;
|
21
20
|
const editorFonts = editor.getCurrentSettings().text?.fonts ?? [];
|
22
21
|
this.textStyleValue = ReactiveValue.fromInitialValue({
|
@@ -34,18 +33,10 @@ export default class TextTool extends BaseTool {
|
|
34
33
|
tool: this,
|
35
34
|
});
|
36
35
|
});
|
36
|
+
this.contentTransform = ReactiveValue.fromInitialValue(Mat33.identity);
|
37
37
|
this.textEditOverlay = document.createElement('div');
|
38
38
|
this.textEditOverlay.classList.add(overlayCSSClass);
|
39
39
|
this.editor.addStyleSheet(`
|
40
|
-
.${overlayCSSClass} {
|
41
|
-
height: 0;
|
42
|
-
overflow: visible;
|
43
|
-
|
44
|
-
/* Allows absolutely-positioned textareas to scroll with
|
45
|
-
the containing overlay. */
|
46
|
-
position: relative;
|
47
|
-
}
|
48
|
-
|
49
40
|
.${overlayCSSClass} textarea {
|
50
41
|
background-color: rgba(0, 0, 0, 0);
|
51
42
|
|
@@ -61,8 +52,7 @@ export default class TextTool extends BaseTool {
|
|
61
52
|
min-height: 1.1em;
|
62
53
|
}
|
63
54
|
`);
|
64
|
-
this.editor.
|
65
|
-
this.editor.notifier.on(EditorEventType.ViewportChanged, () => this.updateTextInput());
|
55
|
+
this.anchorControl = this.editor.anchorElementToCanvas(this.textEditOverlay, this.contentTransform);
|
66
56
|
}
|
67
57
|
initTextMeasuringCanvas() {
|
68
58
|
this.textMeasuringCtx ??= document.createElement('canvas').getContext('2d');
|
@@ -82,24 +72,32 @@ export default class TextTool extends BaseTool {
|
|
82
72
|
// If [removeInput], the HTML input element is removed. Otherwise, its value
|
83
73
|
// is cleared.
|
84
74
|
flushInput(removeInput = true) {
|
85
|
-
if (this.textInputElem
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
75
|
+
if (!this.textInputElem)
|
76
|
+
return;
|
77
|
+
// Determine the scroll first -- removing the input (and other DOM changes)
|
78
|
+
// also change the scroll.
|
79
|
+
const scrollingRegion = this.textEditOverlay.parentElement;
|
80
|
+
const containerScroll = Vec2.of(scrollingRegion?.scrollLeft ?? 0, scrollingRegion?.scrollTop ?? 0);
|
81
|
+
const content = this.textInputElem.value.trimEnd();
|
82
|
+
this.textInputElem.value = '';
|
83
|
+
if (removeInput) {
|
84
|
+
// In some browsers, .remove() triggers a .blur event (synchronously).
|
85
|
+
// Clear this.textInputElem before removal
|
86
|
+
const input = this.textInputElem;
|
87
|
+
this.textInputElem = null;
|
88
|
+
input.remove();
|
89
|
+
}
|
90
|
+
if (content !== '') {
|
91
|
+
// When the text is long, it can cause its container to scroll so that the
|
92
|
+
// editing caret is in view.
|
93
|
+
// So that the text added to the document is in the same position as the text
|
94
|
+
// shown in the editor, account for this scroll when computing the transform:
|
95
|
+
const scrollCorrectionScreen = containerScroll.times(-1);
|
96
|
+
// Uses .transformVec3 to avoid also translating the scroll correction (treating
|
97
|
+
// it as a point):
|
98
|
+
const scrollCorrectionCanvas = this.editor.viewport.screenToCanvasTransform.transformVec3(scrollCorrectionScreen);
|
99
|
+
const scrollTransform = Mat33.translation(scrollCorrectionCanvas);
|
100
|
+
const textComponent = TextComponent.fromLines(content.split('\n'), scrollTransform.rightMul(this.contentTransform.get()), this.textStyle);
|
103
101
|
const action = EditorImage.addElement(textComponent);
|
104
102
|
if (this.removeExistingCommand) {
|
105
103
|
// Unapply so that `removeExistingCommand` can be added to the undo stack.
|
@@ -112,16 +110,10 @@ export default class TextTool extends BaseTool {
|
|
112
110
|
}
|
113
111
|
}
|
114
112
|
}
|
115
|
-
getTextScaleMatrix() {
|
116
|
-
return Mat33.scaling2D(this.textScale.times(1 / this.editor.viewport.getSizeOfPixelOnCanvas()));
|
117
|
-
}
|
118
113
|
updateTextInput() {
|
119
|
-
if (!this.textInputElem
|
120
|
-
this.textInputElem?.remove();
|
114
|
+
if (!this.textInputElem) {
|
121
115
|
return;
|
122
116
|
}
|
123
|
-
const viewport = this.editor.viewport;
|
124
|
-
const textScreenPos = viewport.canvasToScreen(this.textTargetPosition);
|
125
117
|
this.textInputElem.placeholder = this.localizationTable.enterTextToInsert;
|
126
118
|
this.textInputElem.style.fontFamily = this.textStyle.fontFamily;
|
127
119
|
this.textInputElem.style.fontStyle = this.textStyle.fontStyle ?? '';
|
@@ -129,9 +121,6 @@ export default class TextTool extends BaseTool {
|
|
129
121
|
this.textInputElem.style.fontWeight = this.textStyle.fontWeight ?? '';
|
130
122
|
this.textInputElem.style.fontSize = `${this.textStyle.size}px`;
|
131
123
|
this.textInputElem.style.color = this.textStyle.renderingStyle.fill.toHexString();
|
132
|
-
this.textInputElem.style.position = 'absolute';
|
133
|
-
this.textInputElem.style.left = `${textScreenPos.x}px`;
|
134
|
-
this.textInputElem.style.top = `${textScreenPos.y}px`;
|
135
124
|
this.textInputElem.style.margin = '0';
|
136
125
|
this.textInputElem.style.width = `${this.textInputElem.scrollWidth}px`;
|
137
126
|
this.textInputElem.style.height = `${this.textInputElem.scrollHeight}px`;
|
@@ -140,9 +129,7 @@ export default class TextTool extends BaseTool {
|
|
140
129
|
const tallText = 'Testing!';
|
141
130
|
const ascent = this.getTextAscent(tallText, this.textStyle);
|
142
131
|
const vertAdjust = ascent;
|
143
|
-
|
144
|
-
const scale = this.getTextScaleMatrix();
|
145
|
-
this.textInputElem.style.transform = `${scale.toCSSMatrix()} rotate(${(rotation * 180) / Math.PI}deg) translate(0, ${-vertAdjust}px)`;
|
132
|
+
this.textInputElem.style.transform = `translate(0, ${-vertAdjust}px)`;
|
146
133
|
this.textInputElem.style.transformOrigin = 'top left';
|
147
134
|
// Match the line height of default rendered text.
|
148
135
|
const lineHeight = Math.floor(this.textStyle.size);
|
@@ -153,9 +140,14 @@ export default class TextTool extends BaseTool {
|
|
153
140
|
this.textInputElem = document.createElement('textarea');
|
154
141
|
this.textInputElem.value = initialText;
|
155
142
|
this.textInputElem.style.display = 'inline-block';
|
156
|
-
|
157
|
-
|
158
|
-
|
143
|
+
const textTargetPosition = this.editor.viewport.roundPoint(textCanvasPos);
|
144
|
+
const textRotation = -this.editor.viewport.getRotationAngle();
|
145
|
+
const textScale = Vec2.of(1, 1).times(this.editor.viewport.getSizeOfPixelOnCanvas());
|
146
|
+
this.contentTransform.set(
|
147
|
+
// Scale, then rotate, then translate:
|
148
|
+
Mat33.translation(textTargetPosition)
|
149
|
+
.rightMul(Mat33.zRotation(textRotation))
|
150
|
+
.rightMul(Mat33.scaling2D(textScale)));
|
159
151
|
this.updateTextInput();
|
160
152
|
// Update the input size/position/etc. after the placeHolder has had time to appear.
|
161
153
|
setTimeout(() => this.updateTextInput(), 0);
|
@@ -224,10 +216,7 @@ export default class TextTool extends BaseTool {
|
|
224
216
|
this.removeExistingCommand = new Erase([targetNode]);
|
225
217
|
this.removeExistingCommand.apply(this.editor);
|
226
218
|
this.startTextInput(targetNode.getBaselinePos(), targetNode.getText());
|
227
|
-
|
228
|
-
this.textRotation = transform.transformVec3(Vec2.unitX).angle();
|
229
|
-
const scaleFactor = transform.transformVec3(Vec2.unitX).magnitude();
|
230
|
-
this.textScale = Vec2.of(1, 1).times(scaleFactor);
|
219
|
+
this.contentTransform.set(targetNode.getTransform());
|
231
220
|
this.updateTextInput();
|
232
221
|
}
|
233
222
|
else {
|
@@ -278,4 +267,9 @@ export default class TextTool extends BaseTool {
|
|
278
267
|
setTextStyle(style) {
|
279
268
|
this.textStyleValue.set(style);
|
280
269
|
}
|
270
|
+
// @internal
|
271
|
+
onDestroy() {
|
272
|
+
super.onDestroy();
|
273
|
+
this.anchorControl.remove();
|
274
|
+
}
|
281
275
|
}
|
@@ -9,11 +9,11 @@ export default class UndoRedoShortcut extends BaseTool {
|
|
9
9
|
// @internal
|
10
10
|
onKeyPress(event) {
|
11
11
|
if (this.editor.shortcuts.matchesShortcut(undoKeyboardShortcutId, event)) {
|
12
|
-
this.editor.history.undo();
|
12
|
+
void this.editor.history.undo();
|
13
13
|
return true;
|
14
14
|
}
|
15
15
|
else if (this.editor.shortcuts.matchesShortcut(redoKeyboardShortcutId, event)) {
|
16
|
-
this.editor.history.redo();
|
16
|
+
void this.editor.history.redo();
|
17
17
|
return true;
|
18
18
|
}
|
19
19
|
return false;
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-redundant-type-constituents -- Used for clarity */
|
1
2
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
2
3
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
3
4
|
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");
|
package/dist/mjs/version.mjs
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "js-draw",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.24.1",
|
4
4
|
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
|
5
5
|
"types": "./dist/mjs/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/lib.js",
|
@@ -64,11 +64,11 @@
|
|
64
64
|
"postpack": "ts-node tools/copyREADME.ts revert"
|
65
65
|
},
|
66
66
|
"dependencies": {
|
67
|
-
"@js-draw/math": "^1.
|
67
|
+
"@js-draw/math": "^1.24.1",
|
68
68
|
"@melloware/coloris": "0.22.0"
|
69
69
|
},
|
70
70
|
"devDependencies": {
|
71
|
-
"@js-draw/build-tool": "^1.
|
71
|
+
"@js-draw/build-tool": "^1.24.1",
|
72
72
|
"@types/jest": "29.5.5",
|
73
73
|
"@types/jsdom": "21.1.3"
|
74
74
|
},
|
@@ -86,5 +86,5 @@
|
|
86
86
|
"freehand",
|
87
87
|
"svg"
|
88
88
|
],
|
89
|
-
"gitHead": "
|
89
|
+
"gitHead": "ef847374748e32d6d96d993a2236a99d9109a32c"
|
90
90
|
}
|
package/src/Editor.scss
CHANGED
@@ -165,6 +165,37 @@
|
|
165
165
|
z-index: 5;
|
166
166
|
}
|
167
167
|
|
168
|
+
// See Editor.anchorElementToCanvas
|
169
|
+
.imageEditorContainer .anchored-element-overlay {
|
170
|
+
overflow: visible;
|
171
|
+
height: 0;
|
172
|
+
|
173
|
+
> .content-wrapper {
|
174
|
+
width: var(--editor-current-display-width-px);
|
175
|
+
height: var(--editor-current-display-height-px);
|
176
|
+
overflow: hidden;
|
177
|
+
// Display 'position: absolute' children relative to this.
|
178
|
+
position: relative;
|
179
|
+
|
180
|
+
// Disable pointer events: If the parent (or the container) has
|
181
|
+
// captured pointers and the container is removed, this prevents
|
182
|
+
// us from receiving the following events (e.g. in Firefox).
|
183
|
+
pointer-events: none;
|
184
|
+
|
185
|
+
> .content {
|
186
|
+
position: absolute;
|
187
|
+
left: var(--position-x);
|
188
|
+
top: var(--position-y);
|
189
|
+
transform: scale(var(--scale)) rotate(var(--rotation));
|
190
|
+
transform-origin: left top;
|
191
|
+
margin: 0;
|
192
|
+
|
193
|
+
// We *do* want pointer events for the positioned content.
|
194
|
+
pointer-events: all;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
168
199
|
// TODO: Apply this change during a future major release.
|
169
200
|
// So as not to change the position of other overlays, all overlays should have
|
170
201
|
// 0 height.
|