js-draw 1.22.0 → 1.23.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 (63) hide show
  1. package/README.md +1 -1
  2. package/dist/bundle.js +1 -1
  3. package/dist/cjs/Editor.d.ts +1 -3
  4. package/dist/cjs/Editor.js +2 -4
  5. package/dist/cjs/SVGLoader/SVGLoader.js +2 -0
  6. package/dist/cjs/Viewport.d.ts +1 -1
  7. package/dist/cjs/Viewport.js +1 -1
  8. package/dist/cjs/components/AbstractComponent.d.ts +1 -1
  9. package/dist/cjs/components/AbstractComponent.js +1 -1
  10. package/dist/cjs/components/builders/ArrowBuilder.d.ts +1 -1
  11. package/dist/cjs/components/builders/ArrowBuilder.js +1 -1
  12. package/dist/cjs/image/EditorImage.d.ts +30 -7
  13. package/dist/cjs/image/EditorImage.js +30 -7
  14. package/dist/cjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
  15. package/dist/cjs/rendering/renderers/CanvasRenderer.js +2 -25
  16. package/dist/cjs/rendering/renderers/SVGRenderer.js +2 -2
  17. package/dist/cjs/toolbar/AbstractToolbar.d.ts +19 -0
  18. package/dist/cjs/toolbar/AbstractToolbar.js +19 -0
  19. package/dist/cjs/toolbar/IconProvider.d.ts +5 -1
  20. package/dist/cjs/toolbar/IconProvider.js +112 -146
  21. package/dist/cjs/toolbar/localization.js +2 -2
  22. package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +1 -1
  23. package/dist/cjs/toolbar/widgets/BaseWidget.js +1 -1
  24. package/dist/cjs/tools/PanZoom.js +1 -1
  25. package/dist/cjs/tools/Pen.d.ts +13 -0
  26. package/dist/cjs/tools/Pen.js +13 -0
  27. package/dist/cjs/tools/lib.d.ts +1 -0
  28. package/dist/cjs/tools/lib.js +3 -1
  29. package/dist/cjs/util/cloneElementWithStyles.js +1 -1
  30. package/dist/cjs/util/createElement.d.ts +62 -0
  31. package/dist/cjs/util/createElement.js +53 -0
  32. package/dist/cjs/version.js +1 -1
  33. package/dist/mjs/Editor.d.ts +1 -3
  34. package/dist/mjs/Editor.mjs +2 -4
  35. package/dist/mjs/SVGLoader/SVGLoader.mjs +2 -0
  36. package/dist/mjs/Viewport.d.ts +1 -1
  37. package/dist/mjs/Viewport.mjs +1 -1
  38. package/dist/mjs/components/AbstractComponent.d.ts +1 -1
  39. package/dist/mjs/components/AbstractComponent.mjs +1 -1
  40. package/dist/mjs/components/builders/ArrowBuilder.d.ts +1 -1
  41. package/dist/mjs/components/builders/ArrowBuilder.mjs +1 -1
  42. package/dist/mjs/image/EditorImage.d.ts +30 -7
  43. package/dist/mjs/image/EditorImage.mjs +30 -7
  44. package/dist/mjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
  45. package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +2 -25
  46. package/dist/mjs/rendering/renderers/SVGRenderer.mjs +2 -2
  47. package/dist/mjs/toolbar/AbstractToolbar.d.ts +19 -0
  48. package/dist/mjs/toolbar/AbstractToolbar.mjs +19 -0
  49. package/dist/mjs/toolbar/IconProvider.d.ts +5 -1
  50. package/dist/mjs/toolbar/IconProvider.mjs +112 -146
  51. package/dist/mjs/toolbar/localization.mjs +2 -2
  52. package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +1 -1
  53. package/dist/mjs/toolbar/widgets/BaseWidget.mjs +1 -1
  54. package/dist/mjs/tools/PanZoom.mjs +1 -1
  55. package/dist/mjs/tools/Pen.d.ts +13 -0
  56. package/dist/mjs/tools/Pen.mjs +13 -0
  57. package/dist/mjs/tools/lib.d.ts +1 -0
  58. package/dist/mjs/tools/lib.mjs +1 -0
  59. package/dist/mjs/util/cloneElementWithStyles.mjs +1 -1
  60. package/dist/mjs/util/createElement.d.ts +62 -0
  61. package/dist/mjs/util/createElement.mjs +47 -0
  62. package/dist/mjs/version.mjs +1 -1
  63. package/package.json +4 -4
@@ -15,31 +15,32 @@ const Viewport_1 = __importDefault(require("../Viewport"));
15
15
  const FreehandLineBuilder_1 = require("../components/builders/FreehandLineBuilder");
16
16
  const PolylineBuilder_1 = require("../components/builders/PolylineBuilder");
17
17
  const Eraser_1 = require("../tools/Eraser");
18
+ const createElement_1 = require("../util/createElement");
18
19
  const svgNamespace = 'http://www.w3.org/2000/svg';
19
- const iconColorFill = `
20
- style='fill: var(--icon-color);'
21
- `;
22
- const iconColorStrokeFill = `
23
- style='fill: var(--icon-color); stroke: var(--icon-color);'
24
- `;
25
20
  let checkerboardIdCounter = 0;
26
21
  const makeCheckerboardPattern = () => {
27
22
  const id = `checkerboard-${checkerboardIdCounter++}`;
28
- const patternDef = `
29
- <pattern
30
- id='${id}'
31
- viewBox='0,0,10,10'
32
- width='20%'
33
- height='20%'
34
- patternUnits='userSpaceOnUse'
35
- >
36
- <rect x='0' y='0' width='10' height='10' fill='white'/>
37
- <rect x='0' y='0' width='5' height='5' fill='gray'/>
38
- <rect x='5' y='5' width='5' height='5' fill='gray'/>
39
- </pattern>
40
- `;
23
+ const patternElement = (0, createElement_1.createSvgElement)('pattern', {
24
+ id: id,
25
+ viewBox: '0,0,10,10',
26
+ width: '20%',
27
+ height: '20%',
28
+ patternUnits: 'userSpaceOnUse',
29
+ children: (0, createElement_1.createSvgElements)('rect', [
30
+ { x: 0, y: 0, width: 10, height: 10, fill: 'white' },
31
+ { x: 0, y: 0, width: 5, height: 5, fill: 'gray' },
32
+ { x: 5, y: 5, width: 5, height: 5, fill: 'gray' },
33
+ ]),
34
+ });
41
35
  const patternRef = `url(#${id})`;
42
- return { patternDef, patternRef };
36
+ return {
37
+ patternDefElement: patternElement,
38
+ // @deprecated use patternDefElement
39
+ get patternDef() {
40
+ return patternElement.innerHTML;
41
+ },
42
+ patternRef,
43
+ };
43
44
  };
44
45
  const makeRedoIcon = (mirror) => {
45
46
  const icon = document.createElementNS(svgNamespace, 'svg');
@@ -55,11 +56,14 @@ const makeRedoIcon = (mirror) => {
55
56
  transform-origin: center;
56
57
  }
57
58
  </style>
58
- <path
59
- d='M20,20 A15,15 0 0 1 70,80 L80,90 L60,70 L65,90 L87,90 L65,80'
60
- class='toolbar-svg-undo-redo-icon'
61
- style='${mirror ? 'transform: scale(-1, 1);' : ''}'/>
62
59
  `;
60
+ const path = document.createElementNS(svgNamespace, 'path');
61
+ path.setAttribute('d', 'M20,20 A15,15 0 0 1 70,80 L80,90 L60,70 L65,90 L87,90 L65,80');
62
+ path.classList.add('toolbar-svg-undo-redo-icon');
63
+ if (mirror) {
64
+ path.style.transform = 'scale(-1, 1)';
65
+ }
66
+ icon.appendChild(path);
63
67
  icon.setAttribute('viewBox', '0 0 100 100');
64
68
  return icon;
65
69
  };
@@ -107,65 +111,62 @@ class IconProvider {
107
111
  return makeRedoIcon(false);
108
112
  }
109
113
  makeDropdownIcon() {
110
- const icon = document.createElementNS(svgNamespace, 'svg');
111
- icon.innerHTML = `
112
- <g>
113
- <path
114
- d='M5,10 L50,90 L95,10 Z'
115
- ${iconColorFill}
116
- />
117
- </g>
118
- `;
114
+ const icon = this.makeIconFromPath('M5,10 L50,90 L95,10 Z');
119
115
  icon.setAttribute('viewBox', '-10 -10 110 110');
120
116
  return icon;
121
117
  }
122
118
  makeEraserIcon(eraserSize, mode) {
123
- const icon = document.createElementNS(svgNamespace, 'svg');
124
119
  eraserSize ??= 10;
125
120
  const scaledSize = eraserSize / 4;
126
121
  const eraserColor = '#ff70af';
127
122
  // Draw an eraser-like shape. Created with Inkscape
128
- icon.innerHTML = `
129
- <defs>
130
- <linearGradient id="dash-pattern">
131
- <stop offset="80%" stop-color="${eraserColor}"/>
132
- <stop offset="85%" stop-color="white"/>
133
- <stop offset="90%" stop-color="${eraserColor}"/>
134
- </linearGradient>
135
- </defs>
136
- <g>
137
- <path
138
- style="fill:${mode === Eraser_1.EraserMode.PartialStroke ? 'url(#dash-pattern)' : eraserColor}"
139
- stroke="black"
140
- transform="rotate(41.35)"
141
- d="M 52.5 27
142
- C 50 28.9 48.9 31.7 48.9 34.8
143
- L 48.9 39.8
144
- C 48.9 45.3 53.4 49.8 58.9 49.8
145
- L 103.9 49.8
146
- C 105.8 49.8 107.6 49.2 109.1 48.3
147
- L 110.2 ${scaledSize + 49.5} L 159.7 ${scaledSize + 5}
148
- L 157.7 ${-scaledSize + 5.2} L 112.4 ${49.5 - scaledSize}
149
- C 113.4 43.5 113.9 41.7 113.9 39.8
150
- L 113.9 34.8
151
- C 113.9 29.3 109.4 24.8 103.9 24.8
152
- L 58.9 24.8
153
- C 56.5 24.8 54.3 25.7 52.5 27
154
- z "
155
- id="path438" />
156
-
157
- <rect
158
- stroke="#cc8077"
159
- ${iconColorFill}
160
- id="rect218"
161
- width="65"
162
- height="75"
163
- x="48.9"
164
- y="-38.7"
165
- transform="rotate(41.35)" />
166
- </g>
167
- `;
168
- icon.setAttribute('viewBox', '0 0 120 120');
123
+ const icon = (0, createElement_1.createSvgElement)('svg', {
124
+ viewBox: '0 0 120 120',
125
+ children: [
126
+ (0, createElement_1.createSvgElement)('defs', {
127
+ children: [
128
+ (0, createElement_1.createSvgElement)('linearGradient', {
129
+ id: 'dash-pattern',
130
+ children: (0, createElement_1.createSvgElements)('stop', [
131
+ { offset: '80%', 'stop-color': eraserColor },
132
+ { offset: '85%', 'stop-color': 'white' },
133
+ { offset: '90%', 'stop-color': eraserColor },
134
+ ]),
135
+ }),
136
+ ],
137
+ }),
138
+ (0, createElement_1.createSvgElement)('path', {
139
+ fill: mode === Eraser_1.EraserMode.PartialStroke ? 'url(#dash-pattern)' : eraserColor,
140
+ stroke: 'black',
141
+ transform: 'rotate(41.35)',
142
+ d: `
143
+ M 52.5 27
144
+ C 50 28.9 48.9 31.7 48.9 34.8
145
+ L 48.9 39.8
146
+ C 48.9 45.3 53.4 49.8 58.9 49.8
147
+ L 103.9 49.8
148
+ C 105.8 49.8 107.6 49.2 109.1 48.3
149
+ L 110.2 ${scaledSize + 49.5} L 159.7 ${scaledSize + 5}
150
+ L 157.7 ${-scaledSize + 5.2} L 112.4 ${49.5 - scaledSize}
151
+ C 113.4 43.5 113.9 41.7 113.9 39.8
152
+ L 113.9 34.8
153
+ C 113.9 29.3 109.4 24.8 103.9 24.8
154
+ L 58.9 24.8
155
+ C 56.5 24.8 54.3 25.7 52.5 27
156
+ z
157
+ `,
158
+ }),
159
+ (0, createElement_1.createSvgElement)('rect', {
160
+ stroke: '#cc8077',
161
+ fill: 'var(--icon-color)',
162
+ width: 65,
163
+ height: 75,
164
+ x: 48.9,
165
+ y: -38.7,
166
+ transform: 'rotate(41.35)',
167
+ }),
168
+ ],
169
+ });
169
170
  return icon;
170
171
  }
171
172
  makeSelectionIcon() {
@@ -173,8 +174,8 @@ class IconProvider {
173
174
  // Draw a cursor-like shape
174
175
  icon.innerHTML = `
175
176
  <g>
176
- <rect x=10 y=10 width=70 height=70 fill='pink' stroke='black'/>
177
- <rect x=75 y=75 width=10 height=10 fill='white' stroke='black'/>
177
+ <rect x="10" y="10" width="70" height="70" fill="pink" stroke="black"/>
178
+ <rect x="75" y="75" width="10" height="10" fill="white" stroke="black"/>
178
179
  </g>
179
180
  `;
180
181
  icon.setAttribute('viewBox', '0 0 100 100');
@@ -437,8 +438,6 @@ class IconProvider {
437
438
  const strokeSize = Math.round(Math.sqrt(penStyle.thickness) * 4);
438
439
  const color = penStyle.color;
439
440
  const rounded = this.isRoundedTipPen(penStyle);
440
- const icon = document.createElementNS(svgNamespace, 'svg');
441
- icon.setAttribute('viewBox', '0 0 100 100');
442
441
  const tipThickness = strokeSize / 2;
443
442
  const inkTipPath = `
444
443
  M ${15 - tipThickness},${80 - tipThickness}
@@ -471,71 +470,35 @@ class IconProvider {
471
470
  const pencilTipColor = math_1.Color4.fromHex('#f4d7d7');
472
471
  const tipColor = pencilTipColor.mix(color, tipThickness / 40 - 0.1).toHexString();
473
472
  const checkerboardPattern = makeCheckerboardPattern();
474
- const ink = `
475
- <path
476
- fill="${checkerboardPattern.patternRef}"
477
- d="${inkTipPath}"
478
- />
479
- <path
480
- fill="${checkerboardPattern.patternRef}"
481
- d="${inkTrailPath}"
482
- />
483
- <path
484
- fill="${color}"
485
- d="${inkTipPath}"
486
- />
487
- <path
488
- fill="${color}"
489
- d="${inkTrailPath}"
490
- />
491
- `;
492
- const penTip = `
493
- <path
494
- fill="${checkerboardPattern.patternRef}"
495
- d="${penTipPath}"
496
- />
497
- <path
498
- fill="${tipColor}"
499
- stroke="${color}"
500
- d="${penTipPath}"
501
- />
502
- `;
503
- const grip = `
504
- <path
505
- ${iconColorStrokeFill}
506
- d="${gripMainPath}"
507
- />
508
-
509
- <!-- shadows -->
510
- <path
511
- fill="rgba(150, 150, 150, 0.3)"
512
- d="${gripShadow1Path}"
513
- />
514
- <path
515
- fill="rgba(100, 100, 100, 0.2)"
516
- d="${gripShadow2Path}"
517
- />
518
-
519
- <!-- color bubble -->
520
- <path
521
- fill="${checkerboardPattern.patternRef}"
522
- d="${colorBubblePath}"
523
- />
524
- <path
525
- fill="${color}"
526
- d="${colorBubblePath}"
527
- />
528
- `;
529
- icon.innerHTML = `
530
- <defs>
531
- ${checkerboardPattern.patternDef}
532
- </defs>
533
- <g>
534
- ${ink}
535
- ${penTip}
536
- ${grip}
537
- </g>
538
- `;
473
+ const colorString = color.toHexString();
474
+ const ink = (0, createElement_1.createSvgPaths)({
475
+ fill: checkerboardPattern.patternRef,
476
+ d: inkTipPath,
477
+ }, {
478
+ fill: checkerboardPattern.patternRef,
479
+ d: inkTrailPath,
480
+ }, {
481
+ fill: colorString,
482
+ d: inkTipPath,
483
+ }, {
484
+ fill: colorString,
485
+ d: inkTrailPath,
486
+ });
487
+ const penTip = (0, createElement_1.createSvgPaths)({ fill: checkerboardPattern.patternRef, d: penTipPath }, { fill: tipColor, stroke: colorString, d: penTipPath });
488
+ const grip = (0, createElement_1.createSvgPaths)({ fill: 'var(--icon-color)', stroke: 'var(--icon-color)', d: gripMainPath },
489
+ // Shadows
490
+ { fill: 'rgba(150, 150, 150, 0.3)', d: gripShadow1Path }, { fill: 'rgba(100, 100, 100, 0.2)', d: gripShadow2Path },
491
+ // Color bubble
492
+ { fill: checkerboardPattern.patternRef, d: colorBubblePath }, { fill: colorString, d: colorBubblePath });
493
+ const icon = document.createElementNS(svgNamespace, 'svg');
494
+ icon.setAttribute('viewBox', '0 0 100 100');
495
+ const iconMainContent = (0, createElement_1.createSvgElement)('g', {
496
+ children: [ink, penTip, grip].flat(),
497
+ });
498
+ const defs = (0, createElement_1.createSvgElement)('defs', {
499
+ children: [checkerboardPattern.patternDefElement],
500
+ });
501
+ icon.replaceChildren(defs, iconMainContent);
539
502
  return icon;
540
503
  }
541
504
  makeIconFromFactory(penStyle) {
@@ -567,7 +530,7 @@ class IconProvider {
567
530
  if (includeTransparencyGrid) {
568
531
  const checkerboardPattern = makeCheckerboardPattern();
569
532
  const defs = document.createElementNS(svgNamespace, 'defs');
570
- defs.innerHTML = checkerboardPattern.patternDef;
533
+ defs.appendChild(checkerboardPattern.patternDefElement);
571
534
  icon.appendChild(defs);
572
535
  const background = document.createElementNS(svgNamespace, 'g');
573
536
  icon.appendChild(background);
@@ -641,7 +604,7 @@ class IconProvider {
641
604
  if (color) {
642
605
  const checkerboardPattern = makeCheckerboardPattern();
643
606
  const defs = document.createElementNS(svgNamespace, 'defs');
644
- defs.innerHTML = checkerboardPattern.patternDef;
607
+ defs.appendChild(checkerboardPattern.patternDefElement);
645
608
  icon.appendChild(defs);
646
609
  const fluidBackground = document.createElementNS(svgNamespace, 'path');
647
610
  const fluid = document.createElementNS(svgNamespace, 'path');
@@ -846,6 +809,9 @@ class IconProvider {
846
809
  * @returns An object with both the definition of a checkerboard pattern and the syntax to
847
810
  * reference that pattern. The defs provided by this function should be wrapped within a
848
811
  * `<defs></defs>` element.
812
+ *
813
+ * **Note**: This function's return value includes both `patternDefElement` (which returns
814
+ * an Element) and a (deprecated) `patternDef` string. Avoid using the `patternDef` result.
849
815
  */
850
816
  makeCheckerboardPattern() {
851
817
  return makeCheckerboardPattern();
@@ -48,7 +48,7 @@ exports.defaultToolbarLocalization = {
48
48
  about: 'About',
49
49
  inputStabilization: 'Stabilization',
50
50
  strokeAutocorrect: 'Autocorrect',
51
- touchPanning: 'Touchscreen panning',
51
+ touchPanning: 'Scroll with touch',
52
52
  roundedTipPen: 'Round',
53
53
  roundedTipPen2: 'Polyline',
54
54
  flatTipPen: 'Flat',
@@ -75,7 +75,7 @@ exports.defaultToolbarLocalization = {
75
75
  handDropdown__zoomOutHelpText: 'Zooms out.',
76
76
  handDropdown__resetViewHelpText: 'Resets the zoom level to 100% and resets scroll.',
77
77
  handDropdown__zoomDisplayHelpText: 'Shows the current zoom level. 100% shows the image at its actual size.',
78
- handDropdown__touchPanningHelpText: 'When enabled, touch gestures move the image rather than select or draw.',
78
+ handDropdown__touchPanningHelpText: 'When enabled, touchscreen gestures move the image rather than select or draw.',
79
79
  handDropdown__lockRotationHelpText: 'When enabled, prevents touch gestures from rotating the screen.',
80
80
  eraserDropdown__baseHelpText: 'This tool removes strokes, images, and text under the cursor.',
81
81
  eraserDropdown__thicknessHelpText: 'Changes the size of the eraser.',
@@ -98,7 +98,7 @@ export default abstract class BaseWidget {
98
98
  addTo(parent: HTMLElement): HTMLElement;
99
99
  /**
100
100
  * Remove this. This allows the widget to be added to a toolbar again
101
- * in the future using {@link addTo}.
101
+ * in the future using `addTo`.
102
102
  */
103
103
  remove(): void;
104
104
  focus(): void;
@@ -306,7 +306,7 @@ class BaseWidget {
306
306
  }
307
307
  /**
308
308
  * Remove this. This allows the widget to be added to a toolbar again
309
- * in the future using {@link addTo}.
309
+ * in the future using `addTo`.
310
310
  */
311
311
  remove() {
312
312
  this.container.remove();
@@ -433,7 +433,7 @@ class PanZoom extends BaseTool_1.default {
433
433
  translation = translation.times(-1);
434
434
  rotation = rotation * -1;
435
435
  scale = 1 / scale;
436
- // Work around an issue that seems to be related to rotation matricies losing precision on inversion.
436
+ // Work around an issue that seems to be related to rotation matrices losing precision on inversion.
437
437
  // TODO: Figure out why and implement a better solution.
438
438
  if (rotation !== 0) {
439
439
  rotation += 0.0001;
@@ -11,6 +11,12 @@ export interface PenStyle {
11
11
  readonly thickness: number;
12
12
  readonly factory: ComponentBuilderFactory;
13
13
  }
14
+ /**
15
+ * A tool that allows drawing shapes and freehand lines.
16
+ *
17
+ * To change the type of shape drawn by the pen (e.g. to switch to the rectangle
18
+ * pen type), see {@link setStrokeFactory}.
19
+ */
14
20
  export default class Pen extends BaseTool {
15
21
  private editor;
16
22
  protected builder: ComponentBuilder | null;
@@ -42,6 +48,13 @@ export default class Pen extends BaseTool {
42
48
  private noteUpdated;
43
49
  setColor(color: Color4): void;
44
50
  setThickness(thickness: number): void;
51
+ /**
52
+ * Changes the type of stroke created by the pen. The given `factory` can be one of the built-in
53
+ * stroke factories (e.g. {@link makeFreehandLineBuilder}) or a custom stroke factory.
54
+ *
55
+ * Example:
56
+ * [[include:doc-pages/inline-examples/changing-pen-types.md]]
57
+ */
45
58
  setStrokeFactory(factory: ComponentBuilderFactory): void;
46
59
  setHasStabilization(hasStabilization: boolean): void;
47
60
  setStrokeAutocorrectEnabled(enabled: boolean): void;
@@ -37,6 +37,12 @@ const keybindings_2 = require("./keybindings");
37
37
  const InputStabilizer_1 = __importDefault(require("./InputFilter/InputStabilizer"));
38
38
  const ReactiveValue_1 = require("../util/ReactiveValue");
39
39
  const StationaryPenDetector_1 = __importStar(require("./util/StationaryPenDetector"));
40
+ /**
41
+ * A tool that allows drawing shapes and freehand lines.
42
+ *
43
+ * To change the type of shape drawn by the pen (e.g. to switch to the rectangle
44
+ * pen type), see {@link setStrokeFactory}.
45
+ */
40
46
  class Pen extends BaseTool_1.default {
41
47
  constructor(editor, description, style) {
42
48
  super(editor.notifier, description);
@@ -272,6 +278,13 @@ class Pen extends BaseTool_1.default {
272
278
  });
273
279
  }
274
280
  }
281
+ /**
282
+ * Changes the type of stroke created by the pen. The given `factory` can be one of the built-in
283
+ * stroke factories (e.g. {@link makeFreehandLineBuilder}) or a custom stroke factory.
284
+ *
285
+ * Example:
286
+ * [[include:doc-pages/inline-examples/changing-pen-types.md]]
287
+ */
275
288
  setStrokeFactory(factory) {
276
289
  if (factory !== this.style.factory) {
277
290
  this.styleValue.set({
@@ -1,3 +1,4 @@
1
+ export { default as InputMapper } from './InputFilter/InputMapper';
1
2
  export { default as BaseTool } from './BaseTool';
2
3
  export { default as ToolController } from './ToolController';
3
4
  export { default as ToolEnabledGroup } from './ToolEnabledGroup';
@@ -3,7 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ToolbarShortcutHandler = exports.SoundUITool = exports.PasteHandler = exports.EraserMode = exports.EraserTool = exports.SelectAllShortcutHandler = exports.SelectionTool = exports.TextTool = exports.PenTool = exports.PanZoomMode = exports.PanZoomTool = exports.ToolSwitcherShortcut = exports.UndoRedoShortcut = exports.ToolEnabledGroup = exports.ToolController = exports.BaseTool = void 0;
6
+ exports.ToolbarShortcutHandler = exports.SoundUITool = exports.PasteHandler = exports.EraserMode = exports.EraserTool = exports.SelectAllShortcutHandler = exports.SelectionTool = exports.TextTool = exports.PenTool = exports.PanZoomMode = exports.PanZoomTool = exports.ToolSwitcherShortcut = exports.UndoRedoShortcut = exports.ToolEnabledGroup = exports.ToolController = exports.BaseTool = exports.InputMapper = void 0;
7
+ var InputMapper_1 = require("./InputFilter/InputMapper");
8
+ Object.defineProperty(exports, "InputMapper", { enumerable: true, get: function () { return __importDefault(InputMapper_1).default; } });
7
9
  var BaseTool_1 = require("./BaseTool");
8
10
  Object.defineProperty(exports, "BaseTool", { enumerable: true, get: function () { return __importDefault(BaseTool_1).default; } });
9
11
  var ToolController_1 = require("./ToolController");
@@ -12,7 +12,7 @@ const cloneElementWithStyles = (element) => {
12
12
  for (let index = 0; index < originalComputedStyle.length; index++) {
13
13
  const propertyName = originalComputedStyle.item(index);
14
14
  const propertyValue = originalComputedStyle.getPropertyValue(propertyName);
15
- clonedElement.style.setProperty(propertyName, propertyValue);
15
+ clonedElement.style?.setProperty(propertyName, propertyValue);
16
16
  }
17
17
  for (let i = 0; i < originalElement.children.length; i++) {
18
18
  const originalChild = originalElement.children.item(i);
@@ -0,0 +1,62 @@
1
+ type ElementTagNames = keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap;
2
+ /**
3
+ * Maps from known elment tag names to options that can be set with .setAttribute.
4
+ * New elements/properties should be added as necessary.
5
+ */
6
+ interface ElementToPropertiesMap {
7
+ path: {
8
+ d: string;
9
+ fill: string;
10
+ stroke: string;
11
+ transform: string;
12
+ };
13
+ rect: {
14
+ stroke: string;
15
+ fill: string;
16
+ x: number;
17
+ y: number;
18
+ width: number;
19
+ height: number;
20
+ transform: string;
21
+ };
22
+ pattern: {
23
+ viewBox: string;
24
+ width: string;
25
+ height: string;
26
+ patternUnits: 'userSpaceOnUse';
27
+ };
28
+ stop: {
29
+ offset: string;
30
+ 'stop-color': string;
31
+ };
32
+ svg: {
33
+ viewBox: `${number} ${number} ${number} ${number}`;
34
+ };
35
+ }
36
+ type EmptyObject = Record<never, never>;
37
+ type ElementProperties<Tag extends ElementTagNames> = Tag extends keyof ElementToPropertiesMap ? Partial<ElementToPropertiesMap[Tag]> : EmptyObject;
38
+ /** Contains options for creating an element with tag = `Tag`. */
39
+ type ElementConfig<Tag extends ElementTagNames> = ElementProperties<Tag> & {
40
+ id?: string;
41
+ children?: (HTMLElement | SVGElement)[];
42
+ };
43
+ /**
44
+ * Maps from element tag names (e.g. `Tag='button'`) to the corresponding element type
45
+ * (e.g. `HTMLButtonElement`).
46
+ */
47
+ type ElementTagToType<Tag extends ElementTagNames> = Tag extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[Tag] : Tag extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[Tag] : never;
48
+ export declare enum ElementNamespace {
49
+ Html = "html",
50
+ Svg = "svg"
51
+ }
52
+ /**
53
+ * Shorthand for creating an element with `document.createElement`, then assigning properties.
54
+ *
55
+ * Non-HTML elements (e.g. `svg` elements) should use the `elementType` parameter to select
56
+ * the element namespace.
57
+ */
58
+ declare const createElement: <Tag extends ElementTagNames>(tag: Tag, props: ElementConfig<Tag>, elementType?: ElementNamespace) => ElementTagToType<Tag>;
59
+ export declare const createSvgElement: <Tag extends keyof SVGElementTagNameMap>(tag: Tag, props: ElementConfig<Tag>) => ElementTagToType<Tag>;
60
+ export declare const createSvgElements: <Tag extends keyof SVGElementTagNameMap>(tag: Tag, elements: ElementConfig<Tag>[]) => ElementTagToType<Tag>[];
61
+ export declare const createSvgPaths: (...paths: ElementConfig<"path">[]) => SVGPathElement[];
62
+ export default createElement;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSvgPaths = exports.createSvgElements = exports.createSvgElement = exports.ElementNamespace = void 0;
4
+ var ElementNamespace;
5
+ (function (ElementNamespace) {
6
+ ElementNamespace["Html"] = "html";
7
+ ElementNamespace["Svg"] = "svg";
8
+ })(ElementNamespace || (exports.ElementNamespace = ElementNamespace = {}));
9
+ /**
10
+ * Shorthand for creating an element with `document.createElement`, then assigning properties.
11
+ *
12
+ * Non-HTML elements (e.g. `svg` elements) should use the `elementType` parameter to select
13
+ * the element namespace.
14
+ */
15
+ const createElement = (tag, props, elementType = ElementNamespace.Html) => {
16
+ let elem;
17
+ if (elementType === ElementNamespace.Html) {
18
+ elem = document.createElement(tag);
19
+ }
20
+ else if (elementType === ElementNamespace.Svg) {
21
+ elem = document.createElementNS('http://www.w3.org/2000/svg', tag);
22
+ }
23
+ else {
24
+ throw new Error(`Unknown element type ${elementType}`);
25
+ }
26
+ for (const [key, value] of Object.entries(props)) {
27
+ if (key === 'children')
28
+ continue;
29
+ if (typeof value !== 'string' && typeof value !== 'number') {
30
+ throw new Error(`Unsupported value type ${typeof value}`);
31
+ }
32
+ elem.setAttribute(key, value.toString());
33
+ }
34
+ if (props.children) {
35
+ for (const item of props.children) {
36
+ elem.appendChild(item);
37
+ }
38
+ }
39
+ return elem;
40
+ };
41
+ const createSvgElement = (tag, props) => {
42
+ return createElement(tag, props, ElementNamespace.Svg);
43
+ };
44
+ exports.createSvgElement = createSvgElement;
45
+ const createSvgElements = (tag, elements) => {
46
+ return elements.map((props) => (0, exports.createSvgElement)(tag, props));
47
+ };
48
+ exports.createSvgElements = createSvgElements;
49
+ const createSvgPaths = (...paths) => {
50
+ return (0, exports.createSvgElements)('path', paths);
51
+ };
52
+ exports.createSvgPaths = createSvgPaths;
53
+ exports.default = createElement;
@@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  * @internal
7
7
  */
8
8
  exports.default = {
9
- number: '1.22.0',
9
+ number: '1.23.1',
10
10
  };
@@ -411,9 +411,7 @@ export declare class Editor {
411
411
  * Use this to show finalized commands that don't need to have `announceForAccessibility`
412
412
  * called.
413
413
  *
414
- * Prefer `command.apply(editor)` for incomplete commands. `dispatchNoAnnounce` may allow
415
- * clients to listen for the application of commands (e.g. `SerializableCommand`s so they can
416
- * be sent across the network), while `apply` does not.
414
+ * If `addToHistory` is `false`, this is equivalent to `command.apply(editor)`.
417
415
  *
418
416
  * @example
419
417
  * ```
@@ -108,7 +108,7 @@ export class Editor {
108
108
  maxZoom: settings.maxZoom ?? 1e12,
109
109
  keyboardShortcutOverrides: settings.keyboardShortcutOverrides ?? {},
110
110
  iconProvider: settings.iconProvider ?? new IconProvider(),
111
- notices: [],
111
+ notices: settings.notices ?? [],
112
112
  appInfo: settings.appInfo ? { ...settings.appInfo } : null,
113
113
  pens: {
114
114
  additionalPenTypes: settings.pens?.additionalPenTypes ?? [],
@@ -726,9 +726,7 @@ export class Editor {
726
726
  * Use this to show finalized commands that don't need to have `announceForAccessibility`
727
727
  * called.
728
728
  *
729
- * Prefer `command.apply(editor)` for incomplete commands. `dispatchNoAnnounce` may allow
730
- * clients to listen for the application of commands (e.g. `SerializableCommand`s so they can
731
- * be sent across the network), while `apply` does not.
729
+ * If `addToHistory` is `false`, this is equivalent to `command.apply(editor)`.
732
730
  *
733
731
  * @example
734
732
  * ```
@@ -532,6 +532,7 @@ export default class SVGLoader {
532
532
  const { svgElem, cleanUp } = (() => {
533
533
  // If the user requested an iframe load (the default) try to load with an iframe.
534
534
  // There are some cases (e.g. in a sandboxed iframe) where this doesn't work.
535
+ // TODO(v2): Use domParserLoad by default.
535
536
  if (!domParserLoad) {
536
537
  try {
537
538
  const sandbox = document.createElement('iframe');
@@ -571,6 +572,7 @@ export default class SVGLoader {
571
572
  `);
572
573
  sandboxDoc.close();
573
574
  const svgElem = sandboxDoc.createElementNS('http://www.w3.org/2000/svg', 'svg');
575
+ // eslint-disable-next-line no-unsanitized/property -- setting innerHTML in a sandboxed document.
574
576
  svgElem.innerHTML = text;
575
577
  sandboxDoc.body.appendChild(svgElem);
576
578
  const cleanUp = () => {
@@ -53,7 +53,7 @@ export declare class Viewport {
53
53
  /**
54
54
  * Snaps `canvasPos` to the nearest grid cell corner.
55
55
  *
56
- * @see {@link getGridSize} and {@link getScaleFactorToNearestPowerOf}.
56
+ * @see {@link getGridSize}.
57
57
  */
58
58
  snapToGrid(canvasPos: Point2): {
59
59
  readonly x: number;