js-draw 1.14.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. package/dist/Editor.css +288 -1
  2. package/dist/bundle.js +2 -2
  3. package/dist/bundledStyles.js +1 -1
  4. package/dist/cjs/Editor.js +5 -0
  5. package/dist/cjs/components/util/StrokeSmoother.js +11 -4
  6. package/dist/cjs/rendering/caching/CacheRecordManager.js +1 -1
  7. package/dist/cjs/rendering/renderers/CanvasRenderer.js +1 -1
  8. package/dist/cjs/testing/sendHtmlSwipe.d.ts +4 -0
  9. package/dist/cjs/testing/sendHtmlSwipe.js +14 -0
  10. package/dist/cjs/toolbar/EdgeToolbar.d.ts +1 -0
  11. package/dist/cjs/toolbar/EdgeToolbar.js +30 -110
  12. package/dist/cjs/toolbar/IconProvider.d.ts +1 -0
  13. package/dist/cjs/toolbar/IconProvider.js +27 -0
  14. package/dist/cjs/toolbar/localization.d.ts +28 -1
  15. package/dist/cjs/toolbar/localization.js +30 -1
  16. package/dist/cjs/toolbar/utils/HelpDisplay.d.ts +37 -0
  17. package/dist/cjs/toolbar/utils/HelpDisplay.js +442 -0
  18. package/dist/cjs/toolbar/utils/HelpDisplay.test.d.ts +1 -0
  19. package/dist/cjs/toolbar/utils/localization.d.ts +9 -0
  20. package/dist/cjs/toolbar/utils/localization.js +11 -0
  21. package/dist/cjs/toolbar/utils/makeDraggable.d.ts +16 -0
  22. package/dist/cjs/toolbar/utils/makeDraggable.js +130 -0
  23. package/dist/cjs/toolbar/widgets/ActionButtonWidget.d.ts +7 -0
  24. package/dist/cjs/toolbar/widgets/ActionButtonWidget.js +14 -2
  25. package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +8 -1
  26. package/dist/cjs/toolbar/widgets/BaseWidget.js +25 -3
  27. package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.d.ts +3 -1
  28. package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +19 -4
  29. package/dist/cjs/toolbar/widgets/HandToolWidget.d.ts +3 -1
  30. package/dist/cjs/toolbar/widgets/HandToolWidget.js +19 -7
  31. package/dist/cjs/toolbar/widgets/InsertImageWidget.js +1 -0
  32. package/dist/cjs/toolbar/widgets/PenToolWidget.d.ts +4 -2
  33. package/dist/cjs/toolbar/widgets/PenToolWidget.js +27 -8
  34. package/dist/cjs/toolbar/widgets/SelectionToolWidget.d.ts +3 -1
  35. package/dist/cjs/toolbar/widgets/SelectionToolWidget.js +19 -5
  36. package/dist/cjs/toolbar/widgets/components/makeColorInput.d.ts +2 -0
  37. package/dist/cjs/toolbar/widgets/components/makeColorInput.js +17 -7
  38. package/dist/cjs/toolbar/widgets/components/makeGridSelector.d.ts +6 -0
  39. package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +3 -0
  40. package/dist/cjs/tools/FindTool.js +18 -5
  41. package/dist/cjs/tools/PanZoom.d.ts +8 -2
  42. package/dist/cjs/tools/PanZoom.js +29 -10
  43. package/dist/cjs/tools/SelectionTool/Selection.js +16 -2
  44. package/dist/cjs/util/addLongPressOrHoverCssClasses.d.ts +3 -1
  45. package/dist/cjs/util/addLongPressOrHoverCssClasses.js +2 -1
  46. package/dist/cjs/util/cloneElementWithStyles.d.ts +6 -0
  47. package/dist/cjs/util/cloneElementWithStyles.js +32 -0
  48. package/dist/cjs/version.js +1 -1
  49. package/dist/mjs/Editor.mjs +5 -0
  50. package/dist/mjs/components/util/StrokeSmoother.mjs +11 -4
  51. package/dist/mjs/rendering/caching/CacheRecordManager.mjs +1 -1
  52. package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +1 -1
  53. package/dist/mjs/testing/sendHtmlSwipe.d.ts +4 -0
  54. package/dist/mjs/testing/sendHtmlSwipe.mjs +12 -0
  55. package/dist/mjs/toolbar/EdgeToolbar.d.ts +1 -0
  56. package/dist/mjs/toolbar/EdgeToolbar.mjs +30 -110
  57. package/dist/mjs/toolbar/IconProvider.d.ts +1 -0
  58. package/dist/mjs/toolbar/IconProvider.mjs +27 -0
  59. package/dist/mjs/toolbar/localization.d.ts +28 -1
  60. package/dist/mjs/toolbar/localization.mjs +30 -1
  61. package/dist/mjs/toolbar/utils/HelpDisplay.d.ts +37 -0
  62. package/dist/mjs/toolbar/utils/HelpDisplay.mjs +437 -0
  63. package/dist/mjs/toolbar/utils/HelpDisplay.test.d.ts +1 -0
  64. package/dist/mjs/toolbar/utils/localization.d.ts +9 -0
  65. package/dist/mjs/toolbar/utils/localization.mjs +8 -0
  66. package/dist/mjs/toolbar/utils/makeDraggable.d.ts +16 -0
  67. package/dist/mjs/toolbar/utils/makeDraggable.mjs +128 -0
  68. package/dist/mjs/toolbar/widgets/ActionButtonWidget.d.ts +7 -0
  69. package/dist/mjs/toolbar/widgets/ActionButtonWidget.mjs +14 -2
  70. package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +8 -1
  71. package/dist/mjs/toolbar/widgets/BaseWidget.mjs +25 -3
  72. package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.d.ts +3 -1
  73. package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +19 -4
  74. package/dist/mjs/toolbar/widgets/HandToolWidget.d.ts +3 -1
  75. package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +19 -7
  76. package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +1 -0
  77. package/dist/mjs/toolbar/widgets/PenToolWidget.d.ts +4 -2
  78. package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +27 -8
  79. package/dist/mjs/toolbar/widgets/SelectionToolWidget.d.ts +3 -1
  80. package/dist/mjs/toolbar/widgets/SelectionToolWidget.mjs +19 -5
  81. package/dist/mjs/toolbar/widgets/components/makeColorInput.d.ts +2 -0
  82. package/dist/mjs/toolbar/widgets/components/makeColorInput.mjs +17 -7
  83. package/dist/mjs/toolbar/widgets/components/makeGridSelector.d.ts +6 -0
  84. package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +3 -0
  85. package/dist/mjs/tools/FindTool.mjs +18 -5
  86. package/dist/mjs/tools/PanZoom.d.ts +8 -2
  87. package/dist/mjs/tools/PanZoom.mjs +29 -10
  88. package/dist/mjs/tools/SelectionTool/Selection.mjs +16 -2
  89. package/dist/mjs/util/addLongPressOrHoverCssClasses.d.ts +3 -1
  90. package/dist/mjs/util/addLongPressOrHoverCssClasses.mjs +2 -1
  91. package/dist/mjs/util/cloneElementWithStyles.d.ts +6 -0
  92. package/dist/mjs/util/cloneElementWithStyles.mjs +30 -0
  93. package/dist/mjs/version.mjs +1 -1
  94. package/package.json +3 -3
  95. package/src/toolbar/EdgeToolbar.scss +23 -2
  96. package/src/toolbar/toolbar.scss +2 -0
  97. package/src/toolbar/utils/HelpDisplay.scss +315 -0
  98. package/src/toolbar/widgets/components/makeColorInput.scss +7 -0
  99. package/src/tools/SelectionTool/SelectionTool.scss +4 -0
@@ -4,6 +4,7 @@ import EdgeToolbarLayoutManager from './widgets/layout/EdgeToolbarLayoutManage
4
4
  import { MutableReactiveValue, ReactiveValue } from '../util/ReactiveValue.mjs';
5
5
  import AbstractToolbar from './AbstractToolbar.mjs';
6
6
  import stopPropagationOfScrollingWheelEvents from '../util/stopPropagationOfScrollingWheelEvents.mjs';
7
+ import makeDraggable from './utils/makeDraggable.mjs';
7
8
  /**
8
9
  * Creates an `EdgeToolbar`.
9
10
  *
@@ -39,6 +40,7 @@ export default class EdgeToolbar extends AbstractToolbar {
39
40
  /** @internal */
40
41
  constructor(editor, parent, localizationTable) {
41
42
  super(editor, localizationTable);
43
+ this.clearDragListeners = null;
42
44
  this.toolbarContainer = document.createElement('div');
43
45
  this.toolbarContainer.classList.add(`${toolbarCSSPrefix}root`);
44
46
  this.toolbarContainer.classList.add(`${toolbarCSSPrefix}element`);
@@ -124,8 +126,11 @@ export default class EdgeToolbar extends AbstractToolbar {
124
126
  // to animate it to 1.
125
127
  this.menuContainer.style.opacity = '0';
126
128
  }
129
+ const prefersReduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)') ?? '';
127
130
  this.sidebarVisible.onUpdate(visible => {
128
131
  const animationProperties = `${animationDuration}ms ease`;
132
+ // We need to use different animations when reducing motion.
133
+ const reduceMotion = prefersReduceMotion.matches ? '-reduce-motion' : '';
129
134
  if (visible) {
130
135
  this.sidebarY.set(this.snappedSidebarY());
131
136
  if (animationTimeout) {
@@ -133,8 +138,10 @@ export default class EdgeToolbar extends AbstractToolbar {
133
138
  animationTimeout = null;
134
139
  }
135
140
  this.menuContainer.style.display = '';
136
- this.sidebarContainer.style.animation = `${animationProperties} ${toolbarCSSPrefix}-edgemenu-transition-in`;
137
- this.menuContainer.style.animation = `${animationProperties} ${toolbarCSSPrefix}-edgemenu-container-transition-in`;
141
+ this.sidebarContainer.style.animation =
142
+ `${animationProperties} ${toolbarCSSPrefix}-edgemenu-transition-in${reduceMotion}`;
143
+ this.menuContainer.style.animation =
144
+ `${animationProperties} ${toolbarCSSPrefix}-edgemenu-container-transition-in${reduceMotion}`;
138
145
  this.menuContainer.style.opacity = '1';
139
146
  // Focus the close button when first shown, but prevent scroll because the button
140
147
  // is likely at the bottom of the screen (and we want the full sidebar to remain
@@ -144,8 +151,10 @@ export default class EdgeToolbar extends AbstractToolbar {
144
151
  else {
145
152
  this.closeColorPickers();
146
153
  if (animationTimeout === null) {
147
- this.sidebarContainer.style.animation = ` ${animationProperties} ${toolbarCSSPrefix}-edgemenu-transition-out`;
148
- this.menuContainer.style.animation = `${animationProperties} ${toolbarCSSPrefix}-edgemenu-container-transition-out`;
154
+ this.sidebarContainer.style.animation =
155
+ `${animationProperties} ${toolbarCSSPrefix}-edgemenu-transition-out${reduceMotion}`;
156
+ this.menuContainer.style.animation =
157
+ `${animationProperties} ${toolbarCSSPrefix}-edgemenu-container-transition-out${reduceMotion}`;
149
158
  // Manually set the container's opacity to prevent flickering when closing
150
159
  // the toolbar.
151
160
  this.menuContainer.style.opacity = '0';
@@ -254,15 +263,12 @@ export default class EdgeToolbar extends AbstractToolbar {
254
263
  this.toolbarContainer.remove();
255
264
  this.menuContainer.remove();
256
265
  this.toolRowResizeObserver.disconnect();
266
+ this.clearDragListeners?.();
257
267
  }
258
268
  initDragListeners() {
259
- let lastX = 0;
260
- let lastY = 0;
261
- let startX = 0;
262
- let startY = 0;
263
- let pointerDown = false;
264
- let capturedPointerId = null;
265
269
  const dragElements = [this.closeButton, this.sidebarContainer, this.sidebarContent];
270
+ // Forward longer touch events from the menu background to the
271
+ // editor (and close the sidebar).
266
272
  this.manageListener(this.editor.handlePointerEventsExceptClicksFrom(this.menuContainer, (eventName, event) => {
267
273
  if (event.target === this.menuContainer) {
268
274
  if (eventName === 'pointerdown') {
@@ -281,113 +287,27 @@ export default class EdgeToolbar extends AbstractToolbar {
281
287
  }, (_eventName, event) => {
282
288
  return event.target === this.menuContainer;
283
289
  }));
284
- const isDraggableElement = (element) => {
285
- if (!element) {
286
- return false;
287
- }
288
- if (dragElements.includes(element)) {
289
- return true;
290
- }
291
- // Some inputs handle dragging themselves. Don't also interpret such gestures
292
- // as dragging the dropdown.
293
- const undraggableElementTypes = ['INPUT', 'SELECT', 'IMG'];
294
- let hasSuitableAncestors = false;
295
- let ancestor = element.parentElement;
296
- while (ancestor) {
297
- if (undraggableElementTypes.includes(ancestor.tagName)) {
298
- break;
299
- }
300
- if (ancestor === this.sidebarContainer) {
301
- hasSuitableAncestors = true;
302
- break;
303
- }
304
- ancestor = ancestor.parentElement;
305
- }
306
- return !undraggableElementTypes.includes(element.tagName) && hasSuitableAncestors;
307
- };
308
- const clickThreshold = 5;
309
- // Returns whether the current (or if no current, **the last**) gesture is roughly a click.
310
- // Because this can be called **after** a gesture has just ended, it should not require
311
- // the gesture to be in progress.
312
- const isRoughlyClick = () => {
313
- return Math.hypot(lastX - startX, lastY - startY) < clickThreshold;
314
- };
315
- let startedDragging = false;
316
- this.sidebarContainer.addEventListener('pointerdown', event => {
317
- if (event.defaultPrevented || !isDraggableElement(event.target)) {
318
- return;
319
- }
320
- if (event.isPrimary) {
321
- startedDragging = false;
322
- lastX = event.clientX;
323
- lastY = event.clientY;
324
- startX = event.clientX;
325
- startY = event.clientY;
326
- capturedPointerId = null;
327
- pointerDown = true;
328
- }
329
- }, { passive: true });
290
+ // Set lastGestureWasRoughlyClick to `true` initially because on page load
291
+ // performance.now() is zero.
292
+ let lastGestureWasRoughlyClick = true;
330
293
  let gestureEndTimestamp = 0;
331
- const onGestureEnd = (_event) => {
332
- // If the pointerup/pointercancel event was for a pointer not being tracked,
333
- if (!pointerDown) {
334
- return;
335
- }
336
- gestureEndTimestamp = performance.now();
337
- if (capturedPointerId !== null) {
338
- this.sidebarContainer.releasePointerCapture(capturedPointerId);
339
- capturedPointerId = null;
340
- }
341
- this.finalizeDrag();
342
- pointerDown = false;
343
- startedDragging = false;
344
- };
345
- this.sidebarContainer.onpointermove = event => {
346
- if (!event.isPrimary || !pointerDown) {
347
- return undefined;
348
- }
349
- // Mouse event and no buttons pressed? Cancel the event.
350
- // This can happen if the event was canceled by a focus change (e.g. by opening a
351
- // right-click menu).
352
- if (event.pointerType === 'mouse' && event.buttons === 0) {
353
- onGestureEnd(event);
354
- return undefined;
355
- }
356
- // Only capture after motion -- capturing early prevents click events in Chrome.
357
- if (capturedPointerId === null && !isRoughlyClick()) {
358
- this.sidebarContainer.setPointerCapture(event.pointerId);
359
- capturedPointerId = event.pointerId;
360
- }
361
- const x = event.clientX;
362
- const y = event.clientY;
363
- const dx = x - lastX;
364
- const dy = y - lastY;
365
- if (Math.abs(y - startY) > clickThreshold || startedDragging) {
366
- this.handleDrag(dx, dy);
367
- lastX = x;
368
- lastY = y;
369
- startedDragging = true;
370
- }
371
- };
372
- this.sidebarContainer.onpointerleave = event => {
373
- {
374
- // Capture the pointer if it exits the container while dragging.
375
- if (capturedPointerId === null && pointerDown && event.isPrimary) {
376
- this.sidebarContainer.setPointerCapture(event.pointerId);
377
- capturedPointerId = event.pointerId;
378
- }
379
- }
380
- };
294
+ const dragController = makeDraggable(this.sidebarContainer, {
295
+ draggableChildElements: dragElements,
296
+ onDrag: (deltaX, deltaY) => this.handleDrag(deltaX, deltaY),
297
+ onDragEnd: (dragStatistics) => {
298
+ gestureEndTimestamp = dragStatistics.endTimestamp;
299
+ lastGestureWasRoughlyClick = dragStatistics.roughlyClick;
300
+ this.finalizeDrag();
301
+ },
302
+ });
303
+ this.clearDragListeners = () => dragController.removeListeners();
381
304
  this.closeButton.onclick = () => {
382
305
  const wasJustDragging = performance.now() - gestureEndTimestamp < 100;
383
- const roughlyClick = isRoughlyClick();
384
306
  // Ignore the click event if it was caused by dragging the button.
385
- if (wasJustDragging && roughlyClick || !wasJustDragging) {
307
+ if ((wasJustDragging && lastGestureWasRoughlyClick) || !wasJustDragging) {
386
308
  this.sidebarVisible.set(false);
387
309
  }
388
310
  };
389
- this.sidebarContainer.onpointerup = onGestureEnd;
390
- this.sidebarContainer.onpointercancel = onGestureEnd;
391
311
  }
392
312
  /**
393
313
  * Updates the position of this menu **during** a drag. After a drag ends,
@@ -66,6 +66,7 @@ export default class IconProvider {
66
66
  makeSaveIcon(): IconElemType;
67
67
  makeConfigureDocumentIcon(): IconElemType;
68
68
  makeOverflowIcon(): IconElemType;
69
+ makeHelpIcon(): IconElemType;
69
70
  /**
70
71
  * @param pathData - SVG path data (e.g. `m10,10l30,30z`)
71
72
  * @param fill - A valid CSS color (e.g. `var(--icon-color)` or `#f0f`). This can be `none`.
@@ -779,6 +779,33 @@ class IconProvider {
779
779
  z
780
780
  `);
781
781
  }
782
+ makeHelpIcon() {
783
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
784
+ svg.innerHTML = `
785
+ <circle
786
+ style="stroke-width:1.587; stroke: var(--icon-color);"
787
+ fill="none"
788
+ cx="13.23"
789
+ cy="13.23"
790
+ r="11.9"
791
+ />
792
+ <path
793
+ style="stroke-width: 3; stroke-linecap: butt; stroke: var(--icon-color);"
794
+ fill="none"
795
+ d="M 9.26,6.61 C 18.7,3.25 19.95,10.4 14.3,13.4 c -1.15,0.61 -1.32,1.32 -1.32,2.65 v 2.12"
796
+ />
797
+ <circle
798
+ style="fill: var(--icon-color);"
799
+ cx="13"
800
+ cy="21.32"
801
+ r="1.9"
802
+ />
803
+ `;
804
+ svg.setAttribute('viewBox', '0 0 26.46 26.46');
805
+ svg.setAttribute('width', '100');
806
+ svg.setAttribute('height', '100');
807
+ return svg;
808
+ }
782
809
  /**
783
810
  * @param pathData - SVG path data (e.g. `m10,10l30,30z`)
784
811
  * @param fill - A valid CSS color (e.g. `var(--icon-color)` or `#f0f`). This can be `none`.
@@ -1,4 +1,5 @@
1
- export interface ToolbarLocalization {
1
+ import { ToolbarUtilsLocalization } from './utils/localization';
2
+ export interface ToolbarLocalization extends ToolbarUtilsLocalization {
2
3
  fontLabel: string;
3
4
  textSize: string;
4
5
  touchPanning: string;
@@ -52,6 +53,32 @@ export interface ToolbarLocalization {
52
53
  inputStabilization: string;
53
54
  strokeAutocorrect: string;
54
55
  errorImageHasZeroSize: string;
56
+ describeTheImage: string;
57
+ penDropdown__baseHelpText: string;
58
+ penDropdown__colorHelpText: string;
59
+ penDropdown__thicknessHelpText: string;
60
+ penDropdown__penTypeHelpText: string;
61
+ penDropdown__autocorrectHelpText: string;
62
+ penDropdown__stabilizationHelpText: string;
63
+ handDropdown__baseHelpText: string;
64
+ handDropdown__zoomDisplayHelpText: string;
65
+ handDropdown__zoomInHelpText: string;
66
+ handDropdown__zoomOutHelpText: string;
67
+ handDropdown__resetViewHelpText: string;
68
+ handDropdown__touchPanningHelpText: string;
69
+ handDropdown__lockRotationHelpText: string;
70
+ selectionDropdown__baseHelpText: string;
71
+ selectionDropdown__resizeToHelpText: string;
72
+ selectionDropdown__deleteHelpText: string;
73
+ selectionDropdown__duplicateHelpText: string;
74
+ selectionDropdown__changeColorHelpText: string;
75
+ pageDropdown__baseHelpText: string;
76
+ pageDropdown__backgroundColorHelpText: string;
77
+ pageDropdown__gridCheckboxHelpText: string;
78
+ pageDropdown__aboutButtonHelpText: string;
79
+ pageDropdown__autoresizeCheckboxHelpText: string;
80
+ colorPickerPipetteHelpText: string;
81
+ colorPickerToggleHelpText: string;
55
82
  closeSidebar: (toolName: string) => string;
56
83
  dropdownShown: (toolName: string) => string;
57
84
  dropdownHidden: (toolName: string) => string;
@@ -1,4 +1,6 @@
1
+ import { defaultToolbarUtilsLocalization } from './utils/localization.mjs';
1
2
  export const defaultToolbarLocalization = {
3
+ ...defaultToolbarUtilsLocalization,
2
4
  pen: 'Pen',
3
5
  eraser: 'Eraser',
4
6
  select: 'Select',
@@ -51,12 +53,39 @@ export const defaultToolbarLocalization = {
51
53
  outlinedCirclePen: 'Outlined circle',
52
54
  lockRotation: 'Lock rotation',
53
55
  paste: 'Paste',
56
+ errorImageHasZeroSize: 'Error: Image has zero size',
57
+ describeTheImage: 'Image description',
58
+ // Help text
59
+ penDropdown__baseHelpText: 'This tool draws shapes or freehand lines.',
60
+ penDropdown__colorHelpText: 'Changes the pen\'s color',
61
+ penDropdown__thicknessHelpText: 'Changes the thickness of strokes drawn by the pen.',
62
+ penDropdown__penTypeHelpText: 'Changes the pen style.\n\nEither a “pen tip” style or “shape” can be chosen. Choosing a “pen tip” style draws freehand lines. Choosing a “shape” draws shapes.',
63
+ penDropdown__autocorrectHelpText: 'Converts approximate freehand lines and rectangles to perfect ones.\n\nThe pen must be held stationary at the end of a stroke to trigger a correction.',
64
+ penDropdown__stabilizationHelpText: 'Draws smoother strokes.\n\nThis also adds a short delay between the mouse/stylus and the stroke.',
65
+ handDropdown__baseHelpText: 'This tool is responsible for scrolling, rotating, and zooming the editor.',
66
+ handDropdown__zoomInHelpText: 'Zooms in.',
67
+ handDropdown__zoomOutHelpText: 'Zooms out.',
68
+ handDropdown__resetViewHelpText: 'Resets the zoom level to 100% and resets scroll.',
69
+ handDropdown__zoomDisplayHelpText: 'Shows the current zoom level. 100% shows the image at its actual size.',
70
+ handDropdown__touchPanningHelpText: 'When enabled, touch gestures move the image rather than select or draw.',
71
+ handDropdown__lockRotationHelpText: 'When enabled, prevents touch gestures from rotating the screen.',
72
+ selectionDropdown__baseHelpText: 'Selects content and manipulates the selection',
73
+ selectionDropdown__resizeToHelpText: 'Crops the drawing to the size of what\'s currently selected.\n\nIf auto-resize is enabled, it will be disabled.',
74
+ selectionDropdown__deleteHelpText: 'Erases selected items.',
75
+ selectionDropdown__duplicateHelpText: 'Makes a copy of selected items.',
76
+ selectionDropdown__changeColorHelpText: 'Changes the color of selected items.',
77
+ pageDropdown__baseHelpText: 'Controls the drawing canvas\' background color, pattern, and size.',
78
+ pageDropdown__backgroundColorHelpText: 'Changes the background color of the drawing canvas.',
79
+ pageDropdown__gridCheckboxHelpText: 'Enables/disables a background grid pattern.',
80
+ pageDropdown__autoresizeCheckboxHelpText: 'When checked, the page grows to fit the drawing.\n\nWhen unchecked, the page is visible and its size can be set manually.',
81
+ pageDropdown__aboutButtonHelpText: 'Shows version, debug, and other information.',
82
+ colorPickerPipetteHelpText: 'Picks a color from the screen.',
83
+ colorPickerToggleHelpText: 'Opens/closes the color picker.',
54
84
  closeSidebar: (toolName) => `Close sidebar for ${toolName}`,
55
85
  dropdownShown: (toolName) => `Menu for ${toolName} shown`,
56
86
  dropdownHidden: (toolName) => `Menu for ${toolName} hidden`,
57
87
  zoomLevel: (zoomPercent) => `Zoom: ${zoomPercent}%`,
58
88
  colorChangedAnnouncement: (color) => `Color changed to ${color}`,
59
89
  imageSize: (size, units) => `Image size: ${size} ${units}`,
60
- errorImageHasZeroSize: 'Error: Image has zero size',
61
90
  imageLoadError: (message) => `Error loading image: ${message}`,
62
91
  };
@@ -0,0 +1,37 @@
1
+ import { ToolbarContext } from '../types';
2
+ export interface HelpRecord {
3
+ readonly helpText: string;
4
+ /**
5
+ * Elements that have `helpText`. Conceptually, these
6
+ * `HTMLElement`s form a single control (e.g. different radio
7
+ * buttons in a button group).
8
+ *
9
+ * The elements are all shown at once by a `HelpDisplay`.
10
+ */
11
+ readonly targetElements: HTMLElement[];
12
+ }
13
+ /**
14
+ * Creates and manages an overlay that shows help text for a set of
15
+ * `HTMLElement`s.
16
+ *
17
+ * @see {@link BaseWidget.fillDropdown}.
18
+ */
19
+ export default class HelpDisplay {
20
+ #private;
21
+ private createOverlay;
22
+ private context;
23
+ /** Constructed internally by BaseWidget. @internal */
24
+ constructor(createOverlay: (htmlElement: HTMLElement) => void, context: ToolbarContext);
25
+ /** @internal */
26
+ showHelpOverlay(): void;
27
+ /** Marks `helpText` as associated with a single `targetElement`. */
28
+ registerTextHelpForElement(targetElement: HTMLElement, helpText: string): void;
29
+ /** Marks `helpText` as associated with all elements in `targetElements`. */
30
+ registerTextHelpForElements(targetElements: HTMLElement[], helpText: string): void;
31
+ /** Returns true if any help text has been registered. */
32
+ hasHelpText(): boolean;
33
+ /**
34
+ * Creates and returns a button that toggles the help display.
35
+ */
36
+ createToggleButton(): HTMLElement;
37
+ }