js-draw 0.1.11 → 0.2.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 (220) hide show
  1. package/.eslintrc.js +1 -0
  2. package/.firebaserc +5 -0
  3. package/.github/workflows/firebase-hosting-merge.yml +25 -0
  4. package/.github/workflows/firebase-hosting-pull-request.yml +22 -0
  5. package/.github/workflows/github-pages.yml +52 -0
  6. package/CHANGELOG.md +13 -0
  7. package/README.md +11 -6
  8. package/dist/bundle.js +1 -1
  9. package/dist/src/Color4.d.ts +19 -0
  10. package/dist/src/Color4.js +24 -3
  11. package/dist/src/Editor.d.ts +133 -4
  12. package/dist/src/Editor.js +124 -27
  13. package/dist/src/EditorImage.d.ts +8 -3
  14. package/dist/src/EditorImage.js +42 -26
  15. package/dist/src/EventDispatcher.d.ts +18 -0
  16. package/dist/src/EventDispatcher.js +19 -4
  17. package/dist/src/Pointer.d.ts +1 -1
  18. package/dist/src/Pointer.js +4 -3
  19. package/dist/src/SVGLoader.d.ts +1 -1
  20. package/dist/src/SVGLoader.js +14 -6
  21. package/dist/src/UndoRedoHistory.js +15 -2
  22. package/dist/src/Viewport.d.ts +8 -25
  23. package/dist/src/Viewport.js +18 -10
  24. package/dist/src/bundle/bundled.d.ts +1 -2
  25. package/dist/src/bundle/bundled.js +1 -2
  26. package/dist/src/commands/Command.d.ts +2 -2
  27. package/dist/src/commands/Command.js +4 -4
  28. package/dist/src/commands/Duplicate.d.ts +2 -2
  29. package/dist/src/commands/Duplicate.js +4 -5
  30. package/dist/src/commands/Erase.d.ts +2 -2
  31. package/dist/src/commands/Erase.js +7 -6
  32. package/dist/src/commands/SerializableCommand.d.ts +4 -5
  33. package/dist/src/commands/SerializableCommand.js +12 -4
  34. package/dist/src/commands/invertCommand.d.ts +4 -0
  35. package/dist/src/commands/invertCommand.js +44 -0
  36. package/dist/src/commands/lib.d.ts +6 -0
  37. package/dist/src/commands/lib.js +6 -0
  38. package/dist/src/commands/localization.d.ts +2 -1
  39. package/dist/src/commands/localization.js +1 -0
  40. package/dist/src/components/AbstractComponent.d.ts +16 -11
  41. package/dist/src/components/AbstractComponent.js +28 -17
  42. package/dist/src/components/SVGGlobalAttributesObject.d.ts +4 -4
  43. package/dist/src/components/SVGGlobalAttributesObject.js +8 -2
  44. package/dist/src/components/Stroke.d.ts +16 -6
  45. package/dist/src/components/Stroke.js +12 -9
  46. package/dist/src/components/Text.d.ts +5 -5
  47. package/dist/src/components/Text.js +9 -9
  48. package/dist/src/components/UnknownSVGObject.d.ts +4 -4
  49. package/dist/src/components/UnknownSVGObject.js +7 -2
  50. package/dist/src/components/builders/ArrowBuilder.d.ts +1 -1
  51. package/dist/src/components/builders/ArrowBuilder.js +1 -1
  52. package/dist/src/components/builders/FreehandLineBuilder.d.ts +8 -3
  53. package/dist/src/components/builders/FreehandLineBuilder.js +142 -71
  54. package/dist/src/components/builders/LineBuilder.d.ts +1 -1
  55. package/dist/src/components/builders/LineBuilder.js +1 -1
  56. package/dist/src/components/builders/RectangleBuilder.d.ts +1 -1
  57. package/dist/src/components/builders/RectangleBuilder.js +3 -3
  58. package/dist/src/components/builders/types.d.ts +1 -1
  59. package/dist/src/components/lib.d.ts +4 -0
  60. package/dist/src/components/lib.js +4 -0
  61. package/dist/src/lib.d.ts +25 -0
  62. package/dist/src/lib.js +25 -0
  63. package/dist/src/localization.d.ts +1 -0
  64. package/dist/src/localization.js +5 -1
  65. package/dist/src/localizations/es.js +1 -1
  66. package/dist/src/{geometry → math}/LineSegment2.d.ts +0 -0
  67. package/dist/src/{geometry → math}/LineSegment2.js +0 -0
  68. package/dist/src/math/Mat33.d.ts +78 -0
  69. package/dist/src/{geometry → math}/Mat33.js +48 -20
  70. package/dist/src/{geometry → math}/Path.d.ts +2 -1
  71. package/dist/src/{geometry → math}/Path.js +59 -52
  72. package/dist/src/{geometry → math}/Rect2.d.ts +2 -2
  73. package/dist/src/{geometry → math}/Rect2.js +0 -0
  74. package/dist/src/{geometry → math}/Vec2.d.ts +0 -0
  75. package/dist/src/{geometry → math}/Vec2.js +0 -0
  76. package/dist/src/math/Vec3.d.ts +96 -0
  77. package/dist/src/{geometry → math}/Vec3.js +63 -15
  78. package/dist/src/math/lib.d.ts +7 -0
  79. package/dist/src/math/lib.js +7 -0
  80. package/dist/src/math/rounding.d.ts +3 -0
  81. package/dist/src/math/rounding.js +121 -0
  82. package/dist/src/rendering/Display.d.ts +47 -1
  83. package/dist/src/rendering/Display.js +60 -15
  84. package/dist/src/rendering/caching/CacheRecord.d.ts +3 -2
  85. package/dist/src/rendering/caching/CacheRecord.js +4 -1
  86. package/dist/src/rendering/caching/CacheRecordManager.d.ts +5 -4
  87. package/dist/src/rendering/caching/CacheRecordManager.js +16 -4
  88. package/dist/src/rendering/caching/RenderingCache.d.ts +2 -3
  89. package/dist/src/rendering/caching/RenderingCache.js +10 -11
  90. package/dist/src/rendering/caching/RenderingCacheNode.d.ts +2 -1
  91. package/dist/src/rendering/caching/RenderingCacheNode.js +18 -7
  92. package/dist/src/rendering/caching/testUtils.js +1 -1
  93. package/dist/src/rendering/caching/types.d.ts +2 -4
  94. package/dist/src/rendering/localization.d.ts +2 -0
  95. package/dist/src/rendering/localization.js +2 -0
  96. package/dist/src/rendering/renderers/AbstractRenderer.d.ts +4 -4
  97. package/dist/src/rendering/renderers/AbstractRenderer.js +2 -2
  98. package/dist/src/rendering/renderers/CanvasRenderer.d.ts +4 -4
  99. package/dist/src/rendering/renderers/CanvasRenderer.js +2 -2
  100. package/dist/src/rendering/renderers/DummyRenderer.d.ts +4 -4
  101. package/dist/src/rendering/renderers/DummyRenderer.js +1 -1
  102. package/dist/src/rendering/renderers/SVGRenderer.d.ts +3 -3
  103. package/dist/src/rendering/renderers/SVGRenderer.js +8 -2
  104. package/dist/src/rendering/renderers/TextOnlyRenderer.d.ts +5 -3
  105. package/dist/src/rendering/renderers/TextOnlyRenderer.js +13 -3
  106. package/dist/src/toolbar/HTMLToolbar.js +1 -0
  107. package/dist/src/toolbar/icons.d.ts +3 -0
  108. package/dist/src/toolbar/icons.js +142 -132
  109. package/dist/src/toolbar/localization.d.ts +2 -1
  110. package/dist/src/toolbar/localization.js +2 -1
  111. package/dist/src/toolbar/makeColorInput.js +3 -2
  112. package/dist/src/toolbar/widgets/ActionButtonWidget.d.ts +13 -0
  113. package/dist/src/toolbar/widgets/ActionButtonWidget.js +21 -0
  114. package/dist/src/toolbar/widgets/BaseWidget.js +2 -0
  115. package/dist/src/toolbar/widgets/HandToolWidget.js +3 -3
  116. package/dist/src/toolbar/widgets/PenWidget.js +1 -0
  117. package/dist/src/toolbar/widgets/SelectionWidget.d.ts +0 -1
  118. package/dist/src/toolbar/widgets/SelectionWidget.js +23 -30
  119. package/dist/src/tools/Eraser.js +1 -1
  120. package/dist/src/tools/PanZoom.d.ts +1 -1
  121. package/dist/src/tools/PanZoom.js +24 -14
  122. package/dist/src/tools/Pen.d.ts +1 -2
  123. package/dist/src/tools/Pen.js +8 -1
  124. package/dist/src/tools/PipetteTool.js +1 -0
  125. package/dist/src/tools/SelectionTool.d.ts +3 -3
  126. package/dist/src/tools/SelectionTool.js +51 -28
  127. package/dist/src/tools/TextTool.js +1 -1
  128. package/dist/src/types.d.ts +21 -10
  129. package/dist/src/types.js +7 -5
  130. package/firebase.json +16 -0
  131. package/package.json +118 -101
  132. package/src/Color4.ts +23 -2
  133. package/src/Editor.ts +181 -37
  134. package/src/EditorImage.test.ts +2 -4
  135. package/src/EditorImage.ts +46 -28
  136. package/src/EventDispatcher.ts +21 -6
  137. package/src/Pointer.ts +4 -3
  138. package/src/SVGLoader.ts +14 -6
  139. package/src/UndoRedoHistory.ts +18 -2
  140. package/src/Viewport.ts +23 -18
  141. package/src/bundle/bundled.ts +1 -2
  142. package/src/commands/Command.ts +5 -5
  143. package/src/commands/Duplicate.ts +4 -5
  144. package/src/commands/Erase.ts +7 -6
  145. package/src/commands/SerializableCommand.ts +17 -9
  146. package/src/commands/invertCommand.ts +51 -0
  147. package/src/commands/lib.ts +14 -0
  148. package/src/commands/localization.ts +3 -1
  149. package/src/components/AbstractComponent.ts +35 -24
  150. package/src/components/SVGGlobalAttributesObject.ts +11 -4
  151. package/src/components/Stroke.test.ts +4 -6
  152. package/src/components/Stroke.ts +15 -11
  153. package/src/components/Text.test.ts +2 -2
  154. package/src/components/Text.ts +9 -10
  155. package/src/components/UnknownSVGObject.ts +10 -4
  156. package/src/components/builders/ArrowBuilder.ts +2 -2
  157. package/src/components/builders/FreehandLineBuilder.ts +190 -80
  158. package/src/components/builders/LineBuilder.ts +2 -2
  159. package/src/components/builders/RectangleBuilder.ts +3 -3
  160. package/src/components/builders/types.ts +1 -1
  161. package/src/components/lib.ts +9 -0
  162. package/src/lib.ts +28 -0
  163. package/src/localization.ts +6 -0
  164. package/src/localizations/es.ts +2 -1
  165. package/src/{geometry → math}/LineSegment2.test.ts +0 -0
  166. package/src/{geometry → math}/LineSegment2.ts +0 -0
  167. package/src/{geometry → math}/Mat33.test.ts +0 -0
  168. package/src/{geometry → math}/Mat33.ts +48 -20
  169. package/src/{geometry → math}/Path.fromString.test.ts +0 -0
  170. package/src/{geometry → math}/Path.test.ts +0 -0
  171. package/src/{geometry → math}/Path.toString.test.ts +11 -2
  172. package/src/{geometry → math}/Path.ts +61 -58
  173. package/src/{geometry → math}/Rect2.test.ts +0 -0
  174. package/src/{geometry → math}/Rect2.ts +2 -2
  175. package/src/{geometry → math}/Vec2.test.ts +0 -0
  176. package/src/{geometry → math}/Vec2.ts +0 -0
  177. package/src/{geometry → math}/Vec3.test.ts +0 -0
  178. package/src/{geometry → math}/Vec3.ts +64 -16
  179. package/src/math/lib.ts +15 -0
  180. package/src/math/rounding.test.ts +40 -0
  181. package/src/math/rounding.ts +147 -0
  182. package/src/rendering/Display.ts +63 -15
  183. package/src/rendering/caching/CacheRecord.test.ts +3 -3
  184. package/src/rendering/caching/CacheRecord.ts +6 -2
  185. package/src/rendering/caching/CacheRecordManager.ts +34 -8
  186. package/src/rendering/caching/RenderingCache.test.ts +3 -3
  187. package/src/rendering/caching/RenderingCache.ts +11 -16
  188. package/src/rendering/caching/RenderingCacheNode.ts +23 -7
  189. package/src/rendering/caching/testUtils.ts +1 -1
  190. package/src/rendering/caching/types.ts +2 -7
  191. package/src/rendering/localization.ts +4 -0
  192. package/src/rendering/renderers/AbstractRenderer.ts +4 -4
  193. package/src/rendering/renderers/CanvasRenderer.ts +5 -5
  194. package/src/rendering/renderers/DummyRenderer.test.ts +2 -2
  195. package/src/rendering/renderers/DummyRenderer.ts +4 -4
  196. package/src/rendering/renderers/SVGRenderer.ts +10 -4
  197. package/src/rendering/renderers/TextOnlyRenderer.ts +17 -6
  198. package/src/toolbar/HTMLToolbar.ts +1 -0
  199. package/src/toolbar/icons.ts +157 -137
  200. package/src/toolbar/localization.ts +4 -2
  201. package/src/toolbar/makeColorInput.ts +3 -2
  202. package/src/toolbar/toolbar.css +1 -1
  203. package/src/toolbar/widgets/ActionButtonWidget.ts +31 -0
  204. package/src/toolbar/widgets/BaseWidget.ts +2 -0
  205. package/src/toolbar/widgets/HandToolWidget.ts +3 -3
  206. package/src/toolbar/widgets/PenWidget.ts +2 -0
  207. package/src/toolbar/widgets/SelectionWidget.ts +46 -41
  208. package/src/tools/Eraser.ts +2 -2
  209. package/src/tools/PanZoom.ts +28 -17
  210. package/src/tools/Pen.ts +11 -2
  211. package/src/tools/PipetteTool.ts +2 -0
  212. package/src/tools/SelectionTool.test.ts +2 -4
  213. package/src/tools/SelectionTool.ts +52 -24
  214. package/src/tools/TextTool.ts +2 -2
  215. package/src/tools/UndoRedoShortcut.test.ts +1 -1
  216. package/src/types.ts +23 -7
  217. package/tsconfig.json +4 -1
  218. package/typedoc.json +20 -0
  219. package/dist/src/geometry/Mat33.d.ts +0 -32
  220. package/dist/src/geometry/Vec3.d.ts +0 -34
@@ -1,7 +1,7 @@
1
1
 
2
2
  import EventDispatcher from '../../EventDispatcher';
3
- import Mat33 from '../../geometry/Mat33';
4
- import { Vec2 } from '../../geometry/Vec2';
3
+ import Mat33 from '../../math/Mat33';
4
+ import { Vec2 } from '../../math/Vec2';
5
5
  import Viewport from '../../Viewport';
6
6
  import DummyRenderer from './DummyRenderer';
7
7
 
@@ -1,10 +1,10 @@
1
1
  // Renderer that outputs nothing. Useful for automated tests.
2
2
 
3
3
  import { TextStyle } from '../../components/Text';
4
- import Mat33 from '../../geometry/Mat33';
5
- import Rect2 from '../../geometry/Rect2';
6
- import { Point2, Vec2 } from '../../geometry/Vec2';
7
- import Vec3 from '../../geometry/Vec3';
4
+ import Mat33 from '../../math/Mat33';
5
+ import Rect2 from '../../math/Rect2';
6
+ import { Point2, Vec2 } from '../../math/Vec2';
7
+ import Vec3 from '../../math/Vec3';
8
8
  import Viewport from '../../Viewport';
9
9
  import RenderingStyle from '../RenderingStyle';
10
10
  import AbstractRenderer from './AbstractRenderer';
@@ -1,10 +1,11 @@
1
1
 
2
2
  import { LoadSaveDataTable } from '../../components/AbstractComponent';
3
3
  import { TextStyle } from '../../components/Text';
4
- import Mat33 from '../../geometry/Mat33';
5
- import Path, { PathCommand, PathCommandType } from '../../geometry/Path';
6
- import Rect2 from '../../geometry/Rect2';
7
- import { Point2, Vec2 } from '../../geometry/Vec2';
4
+ import Mat33 from '../../math/Mat33';
5
+ import Path, { PathCommand, PathCommandType } from '../../math/Path';
6
+ import Rect2 from '../../math/Rect2';
7
+ import { toRoundedString } from '../../math/rounding';
8
+ import { Point2, Vec2 } from '../../math/Vec2';
8
9
  import { svgAttributesDataKey, SVGLoaderUnknownAttribute, SVGLoaderUnknownStyleAttribute, svgStyleAttributesDataKey } from '../../SVGLoader';
9
10
  import Viewport from '../../Viewport';
10
11
  import RenderingStyle from '../RenderingStyle';
@@ -113,6 +114,9 @@ export default class SVGRenderer extends AbstractRenderer {
113
114
  public drawText(text: string, transform: Mat33, style: TextStyle): void {
114
115
  transform = this.getCanvasToScreenTransform().rightMul(transform);
115
116
 
117
+ const translation = transform.transformVec2(Vec2.zero);
118
+ transform = transform.rightMul(Mat33.translation(translation.times(-1)));
119
+
116
120
  const textElem = document.createElementNS(svgNameSpace, 'text');
117
121
  textElem.appendChild(document.createTextNode(text));
118
122
  textElem.style.transform = `matrix(
@@ -125,6 +129,8 @@ export default class SVGRenderer extends AbstractRenderer {
125
129
  textElem.style.fontWeight = style.fontWeight ?? '';
126
130
  textElem.style.fontSize = style.size + 'px';
127
131
  textElem.style.fill = style.renderingStyle.fill.toHexString();
132
+ textElem.setAttribute('x', `${toRoundedString(translation.x)}`);
133
+ textElem.setAttribute('y', `${toRoundedString(translation.y)}`);
128
134
 
129
135
  if (style.renderingStyle.stroke) {
130
136
  const strokeStyle = style.renderingStyle.stroke;
@@ -1,8 +1,8 @@
1
1
  import { TextStyle } from '../../components/Text';
2
- import Mat33 from '../../geometry/Mat33';
3
- import Rect2 from '../../geometry/Rect2';
4
- import { Vec2 } from '../../geometry/Vec2';
5
- import Vec3 from '../../geometry/Vec3';
2
+ import Mat33 from '../../math/Mat33';
3
+ import Rect2 from '../../math/Rect2';
4
+ import { Vec2 } from '../../math/Vec2';
5
+ import Vec3 from '../../math/Vec3';
6
6
  import Viewport from '../../Viewport';
7
7
  import { TextRendererLocalization } from '../localization';
8
8
  import RenderingStyle from '../RenderingStyle';
@@ -12,6 +12,9 @@ import AbstractRenderer from './AbstractRenderer';
12
12
 
13
13
  export default class TextOnlyRenderer extends AbstractRenderer {
14
14
  private descriptionBuilder: string[] = [];
15
+ private pathCount: number = 0;
16
+ private textNodeCount: number = 0;
17
+
15
18
  public constructor(viewport: Viewport, private localizationTable: TextRendererLocalization) {
16
19
  super(viewport);
17
20
  }
@@ -23,15 +26,22 @@ export default class TextOnlyRenderer extends AbstractRenderer {
23
26
 
24
27
  public clear(): void {
25
28
  this.descriptionBuilder = [];
29
+ this.pathCount = 0;
30
+ this.textNodeCount = 0;
26
31
  }
27
32
 
28
33
  public getDescription(): string {
29
- return this.descriptionBuilder.join('\n');
34
+ return [
35
+ this.localizationTable.pathNodeCount(this.pathCount),
36
+ this.localizationTable.textNodeCount(this.textNodeCount),
37
+ ...this.descriptionBuilder
38
+ ].join('\n');
30
39
  }
31
40
 
32
41
  protected beginPath(_startPoint: Vec3): void {
33
42
  }
34
43
  protected endPath(_style: RenderingStyle): void {
44
+ this.pathCount ++;
35
45
  }
36
46
  protected lineTo(_point: Vec3): void {
37
47
  }
@@ -43,9 +53,10 @@ export default class TextOnlyRenderer extends AbstractRenderer {
43
53
  }
44
54
  public drawText(text: string, _transform: Mat33, _style: TextStyle): void {
45
55
  this.descriptionBuilder.push(this.localizationTable.textNode(text));
56
+ this.textNodeCount ++;
46
57
  }
47
58
  public isTooSmallToRender(rect: Rect2): boolean {
48
- return rect.maxDimension < 10 / this.getSizeOfCanvasPixelOnScreen();
59
+ return rect.maxDimension < 15 / this.getSizeOfCanvasPixelOnScreen();
49
60
  }
50
61
  public drawPoints(..._points: Vec3[]): void {
51
62
  }
@@ -43,6 +43,7 @@ export default class HTMLToolbar {
43
43
  this.setupColorPickers();
44
44
  }
45
45
 
46
+ // @internal
46
47
  public setupColorPickers() {
47
48
  const closePickerOverlay = document.createElement('div');
48
49
  closePickerOverlay.className = `${toolbarCSSPrefix}closeColorPickerOverlay`;
@@ -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',
@@ -8,7 +8,7 @@ import { makePipetteIcon } from './icons';
8
8
  type OnColorChangeListener = (color: Color4)=>void;
9
9
 
10
10
 
11
- // Returns [ input, container ].
11
+ // Returns [ color input, input container ].
12
12
  export const makeColorInput = (editor: Editor, onColorChange: OnColorChangeListener): [ HTMLInputElement, HTMLElement ] => {
13
13
  const colorInputContainer = document.createElement('span');
14
14
  const colorInput = document.createElement('input');
@@ -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,3 +1,5 @@
1
+ // @internal @packageDocumentation
2
+
1
3
  import { makeArrowBuilder } from '../../components/builders/ArrowBuilder';
2
4
  import { makeFreehandLineBuilder } from '../../components/builders/FreehandLineBuilder';
3
5
  import { makeLineBuilder } from '../../components/builders/LineBuilder';