js-draw 1.0.1 → 1.1.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/LICENSE +21 -0
- package/dist/Editor.css +1 -0
- package/dist/bundle.js +1 -1
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/toolbar/AbstractToolbar.d.ts +9 -13
- package/dist/cjs/toolbar/AbstractToolbar.js +14 -19
- package/dist/cjs/toolbar/widgets/SaveActionWidget.d.ts +10 -0
- package/dist/cjs/toolbar/widgets/SaveActionWidget.js +26 -0
- package/dist/cjs/toolbar/widgets/keybindings.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/keybindings.js +4 -1
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/toolbar/AbstractToolbar.d.ts +9 -13
- package/dist/mjs/toolbar/AbstractToolbar.mjs +14 -19
- package/dist/mjs/toolbar/widgets/SaveActionWidget.d.ts +10 -0
- package/dist/mjs/toolbar/widgets/SaveActionWidget.mjs +21 -0
- package/dist/mjs/toolbar/widgets/keybindings.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/keybindings.mjs +3 -0
- package/dist/mjs/version.mjs +1 -1
- package/docs/img/readme-images/js-draw.jpg +0 -0
- package/docs/img/readme-images/unsupported-elements--in-editor.png +0 -0
- package/package.json +5 -4
- package/src/toolbar/EdgeToolbar.scss +1 -0
- package/dist-test/test_imports/package-lock.json +0 -13
- package/dist-test/test_imports/package.json +0 -12
- package/dist-test/test_imports/test-imports.js +0 -11
- package/dist-test/test_imports/test-require.cjs +0 -14
- package/src/Editor.loadFrom.test.ts +0 -24
- package/src/Editor.test.ts +0 -107
- package/src/Editor.toSVG.test.ts +0 -294
- package/src/Editor.ts +0 -1443
- package/src/EditorImage.test.ts +0 -117
- package/src/EditorImage.ts +0 -609
- package/src/EventDispatcher.test.ts +0 -123
- package/src/EventDispatcher.ts +0 -72
- package/src/Pointer.ts +0 -183
- package/src/SVGLoader.test.ts +0 -114
- package/src/SVGLoader.ts +0 -672
- package/src/UndoRedoHistory.test.ts +0 -34
- package/src/UndoRedoHistory.ts +0 -102
- package/src/Viewport.ts +0 -322
- package/src/bundle/bundled.ts +0 -7
- package/src/commands/Command.ts +0 -45
- package/src/commands/Duplicate.ts +0 -75
- package/src/commands/Erase.ts +0 -95
- package/src/commands/SerializableCommand.ts +0 -49
- package/src/commands/UnresolvedCommand.ts +0 -37
- package/src/commands/invertCommand.ts +0 -58
- 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 -140
- package/src/components/AbstractComponent.transformBy.test.ts +0 -23
- package/src/components/AbstractComponent.ts +0 -383
- package/src/components/BackgroundComponent.test.ts +0 -44
- package/src/components/BackgroundComponent.ts +0 -348
- package/src/components/ImageComponent.ts +0 -176
- package/src/components/RestylableComponent.ts +0 -161
- package/src/components/SVGGlobalAttributesObject.ts +0 -79
- package/src/components/Stroke.test.ts +0 -137
- package/src/components/Stroke.ts +0 -294
- package/src/components/TextComponent.test.ts +0 -202
- package/src/components/TextComponent.ts +0 -429
- package/src/components/UnknownSVGObject.test.ts +0 -10
- package/src/components/UnknownSVGObject.ts +0 -60
- package/src/components/builders/ArrowBuilder.ts +0 -106
- package/src/components/builders/CircleBuilder.ts +0 -100
- package/src/components/builders/FreehandLineBuilder.test.ts +0 -24
- package/src/components/builders/FreehandLineBuilder.ts +0 -210
- package/src/components/builders/LineBuilder.ts +0 -77
- package/src/components/builders/PressureSensitiveFreehandLineBuilder.ts +0 -453
- package/src/components/builders/RectangleBuilder.ts +0 -73
- package/src/components/builders/types.ts +0 -15
- package/src/components/lib.ts +0 -31
- package/src/components/localization.ts +0 -24
- package/src/components/util/StrokeSmoother.ts +0 -302
- package/src/components/util/describeComponentList.ts +0 -18
- package/src/dialogs/makeAboutDialog.ts +0 -82
- package/src/inputEvents.ts +0 -143
- package/src/lib.ts +0 -91
- package/src/localization.ts +0 -34
- package/src/localizations/de.ts +0 -146
- 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 -74
- package/src/rendering/Display.ts +0 -247
- package/src/rendering/RenderablePathSpec.ts +0 -88
- package/src/rendering/RenderingStyle.test.ts +0 -68
- package/src/rendering/RenderingStyle.ts +0 -55
- package/src/rendering/TextRenderingStyle.ts +0 -55
- package/src/rendering/caching/CacheRecord.test.ts +0 -48
- package/src/rendering/caching/CacheRecord.ts +0 -76
- package/src/rendering/caching/CacheRecordManager.ts +0 -71
- package/src/rendering/caching/RenderingCache.test.ts +0 -43
- package/src/rendering/caching/RenderingCache.ts +0 -66
- package/src/rendering/caching/RenderingCacheNode.ts +0 -404
- package/src/rendering/caching/testUtils.ts +0 -35
- package/src/rendering/caching/types.ts +0 -34
- package/src/rendering/lib.ts +0 -8
- package/src/rendering/localization.ts +0 -20
- package/src/rendering/renderers/AbstractRenderer.ts +0 -232
- package/src/rendering/renderers/CanvasRenderer.ts +0 -312
- package/src/rendering/renderers/DummyRenderer.test.ts +0 -41
- package/src/rendering/renderers/DummyRenderer.ts +0 -142
- package/src/rendering/renderers/SVGRenderer.ts +0 -434
- package/src/rendering/renderers/TextOnlyRenderer.test.ts +0 -34
- package/src/rendering/renderers/TextOnlyRenderer.ts +0 -68
- package/src/shortcuts/KeyBinding.test.ts +0 -61
- package/src/shortcuts/KeyBinding.ts +0 -257
- package/src/shortcuts/KeyboardShortcutManager.test.ts +0 -95
- package/src/shortcuts/KeyboardShortcutManager.ts +0 -163
- package/src/shortcuts/lib.ts +0 -3
- package/src/testing/createEditor.ts +0 -11
- package/src/testing/getUniquePointerId.ts +0 -18
- package/src/testing/lib.ts +0 -3
- package/src/testing/sendPenEvent.ts +0 -36
- package/src/testing/sendTouchEvent.ts +0 -71
- package/src/toolbar/AbstractToolbar.ts +0 -542
- package/src/toolbar/DropdownToolbar.ts +0 -220
- package/src/toolbar/EdgeToolbar.test.ts +0 -54
- package/src/toolbar/EdgeToolbar.ts +0 -543
- package/src/toolbar/IconProvider.ts +0 -861
- package/src/toolbar/constants.ts +0 -1
- package/src/toolbar/lib.ts +0 -6
- package/src/toolbar/localization.ts +0 -136
- package/src/toolbar/types.ts +0 -13
- package/src/toolbar/widgets/ActionButtonWidget.ts +0 -39
- package/src/toolbar/widgets/BaseToolWidget.ts +0 -81
- package/src/toolbar/widgets/BaseWidget.ts +0 -495
- package/src/toolbar/widgets/DocumentPropertiesWidget.ts +0 -250
- package/src/toolbar/widgets/EraserToolWidget.ts +0 -84
- package/src/toolbar/widgets/HandToolWidget.ts +0 -239
- package/src/toolbar/widgets/InsertImageWidget.ts +0 -248
- package/src/toolbar/widgets/OverflowWidget.ts +0 -92
- package/src/toolbar/widgets/PenToolWidget.ts +0 -369
- package/src/toolbar/widgets/SelectionToolWidget.ts +0 -195
- package/src/toolbar/widgets/TextToolWidget.ts +0 -149
- package/src/toolbar/widgets/components/makeColorInput.ts +0 -184
- package/src/toolbar/widgets/components/makeFileInput.ts +0 -128
- package/src/toolbar/widgets/components/makeGridSelector.ts +0 -179
- package/src/toolbar/widgets/components/makeSeparator.ts +0 -17
- package/src/toolbar/widgets/components/makeThicknessSlider.ts +0 -62
- package/src/toolbar/widgets/keybindings.ts +0 -19
- package/src/toolbar/widgets/layout/DropdownLayoutManager.ts +0 -262
- package/src/toolbar/widgets/layout/EdgeToolbarLayoutManager.ts +0 -71
- package/src/toolbar/widgets/layout/types.ts +0 -74
- package/src/toolbar/widgets/lib.ts +0 -13
- package/src/tools/BaseTool.ts +0 -169
- package/src/tools/Eraser.test.ts +0 -103
- package/src/tools/Eraser.ts +0 -173
- package/src/tools/FindTool.test.ts +0 -67
- package/src/tools/FindTool.ts +0 -153
- package/src/tools/InputFilter/FunctionMapper.ts +0 -17
- package/src/tools/InputFilter/InputMapper.ts +0 -41
- package/src/tools/InputFilter/InputPipeline.test.ts +0 -41
- package/src/tools/InputFilter/InputPipeline.ts +0 -34
- package/src/tools/InputFilter/InputStabilizer.ts +0 -254
- package/src/tools/InputFilter/StrokeKeyboardControl.ts +0 -104
- package/src/tools/PanZoom.test.ts +0 -339
- package/src/tools/PanZoom.ts +0 -525
- package/src/tools/PasteHandler.ts +0 -94
- package/src/tools/Pen.test.ts +0 -260
- package/src/tools/Pen.ts +0 -284
- package/src/tools/PipetteTool.ts +0 -84
- package/src/tools/SelectionTool/SelectAllShortcutHandler.ts +0 -29
- package/src/tools/SelectionTool/Selection.ts +0 -647
- package/src/tools/SelectionTool/SelectionHandle.ts +0 -142
- package/src/tools/SelectionTool/SelectionTool.test.ts +0 -370
- package/src/tools/SelectionTool/SelectionTool.ts +0 -510
- package/src/tools/SelectionTool/TransformMode.ts +0 -112
- package/src/tools/SelectionTool/types.ts +0 -11
- package/src/tools/SoundUITool.ts +0 -221
- package/src/tools/TextTool.ts +0 -339
- package/src/tools/ToolController.ts +0 -224
- package/src/tools/ToolEnabledGroup.ts +0 -14
- package/src/tools/ToolSwitcherShortcut.ts +0 -39
- package/src/tools/ToolbarShortcutHandler.ts +0 -39
- package/src/tools/UndoRedoShortcut.test.ts +0 -62
- package/src/tools/UndoRedoShortcut.ts +0 -24
- package/src/tools/keybindings.ts +0 -85
- package/src/tools/lib.ts +0 -22
- package/src/tools/localization.ts +0 -76
- package/src/types.ts +0 -151
- package/src/util/ReactiveValue.test.ts +0 -168
- package/src/util/ReactiveValue.ts +0 -241
- package/src/util/assertions.ts +0 -55
- package/src/util/fileToBase64.ts +0 -18
- package/src/util/guessKeyCodeFromKey.ts +0 -36
- package/src/util/listPrefixMatch.ts +0 -19
- package/src/util/stopPropagationOfScrollingWheelEvents.ts +0 -20
- package/src/util/untilNextAnimationFrame.ts +0 -9
- package/src/util/waitForAll.ts +0 -18
- package/src/util/waitForTimeout.ts +0 -9
- package/src/version.test.ts +0 -12
- package/src/version.ts +0 -3
- package/tools/allLocales.js +0 -4
- package/tools/copyREADME.ts +0 -62
@@ -1,495 +0,0 @@
|
|
1
|
-
import Editor from '../../Editor';
|
2
|
-
import ToolbarShortcutHandler from '../../tools/ToolbarShortcutHandler';
|
3
|
-
import { KeyPressEvent, keyPressEventFromHTMLEvent, keyUpEventFromHTMLEvent } from '../../inputEvents';
|
4
|
-
import { toolbarCSSPrefix } from '../constants';
|
5
|
-
import { ToolbarLocalization } from '../localization';
|
6
|
-
import DropdownLayoutManager from './layout/DropdownLayoutManager';
|
7
|
-
import { ToolMenu, WidgetContentLayoutManager } from './layout/types';
|
8
|
-
|
9
|
-
export type SavedToolbuttonState = Record<string, any>;
|
10
|
-
|
11
|
-
/**
|
12
|
-
* A set of labels that allow toolbar themes to treat buttons differently.
|
13
|
-
*/
|
14
|
-
export enum ToolbarWidgetTag {
|
15
|
-
Save = 'save',
|
16
|
-
Exit = 'exit',
|
17
|
-
Undo = 'undo',
|
18
|
-
Redo = 'redo',
|
19
|
-
}
|
20
|
-
|
21
|
-
export default abstract class BaseWidget {
|
22
|
-
protected readonly container: HTMLElement;
|
23
|
-
private button: HTMLElement;
|
24
|
-
private icon: Element|null;
|
25
|
-
private layoutManager: WidgetContentLayoutManager;
|
26
|
-
private dropdown: ToolMenu|null = null;
|
27
|
-
private dropdownContent: HTMLElement;
|
28
|
-
private dropdownIcon: Element;
|
29
|
-
private label: HTMLLabelElement;
|
30
|
-
#hasDropdown: boolean;
|
31
|
-
private disabled: boolean = false;
|
32
|
-
|
33
|
-
#tags: (ToolbarWidgetTag|string)[] = [];
|
34
|
-
|
35
|
-
// Maps subWidget IDs to subWidgets.
|
36
|
-
private subWidgets: Record<string, BaseWidget> = {};
|
37
|
-
|
38
|
-
private toplevel: boolean = true;
|
39
|
-
protected readonly localizationTable: ToolbarLocalization;
|
40
|
-
|
41
|
-
public constructor(
|
42
|
-
protected editor: Editor,
|
43
|
-
protected id: string,
|
44
|
-
localizationTable?: ToolbarLocalization
|
45
|
-
) {
|
46
|
-
this.localizationTable = localizationTable ?? editor.localization;
|
47
|
-
|
48
|
-
// Default layout manager
|
49
|
-
const defaultLayoutManager = new DropdownLayoutManager(
|
50
|
-
(text) => this.editor.announceForAccessibility(text),
|
51
|
-
this.localizationTable
|
52
|
-
);
|
53
|
-
defaultLayoutManager.connectToEditorNotifier(editor.notifier);
|
54
|
-
this.layoutManager = defaultLayoutManager;
|
55
|
-
|
56
|
-
this.icon = null;
|
57
|
-
this.container = document.createElement('div');
|
58
|
-
this.container.classList.add(
|
59
|
-
`${toolbarCSSPrefix}toolContainer`, `${toolbarCSSPrefix}toolButtonContainer`
|
60
|
-
);
|
61
|
-
this.dropdownContent = document.createElement('div');
|
62
|
-
this.#hasDropdown = false;
|
63
|
-
|
64
|
-
this.button = document.createElement('div');
|
65
|
-
this.button.classList.add(`${toolbarCSSPrefix}button`);
|
66
|
-
this.label = document.createElement('label');
|
67
|
-
this.button.setAttribute('role', 'button');
|
68
|
-
this.button.tabIndex = 0;
|
69
|
-
|
70
|
-
const toolbarShortcutHandlers = this.editor.toolController.getMatchingTools(ToolbarShortcutHandler);
|
71
|
-
|
72
|
-
// If the onKeyPress function has been extended and the editor is configured to send keypress events to
|
73
|
-
// toolbar widgets,
|
74
|
-
if (toolbarShortcutHandlers.length > 0 && this.onKeyPress !== BaseWidget.prototype.onKeyPress) {
|
75
|
-
toolbarShortcutHandlers[0].registerListener(event => this.onKeyPress(event));
|
76
|
-
}
|
77
|
-
}
|
78
|
-
|
79
|
-
public getId(): string {
|
80
|
-
return this.id;
|
81
|
-
}
|
82
|
-
|
83
|
-
/**
|
84
|
-
* Note: Tags should be set *before* a tool widget is added to a toolbar.
|
85
|
-
*
|
86
|
-
*
|
87
|
-
* Associates tags with this widget that can be used by toolbar themes
|
88
|
-
* to customize the layout/appearance of this button. Prefer tags in
|
89
|
-
* the `ToolbarWidgetTag` enum, where possible.
|
90
|
-
*
|
91
|
-
* In addition to being readable from the {@link getTags} method, tags are
|
92
|
-
* added to a button's main container as CSS classes with the `toolwidget-tag--` prefix.
|
93
|
-
*
|
94
|
-
* For example, the `undo` tag would result in `toolwidget-tag--undo`
|
95
|
-
* being added to the button's container's class list.
|
96
|
-
*
|
97
|
-
*/
|
98
|
-
public setTags(tags: (string|ToolbarWidgetTag)[]) {
|
99
|
-
const toClassName = (tag: string) => {
|
100
|
-
return `toolwidget-tag--${tag}`;
|
101
|
-
};
|
102
|
-
|
103
|
-
// Remove CSS classes associated with old tags
|
104
|
-
for (const tag of this.#tags) {
|
105
|
-
this.container.classList.remove(toClassName(tag));
|
106
|
-
}
|
107
|
-
|
108
|
-
this.#tags = [...tags];
|
109
|
-
|
110
|
-
// Add new CSS classes
|
111
|
-
for (const tag of this.#tags) {
|
112
|
-
this.container.classList.add(toClassName(tag));
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
|
-
public getTags() {
|
117
|
-
return [ ...this.#tags ];
|
118
|
-
}
|
119
|
-
|
120
|
-
/**
|
121
|
-
* Returns the ID of this widget in `container`. Adds a suffix to this' ID
|
122
|
-
* if an item in `container` already has this' ID.
|
123
|
-
*
|
124
|
-
* For example, if `this` has ID `foo` and if
|
125
|
-
* `container = { 'foo': somethingNotThis, 'foo-1': somethingElseNotThis }`, this method
|
126
|
-
* returns `foo-2` because elements with IDs `foo` and `foo-1` are already present in
|
127
|
-
* `container`.
|
128
|
-
*
|
129
|
-
* If `this` is already in `container`, returns the id given to `this` in the container.
|
130
|
-
*/
|
131
|
-
public getUniqueIdIn(container: Record<string, BaseWidget>): string {
|
132
|
-
let id = this.getId();
|
133
|
-
let idCounter = 0;
|
134
|
-
|
135
|
-
while (id in container && container[id] !== this) {
|
136
|
-
id = this.getId() + '-' + idCounter.toString();
|
137
|
-
idCounter ++;
|
138
|
-
}
|
139
|
-
|
140
|
-
return id;
|
141
|
-
}
|
142
|
-
|
143
|
-
protected abstract getTitle(): string;
|
144
|
-
protected abstract createIcon(): Element|null;
|
145
|
-
|
146
|
-
// Add content to the widget's associated dropdown menu.
|
147
|
-
// Returns true if such a menu should be created, false otherwise.
|
148
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
149
|
-
if (Object.keys(this.subWidgets).length === 0) {
|
150
|
-
return false;
|
151
|
-
}
|
152
|
-
|
153
|
-
for (const widgetId in this.subWidgets) {
|
154
|
-
const widget = this.subWidgets[widgetId];
|
155
|
-
|
156
|
-
widget.addTo(dropdown);
|
157
|
-
widget.setIsToplevel(false);
|
158
|
-
}
|
159
|
-
return true;
|
160
|
-
}
|
161
|
-
|
162
|
-
/** @deprecated Renamed to `setUpButtonEventListeners`. */
|
163
|
-
protected setupActionBtnClickListener(button: HTMLElement) {
|
164
|
-
return this.setUpButtonEventListeners(button);
|
165
|
-
}
|
166
|
-
|
167
|
-
protected setUpButtonEventListeners(button: HTMLElement) {
|
168
|
-
const clickTriggers = { Enter: true, ' ': true, };
|
169
|
-
button.onkeydown = (evt) => {
|
170
|
-
let handled = false;
|
171
|
-
|
172
|
-
if (evt.key in clickTriggers) {
|
173
|
-
if (!this.disabled) {
|
174
|
-
this.handleClick();
|
175
|
-
handled = true;
|
176
|
-
}
|
177
|
-
}
|
178
|
-
|
179
|
-
// If we didn't do anything with the event, send it to the editor.
|
180
|
-
if (!handled) {
|
181
|
-
const editorEvent = keyPressEventFromHTMLEvent(evt);
|
182
|
-
handled = this.editor.toolController.dispatchInputEvent(editorEvent);
|
183
|
-
}
|
184
|
-
|
185
|
-
if (handled) {
|
186
|
-
evt.preventDefault();
|
187
|
-
}
|
188
|
-
};
|
189
|
-
|
190
|
-
button.onkeyup = htmlEvent => {
|
191
|
-
if (htmlEvent.key in clickTriggers) {
|
192
|
-
return;
|
193
|
-
}
|
194
|
-
|
195
|
-
const event = keyUpEventFromHTMLEvent(htmlEvent);
|
196
|
-
const handled = this.editor.toolController.dispatchInputEvent(event);
|
197
|
-
|
198
|
-
if (handled) {
|
199
|
-
htmlEvent.preventDefault();
|
200
|
-
}
|
201
|
-
};
|
202
|
-
|
203
|
-
button.onclick = () => {
|
204
|
-
if (!this.disabled) {
|
205
|
-
this.handleClick();
|
206
|
-
}
|
207
|
-
};
|
208
|
-
|
209
|
-
// Prevent double-click zoom on some devices.
|
210
|
-
button.ondblclick = event => {
|
211
|
-
event.preventDefault();
|
212
|
-
};
|
213
|
-
}
|
214
|
-
|
215
|
-
// Add a listener that is triggered when a key is pressed.
|
216
|
-
// Listeners will fire regardless of whether this widget is selected and require that
|
217
|
-
// {@link Editor.toolController} to have an enabled {@link ToolbarShortcutHandler} tool.
|
218
|
-
protected onKeyPress(_event: KeyPressEvent): boolean {
|
219
|
-
return false;
|
220
|
-
}
|
221
|
-
|
222
|
-
protected abstract handleClick(): void;
|
223
|
-
|
224
|
-
protected get hasDropdown() {
|
225
|
-
return this.#hasDropdown;
|
226
|
-
}
|
227
|
-
|
228
|
-
// Add a widget to this' dropdown. Must be called before this.addTo.
|
229
|
-
protected addSubWidget(widget: BaseWidget) {
|
230
|
-
// Generate a unique ID for the widget.
|
231
|
-
const id = widget.getUniqueIdIn(this.subWidgets);
|
232
|
-
|
233
|
-
this.subWidgets[id] = widget;
|
234
|
-
}
|
235
|
-
|
236
|
-
public setLayoutManager(manager: WidgetContentLayoutManager) {
|
237
|
-
if (manager === this.layoutManager) {
|
238
|
-
return;
|
239
|
-
}
|
240
|
-
|
241
|
-
this.layoutManager = manager;
|
242
|
-
if (this.container.parentElement) {
|
243
|
-
// Trigger a re-creation of this' content
|
244
|
-
this.addTo(this.container.parentElement);
|
245
|
-
}
|
246
|
-
}
|
247
|
-
|
248
|
-
|
249
|
-
/**
|
250
|
-
* Adds this to `parent`.
|
251
|
-
* Returns the element that was just added to `parent`.
|
252
|
-
* @internal
|
253
|
-
*/
|
254
|
-
public addTo(parent: HTMLElement) {
|
255
|
-
// Update title and icon
|
256
|
-
this.icon = null;
|
257
|
-
this.updateIcon();
|
258
|
-
this.label.innerText = this.getTitle();
|
259
|
-
|
260
|
-
const longLabelCSSClass = 'long-label';
|
261
|
-
if (this.label.innerText.length > 7) {
|
262
|
-
this.label.classList.add(longLabelCSSClass);
|
263
|
-
} else {
|
264
|
-
this.label.classList.remove(longLabelCSSClass);
|
265
|
-
}
|
266
|
-
|
267
|
-
// Click functionality
|
268
|
-
this.setUpButtonEventListeners(this.button);
|
269
|
-
|
270
|
-
// Clear anything already in this.container.
|
271
|
-
this.container.replaceChildren();
|
272
|
-
|
273
|
-
this.button.replaceChildren(this.icon!, this.label);
|
274
|
-
this.container.appendChild(this.button);
|
275
|
-
|
276
|
-
// Clear the dropdownContainer in case this element is being moved to another
|
277
|
-
// parent.
|
278
|
-
this.dropdownContent.replaceChildren();
|
279
|
-
this.#hasDropdown = this.fillDropdown(this.dropdownContent);
|
280
|
-
if (this.#hasDropdown) {
|
281
|
-
this.button.classList.add('has-dropdown');
|
282
|
-
|
283
|
-
// We're re-creating the dropdown.
|
284
|
-
this.dropdown?.destroy();
|
285
|
-
|
286
|
-
this.dropdownIcon = this.createDropdownIcon();
|
287
|
-
this.button.appendChild(this.dropdownIcon);
|
288
|
-
|
289
|
-
this.dropdown = this.layoutManager.createToolMenu({
|
290
|
-
target: this.button,
|
291
|
-
getTitle: () => this.getTitle(),
|
292
|
-
isToplevel: () => this.toplevel,
|
293
|
-
});
|
294
|
-
|
295
|
-
this.dropdown.visible.onUpdate(visible => {
|
296
|
-
if (visible) {
|
297
|
-
this.container.classList.add('dropdownVisible');
|
298
|
-
} else {
|
299
|
-
this.container.classList.remove('dropdownVisible');
|
300
|
-
}
|
301
|
-
|
302
|
-
// Auto-focus this component's button when the dropdown hides --
|
303
|
-
// this ensures that keyboard focus goes to a reasonable location when
|
304
|
-
// the user closes a menu.
|
305
|
-
if (!visible) {
|
306
|
-
this.focus();
|
307
|
-
}
|
308
|
-
});
|
309
|
-
|
310
|
-
this.dropdown.appendChild(this.dropdownContent);
|
311
|
-
}
|
312
|
-
|
313
|
-
this.setDropdownVisible(false);
|
314
|
-
|
315
|
-
if (this.container.parentElement) {
|
316
|
-
this.container.remove();
|
317
|
-
}
|
318
|
-
|
319
|
-
parent.appendChild(this.container);
|
320
|
-
return this.container;
|
321
|
-
}
|
322
|
-
|
323
|
-
public focus() {
|
324
|
-
this.button.focus();
|
325
|
-
}
|
326
|
-
|
327
|
-
/**
|
328
|
-
* @internal
|
329
|
-
*/
|
330
|
-
public addCSSClassToContainer(className: string) {
|
331
|
-
this.container.classList.add(className);
|
332
|
-
}
|
333
|
-
|
334
|
-
public removeCSSClassFromContainer(className: string) {
|
335
|
-
this.container.classList.remove(className);
|
336
|
-
}
|
337
|
-
|
338
|
-
public remove() {
|
339
|
-
this.container.remove();
|
340
|
-
}
|
341
|
-
|
342
|
-
protected updateIcon() {
|
343
|
-
let newIcon = this.createIcon();
|
344
|
-
|
345
|
-
if (!newIcon) {
|
346
|
-
newIcon = document.createElement('div');
|
347
|
-
this.container.classList.add('no-icon');
|
348
|
-
} else {
|
349
|
-
this.container.classList.remove('no-icon');
|
350
|
-
}
|
351
|
-
|
352
|
-
this.icon?.replaceWith(newIcon);
|
353
|
-
this.icon = newIcon;
|
354
|
-
this.icon.classList.add(`${toolbarCSSPrefix}icon`);
|
355
|
-
}
|
356
|
-
|
357
|
-
public setDisabled(disabled: boolean) {
|
358
|
-
this.disabled = disabled;
|
359
|
-
|
360
|
-
if (this.disabled) {
|
361
|
-
this.button.classList.add('disabled');
|
362
|
-
this.button.setAttribute('aria-disabled', 'true');
|
363
|
-
} else {
|
364
|
-
this.button.classList.remove('disabled');
|
365
|
-
this.button.removeAttribute('aria-disabled');
|
366
|
-
}
|
367
|
-
}
|
368
|
-
|
369
|
-
public setSelected(selected: boolean) {
|
370
|
-
const currentlySelected = this.isSelected();
|
371
|
-
if (currentlySelected === selected) {
|
372
|
-
return;
|
373
|
-
}
|
374
|
-
|
375
|
-
// Ensure that accessibility tools check and read the value of
|
376
|
-
// aria-checked.
|
377
|
-
// TODO: Ensure that 'role' is set to 'switch' by default for selectable
|
378
|
-
// buttons.
|
379
|
-
this.button.setAttribute('role', 'switch');
|
380
|
-
|
381
|
-
if (selected) {
|
382
|
-
this.container.classList.add('selected');
|
383
|
-
this.button.setAttribute('aria-checked', 'true');
|
384
|
-
} else {
|
385
|
-
this.container.classList.remove('selected');
|
386
|
-
this.button.setAttribute('aria-checked', 'false');
|
387
|
-
}
|
388
|
-
}
|
389
|
-
|
390
|
-
|
391
|
-
protected setDropdownVisible(visible: boolean) {
|
392
|
-
if (visible) {
|
393
|
-
this.dropdown?.requestShow();
|
394
|
-
} else {
|
395
|
-
this.dropdown?.requestHide();
|
396
|
-
}
|
397
|
-
}
|
398
|
-
|
399
|
-
/**
|
400
|
-
* Only used by some layout managers.
|
401
|
-
* In those layout managers, makes this dropdown visible.
|
402
|
-
*/
|
403
|
-
protected activateDropdown() {
|
404
|
-
this.dropdown?.onActivated();
|
405
|
-
}
|
406
|
-
|
407
|
-
/**
|
408
|
-
* Returns `true` if this widget must always be in a toplevel menu and not
|
409
|
-
* in a scrolling/overflow menu.
|
410
|
-
*
|
411
|
-
* This method can be overidden to override the default of `true`.
|
412
|
-
*/
|
413
|
-
public mustBeInToplevelMenu(): boolean {
|
414
|
-
return false;
|
415
|
-
}
|
416
|
-
|
417
|
-
/**
|
418
|
-
* Returns true iff this widget can be in a nontoplevel menu.
|
419
|
-
*
|
420
|
-
* @deprecated Use `!mustBeInToplevelMenu()` instead.
|
421
|
-
*/
|
422
|
-
public canBeInOverflowMenu(): boolean {
|
423
|
-
return !this.mustBeInToplevelMenu();
|
424
|
-
}
|
425
|
-
|
426
|
-
public getButtonWidth(): number {
|
427
|
-
return this.button.clientWidth;
|
428
|
-
}
|
429
|
-
|
430
|
-
public isHidden(): boolean {
|
431
|
-
return this.container.style.display === 'none';
|
432
|
-
}
|
433
|
-
|
434
|
-
public setHidden(hidden: boolean) {
|
435
|
-
this.container.style.display = hidden ? 'none' : '';
|
436
|
-
}
|
437
|
-
|
438
|
-
/** Set whether the widget is contained within another. @internal */
|
439
|
-
public setIsToplevel(toplevel: boolean) {
|
440
|
-
this.toplevel = toplevel;
|
441
|
-
}
|
442
|
-
|
443
|
-
protected isDropdownVisible(): boolean {
|
444
|
-
return this.dropdown?.visible?.get() ?? false;
|
445
|
-
}
|
446
|
-
|
447
|
-
protected isSelected(): boolean {
|
448
|
-
return this.container.classList.contains('selected');
|
449
|
-
}
|
450
|
-
|
451
|
-
private createDropdownIcon(): Element {
|
452
|
-
const icon = this.editor.icons.makeDropdownIcon();
|
453
|
-
icon.classList.add(`${toolbarCSSPrefix}showHideDropdownIcon`);
|
454
|
-
return icon;
|
455
|
-
}
|
456
|
-
|
457
|
-
/**
|
458
|
-
* Serialize state associated with this widget.
|
459
|
-
* Override this method to allow saving/restoring from state on application load.
|
460
|
-
*
|
461
|
-
* Overriders should call `super` and include the output of `super.serializeState` in
|
462
|
-
* the output dictionary.
|
463
|
-
*
|
464
|
-
* Clients should not rely on the output from `saveState` being in any particular
|
465
|
-
* format.
|
466
|
-
*/
|
467
|
-
public serializeState(): SavedToolbuttonState {
|
468
|
-
const subwidgetState: Record<string, any> = {};
|
469
|
-
|
470
|
-
// Save all subwidget state.
|
471
|
-
for (const subwidgetId in this.subWidgets) {
|
472
|
-
subwidgetState[subwidgetId] = this.subWidgets[subwidgetId].serializeState();
|
473
|
-
}
|
474
|
-
|
475
|
-
return {
|
476
|
-
subwidgetState,
|
477
|
-
};
|
478
|
-
}
|
479
|
-
|
480
|
-
/**
|
481
|
-
* Restore widget state from serialized data. See also `saveState`.
|
482
|
-
*
|
483
|
-
* Overriders must call `super`.
|
484
|
-
*/
|
485
|
-
public deserializeFrom(state: SavedToolbuttonState): void {
|
486
|
-
if (state.subwidgetState) {
|
487
|
-
// Deserialize all subwidgets.
|
488
|
-
for (const subwidgetId in state.subwidgetState) {
|
489
|
-
if (subwidgetId in this.subWidgets) {
|
490
|
-
this.subWidgets[subwidgetId].deserializeFrom(state.subwidgetState[subwidgetId]);
|
491
|
-
}
|
492
|
-
}
|
493
|
-
}
|
494
|
-
}
|
495
|
-
}
|