js-draw 1.14.0 → 1.15.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Editor.css +285 -1
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.js +5 -0
- package/dist/cjs/components/util/StrokeSmoother.js +11 -4
- package/dist/cjs/rendering/caching/CacheRecordManager.js +1 -1
- package/dist/cjs/testing/sendHtmlSwipe.d.ts +4 -0
- package/dist/cjs/testing/sendHtmlSwipe.js +14 -0
- package/dist/cjs/toolbar/EdgeToolbar.d.ts +1 -0
- package/dist/cjs/toolbar/EdgeToolbar.js +30 -110
- package/dist/cjs/toolbar/IconProvider.d.ts +1 -0
- package/dist/cjs/toolbar/IconProvider.js +27 -0
- package/dist/cjs/toolbar/localization.d.ts +28 -1
- package/dist/cjs/toolbar/localization.js +30 -1
- package/dist/cjs/toolbar/utils/HelpDisplay.d.ts +37 -0
- package/dist/cjs/toolbar/utils/HelpDisplay.js +442 -0
- package/dist/cjs/toolbar/utils/HelpDisplay.test.d.ts +1 -0
- package/dist/cjs/toolbar/utils/localization.d.ts +9 -0
- package/dist/cjs/toolbar/utils/localization.js +11 -0
- package/dist/cjs/toolbar/utils/makeDraggable.d.ts +16 -0
- package/dist/cjs/toolbar/utils/makeDraggable.js +130 -0
- package/dist/cjs/toolbar/widgets/ActionButtonWidget.d.ts +7 -0
- package/dist/cjs/toolbar/widgets/ActionButtonWidget.js +14 -2
- package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +8 -1
- package/dist/cjs/toolbar/widgets/BaseWidget.js +25 -3
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.d.ts +3 -1
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +19 -4
- package/dist/cjs/toolbar/widgets/HandToolWidget.d.ts +3 -1
- package/dist/cjs/toolbar/widgets/HandToolWidget.js +19 -7
- package/dist/cjs/toolbar/widgets/InsertImageWidget.js +1 -0
- package/dist/cjs/toolbar/widgets/PenToolWidget.d.ts +4 -2
- package/dist/cjs/toolbar/widgets/PenToolWidget.js +27 -8
- package/dist/cjs/toolbar/widgets/SelectionToolWidget.d.ts +3 -1
- package/dist/cjs/toolbar/widgets/SelectionToolWidget.js +19 -5
- package/dist/cjs/toolbar/widgets/components/makeColorInput.d.ts +2 -0
- package/dist/cjs/toolbar/widgets/components/makeColorInput.js +17 -7
- package/dist/cjs/toolbar/widgets/components/makeGridSelector.d.ts +6 -0
- package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +3 -0
- package/dist/cjs/tools/FindTool.js +18 -5
- package/dist/cjs/util/addLongPressOrHoverCssClasses.d.ts +3 -1
- package/dist/cjs/util/addLongPressOrHoverCssClasses.js +2 -1
- package/dist/cjs/util/cloneElementWithStyles.d.ts +6 -0
- package/dist/cjs/util/cloneElementWithStyles.js +32 -0
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.mjs +5 -0
- package/dist/mjs/components/util/StrokeSmoother.mjs +11 -4
- package/dist/mjs/rendering/caching/CacheRecordManager.mjs +1 -1
- package/dist/mjs/testing/sendHtmlSwipe.d.ts +4 -0
- package/dist/mjs/testing/sendHtmlSwipe.mjs +12 -0
- package/dist/mjs/toolbar/EdgeToolbar.d.ts +1 -0
- package/dist/mjs/toolbar/EdgeToolbar.mjs +30 -110
- package/dist/mjs/toolbar/IconProvider.d.ts +1 -0
- package/dist/mjs/toolbar/IconProvider.mjs +27 -0
- package/dist/mjs/toolbar/localization.d.ts +28 -1
- package/dist/mjs/toolbar/localization.mjs +30 -1
- package/dist/mjs/toolbar/utils/HelpDisplay.d.ts +37 -0
- package/dist/mjs/toolbar/utils/HelpDisplay.mjs +437 -0
- package/dist/mjs/toolbar/utils/HelpDisplay.test.d.ts +1 -0
- package/dist/mjs/toolbar/utils/localization.d.ts +9 -0
- package/dist/mjs/toolbar/utils/localization.mjs +8 -0
- package/dist/mjs/toolbar/utils/makeDraggable.d.ts +16 -0
- package/dist/mjs/toolbar/utils/makeDraggable.mjs +128 -0
- package/dist/mjs/toolbar/widgets/ActionButtonWidget.d.ts +7 -0
- package/dist/mjs/toolbar/widgets/ActionButtonWidget.mjs +14 -2
- package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +8 -1
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +25 -3
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.d.ts +3 -1
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +19 -4
- package/dist/mjs/toolbar/widgets/HandToolWidget.d.ts +3 -1
- package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +19 -7
- package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +1 -0
- package/dist/mjs/toolbar/widgets/PenToolWidget.d.ts +4 -2
- package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +27 -8
- package/dist/mjs/toolbar/widgets/SelectionToolWidget.d.ts +3 -1
- package/dist/mjs/toolbar/widgets/SelectionToolWidget.mjs +19 -5
- package/dist/mjs/toolbar/widgets/components/makeColorInput.d.ts +2 -0
- package/dist/mjs/toolbar/widgets/components/makeColorInput.mjs +17 -7
- package/dist/mjs/toolbar/widgets/components/makeGridSelector.d.ts +6 -0
- package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +3 -0
- package/dist/mjs/tools/FindTool.mjs +18 -5
- package/dist/mjs/util/addLongPressOrHoverCssClasses.d.ts +3 -1
- package/dist/mjs/util/addLongPressOrHoverCssClasses.mjs +2 -1
- package/dist/mjs/util/cloneElementWithStyles.d.ts +6 -0
- package/dist/mjs/util/cloneElementWithStyles.mjs +30 -0
- package/dist/mjs/version.mjs +1 -1
- package/package.json +2 -2
- package/src/toolbar/EdgeToolbar.scss +23 -2
- package/src/toolbar/toolbar.scss +2 -0
- package/src/toolbar/utils/HelpDisplay.scss +315 -0
- package/src/toolbar/widgets/components/makeColorInput.scss +7 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const math_1 = require("@js-draw/math");
|
4
|
+
const makeDraggable = (dragElement, options) => {
|
5
|
+
const dragElements = [
|
6
|
+
...options.draggableChildElements,
|
7
|
+
dragElement,
|
8
|
+
];
|
9
|
+
let lastX = 0;
|
10
|
+
let lastY = 0;
|
11
|
+
let startX = 0;
|
12
|
+
let startY = 0;
|
13
|
+
let pointerDown = false;
|
14
|
+
let capturedPointerId = null;
|
15
|
+
const isDraggableElement = (element) => {
|
16
|
+
if (!element) {
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
if (dragElements.includes(element)) {
|
20
|
+
return true;
|
21
|
+
}
|
22
|
+
// Some inputs handle dragging themselves. Don't also interpret such gestures
|
23
|
+
// as dragging the dropdown.
|
24
|
+
const undraggableElementTypes = ['INPUT', 'SELECT', 'IMG'];
|
25
|
+
let hasSuitableAncestors = false;
|
26
|
+
let ancestor = element.parentElement;
|
27
|
+
while (ancestor) {
|
28
|
+
if (undraggableElementTypes.includes(ancestor.tagName)) {
|
29
|
+
break;
|
30
|
+
}
|
31
|
+
if (dragElements.includes(ancestor)) {
|
32
|
+
hasSuitableAncestors = true;
|
33
|
+
break;
|
34
|
+
}
|
35
|
+
ancestor = ancestor.parentElement;
|
36
|
+
}
|
37
|
+
return !undraggableElementTypes.includes(element.tagName) && hasSuitableAncestors;
|
38
|
+
};
|
39
|
+
const removeEventListenerCallbacks = [];
|
40
|
+
const addEventListener = (listenerType, listener, options) => {
|
41
|
+
dragElement.addEventListener(listenerType, listener, options);
|
42
|
+
removeEventListenerCallbacks.push(() => {
|
43
|
+
dragElement.removeEventListener(listenerType, listener);
|
44
|
+
});
|
45
|
+
};
|
46
|
+
const clickThreshold = 5;
|
47
|
+
// Returns whether the current (or if no current, **the last**) gesture is roughly a click.
|
48
|
+
// Because this can be called **after** a gesture has just ended, it should not require
|
49
|
+
// the gesture to be in progress.
|
50
|
+
const isRoughlyClick = () => {
|
51
|
+
return Math.hypot(lastX - startX, lastY - startY) < clickThreshold;
|
52
|
+
};
|
53
|
+
let startedDragging = false;
|
54
|
+
addEventListener('pointerdown', event => {
|
55
|
+
if (event.defaultPrevented || !isDraggableElement(event.target)) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
if (event.isPrimary) {
|
59
|
+
startedDragging = false;
|
60
|
+
lastX = event.clientX;
|
61
|
+
lastY = event.clientY;
|
62
|
+
startX = event.clientX;
|
63
|
+
startY = event.clientY;
|
64
|
+
capturedPointerId = null;
|
65
|
+
pointerDown = true;
|
66
|
+
}
|
67
|
+
}, { passive: true });
|
68
|
+
const onGestureEnd = (_event) => {
|
69
|
+
// If the pointerup/pointercancel event was for a pointer not being tracked,
|
70
|
+
if (!pointerDown) {
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
if (capturedPointerId !== null) {
|
74
|
+
dragElement.releasePointerCapture(capturedPointerId);
|
75
|
+
capturedPointerId = null;
|
76
|
+
}
|
77
|
+
options.onDragEnd({
|
78
|
+
roughlyClick: isRoughlyClick(),
|
79
|
+
endTimestamp: performance.now(),
|
80
|
+
displacement: math_1.Vec2.of(lastX - startX, lastY - startY),
|
81
|
+
});
|
82
|
+
pointerDown = false;
|
83
|
+
startedDragging = false;
|
84
|
+
};
|
85
|
+
addEventListener('pointermove', event => {
|
86
|
+
if (!event.isPrimary || !pointerDown) {
|
87
|
+
return undefined;
|
88
|
+
}
|
89
|
+
// Mouse event and no buttons pressed? Cancel the event.
|
90
|
+
// This can happen if the event was canceled by a focus change (e.g. by opening a
|
91
|
+
// right-click menu).
|
92
|
+
if (event.pointerType === 'mouse' && event.buttons === 0) {
|
93
|
+
onGestureEnd(event);
|
94
|
+
return undefined;
|
95
|
+
}
|
96
|
+
// Only capture after motion -- capturing early prevents click events in Chrome.
|
97
|
+
if (capturedPointerId === null && !isRoughlyClick()) {
|
98
|
+
dragElement.setPointerCapture(event.pointerId);
|
99
|
+
capturedPointerId = event.pointerId;
|
100
|
+
}
|
101
|
+
const x = event.clientX;
|
102
|
+
const y = event.clientY;
|
103
|
+
const dx = x - lastX;
|
104
|
+
const dy = y - lastY;
|
105
|
+
const isClick = Math.abs(x - startX) <= clickThreshold && Math.abs(y - startY) <= clickThreshold;
|
106
|
+
if (!isClick || startedDragging) {
|
107
|
+
options.onDrag(dx, dy, math_1.Vec2.of(x - startX, y - startY));
|
108
|
+
lastX = x;
|
109
|
+
lastY = y;
|
110
|
+
startedDragging = true;
|
111
|
+
}
|
112
|
+
});
|
113
|
+
addEventListener('pointerleave', event => {
|
114
|
+
// Capture the pointer if it exits the container while dragging.
|
115
|
+
if (capturedPointerId === null && pointerDown && event.isPrimary) {
|
116
|
+
dragElement.setPointerCapture(event.pointerId);
|
117
|
+
capturedPointerId = event.pointerId;
|
118
|
+
}
|
119
|
+
});
|
120
|
+
addEventListener('pointerup', onGestureEnd);
|
121
|
+
addEventListener('pointercancel', onGestureEnd);
|
122
|
+
return {
|
123
|
+
removeListeners: () => {
|
124
|
+
for (const removeListenerCallback of removeEventListenerCallbacks) {
|
125
|
+
removeListenerCallback();
|
126
|
+
}
|
127
|
+
},
|
128
|
+
};
|
129
|
+
};
|
130
|
+
exports.default = makeDraggable;
|
@@ -8,6 +8,13 @@ export default class ActionButtonWidget extends BaseWidget {
|
|
8
8
|
protected clickAction: () => void;
|
9
9
|
protected mustBeToplevel: boolean;
|
10
10
|
constructor(editor: Editor, id: string, makeIcon: () => Element | null, title: string, clickAction: () => void, localizationTable?: ToolbarLocalization, mustBeToplevel?: boolean, autoDisableInReadOnlyEditors?: boolean);
|
11
|
+
/**
|
12
|
+
* Sets the text shown in a help overlay for this button.
|
13
|
+
*
|
14
|
+
* See {@link getHelpText}.
|
15
|
+
*/
|
16
|
+
setHelpText(helpText: string): void;
|
17
|
+
protected getHelpText(): string | undefined;
|
11
18
|
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
12
19
|
protected handleClick(): void;
|
13
20
|
protected getTitle(): string;
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
15
15
|
};
|
16
|
-
var _ActionButtonWidget_autoDisableInReadOnlyEditors;
|
16
|
+
var _ActionButtonWidget_autoDisableInReadOnlyEditors, _ActionButtonWidget_helpText;
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
18
|
const BaseWidget_1 = __importDefault(require("./BaseWidget"));
|
19
19
|
class ActionButtonWidget extends BaseWidget_1.default {
|
@@ -24,8 +24,20 @@ class ActionButtonWidget extends BaseWidget_1.default {
|
|
24
24
|
this.clickAction = clickAction;
|
25
25
|
this.mustBeToplevel = mustBeToplevel;
|
26
26
|
_ActionButtonWidget_autoDisableInReadOnlyEditors.set(this, void 0);
|
27
|
+
_ActionButtonWidget_helpText.set(this, undefined);
|
27
28
|
__classPrivateFieldSet(this, _ActionButtonWidget_autoDisableInReadOnlyEditors, autoDisableInReadOnlyEditors, "f");
|
28
29
|
}
|
30
|
+
/**
|
31
|
+
* Sets the text shown in a help overlay for this button.
|
32
|
+
*
|
33
|
+
* See {@link getHelpText}.
|
34
|
+
*/
|
35
|
+
setHelpText(helpText) {
|
36
|
+
__classPrivateFieldSet(this, _ActionButtonWidget_helpText, helpText, "f");
|
37
|
+
}
|
38
|
+
getHelpText() {
|
39
|
+
return __classPrivateFieldGet(this, _ActionButtonWidget_helpText, "f");
|
40
|
+
}
|
29
41
|
shouldAutoDisableInReadOnlyEditor() {
|
30
42
|
return __classPrivateFieldGet(this, _ActionButtonWidget_autoDisableInReadOnlyEditors, "f");
|
31
43
|
}
|
@@ -45,5 +57,5 @@ class ActionButtonWidget extends BaseWidget_1.default {
|
|
45
57
|
return this.mustBeToplevel;
|
46
58
|
}
|
47
59
|
}
|
48
|
-
_ActionButtonWidget_autoDisableInReadOnlyEditors = new WeakMap();
|
60
|
+
_ActionButtonWidget_autoDisableInReadOnlyEditors = new WeakMap(), _ActionButtonWidget_helpText = new WeakMap();
|
49
61
|
exports.default = ActionButtonWidget;
|
@@ -2,6 +2,7 @@ import Editor from '../../Editor';
|
|
2
2
|
import { KeyPressEvent } from '../../inputEvents';
|
3
3
|
import { ToolbarLocalization } from '../localization';
|
4
4
|
import { WidgetContentLayoutManager } from './layout/types';
|
5
|
+
import HelpDisplay from '../utils/HelpDisplay';
|
5
6
|
export type SavedToolbuttonState = Record<string, any>;
|
6
7
|
/**
|
7
8
|
* A set of labels that allow toolbar themes to treat buttons differently.
|
@@ -66,7 +67,13 @@ export default abstract class BaseWidget {
|
|
66
67
|
getUniqueIdIn(container: Record<string, BaseWidget>): string;
|
67
68
|
protected abstract getTitle(): string;
|
68
69
|
protected abstract createIcon(): Element | null;
|
69
|
-
protected fillDropdown(dropdown: HTMLElement): boolean;
|
70
|
+
protected fillDropdown(dropdown: HTMLElement, helpDisplay?: HelpDisplay): boolean;
|
71
|
+
/**
|
72
|
+
* Should return a 1-2 sentence description of the widget.
|
73
|
+
*
|
74
|
+
* At present, this is only used if this widget has an associated dropdown.
|
75
|
+
*/
|
76
|
+
protected getHelpText(): undefined | string;
|
70
77
|
/** @deprecated Renamed to `setUpButtonEventListeners`. */
|
71
78
|
protected setupActionBtnClickListener(button: HTMLElement): void;
|
72
79
|
protected setUpButtonEventListeners(button: HTMLElement): void;
|
@@ -21,6 +21,7 @@ const inputEvents_1 = require("../../inputEvents");
|
|
21
21
|
const constants_1 = require("../constants");
|
22
22
|
const DropdownLayoutManager_1 = __importDefault(require("./layout/DropdownLayoutManager"));
|
23
23
|
const addLongPressOrHoverCssClasses_1 = __importDefault(require("../../util/addLongPressOrHoverCssClasses"));
|
24
|
+
const HelpDisplay_1 = __importDefault(require("../utils/HelpDisplay"));
|
24
25
|
/**
|
25
26
|
* A set of labels that allow toolbar themes to treat buttons differently.
|
26
27
|
*/
|
@@ -133,17 +134,30 @@ class BaseWidget {
|
|
133
134
|
}
|
134
135
|
// Add content to the widget's associated dropdown menu.
|
135
136
|
// Returns true if such a menu should be created, false otherwise.
|
136
|
-
fillDropdown(dropdown) {
|
137
|
+
fillDropdown(dropdown, helpDisplay) {
|
137
138
|
if (Object.keys(this.subWidgets).length === 0) {
|
138
139
|
return false;
|
139
140
|
}
|
140
141
|
for (const widgetId in this.subWidgets) {
|
141
142
|
const widget = this.subWidgets[widgetId];
|
142
|
-
widget.addTo(dropdown);
|
143
|
+
const widgetElement = widget.addTo(dropdown);
|
143
144
|
widget.setIsToplevel(false);
|
145
|
+
// Add help information
|
146
|
+
const helpText = widget.getHelpText();
|
147
|
+
if (helpText) {
|
148
|
+
helpDisplay?.registerTextHelpForElement(widgetElement, helpText);
|
149
|
+
}
|
144
150
|
}
|
145
151
|
return true;
|
146
152
|
}
|
153
|
+
/**
|
154
|
+
* Should return a 1-2 sentence description of the widget.
|
155
|
+
*
|
156
|
+
* At present, this is only used if this widget has an associated dropdown.
|
157
|
+
*/
|
158
|
+
getHelpText() {
|
159
|
+
return undefined;
|
160
|
+
}
|
147
161
|
/** @deprecated Renamed to `setUpButtonEventListeners`. */
|
148
162
|
setupActionBtnClickListener(button) {
|
149
163
|
return this.setUpButtonEventListeners(button);
|
@@ -235,10 +249,15 @@ class BaseWidget {
|
|
235
249
|
this.container.replaceChildren();
|
236
250
|
this.button.replaceChildren(this.icon, this.label);
|
237
251
|
this.container.appendChild(this.button);
|
252
|
+
const helpDisplay = new HelpDisplay_1.default(content => this.editor.createHTMLOverlay(content), this.editor);
|
253
|
+
const helpText = this.getHelpText();
|
254
|
+
if (helpText) {
|
255
|
+
helpDisplay.registerTextHelpForElement(this.dropdownContent, [this.getTitle(), helpText].join('\n\n'));
|
256
|
+
}
|
238
257
|
// Clear the dropdownContainer in case this element is being moved to another
|
239
258
|
// parent.
|
240
259
|
this.dropdownContent.replaceChildren();
|
241
|
-
__classPrivateFieldSet(this, _BaseWidget_hasDropdown, this.fillDropdown(this.dropdownContent), "f");
|
260
|
+
__classPrivateFieldSet(this, _BaseWidget_hasDropdown, this.fillDropdown(this.dropdownContent, helpDisplay), "f");
|
242
261
|
if (__classPrivateFieldGet(this, _BaseWidget_hasDropdown, "f")) {
|
243
262
|
this.button.classList.add('has-dropdown');
|
244
263
|
// We're re-creating the dropdown.
|
@@ -264,6 +283,9 @@ class BaseWidget {
|
|
264
283
|
this.focus();
|
265
284
|
}
|
266
285
|
});
|
286
|
+
if (helpDisplay.hasHelpText()) {
|
287
|
+
this.dropdown.appendChild(helpDisplay.createToggleButton());
|
288
|
+
}
|
267
289
|
this.dropdown.appendChild(this.dropdownContent);
|
268
290
|
}
|
269
291
|
this.setDropdownVisible(false);
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import Editor from '../../Editor';
|
2
2
|
import { ToolbarLocalization } from '../localization';
|
3
3
|
import BaseWidget from './BaseWidget';
|
4
|
+
import HelpDisplay from '../utils/HelpDisplay';
|
4
5
|
export default class DocumentPropertiesWidget extends BaseWidget {
|
5
6
|
private updateDropdownContent;
|
6
7
|
constructor(editor: Editor, localizationTable?: ToolbarLocalization);
|
@@ -18,6 +19,7 @@ export default class DocumentPropertiesWidget extends BaseWidget {
|
|
18
19
|
/** Returns the type of the topmost background component */
|
19
20
|
private getBackgroundType;
|
20
21
|
private updateImportExportRectSize;
|
22
|
+
protected getHelpText(): string;
|
21
23
|
private static idCounter;
|
22
|
-
protected fillDropdown(dropdown: HTMLElement): boolean;
|
24
|
+
protected fillDropdown(dropdown: HTMLElement, helpDisplay?: HelpDisplay): boolean;
|
23
25
|
}
|
@@ -118,7 +118,10 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
118
118
|
this.editor.dispatch(this.editor.image.setImportExportRect(newRect));
|
119
119
|
this.editor.queueRerender();
|
120
120
|
}
|
121
|
-
|
121
|
+
getHelpText() {
|
122
|
+
return this.localizationTable.pageDropdown__baseHelpText;
|
123
|
+
}
|
124
|
+
fillDropdown(dropdown, helpDisplay) {
|
122
125
|
const container = document.createElement('div');
|
123
126
|
container.classList.add(`${constants_1.toolbarCSSPrefix}spacedList`, `${constants_1.toolbarCSSPrefix}nonbutton-controls-main-list`, `${constants_1.toolbarCSSPrefix}document-properties-widget`);
|
124
127
|
// Background color input
|
@@ -126,7 +129,7 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
126
129
|
const backgroundColorRow = document.createElement('div');
|
127
130
|
const backgroundColorLabel = document.createElement('label');
|
128
131
|
backgroundColorLabel.innerText = this.localizationTable.backgroundColor;
|
129
|
-
const { input: colorInput, container: backgroundColorInputContainer, setValue: setBgColorInputValue } = (0, makeColorInput_1.default)(this.editor, color => {
|
132
|
+
const { input: colorInput, container: backgroundColorInputContainer, setValue: setBgColorInputValue, registerWithHelpTextDisplay: registerHelpForInputs, } = (0, makeColorInput_1.default)(this.editor, color => {
|
130
133
|
if (!color.eq(this.getBackgroundColor())) {
|
131
134
|
this.setBackgroundColor(color);
|
132
135
|
}
|
@@ -134,9 +137,16 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
134
137
|
colorInput.id = `${constants_1.toolbarCSSPrefix}docPropertiesColorInput-${DocumentPropertiesWidget.idCounter++}`;
|
135
138
|
backgroundColorLabel.htmlFor = colorInput.id;
|
136
139
|
backgroundColorRow.replaceChildren(backgroundColorLabel, backgroundColorInputContainer);
|
137
|
-
|
140
|
+
const registerWithHelp = (helpDisplay) => {
|
141
|
+
if (!helpDisplay) {
|
142
|
+
return;
|
143
|
+
}
|
144
|
+
helpDisplay?.registerTextHelpForElement(backgroundColorRow, this.localizationTable.pageDropdown__backgroundColorHelpText);
|
145
|
+
registerHelpForInputs(helpDisplay);
|
146
|
+
};
|
147
|
+
return { setBgColorInputValue, backgroundColorRow, registerWithHelp, };
|
138
148
|
};
|
139
|
-
const { backgroundColorRow, setBgColorInputValue } = makeBackgroundColorInput();
|
149
|
+
const { backgroundColorRow, setBgColorInputValue, registerWithHelp: registerBackgroundRowWithHelp, } = makeBackgroundColorInput();
|
140
150
|
const makeCheckboxRow = (labelText, onChange) => {
|
141
151
|
const rowContainer = document.createElement('div');
|
142
152
|
const labelElement = document.createElement('label');
|
@@ -217,6 +227,11 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
217
227
|
aboutButton.onclick = () => {
|
218
228
|
this.editor.showAboutDialog();
|
219
229
|
};
|
230
|
+
// Add help text
|
231
|
+
registerBackgroundRowWithHelp(helpDisplay);
|
232
|
+
helpDisplay?.registerTextHelpForElement(useGridRow, this.localizationTable.pageDropdown__gridCheckboxHelpText);
|
233
|
+
helpDisplay?.registerTextHelpForElement(auroresizeRow, this.localizationTable.pageDropdown__autoresizeCheckboxHelpText);
|
234
|
+
helpDisplay?.registerTextHelpForElement(aboutButton, this.localizationTable.pageDropdown__aboutButtonHelpText);
|
220
235
|
this.updateDropdownContent = () => {
|
221
236
|
setBgColorInputValue(this.getBackgroundColor());
|
222
237
|
const autoresize = this.editor.image.getAutoresizeEnabled();
|
@@ -3,6 +3,7 @@ import PanZoom from '../../tools/PanZoom';
|
|
3
3
|
import { ToolbarLocalization } from '../localization';
|
4
4
|
import BaseToolWidget from './BaseToolWidget';
|
5
5
|
import { SavedToolbuttonState } from './BaseWidget';
|
6
|
+
import HelpDisplay from '../utils/HelpDisplay';
|
6
7
|
export default class HandToolWidget extends BaseToolWidget {
|
7
8
|
private allowTogglingBaseTool;
|
8
9
|
protected overridePanZoomTool: PanZoom;
|
@@ -13,7 +14,8 @@ export default class HandToolWidget extends BaseToolWidget {
|
|
13
14
|
protected getTitle(): string;
|
14
15
|
protected createIcon(): Element;
|
15
16
|
protected handleClick(): void;
|
16
|
-
protected
|
17
|
+
protected getHelpText(): string;
|
18
|
+
protected fillDropdown(dropdown: HTMLElement, helpDisplay?: HelpDisplay): boolean;
|
17
19
|
setSelected(selected: boolean): void;
|
18
20
|
serializeState(): SavedToolbuttonState;
|
19
21
|
deserializeFrom(state: SavedToolbuttonState): void;
|
@@ -34,7 +34,7 @@ const constants_1 = require("../constants");
|
|
34
34
|
const BaseToolWidget_1 = __importDefault(require("./BaseToolWidget"));
|
35
35
|
const BaseWidget_1 = __importDefault(require("./BaseWidget"));
|
36
36
|
const makeSeparator_1 = __importDefault(require("./components/makeSeparator"));
|
37
|
-
const makeZoomControl = (localizationTable, editor) => {
|
37
|
+
const makeZoomControl = (localizationTable, editor, helpDisplay) => {
|
38
38
|
const zoomLevelRow = document.createElement('div');
|
39
39
|
const increaseButton = document.createElement('button');
|
40
40
|
const decreaseButton = document.createElement('button');
|
@@ -83,15 +83,20 @@ const makeZoomControl = (localizationTable, editor) => {
|
|
83
83
|
const addToHistory = false;
|
84
84
|
editor.dispatch(Viewport_1.default.transformBy(editor.viewport.canvasToScreenTransform.inverse()), addToHistory);
|
85
85
|
};
|
86
|
+
helpDisplay?.registerTextHelpForElement(increaseButton, localizationTable.handDropdown__zoomInHelpText);
|
87
|
+
helpDisplay?.registerTextHelpForElement(decreaseButton, localizationTable.handDropdown__zoomOutHelpText);
|
88
|
+
helpDisplay?.registerTextHelpForElement(resetViewButton, localizationTable.handDropdown__resetViewHelpText);
|
89
|
+
helpDisplay?.registerTextHelpForElement(zoomLevelDisplay, localizationTable.handDropdown__zoomDisplayHelpText);
|
86
90
|
return zoomLevelRow;
|
87
91
|
};
|
88
92
|
class HandModeWidget extends BaseWidget_1.default {
|
89
|
-
constructor(editor, tool, flag, makeIcon, title, localizationTable) {
|
93
|
+
constructor(editor, tool, flag, makeIcon, title, helpText, localizationTable) {
|
90
94
|
super(editor, `pan-mode-${flag}`, localizationTable);
|
91
95
|
this.tool = tool;
|
92
96
|
this.flag = flag;
|
93
97
|
this.makeIcon = makeIcon;
|
94
98
|
this.title = title;
|
99
|
+
this.helpText = helpText;
|
95
100
|
editor.notifier.on(types_1.EditorEventType.ToolUpdated, toolEvt => {
|
96
101
|
if (toolEvt.kind === types_1.EditorEventType.ToolUpdated && toolEvt.tool === tool) {
|
97
102
|
const allEnabled = !!(tool.getMode() & PanZoom_1.PanZoomMode.SinglePointerGestures);
|
@@ -121,6 +126,9 @@ class HandModeWidget extends BaseWidget_1.default {
|
|
121
126
|
fillDropdown(_dropdown) {
|
122
127
|
return false;
|
123
128
|
}
|
129
|
+
getHelpText() {
|
130
|
+
return this.helpText;
|
131
|
+
}
|
124
132
|
}
|
125
133
|
class HandToolWidget extends BaseToolWidget_1.default {
|
126
134
|
constructor(editor,
|
@@ -145,8 +153,8 @@ class HandToolWidget extends BaseToolWidget_1.default {
|
|
145
153
|
this.container.classList.add('dropdownShowable');
|
146
154
|
}
|
147
155
|
// Controls for the overriding hand tool.
|
148
|
-
const touchPanningWidget = new HandModeWidget(editor, this.overridePanZoomTool, PanZoom_1.PanZoomMode.OneFingerTouchGestures, () => this.editor.icons.makeTouchPanningIcon(), localizationTable.touchPanning, localizationTable);
|
149
|
-
const rotationLockWidget = new HandModeWidget(editor, this.overridePanZoomTool, PanZoom_1.PanZoomMode.RotationLocked, () => this.editor.icons.makeRotationLockIcon(), localizationTable.lockRotation, localizationTable);
|
156
|
+
const touchPanningWidget = new HandModeWidget(editor, this.overridePanZoomTool, PanZoom_1.PanZoomMode.OneFingerTouchGestures, () => this.editor.icons.makeTouchPanningIcon(), localizationTable.touchPanning, localizationTable.handDropdown__touchPanningHelpText, localizationTable);
|
157
|
+
const rotationLockWidget = new HandModeWidget(editor, this.overridePanZoomTool, PanZoom_1.PanZoomMode.RotationLocked, () => this.editor.icons.makeRotationLockIcon(), localizationTable.lockRotation, localizationTable.handDropdown__lockRotationHelpText, localizationTable);
|
150
158
|
this.addSubWidget(touchPanningWidget);
|
151
159
|
this.addSubWidget(rotationLockWidget);
|
152
160
|
}
|
@@ -177,13 +185,17 @@ class HandToolWidget extends BaseToolWidget_1.default {
|
|
177
185
|
this.setDropdownVisible(!this.isDropdownVisible());
|
178
186
|
}
|
179
187
|
}
|
180
|
-
|
181
|
-
|
188
|
+
getHelpText() {
|
189
|
+
return this.localizationTable.handDropdown__baseHelpText;
|
190
|
+
}
|
191
|
+
fillDropdown(dropdown, helpDisplay) {
|
192
|
+
super.fillDropdown(dropdown, helpDisplay);
|
182
193
|
// The container for all actions that come after the toolbar buttons.
|
183
194
|
const nonbuttonActionContainer = document.createElement('div');
|
184
195
|
nonbuttonActionContainer.classList.add(`${constants_1.toolbarCSSPrefix}nonbutton-controls-main-list`);
|
185
196
|
(0, makeSeparator_1.default)().addTo(nonbuttonActionContainer);
|
186
|
-
|
197
|
+
const zoomControl = makeZoomControl(this.localizationTable, this.editor, helpDisplay);
|
198
|
+
nonbuttonActionContainer.appendChild(zoomControl);
|
187
199
|
dropdown.appendChild(nonbuttonActionContainer);
|
188
200
|
return true;
|
189
201
|
}
|
@@ -100,6 +100,7 @@ class InsertImageWidget extends BaseWidget_1.default {
|
|
100
100
|
imageAltTextLabel.htmlFor = altTextInputId;
|
101
101
|
imageAltTextLabel.innerText = this.localizationTable.inputAltText;
|
102
102
|
this.imageAltTextInput.type = 'text';
|
103
|
+
this.imageAltTextInput.placeholder = this.localizationTable.describeTheImage;
|
103
104
|
this.statusView.setAttribute('aria-live', 'polite');
|
104
105
|
this.submitButton.innerText = this.localizationTable.submit;
|
105
106
|
this.selectedFiles.onUpdateAndNow(async (files) => {
|
@@ -5,6 +5,7 @@ import { KeyPressEvent } from '../../inputEvents';
|
|
5
5
|
import { ToolbarLocalization } from '../localization';
|
6
6
|
import BaseToolWidget from './BaseToolWidget';
|
7
7
|
import { SavedToolbuttonState } from './BaseWidget';
|
8
|
+
import HelpDisplay from '../utils/HelpDisplay';
|
8
9
|
export interface PenTypeRecord {
|
9
10
|
name: string;
|
10
11
|
id: string;
|
@@ -24,11 +25,12 @@ export default class PenToolWidget extends BaseToolWidget {
|
|
24
25
|
private createIconForRecord;
|
25
26
|
protected createIcon(): Element;
|
26
27
|
private createPenTypeSelector;
|
27
|
-
protected createStrokeCorrectionOptions(): {
|
28
|
+
protected createStrokeCorrectionOptions(helpOverlay?: HelpDisplay): {
|
28
29
|
update: () => void;
|
29
30
|
addTo: (parent: HTMLElement) => void;
|
30
31
|
};
|
31
|
-
protected
|
32
|
+
protected getHelpText(): string;
|
33
|
+
protected fillDropdown(dropdown: HTMLElement, helpDisplay?: HelpDisplay): boolean;
|
32
34
|
protected onKeyPress(event: KeyPressEvent): boolean;
|
33
35
|
serializeState(): SavedToolbuttonState;
|
34
36
|
deserializeFrom(state: SavedToolbuttonState): void;
|
@@ -121,7 +121,7 @@ class PenToolWidget extends BaseToolWidget_1.default {
|
|
121
121
|
return this.createIconForRecord(this.getCurrentPenType());
|
122
122
|
}
|
123
123
|
// Creates a widget that allows selecting different pen types
|
124
|
-
createPenTypeSelector() {
|
124
|
+
createPenTypeSelector(helpOverlay) {
|
125
125
|
const allChoices = this.penTypes.map((penType, index) => {
|
126
126
|
return {
|
127
127
|
id: index,
|
@@ -137,6 +137,7 @@ class PenToolWidget extends BaseToolWidget_1.default {
|
|
137
137
|
};
|
138
138
|
penSelector.value.onUpdate(onSelectorUpdate);
|
139
139
|
shapeSelector.value.onUpdate(onSelectorUpdate);
|
140
|
+
helpOverlay?.registerTextHelpForElements([penSelector.getRootElement(), shapeSelector.getRootElement()], this.localizationTable.penDropdown__penTypeHelpText);
|
140
141
|
return {
|
141
142
|
setValue: (penTypeIndex) => {
|
142
143
|
penSelector.value.set(penTypeIndex);
|
@@ -152,7 +153,7 @@ class PenToolWidget extends BaseToolWidget_1.default {
|
|
152
153
|
},
|
153
154
|
};
|
154
155
|
}
|
155
|
-
createStrokeCorrectionOptions() {
|
156
|
+
createStrokeCorrectionOptions(helpOverlay) {
|
156
157
|
const container = document.createElement('div');
|
157
158
|
container.classList.add('action-button-row', `${constants_1.toolbarCSSPrefix}-pen-tool-toggle-buttons`);
|
158
159
|
const addToggleButton = (labelText, icon) => {
|
@@ -176,6 +177,9 @@ class PenToolWidget extends BaseToolWidget_1.default {
|
|
176
177
|
setOnInputListener(listener) {
|
177
178
|
onChangeListener = listener;
|
178
179
|
},
|
180
|
+
addHelpText(text) {
|
181
|
+
helpOverlay?.registerTextHelpForElement(button, text);
|
182
|
+
},
|
179
183
|
};
|
180
184
|
button.onclick = () => {
|
181
185
|
result.setChecked(!checked);
|
@@ -190,6 +194,9 @@ class PenToolWidget extends BaseToolWidget_1.default {
|
|
190
194
|
autocorrectOption.setOnInputListener(enabled => {
|
191
195
|
this.tool.setStrokeAutocorrectEnabled(enabled);
|
192
196
|
});
|
197
|
+
// Help text
|
198
|
+
autocorrectOption.addHelpText(this.localizationTable.penDropdown__autocorrectHelpText);
|
199
|
+
stabilizationOption.addHelpText(this.localizationTable.penDropdown__stabilizationHelpText);
|
193
200
|
return {
|
194
201
|
update: () => {
|
195
202
|
stabilizationOption.setChecked(!!this.tool.getInputMapper());
|
@@ -197,30 +204,42 @@ class PenToolWidget extends BaseToolWidget_1.default {
|
|
197
204
|
},
|
198
205
|
addTo: (parent) => {
|
199
206
|
parent.appendChild(container);
|
200
|
-
}
|
207
|
+
},
|
201
208
|
};
|
202
209
|
}
|
203
|
-
|
210
|
+
getHelpText() {
|
211
|
+
return this.localizationTable.penDropdown__baseHelpText;
|
212
|
+
}
|
213
|
+
fillDropdown(dropdown, helpDisplay) {
|
204
214
|
const container = document.createElement('div');
|
205
215
|
container.classList.add(`${constants_1.toolbarCSSPrefix}spacedList`, `${constants_1.toolbarCSSPrefix}nonbutton-controls-main-list`);
|
206
216
|
// Thickness: Value of the input is squared to allow for finer control/larger values.
|
207
217
|
const { container: thicknessRow, setValue: setThickness } = (0, makeThicknessSlider_1.default)(this.editor, thickness => {
|
208
218
|
this.tool.setThickness(thickness);
|
209
219
|
});
|
210
|
-
const penTypeSelect = this.createPenTypeSelector();
|
211
220
|
const colorRow = document.createElement('div');
|
212
221
|
const colorLabel = document.createElement('label');
|
213
|
-
const
|
222
|
+
const colorInputControl = (0, makeColorInput_1.default)(this.editor, color => {
|
214
223
|
this.tool.setColor(color);
|
215
224
|
});
|
225
|
+
const { input: colorInput, container: colorInputContainer } = colorInputControl;
|
216
226
|
colorInput.id = `${constants_1.toolbarCSSPrefix}colorInput${PenToolWidget.idCounter++}`;
|
217
227
|
colorLabel.innerText = this.localizationTable.colorLabel;
|
218
228
|
colorLabel.setAttribute('for', colorInput.id);
|
219
229
|
colorRow.appendChild(colorLabel);
|
220
230
|
colorRow.appendChild(colorInputContainer);
|
221
|
-
|
231
|
+
// Autocorrect and stabilization options
|
232
|
+
const toggleButtonRow = this.createStrokeCorrectionOptions(helpDisplay);
|
233
|
+
const penTypeSelect = this.createPenTypeSelector(helpDisplay);
|
234
|
+
// Add help text for color and thickness last, as these are likely to be
|
235
|
+
// features users are least interested in.
|
236
|
+
helpDisplay?.registerTextHelpForElement(colorRow, this.localizationTable.penDropdown__colorHelpText);
|
237
|
+
if (helpDisplay) {
|
238
|
+
colorInputControl.registerWithHelpTextDisplay(helpDisplay);
|
239
|
+
}
|
240
|
+
helpDisplay?.registerTextHelpForElement(thicknessRow, this.localizationTable.penDropdown__thicknessHelpText);
|
222
241
|
this.updateInputs = () => {
|
223
|
-
|
242
|
+
colorInputControl.setValue(this.tool.getColor());
|
224
243
|
setThickness(this.tool.getThickness());
|
225
244
|
penTypeSelect.updateIcons();
|
226
245
|
// Update the selected stroke factory.
|
@@ -3,6 +3,7 @@ import SelectionTool from '../../tools/SelectionTool/SelectionTool';
|
|
3
3
|
import { KeyPressEvent } from '../../inputEvents';
|
4
4
|
import { ToolbarLocalization } from '../localization';
|
5
5
|
import BaseToolWidget from './BaseToolWidget';
|
6
|
+
import HelpDisplay from '../utils/HelpDisplay';
|
6
7
|
export default class SelectionToolWidget extends BaseToolWidget {
|
7
8
|
private tool;
|
8
9
|
private updateFormatMenu;
|
@@ -11,5 +12,6 @@ export default class SelectionToolWidget extends BaseToolWidget {
|
|
11
12
|
protected onKeyPress(event: KeyPressEvent): boolean;
|
12
13
|
protected getTitle(): string;
|
13
14
|
protected createIcon(): Element;
|
14
|
-
protected
|
15
|
+
protected getHelpText(): string;
|
16
|
+
protected fillDropdown(dropdown: HTMLElement, helpDisplay?: HelpDisplay): boolean;
|
15
17
|
}
|