js-draw 0.21.0 → 0.22.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/CHANGELOG.md +10 -1
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/src/Color4.js +2 -2
- package/dist/cjs/src/Editor.d.ts +1 -3
- package/dist/cjs/src/EditorImage.js +8 -2
- package/dist/cjs/src/Viewport.js +1 -1
- package/dist/cjs/src/commands/Command.js +1 -1
- package/dist/cjs/src/commands/SerializableCommand.js +1 -1
- package/dist/cjs/src/components/AbstractComponent.js +6 -1
- package/dist/cjs/src/components/TextComponent.js +1 -1
- package/dist/cjs/src/localizations/de.js +1 -1
- package/dist/cjs/src/math/Mat33.js +1 -1
- package/dist/cjs/src/math/Path.js +1 -1
- package/dist/cjs/src/math/Rect2.js +1 -1
- package/dist/cjs/src/math/Vec3.js +1 -1
- package/dist/cjs/src/rendering/Display.d.ts +1 -1
- package/dist/cjs/src/rendering/Display.js +1 -2
- package/dist/cjs/src/toolbar/HTMLToolbar.d.ts +2 -0
- package/dist/cjs/src/toolbar/HTMLToolbar.js +71 -12
- package/dist/cjs/src/toolbar/widgets/BaseToolWidget.d.ts +0 -1
- package/dist/cjs/src/toolbar/widgets/BaseToolWidget.js +0 -1
- package/dist/cjs/src/toolbar/widgets/BaseWidget.d.ts +5 -0
- package/dist/cjs/src/toolbar/widgets/BaseWidget.js +17 -5
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.js +1 -1
- package/dist/cjs/src/toolbar/widgets/EraserToolWidget.js +1 -1
- package/dist/cjs/src/toolbar/widgets/InsertImageWidget.js +1 -1
- package/dist/cjs/src/toolbar/widgets/PenToolWidget.js +1 -1
- package/dist/cjs/src/toolbar/widgets/TextToolWidget.js +1 -1
- package/dist/cjs/src/tools/SelectionTool/Selection.js +5 -2
- package/dist/cjs/src/tools/SelectionTool/SelectionTool.js +1 -1
- package/dist/cjs/src/types.d.ts +2 -0
- package/dist/mjs/src/Color4.mjs +2 -1
- package/dist/mjs/src/Editor.d.ts +1 -3
- package/dist/mjs/src/EditorImage.mjs +10 -2
- package/dist/mjs/src/Viewport.mjs +2 -1
- package/dist/mjs/src/commands/Command.mjs +2 -1
- package/dist/mjs/src/commands/SerializableCommand.mjs +2 -1
- package/dist/mjs/src/components/AbstractComponent.mjs +7 -1
- package/dist/mjs/src/components/TextComponent.mjs +2 -1
- package/dist/mjs/src/localizations/de.mjs +1 -1
- package/dist/mjs/src/math/Mat33.mjs +2 -1
- package/dist/mjs/src/math/Path.mjs +2 -1
- package/dist/mjs/src/math/Rect2.mjs +2 -1
- package/dist/mjs/src/math/Vec3.mjs +2 -1
- package/dist/mjs/src/rendering/Display.d.ts +1 -1
- package/dist/mjs/src/rendering/Display.mjs +1 -2
- package/dist/mjs/src/toolbar/HTMLToolbar.d.ts +2 -0
- package/dist/mjs/src/toolbar/HTMLToolbar.mjs +72 -12
- package/dist/mjs/src/toolbar/widgets/BaseToolWidget.d.ts +0 -1
- package/dist/mjs/src/toolbar/widgets/BaseToolWidget.mjs +0 -1
- package/dist/mjs/src/toolbar/widgets/BaseWidget.d.ts +5 -0
- package/dist/mjs/src/toolbar/widgets/BaseWidget.mjs +17 -5
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.mjs +2 -1
- package/dist/mjs/src/toolbar/widgets/EraserToolWidget.mjs +2 -1
- package/dist/mjs/src/toolbar/widgets/InsertImageWidget.mjs +2 -1
- package/dist/mjs/src/toolbar/widgets/PenToolWidget.mjs +2 -1
- package/dist/mjs/src/toolbar/widgets/TextToolWidget.mjs +2 -1
- package/dist/mjs/src/tools/SelectionTool/Selection.mjs +6 -2
- package/dist/mjs/src/tools/SelectionTool/SelectionTool.mjs +2 -1
- package/dist/mjs/src/types.d.ts +2 -0
- package/package.json +12 -12
- package/src/toolbar/toolbar.css +7 -0
- package/tsconfig-typedoc.json +7 -0
- package/tsconfig.json +2 -0
- package/typedoc.json +1 -0
@@ -153,6 +153,9 @@ class Selection {
|
|
153
153
|
this.transform = Mat33_1.default.identity;
|
154
154
|
// Make the commands undo-able
|
155
155
|
this.editor.dispatch(new Selection.ApplyTransformationCommand(this, selectedElems, fullTransform));
|
156
|
+
// Clear renderings of any in-progress transformations
|
157
|
+
const wetInkRenderer = this.editor.display.getWetInkRenderer();
|
158
|
+
wetInkRenderer.clear();
|
156
159
|
}
|
157
160
|
// Preview the effects of the current transformation on the selection
|
158
161
|
previewTransformCmds() {
|
@@ -406,7 +409,6 @@ class Selection {
|
|
406
409
|
return this.selectedElems;
|
407
410
|
}
|
408
411
|
}
|
409
|
-
exports.default = Selection;
|
410
412
|
_a = Selection;
|
411
413
|
(() => {
|
412
414
|
SerializableCommand_1.default.register('selection-tool-transform', (json, _editor) => {
|
@@ -471,7 +473,7 @@ Selection.ApplyTransformationCommand = class extends SerializableCommand_1.defau
|
|
471
473
|
(_b = this.selection) === null || _b === void 0 ? void 0 : _b.setTransform(this.fullTransform.inverse(), false);
|
472
474
|
(_c = this.selection) === null || _c === void 0 ? void 0 : _c.updateUI();
|
473
475
|
yield editor.asyncUnapplyCommands(this.transformCommands, updateChunkSize, true);
|
474
|
-
(_d = this.selection) === null || _d === void 0 ? void 0 : _d.setTransform(Mat33_1.default.identity);
|
476
|
+
(_d = this.selection) === null || _d === void 0 ? void 0 : _d.setTransform(Mat33_1.default.identity, false);
|
475
477
|
(_e = this.selection) === null || _e === void 0 ? void 0 : _e.recomputeRegion();
|
476
478
|
(_f = this.selection) === null || _f === void 0 ? void 0 : _f.updateUI();
|
477
479
|
});
|
@@ -486,3 +488,4 @@ Selection.ApplyTransformationCommand = class extends SerializableCommand_1.defau
|
|
486
488
|
return localizationTable.transformedElements(this.selectedElemIds.length);
|
487
489
|
}
|
488
490
|
};
|
491
|
+
exports.default = Selection;
|
@@ -393,7 +393,6 @@ class SelectionTool extends BaseTool_1.default {
|
|
393
393
|
this.onSelectionUpdated();
|
394
394
|
}
|
395
395
|
}
|
396
|
-
exports.default = SelectionTool;
|
397
396
|
SelectionTool.handleableKeys = [
|
398
397
|
'a', 'h', 'ArrowLeft',
|
399
398
|
'd', 'l', 'ArrowRight',
|
@@ -403,3 +402,4 @@ SelectionTool.handleableKeys = [
|
|
403
402
|
'i', 'I', 'o', 'O',
|
404
403
|
'Control', 'Meta',
|
405
404
|
];
|
405
|
+
exports.default = SelectionTool;
|
package/dist/cjs/src/types.d.ts
CHANGED
@@ -9,6 +9,8 @@ import Pointer from './Pointer';
|
|
9
9
|
import Color4 from './Color4';
|
10
10
|
import Command from './commands/Command';
|
11
11
|
import BaseWidget from './toolbar/widgets/BaseWidget';
|
12
|
+
export type HTMLPointerEventName = 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel';
|
13
|
+
export type HTMLPointerEventFilter = (eventName: HTMLPointerEventName, event: PointerEvent) => boolean;
|
12
14
|
export interface PointerEvtListener {
|
13
15
|
onPointerDown(event: PointerEvt): boolean;
|
14
16
|
onPointerMove(event: PointerEvt): void;
|
package/dist/mjs/src/Color4.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import Vec3 from './math/Vec3.mjs';
|
2
|
-
|
2
|
+
class Color4 {
|
3
3
|
constructor(
|
4
4
|
/** Red component. Should be in the range [0, 1]. */
|
5
5
|
r,
|
@@ -254,4 +254,5 @@ Color4.clay = Color4.ofRGB(0.8, 0.4, 0.2);
|
|
254
254
|
Color4.black = Color4.ofRGB(0, 0, 0);
|
255
255
|
Color4.gray = Color4.ofRGB(0.5, 0.5, 0.5);
|
256
256
|
Color4.white = Color4.ofRGB(1, 1, 1);
|
257
|
+
export default Color4;
|
257
258
|
export { Color4 };
|
package/dist/mjs/src/Editor.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import EditorImage from './EditorImage';
|
2
2
|
import ToolController from './tools/ToolController';
|
3
|
-
import { InputEvtType, EditorNotifier, ImageLoader } from './types';
|
3
|
+
import { InputEvtType, EditorNotifier, ImageLoader, HTMLPointerEventFilter } from './types';
|
4
4
|
import Command from './commands/Command';
|
5
5
|
import UndoRedoHistory from './UndoRedoHistory';
|
6
6
|
import Viewport from './Viewport';
|
@@ -14,8 +14,6 @@ import Rect2 from './math/Rect2';
|
|
14
14
|
import { EditorLocalization } from './localization';
|
15
15
|
import IconProvider from './toolbar/IconProvider';
|
16
16
|
import AbstractComponent from './components/AbstractComponent';
|
17
|
-
type HTMLPointerEventType = 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel';
|
18
|
-
type HTMLPointerEventFilter = (eventName: HTMLPointerEventType, event: PointerEvent) => boolean;
|
19
17
|
export interface EditorSettings {
|
20
18
|
/** Defaults to `RenderingMode.CanvasRenderer` */
|
21
19
|
renderingMode: RenderingMode;
|
@@ -1,3 +1,7 @@
|
|
1
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
2
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
3
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
4
|
+
};
|
1
5
|
var _a, _b, _c;
|
2
6
|
import Viewport from './Viewport.mjs';
|
3
7
|
import AbstractComponent from './components/AbstractComponent.mjs';
|
@@ -16,7 +20,7 @@ export var EditorImageEventType;
|
|
16
20
|
EditorImageEventType[EditorImageEventType["ExportViewportChanged"] = 0] = "ExportViewportChanged";
|
17
21
|
})(EditorImageEventType || (EditorImageEventType = {}));
|
18
22
|
// Handles lookup/storage of elements in the image
|
19
|
-
|
23
|
+
class EditorImage {
|
20
24
|
// @internal
|
21
25
|
constructor() {
|
22
26
|
this.root = new ImageNode();
|
@@ -194,6 +198,7 @@ EditorImage.AddElementCommand = (_b = class extends SerializableCommand {
|
|
194
198
|
};
|
195
199
|
}
|
196
200
|
},
|
201
|
+
__setFunctionName(_b, "AddElementCommand"),
|
197
202
|
(() => {
|
198
203
|
SerializableCommand.register('add-element', (json, editor) => {
|
199
204
|
const id = json.elemData.id;
|
@@ -241,6 +246,7 @@ EditorImage.SetImportExportRectCommand = (_c = class extends SerializableCommand
|
|
241
246
|
};
|
242
247
|
}
|
243
248
|
},
|
249
|
+
__setFunctionName(_c, "SetImportExportRectCommand"),
|
244
250
|
_c.commandId = 'set-import-export-rect',
|
245
251
|
(() => {
|
246
252
|
const commandId = _c.commandId;
|
@@ -261,8 +267,9 @@ EditorImage.SetImportExportRectCommand = (_c = class extends SerializableCommand
|
|
261
267
|
});
|
262
268
|
})(),
|
263
269
|
_c);
|
270
|
+
export default EditorImage;
|
264
271
|
/** Part of the Editor's image. @internal */
|
265
|
-
|
272
|
+
class ImageNode {
|
266
273
|
constructor(parent = null) {
|
267
274
|
this.parent = parent;
|
268
275
|
this.targetChildCount = 30;
|
@@ -475,3 +482,4 @@ export class ImageNode {
|
|
475
482
|
}
|
476
483
|
}
|
477
484
|
ImageNode.idCounter = 0;
|
485
|
+
export { ImageNode };
|
@@ -17,7 +17,7 @@ import { Vec2 } from './math/Vec2.mjs';
|
|
17
17
|
import Vec3 from './math/Vec3.mjs';
|
18
18
|
export class ViewportTransform extends Command {
|
19
19
|
}
|
20
|
-
|
20
|
+
class Viewport {
|
21
21
|
// @internal
|
22
22
|
constructor(onTransformChangeCallback) {
|
23
23
|
this.onTransformChangeCallback = onTransformChangeCallback;
|
@@ -257,4 +257,5 @@ Viewport.ViewportTransform = (_a = class extends ViewportTransform {
|
|
257
257
|
},
|
258
258
|
_inverseTransform = new WeakMap(),
|
259
259
|
_a);
|
260
|
+
export { Viewport };
|
260
261
|
export default Viewport;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
class Command {
|
2
2
|
// Called when the command is being deleted
|
3
3
|
onDrop(_editor) { }
|
4
4
|
static union(a, b) {
|
@@ -27,4 +27,5 @@ Command.empty = new class extends Command {
|
|
27
27
|
apply(_editor) { }
|
28
28
|
unapply(_editor) { }
|
29
29
|
};
|
30
|
+
export { Command };
|
30
31
|
export default Command;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import Command from './Command.mjs';
|
2
|
-
|
2
|
+
class SerializableCommand extends Command {
|
3
3
|
constructor(commandTypeId) {
|
4
4
|
super();
|
5
5
|
this.commandTypeId = commandTypeId;
|
@@ -34,3 +34,4 @@ export default class SerializableCommand extends Command {
|
|
34
34
|
}
|
35
35
|
}
|
36
36
|
SerializableCommand.deserializationCallbacks = {};
|
37
|
+
export default SerializableCommand;
|
@@ -1,3 +1,7 @@
|
|
1
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
2
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
3
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
4
|
+
};
|
1
5
|
var _a;
|
2
6
|
import SerializableCommand from '../commands/SerializableCommand.mjs';
|
3
7
|
import EditorImage from '../EditorImage.mjs';
|
@@ -6,7 +10,7 @@ import UnresolvedSerializableCommand from '../commands/UnresolvedCommand.mjs';
|
|
6
10
|
/**
|
7
11
|
* A base class for everything that can be added to an {@link EditorImage}.
|
8
12
|
*/
|
9
|
-
|
13
|
+
class AbstractComponent {
|
10
14
|
constructor(
|
11
15
|
// A unique identifier for the type of component
|
12
16
|
componentKind, initialZIndex) {
|
@@ -249,6 +253,7 @@ AbstractComponent.TransformElementCommand = (_a = class extends UnresolvedSerial
|
|
249
253
|
};
|
250
254
|
}
|
251
255
|
},
|
256
|
+
__setFunctionName(_a, "TransformElementCommand"),
|
252
257
|
(() => {
|
253
258
|
SerializableCommand.register(AbstractComponent.transformElementCommandId, (json, editor) => {
|
254
259
|
var _a, _b;
|
@@ -260,3 +265,4 @@ AbstractComponent.TransformElementCommand = (_a = class extends UnresolvedSerial
|
|
260
265
|
});
|
261
266
|
})(),
|
262
267
|
_a);
|
268
|
+
export default AbstractComponent;
|
@@ -9,7 +9,7 @@ const componentTypeId = 'text';
|
|
9
9
|
/**
|
10
10
|
* Displays text.
|
11
11
|
*/
|
12
|
-
|
12
|
+
class TextComponent extends AbstractComponent {
|
13
13
|
/**
|
14
14
|
* Creates a new text object from a list of component text or child TextComponents.
|
15
15
|
*
|
@@ -271,4 +271,5 @@ export default class TextComponent extends AbstractComponent {
|
|
271
271
|
}
|
272
272
|
}
|
273
273
|
TextComponent.textMeasuringCtx = null;
|
274
|
+
export default TextComponent;
|
274
275
|
AbstractComponent.registerComponent(componentTypeId, (data) => TextComponent.deserializeFromString(data));
|
@@ -1,4 +1,4 @@
|
|
1
1
|
import { defaultEditorLocalization } from '../localization.mjs';
|
2
2
|
// German localization
|
3
|
-
const localization = Object.assign(Object.assign({}, defaultEditorLocalization), { pen: 'Stift', eraser: 'Radierer', select: 'Auswahl', handTool: 'Verschieben', zoom: 'Vergrößerung', resetView: 'Ansicht zurücksetzen', thicknessLabel: 'Dicke: ', colorLabel: 'Farbe: ', fontLabel: 'Schriftart: ', resizeImageToSelection: 'Bildgröße an Auswahl anpassen', deleteSelection: 'Auswahl löschen', duplicateSelection: 'Auswahl duplizieren', undo: 'Rückgängig', redo: 'Wiederholen', pickColorFromScreen: 'Farbe von Bildschirm auswählen', clickToPickColorAnnouncement: 'Klicke auf den Bildschirm, um eine Farbe auszuwählen', selectionToolKeyboardShortcuts: 'Auswahl-Werkzeug: Verwende die Pfeiltasten, um ausgewählte Elemente zu verschieben und ‚i‘ und ‚o‘, um ihre Größe zu ändern.', touchPanning: 'Ansicht mit Touchscreen verschieben', anyDevicePanning: 'Ansicht mit jedem Eingabegerät verschieben', selectPenType: 'Objekt-Typ: ', freehandPen: 'Freihand', arrowPen: 'Pfeil', linePen: 'Linie', outlinedRectanglePen: 'Umrissenes Rechteck', filledRectanglePen: 'Ausgefülltes Rechteck', dropdownShown:
|
3
|
+
const localization = Object.assign(Object.assign({}, defaultEditorLocalization), { pen: 'Stift', eraser: 'Radierer', select: 'Auswahl', handTool: 'Verschieben', zoom: 'Vergrößerung', image: 'Bild', inputAltText: 'Alt-Text: ', chooseFile: 'Wähle Datei: ', submit: 'Absenden', cancel: 'Abbrechen', resetView: 'Ansicht zurücksetzen', thicknessLabel: 'Dicke: ', colorLabel: 'Farbe: ', fontLabel: 'Schriftart: ', textSize: 'Größe: ', resizeImageToSelection: 'Bildgröße an Auswahl anpassen', deleteSelection: 'Auswahl löschen', duplicateSelection: 'Auswahl duplizieren', undo: 'Rückgängig', redo: 'Wiederholen', pickColorFromScreen: 'Farbe von Bildschirm auswählen', clickToPickColorAnnouncement: 'Klicke auf den Bildschirm, um eine Farbe auszuwählen', selectionToolKeyboardShortcuts: 'Auswahl-Werkzeug: Verwende die Pfeiltasten, um ausgewählte Elemente zu verschieben und ‚i‘ und ‚o‘, um ihre Größe zu ändern.', touchPanning: 'Ansicht mit Touchscreen verschieben', anyDevicePanning: 'Ansicht mit jedem Eingabegerät verschieben', selectPenType: 'Objekt-Typ: ', freehandPen: 'Freihand', pressureSensitiveFreehandPen: 'Stift (druckempfindlich)', arrowPen: 'Pfeil', linePen: 'Linie', outlinedRectanglePen: 'Umrissenes Rechteck', filledRectanglePen: 'Ausgefülltes Rechteck', lockRotation: 'Sperre Rotation', paste: 'Einfügen', dropdownShown: (toolName) => `Dropdown-Menü für ${toolName} angezeigt`, dropdownHidden: (toolName) => `Dropdown-Menü für ${toolName} versteckt`, zoomLevel: (zoomPercent) => `Vergößerung: ${zoomPercent}%`, colorChangedAnnouncement: (color) => `Farbe zu ${color} geändert`, imageSize: (size, units) => `Bild-Größe: ${size} ${units}`, imageLoadError: (message) => `Fehler beim Laden des Bildes: ${message}`, errorImageHasZeroSize: 'Fehler: Bild hat Größe Null', penTool: (penNumber) => `Stift ${penNumber}`, selectionTool: 'Auswahl', eraserTool: 'Radiergummi', touchPanTool: 'Ansicht mit Touchscreen verschieben', twoFingerPanZoomTool: 'Ansicht verschieben und vergrößern', undoRedoTool: 'Rückgängig/Wiederholen', rightClickDragPanTool: 'Rechtsklick-Ziehen', pipetteTool: 'Farbe von Bildschirm auswählen', keyboardPanZoom: 'Tastaturkürzel zum Verschieben/Vergrößern der Ansicht', textTool: 'Text', enterTextToInsert: 'Einzufügender Text', changeTool: 'Wechsle Werkzeug', pasteHandler: 'Copy-Paste-Handler', findLabel: 'Finde', toNextMatch: 'Nächstes', closeFindDialog: 'Schließen', findDialogShown: 'Finde-Dialog angezeigt', findDialogHidden: 'Finde-Dialog versteckt', focusedFoundText: (matchIdx, totalMatches) => `Sieh Treffer ${matchIdx} von ${totalMatches} an`, toolEnabledAnnouncement: (toolName) => `${toolName} aktiviert`, toolDisabledAnnouncement: (toolName) => `${toolName} deaktiviert`, updatedViewport: 'Transformierte Ansicht', transformedElements: (elemCount) => `${elemCount} Element${1 === elemCount ? '' : 'e'} transformiert`, resizeOutputCommand: (newSize) => `Bildgröße auf ${newSize.w}x${newSize.h} geändert`, addElementAction: (componentDescription) => `${componentDescription} hinzugefügt`, eraseAction: (elemDescription, countErased) => `${countErased} ${elemDescription} gelöscht`, duplicateAction: (elemDescription, countErased) => `${countErased} ${elemDescription} dupliziert`, inverseOf: (actionDescription) => `${actionDescription} umgekehrt`, elements: 'Elemente', erasedNoElements: 'Nichts entfernt', duplicatedNoElements: 'Nichts dupliziert', rotatedBy: (degrees) => `${Math.abs(degrees)} Grad ${degrees < 0 ? 'im Uhrzeigersinn' : 'gegen den Uhrzeigersinn'} gedreht`, movedLeft: 'Nacht links bewegt', movedUp: 'Nacht oben bewegt', movedDown: 'Nacht unten bewegt', movedRight: 'Nacht rechts bewegt', zoomedOut: 'Ansicht verkleinert', zoomedIn: 'Ansicht vergrößert', selectedElements: (count) => `${count} Element${1 === count ? '' : 'e'} ausgewählt`, stroke: 'Strich', svgObject: 'SVG-Objekt', text: (text) => `Text-Objekt: ${text}`, pathNodeCount: (count) => `Es gibt ${count} sichtbare Pfad-Objekte.`, textNodeCount: (count) => `Es gibt ${count} sichtbare Text-Knotenpunkte.`, textNode: (content) => `Text: ${content}`, imageNodeCount: (nodeCount) => `Es gibt ${nodeCount} sichtbare Bild-Knoten.`, imageNode: label => `Bild: ${label}`, unlabeledImageNode: 'Bild ohne Label', rerenderAsText: 'Als Text darstellen', accessibilityInputInstructions: 'Drücke ‚t‘, um den Inhalt des Ansichtsfensters als Text zu lesen. Verwende die Pfeiltasten, um die Ansicht zu verschieben, und klicke und ziehe, um Striche zu zeichnen. Drücke ‚w‘ zum Vergrößern und ‚s‘ zum Verkleinern der Ansicht.', loading: percentage => `Laden ${percentage}%...`, doneLoading: 'Laden fertig', imageEditor: 'Bild-Editor', undoAnnouncement: (commandDescription) => `${commandDescription} rückgängig gemacht`, redoAnnouncement: (commandDescription) => `${commandDescription} wiederholt`, reformatSelection: 'Formatiere Auswahl', documentProperties: 'Seite', backgroundColor: 'Hintergrundfarbe: ', imageWidthOption: 'Breite: ', imageHeightOption: 'Höhe: ', useGridOption: 'Gitter: ', toggleOverflow: 'Mehr', selectAllTool: 'Alle auswählen', soundExplorer: 'Klangbasierte Bilderkundung', disableAccessibilityExploreTool: 'Deaktiviere klangbasierte Erkundung', enableAccessibilityExploreTool: 'Aktiviere klangbasierte Erkundung', copied: (count, description) => `${count} ${description} kopiert`, pasted: (count, description) => `${count} ${description} eingefügt`, unionOf: (actionDescription, actionCount) => `Vereinigung: ${actionCount} ${actionDescription}`, emptyBackground: 'Leerer Hintergrund', filledBackgroundWithColor: (color) => `Gefüllter Hintergrund (${color})`, restyledElement: (elementDescription) => `${elementDescription} umgestaltet` });
|
4
4
|
export default localization;
|
@@ -5,7 +5,7 @@ import Vec3 from './Vec3.mjs';
|
|
5
5
|
* a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
|
6
6
|
* **and** translates while a linear transformation just scales/rotates/shears).
|
7
7
|
*/
|
8
|
-
|
8
|
+
class Mat33 {
|
9
9
|
/**
|
10
10
|
* Creates a matrix from inputs in the form,
|
11
11
|
* ```
|
@@ -324,3 +324,4 @@ export default class Mat33 {
|
|
324
324
|
}
|
325
325
|
}
|
326
326
|
Mat33.identity = new Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
327
|
+
export default Mat33;
|
@@ -29,7 +29,7 @@ const getPartBBox = (part) => {
|
|
29
29
|
}
|
30
30
|
return partBBox;
|
31
31
|
};
|
32
|
-
|
32
|
+
class Path {
|
33
33
|
constructor(startPoint, parts) {
|
34
34
|
this.startPoint = startPoint;
|
35
35
|
this.parts = parts;
|
@@ -867,3 +867,4 @@ export default class Path {
|
|
867
867
|
}
|
868
868
|
}
|
869
869
|
Path.empty = new Path(Vec2.zero, []);
|
870
|
+
export default Path;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import LineSegment2 from './LineSegment2.mjs';
|
2
2
|
import { Vec2 } from './Vec2.mjs';
|
3
3
|
// invariant: w ≥ 0, h ≥ 0.
|
4
|
-
|
4
|
+
class Rect2 {
|
5
5
|
constructor(x, y, w, h) {
|
6
6
|
this.x = x;
|
7
7
|
this.y = y;
|
@@ -227,3 +227,4 @@ export default class Rect2 {
|
|
227
227
|
}
|
228
228
|
Rect2.empty = new Rect2(0, 0, 0, 0);
|
229
229
|
Rect2.unitSquare = new Rect2(0, 0, 1, 1);
|
230
|
+
export default Rect2;
|
@@ -3,7 +3,7 @@
|
|
3
3
|
*
|
4
4
|
* A `Vec3` is immutable.
|
5
5
|
*/
|
6
|
-
|
6
|
+
class Vec3 {
|
7
7
|
constructor(x, y, z) {
|
8
8
|
this.x = x;
|
9
9
|
this.y = y;
|
@@ -172,3 +172,4 @@ Vec3.unitX = Vec3.of(1, 0, 0);
|
|
172
172
|
Vec3.unitY = Vec3.of(0, 1, 0);
|
173
173
|
Vec3.unitZ = Vec3.of(0, 0, 1);
|
174
174
|
Vec3.zero = Vec3.of(0, 0, 0);
|
175
|
+
export default Vec3;
|
@@ -53,7 +53,7 @@ export default class Display {
|
|
53
53
|
*/
|
54
54
|
rerenderAsText(): void;
|
55
55
|
/**
|
56
|
-
* Clears the drawing
|
56
|
+
* Clears the main drawing surface and otherwise prepares for a rerender.
|
57
57
|
*
|
58
58
|
* @returns the dry ink renderer.
|
59
59
|
*/
|
@@ -170,14 +170,13 @@ export default class Display {
|
|
170
170
|
}
|
171
171
|
}
|
172
172
|
/**
|
173
|
-
* Clears the drawing
|
173
|
+
* Clears the main drawing surface and otherwise prepares for a rerender.
|
174
174
|
*
|
175
175
|
* @returns the dry ink renderer.
|
176
176
|
*/
|
177
177
|
startRerender() {
|
178
178
|
var _a;
|
179
179
|
(_a = this.resizeSurfacesCallback) === null || _a === void 0 ? void 0 : _a.call(this);
|
180
|
-
this.wetInkRenderer.clear();
|
181
180
|
this.dryInkRenderer.clear();
|
182
181
|
return this.dryInkRenderer;
|
183
182
|
}
|
@@ -22,6 +22,8 @@ export default class HTMLToolbar {
|
|
22
22
|
private updateColoris;
|
23
23
|
/** @internal */
|
24
24
|
constructor(editor: Editor, parent: HTMLElement, localizationTable?: ToolbarLocalization);
|
25
|
+
private closeColorPickerOverlay;
|
26
|
+
private setupCloseColorPickerOverlay;
|
25
27
|
setupColorPickers(): void;
|
26
28
|
private reLayoutQueued;
|
27
29
|
private queueReLayout;
|
@@ -16,8 +16,9 @@ import ActionButtonWidget from './widgets/ActionButtonWidget.mjs';
|
|
16
16
|
import InsertImageWidget from './widgets/InsertImageWidget.mjs';
|
17
17
|
import DocumentPropertiesWidget from './widgets/DocumentPropertiesWidget.mjs';
|
18
18
|
import OverflowWidget from './widgets/OverflowWidget.mjs';
|
19
|
+
import { Vec2 } from '../math/Vec2.mjs';
|
19
20
|
export const toolbarCSSPrefix = 'toolbar-';
|
20
|
-
|
21
|
+
class HTMLToolbar {
|
21
22
|
/** @internal */
|
22
23
|
constructor(editor, parent, localizationTable = defaultToolbarLocalization) {
|
23
24
|
this.editor = editor;
|
@@ -30,6 +31,7 @@ export default class HTMLToolbar {
|
|
30
31
|
// Widget to toggle overflow menu.
|
31
32
|
this.overflowWidget = null;
|
32
33
|
this.updateColoris = null;
|
34
|
+
this.closeColorPickerOverlay = null;
|
33
35
|
this.reLayoutQueued = false;
|
34
36
|
this.container = document.createElement('div');
|
35
37
|
this.container.classList.add(`${toolbarCSSPrefix}root`);
|
@@ -50,6 +52,68 @@ export default class HTMLToolbar {
|
|
50
52
|
console.warn('ResizeObserver not supported. Toolbar will not resize.');
|
51
53
|
}
|
52
54
|
}
|
55
|
+
setupCloseColorPickerOverlay() {
|
56
|
+
if (this.closeColorPickerOverlay)
|
57
|
+
return;
|
58
|
+
this.closeColorPickerOverlay = document.createElement('div');
|
59
|
+
this.closeColorPickerOverlay.className = `${toolbarCSSPrefix}closeColorPickerOverlay`;
|
60
|
+
this.editor.createHTMLOverlay(this.closeColorPickerOverlay);
|
61
|
+
// Buffer events: Send events to the editor only if the pointer has moved enough to
|
62
|
+
// suggest that the user is attempting to draw, rather than click to close the color picker.
|
63
|
+
let eventBuffer = [];
|
64
|
+
let gestureStartPos = null;
|
65
|
+
// Hide the color picker when attempting to draw on the overlay.
|
66
|
+
this.listeners.push(this.editor.handlePointerEventsFrom(this.closeColorPickerOverlay, (eventName, event) => {
|
67
|
+
var _a, _b;
|
68
|
+
// Position of the current event.
|
69
|
+
const currentPos = Vec2.of(event.pageX, event.pageY);
|
70
|
+
// Whether to send the current event to the editor
|
71
|
+
let sendToEditor = true;
|
72
|
+
if (eventName === 'pointerdown') {
|
73
|
+
closeColoris();
|
74
|
+
// Buffer the event, but don't send it to the editor yet.
|
75
|
+
// We don't want to send single-click events, but we do want to send full strokes.
|
76
|
+
eventBuffer = [];
|
77
|
+
eventBuffer.push([eventName, event]);
|
78
|
+
gestureStartPos = currentPos;
|
79
|
+
// Capture the pointer so we receive future events even if the overlay is hidden.
|
80
|
+
(_a = this.closeColorPickerOverlay) === null || _a === void 0 ? void 0 : _a.setPointerCapture(event.pointerId);
|
81
|
+
// Don't send to the editor.
|
82
|
+
sendToEditor = false;
|
83
|
+
}
|
84
|
+
else if (eventName === 'pointermove') {
|
85
|
+
// Skip if the pointer hasn't moved enough to not be a "click".
|
86
|
+
const strokeStartThreshold = 10;
|
87
|
+
if (gestureStartPos && currentPos.minus(gestureStartPos).magnitude() < strokeStartThreshold) {
|
88
|
+
eventBuffer.push([eventName, event]);
|
89
|
+
sendToEditor = false;
|
90
|
+
}
|
91
|
+
else {
|
92
|
+
// Send all buffered events to the editor -- start the stroke.
|
93
|
+
for (const [eventName, event] of eventBuffer) {
|
94
|
+
this.editor.handleHTMLPointerEvent(eventName, event);
|
95
|
+
}
|
96
|
+
eventBuffer = [];
|
97
|
+
sendToEditor = true;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
// Otherwise, if we received a pointerup/pointercancel without flushing all pointerevents from the
|
101
|
+
// buffer, the gesture wasn't recognised as a stroke. Thus, the editor isn't expecting a pointerup/
|
102
|
+
// pointercancel event.
|
103
|
+
else if ((eventName === 'pointerup' || eventName === 'pointercancel') && eventBuffer.length > 0) {
|
104
|
+
(_b = this.closeColorPickerOverlay) === null || _b === void 0 ? void 0 : _b.releasePointerCapture(event.pointerId);
|
105
|
+
eventBuffer = [];
|
106
|
+
// Don't send to the editor.
|
107
|
+
sendToEditor = false;
|
108
|
+
}
|
109
|
+
// Transfer focus to the editor to allow keyboard events to be handled.
|
110
|
+
if (eventName === 'pointerup') {
|
111
|
+
this.editor.focus();
|
112
|
+
}
|
113
|
+
// Forward all other events to the editor.
|
114
|
+
return sendToEditor;
|
115
|
+
}));
|
116
|
+
}
|
53
117
|
// @internal
|
54
118
|
setupColorPickers() {
|
55
119
|
// Much of the setup only needs to be done once.
|
@@ -57,16 +121,7 @@ export default class HTMLToolbar {
|
|
57
121
|
this.updateColoris();
|
58
122
|
return;
|
59
123
|
}
|
60
|
-
|
61
|
-
closePickerOverlay.className = `${toolbarCSSPrefix}closeColorPickerOverlay`;
|
62
|
-
this.editor.createHTMLOverlay(closePickerOverlay);
|
63
|
-
// Hide the color picker when attempting to draw on the overlay.
|
64
|
-
this.listeners.push(this.editor.handlePointerEventsFrom(closePickerOverlay, (eventName) => {
|
65
|
-
if (eventName === 'pointerdown') {
|
66
|
-
closeColoris();
|
67
|
-
}
|
68
|
-
return true;
|
69
|
-
}));
|
124
|
+
this.setupCloseColorPickerOverlay();
|
70
125
|
const maxSwatchLen = 12;
|
71
126
|
const swatches = [
|
72
127
|
Color4.red.toHexString(),
|
@@ -111,7 +166,9 @@ export default class HTMLToolbar {
|
|
111
166
|
}
|
112
167
|
// Show/hide the overlay. Making the overlay visible gives users a surface to click
|
113
168
|
// on that shows/hides the color picker.
|
114
|
-
|
169
|
+
if (this.closeColorPickerOverlay) {
|
170
|
+
this.closeColorPickerOverlay.style.display = event.open ? 'block' : 'none';
|
171
|
+
}
|
115
172
|
}));
|
116
173
|
// Add newly-selected colors to the swatch.
|
117
174
|
this.listeners.push(this.editor.notifier.on(EditorEventType.ColorPickerColorSelected, event => {
|
@@ -373,11 +430,14 @@ export default class HTMLToolbar {
|
|
373
430
|
this.addDefaultActionButtons();
|
374
431
|
}
|
375
432
|
remove() {
|
433
|
+
var _a;
|
376
434
|
this.container.remove();
|
377
435
|
this.resizeObserver.disconnect();
|
436
|
+
(_a = this.closeColorPickerOverlay) === null || _a === void 0 ? void 0 : _a.remove();
|
378
437
|
for (const listener of this.listeners) {
|
379
438
|
listener.remove();
|
380
439
|
}
|
381
440
|
}
|
382
441
|
}
|
383
442
|
HTMLToolbar.colorisStarted = false;
|
443
|
+
export default HTMLToolbar;
|
@@ -3,7 +3,6 @@ import BaseTool from '../../tools/BaseTool';
|
|
3
3
|
import { ToolbarLocalization } from '../localization';
|
4
4
|
import BaseWidget from './BaseWidget';
|
5
5
|
export default abstract class BaseToolWidget extends BaseWidget {
|
6
|
-
protected editor: Editor;
|
7
6
|
protected targetTool: BaseTool;
|
8
7
|
constructor(editor: Editor, targetTool: BaseTool, id: string, localizationTable?: ToolbarLocalization);
|
9
8
|
protected handleClick(): void;
|
@@ -3,7 +3,6 @@ import BaseWidget from './BaseWidget.mjs';
|
|
3
3
|
export default class BaseToolWidget extends BaseWidget {
|
4
4
|
constructor(editor, targetTool, id, localizationTable) {
|
5
5
|
super(editor, id, localizationTable);
|
6
|
-
this.editor = editor;
|
7
6
|
this.targetTool = targetTool;
|
8
7
|
editor.notifier.on(EditorEventType.ToolEnabled, toolEvt => {
|
9
8
|
if (toolEvt.kind !== EditorEventType.ToolEnabled) {
|
@@ -37,6 +37,11 @@ export default abstract class BaseWidget {
|
|
37
37
|
protected get hasDropdown(): boolean;
|
38
38
|
protected addSubWidget(widget: BaseWidget): void;
|
39
39
|
private toolbarWidgetToggleListener;
|
40
|
+
/**
|
41
|
+
* Adds this to `parent`. This can only be called once for each ToolbarWidget.
|
42
|
+
* Returns the element that was just added to `parent`.
|
43
|
+
* @internal
|
44
|
+
*/
|
40
45
|
addTo(parent: HTMLElement): HTMLElement;
|
41
46
|
protected updateIcon(): void;
|
42
47
|
setDisabled(disabled: boolean): void;
|
@@ -135,14 +135,26 @@ export default class BaseWidget {
|
|
135
135
|
const id = widget.getUniqueIdIn(this.subWidgets);
|
136
136
|
this.subWidgets[id] = widget;
|
137
137
|
}
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
/**
|
139
|
+
* Adds this to `parent`. This can only be called once for each ToolbarWidget.
|
140
|
+
* Returns the element that was just added to `parent`.
|
141
|
+
* @internal
|
142
|
+
*/
|
141
143
|
addTo(parent) {
|
142
|
-
|
143
|
-
this.setupActionBtnClickListener(this.button);
|
144
|
+
// Update title and icon
|
144
145
|
this.icon = null;
|
145
146
|
this.updateIcon();
|
147
|
+
this.label.innerText = this.getTitle();
|
148
|
+
const longLabelCSSClass = 'long-label';
|
149
|
+
if (this.label.innerText.length > 7) {
|
150
|
+
this.label.classList.add(longLabelCSSClass);
|
151
|
+
}
|
152
|
+
else {
|
153
|
+
this.label.classList.remove(longLabelCSSClass);
|
154
|
+
}
|
155
|
+
// Click functionality
|
156
|
+
this.setupActionBtnClickListener(this.button);
|
157
|
+
// Clear anything already in this.container.
|
146
158
|
this.container.replaceChildren();
|
147
159
|
this.button.replaceChildren(this.icon, this.label);
|
148
160
|
this.container.appendChild(this.button);
|
@@ -7,7 +7,7 @@ import { EditorEventType } from '../../types.mjs';
|
|
7
7
|
import { toolbarCSSPrefix } from '../HTMLToolbar.mjs';
|
8
8
|
import makeColorInput from '../makeColorInput.mjs';
|
9
9
|
import BaseWidget from './BaseWidget.mjs';
|
10
|
-
|
10
|
+
class DocumentPropertiesWidget extends BaseWidget {
|
11
11
|
constructor(editor, localizationTable) {
|
12
12
|
super(editor, 'document-properties-widget', localizationTable);
|
13
13
|
this.updateDropdownContent = () => { };
|
@@ -170,3 +170,4 @@ export default class DocumentPropertiesWidget extends BaseWidget {
|
|
170
170
|
}
|
171
171
|
}
|
172
172
|
DocumentPropertiesWidget.idCounter = 0;
|
173
|
+
export default DocumentPropertiesWidget;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { EditorEventType } from '../../types.mjs';
|
2
2
|
import { toolbarCSSPrefix } from '../HTMLToolbar.mjs';
|
3
3
|
import BaseToolWidget from './BaseToolWidget.mjs';
|
4
|
-
|
4
|
+
class EraserToolWidget extends BaseToolWidget {
|
5
5
|
constructor(editor, tool, localizationTable) {
|
6
6
|
super(editor, tool, 'eraser-tool-widget', localizationTable);
|
7
7
|
this.tool = tool;
|
@@ -55,3 +55,4 @@ export default class EraserToolWidget extends BaseToolWidget {
|
|
55
55
|
}
|
56
56
|
}
|
57
57
|
EraserToolWidget.nextThicknessInputId = 0;
|
58
|
+
export default EraserToolWidget;
|
@@ -15,7 +15,7 @@ import SelectionTool from '../../tools/SelectionTool/SelectionTool.mjs';
|
|
15
15
|
import Mat33 from '../../math/Mat33.mjs';
|
16
16
|
import fileToBase64 from '../../util/fileToBase64.mjs';
|
17
17
|
import ActionButtonWidget from './ActionButtonWidget.mjs';
|
18
|
-
|
18
|
+
class InsertImageWidget extends ActionButtonWidget {
|
19
19
|
constructor(editor, localization) {
|
20
20
|
localization !== null && localization !== void 0 ? localization : (localization = editor.localization);
|
21
21
|
super(editor, 'insert-image-widget', () => editor.icons.makeInsertImageIcon(), localization.image, () => this.onClicked());
|
@@ -168,3 +168,4 @@ export default class InsertImageWidget extends ActionButtonWidget {
|
|
168
168
|
}
|
169
169
|
}
|
170
170
|
InsertImageWidget.nextInputId = 0;
|
171
|
+
export default InsertImageWidget;
|
@@ -8,7 +8,7 @@ import { toolbarCSSPrefix } from '../HTMLToolbar.mjs';
|
|
8
8
|
import makeColorInput from '../makeColorInput.mjs';
|
9
9
|
import BaseToolWidget from './BaseToolWidget.mjs';
|
10
10
|
import Color4 from '../../Color4.mjs';
|
11
|
-
|
11
|
+
class PenToolWidget extends BaseToolWidget {
|
12
12
|
constructor(editor, tool, localization) {
|
13
13
|
super(editor, tool, 'pen', localization);
|
14
14
|
this.tool = tool;
|
@@ -218,3 +218,4 @@ export default class PenToolWidget extends BaseToolWidget {
|
|
218
218
|
}
|
219
219
|
}
|
220
220
|
PenToolWidget.idCounter = 0;
|
221
|
+
export default PenToolWidget;
|
@@ -3,7 +3,7 @@ import { EditorEventType } from '../../types.mjs';
|
|
3
3
|
import { toolbarCSSPrefix } from '../HTMLToolbar.mjs';
|
4
4
|
import makeColorInput from '../makeColorInput.mjs';
|
5
5
|
import BaseToolWidget from './BaseToolWidget.mjs';
|
6
|
-
|
6
|
+
class TextToolWidget extends BaseToolWidget {
|
7
7
|
constructor(editor, tool, localization) {
|
8
8
|
super(editor, tool, 'text-tool-widget', localization);
|
9
9
|
this.tool = tool;
|
@@ -107,3 +107,4 @@ export default class TextToolWidget extends BaseToolWidget {
|
|
107
107
|
}
|
108
108
|
}
|
109
109
|
TextToolWidget.idCounter = 0;
|
110
|
+
export default TextToolWidget;
|