js-draw 0.1.11 → 0.1.12

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 (167) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/bundle.js +1 -1
  3. package/dist/src/Editor.d.ts +4 -2
  4. package/dist/src/Editor.js +30 -10
  5. package/dist/src/EditorImage.d.ts +1 -1
  6. package/dist/src/EditorImage.js +2 -2
  7. package/dist/src/Pointer.d.ts +1 -1
  8. package/dist/src/Pointer.js +1 -1
  9. package/dist/src/SVGLoader.d.ts +1 -1
  10. package/dist/src/SVGLoader.js +14 -6
  11. package/dist/src/Viewport.d.ts +8 -25
  12. package/dist/src/Viewport.js +15 -10
  13. package/dist/src/commands/Command.d.ts +2 -2
  14. package/dist/src/commands/Command.js +4 -4
  15. package/dist/src/commands/Duplicate.d.ts +1 -1
  16. package/dist/src/commands/Duplicate.js +1 -1
  17. package/dist/src/commands/Erase.d.ts +1 -1
  18. package/dist/src/commands/Erase.js +1 -1
  19. package/dist/src/commands/localization.d.ts +1 -1
  20. package/dist/src/components/AbstractComponent.d.ts +3 -3
  21. package/dist/src/components/AbstractComponent.js +2 -2
  22. package/dist/src/components/SVGGlobalAttributesObject.d.ts +3 -3
  23. package/dist/src/components/SVGGlobalAttributesObject.js +1 -1
  24. package/dist/src/components/Stroke.d.ts +4 -4
  25. package/dist/src/components/Stroke.js +2 -2
  26. package/dist/src/components/Text.d.ts +3 -3
  27. package/dist/src/components/Text.js +3 -3
  28. package/dist/src/components/UnknownSVGObject.d.ts +3 -3
  29. package/dist/src/components/UnknownSVGObject.js +1 -1
  30. package/dist/src/components/builders/ArrowBuilder.d.ts +1 -1
  31. package/dist/src/components/builders/ArrowBuilder.js +1 -1
  32. package/dist/src/components/builders/FreehandLineBuilder.d.ts +8 -3
  33. package/dist/src/components/builders/FreehandLineBuilder.js +142 -71
  34. package/dist/src/components/builders/LineBuilder.d.ts +1 -1
  35. package/dist/src/components/builders/LineBuilder.js +1 -1
  36. package/dist/src/components/builders/RectangleBuilder.d.ts +1 -1
  37. package/dist/src/components/builders/RectangleBuilder.js +3 -3
  38. package/dist/src/components/builders/types.d.ts +1 -1
  39. package/dist/src/localization.d.ts +1 -0
  40. package/dist/src/localization.js +5 -1
  41. package/dist/src/localizations/es.js +1 -1
  42. package/dist/src/{geometry → math}/LineSegment2.d.ts +0 -0
  43. package/dist/src/{geometry → math}/LineSegment2.js +0 -0
  44. package/dist/src/{geometry → math}/Mat33.d.ts +0 -0
  45. package/dist/src/{geometry → math}/Mat33.js +0 -0
  46. package/dist/src/{geometry → math}/Path.d.ts +2 -1
  47. package/dist/src/{geometry → math}/Path.js +58 -51
  48. package/dist/src/{geometry → math}/Rect2.d.ts +0 -0
  49. package/dist/src/{geometry → math}/Rect2.js +0 -0
  50. package/dist/src/{geometry → math}/Vec2.d.ts +0 -0
  51. package/dist/src/{geometry → math}/Vec2.js +0 -0
  52. package/dist/src/{geometry → math}/Vec3.d.ts +1 -1
  53. package/dist/src/{geometry → math}/Vec3.js +1 -1
  54. package/dist/src/math/rounding.d.ts +3 -0
  55. package/dist/src/math/rounding.js +120 -0
  56. package/dist/src/rendering/Display.d.ts +3 -1
  57. package/dist/src/rendering/Display.js +16 -10
  58. package/dist/src/rendering/caching/CacheRecord.d.ts +2 -2
  59. package/dist/src/rendering/caching/CacheRecord.js +1 -1
  60. package/dist/src/rendering/caching/CacheRecordManager.d.ts +1 -1
  61. package/dist/src/rendering/caching/RenderingCache.js +1 -1
  62. package/dist/src/rendering/caching/RenderingCacheNode.d.ts +2 -1
  63. package/dist/src/rendering/caching/RenderingCacheNode.js +18 -7
  64. package/dist/src/rendering/caching/testUtils.js +1 -1
  65. package/dist/src/rendering/caching/types.d.ts +1 -1
  66. package/dist/src/rendering/localization.d.ts +2 -0
  67. package/dist/src/rendering/localization.js +2 -0
  68. package/dist/src/rendering/renderers/AbstractRenderer.d.ts +4 -4
  69. package/dist/src/rendering/renderers/AbstractRenderer.js +2 -2
  70. package/dist/src/rendering/renderers/CanvasRenderer.d.ts +4 -4
  71. package/dist/src/rendering/renderers/CanvasRenderer.js +1 -1
  72. package/dist/src/rendering/renderers/DummyRenderer.d.ts +4 -4
  73. package/dist/src/rendering/renderers/DummyRenderer.js +1 -1
  74. package/dist/src/rendering/renderers/SVGRenderer.d.ts +3 -3
  75. package/dist/src/rendering/renderers/SVGRenderer.js +8 -2
  76. package/dist/src/rendering/renderers/TextOnlyRenderer.d.ts +5 -3
  77. package/dist/src/rendering/renderers/TextOnlyRenderer.js +13 -3
  78. package/dist/src/toolbar/icons.d.ts +3 -0
  79. package/dist/src/toolbar/icons.js +142 -132
  80. package/dist/src/toolbar/localization.d.ts +2 -1
  81. package/dist/src/toolbar/localization.js +2 -1
  82. package/dist/src/toolbar/makeColorInput.js +2 -1
  83. package/dist/src/toolbar/widgets/ActionButtonWidget.d.ts +13 -0
  84. package/dist/src/toolbar/widgets/ActionButtonWidget.js +21 -0
  85. package/dist/src/toolbar/widgets/BaseWidget.js +2 -0
  86. package/dist/src/toolbar/widgets/HandToolWidget.js +3 -3
  87. package/dist/src/toolbar/widgets/SelectionWidget.d.ts +0 -1
  88. package/dist/src/toolbar/widgets/SelectionWidget.js +23 -30
  89. package/dist/src/tools/Eraser.js +1 -1
  90. package/dist/src/tools/PanZoom.d.ts +1 -1
  91. package/dist/src/tools/PanZoom.js +24 -14
  92. package/dist/src/tools/SelectionTool.d.ts +3 -3
  93. package/dist/src/tools/SelectionTool.js +6 -6
  94. package/dist/src/tools/TextTool.js +1 -1
  95. package/dist/src/types.d.ts +4 -4
  96. package/package.json +1 -1
  97. package/src/Editor.ts +34 -12
  98. package/src/EditorImage.test.ts +2 -4
  99. package/src/EditorImage.ts +2 -2
  100. package/src/Pointer.ts +1 -1
  101. package/src/SVGLoader.ts +14 -6
  102. package/src/Viewport.ts +19 -17
  103. package/src/commands/Command.ts +5 -5
  104. package/src/commands/Duplicate.ts +1 -1
  105. package/src/commands/Erase.ts +1 -1
  106. package/src/commands/localization.ts +1 -1
  107. package/src/components/AbstractComponent.ts +4 -4
  108. package/src/components/SVGGlobalAttributesObject.ts +3 -3
  109. package/src/components/Stroke.test.ts +3 -5
  110. package/src/components/Stroke.ts +4 -4
  111. package/src/components/Text.test.ts +2 -2
  112. package/src/components/Text.ts +3 -3
  113. package/src/components/UnknownSVGObject.ts +3 -3
  114. package/src/components/builders/ArrowBuilder.ts +2 -2
  115. package/src/components/builders/FreehandLineBuilder.ts +190 -80
  116. package/src/components/builders/LineBuilder.ts +2 -2
  117. package/src/components/builders/RectangleBuilder.ts +3 -3
  118. package/src/components/builders/types.ts +1 -1
  119. package/src/localization.ts +6 -0
  120. package/src/localizations/es.ts +2 -1
  121. package/src/{geometry → math}/LineSegment2.test.ts +0 -0
  122. package/src/{geometry → math}/LineSegment2.ts +0 -0
  123. package/src/{geometry → math}/Mat33.test.ts +0 -0
  124. package/src/{geometry → math}/Mat33.ts +0 -0
  125. package/src/{geometry → math}/Path.fromString.test.ts +0 -0
  126. package/src/{geometry → math}/Path.test.ts +0 -0
  127. package/src/{geometry → math}/Path.toString.test.ts +11 -2
  128. package/src/{geometry → math}/Path.ts +60 -57
  129. package/src/{geometry → math}/Rect2.test.ts +0 -0
  130. package/src/{geometry → math}/Rect2.ts +0 -0
  131. package/src/{geometry → math}/Vec2.test.ts +0 -0
  132. package/src/{geometry → math}/Vec2.ts +0 -0
  133. package/src/{geometry → math}/Vec3.test.ts +0 -0
  134. package/src/{geometry → math}/Vec3.ts +2 -2
  135. package/src/math/rounding.test.ts +40 -0
  136. package/src/math/rounding.ts +145 -0
  137. package/src/rendering/Display.ts +18 -10
  138. package/src/rendering/caching/CacheRecord.test.ts +2 -2
  139. package/src/rendering/caching/CacheRecord.ts +2 -2
  140. package/src/rendering/caching/CacheRecordManager.ts +1 -1
  141. package/src/rendering/caching/RenderingCache.test.ts +3 -3
  142. package/src/rendering/caching/RenderingCache.ts +1 -1
  143. package/src/rendering/caching/RenderingCacheNode.ts +23 -7
  144. package/src/rendering/caching/testUtils.ts +1 -1
  145. package/src/rendering/caching/types.ts +1 -1
  146. package/src/rendering/localization.ts +4 -0
  147. package/src/rendering/renderers/AbstractRenderer.ts +4 -4
  148. package/src/rendering/renderers/CanvasRenderer.ts +4 -4
  149. package/src/rendering/renderers/DummyRenderer.test.ts +2 -2
  150. package/src/rendering/renderers/DummyRenderer.ts +4 -4
  151. package/src/rendering/renderers/SVGRenderer.ts +10 -4
  152. package/src/rendering/renderers/TextOnlyRenderer.ts +17 -6
  153. package/src/toolbar/icons.ts +157 -137
  154. package/src/toolbar/localization.ts +4 -2
  155. package/src/toolbar/makeColorInput.ts +2 -1
  156. package/src/toolbar/toolbar.css +1 -1
  157. package/src/toolbar/widgets/ActionButtonWidget.ts +31 -0
  158. package/src/toolbar/widgets/BaseWidget.ts +2 -0
  159. package/src/toolbar/widgets/HandToolWidget.ts +3 -3
  160. package/src/toolbar/widgets/SelectionWidget.ts +46 -41
  161. package/src/tools/Eraser.ts +2 -2
  162. package/src/tools/PanZoom.ts +28 -16
  163. package/src/tools/SelectionTool.test.ts +2 -4
  164. package/src/tools/SelectionTool.ts +6 -6
  165. package/src/tools/TextTool.ts +2 -2
  166. package/src/tools/UndoRedoShortcut.test.ts +1 -1
  167. package/src/types.ts +4 -4
@@ -2,7 +2,7 @@ import Color4 from '../Color4';
2
2
  import { ComponentBuilderFactory } from '../components/builders/types';
3
3
  import { TextStyle } from '../components/Text';
4
4
  import EventDispatcher from '../EventDispatcher';
5
- import { Vec2 } from '../geometry/Vec2';
5
+ import { Vec2 } from '../math/Vec2';
6
6
  import SVGRenderer from '../rendering/renderers/SVGRenderer';
7
7
  import Pen from '../tools/Pen';
8
8
  import { StrokeDataPoint } from '../types';
@@ -103,152 +103,141 @@ export const makeSelectionIcon = () => {
103
103
  return icon;
104
104
  };
105
105
 
106
- export const makeHandToolIcon = () => {
106
+ const pathIcon = (
107
+ pathData: string,
108
+ fill: string = 'var(--icon-color)',
109
+ strokeColor: string = 'none',
110
+ strokeWidth: string = '0px',
111
+ ) => {
107
112
  const icon = document.createElementNS(svgNamespace, 'svg');
108
-
109
- // Draw a cursor-like shape (like some of the other icons, made with Inkscape)
110
- icon.innerHTML = `
111
- <g>
112
- <path d='
113
- m 10,60
114
- 5,30
115
- H 90
116
- V 30
117
- C 90,20 75,20 75,30
118
- V 60
119
- 20
120
- C 75,10 60,10 60,20
121
- V 60
122
- 15
123
- C 60,5 45,5 45,15
124
- V 60
125
- 25
126
- C 45,15 30,15 30,25
127
- V 60
128
- 75
129
- L 25,60
130
- C 20,45 10,50 10,60
131
- Z'
132
-
133
- fill='none'
134
- style='
135
- stroke: var(--icon-color);
136
- stroke-width: 2;
137
- '
138
- />
139
- </g>
140
- `;
113
+ const path = document.createElementNS(svgNamespace, 'path');
114
+ path.setAttribute('d', pathData);
115
+ path.style.fill = fill;
116
+ path.style.stroke = strokeColor;
117
+ path.style.strokeWidth = strokeWidth;
118
+ icon.appendChild(path);
141
119
  icon.setAttribute('viewBox', '0 0 100 100');
120
+
142
121
  return icon;
143
122
  };
144
123
 
124
+ export const makeHandToolIcon = () => {
125
+ const fill = 'none';
126
+ const strokeColor = 'var(--icon-color)';
127
+ const strokeWidth = '3';
128
+
129
+ // Draw a cursor-like shape (like some of the other icons, made with Inkscape)
130
+ return pathIcon(`
131
+ m 10,60
132
+ 5,30
133
+ H 90
134
+ V 30
135
+ C 90,20 75,20 75,30
136
+ V 60
137
+ 20
138
+ C 75,10 60,10 60,20
139
+ V 60
140
+ 15
141
+ C 60,5 45,5 45,15
142
+ V 60
143
+ 25
144
+ C 45,15 30,15 30,25
145
+ V 60
146
+ 75
147
+ L 25,60
148
+ C 20,45 10,50 10,60
149
+ Z
150
+ `, fill, strokeColor, strokeWidth);
151
+ };
152
+
145
153
  export const makeTouchPanningIcon = () => {
146
- const icon = document.createElementNS(svgNamespace, 'svg');
147
- icon.innerHTML = `
148
- <path
149
- d='
150
- M 5,5.5
151
- V 17.2
152
- L 16.25,5.46
153
- Z
154
-
155
- m 33.75,0
156
- L 50,17
157
- V 5.5
158
- Z
159
-
160
- M 5,40.7
161
- v 11.7
162
- h 11.25
163
- z
164
-
165
- M 26,19
166
- C 19.8,19.4 17.65,30.4 21.9,34.8
167
- L 50,70
168
- H 27.5
169
- c -11.25,0 -11.25,17.6 0,17.6
170
- H 61.25
171
- C 94.9,87.8 95,87.6 95,40.7 78.125,23 67,29 55.6,46.5
172
- L 33.1,23
173
- C 30.3125,20.128192 27.9,19 25.830078,19.119756
174
- Z
175
- '
176
- fill='none'
177
- style='
178
- stroke: var(--icon-color);
179
- stroke-width: 2;
180
- '
181
- />
182
- `;
154
+ const fill = 'none';
155
+ const strokeColor = 'var(--icon-color)';
156
+ const strokeWidth = '3';
157
+
158
+ return pathIcon(`
159
+ M 5,5.5
160
+ V 17.2
161
+ L 16.25,5.46
162
+ Z
183
163
 
184
- icon.setAttribute('viewBox', '0 0 100 100');
185
- return icon;
164
+ m 33.75,0
165
+ L 50,17
166
+ V 5.5
167
+ Z
168
+
169
+ M 5,40.7
170
+ v 11.7
171
+ h 11.25
172
+ z
173
+
174
+ M 26,19
175
+ C 19.8,19.4 17.65,30.4 21.9,34.8
176
+ L 50,70
177
+ H 27.5
178
+ c -11.25,0 -11.25,17.6 0,17.6
179
+ H 61.25
180
+ C 94.9,87.8 95,87.6 95,40.7 78.125,23 67,29 55.6,46.5
181
+ L 33.1,23
182
+ C 30.3125,20.128192 27.9,19 25.830078,19.119756
183
+ Z
184
+ `, fill, strokeColor, strokeWidth);
186
185
  };
187
186
 
188
187
  export const makeAllDevicePanningIcon = () => {
189
- const icon = document.createElementNS(svgNamespace, 'svg');
190
- icon.innerHTML = `
191
- <path
192
- d='
193
- M 5 5
194
- L 5 17.5
195
- 17.5 5
196
- 5 5
197
- z
198
-
199
- M 42.5 5
200
- L 55 17.5
201
- 55 5
202
- 42.5 5
203
- z
204
-
205
- M 70 10
206
- L 70 21
207
- 61 15
208
- 55.5 23
209
- 66 30
210
- 56 37
211
- 61 45
212
- 70 39
213
- 70 50
214
- 80 50
215
- 80 39
216
- 89 45
217
- 95 36
218
- 84 30
219
- 95 23
220
- 89 15
221
- 80 21
222
- 80 10
223
- 70 10
224
- z
225
-
226
- M 27.5 26.25
227
- L 27.5 91.25
228
- L 43.75 83.125
229
- L 52 99
230
- L 68 91
231
- L 60 75
232
- L 76.25 66.875
233
- L 27.5 26.25
234
- z
235
-
236
- M 5 42.5
237
- L 5 55
238
- L 17.5 55
239
- L 5 42.5
240
- z
241
- '
242
- fill='none'
243
- style='
244
- stroke: var(--icon-color);
245
- stroke-width: 2;
246
- '
247
- />
248
- `;
249
-
250
- icon.setAttribute('viewBox', '0 0 100 100');
251
- return icon;
188
+ const fill = 'none';
189
+ const strokeColor = 'var(--icon-color)';
190
+ const strokeWidth = '3';
191
+ return pathIcon(`
192
+ M 5 5
193
+ L 5 17.5
194
+ 17.5 5
195
+ 5 5
196
+ z
197
+
198
+ M 42.5 5
199
+ L 55 17.5
200
+ 55 5
201
+ 42.5 5
202
+ z
203
+
204
+ M 70 10
205
+ L 70 21
206
+ 61 15
207
+ 55.5 23
208
+ 66 30
209
+ 56 37
210
+ 61 45
211
+ 70 39
212
+ 70 50
213
+ 80 50
214
+ 80 39
215
+ 89 45
216
+ 95 36
217
+ 84 30
218
+ 95 23
219
+ 89 15
220
+ 80 21
221
+ 80 10
222
+ 70 10
223
+ z
224
+
225
+ M 27.5 26.25
226
+ L 27.5 91.25
227
+ L 43.75 83.125
228
+ L 52 99
229
+ L 68 91
230
+ L 60 75
231
+ L 76.25 66.875
232
+ L 27.5 26.25
233
+ z
234
+
235
+ M 5 42.5
236
+ L 5 55
237
+ L 17.5 55
238
+ L 5 42.5
239
+ z
240
+ `, fill, strokeColor, strokeWidth);
252
241
  };
253
242
 
254
243
  export const makeZoomIcon = () => {
@@ -417,3 +406,34 @@ export const makePipetteIcon = (color?: Color4) => {
417
406
  icon.setAttribute('viewBox', '0 0 100 100');
418
407
  return icon;
419
408
  };
409
+
410
+ export const makeResizeViewportIcon = () => {
411
+ return pathIcon(`
412
+ M 75 5 75 10 90 10 90 25 95 25 95 5 75 5 z
413
+ M 15 15 15 30 20 30 20 20 30 20 30 15 15 15 z
414
+ M 84 15 82 17 81 16 81 20 85 20 84 19 86 17 84 15 z
415
+ M 26 24 24 26 26 28 25 29 29 29 29 25 28 26 26 24 z
416
+ M 25 71 26 72 24 74 26 76 28 74 29 75 29 71 25 71 z
417
+ M 15 75 15 85 25 85 25 80 20 80 20 75 15 75 z
418
+ M 90 75 90 90 75 90 75 95 95 95 95 75 90 75 z
419
+ M 81 81 81 85 82 84 84 86 86 84 84 82 85 81 81 81 z
420
+ `);
421
+ };
422
+
423
+ export const makeDuplicateSelectionIcon = () => {
424
+ return pathIcon(`
425
+ M 45,10 45,55 90,55 90,10 45,10 z
426
+ M 10,25 10,90 70,90 70,60 40,60 40,25 10,25 z
427
+ `);
428
+ };
429
+
430
+ export const makeDeleteSelectionIcon = () => {
431
+ const strokeWidth = '5px';
432
+ const strokeColor = 'var(--icon-color)';
433
+ const fillColor = 'none';
434
+
435
+ return pathIcon(`
436
+ M 10,10 90,90
437
+ M 10,90 90,10
438
+ `, fillColor, strokeColor, strokeWidth);
439
+ };
@@ -19,7 +19,8 @@ export interface ToolbarLocalization {
19
19
  resizeImageToSelection: string;
20
20
  deleteSelection: string;
21
21
  duplicateSelection: string;
22
- pickColorFronScreen: string;
22
+ pickColorFromScreen: string;
23
+ clickToPickColorAnnouncement: string;
23
24
  undo: string;
24
25
  redo: string;
25
26
  zoom: string;
@@ -48,7 +49,8 @@ export const defaultToolbarLocalization: ToolbarLocalization = {
48
49
  undo: 'Undo',
49
50
  redo: 'Redo',
50
51
  selectObjectType: 'Object type: ',
51
- pickColorFronScreen: 'Pick color from screen',
52
+ pickColorFromScreen: 'Pick color from screen',
53
+ clickToPickColorAnnouncement: 'Click on the screen to pick a color',
52
54
  selectionToolKeyboardShortcuts: 'Selection tool: Use arrow keys to move selected items, lowercase/uppercase ‘i’ and ‘o’ to resize.',
53
55
 
54
56
  touchPanning: 'Touchscreen panning',
@@ -69,7 +69,7 @@ export const makeColorInput = (editor: Editor, onColorChange: OnColorChangeListe
69
69
  const addPipetteTool = (editor: Editor, container: HTMLElement, onColorChange: OnColorChangeListener) => {
70
70
  const pipetteButton = document.createElement('button');
71
71
  pipetteButton.classList.add('pipetteButton');
72
- pipetteButton.title = editor.localization.pickColorFronScreen;
72
+ pipetteButton.title = editor.localization.pickColorFromScreen;
73
73
  pipetteButton.setAttribute('alt', pipetteButton.title);
74
74
 
75
75
  const updatePipetteIcon = (color?: Color4) => {
@@ -111,6 +111,7 @@ const addPipetteTool = (editor: Editor, container: HTMLElement, onColorChange: O
111
111
  );
112
112
  if (pipetteTool) {
113
113
  pipetteButton.classList.add('active');
114
+ editor.announceForAccessibility(editor.localization.clickToPickColorAnnouncement);
114
115
  }
115
116
  };
116
117
 
@@ -83,7 +83,7 @@
83
83
  min-height: 30px;
84
84
  }
85
85
 
86
- .toolbar-toolContainer.selected .toolbar-button {
86
+ .toolbar-toolContainer.selected > .toolbar-button {
87
87
  background-color: var(--secondary-background-color);
88
88
  color: var(--secondary-foreground-color);
89
89
  --icon-color: var(--secondary-foreground-color);
@@ -0,0 +1,31 @@
1
+ import Editor from '../../Editor';
2
+ import { ToolbarLocalization } from '../localization';
3
+ import BaseWidget from './BaseWidget';
4
+
5
+ export default class ActionButtonWidget extends BaseWidget {
6
+ public constructor(
7
+ editor: Editor, localizationTable: ToolbarLocalization,
8
+ protected makeIcon: ()=> Element,
9
+ protected title: string,
10
+
11
+ protected clickAction: ()=>void,
12
+ ) {
13
+ super(editor, localizationTable);
14
+ }
15
+
16
+ protected handleClick() {
17
+ this.clickAction();
18
+ }
19
+
20
+ protected getTitle(): string {
21
+ return this.title;
22
+ }
23
+
24
+ protected createIcon(): Element {
25
+ return this.makeIcon();
26
+ }
27
+
28
+ protected fillDropdown(_dropdown: HTMLElement): boolean {
29
+ return false;
30
+ }
31
+ }
@@ -137,8 +137,10 @@ export default abstract class BaseWidget {
137
137
  this.disabled = disabled;
138
138
  if (this.disabled) {
139
139
  this.button.classList.add('disabled');
140
+ this.button.setAttribute('aria-disabled', 'true');
140
141
  } else {
141
142
  this.button.classList.remove('disabled');
143
+ this.button.removeAttribute('aria-disabled');
142
144
  }
143
145
  }
144
146
 
@@ -1,5 +1,5 @@
1
1
  import Editor from '../../Editor';
2
- import Mat33 from '../../geometry/Mat33';
2
+ import Mat33 from '../../math/Mat33';
3
3
  import PanZoom, { PanZoomMode } from '../../tools/PanZoom';
4
4
  import { EditorEventType } from '../../types';
5
5
  import Viewport from '../../Viewport';
@@ -53,7 +53,7 @@ const makeZoomControl = (localizationTable: ToolbarLocalization, editor: Editor)
53
53
  const zoomBy = (factor: number) => {
54
54
  const screenCenter = editor.viewport.visibleRect.center;
55
55
  const transformUpdate = Mat33.scaling2D(factor, screenCenter);
56
- editor.dispatch(new Viewport.ViewportTransform(transformUpdate), false);
56
+ editor.dispatch(Viewport.transformBy(transformUpdate), false);
57
57
  };
58
58
 
59
59
  increaseButton.onclick = () => {
@@ -65,7 +65,7 @@ const makeZoomControl = (localizationTable: ToolbarLocalization, editor: Editor)
65
65
  };
66
66
 
67
67
  resetViewButton.onclick = () => {
68
- editor.dispatch(new Viewport.ViewportTransform(
68
+ editor.dispatch(Viewport.transformBy(
69
69
  editor.viewport.canvasToScreenTransform.inverse()
70
70
  ), true);
71
71
  };
@@ -1,8 +1,9 @@
1
1
  import Editor from '../../Editor';
2
2
  import SelectionTool from '../../tools/SelectionTool';
3
3
  import { EditorEventType } from '../../types';
4
- import { makeSelectionIcon } from '../icons';
4
+ import { makeDeleteSelectionIcon, makeDuplicateSelectionIcon, makeResizeViewportIcon, makeSelectionIcon } from '../icons';
5
5
  import { ToolbarLocalization } from '../localization';
6
+ import ActionButtonWidget from './ActionButtonWidget';
6
7
  import BaseToolWidget from './BaseToolWidget';
7
8
 
8
9
  export class SelectionWidget extends BaseToolWidget {
@@ -10,44 +11,46 @@ export class SelectionWidget extends BaseToolWidget {
10
11
  editor: Editor, private tool: SelectionTool, localization: ToolbarLocalization
11
12
  ) {
12
13
  super(editor, tool, localization);
13
- }
14
-
15
- protected getTitle(): string {
16
- return this.localizationTable.select;
17
- }
18
-
19
- protected createIcon(): Element {
20
- return makeSelectionIcon();
21
- }
22
14
 
23
- protected fillDropdown(dropdown: HTMLElement): boolean {
24
- const container = document.createElement('div');
25
- const resizeButton = document.createElement('button');
26
- const duplicateButton = document.createElement('button');
27
- const deleteButton = document.createElement('button');
28
-
29
- resizeButton.innerText = this.localizationTable.resizeImageToSelection;
30
- resizeButton.disabled = true;
31
- deleteButton.innerText = this.localizationTable.deleteSelection;
32
- deleteButton.disabled = true;
33
- duplicateButton.innerText = this.localizationTable.duplicateSelection;
34
- duplicateButton.disabled = true;
35
-
36
- resizeButton.onclick = () => {
37
- const selection = this.tool.getSelection();
38
- this.editor.dispatch(this.editor.setImportExportRect(selection!.region));
39
- };
15
+ const resizeButton = new ActionButtonWidget(
16
+ editor, localization,
17
+ makeResizeViewportIcon,
18
+ this.localizationTable.resizeImageToSelection,
19
+ () => {
20
+ const selection = this.tool.getSelection();
21
+ this.editor.dispatch(this.editor.setImportExportRect(selection!.region));
22
+ },
23
+ );
24
+ const deleteButton = new ActionButtonWidget(
25
+ editor, localization,
26
+ makeDeleteSelectionIcon,
27
+ this.localizationTable.deleteSelection,
28
+ () => {
29
+ const selection = this.tool.getSelection();
30
+ this.editor.dispatch(selection!.deleteSelectedObjects());
31
+ this.tool.clearSelection();
32
+ },
33
+ );
34
+ const duplicateButton = new ActionButtonWidget(
35
+ editor, localization,
36
+ makeDuplicateSelectionIcon,
37
+ this.localizationTable.duplicateSelection,
38
+ () => {
39
+ const selection = this.tool.getSelection();
40
+ this.editor.dispatch(selection!.duplicateSelectedObjects());
41
+ },
42
+ );
40
43
 
41
- deleteButton.onclick = () => {
42
- const selection = this.tool.getSelection();
43
- this.editor.dispatch(selection!.deleteSelectedObjects());
44
- this.tool.clearSelection();
45
- };
44
+ this.addSubWidget(resizeButton);
45
+ this.addSubWidget(deleteButton);
46
+ this.addSubWidget(duplicateButton);
46
47
 
47
- duplicateButton.onclick = () => {
48
- const selection = this.tool.getSelection();
49
- this.editor.dispatch(selection!.duplicateSelectedObjects());
48
+ const updateDisabled = (disabled: boolean) => {
49
+ resizeButton.setDisabled(disabled);
50
+ deleteButton.setDisabled(disabled);
51
+ duplicateButton.setDisabled(disabled);
50
52
  };
53
+ updateDisabled(true);
51
54
 
52
55
  // Enable/disable actions based on whether items are selected
53
56
  this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
@@ -59,14 +62,16 @@ export class SelectionWidget extends BaseToolWidget {
59
62
  const selection = this.tool.getSelection();
60
63
  const hasSelection = selection && selection.region.area > 0;
61
64
 
62
- resizeButton.disabled = !hasSelection;
63
- deleteButton.disabled = resizeButton.disabled;
64
- duplicateButton.disabled = resizeButton.disabled;
65
+ updateDisabled(!hasSelection);
65
66
  }
66
67
  });
68
+ }
67
69
 
68
- container.replaceChildren(resizeButton, duplicateButton, deleteButton);
69
- dropdown.appendChild(container);
70
- return true;
70
+ protected getTitle(): string {
71
+ return this.localizationTable.select;
72
+ }
73
+
74
+ protected createIcon(): Element {
75
+ return makeSelectionIcon();
71
76
  }
72
77
  }
@@ -1,8 +1,8 @@
1
1
  import { PointerEvt } from '../types';
2
2
  import BaseTool from './BaseTool';
3
3
  import Editor from '../Editor';
4
- import { Point2 } from '../geometry/Vec2';
5
- import LineSegment2 from '../geometry/LineSegment2';
4
+ import { Point2 } from '../math/Vec2';
5
+ import LineSegment2 from '../math/LineSegment2';
6
6
  import Erase from '../commands/Erase';
7
7
  import { ToolType } from './ToolController';
8
8
  import AbstractComponent from '../components/AbstractComponent';