js-draw 1.29.2 → 1.30.1

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.
Files changed (118) hide show
  1. package/dist/bundle.js +44 -34
  2. package/dist/cjs/Editor.d.ts +2 -2
  3. package/dist/cjs/Editor.js +16 -9
  4. package/dist/cjs/components/ImageComponent.js +1 -1
  5. package/dist/cjs/components/builders/FreehandLineBuilder.d.ts +5 -1
  6. package/dist/cjs/components/builders/FreehandLineBuilder.js +7 -4
  7. package/dist/cjs/components/builders/PolylineBuilder.d.ts +5 -1
  8. package/dist/cjs/components/builders/PolylineBuilder.js +7 -4
  9. package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.d.ts +1 -0
  10. package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.js +13 -10
  11. package/dist/cjs/components/builders/autocorrect/makeShapeFitAutocorrect.js +3 -0
  12. package/dist/cjs/components/builders/autocorrect/makeSnapToGridAutocorrect.js +3 -0
  13. package/dist/cjs/components/builders/types.d.ts +6 -0
  14. package/dist/cjs/dialogs/makeMessageDialog.js +5 -3
  15. package/dist/cjs/localizations/getLocalizationTable.js +2 -0
  16. package/dist/cjs/localizations/sk.d.ts +3 -0
  17. package/dist/cjs/localizations/sk.js +182 -0
  18. package/dist/cjs/rendering/Display.d.ts +2 -0
  19. package/dist/cjs/rendering/Display.js +13 -4
  20. package/dist/cjs/rendering/renderers/AbstractRenderer.d.ts +20 -1
  21. package/dist/cjs/rendering/renderers/AbstractRenderer.js +7 -0
  22. package/dist/cjs/rendering/renderers/AcceleratedInkingCanvasRenderer.d.ts +22 -0
  23. package/dist/cjs/rendering/renderers/AcceleratedInkingCanvasRenderer.js +50 -0
  24. package/dist/cjs/toolbar/EdgeToolbar.js +3 -2
  25. package/dist/cjs/toolbar/IconProvider.js +1 -1
  26. package/dist/cjs/toolbar/utils/HelpDisplay.js +7 -6
  27. package/dist/cjs/toolbar/widgets/BaseWidget.js +1 -1
  28. package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +5 -3
  29. package/dist/cjs/toolbar/widgets/HandToolWidget.js +4 -3
  30. package/dist/cjs/toolbar/widgets/InsertImageWidget/InsertImageWidget.js +14 -11
  31. package/dist/cjs/toolbar/widgets/PenToolWidget.js +2 -1
  32. package/dist/cjs/toolbar/widgets/components/makeButtonGrid.js +3 -2
  33. package/dist/cjs/toolbar/widgets/components/makeColorInput.js +2 -1
  34. package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +2 -2
  35. package/dist/cjs/toolbar/widgets/components/makeSnappedList.js +1 -1
  36. package/dist/cjs/tools/FindTool.js +3 -2
  37. package/dist/cjs/tools/Pen.d.ts +2 -0
  38. package/dist/cjs/tools/Pen.js +24 -12
  39. package/dist/cjs/tools/SelectionTool/SelectionMenuShortcut.js +7 -2
  40. package/dist/cjs/tools/SoundUITool.js +6 -4
  41. package/dist/cjs/tools/util/createMenuOverlay.js +9 -7
  42. package/dist/cjs/util/dom/createButton.d.ts +7 -0
  43. package/dist/cjs/util/dom/createButton.js +20 -0
  44. package/dist/cjs/util/{createElement.d.ts → dom/createElement.d.ts} +3 -0
  45. package/dist/cjs/version.js +1 -1
  46. package/dist/mjs/Editor.d.ts +2 -2
  47. package/dist/mjs/Editor.mjs +16 -9
  48. package/dist/mjs/components/ImageComponent.mjs +1 -1
  49. package/dist/mjs/components/builders/FreehandLineBuilder.d.ts +5 -1
  50. package/dist/mjs/components/builders/FreehandLineBuilder.mjs +7 -4
  51. package/dist/mjs/components/builders/PolylineBuilder.d.ts +5 -1
  52. package/dist/mjs/components/builders/PolylineBuilder.mjs +7 -4
  53. package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.d.ts +1 -0
  54. package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.mjs +13 -10
  55. package/dist/mjs/components/builders/autocorrect/makeShapeFitAutocorrect.mjs +3 -0
  56. package/dist/mjs/components/builders/autocorrect/makeSnapToGridAutocorrect.mjs +3 -0
  57. package/dist/mjs/components/builders/types.d.ts +6 -0
  58. package/dist/mjs/dialogs/makeMessageDialog.mjs +5 -3
  59. package/dist/mjs/localizations/getLocalizationTable.mjs +2 -0
  60. package/dist/mjs/localizations/sk.d.ts +3 -0
  61. package/dist/mjs/localizations/sk.mjs +180 -0
  62. package/dist/mjs/rendering/Display.d.ts +2 -0
  63. package/dist/mjs/rendering/Display.mjs +13 -4
  64. package/dist/mjs/rendering/renderers/AbstractRenderer.d.ts +20 -1
  65. package/dist/mjs/rendering/renderers/AbstractRenderer.mjs +7 -0
  66. package/dist/mjs/rendering/renderers/AcceleratedInkingCanvasRenderer.d.ts +22 -0
  67. package/dist/mjs/rendering/renderers/AcceleratedInkingCanvasRenderer.mjs +44 -0
  68. package/dist/mjs/toolbar/EdgeToolbar.mjs +3 -2
  69. package/dist/mjs/toolbar/IconProvider.mjs +1 -1
  70. package/dist/mjs/toolbar/utils/HelpDisplay.mjs +7 -6
  71. package/dist/mjs/toolbar/widgets/BaseWidget.mjs +1 -1
  72. package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +5 -3
  73. package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +4 -3
  74. package/dist/mjs/toolbar/widgets/InsertImageWidget/InsertImageWidget.mjs +14 -11
  75. package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +2 -1
  76. package/dist/mjs/toolbar/widgets/components/makeButtonGrid.mjs +3 -2
  77. package/dist/mjs/toolbar/widgets/components/makeColorInput.mjs +2 -1
  78. package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +2 -2
  79. package/dist/mjs/toolbar/widgets/components/makeSnappedList.mjs +1 -1
  80. package/dist/mjs/tools/FindTool.mjs +3 -2
  81. package/dist/mjs/tools/Pen.d.ts +2 -0
  82. package/dist/mjs/tools/Pen.mjs +24 -12
  83. package/dist/mjs/tools/SelectionTool/SelectionMenuShortcut.mjs +4 -2
  84. package/dist/mjs/tools/SoundUITool.mjs +6 -4
  85. package/dist/mjs/tools/util/createMenuOverlay.mjs +9 -7
  86. package/dist/mjs/util/dom/createButton.d.ts +7 -0
  87. package/dist/mjs/util/dom/createButton.mjs +15 -0
  88. package/dist/mjs/util/{createElement.d.ts → dom/createElement.d.ts} +3 -0
  89. package/dist/mjs/version.mjs +1 -1
  90. package/package.json +4 -4
  91. /package/dist/cjs/util/{addLongPressOrHoverCssClasses.d.ts → dom/addLongPressOrHoverCssClasses.d.ts} +0 -0
  92. /package/dist/cjs/util/{addLongPressOrHoverCssClasses.js → dom/addLongPressOrHoverCssClasses.js} +0 -0
  93. /package/dist/cjs/util/{cloneElementWithStyles.d.ts → dom/cloneElementWithStyles.d.ts} +0 -0
  94. /package/dist/cjs/util/{cloneElementWithStyles.js → dom/cloneElementWithStyles.js} +0 -0
  95. /package/dist/cjs/util/{createElement.js → dom/createElement.js} +0 -0
  96. /package/dist/cjs/util/{listenForKeyboardEventsFrom.d.ts → dom/listenForKeyboardEventsFrom.d.ts} +0 -0
  97. /package/dist/cjs/util/{listenForKeyboardEventsFrom.js → dom/listenForKeyboardEventsFrom.js} +0 -0
  98. /package/dist/cjs/util/{listenForLongPressOrHover.d.ts → dom/listenForLongPressOrHover.d.ts} +0 -0
  99. /package/dist/cjs/util/{listenForLongPressOrHover.js → dom/listenForLongPressOrHover.js} +0 -0
  100. /package/dist/cjs/util/{listenForLongPressOrHover.test.d.ts → dom/listenForLongPressOrHover.test.d.ts} +0 -0
  101. /package/dist/cjs/util/{stopPropagationOfScrollingWheelEvents.d.ts → dom/stopPropagationOfScrollingWheelEvents.d.ts} +0 -0
  102. /package/dist/cjs/util/{stopPropagationOfScrollingWheelEvents.js → dom/stopPropagationOfScrollingWheelEvents.js} +0 -0
  103. /package/dist/cjs/util/{waitForImageLoaded.d.ts → dom/waitForImageLoaded.d.ts} +0 -0
  104. /package/dist/cjs/util/{waitForImageLoaded.js → dom/waitForImageLoaded.js} +0 -0
  105. /package/dist/mjs/util/{addLongPressOrHoverCssClasses.d.ts → dom/addLongPressOrHoverCssClasses.d.ts} +0 -0
  106. /package/dist/mjs/util/{addLongPressOrHoverCssClasses.mjs → dom/addLongPressOrHoverCssClasses.mjs} +0 -0
  107. /package/dist/mjs/util/{cloneElementWithStyles.d.ts → dom/cloneElementWithStyles.d.ts} +0 -0
  108. /package/dist/mjs/util/{cloneElementWithStyles.mjs → dom/cloneElementWithStyles.mjs} +0 -0
  109. /package/dist/mjs/util/{createElement.mjs → dom/createElement.mjs} +0 -0
  110. /package/dist/mjs/util/{listenForKeyboardEventsFrom.d.ts → dom/listenForKeyboardEventsFrom.d.ts} +0 -0
  111. /package/dist/mjs/util/{listenForKeyboardEventsFrom.mjs → dom/listenForKeyboardEventsFrom.mjs} +0 -0
  112. /package/dist/mjs/util/{listenForLongPressOrHover.d.ts → dom/listenForLongPressOrHover.d.ts} +0 -0
  113. /package/dist/mjs/util/{listenForLongPressOrHover.mjs → dom/listenForLongPressOrHover.mjs} +0 -0
  114. /package/dist/mjs/util/{listenForLongPressOrHover.test.d.ts → dom/listenForLongPressOrHover.test.d.ts} +0 -0
  115. /package/dist/mjs/util/{stopPropagationOfScrollingWheelEvents.d.ts → dom/stopPropagationOfScrollingWheelEvents.d.ts} +0 -0
  116. /package/dist/mjs/util/{stopPropagationOfScrollingWheelEvents.mjs → dom/stopPropagationOfScrollingWheelEvents.mjs} +0 -0
  117. /package/dist/mjs/util/{waitForImageLoaded.d.ts → dom/waitForImageLoaded.d.ts} +0 -0
  118. /package/dist/mjs/util/{waitForImageLoaded.mjs → dom/waitForImageLoaded.mjs} +0 -0
@@ -26,7 +26,7 @@ import makeAboutDialog from './dialogs/makeAboutDialog.mjs';
26
26
  import version from './version.mjs';
27
27
  import { editorImageToSVGSync, editorImageToSVGAsync } from './image/export/editorImageToSVG.mjs';
28
28
  import ReactiveValue, { MutableReactiveValue } from './util/ReactiveValue.mjs';
29
- import listenForKeyboardEventsFrom from './util/listenForKeyboardEventsFrom.mjs';
29
+ import listenForKeyboardEventsFrom from './util/dom/listenForKeyboardEventsFrom.mjs';
30
30
  import mitLicenseAttribution from './util/mitLicenseAttribution.mjs';
31
31
  import ClipboardHandler from './util/ClipboardHandler.mjs';
32
32
  import ContextMenuRecognizer from './tools/InputFilter/ContextMenuRecognizer.mjs';
@@ -385,18 +385,24 @@ export class Editor {
385
385
  * A protected method that can override setPointerCapture in environments where it may fail
386
386
  * (e.g. with synthetic events). @internal
387
387
  */
388
- setPointerCapture(target, pointerId) {
388
+ setPointerCapture(target, pointer) {
389
+ // Prevent synthetic events from attempting to capture the pointer.
390
+ // Such events are sometimes created during debug/testing.
391
+ if ('__mockEvent' in pointer)
392
+ return;
389
393
  try {
390
- target.setPointerCapture(pointerId);
394
+ target.setPointerCapture(pointer.pointerId);
391
395
  }
392
396
  catch (error) {
393
397
  console.warn('Failed to setPointerCapture', error);
394
398
  }
395
399
  }
396
400
  /** Can be overridden in a testing environment to handle synthetic events. @internal */
397
- releasePointerCapture(target, pointerId) {
401
+ releasePointerCapture(target, pointer) {
402
+ if ('__mockEvent' in pointer)
403
+ return;
398
404
  try {
399
- target.releasePointerCapture(pointerId);
405
+ target.releasePointerCapture(pointer.pointerId);
400
406
  }
401
407
  catch (error) {
402
408
  console.warn('Failed to releasePointerCapture', error);
@@ -409,10 +415,11 @@ export class Editor {
409
415
  handleHTMLPointerEvent(eventType, evt) {
410
416
  const eventsRelativeTo = this.renderingRegion;
411
417
  const eventTarget = evt.target ?? this.renderingRegion;
418
+ this.display.onPointerEvent(evt);
412
419
  if (eventType === 'pointerdown') {
413
420
  const pointer = Pointer.ofEvent(evt, true, this.viewport, eventsRelativeTo);
414
421
  this.pointers[pointer.id] = pointer;
415
- this.setPointerCapture(eventTarget, pointer.id);
422
+ this.setPointerCapture(eventTarget, evt);
416
423
  const event = {
417
424
  kind: InputEvtType.PointerDownEvt,
418
425
  current: pointer,
@@ -449,7 +456,7 @@ export class Editor {
449
456
  return false;
450
457
  }
451
458
  this.pointers[pointer.id] = pointer;
452
- this.releasePointerCapture(eventTarget, pointer.id);
459
+ this.releasePointerCapture(eventTarget, evt);
453
460
  if (this.toolController.dispatchInputEvent({
454
461
  kind: InputEvtType.PointerUpEvt,
455
462
  current: pointer,
@@ -592,7 +599,7 @@ export class Editor {
592
599
  hasMovedSignificantly: false,
593
600
  };
594
601
  // Capture the pointer so we receive future events even if the overlay is hidden.
595
- this.setPointerCapture(elem, event.pointerId);
602
+ this.setPointerCapture(elem, event);
596
603
  // Don't send to the editor.
597
604
  sendToEditor = false;
598
605
  }
@@ -626,7 +633,7 @@ export class Editor {
626
633
  else if ((eventName === 'pointerup' || eventName === 'pointercancel') &&
627
634
  gestureData[pointerId] &&
628
635
  gestureData[pointerId].eventBuffer.length > 0) {
629
- this.releasePointerCapture(elem, event.pointerId);
636
+ this.releasePointerCapture(elem, event);
630
637
  // Don't send to the editor.
631
638
  sendToEditor = false;
632
639
  delete gestureData[pointerId];
@@ -1,7 +1,7 @@
1
1
  import { Rect2, Mat33 } from '@js-draw/math';
2
2
  import { assertIsNumber, assertIsNumberArray } from '../util/assertions.mjs';
3
3
  import AbstractComponent from './AbstractComponent.mjs';
4
- import waitForImageLoaded from '../util/waitForImageLoaded.mjs';
4
+ import waitForImageLoaded from '../util/dom/waitForImageLoaded.mjs';
5
5
  /**
6
6
  * Represents a raster image.
7
7
  *
@@ -1,6 +1,6 @@
1
1
  import AbstractRenderer from '../../rendering/renderers/AbstractRenderer';
2
2
  import RenderablePathSpec from '../../rendering/RenderablePathSpec';
3
- import { Rect2 } from '@js-draw/math';
3
+ import { Rect2, Color4 } from '@js-draw/math';
4
4
  import Stroke from '../Stroke';
5
5
  import Viewport from '../../Viewport';
6
6
  import { StrokeDataPoint } from '../../types';
@@ -26,6 +26,10 @@ export default class FreehandLineBuilder implements ComponentBuilder {
26
26
  constructor(startPoint: StrokeDataPoint, minFitAllowed: number, maxFitAllowed: number, viewport: Viewport);
27
27
  getBBox(): Rect2;
28
28
  protected getRenderingStyle(): RenderingStyle;
29
+ inkTrailStyle(): {
30
+ color: Color4;
31
+ width: number;
32
+ };
29
33
  protected previewCurrentPath(): RenderablePathSpec | null;
30
34
  protected previewFullPath(): RenderablePathSpec[] | null;
31
35
  private previewStroke;
@@ -35,10 +35,13 @@ export default class FreehandLineBuilder {
35
35
  getRenderingStyle() {
36
36
  return {
37
37
  fill: Color4.transparent,
38
- stroke: {
39
- color: this.startPoint.color,
40
- width: this.roundDistance(this.averageWidth),
41
- },
38
+ stroke: this.inkTrailStyle(),
39
+ };
40
+ }
41
+ inkTrailStyle() {
42
+ return {
43
+ color: this.startPoint.color,
44
+ width: this.roundDistance(this.averageWidth),
42
45
  };
43
46
  }
44
47
  previewCurrentPath() {
@@ -1,6 +1,6 @@
1
1
  import AbstractRenderer from '../../rendering/renderers/AbstractRenderer';
2
2
  import RenderablePathSpec from '../../rendering/RenderablePathSpec';
3
- import { Rect2 } from '@js-draw/math';
3
+ import { Rect2, Color4 } from '@js-draw/math';
4
4
  import Stroke from '../Stroke';
5
5
  import Viewport from '../../Viewport';
6
6
  import { StrokeDataPoint } from '../../types';
@@ -27,6 +27,10 @@ export default class PolylineBuilder implements ComponentBuilder {
27
27
  constructor(startPoint: StrokeDataPoint, minFitAllowed: number, viewport: Viewport);
28
28
  getBBox(): Rect2;
29
29
  protected getRenderingStyle(): RenderingStyle;
30
+ inkTrailStyle(): {
31
+ color: Color4;
32
+ width: number;
33
+ };
30
34
  protected previewCurrentPath(): RenderablePathSpec;
31
35
  protected previewFullPath(): RenderablePathSpec[];
32
36
  preview(renderer: AbstractRenderer): void;
@@ -42,10 +42,13 @@ export default class PolylineBuilder {
42
42
  getRenderingStyle() {
43
43
  return {
44
44
  fill: Color4.transparent,
45
- stroke: {
46
- color: this.startPoint.color,
47
- width: this.roundDistance(this.averageWidth),
48
- },
45
+ stroke: this.inkTrailStyle(),
46
+ };
47
+ }
48
+ inkTrailStyle() {
49
+ return {
50
+ color: this.startPoint.color,
51
+ width: this.roundDistance(this.averageWidth),
49
52
  };
50
53
  }
51
54
  previewCurrentPath() {
@@ -30,6 +30,7 @@ export default class PressureSensitiveFreehandLineBuilder implements ComponentBu
30
30
  build(): Stroke;
31
31
  private roundPoint;
32
32
  private shouldStartNewSegment;
33
+ private getCurrentRadius;
33
34
  private addCurve;
34
35
  private segmentToPath;
35
36
  addPoint(newPoint: StrokeDataPoint): void;
@@ -184,6 +184,9 @@ export default class PressureSensitiveFreehandLineBuilder {
184
184
  }
185
185
  return false;
186
186
  }
187
+ getCurrentRadius() {
188
+ return Viewport.roundPoint(this.startPoint.width / 2.2, Math.min(this.minFitAllowed, this.startPoint.width / 4));
189
+ }
187
190
  addCurve(curve) {
188
191
  // Case where no points have been added
189
192
  if (!curve) {
@@ -191,35 +194,35 @@ export default class PressureSensitiveFreehandLineBuilder {
191
194
  if (!this.isFirstSegment) {
192
195
  return;
193
196
  }
194
- const width = Viewport.roundPoint(this.startPoint.width / 2.2, Math.min(this.minFitAllowed, this.startPoint.width / 4));
197
+ const radius = this.getCurrentRadius();
195
198
  const center = this.roundPoint(this.startPoint.pos);
196
199
  // Start on the right, cycle clockwise:
197
200
  // |
198
201
  // ----- ←
199
202
  // |
200
- const startPoint = this.startPoint.pos.plus(Vec2.of(width, 0));
203
+ const startPoint = this.startPoint.pos.plus(Vec2.of(radius, 0));
201
204
  // Draw a circle-ish shape around the start point
202
205
  this.lowerSegments.push({
203
206
  kind: PathCommandType.QuadraticBezierTo,
204
- controlPoint: center.plus(Vec2.of(width, width)),
207
+ controlPoint: center.plus(Vec2.of(radius, radius)),
205
208
  // Bottom of the circle
206
209
  // |
207
210
  // -----
208
211
  // |
209
212
  // ↑
210
- endPoint: center.plus(Vec2.of(0, width)),
213
+ endPoint: center.plus(Vec2.of(0, radius)),
211
214
  }, {
212
215
  kind: PathCommandType.QuadraticBezierTo,
213
- controlPoint: center.plus(Vec2.of(-width, width)),
214
- endPoint: center.plus(Vec2.of(-width, 0)),
216
+ controlPoint: center.plus(Vec2.of(-radius, radius)),
217
+ endPoint: center.plus(Vec2.of(-radius, 0)),
215
218
  }, {
216
219
  kind: PathCommandType.QuadraticBezierTo,
217
- controlPoint: center.plus(Vec2.of(-width, -width)),
218
- endPoint: center.plus(Vec2.of(0, -width)),
220
+ controlPoint: center.plus(Vec2.of(-radius, -radius)),
221
+ endPoint: center.plus(Vec2.of(0, -radius)),
219
222
  }, {
220
223
  kind: PathCommandType.QuadraticBezierTo,
221
- controlPoint: center.plus(Vec2.of(width, -width)),
222
- endPoint: center.plus(Vec2.of(width, 0)),
224
+ controlPoint: center.plus(Vec2.of(radius, -radius)),
225
+ endPoint: center.plus(Vec2.of(radius, 0)),
223
226
  });
224
227
  const connector = {
225
228
  kind: PathCommandType.LineTo,
@@ -19,6 +19,9 @@ class ShapeFitBuilder {
19
19
  this.viewport = viewport;
20
20
  this.builder = sourceFactory(startPoint, viewport);
21
21
  this.points = [startPoint];
22
+ if (this.builder.inkTrailStyle) {
23
+ this.inkTrailStyle = this.builder.inkTrailStyle.bind(this.builder);
24
+ }
22
25
  }
23
26
  getBBox() {
24
27
  return this.builder.getBBox();
@@ -11,6 +11,9 @@ class SnapToGridAutocompleteBuilder {
11
11
  this.viewport = viewport;
12
12
  this.builder = sourceFactory(startPoint, viewport);
13
13
  this.points = [startPoint];
14
+ if (this.builder.inkTrailStyle) {
15
+ this.inkTrailStyle = this.builder.inkTrailStyle.bind(this.builder);
16
+ }
14
17
  }
15
18
  getBBox() {
16
19
  return this.builder.getBBox();
@@ -3,10 +3,16 @@ import AbstractRenderer from '../../rendering/renderers/AbstractRenderer';
3
3
  import { StrokeDataPoint } from '../../types';
4
4
  import Viewport from '../../Viewport';
5
5
  import AbstractComponent from '../AbstractComponent';
6
+ import { StrokeStyle } from '../../rendering/RenderingStyle';
6
7
  export interface ComponentBuilder {
7
8
  getBBox(): Rect2;
8
9
  build(): AbstractComponent;
9
10
  preview(renderer: AbstractRenderer): void;
11
+ /**
12
+ * (Optional) If provided, allows js-draw to efficiently render
13
+ * an ink trail with the given style on some devices.
14
+ */
15
+ inkTrailStyle?: () => StrokeStyle;
10
16
  /**
11
17
  * Called when the pen is stationary (or the user otherwise
12
18
  * activates autocomplete). This might attempt to fit the user's
@@ -1,3 +1,4 @@
1
+ import createButton from '../util/dom/createButton.mjs';
1
2
  import waitForTimeout from '../util/waitForTimeout.mjs';
2
3
  const makeAboutDialog = (editor, options) => {
3
4
  const overlay = document.createElement('div');
@@ -9,9 +10,10 @@ const makeAboutDialog = (editor, options) => {
9
10
  const heading = document.createElement('h1');
10
11
  heading.textContent = options.title;
11
12
  heading.setAttribute('autofocus', 'true');
12
- const closeButton = document.createElement('button');
13
- closeButton.innerText = editor.localization.closeDialog;
14
- closeButton.classList.add('close');
13
+ const closeButton = createButton({
14
+ text: editor.localization.closeDialog,
15
+ classList: ['close'],
16
+ });
15
17
  const scrollRegion = document.createElement('div');
16
18
  scrollRegion.classList.add('scroll');
17
19
  // Allow scrolling in the scrollable container -- don't forward wheel events.
@@ -2,10 +2,12 @@ import { defaultEditorLocalization } from '../localization.mjs';
2
2
  import de from './de.mjs';
3
3
  import en from './en.mjs';
4
4
  import es from './es.mjs';
5
+ import sk from './sk.mjs';
5
6
  export const allLocales = {
6
7
  de,
7
8
  en,
8
9
  es,
10
+ sk,
9
11
  };
10
12
  // [locale]: A string in the format languageCode_Region or just languageCode. For example, en_US.
11
13
  const languageFromLocale = (locale) => {
@@ -0,0 +1,3 @@
1
+ import { EditorLocalization } from '../localization';
2
+ declare const localization: EditorLocalization;
3
+ export default localization;
@@ -0,0 +1,180 @@
1
+ import { defaultEditorLocalization } from '../localization.mjs';
2
+ // Slovak localization
3
+ const localization = {
4
+ ...defaultEditorLocalization,
5
+ help: 'Pomoc',
6
+ helpHidden: 'Skrytá pomoc',
7
+ next: 'Ďalšie',
8
+ previous: 'Prechádzajúce',
9
+ close: 'Zavrieť',
10
+ helpScreenNavigationHelp: 'Kliknutím na ovládací prvok získate viac informácií.',
11
+ helpControlsAccessibilityLabel: 'Ovládacie prvky: Aktivujte ovládací prvok, ktorý zobrazí pomoc.',
12
+ pen: 'Pero',
13
+ eraser: 'Guma',
14
+ select: 'Vybrať',
15
+ handTool: 'Posun',
16
+ zoom: 'Priblížiť',
17
+ image: 'Obrázok',
18
+ reformatSelection: 'Výber formátu',
19
+ inputAltText: 'Alternatívny text',
20
+ decreaseImageSize: 'Zmenšiť veľkosť',
21
+ resetImage: 'Obnoviť',
22
+ chooseFile: 'Vybrať súbor',
23
+ dragAndDropHereOrBrowse: 'Presuňte sem alebo {{prehľadávať}}',
24
+ submit: 'Odoslať',
25
+ addAll: 'Pridať všetko',
26
+ cancel: 'Zrušiť',
27
+ resetView: 'Obnoviť zobrazenie',
28
+ thicknessLabel: 'Hrúbka',
29
+ colorLabel: 'Farba',
30
+ fontLabel: 'Písmo',
31
+ textSize: 'Veľkosť',
32
+ resizeImageToSelection: 'Zmena veľkosti obrázka podľa výberu',
33
+ deleteSelection: 'Vymazať výber',
34
+ duplicateSelection: 'Duplikovať výber',
35
+ exit: 'Ukončiť',
36
+ save: 'Uložiť',
37
+ undo: 'Späť',
38
+ redo: 'Opakovať',
39
+ fullStrokeEraser: 'Guma s plným ťahom',
40
+ selectPenType: 'Typ pera',
41
+ selectShape: 'Tvar',
42
+ pickColorFromScreen: 'Vybrať farbu z obrazovky',
43
+ clickToPickColorAnnouncement: 'Kliknutím na obrazovku vyberte farbu',
44
+ colorSelectionCanceledAnnouncement: 'Výber farby zrušený',
45
+ selectionTool__lassoSelect: 'Výber voľného tvaru',
46
+ selectionTool__lassoSelect__help: 'Ak je táto funkcia zapnutá, ťahanie vytvorí voľný tvar (laso) výberu.',
47
+ selectionToolKeyboardShortcuts: 'Nástroj na výber: Pomocou klávesov so šípkami môžete presunúť vybrané položky, malými/veľkými písmenami „i“ a „o“ môžete zmeniť veľkosť.',
48
+ documentProperties: 'Strana',
49
+ backgroundColor: 'Farba pozadia',
50
+ imageWidthOption: 'Šírka',
51
+ imageHeightOption: 'Výška',
52
+ useGridOption: 'Mriežka',
53
+ enableAutoresizeOption: 'Automatická zmena veľkosti',
54
+ toggleOverflow: 'Viac',
55
+ about: 'O aplikácii',
56
+ inputStabilization: 'Stabilizácia',
57
+ strokeAutocorrect: 'Automatická oprava',
58
+ pressureSensitivity: 'Tlak',
59
+ touchPanning: 'Posúvanie dotykom',
60
+ roundedTipPen: 'Okrúhle',
61
+ roundedTipPen2: 'Viacčiarové',
62
+ flatTipPen: 'Ploché',
63
+ arrowPen: 'Šípka',
64
+ linePen: 'Čiara',
65
+ outlinedRectanglePen: 'Obrys obdĺžnika',
66
+ filledRectanglePen: 'Plný obdĺžnik',
67
+ outlinedCirclePen: 'Kružnica',
68
+ lockRotation: 'Zamknúť otáčanie',
69
+ paste: 'Vložiť',
70
+ errorImageHasZeroSize: 'Chyba: Obrázok má nulovú veľkosť',
71
+ describeTheImage: 'Popis obrázku',
72
+ fileInput__loading: 'Načítavanie...',
73
+ fileInput__andNMoreFiles: (n) => `(...${n} ďalších)`,
74
+ penDropdown__baseHelpText: 'Tento nástroj kreslí tvary alebo voľné čiary.',
75
+ penDropdown__colorHelpText: 'Zmení farbu pera',
76
+ penDropdown__thicknessHelpText: 'Mení hrúbku ťahov nakreslených perom.',
77
+ penDropdown__penTypeHelpText: 'Zmení štýl pera.\n\nMôžete si vybrať buď štýl „pero“, alebo „tvar“. Výberom štýlu „pero“ sa kreslia voľné čiary. Výberom štýlu „tvar“ sa kreslia tvary.',
78
+ penDropdown__autocorrectHelpText: 'Prevedie približné voľné čiary a obdĺžniky na dokonalé.\n\nPero musí byť držané nehybne na konci ťahu, aby sa spustila oprava.',
79
+ penDropdown__stabilizationHelpText: 'Kreslí hladšie ťahy.\n\nPridáva tiež krátke oneskorenie medzi pohybom myši/stylusu a ťahom.',
80
+ penDropdown__pressureSensitivityHelpText: 'Pri použití kompatibilného zariadenia, napríklad stylusu, mení hrúbku ťahov podľa sily stlačenia.',
81
+ handDropdown__baseHelpText: 'Tento nástroj je zodpovedný za posúvanie, otáčanie a zväčšovanie editora.',
82
+ handDropdown__zoomInHelpText: 'Priblížiť.',
83
+ handDropdown__zoomOutHelpText: 'Oddialiť.',
84
+ handDropdown__resetViewHelpText: 'Obnoví úroveň priblíženia na 100 % a vynuluje posúvanie.',
85
+ handDropdown__zoomDisplayHelpText: 'Zobrazí aktuálnu úroveň priblíženia. 100 % zobrazuje obrázok v jeho skutočnej veľkosti.',
86
+ handDropdown__touchPanningHelpText: 'Keď je táto funkcia zapnutá, gestá dotykovej obrazovky posúvajú obrázok, a nevyberajú ho ani nekreslia.',
87
+ handDropdown__lockRotationHelpText: 'Ak je táto funkcia zapnutá, zabraňuje dotykovým gestám otáčať obrazovku.',
88
+ eraserDropdown__baseHelpText: 'Tento nástroj odstraňuje ťahy, obrázky a text pod kurzorom.',
89
+ eraserDropdown__thicknessHelpText: 'Zmení veľkosť gumy.',
90
+ eraserDropdown__fullStrokeEraserHelpText: '`V režime plného ťahu sa vymažú celé tvary.\n\nKeď nie je v režime plného ťahu, tvary sa môžu byť čiastočne vymazané.`',
91
+ selectionDropdown__baseHelpText: 'Vyberá obsah a manipuluje s výberom',
92
+ selectionDropdown__resizeToHelpText: 'Oreže kresbu na veľkosť toho, čo je aktuálne vybrané.\n\nAk je zapnutá automatická zmena veľkosti, bude táto funkcia vypnutá.',
93
+ selectionDropdown__deleteHelpText: 'Vymaže vybrané položky.',
94
+ selectionDropdown__duplicateHelpText: 'Vytvorí kópiu vybraných položiek.',
95
+ selectionDropdown__changeColorHelpText: 'Zmení farbu vybraných položiek.',
96
+ pageDropdown__baseHelpText: 'Ovláda farbu, vzor a veľkosť pozadia kresliaceho plátna.',
97
+ pageDropdown__backgroundColorHelpText: 'Zmení farbu pozadia kresliaceho plátna.',
98
+ pageDropdown__gridCheckboxHelpText: 'Zapne/vypne vzor mriežky na pozadí.',
99
+ pageDropdown__autoresizeCheckboxHelpText: 'Pokiaľ je označené, stránka sa zväčší tak, aby sa prispôsobila kresbe.\n\nKeď nie je označené, stránka je viditeľná a jej veľkosť sa dá nastaviť ručne.',
100
+ pageDropdown__aboutButtonHelpText: 'Zobrazí verziu, ladenie a ďalšie informácie.',
101
+ colorPickerPipetteHelpText: 'Vyberie farbu z obrazovky.',
102
+ colorPickerToggleHelpText: 'Otvorí/zatvorí výber farieb.',
103
+ closeSidebar: (toolName) => `Zatvoriť bočný panel pre ${toolName}`,
104
+ dropdownShown: (toolName) => `Ponuka pre ${toolName} zobrazená`,
105
+ dropdownHidden: (toolName) => `Ponuka pre ${toolName} skrytá`,
106
+ zoomLevel: (zoomPercent) => `Priblíženie: ${zoomPercent}%`,
107
+ colorChangedAnnouncement: (color) => `Farba zmenená na ${color}`,
108
+ imageSize: (size, units) => `Veľkosť obrázka: ${size} ${units}`,
109
+ imageLoadError: (message) => `Chyba pri načítavaní obrázka: ${message}`,
110
+ penTool: (penId) => `Pero ${penId}`,
111
+ selectionTool: 'Výber',
112
+ selectAllTool: 'Skratka pre výber všetkých',
113
+ eraserTool: 'Guma',
114
+ touchPanTool: 'Posúvanie dotykom',
115
+ twoFingerPanZoomTool: 'Posun a priblíženie',
116
+ undoRedoTool: 'Späť/Opakovať',
117
+ rightClickDragPanTool: 'Ťahanie pravým tlačidlom myši',
118
+ pipetteTool: 'Vybrať farbu z obrazovky',
119
+ keyboardPanZoom: 'Klávesové skratky pre posúvanie/priblíženie',
120
+ selectionMenu__show: 'Zobraziť ponuku výberu',
121
+ selectionMenu__copyToClipboard: 'Kopírovať do schránky',
122
+ selectionMenu__duplicate: 'Duplikovať',
123
+ selectionMenu__delete: 'Vymazať',
124
+ selectionMenu__paste: 'Vložiť',
125
+ copyPasteError__heading: 'Kopírovať/vložiť',
126
+ copyPasteError__description: 'Niečo sa pokazilo - tento nástroj nemusí mať prístup k schránke.',
127
+ copyPasteError__errorDetails: 'Zobraziť chybu',
128
+ copyPasteError__pasteRetry: 'Ak chcete opakovať pokus, vložte ho do nižšie uvedeného vstupného poľa:',
129
+ copyPasteError__copyRetry: 'Ak chcete opakovať pokus, skopírujte text do vstupného poľa nižšie:',
130
+ copyPasteError__copyMe: 'Skopíruj ma!',
131
+ autocorrectedTo: (strokeDescription) => `Automaticky opravené na ${strokeDescription}`,
132
+ autocorrectionCanceled: 'Automatická oprava zrušená',
133
+ enterTextToInsert: 'Text, ktorý sa má vložiť',
134
+ changeTool: 'Zmeniť nástroj',
135
+ findLabel: 'Hľadať',
136
+ toNextMatch: 'Ďalšie',
137
+ closeDialog: 'Zavrieť',
138
+ findDialogShown: 'Dialógové okno vyhľadávania zobrazené',
139
+ findDialogHidden: 'Dialógové okno vyhľadávania je skryté',
140
+ copied: (count) => `Skopírovaných ${count} položiek`,
141
+ pasted: (count) => `Vložených ${count} položiek`,
142
+ toolEnabledAnnouncement: (toolName) => `${toolName} zapnuté`,
143
+ toolDisabledAnnouncement: (toolName) => `${toolName} vypnuté`,
144
+ resizeOutputCommand: (newSize) => `Zmenená veľkosť obrázka na ${newSize.w}x${newSize.h}`,
145
+ enabledAutoresizeOutputCommand: 'Automatická zmena veľkosti výstupu je povolená',
146
+ disabledAutoresizeOutputCommand: 'Automatická zmena veľkosti výstupu je zakázaná',
147
+ addComponentAction: (componentDescription) => `Pridané ${componentDescription}`,
148
+ eraseAction: (componentDescription, numElems) => `Vymazané ${numElems} ${componentDescription}`,
149
+ duplicateAction: (componentDescription, numElems) => `Duplikované ${numElems} ${componentDescription}`,
150
+ elements: 'Prvky',
151
+ erasedNoElements: 'Nič sa nevymazalo.',
152
+ duplicatedNoElements: 'Nič sa neduplikovalo.',
153
+ rotatedBy: (degrees) => `Otočené o ${Math.abs(degrees)} stupňov ${degrees < 0 ? 'clockwise' : 'counter-clockwise'}`,
154
+ movedLeft: 'Presunuté doľava',
155
+ movedUp: 'Presunuté hore',
156
+ movedDown: 'Presunuté dole',
157
+ movedRight: 'Presunuté doprava',
158
+ zoomedOut: 'Oddialené',
159
+ zoomedIn: 'Priblížené',
160
+ andNMoreCommands: (count) => `A ${count} ďalších príkazov.`,
161
+ unlabeledImageNode: 'Obrázok bez označenia',
162
+ stroke: 'Ťah',
163
+ svgObject: 'Objekt SVG',
164
+ emptyBackground: 'Prázdne pozadie',
165
+ gridBackground: 'Pozadie s mriežkou',
166
+ filledBackgroundWithColor: (color) => `Vyplnené pozadie (${color})`,
167
+ text: (text) => `Textový objekt: ${text}`,
168
+ imageNode: (label) => `Obrázok: ${label}`,
169
+ pathNodeCount: (count) => `Viditeľných je ${count} objektov ciest.`,
170
+ textNodeCount: (count) => `Viditeľných je ${count} textových uzlov.`,
171
+ imageNodeCount: (nodeCount) => `Viditeľných je ${nodeCount} obrazových uzlov.`,
172
+ rerenderAsText: 'Opätovne vykresliť ako text.',
173
+ accessibilityInputInstructions: 'Pomocou tlačidla „t“ prečítate obsah zobrazovacieho okna ako text. Pomocou klávesov so šípkami pohybujte zobrazovacím oknom, kliknutím a ťahaním kreslite ťahy. Stlačením tlačidla „w“ priblížite a stlačením tlačidla „s“ oddialite pohľad.',
174
+ loading: (percentage) => `Načítava sa ${percentage}%...`,
175
+ imageEditor: 'Editor obrázkov',
176
+ doneLoading: 'Načítanie dokončené',
177
+ softwareLibraries: 'Knižnice',
178
+ developerInformation: 'Informácie pre vývojárov',
179
+ };
180
+ export default localization;
@@ -58,6 +58,8 @@ export default class Display {
58
58
  setDevicePixelRatio(dpr: number): Promise<void> | undefined;
59
59
  /** @internal */
60
60
  getDevicePixelRatio(): number;
61
+ /** @internal -- used for internal performance improvements. */
62
+ onPointerEvent(event: PointerEvent): void;
61
63
  /**
62
64
  * Rerenders the text-based display.
63
65
  * The text-based display is intended for screen readers and can be navigated to by pressing `tab`.
@@ -4,6 +4,8 @@ import DummyRenderer from './renderers/DummyRenderer.mjs';
4
4
  import { Vec2, Color4 } from '@js-draw/math';
5
5
  import RenderingCache from './caching/RenderingCache.mjs';
6
6
  import TextOnlyRenderer from './renderers/TextOnlyRenderer.mjs';
7
+ import AcceleratedInkingCanvasRenderer from './renderers/AcceleratedInkingCanvasRenderer.mjs';
8
+ import createButton from '../util/dom/createButton.mjs';
7
9
  export var RenderingMode;
8
10
  (function (RenderingMode) {
9
11
  RenderingMode[RenderingMode["DummyRenderer"] = 0] = "DummyRenderer";
@@ -108,7 +110,7 @@ export default class Display {
108
110
  const dryInkCtx = dryInkCanvas.getContext('2d');
109
111
  const wetInkCtx = wetInkCanvas.getContext('2d');
110
112
  this.dryInkRenderer = new CanvasRenderer(dryInkCtx, this.editor.viewport);
111
- this.wetInkRenderer = new CanvasRenderer(wetInkCtx, this.editor.viewport);
113
+ this.wetInkRenderer = new AcceleratedInkingCanvasRenderer(wetInkCtx, this.editor.viewport);
112
114
  dryInkCanvas.className = 'dryInkCanvas';
113
115
  wetInkCanvas.className = 'wetInkCanvas';
114
116
  if (this.parent) {
@@ -176,9 +178,10 @@ export default class Display {
176
178
  initializeTextRendering() {
177
179
  const textRendererOutputContainer = document.createElement('div');
178
180
  textRendererOutputContainer.classList.add('textRendererOutputContainer');
179
- const rerenderButton = document.createElement('button');
180
- rerenderButton.classList.add('rerenderButton');
181
- rerenderButton.innerText = this.editor.localization.rerenderAsText;
181
+ const rerenderButton = createButton({
182
+ classList: ['rerenderButton'],
183
+ text: this.editor.localization.rerenderAsText,
184
+ });
182
185
  this.textRerenderOutput = document.createElement('div');
183
186
  this.textRerenderOutput.setAttribute('aria-live', 'polite');
184
187
  rerenderButton.onclick = () => {
@@ -208,6 +211,12 @@ export default class Display {
208
211
  getDevicePixelRatio() {
209
212
  return this.devicePixelRatio;
210
213
  }
214
+ /** @internal -- used for internal performance improvements. */
215
+ onPointerEvent(event) {
216
+ if (this.wetInkRenderer instanceof AcceleratedInkingCanvasRenderer) {
217
+ this.wetInkRenderer.onEvent(event);
218
+ }
219
+ }
211
220
  /**
212
221
  * Rerenders the text-based display.
213
222
  * The text-based display is intended for screen readers and can be navigated to by pressing `tab`.
@@ -1,7 +1,7 @@
1
1
  import { Color4, Mat33, Point2, Vec2, Rect2 } from '@js-draw/math';
2
2
  import { LoadSaveDataTable } from '../../components/AbstractComponent';
3
3
  import Viewport from '../../Viewport';
4
- import RenderingStyle from '../RenderingStyle';
4
+ import RenderingStyle, { StrokeStyle } from '../RenderingStyle';
5
5
  import TextRenderingStyle from '../TextRenderingStyle';
6
6
  import RenderablePathSpec from '../RenderablePathSpec';
7
7
  export interface RenderableImage {
@@ -10,6 +10,21 @@ export interface RenderableImage {
10
10
  base64Url: string;
11
11
  label?: string;
12
12
  }
13
+ /**
14
+ * An interface that allows renderers to provide accelerated inking.
15
+ *
16
+ * This API is intended to reduce latency by rendering a draft preview of the
17
+ * last, trailing part of a stroke.
18
+ *
19
+ * This may be implemented with, for example, [the web `Ink` API](https://developer.mozilla.org/en-US/docs/Web/API/Ink),
20
+ * or do nothing at all, depending on the renderer and platform.
21
+ */
22
+ export interface DraftInkPresenter {
23
+ /** Enables the ink presenter, if available on the current platform. */
24
+ setEnabled(pointerId: number, enabled: boolean): void;
25
+ /** Sets the color and width of the stroke trail. */
26
+ updateStyle(style: StrokeStyle): void;
27
+ }
13
28
  /**
14
29
  * Abstract base class for renderers.
15
30
  *
@@ -38,6 +53,10 @@ export default abstract class AbstractRenderer {
38
53
  abstract drawImage(image: RenderableImage): void;
39
54
  abstract isTooSmallToRender(rect: Rect2): boolean;
40
55
  setDraftMode(_draftMode: boolean): void;
56
+ /**
57
+ * Returns an API that can be used to accelerate inking.
58
+ */
59
+ getDraftInkPresenter(): DraftInkPresenter;
41
60
  protected objectLevel: number;
42
61
  private currentPaths;
43
62
  private flushPath;
@@ -1,6 +1,7 @@
1
1
  import { Vec2, Path, PathCommandType } from '@js-draw/math';
2
2
  import { stylesEqual } from '../RenderingStyle.mjs';
3
3
  import { pathToRenderable } from '../RenderablePathSpec.mjs';
4
+ const defaultDraftInkPresenter = { setEnabled: () => { }, updateStyle: () => { } };
4
5
  /**
5
6
  * Abstract base class for renderers.
6
7
  *
@@ -24,6 +25,12 @@ export default class AbstractRenderer {
24
25
  return this.viewport;
25
26
  }
26
27
  setDraftMode(_draftMode) { }
28
+ /**
29
+ * Returns an API that can be used to accelerate inking.
30
+ */
31
+ getDraftInkPresenter() {
32
+ return defaultDraftInkPresenter;
33
+ }
27
34
  flushPath() {
28
35
  if (!this.currentPaths) {
29
36
  return;
@@ -0,0 +1,22 @@
1
+ import { StrokeStyle } from '../RenderingStyle';
2
+ import { DraftInkPresenter } from './AbstractRenderer';
3
+ import CanvasRenderer from './CanvasRenderer';
4
+ import Viewport from '../../Viewport';
5
+ declare class CanvasInkPresenter implements DraftInkPresenter {
6
+ private viewport;
7
+ private enabled;
8
+ private presenter;
9
+ private style;
10
+ constructor(canvas: HTMLCanvasElement, viewport: Viewport);
11
+ setEnabled(pointerId: number, enabled: boolean): void;
12
+ updateStyle(style: StrokeStyle): void;
13
+ onEvent(event: PointerEvent): void;
14
+ }
15
+ /** A canvas that uses the web ink API for accelerated inking. */
16
+ export default class AcceleratedInkingCanvasRenderer extends CanvasRenderer {
17
+ private inkPresenter;
18
+ constructor(ctx: CanvasRenderingContext2D, viewport: Viewport);
19
+ getDraftInkPresenter(): CanvasInkPresenter;
20
+ onEvent(event: PointerEvent): void;
21
+ }
22
+ export {};