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.
- package/README.md +1 -1
- package/dist/bundle.js +1 -1
- package/dist/cjs/Editor.d.ts +1 -3
- package/dist/cjs/Editor.js +2 -4
- package/dist/cjs/SVGLoader/SVGLoader.js +2 -0
- package/dist/cjs/Viewport.d.ts +1 -1
- package/dist/cjs/Viewport.js +1 -1
- package/dist/cjs/components/AbstractComponent.d.ts +1 -1
- package/dist/cjs/components/AbstractComponent.js +1 -1
- package/dist/cjs/components/builders/ArrowBuilder.d.ts +1 -1
- package/dist/cjs/components/builders/ArrowBuilder.js +1 -1
- package/dist/cjs/image/EditorImage.d.ts +30 -7
- package/dist/cjs/image/EditorImage.js +30 -7
- package/dist/cjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
- package/dist/cjs/rendering/renderers/CanvasRenderer.js +2 -25
- package/dist/cjs/rendering/renderers/SVGRenderer.js +2 -2
- package/dist/cjs/toolbar/AbstractToolbar.d.ts +19 -0
- package/dist/cjs/toolbar/AbstractToolbar.js +19 -0
- package/dist/cjs/toolbar/IconProvider.d.ts +5 -1
- package/dist/cjs/toolbar/IconProvider.js +112 -146
- package/dist/cjs/toolbar/localization.js +2 -2
- package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +1 -1
- package/dist/cjs/toolbar/widgets/BaseWidget.js +1 -1
- package/dist/cjs/tools/PanZoom.js +1 -1
- package/dist/cjs/tools/Pen.d.ts +13 -0
- package/dist/cjs/tools/Pen.js +13 -0
- package/dist/cjs/tools/lib.d.ts +1 -0
- package/dist/cjs/tools/lib.js +3 -1
- package/dist/cjs/util/cloneElementWithStyles.js +1 -1
- package/dist/cjs/util/createElement.d.ts +62 -0
- package/dist/cjs/util/createElement.js +53 -0
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +1 -3
- package/dist/mjs/Editor.mjs +2 -4
- package/dist/mjs/SVGLoader/SVGLoader.mjs +2 -0
- package/dist/mjs/Viewport.d.ts +1 -1
- package/dist/mjs/Viewport.mjs +1 -1
- package/dist/mjs/components/AbstractComponent.d.ts +1 -1
- package/dist/mjs/components/AbstractComponent.mjs +1 -1
- package/dist/mjs/components/builders/ArrowBuilder.d.ts +1 -1
- package/dist/mjs/components/builders/ArrowBuilder.mjs +1 -1
- package/dist/mjs/image/EditorImage.d.ts +30 -7
- package/dist/mjs/image/EditorImage.mjs +30 -7
- package/dist/mjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
- package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +2 -25
- package/dist/mjs/rendering/renderers/SVGRenderer.mjs +2 -2
- package/dist/mjs/toolbar/AbstractToolbar.d.ts +19 -0
- package/dist/mjs/toolbar/AbstractToolbar.mjs +19 -0
- package/dist/mjs/toolbar/IconProvider.d.ts +5 -1
- package/dist/mjs/toolbar/IconProvider.mjs +112 -146
- package/dist/mjs/toolbar/localization.mjs +2 -2
- package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +1 -1
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +1 -1
- package/dist/mjs/tools/PanZoom.mjs +1 -1
- package/dist/mjs/tools/Pen.d.ts +13 -0
- package/dist/mjs/tools/Pen.mjs +13 -0
- package/dist/mjs/tools/lib.d.ts +1 -0
- package/dist/mjs/tools/lib.mjs +1 -0
- package/dist/mjs/util/cloneElementWithStyles.mjs +1 -1
- package/dist/mjs/util/createElement.d.ts +62 -0
- package/dist/mjs/util/createElement.mjs +47 -0
- package/dist/mjs/version.mjs +1 -1
- 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
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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 {
|
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 =
|
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
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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=
|
177
|
-
<rect x=75 y=75 width=10 height=10 fill=
|
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
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
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.
|
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.
|
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: '
|
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,
|
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
|
101
|
+
* in the future using `addTo`.
|
102
102
|
*/
|
103
103
|
remove(): void;
|
104
104
|
focus(): void;
|
@@ -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
|
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;
|
package/dist/cjs/tools/Pen.d.ts
CHANGED
@@ -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;
|
package/dist/cjs/tools/Pen.js
CHANGED
@@ -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({
|
package/dist/cjs/tools/lib.d.ts
CHANGED
package/dist/cjs/tools/lib.js
CHANGED
@@ -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
|
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;
|
package/dist/cjs/version.js
CHANGED
package/dist/mjs/Editor.d.ts
CHANGED
@@ -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
|
-
*
|
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
|
* ```
|
package/dist/mjs/Editor.mjs
CHANGED
@@ -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
|
-
*
|
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 = () => {
|
package/dist/mjs/Viewport.d.ts
CHANGED
@@ -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}
|
56
|
+
* @see {@link getGridSize}.
|
57
57
|
*/
|
58
58
|
snapToGrid(canvasPos: Point2): {
|
59
59
|
readonly x: number;
|