js-draw 0.18.2 → 0.20.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/.eslintrc.js +1 -0
- package/CHANGELOG.md +10 -0
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -0
- package/dist/cjs/src/Color4.d.ts +8 -0
- package/dist/cjs/src/Color4.js +67 -0
- package/dist/cjs/src/Editor.d.ts +2 -2
- package/dist/cjs/src/Editor.js +7 -7
- package/dist/cjs/src/SVGLoader.js +77 -12
- package/dist/cjs/src/Viewport.d.ts +2 -0
- package/dist/cjs/src/Viewport.js +6 -2
- package/dist/cjs/src/components/AbstractComponent.d.ts +2 -2
- package/dist/cjs/src/components/AbstractComponent.js +3 -3
- package/dist/cjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
- package/dist/cjs/src/components/BackgroundComponent.js +309 -0
- package/dist/cjs/src/components/RestylableComponent.d.ts +21 -2
- package/dist/cjs/src/components/Stroke.d.ts +35 -0
- package/dist/cjs/src/components/Stroke.js +37 -3
- package/dist/cjs/src/components/TextComponent.d.ts +27 -17
- package/dist/cjs/src/components/TextComponent.js +23 -1
- package/dist/cjs/src/components/lib.d.ts +4 -3
- package/dist/cjs/src/components/lib.js +2 -2
- package/dist/cjs/src/components/util/StrokeSmoother.js +25 -15
- package/dist/cjs/src/lib.d.ts +30 -0
- package/dist/cjs/src/lib.js +30 -0
- package/dist/cjs/src/localizations/de.js +1 -1
- package/dist/cjs/src/localizations/es.js +1 -1
- package/dist/cjs/src/math/Path.js +1 -1
- package/dist/cjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/cjs/src/math/polynomial/QuadraticBezier.js +115 -0
- package/dist/cjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
- package/dist/cjs/src/math/polynomial/solveQuadratic.js +36 -0
- package/dist/cjs/src/rendering/RenderingStyle.d.ts +4 -4
- package/dist/cjs/src/rendering/TextRenderingStyle.d.ts +10 -10
- package/dist/cjs/src/rendering/lib.d.ts +2 -0
- package/dist/cjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/CanvasRenderer.js +5 -3
- package/dist/cjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/SVGRenderer.js +15 -6
- package/dist/cjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
- package/dist/cjs/src/toolbar/IconProvider.d.ts +2 -2
- package/dist/cjs/src/toolbar/localization.d.ts +2 -1
- package/dist/cjs/src/toolbar/localization.js +3 -2
- package/dist/cjs/src/toolbar/widgets/BaseWidget.js +1 -1
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.js +77 -2
- package/dist/cjs/src/toolbar/widgets/PenToolWidget.js +1 -1
- package/dist/cjs/src/tools/FindTool.js +1 -1
- package/dist/cjs/src/tools/SoundUITool.d.ts +24 -0
- package/dist/cjs/src/tools/SoundUITool.js +164 -0
- package/dist/cjs/src/tools/TextTool.d.ts +2 -2
- package/dist/cjs/src/tools/ToolController.js +6 -1
- package/dist/cjs/src/tools/lib.d.ts +1 -0
- package/dist/cjs/src/tools/lib.js +3 -1
- package/dist/cjs/src/tools/localization.d.ts +3 -0
- package/dist/cjs/src/tools/localization.js +3 -0
- package/dist/mjs/src/Color4.d.ts +8 -0
- package/dist/mjs/src/Color4.mjs +64 -0
- package/dist/mjs/src/Editor.d.ts +2 -2
- package/dist/mjs/src/Editor.mjs +6 -6
- package/dist/mjs/src/SVGLoader.mjs +76 -11
- package/dist/mjs/src/Viewport.d.ts +2 -0
- package/dist/mjs/src/Viewport.mjs +6 -2
- package/dist/mjs/src/components/AbstractComponent.d.ts +2 -2
- package/dist/mjs/src/components/AbstractComponent.mjs +3 -3
- package/dist/mjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
- package/dist/mjs/src/components/BackgroundComponent.mjs +279 -0
- package/dist/mjs/src/components/RestylableComponent.d.ts +21 -2
- package/dist/mjs/src/components/Stroke.d.ts +35 -0
- package/dist/mjs/src/components/Stroke.mjs +37 -3
- package/dist/mjs/src/components/TextComponent.d.ts +27 -17
- package/dist/mjs/src/components/TextComponent.mjs +23 -1
- package/dist/mjs/src/components/lib.d.ts +4 -3
- package/dist/mjs/src/components/lib.mjs +2 -2
- package/dist/mjs/src/components/util/StrokeSmoother.mjs +25 -15
- package/dist/mjs/src/lib.d.ts +30 -0
- package/dist/mjs/src/lib.mjs +30 -0
- package/dist/mjs/src/localizations/de.mjs +1 -1
- package/dist/mjs/src/localizations/es.mjs +1 -1
- package/dist/mjs/src/math/Path.mjs +1 -1
- package/dist/mjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/mjs/src/math/polynomial/QuadraticBezier.mjs +109 -0
- package/dist/mjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
- package/dist/mjs/src/math/polynomial/solveQuadratic.mjs +34 -0
- package/dist/mjs/src/rendering/RenderingStyle.d.ts +4 -4
- package/dist/mjs/src/rendering/TextRenderingStyle.d.ts +10 -10
- package/dist/mjs/src/rendering/lib.d.ts +2 -0
- package/dist/mjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/CanvasRenderer.mjs +5 -3
- package/dist/mjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/SVGRenderer.mjs +15 -6
- package/dist/mjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
- package/dist/mjs/src/toolbar/IconProvider.d.ts +2 -2
- package/dist/mjs/src/toolbar/localization.d.ts +2 -1
- package/dist/mjs/src/toolbar/localization.mjs +3 -2
- package/dist/mjs/src/toolbar/widgets/BaseWidget.mjs +1 -1
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.mjs +54 -2
- package/dist/mjs/src/toolbar/widgets/PenToolWidget.mjs +1 -1
- package/dist/mjs/src/tools/FindTool.mjs +1 -1
- package/dist/mjs/src/tools/SoundUITool.d.ts +24 -0
- package/dist/mjs/src/tools/SoundUITool.mjs +158 -0
- package/dist/mjs/src/tools/TextTool.d.ts +2 -2
- package/dist/mjs/src/tools/ToolController.mjs +6 -1
- package/dist/mjs/src/tools/lib.d.ts +1 -0
- package/dist/mjs/src/tools/lib.mjs +1 -0
- package/dist/mjs/src/tools/localization.d.ts +3 -0
- package/dist/mjs/src/tools/localization.mjs +3 -0
- package/jest.config.js +1 -1
- package/package.json +19 -17
- package/src/Editor.css +2 -2
- package/src/tools/SoundUITool.css +15 -0
- package/src/tools/tools.css +4 -0
- package/dist/cjs/src/components/ImageBackground.js +0 -146
- package/dist/mjs/src/components/ImageBackground.mjs +0 -139
- package/src/Color4.test.ts +0 -40
- package/src/Color4.ts +0 -236
- package/src/Editor.loadFrom.test.ts +0 -24
- package/src/Editor.toSVG.test.ts +0 -111
- package/src/Editor.ts +0 -1122
- package/src/EditorImage.test.ts +0 -120
- package/src/EditorImage.ts +0 -603
- package/src/EventDispatcher.test.ts +0 -123
- package/src/EventDispatcher.ts +0 -71
- package/src/Pointer.ts +0 -127
- package/src/SVGLoader.test.ts +0 -114
- package/src/SVGLoader.ts +0 -511
- package/src/UndoRedoHistory.test.ts +0 -33
- package/src/UndoRedoHistory.ts +0 -102
- package/src/Viewport.ts +0 -319
- package/src/bundle/bundled.ts +0 -7
- package/src/commands/Command.ts +0 -45
- package/src/commands/Duplicate.ts +0 -48
- package/src/commands/Erase.ts +0 -74
- package/src/commands/SerializableCommand.ts +0 -49
- package/src/commands/UnresolvedCommand.ts +0 -37
- package/src/commands/invertCommand.ts +0 -51
- package/src/commands/lib.ts +0 -16
- package/src/commands/localization.ts +0 -47
- package/src/commands/uniteCommands.test.ts +0 -23
- package/src/commands/uniteCommands.ts +0 -135
- package/src/components/AbstractComponent.transformBy.test.ts +0 -22
- package/src/components/AbstractComponent.ts +0 -364
- package/src/components/ImageBackground.test.ts +0 -35
- package/src/components/ImageBackground.ts +0 -176
- package/src/components/ImageComponent.ts +0 -171
- package/src/components/RestylableComponent.ts +0 -142
- package/src/components/SVGGlobalAttributesObject.ts +0 -81
- package/src/components/Stroke.test.ts +0 -139
- package/src/components/Stroke.ts +0 -245
- package/src/components/TextComponent.test.ts +0 -99
- package/src/components/TextComponent.ts +0 -315
- package/src/components/UnknownSVGObject.test.ts +0 -10
- package/src/components/UnknownSVGObject.ts +0 -60
- package/src/components/builders/ArrowBuilder.ts +0 -107
- package/src/components/builders/FreehandLineBuilder.ts +0 -212
- package/src/components/builders/LineBuilder.ts +0 -77
- package/src/components/builders/PressureSensitiveFreehandLineBuilder.ts +0 -454
- package/src/components/builders/RectangleBuilder.ts +0 -74
- package/src/components/builders/types.ts +0 -15
- package/src/components/lib.ts +0 -25
- package/src/components/localization.ts +0 -22
- package/src/components/util/StrokeSmoother.ts +0 -293
- package/src/components/util/describeComponentList.ts +0 -18
- package/src/lib.ts +0 -37
- package/src/localization.ts +0 -34
- package/src/localizations/de.ts +0 -98
- package/src/localizations/en.ts +0 -8
- package/src/localizations/es.ts +0 -74
- package/src/localizations/getLocalizationTable.test.ts +0 -27
- package/src/localizations/getLocalizationTable.ts +0 -55
- package/src/math/LineSegment2.test.ts +0 -99
- package/src/math/LineSegment2.ts +0 -160
- package/src/math/Mat33.test.ts +0 -244
- package/src/math/Mat33.ts +0 -437
- package/src/math/Path.fromString.test.ts +0 -223
- package/src/math/Path.test.ts +0 -198
- package/src/math/Path.toString.test.ts +0 -77
- package/src/math/Path.ts +0 -790
- package/src/math/Rect2.test.ts +0 -204
- package/src/math/Rect2.ts +0 -315
- package/src/math/Triangle.ts +0 -29
- package/src/math/Vec2.test.ts +0 -30
- package/src/math/Vec2.ts +0 -18
- package/src/math/Vec3.test.ts +0 -44
- package/src/math/Vec3.ts +0 -218
- package/src/math/lib.ts +0 -15
- package/src/math/rounding.test.ts +0 -65
- package/src/math/rounding.ts +0 -156
- package/src/rendering/Display.ts +0 -249
- package/src/rendering/RenderingStyle.test.ts +0 -68
- package/src/rendering/RenderingStyle.ts +0 -55
- package/src/rendering/TextRenderingStyle.ts +0 -45
- package/src/rendering/caching/CacheRecord.test.ts +0 -49
- package/src/rendering/caching/CacheRecord.ts +0 -77
- package/src/rendering/caching/CacheRecordManager.ts +0 -71
- package/src/rendering/caching/RenderingCache.test.ts +0 -44
- package/src/rendering/caching/RenderingCache.ts +0 -66
- package/src/rendering/caching/RenderingCacheNode.ts +0 -405
- package/src/rendering/caching/testUtils.ts +0 -35
- package/src/rendering/caching/types.ts +0 -34
- package/src/rendering/lib.ts +0 -6
- package/src/rendering/localization.ts +0 -20
- package/src/rendering/renderers/AbstractRenderer.ts +0 -222
- package/src/rendering/renderers/CanvasRenderer.ts +0 -296
- package/src/rendering/renderers/DummyRenderer.test.ts +0 -42
- package/src/rendering/renderers/DummyRenderer.ts +0 -136
- package/src/rendering/renderers/SVGRenderer.ts +0 -354
- package/src/rendering/renderers/TextOnlyRenderer.ts +0 -70
- package/src/testing/beforeEachFile.ts +0 -8
- package/src/testing/createEditor.ts +0 -11
- package/src/testing/global.d.ts +0 -17
- package/src/testing/lib.ts +0 -3
- package/src/testing/loadExpectExtensions.ts +0 -25
- package/src/testing/sendPenEvent.ts +0 -31
- package/src/testing/sendTouchEvent.ts +0 -78
- package/src/toolbar/HTMLToolbar.ts +0 -492
- package/src/toolbar/IconProvider.ts +0 -736
- package/src/toolbar/lib.ts +0 -4
- package/src/toolbar/localization.ts +0 -106
- package/src/toolbar/makeColorInput.ts +0 -145
- package/src/toolbar/types.ts +0 -5
- package/src/toolbar/widgets/ActionButtonWidget.ts +0 -39
- package/src/toolbar/widgets/BaseToolWidget.ts +0 -56
- package/src/toolbar/widgets/BaseWidget.ts +0 -377
- package/src/toolbar/widgets/DocumentPropertiesWidget.ts +0 -167
- package/src/toolbar/widgets/EraserToolWidget.ts +0 -85
- package/src/toolbar/widgets/HandToolWidget.ts +0 -250
- package/src/toolbar/widgets/InsertImageWidget.ts +0 -223
- package/src/toolbar/widgets/OverflowWidget.ts +0 -92
- package/src/toolbar/widgets/PenToolWidget.ts +0 -288
- package/src/toolbar/widgets/SelectionToolWidget.ts +0 -190
- package/src/toolbar/widgets/TextToolWidget.ts +0 -145
- package/src/toolbar/widgets/lib.ts +0 -13
- package/src/tools/BaseTool.ts +0 -76
- package/src/tools/Eraser.test.ts +0 -103
- package/src/tools/Eraser.ts +0 -139
- package/src/tools/FindTool.ts +0 -152
- package/src/tools/PanZoom.test.ts +0 -310
- package/src/tools/PanZoom.ts +0 -520
- package/src/tools/PasteHandler.ts +0 -95
- package/src/tools/Pen.test.ts +0 -194
- package/src/tools/Pen.ts +0 -226
- package/src/tools/PipetteTool.ts +0 -55
- package/src/tools/SelectionTool/SelectAllShortcutHandler.ts +0 -28
- package/src/tools/SelectionTool/Selection.ts +0 -607
- package/src/tools/SelectionTool/SelectionHandle.ts +0 -108
- package/src/tools/SelectionTool/SelectionTool.test.ts +0 -261
- package/src/tools/SelectionTool/SelectionTool.ts +0 -480
- package/src/tools/SelectionTool/TransformMode.ts +0 -114
- package/src/tools/SelectionTool/types.ts +0 -11
- package/src/tools/TextTool.ts +0 -326
- package/src/tools/ToolController.ts +0 -178
- package/src/tools/ToolEnabledGroup.ts +0 -14
- package/src/tools/ToolSwitcherShortcut.ts +0 -39
- package/src/tools/ToolbarShortcutHandler.ts +0 -34
- package/src/tools/UndoRedoShortcut.test.ts +0 -56
- package/src/tools/UndoRedoShortcut.ts +0 -25
- package/src/tools/lib.ts +0 -21
- package/src/tools/localization.ts +0 -66
- package/src/types.ts +0 -234
- package/src/util/assertions.ts +0 -55
- package/src/util/fileToBase64.ts +0 -18
- package/src/util/untilNextAnimationFrame.ts +0 -9
- package/src/util/waitForTimeout.ts +0 -9
@@ -1,377 +0,0 @@
|
|
1
|
-
import Editor from '../../Editor';
|
2
|
-
import { DispatcherEventListener } from '../../EventDispatcher';
|
3
|
-
import ToolbarShortcutHandler from '../../tools/ToolbarShortcutHandler';
|
4
|
-
import { EditorEventType, InputEvtType, KeyPressEvent } from '../../types';
|
5
|
-
import { toolbarCSSPrefix } from '../HTMLToolbar';
|
6
|
-
import { ToolbarLocalization } from '../localization';
|
7
|
-
|
8
|
-
export type SavedToolbuttonState = Record<string, any>;
|
9
|
-
|
10
|
-
export default abstract class BaseWidget {
|
11
|
-
protected readonly container: HTMLElement;
|
12
|
-
private button: HTMLElement;
|
13
|
-
private icon: Element|null;
|
14
|
-
private dropdownContainer: HTMLElement;
|
15
|
-
private dropdownIcon: Element;
|
16
|
-
private label: HTMLLabelElement;
|
17
|
-
#hasDropdown: boolean;
|
18
|
-
private disabled: boolean = false;
|
19
|
-
|
20
|
-
// Maps subWidget IDs to subWidgets.
|
21
|
-
private subWidgets: Record<string, BaseWidget> = {};
|
22
|
-
|
23
|
-
private toplevel: boolean = true;
|
24
|
-
protected readonly localizationTable: ToolbarLocalization;
|
25
|
-
|
26
|
-
public constructor(
|
27
|
-
protected editor: Editor,
|
28
|
-
protected id: string,
|
29
|
-
localizationTable?: ToolbarLocalization,
|
30
|
-
) {
|
31
|
-
this.localizationTable = localizationTable ?? editor.localization;
|
32
|
-
|
33
|
-
this.icon = null;
|
34
|
-
this.container = document.createElement('div');
|
35
|
-
this.container.classList.add(`${toolbarCSSPrefix}toolContainer`);
|
36
|
-
this.dropdownContainer = document.createElement('div');
|
37
|
-
this.dropdownContainer.classList.add(`${toolbarCSSPrefix}dropdown`);
|
38
|
-
this.dropdownContainer.classList.add('hidden');
|
39
|
-
this.#hasDropdown = false;
|
40
|
-
|
41
|
-
this.button = document.createElement('div');
|
42
|
-
this.button.classList.add(`${toolbarCSSPrefix}button`);
|
43
|
-
this.label = document.createElement('label');
|
44
|
-
this.button.setAttribute('role', 'button');
|
45
|
-
this.button.tabIndex = 0;
|
46
|
-
|
47
|
-
const toolbarShortcutHandlers = this.editor.toolController.getMatchingTools(ToolbarShortcutHandler);
|
48
|
-
|
49
|
-
// If the onKeyPress function has been extended and the editor is configured to send keypress events to
|
50
|
-
// toolbar widgets,
|
51
|
-
if (toolbarShortcutHandlers.length > 0 && this.onKeyPress !== BaseWidget.prototype.onKeyPress) {
|
52
|
-
toolbarShortcutHandlers[0].registerListener(event => this.onKeyPress(event));
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
public getId(): string {
|
57
|
-
return this.id;
|
58
|
-
}
|
59
|
-
|
60
|
-
/**
|
61
|
-
* Returns the ID of this widget in `container`. Adds a suffix to this' ID
|
62
|
-
* if an item in `container` already has this' ID.
|
63
|
-
*
|
64
|
-
* For example, if `this` has ID `foo` and if
|
65
|
-
* `container = { 'foo': somethingNotThis, 'foo-1': somethingElseNotThis }`, this method
|
66
|
-
* returns `foo-2` because elements with IDs `foo` and `foo-1` are already present in
|
67
|
-
* `container`.
|
68
|
-
*/
|
69
|
-
public getUniqueIdIn(container: Record<string, BaseWidget>): string {
|
70
|
-
let id = this.getId();
|
71
|
-
let idCounter = 0;
|
72
|
-
|
73
|
-
while (id in container && container[id] !== this) {
|
74
|
-
id = this.getId() + '-' + idCounter.toString();
|
75
|
-
idCounter ++;
|
76
|
-
}
|
77
|
-
|
78
|
-
return id;
|
79
|
-
}
|
80
|
-
|
81
|
-
protected abstract getTitle(): string;
|
82
|
-
protected abstract createIcon(): Element|null;
|
83
|
-
|
84
|
-
// Add content to the widget's associated dropdown menu.
|
85
|
-
// Returns true if such a menu should be created, false otherwise.
|
86
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
87
|
-
if (Object.keys(this.subWidgets).length === 0) {
|
88
|
-
return false;
|
89
|
-
}
|
90
|
-
|
91
|
-
for (const widgetId in this.subWidgets) {
|
92
|
-
const widget = this.subWidgets[widgetId];
|
93
|
-
|
94
|
-
widget.addTo(dropdown);
|
95
|
-
widget.setIsToplevel(false);
|
96
|
-
}
|
97
|
-
return true;
|
98
|
-
}
|
99
|
-
|
100
|
-
protected setupActionBtnClickListener(button: HTMLElement) {
|
101
|
-
const clickTriggers = { Enter: true, ' ': true, };
|
102
|
-
button.onkeydown = (evt) => {
|
103
|
-
let handled = false;
|
104
|
-
|
105
|
-
if (evt.key in clickTriggers) {
|
106
|
-
if (!this.disabled) {
|
107
|
-
this.handleClick();
|
108
|
-
handled = true;
|
109
|
-
}
|
110
|
-
}
|
111
|
-
|
112
|
-
// If we didn't do anything with the event, send it to the editor.
|
113
|
-
if (!handled) {
|
114
|
-
handled = this.editor.toolController.dispatchInputEvent({
|
115
|
-
kind: InputEvtType.KeyPressEvent,
|
116
|
-
key: evt.key,
|
117
|
-
ctrlKey: evt.ctrlKey || evt.metaKey,
|
118
|
-
altKey: evt.altKey,
|
119
|
-
});
|
120
|
-
}
|
121
|
-
|
122
|
-
if (handled) {
|
123
|
-
evt.preventDefault();
|
124
|
-
}
|
125
|
-
};
|
126
|
-
|
127
|
-
button.onkeyup = evt => {
|
128
|
-
if (evt.key in clickTriggers) {
|
129
|
-
return;
|
130
|
-
}
|
131
|
-
|
132
|
-
const handled = this.editor.toolController.dispatchInputEvent({
|
133
|
-
kind: InputEvtType.KeyUpEvent,
|
134
|
-
key: evt.key,
|
135
|
-
ctrlKey: evt.ctrlKey || evt.metaKey,
|
136
|
-
altKey: evt.altKey,
|
137
|
-
});
|
138
|
-
|
139
|
-
if (handled) {
|
140
|
-
evt.preventDefault();
|
141
|
-
}
|
142
|
-
};
|
143
|
-
|
144
|
-
button.onclick = () => {
|
145
|
-
if (!this.disabled) {
|
146
|
-
this.handleClick();
|
147
|
-
}
|
148
|
-
};
|
149
|
-
}
|
150
|
-
|
151
|
-
// Add a listener that is triggered when a key is pressed.
|
152
|
-
// Listeners will fire regardless of whether this widget is selected and require that
|
153
|
-
// {@link lib!Editor.toolController} to have an enabled {@link lib!ToolbarShortcutHandler} tool.
|
154
|
-
protected onKeyPress(_event: KeyPressEvent): boolean {
|
155
|
-
return false;
|
156
|
-
}
|
157
|
-
|
158
|
-
protected abstract handleClick(): void;
|
159
|
-
|
160
|
-
protected get hasDropdown() {
|
161
|
-
return this.#hasDropdown;
|
162
|
-
}
|
163
|
-
|
164
|
-
// Add a widget to this' dropdown. Must be called before this.addTo.
|
165
|
-
protected addSubWidget(widget: BaseWidget) {
|
166
|
-
// Generate a unique ID for the widget.
|
167
|
-
const id = widget.getUniqueIdIn(this.subWidgets);
|
168
|
-
|
169
|
-
this.subWidgets[id] = widget;
|
170
|
-
}
|
171
|
-
|
172
|
-
private toolbarWidgetToggleListener: DispatcherEventListener|null = null;
|
173
|
-
|
174
|
-
// Adds this to [parent]. This can only be called once for each ToolbarWidget.
|
175
|
-
// Returns the element that was just added to `parent`.
|
176
|
-
// @internal
|
177
|
-
public addTo(parent: HTMLElement) {
|
178
|
-
this.label.innerText = this.getTitle();
|
179
|
-
|
180
|
-
this.setupActionBtnClickListener(this.button);
|
181
|
-
|
182
|
-
this.icon = null;
|
183
|
-
this.updateIcon();
|
184
|
-
|
185
|
-
this.container.replaceChildren();
|
186
|
-
|
187
|
-
this.button.replaceChildren(this.icon!, this.label);
|
188
|
-
this.container.appendChild(this.button);
|
189
|
-
|
190
|
-
this.#hasDropdown = this.fillDropdown(this.dropdownContainer);
|
191
|
-
if (this.#hasDropdown) {
|
192
|
-
this.dropdownIcon = this.createDropdownIcon();
|
193
|
-
this.button.appendChild(this.dropdownIcon);
|
194
|
-
this.container.appendChild(this.dropdownContainer);
|
195
|
-
|
196
|
-
if (this.toolbarWidgetToggleListener) {
|
197
|
-
this.toolbarWidgetToggleListener.remove();
|
198
|
-
}
|
199
|
-
|
200
|
-
this.toolbarWidgetToggleListener = this.editor.notifier.on(EditorEventType.ToolbarDropdownShown, (evt) => {
|
201
|
-
if (
|
202
|
-
evt.kind === EditorEventType.ToolbarDropdownShown
|
203
|
-
&& evt.parentWidget !== this
|
204
|
-
|
205
|
-
// Don't hide if a submenu wash shown (it might be a submenu of
|
206
|
-
// the current menu).
|
207
|
-
&& evt.parentWidget.toplevel
|
208
|
-
) {
|
209
|
-
this.setDropdownVisible(false);
|
210
|
-
}
|
211
|
-
});
|
212
|
-
}
|
213
|
-
|
214
|
-
this.setDropdownVisible(false);
|
215
|
-
|
216
|
-
if (this.container.parentElement) {
|
217
|
-
this.container.remove();
|
218
|
-
}
|
219
|
-
|
220
|
-
parent.appendChild(this.container);
|
221
|
-
return this.container;
|
222
|
-
}
|
223
|
-
|
224
|
-
|
225
|
-
protected updateIcon() {
|
226
|
-
const newIcon = this.createIcon();
|
227
|
-
|
228
|
-
if (newIcon) {
|
229
|
-
this.icon?.replaceWith(newIcon);
|
230
|
-
this.icon = newIcon;
|
231
|
-
this.icon.classList.add(`${toolbarCSSPrefix}icon`);
|
232
|
-
} else {
|
233
|
-
this.icon?.remove();
|
234
|
-
}
|
235
|
-
}
|
236
|
-
|
237
|
-
public setDisabled(disabled: boolean) {
|
238
|
-
this.disabled = disabled;
|
239
|
-
if (this.disabled) {
|
240
|
-
this.button.classList.add('disabled');
|
241
|
-
this.button.setAttribute('aria-disabled', 'true');
|
242
|
-
} else {
|
243
|
-
this.button.classList.remove('disabled');
|
244
|
-
this.button.removeAttribute('aria-disabled');
|
245
|
-
}
|
246
|
-
}
|
247
|
-
|
248
|
-
public setSelected(selected: boolean) {
|
249
|
-
const currentlySelected = this.isSelected();
|
250
|
-
if (currentlySelected === selected) {
|
251
|
-
return;
|
252
|
-
}
|
253
|
-
|
254
|
-
if (selected) {
|
255
|
-
this.container.classList.add('selected');
|
256
|
-
this.button.ariaSelected = 'true';
|
257
|
-
} else {
|
258
|
-
this.container.classList.remove('selected');
|
259
|
-
this.button.ariaSelected = 'false';
|
260
|
-
}
|
261
|
-
}
|
262
|
-
|
263
|
-
protected setDropdownVisible(visible: boolean) {
|
264
|
-
const currentlyVisible = this.container.classList.contains('dropdownVisible');
|
265
|
-
if (currentlyVisible === visible) {
|
266
|
-
return;
|
267
|
-
}
|
268
|
-
|
269
|
-
if (visible) {
|
270
|
-
this.dropdownContainer.classList.remove('hidden');
|
271
|
-
this.container.classList.add('dropdownVisible');
|
272
|
-
this.editor.announceForAccessibility(
|
273
|
-
this.localizationTable.dropdownShown(this.getTitle())
|
274
|
-
);
|
275
|
-
|
276
|
-
this.editor.notifier.dispatch(EditorEventType.ToolbarDropdownShown, {
|
277
|
-
kind: EditorEventType.ToolbarDropdownShown,
|
278
|
-
parentWidget: this,
|
279
|
-
});
|
280
|
-
} else {
|
281
|
-
this.dropdownContainer.classList.add('hidden');
|
282
|
-
this.container.classList.remove('dropdownVisible');
|
283
|
-
this.editor.announceForAccessibility(
|
284
|
-
this.localizationTable.dropdownHidden(this.getTitle())
|
285
|
-
);
|
286
|
-
}
|
287
|
-
|
288
|
-
this.repositionDropdown();
|
289
|
-
}
|
290
|
-
|
291
|
-
public canBeInOverflowMenu(): boolean {
|
292
|
-
return true;
|
293
|
-
}
|
294
|
-
|
295
|
-
public getButtonWidth(): number {
|
296
|
-
return this.button.clientWidth;
|
297
|
-
}
|
298
|
-
|
299
|
-
public isHidden(): boolean {
|
300
|
-
return this.container.style.display === 'none';
|
301
|
-
}
|
302
|
-
|
303
|
-
public setHidden(hidden: boolean) {
|
304
|
-
this.container.style.display = hidden ? 'none' : '';
|
305
|
-
}
|
306
|
-
|
307
|
-
protected repositionDropdown() {
|
308
|
-
const dropdownBBox = this.dropdownContainer.getBoundingClientRect();
|
309
|
-
const screenWidth = document.body.clientWidth;
|
310
|
-
|
311
|
-
if (dropdownBBox.left > screenWidth / 2) {
|
312
|
-
this.dropdownContainer.style.marginLeft = this.button.clientWidth + 'px';
|
313
|
-
this.dropdownContainer.style.transform = 'translate(-100%, 0)';
|
314
|
-
} else {
|
315
|
-
this.dropdownContainer.style.marginLeft = '';
|
316
|
-
this.dropdownContainer.style.transform = '';
|
317
|
-
}
|
318
|
-
}
|
319
|
-
|
320
|
-
/** Set whether the widget is contained within another. @internal */
|
321
|
-
public setIsToplevel(toplevel: boolean) {
|
322
|
-
this.toplevel = toplevel;
|
323
|
-
}
|
324
|
-
|
325
|
-
protected isDropdownVisible(): boolean {
|
326
|
-
return !this.dropdownContainer.classList.contains('hidden');
|
327
|
-
}
|
328
|
-
|
329
|
-
protected isSelected(): boolean {
|
330
|
-
return this.container.classList.contains('selected');
|
331
|
-
}
|
332
|
-
|
333
|
-
private createDropdownIcon(): Element {
|
334
|
-
const icon = this.editor.icons.makeDropdownIcon();
|
335
|
-
icon.classList.add(`${toolbarCSSPrefix}showHideDropdownIcon`);
|
336
|
-
return icon;
|
337
|
-
}
|
338
|
-
|
339
|
-
/**
|
340
|
-
* Serialize state associated with this widget.
|
341
|
-
* Override this method to allow saving/restoring from state on application load.
|
342
|
-
*
|
343
|
-
* Overriders should call `super` and include the output of `super.serializeState` in
|
344
|
-
* the output dictionary.
|
345
|
-
*
|
346
|
-
* Clients should not rely on the output from `saveState` being in any particular
|
347
|
-
* format.
|
348
|
-
*/
|
349
|
-
public serializeState(): SavedToolbuttonState {
|
350
|
-
const subwidgetState: Record<string, any> = {};
|
351
|
-
|
352
|
-
// Save all subwidget state.
|
353
|
-
for (const subwidgetId in this.subWidgets) {
|
354
|
-
subwidgetState[subwidgetId] = this.subWidgets[subwidgetId].serializeState();
|
355
|
-
}
|
356
|
-
|
357
|
-
return {
|
358
|
-
subwidgetState,
|
359
|
-
};
|
360
|
-
}
|
361
|
-
|
362
|
-
/**
|
363
|
-
* Restore widget state from serialized data. See also `saveState`.
|
364
|
-
*
|
365
|
-
* Overriders must call `super`.
|
366
|
-
*/
|
367
|
-
public deserializeFrom(state: SavedToolbuttonState): void {
|
368
|
-
if (state.subwidgetState) {
|
369
|
-
// Deserialize all subwidgets.
|
370
|
-
for (const subwidgetId in state.subwidgetState) {
|
371
|
-
if (subwidgetId in this.subWidgets) {
|
372
|
-
this.subWidgets[subwidgetId].deserializeFrom(state.subwidgetState[subwidgetId]);
|
373
|
-
}
|
374
|
-
}
|
375
|
-
}
|
376
|
-
}
|
377
|
-
}
|
@@ -1,167 +0,0 @@
|
|
1
|
-
import Color4 from '../../Color4';
|
2
|
-
import Editor from '../../Editor';
|
3
|
-
import { EditorImageEventType } from '../../EditorImage';
|
4
|
-
import Rect2 from '../../math/Rect2';
|
5
|
-
import { EditorEventType } from '../../types';
|
6
|
-
import { toolbarCSSPrefix } from '../HTMLToolbar';
|
7
|
-
import { ToolbarLocalization } from '../localization';
|
8
|
-
import makeColorInput from '../makeColorInput';
|
9
|
-
import BaseWidget from './BaseWidget';
|
10
|
-
|
11
|
-
export default class DocumentPropertiesWidget extends BaseWidget {
|
12
|
-
private updateDropdownContent: ()=>void = () => {};
|
13
|
-
|
14
|
-
public constructor(editor: Editor, localizationTable?: ToolbarLocalization) {
|
15
|
-
super(editor, 'zoom-widget', localizationTable);
|
16
|
-
|
17
|
-
// Make it possible to open the dropdown, even if this widget isn't selected.
|
18
|
-
this.container.classList.add('dropdownShowable');
|
19
|
-
|
20
|
-
this.editor.notifier.on(EditorEventType.UndoRedoStackUpdated, () => {
|
21
|
-
this.queueDropdownUpdate();
|
22
|
-
});
|
23
|
-
|
24
|
-
|
25
|
-
this.editor.image.notifier.on(EditorImageEventType.ExportViewportChanged, () => {
|
26
|
-
this.queueDropdownUpdate();
|
27
|
-
});
|
28
|
-
}
|
29
|
-
|
30
|
-
protected getTitle(): string {
|
31
|
-
return this.localizationTable.documentProperties;
|
32
|
-
}
|
33
|
-
|
34
|
-
protected createIcon(): Element {
|
35
|
-
return this.editor.icons.makeConfigureDocumentIcon();
|
36
|
-
}
|
37
|
-
|
38
|
-
protected handleClick() {
|
39
|
-
this.setDropdownVisible(!this.isDropdownVisible());
|
40
|
-
this.queueDropdownUpdate();
|
41
|
-
}
|
42
|
-
|
43
|
-
private dropdownUpdateQueued: boolean = false;
|
44
|
-
private queueDropdownUpdate() {
|
45
|
-
if (!this.dropdownUpdateQueued) {
|
46
|
-
requestAnimationFrame(() => this.updateDropdown());
|
47
|
-
this.dropdownUpdateQueued = true;
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
private updateDropdown() {
|
52
|
-
this.dropdownUpdateQueued = false;
|
53
|
-
|
54
|
-
if (this.isDropdownVisible()) {
|
55
|
-
this.updateDropdownContent();
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
private setBackgroundColor(color: Color4) {
|
60
|
-
this.editor.dispatch(this.editor.setBackgroundColor(color));
|
61
|
-
}
|
62
|
-
|
63
|
-
private getBackgroundColor() {
|
64
|
-
return this.editor.estimateBackgroundColor();
|
65
|
-
}
|
66
|
-
|
67
|
-
private updateImportExportRectSize(size: { width?: number, height?: number }) {
|
68
|
-
const filterDimension = (dim: number|undefined) => {
|
69
|
-
if (dim !== undefined && (!isFinite(dim) || dim <= 0)) {
|
70
|
-
dim = 100;
|
71
|
-
}
|
72
|
-
|
73
|
-
return dim;
|
74
|
-
};
|
75
|
-
|
76
|
-
const width = filterDimension(size.width);
|
77
|
-
const height = filterDimension(size.height);
|
78
|
-
|
79
|
-
const currentRect = this.editor.getImportExportRect();
|
80
|
-
const newRect = new Rect2(
|
81
|
-
currentRect.x, currentRect.y,
|
82
|
-
width ?? currentRect.w, height ?? currentRect.h
|
83
|
-
);
|
84
|
-
|
85
|
-
this.editor.dispatch(this.editor.image.setImportExportRect(newRect));
|
86
|
-
this.editor.queueRerender();
|
87
|
-
}
|
88
|
-
|
89
|
-
private static idCounter = 0;
|
90
|
-
|
91
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
92
|
-
const container = document.createElement('div');
|
93
|
-
container.classList.add(`${toolbarCSSPrefix}spacedList`);
|
94
|
-
|
95
|
-
const backgroundColorRow = document.createElement('div');
|
96
|
-
const backgroundColorLabel = document.createElement('label');
|
97
|
-
|
98
|
-
backgroundColorLabel.innerText = this.localizationTable.backgroundColor;
|
99
|
-
|
100
|
-
const [ colorInput, backgroundColorInputContainer, setBgColorInputValue ] = makeColorInput(this.editor, color => {
|
101
|
-
if (!color.eq(this.getBackgroundColor())) {
|
102
|
-
this.setBackgroundColor(color);
|
103
|
-
}
|
104
|
-
});
|
105
|
-
|
106
|
-
colorInput.id = `${toolbarCSSPrefix}docPropertiesColorInput-${DocumentPropertiesWidget.idCounter++}`;
|
107
|
-
backgroundColorLabel.htmlFor = colorInput.id;
|
108
|
-
|
109
|
-
backgroundColorRow.replaceChildren(backgroundColorLabel, backgroundColorInputContainer);
|
110
|
-
|
111
|
-
const addDimensionRow = (labelContent: string, onChange: (value: number)=>void) => {
|
112
|
-
const row = document.createElement('div');
|
113
|
-
const label = document.createElement('label');
|
114
|
-
const spacer = document.createElement('span');
|
115
|
-
const input = document.createElement('input');
|
116
|
-
|
117
|
-
label.innerText = labelContent;
|
118
|
-
input.type = 'number';
|
119
|
-
input.min = '0';
|
120
|
-
input.id = `${toolbarCSSPrefix}docPropertiesDimensionRow-${DocumentPropertiesWidget.idCounter++}`;
|
121
|
-
label.htmlFor = input.id;
|
122
|
-
|
123
|
-
spacer.style.flexGrow = '1';
|
124
|
-
input.style.flexGrow = '2';
|
125
|
-
input.style.width = '25px';
|
126
|
-
|
127
|
-
row.style.display = 'flex';
|
128
|
-
|
129
|
-
input.oninput = () => {
|
130
|
-
onChange(parseFloat(input.value));
|
131
|
-
};
|
132
|
-
|
133
|
-
row.replaceChildren(label, spacer, input);
|
134
|
-
|
135
|
-
return {
|
136
|
-
setValue: (value: number) => {
|
137
|
-
input.value = value.toString();
|
138
|
-
},
|
139
|
-
element: row,
|
140
|
-
};
|
141
|
-
};
|
142
|
-
|
143
|
-
const imageWidthRow = addDimensionRow(this.localizationTable.imageWidthOption, (value: number) => {
|
144
|
-
this.updateImportExportRectSize({ width: value });
|
145
|
-
});
|
146
|
-
const imageHeightRow = addDimensionRow(this.localizationTable.imageHeightOption, (value: number) => {
|
147
|
-
this.updateImportExportRectSize({ height: value });
|
148
|
-
});
|
149
|
-
|
150
|
-
this.updateDropdownContent = () => {
|
151
|
-
setBgColorInputValue(this.getBackgroundColor());
|
152
|
-
|
153
|
-
const importExportRect = this.editor.getImportExportRect();
|
154
|
-
imageWidthRow.setValue(importExportRect.width);
|
155
|
-
imageHeightRow.setValue(importExportRect.height);
|
156
|
-
};
|
157
|
-
this.updateDropdownContent();
|
158
|
-
|
159
|
-
|
160
|
-
container.replaceChildren(
|
161
|
-
backgroundColorRow, imageWidthRow.element, imageHeightRow.element
|
162
|
-
);
|
163
|
-
dropdown.replaceChildren(container);
|
164
|
-
|
165
|
-
return true;
|
166
|
-
}
|
167
|
-
}
|
@@ -1,85 +0,0 @@
|
|
1
|
-
import Editor from '../../Editor';
|
2
|
-
import Eraser from '../../tools/Eraser';
|
3
|
-
import { EditorEventType } from '../../types';
|
4
|
-
import { toolbarCSSPrefix } from '../HTMLToolbar';
|
5
|
-
import { ToolbarLocalization } from '../localization';
|
6
|
-
import BaseToolWidget from './BaseToolWidget';
|
7
|
-
import { SavedToolbuttonState } from './BaseWidget';
|
8
|
-
|
9
|
-
export default class EraserToolWidget extends BaseToolWidget {
|
10
|
-
private thicknessInput: HTMLInputElement|null = null;
|
11
|
-
public constructor(
|
12
|
-
editor: Editor,
|
13
|
-
private tool: Eraser,
|
14
|
-
localizationTable?: ToolbarLocalization
|
15
|
-
) {
|
16
|
-
super(editor, tool, 'eraser-tool-widget', localizationTable);
|
17
|
-
|
18
|
-
this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
|
19
|
-
if (toolEvt.kind === EditorEventType.ToolUpdated && toolEvt.tool === this.tool) {
|
20
|
-
this.updateInputs();
|
21
|
-
this.updateIcon();
|
22
|
-
}
|
23
|
-
});
|
24
|
-
}
|
25
|
-
|
26
|
-
protected getTitle(): string {
|
27
|
-
return this.localizationTable.eraser;
|
28
|
-
}
|
29
|
-
|
30
|
-
protected createIcon(): Element {
|
31
|
-
return this.editor.icons.makeEraserIcon(this.tool.getThickness());
|
32
|
-
}
|
33
|
-
|
34
|
-
private updateInputs() {
|
35
|
-
if (this.thicknessInput) {
|
36
|
-
this.thicknessInput.value = `${this.tool.getThickness()}`;
|
37
|
-
}
|
38
|
-
}
|
39
|
-
|
40
|
-
private static nextThicknessInputId = 0;
|
41
|
-
|
42
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
43
|
-
const thicknessLabel = document.createElement('label');
|
44
|
-
this.thicknessInput = document.createElement('input');
|
45
|
-
|
46
|
-
this.thicknessInput.type = 'range';
|
47
|
-
this.thicknessInput.min = '4';
|
48
|
-
this.thicknessInput.max = '40';
|
49
|
-
this.thicknessInput.oninput = () => {
|
50
|
-
this.tool.setThickness(parseFloat(this.thicknessInput!.value));
|
51
|
-
};
|
52
|
-
this.thicknessInput.id = `${toolbarCSSPrefix}eraserThicknessInput${EraserToolWidget.nextThicknessInputId++}`;
|
53
|
-
|
54
|
-
thicknessLabel.innerText = this.localizationTable.thicknessLabel;
|
55
|
-
thicknessLabel.htmlFor = this.thicknessInput.id;
|
56
|
-
|
57
|
-
this.updateInputs();
|
58
|
-
dropdown.replaceChildren(thicknessLabel, this.thicknessInput);
|
59
|
-
return true;
|
60
|
-
}
|
61
|
-
|
62
|
-
public serializeState(): SavedToolbuttonState {
|
63
|
-
return {
|
64
|
-
...super.serializeState(),
|
65
|
-
|
66
|
-
thickness: this.tool.getThickness(),
|
67
|
-
};
|
68
|
-
}
|
69
|
-
|
70
|
-
public deserializeFrom(state: SavedToolbuttonState) {
|
71
|
-
super.deserializeFrom(state);
|
72
|
-
|
73
|
-
if (state.thickness) {
|
74
|
-
const parsedThickness = parseFloat(state.thickness);
|
75
|
-
|
76
|
-
if (typeof parsedThickness !== 'number' || !isFinite(parsedThickness)) {
|
77
|
-
throw new Error(
|
78
|
-
`Deserializing property ${parsedThickness} is not a number or is not finite.`
|
79
|
-
);
|
80
|
-
}
|
81
|
-
|
82
|
-
this.tool.setThickness(parsedThickness);
|
83
|
-
}
|
84
|
-
}
|
85
|
-
}
|