js-draw 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/.firebase/hosting.ZG9jcw.cache +338 -0
  2. package/.github/ISSUE_TEMPLATE/translation.md +1 -1
  3. package/CHANGELOG.md +19 -0
  4. package/dist/bundle.js +1 -1
  5. package/dist/src/Editor.d.ts +8 -6
  6. package/dist/src/Editor.js +8 -4
  7. package/dist/src/EditorImage.d.ts +3 -0
  8. package/dist/src/EditorImage.js +7 -0
  9. package/dist/src/SVGLoader.js +7 -8
  10. package/dist/src/components/AbstractComponent.d.ts +1 -0
  11. package/dist/src/components/AbstractComponent.js +4 -0
  12. package/dist/src/components/SVGGlobalAttributesObject.d.ts +1 -0
  13. package/dist/src/components/SVGGlobalAttributesObject.js +3 -0
  14. package/dist/src/components/Stroke.js +1 -0
  15. package/dist/src/components/Text.d.ts +11 -8
  16. package/dist/src/components/Text.js +63 -20
  17. package/dist/src/components/UnknownSVGObject.d.ts +1 -0
  18. package/dist/src/components/UnknownSVGObject.js +3 -0
  19. package/dist/src/components/builders/FreehandLineBuilder.d.ts +9 -2
  20. package/dist/src/components/builders/FreehandLineBuilder.js +129 -30
  21. package/dist/src/components/lib.d.ts +2 -2
  22. package/dist/src/components/lib.js +2 -2
  23. package/dist/src/rendering/renderers/CanvasRenderer.js +2 -2
  24. package/dist/src/rendering/renderers/SVGRenderer.d.ts +2 -0
  25. package/dist/src/rendering/renderers/SVGRenderer.js +49 -22
  26. package/dist/src/testing/beforeEachFile.js +4 -0
  27. package/dist/src/toolbar/HTMLToolbar.js +2 -3
  28. package/dist/src/toolbar/IconProvider.d.ts +30 -0
  29. package/dist/src/toolbar/IconProvider.js +417 -0
  30. package/dist/src/toolbar/lib.d.ts +1 -1
  31. package/dist/src/toolbar/lib.js +1 -2
  32. package/dist/src/toolbar/localization.d.ts +0 -1
  33. package/dist/src/toolbar/localization.js +0 -1
  34. package/dist/src/toolbar/makeColorInput.js +1 -2
  35. package/dist/src/toolbar/widgets/BaseWidget.js +1 -2
  36. package/dist/src/toolbar/widgets/EraserToolWidget.js +1 -2
  37. package/dist/src/toolbar/widgets/HandToolWidget.d.ts +5 -3
  38. package/dist/src/toolbar/widgets/HandToolWidget.js +35 -12
  39. package/dist/src/toolbar/widgets/PenToolWidget.js +10 -8
  40. package/dist/src/toolbar/widgets/SelectionToolWidget.d.ts +3 -0
  41. package/dist/src/toolbar/widgets/SelectionToolWidget.js +20 -7
  42. package/dist/src/toolbar/widgets/TextToolWidget.js +1 -2
  43. package/dist/src/tools/PanZoom.d.ts +1 -1
  44. package/dist/src/tools/PanZoom.js +4 -1
  45. package/dist/src/tools/PasteHandler.js +2 -22
  46. package/dist/src/tools/SelectionTool/SelectionTool.d.ts +3 -0
  47. package/dist/src/tools/SelectionTool/SelectionTool.js +66 -3
  48. package/dist/src/tools/TextTool.d.ts +4 -0
  49. package/dist/src/tools/TextTool.js +73 -15
  50. package/dist/src/tools/ToolController.js +1 -0
  51. package/dist/src/tools/localization.d.ts +1 -0
  52. package/dist/src/tools/localization.js +1 -0
  53. package/package.json +1 -1
  54. package/src/Editor.toSVG.test.ts +27 -0
  55. package/src/Editor.ts +15 -9
  56. package/src/EditorImage.ts +9 -0
  57. package/src/SVGLoader.test.ts +57 -0
  58. package/src/SVGLoader.ts +9 -10
  59. package/src/components/AbstractComponent.ts +5 -0
  60. package/src/components/SVGGlobalAttributesObject.ts +4 -0
  61. package/src/components/Stroke.ts +1 -0
  62. package/src/components/Text.test.ts +3 -18
  63. package/src/components/Text.ts +78 -25
  64. package/src/components/UnknownSVGObject.ts +4 -0
  65. package/src/components/builders/FreehandLineBuilder.ts +162 -34
  66. package/src/components/lib.ts +3 -3
  67. package/src/rendering/renderers/CanvasRenderer.ts +2 -2
  68. package/src/rendering/renderers/SVGRenderer.ts +50 -24
  69. package/src/testing/beforeEachFile.ts +6 -1
  70. package/src/toolbar/HTMLToolbar.ts +2 -3
  71. package/src/toolbar/IconProvider.ts +480 -0
  72. package/src/toolbar/lib.ts +1 -1
  73. package/src/toolbar/localization.ts +0 -2
  74. package/src/toolbar/makeColorInput.ts +1 -2
  75. package/src/toolbar/widgets/BaseWidget.ts +1 -2
  76. package/src/toolbar/widgets/EraserToolWidget.ts +1 -2
  77. package/src/toolbar/widgets/HandToolWidget.ts +42 -20
  78. package/src/toolbar/widgets/PenToolWidget.ts +11 -8
  79. package/src/toolbar/widgets/SelectionToolWidget.ts +24 -8
  80. package/src/toolbar/widgets/TextToolWidget.ts +1 -2
  81. package/src/tools/PanZoom.ts +4 -1
  82. package/src/tools/PasteHandler.ts +2 -24
  83. package/src/tools/SelectionTool/SelectionTool.css +1 -0
  84. package/src/tools/SelectionTool/SelectionTool.test.ts +40 -0
  85. package/src/tools/SelectionTool/SelectionTool.ts +73 -4
  86. package/src/tools/TextTool.ts +82 -17
  87. package/src/tools/ToolController.ts +1 -0
  88. package/src/tools/localization.ts +4 -0
  89. package/typedoc.json +5 -1
  90. package/dist/src/toolbar/icons.d.ts +0 -20
  91. package/dist/src/toolbar/icons.js +0 -385
  92. package/src/toolbar/icons.ts +0 -443
@@ -1,385 +0,0 @@
1
- import Color4 from '../Color4';
2
- import EventDispatcher from '../EventDispatcher';
3
- import { Vec2 } from '../math/Vec2';
4
- import SVGRenderer from '../rendering/renderers/SVGRenderer';
5
- import Viewport from '../Viewport';
6
- const svgNamespace = 'http://www.w3.org/2000/svg';
7
- const iconColorFill = `
8
- style='fill: var(--icon-color);'
9
- `;
10
- const iconColorStrokeFill = `
11
- style='fill: var(--icon-color); stroke: var(--icon-color);'
12
- `;
13
- const checkerboardPatternDef = `
14
- <pattern
15
- id='checkerboard'
16
- viewBox='0,0,10,10'
17
- width='20%'
18
- height='20%'
19
- patternUnits='userSpaceOnUse'
20
- >
21
- <rect x=0 y=0 width=10 height=10 fill='white'/>
22
- <rect x=0 y=0 width=5 height=5 fill='gray'/>
23
- <rect x=5 y=5 width=5 height=5 fill='gray'/>
24
- </pattern>
25
- `;
26
- const checkerboardPatternRef = 'url(#checkerboard)';
27
- export const makeUndoIcon = () => {
28
- return makeRedoIcon(true);
29
- };
30
- export const makeRedoIcon = (mirror = false) => {
31
- const icon = document.createElementNS(svgNamespace, 'svg');
32
- icon.innerHTML = `
33
- <style>
34
- .toolbar-svg-undo-redo-icon {
35
- stroke: var(--icon-color);
36
- stroke-width: 12;
37
- stroke-linejoin: round;
38
- stroke-linecap: round;
39
- fill: none;
40
-
41
- transform-origin: center;
42
- }
43
- </style>
44
- <path
45
- d='M20,20 A15,15 0 0 1 70,80 L80,90 L60,70 L65,90 L87,90 L65,80'
46
- class='toolbar-svg-undo-redo-icon'
47
- style='${mirror ? 'transform: scale(-1, 1);' : ''}'/>
48
- `;
49
- icon.setAttribute('viewBox', '0 0 100 100');
50
- return icon;
51
- };
52
- export const makeDropdownIcon = () => {
53
- const icon = document.createElementNS(svgNamespace, 'svg');
54
- icon.innerHTML = `
55
- <g>
56
- <path
57
- d='M5,10 L50,90 L95,10 Z'
58
- ${iconColorFill}
59
- />
60
- </g>
61
- `;
62
- icon.setAttribute('viewBox', '0 0 100 100');
63
- return icon;
64
- };
65
- export const makeEraserIcon = () => {
66
- const icon = document.createElementNS(svgNamespace, 'svg');
67
- // Draw an eraser-like shape
68
- icon.innerHTML = `
69
- <g>
70
- <rect x=10 y=50 width=80 height=30 rx=10 fill='pink' />
71
- <rect
72
- x=10 y=10 width=80 height=50
73
- ${iconColorFill}
74
- />
75
- </g>
76
- `;
77
- icon.setAttribute('viewBox', '0 0 100 100');
78
- return icon;
79
- };
80
- export const makeSelectionIcon = () => {
81
- const icon = document.createElementNS(svgNamespace, 'svg');
82
- // Draw a cursor-like shape
83
- icon.innerHTML = `
84
- <g>
85
- <rect x=10 y=10 width=70 height=70 fill='pink' stroke='black'/>
86
- <rect x=75 y=75 width=10 height=10 fill='white' stroke='black'/>
87
- </g>
88
- `;
89
- icon.setAttribute('viewBox', '0 0 100 100');
90
- return icon;
91
- };
92
- const pathIcon = (pathData, fill = 'var(--icon-color)', strokeColor = 'none', strokeWidth = '0px') => {
93
- const icon = document.createElementNS(svgNamespace, 'svg');
94
- const path = document.createElementNS(svgNamespace, 'path');
95
- path.setAttribute('d', pathData);
96
- path.style.fill = fill;
97
- path.style.stroke = strokeColor;
98
- path.style.strokeWidth = strokeWidth;
99
- icon.appendChild(path);
100
- icon.setAttribute('viewBox', '0 0 100 100');
101
- return icon;
102
- };
103
- export const makeHandToolIcon = () => {
104
- const fill = 'none';
105
- const strokeColor = 'var(--icon-color)';
106
- const strokeWidth = '3';
107
- // Draw a cursor-like shape (like some of the other icons, made with Inkscape)
108
- return pathIcon(`
109
- m 10,60
110
- 5,30
111
- H 90
112
- V 30
113
- C 90,20 75,20 75,30
114
- V 60
115
- 20
116
- C 75,10 60,10 60,20
117
- V 60
118
- 15
119
- C 60,5 45,5 45,15
120
- V 60
121
- 25
122
- C 45,15 30,15 30,25
123
- V 60
124
- 75
125
- L 25,60
126
- C 20,45 10,50 10,60
127
- Z
128
- `, fill, strokeColor, strokeWidth);
129
- };
130
- export const makeTouchPanningIcon = () => {
131
- const fill = 'none';
132
- const strokeColor = 'var(--icon-color)';
133
- const strokeWidth = '3';
134
- return pathIcon(`
135
- M 5,5.5
136
- V 17.2
137
- L 16.25,5.46
138
- Z
139
-
140
- m 33.75,0
141
- L 50,17
142
- V 5.5
143
- Z
144
-
145
- M 5,40.7
146
- v 11.7
147
- h 11.25
148
- z
149
-
150
- M 26,19
151
- C 19.8,19.4 17.65,30.4 21.9,34.8
152
- L 50,70
153
- H 27.5
154
- c -11.25,0 -11.25,17.6 0,17.6
155
- H 61.25
156
- C 94.9,87.8 95,87.6 95,40.7 78.125,23 67,29 55.6,46.5
157
- L 33.1,23
158
- C 30.3125,20.128192 27.9,19 25.830078,19.119756
159
- Z
160
- `, fill, strokeColor, strokeWidth);
161
- };
162
- export const makeAllDevicePanningIcon = () => {
163
- const fill = 'none';
164
- const strokeColor = 'var(--icon-color)';
165
- const strokeWidth = '3';
166
- return pathIcon(`
167
- M 5 5
168
- L 5 17.5
169
- 17.5 5
170
- 5 5
171
- z
172
-
173
- M 42.5 5
174
- L 55 17.5
175
- 55 5
176
- 42.5 5
177
- z
178
-
179
- M 70 10
180
- L 70 21
181
- 61 15
182
- 55.5 23
183
- 66 30
184
- 56 37
185
- 61 45
186
- 70 39
187
- 70 50
188
- 80 50
189
- 80 39
190
- 89 45
191
- 95 36
192
- 84 30
193
- 95 23
194
- 89 15
195
- 80 21
196
- 80 10
197
- 70 10
198
- z
199
-
200
- M 27.5 26.25
201
- L 27.5 91.25
202
- L 43.75 83.125
203
- L 52 99
204
- L 68 91
205
- L 60 75
206
- L 76.25 66.875
207
- L 27.5 26.25
208
- z
209
-
210
- M 5 42.5
211
- L 5 55
212
- L 17.5 55
213
- L 5 42.5
214
- z
215
- `, fill, strokeColor, strokeWidth);
216
- };
217
- export const makeZoomIcon = () => {
218
- const icon = document.createElementNS(svgNamespace, 'svg');
219
- icon.setAttribute('viewBox', '0 0 100 100');
220
- const addTextNode = (text, x, y) => {
221
- const textNode = document.createElementNS(svgNamespace, 'text');
222
- textNode.appendChild(document.createTextNode(text));
223
- textNode.setAttribute('x', x.toString());
224
- textNode.setAttribute('y', y.toString());
225
- textNode.style.textAlign = 'center';
226
- textNode.style.textAnchor = 'middle';
227
- textNode.style.fontSize = '55px';
228
- textNode.style.fill = 'var(--icon-color)';
229
- textNode.style.fontFamily = 'monospace';
230
- icon.appendChild(textNode);
231
- };
232
- addTextNode('+', 40, 45);
233
- addTextNode('-', 70, 75);
234
- return icon;
235
- };
236
- export const makeTextIcon = (textStyle) => {
237
- var _a, _b;
238
- const icon = document.createElementNS(svgNamespace, 'svg');
239
- icon.setAttribute('viewBox', '0 0 100 100');
240
- const textNode = document.createElementNS(svgNamespace, 'text');
241
- textNode.appendChild(document.createTextNode('T'));
242
- textNode.style.fontFamily = textStyle.fontFamily;
243
- textNode.style.fontWeight = (_a = textStyle.fontWeight) !== null && _a !== void 0 ? _a : '';
244
- textNode.style.fontVariant = (_b = textStyle.fontVariant) !== null && _b !== void 0 ? _b : '';
245
- textNode.style.fill = textStyle.renderingStyle.fill.toHexString();
246
- textNode.style.textAnchor = 'middle';
247
- textNode.setAttribute('x', '50');
248
- textNode.setAttribute('y', '75');
249
- textNode.style.fontSize = '65px';
250
- textNode.style.filter = 'drop-shadow(0px 0px 10px var(--primary-shadow-color))';
251
- icon.appendChild(textNode);
252
- return icon;
253
- };
254
- export const makePenIcon = (tipThickness, color) => {
255
- if (color instanceof Color4) {
256
- color = color.toHexString();
257
- }
258
- const icon = document.createElementNS(svgNamespace, 'svg');
259
- icon.setAttribute('viewBox', '0 0 100 100');
260
- const halfThickness = tipThickness / 2;
261
- // Draw a pen-like shape
262
- const primaryStrokeTipPath = `M14,63 L${50 - halfThickness},95 L${50 + halfThickness},90 L88,60 Z`;
263
- const backgroundStrokeTipPath = `M14,63 L${50 - halfThickness},85 L${50 + halfThickness},83 L88,60 Z`;
264
- icon.innerHTML = `
265
- <defs>
266
- ${checkerboardPatternDef}
267
- </defs>
268
- <g>
269
- <!-- Pen grip -->
270
- <path
271
- d='M10,10 L90,10 L90,60 L${50 + halfThickness},80 L${50 - halfThickness},80 L10,60 Z'
272
- ${iconColorStrokeFill}
273
- />
274
- </g>
275
- <g>
276
- <!-- Checkerboard background for slightly transparent pens -->
277
- <path d='${backgroundStrokeTipPath}' fill='${checkerboardPatternRef}'/>
278
-
279
- <!-- Actual pen tip -->
280
- <path
281
- d='${primaryStrokeTipPath}'
282
- fill='${color}'
283
- stroke='${color}'
284
- />
285
- </g>
286
- `;
287
- return icon;
288
- };
289
- export const makeIconFromFactory = (pen, factory) => {
290
- const toolThickness = pen.getThickness();
291
- const nowTime = (new Date()).getTime();
292
- const startPoint = {
293
- pos: Vec2.of(10, 10),
294
- width: toolThickness / 5,
295
- color: pen.getColor(),
296
- time: nowTime - 100,
297
- };
298
- const endPoint = {
299
- pos: Vec2.of(90, 90),
300
- width: toolThickness / 5,
301
- color: pen.getColor(),
302
- time: nowTime,
303
- };
304
- const viewport = new Viewport(new EventDispatcher());
305
- const builder = factory(startPoint, viewport);
306
- builder.addPoint(endPoint);
307
- const icon = document.createElementNS(svgNamespace, 'svg');
308
- icon.setAttribute('viewBox', '0 0 100 100');
309
- viewport.updateScreenSize(Vec2.of(100, 100));
310
- const renderer = new SVGRenderer(icon, viewport);
311
- builder.preview(renderer);
312
- return icon;
313
- };
314
- export const makePipetteIcon = (color) => {
315
- const icon = document.createElementNS(svgNamespace, 'svg');
316
- const pipette = document.createElementNS(svgNamespace, 'path');
317
- pipette.setAttribute('d', `
318
- M 47,6
319
- C 35,5 25,15 35,30
320
- c -9.2,1.3 -15,0 -15,3
321
- 0,2 5,5 15,7
322
- V 81
323
- L 40,90
324
- h 6
325
- L 40,80
326
- V 40
327
- h 15
328
- v 40
329
- l -6,10
330
- h 6
331
- l 5,-9.2
332
- V 40
333
- C 70,38 75,35 75,33
334
- 75,30 69.2,31.2 60,30
335
- 65,15 65,5 47,6
336
- Z
337
- `);
338
- pipette.style.fill = 'var(--icon-color)';
339
- if (color) {
340
- const defs = document.createElementNS(svgNamespace, 'defs');
341
- defs.innerHTML = checkerboardPatternDef;
342
- icon.appendChild(defs);
343
- const fluidBackground = document.createElementNS(svgNamespace, 'path');
344
- const fluid = document.createElementNS(svgNamespace, 'path');
345
- const fluidPathData = `
346
- m 40,50 c 5,5 10,0 15,-5 V 80 L 50,90 H 45 L 40,80 Z
347
- `;
348
- fluid.setAttribute('d', fluidPathData);
349
- fluidBackground.setAttribute('d', fluidPathData);
350
- fluid.style.fill = color.toHexString();
351
- fluidBackground.style.fill = checkerboardPatternRef;
352
- icon.appendChild(fluidBackground);
353
- icon.appendChild(fluid);
354
- }
355
- icon.appendChild(pipette);
356
- icon.setAttribute('viewBox', '0 0 100 100');
357
- return icon;
358
- };
359
- export const makeResizeViewportIcon = () => {
360
- return pathIcon(`
361
- M 75 5 75 10 90 10 90 25 95 25 95 5 75 5 z
362
- M 15 15 15 30 20 30 20 20 30 20 30 15 15 15 z
363
- M 84 15 82 17 81 16 81 20 85 20 84 19 86 17 84 15 z
364
- M 26 24 24 26 26 28 25 29 29 29 29 25 28 26 26 24 z
365
- M 25 71 26 72 24 74 26 76 28 74 29 75 29 71 25 71 z
366
- M 15 75 15 85 25 85 25 80 20 80 20 75 15 75 z
367
- M 90 75 90 90 75 90 75 95 95 95 95 75 90 75 z
368
- M 81 81 81 85 82 84 84 86 86 84 84 82 85 81 81 81 z
369
- `);
370
- };
371
- export const makeDuplicateSelectionIcon = () => {
372
- return pathIcon(`
373
- M 45,10 45,55 90,55 90,10 45,10 z
374
- M 10,25 10,90 70,90 70,60 40,60 40,25 10,25 z
375
- `);
376
- };
377
- export const makeDeleteSelectionIcon = () => {
378
- const strokeWidth = '5px';
379
- const strokeColor = 'var(--icon-color)';
380
- const fillColor = 'none';
381
- return pathIcon(`
382
- M 10,10 90,90
383
- M 10,90 90,10
384
- `, fillColor, strokeColor, strokeWidth);
385
- };