js-draw 0.1.9 → 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 (193) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +15 -3
  3. package/dist/bundle.js +1 -1
  4. package/dist/src/Editor.d.ts +7 -2
  5. package/dist/src/Editor.js +74 -25
  6. package/dist/src/EditorImage.d.ts +1 -1
  7. package/dist/src/EditorImage.js +2 -2
  8. package/dist/src/Pointer.d.ts +1 -1
  9. package/dist/src/Pointer.js +1 -1
  10. package/dist/src/SVGLoader.d.ts +1 -1
  11. package/dist/src/SVGLoader.js +14 -6
  12. package/dist/src/UndoRedoHistory.js +3 -0
  13. package/dist/src/Viewport.d.ts +8 -25
  14. package/dist/src/Viewport.js +17 -10
  15. package/dist/src/bundle/bundled.d.ts +2 -1
  16. package/dist/src/bundle/bundled.js +2 -1
  17. package/dist/src/commands/Command.d.ts +2 -2
  18. package/dist/src/commands/Command.js +4 -4
  19. package/dist/src/commands/Duplicate.d.ts +1 -1
  20. package/dist/src/commands/Duplicate.js +1 -1
  21. package/dist/src/commands/Erase.d.ts +1 -1
  22. package/dist/src/commands/Erase.js +1 -1
  23. package/dist/src/commands/localization.d.ts +1 -1
  24. package/dist/src/components/AbstractComponent.d.ts +3 -3
  25. package/dist/src/components/AbstractComponent.js +2 -2
  26. package/dist/src/components/SVGGlobalAttributesObject.d.ts +3 -3
  27. package/dist/src/components/SVGGlobalAttributesObject.js +1 -1
  28. package/dist/src/components/Stroke.d.ts +4 -4
  29. package/dist/src/components/Stroke.js +2 -2
  30. package/dist/src/components/Text.d.ts +3 -3
  31. package/dist/src/components/Text.js +3 -3
  32. package/dist/src/components/UnknownSVGObject.d.ts +3 -3
  33. package/dist/src/components/UnknownSVGObject.js +1 -1
  34. package/dist/src/components/builders/ArrowBuilder.d.ts +1 -1
  35. package/dist/src/components/builders/ArrowBuilder.js +1 -1
  36. package/dist/src/components/builders/FreehandLineBuilder.d.ts +8 -3
  37. package/dist/src/components/builders/FreehandLineBuilder.js +142 -71
  38. package/dist/src/components/builders/LineBuilder.d.ts +1 -1
  39. package/dist/src/components/builders/LineBuilder.js +1 -1
  40. package/dist/src/components/builders/RectangleBuilder.d.ts +1 -1
  41. package/dist/src/components/builders/RectangleBuilder.js +3 -3
  42. package/dist/src/components/builders/types.d.ts +1 -1
  43. package/dist/src/localization.d.ts +1 -0
  44. package/dist/src/localization.js +5 -1
  45. package/dist/src/localizations/en.d.ts +3 -0
  46. package/dist/src/localizations/en.js +4 -0
  47. package/dist/src/localizations/es.d.ts +3 -0
  48. package/dist/src/localizations/es.js +18 -0
  49. package/dist/src/localizations/getLocalizationTable.d.ts +3 -0
  50. package/dist/src/localizations/getLocalizationTable.js +43 -0
  51. package/dist/src/{geometry → math}/LineSegment2.d.ts +1 -0
  52. package/dist/src/{geometry → math}/LineSegment2.js +16 -0
  53. package/dist/src/{geometry → math}/Mat33.d.ts +0 -0
  54. package/dist/src/{geometry → math}/Mat33.js +0 -0
  55. package/dist/src/{geometry → math}/Path.d.ts +2 -1
  56. package/dist/src/{geometry → math}/Path.js +58 -51
  57. package/dist/src/{geometry → math}/Rect2.d.ts +1 -0
  58. package/dist/src/{geometry → math}/Rect2.js +16 -0
  59. package/dist/src/{geometry → math}/Vec2.d.ts +0 -0
  60. package/dist/src/{geometry → math}/Vec2.js +0 -0
  61. package/dist/src/{geometry → math}/Vec3.d.ts +1 -1
  62. package/dist/src/{geometry → math}/Vec3.js +1 -1
  63. package/dist/src/math/rounding.d.ts +3 -0
  64. package/dist/src/math/rounding.js +120 -0
  65. package/dist/src/rendering/Display.d.ts +3 -1
  66. package/dist/src/rendering/Display.js +16 -10
  67. package/dist/src/rendering/caching/CacheRecord.d.ts +2 -2
  68. package/dist/src/rendering/caching/CacheRecord.js +1 -1
  69. package/dist/src/rendering/caching/CacheRecordManager.d.ts +1 -1
  70. package/dist/src/rendering/caching/RenderingCache.js +1 -1
  71. package/dist/src/rendering/caching/RenderingCacheNode.d.ts +2 -1
  72. package/dist/src/rendering/caching/RenderingCacheNode.js +18 -7
  73. package/dist/src/rendering/caching/testUtils.js +1 -1
  74. package/dist/src/rendering/caching/types.d.ts +1 -1
  75. package/dist/src/rendering/localization.d.ts +2 -0
  76. package/dist/src/rendering/localization.js +2 -0
  77. package/dist/src/rendering/renderers/AbstractRenderer.d.ts +4 -4
  78. package/dist/src/rendering/renderers/AbstractRenderer.js +2 -2
  79. package/dist/src/rendering/renderers/CanvasRenderer.d.ts +4 -4
  80. package/dist/src/rendering/renderers/CanvasRenderer.js +1 -1
  81. package/dist/src/rendering/renderers/DummyRenderer.d.ts +4 -4
  82. package/dist/src/rendering/renderers/DummyRenderer.js +1 -1
  83. package/dist/src/rendering/renderers/SVGRenderer.d.ts +3 -3
  84. package/dist/src/rendering/renderers/SVGRenderer.js +8 -2
  85. package/dist/src/rendering/renderers/TextOnlyRenderer.d.ts +5 -3
  86. package/dist/src/rendering/renderers/TextOnlyRenderer.js +13 -3
  87. package/dist/src/toolbar/HTMLToolbar.js +5 -7
  88. package/dist/src/toolbar/icons.d.ts +3 -0
  89. package/dist/src/toolbar/icons.js +152 -142
  90. package/dist/src/toolbar/localization.d.ts +4 -1
  91. package/dist/src/toolbar/localization.js +4 -1
  92. package/dist/src/toolbar/makeColorInput.js +2 -1
  93. package/dist/src/toolbar/widgets/ActionButtonWidget.d.ts +13 -0
  94. package/dist/src/toolbar/widgets/ActionButtonWidget.js +21 -0
  95. package/dist/src/toolbar/widgets/BaseWidget.js +31 -0
  96. package/dist/src/toolbar/widgets/HandToolWidget.js +10 -3
  97. package/dist/src/toolbar/widgets/SelectionWidget.d.ts +0 -1
  98. package/dist/src/toolbar/widgets/SelectionWidget.js +23 -30
  99. package/dist/src/tools/BaseTool.d.ts +2 -1
  100. package/dist/src/tools/BaseTool.js +3 -0
  101. package/dist/src/tools/Eraser.js +1 -1
  102. package/dist/src/tools/PanZoom.d.ts +3 -2
  103. package/dist/src/tools/PanZoom.js +32 -16
  104. package/dist/src/tools/SelectionTool.d.ts +11 -4
  105. package/dist/src/tools/SelectionTool.js +135 -23
  106. package/dist/src/tools/TextTool.js +1 -1
  107. package/dist/src/tools/ToolController.js +6 -2
  108. package/dist/src/tools/localization.d.ts +1 -0
  109. package/dist/src/tools/localization.js +1 -0
  110. package/dist/src/types.d.ts +13 -6
  111. package/dist/src/types.js +1 -0
  112. package/package.json +9 -1
  113. package/src/Editor.ts +86 -24
  114. package/src/EditorImage.test.ts +2 -4
  115. package/src/EditorImage.ts +2 -2
  116. package/src/Pointer.ts +1 -1
  117. package/src/SVGLoader.ts +14 -6
  118. package/src/UndoRedoHistory.ts +4 -0
  119. package/src/Viewport.ts +21 -17
  120. package/src/bundle/bundled.ts +2 -1
  121. package/src/commands/Command.ts +5 -5
  122. package/src/commands/Duplicate.ts +1 -1
  123. package/src/commands/Erase.ts +1 -1
  124. package/src/commands/localization.ts +1 -1
  125. package/src/components/AbstractComponent.ts +4 -4
  126. package/src/components/SVGGlobalAttributesObject.ts +3 -3
  127. package/src/components/Stroke.test.ts +3 -5
  128. package/src/components/Stroke.ts +4 -4
  129. package/src/components/Text.test.ts +2 -2
  130. package/src/components/Text.ts +3 -3
  131. package/src/components/UnknownSVGObject.ts +3 -3
  132. package/src/components/builders/ArrowBuilder.ts +2 -2
  133. package/src/components/builders/FreehandLineBuilder.ts +190 -80
  134. package/src/components/builders/LineBuilder.ts +2 -2
  135. package/src/components/builders/RectangleBuilder.ts +3 -3
  136. package/src/components/builders/types.ts +1 -1
  137. package/src/localization.ts +6 -0
  138. package/src/localizations/en.ts +8 -0
  139. package/src/localizations/es.ts +63 -0
  140. package/src/localizations/getLocalizationTable.test.ts +27 -0
  141. package/src/localizations/getLocalizationTable.ts +53 -0
  142. package/src/{geometry → math}/LineSegment2.test.ts +15 -0
  143. package/src/{geometry → math}/LineSegment2.ts +20 -0
  144. package/src/{geometry → math}/Mat33.test.ts +0 -0
  145. package/src/{geometry → math}/Mat33.ts +0 -0
  146. package/src/{geometry → math}/Path.fromString.test.ts +0 -0
  147. package/src/{geometry → math}/Path.test.ts +0 -0
  148. package/src/{geometry → math}/Path.toString.test.ts +11 -2
  149. package/src/{geometry → math}/Path.ts +60 -57
  150. package/src/{geometry → math}/Rect2.test.ts +20 -7
  151. package/src/{geometry → math}/Rect2.ts +19 -1
  152. package/src/{geometry → math}/Vec2.test.ts +0 -0
  153. package/src/{geometry → math}/Vec2.ts +0 -0
  154. package/src/{geometry → math}/Vec3.test.ts +0 -0
  155. package/src/{geometry → math}/Vec3.ts +2 -2
  156. package/src/math/rounding.test.ts +40 -0
  157. package/src/math/rounding.ts +145 -0
  158. package/src/rendering/Display.ts +18 -10
  159. package/src/rendering/caching/CacheRecord.test.ts +2 -2
  160. package/src/rendering/caching/CacheRecord.ts +2 -2
  161. package/src/rendering/caching/CacheRecordManager.ts +1 -1
  162. package/src/rendering/caching/RenderingCache.test.ts +3 -3
  163. package/src/rendering/caching/RenderingCache.ts +1 -1
  164. package/src/rendering/caching/RenderingCacheNode.ts +23 -7
  165. package/src/rendering/caching/testUtils.ts +1 -1
  166. package/src/rendering/caching/types.ts +1 -1
  167. package/src/rendering/localization.ts +4 -0
  168. package/src/rendering/renderers/AbstractRenderer.ts +4 -4
  169. package/src/rendering/renderers/CanvasRenderer.ts +4 -4
  170. package/src/rendering/renderers/DummyRenderer.test.ts +2 -2
  171. package/src/rendering/renderers/DummyRenderer.ts +4 -4
  172. package/src/rendering/renderers/SVGRenderer.ts +10 -4
  173. package/src/rendering/renderers/TextOnlyRenderer.ts +17 -6
  174. package/src/toolbar/HTMLToolbar.ts +5 -8
  175. package/src/toolbar/icons.ts +167 -147
  176. package/src/toolbar/localization.ts +8 -2
  177. package/src/toolbar/makeColorInput.ts +2 -1
  178. package/src/toolbar/toolbar.css +7 -3
  179. package/src/toolbar/widgets/ActionButtonWidget.ts +31 -0
  180. package/src/toolbar/widgets/BaseWidget.ts +36 -0
  181. package/src/toolbar/widgets/HandToolWidget.ts +14 -3
  182. package/src/toolbar/widgets/SelectionWidget.ts +46 -41
  183. package/src/tools/BaseTool.ts +5 -1
  184. package/src/tools/Eraser.ts +2 -2
  185. package/src/tools/PanZoom.ts +39 -18
  186. package/src/tools/SelectionTool.test.ts +26 -5
  187. package/src/tools/SelectionTool.ts +162 -27
  188. package/src/tools/TextTool.ts +2 -2
  189. package/src/tools/ToolController.ts +6 -2
  190. package/src/tools/UndoRedoShortcut.test.ts +1 -1
  191. package/src/tools/localization.ts +2 -0
  192. package/src/types.ts +14 -5
  193. package/dist-test/test-dist-bundle.html +0 -42
@@ -4,17 +4,19 @@ import { InputEvtType, EditorNotifier, ImageLoader } from './types';
4
4
  import Command from './commands/Command';
5
5
  import UndoRedoHistory from './UndoRedoHistory';
6
6
  import Viewport from './Viewport';
7
- import { Point2 } from './geometry/Vec2';
7
+ import { Point2 } from './math/Vec2';
8
8
  import HTMLToolbar from './toolbar/HTMLToolbar';
9
9
  import { RenderablePathSpec } from './rendering/renderers/AbstractRenderer';
10
10
  import Display, { RenderingMode } from './rendering/Display';
11
11
  import Pointer from './Pointer';
12
- import Rect2 from './geometry/Rect2';
12
+ import Rect2 from './math/Rect2';
13
13
  import { EditorLocalization } from './localization';
14
14
  export interface EditorSettings {
15
15
  renderingMode: RenderingMode;
16
16
  localization: Partial<EditorLocalization>;
17
17
  wheelEventsEnabled: boolean | 'only-if-focused';
18
+ minZoom: number;
19
+ maxZoom: number;
18
20
  }
19
21
  export declare class Editor {
20
22
  private container;
@@ -29,14 +31,17 @@ export declare class Editor {
29
31
  notifier: EditorNotifier;
30
32
  private loadingWarning;
31
33
  private accessibilityAnnounceArea;
34
+ private accessibilityControlArea;
32
35
  private settings;
33
36
  constructor(parent: HTMLElement, settings?: Partial<EditorSettings>);
34
37
  getRootElement(): HTMLElement;
35
38
  showLoadingWarning(fractionLoaded: number): void;
36
39
  hideLoadingWarning(): void;
40
+ private previousAccessibilityAnnouncement;
37
41
  announceForAccessibility(message: string): void;
38
42
  addToolbar(defaultLayout?: boolean): HTMLToolbar;
39
43
  private registerListeners;
44
+ handleKeyEventsFrom(elem: HTMLElement): void;
40
45
  dispatch(command: Command, addToHistory?: boolean): void;
41
46
  dispatchNoAnnounce(command: Command, addToHistory?: boolean): void;
42
47
  private asyncApplyOrUnapplyCommands;
@@ -14,33 +14,35 @@ import Command from './commands/Command';
14
14
  import UndoRedoHistory from './UndoRedoHistory';
15
15
  import Viewport from './Viewport';
16
16
  import EventDispatcher from './EventDispatcher';
17
- import { Vec2 } from './geometry/Vec2';
18
- import Vec3 from './geometry/Vec3';
17
+ import { Vec2 } from './math/Vec2';
18
+ import Vec3 from './math/Vec3';
19
19
  import HTMLToolbar from './toolbar/HTMLToolbar';
20
20
  import Display, { RenderingMode } from './rendering/Display';
21
21
  import SVGRenderer from './rendering/renderers/SVGRenderer';
22
22
  import Color4 from './Color4';
23
23
  import SVGLoader from './SVGLoader';
24
24
  import Pointer from './Pointer';
25
- import Mat33 from './geometry/Mat33';
26
- import { defaultEditorLocalization } from './localization';
25
+ import Mat33 from './math/Mat33';
26
+ import getLocalizationTable from './localizations/getLocalizationTable';
27
27
  export class Editor {
28
28
  constructor(parent, settings = {}) {
29
- var _a, _b;
30
- this.localization = defaultEditorLocalization;
29
+ var _a, _b, _c, _d;
30
+ this.previousAccessibilityAnnouncement = '';
31
31
  this.announceUndoCallback = (command) => {
32
- this.announceForAccessibility(this.localization.undoAnnouncement(command.description(this.localization)));
32
+ this.announceForAccessibility(this.localization.undoAnnouncement(command.description(this, this.localization)));
33
33
  };
34
34
  this.announceRedoCallback = (command) => {
35
- this.announceForAccessibility(this.localization.redoAnnouncement(command.description(this.localization)));
35
+ this.announceForAccessibility(this.localization.redoAnnouncement(command.description(this, this.localization)));
36
36
  };
37
37
  this.rerenderQueued = false;
38
- this.localization = Object.assign(Object.assign({}, this.localization), settings.localization);
38
+ this.localization = Object.assign(Object.assign({}, getLocalizationTable()), settings.localization);
39
39
  // Fill default settings.
40
40
  this.settings = {
41
41
  wheelEventsEnabled: (_a = settings.wheelEventsEnabled) !== null && _a !== void 0 ? _a : true,
42
42
  renderingMode: (_b = settings.renderingMode) !== null && _b !== void 0 ? _b : RenderingMode.CanvasRenderer,
43
43
  localization: this.localization,
44
+ minZoom: (_c = settings.minZoom) !== null && _c !== void 0 ? _c : 2e-10,
45
+ maxZoom: (_d = settings.maxZoom) !== null && _d !== void 0 ? _d : 1e12,
44
46
  };
45
47
  this.container = document.createElement('div');
46
48
  this.renderingRegion = document.createElement('div');
@@ -50,14 +52,21 @@ export class Editor {
50
52
  this.loadingWarning.classList.add('loadingMessage');
51
53
  this.loadingWarning.ariaLive = 'polite';
52
54
  this.container.appendChild(this.loadingWarning);
55
+ this.accessibilityControlArea = document.createElement('textarea');
56
+ this.accessibilityControlArea.setAttribute('placeholder', this.localization.accessibilityInputInstructions);
57
+ this.accessibilityControlArea.style.opacity = '0';
58
+ this.accessibilityControlArea.style.width = '0';
59
+ this.accessibilityControlArea.style.height = '0';
60
+ this.accessibilityControlArea.style.position = 'absolute';
53
61
  this.accessibilityAnnounceArea = document.createElement('div');
54
- this.accessibilityAnnounceArea.ariaLive = 'assertive';
62
+ this.accessibilityAnnounceArea.setAttribute('aria-live', 'assertive');
55
63
  this.accessibilityAnnounceArea.className = 'accessibilityAnnouncement';
56
64
  this.container.appendChild(this.accessibilityAnnounceArea);
57
65
  this.renderingRegion.style.touchAction = 'none';
58
66
  this.renderingRegion.className = 'imageEditorRenderArea';
67
+ this.renderingRegion.appendChild(this.accessibilityControlArea);
59
68
  this.renderingRegion.setAttribute('tabIndex', '0');
60
- this.renderingRegion.ariaLabel = this.localization.imageEditor;
69
+ this.renderingRegion.setAttribute('alt', '');
61
70
  this.notifier = new EventDispatcher();
62
71
  this.importExportViewport = new Viewport(this.notifier);
63
72
  this.viewport = new Viewport(this.notifier);
@@ -72,6 +81,20 @@ export class Editor {
72
81
  this.registerListeners();
73
82
  this.queueRerender();
74
83
  this.hideLoadingWarning();
84
+ // Enforce zoom limits.
85
+ this.notifier.on(EditorEventType.ViewportChanged, evt => {
86
+ if (evt.kind === EditorEventType.ViewportChanged) {
87
+ const zoom = evt.newTransform.transformVec3(Vec2.unitX).length();
88
+ if (zoom > this.settings.maxZoom || zoom < this.settings.minZoom) {
89
+ const oldZoom = evt.oldTransform.transformVec3(Vec2.unitX).length();
90
+ let resetTransform = Mat33.identity;
91
+ if (oldZoom <= this.settings.maxZoom && oldZoom >= this.settings.minZoom) {
92
+ resetTransform = evt.oldTransform;
93
+ }
94
+ this.viewport.resetTransform(resetTransform);
95
+ }
96
+ }
97
+ });
75
98
  }
76
99
  // Returns a reference to this' container.
77
100
  // Example usage:
@@ -90,7 +113,12 @@ export class Editor {
90
113
  this.announceForAccessibility(this.localization.doneLoading);
91
114
  }
92
115
  announceForAccessibility(message) {
116
+ // Force re-announcing an announcement if announced again.
117
+ if (message === this.previousAccessibilityAnnouncement) {
118
+ message = message + '. ';
119
+ }
93
120
  this.accessibilityAnnounceArea.innerText = message;
121
+ this.previousAccessibilityAnnouncement = message;
94
122
  }
95
123
  addToolbar(defaultLayout = true) {
96
124
  const toolbar = new HTMLToolbar(this, this.container, this.localization);
@@ -176,18 +204,7 @@ export class Editor {
176
204
  this.renderingRegion.addEventListener('pointercancel', evt => {
177
205
  pointerEnd(evt);
178
206
  });
179
- this.renderingRegion.addEventListener('keydown', evt => {
180
- if (this.toolController.dispatchInputEvent({
181
- kind: InputEvtType.KeyPressEvent,
182
- key: evt.key,
183
- ctrlKey: evt.ctrlKey,
184
- })) {
185
- evt.preventDefault();
186
- }
187
- else if (evt.key === 'Escape') {
188
- this.renderingRegion.blur();
189
- }
190
- });
207
+ this.handleKeyEventsFrom(this.renderingRegion);
191
208
  this.container.addEventListener('wheel', evt => {
192
209
  let delta = Vec3.of(evt.deltaX, evt.deltaY, evt.deltaZ);
193
210
  // Process wheel events if the ctrl key is down, even if disabled -- we do want to handle
@@ -233,6 +250,38 @@ export class Editor {
233
250
  });
234
251
  this.queueRerender();
235
252
  });
253
+ this.accessibilityControlArea.addEventListener('input', () => {
254
+ this.accessibilityControlArea.value = '';
255
+ });
256
+ }
257
+ // Adds event listners for keypresses to [elem] and forwards those events to the
258
+ // editor.
259
+ handleKeyEventsFrom(elem) {
260
+ elem.addEventListener('keydown', evt => {
261
+ if (evt.key === 't' || evt.key === 'T') {
262
+ evt.preventDefault();
263
+ this.display.rerenderAsText();
264
+ }
265
+ else if (this.toolController.dispatchInputEvent({
266
+ kind: InputEvtType.KeyPressEvent,
267
+ key: evt.key,
268
+ ctrlKey: evt.ctrlKey,
269
+ })) {
270
+ evt.preventDefault();
271
+ }
272
+ else if (evt.key === 'Escape') {
273
+ this.renderingRegion.blur();
274
+ }
275
+ });
276
+ elem.addEventListener('keyup', evt => {
277
+ if (this.toolController.dispatchInputEvent({
278
+ kind: InputEvtType.KeyUpEvent,
279
+ key: evt.key,
280
+ ctrlKey: evt.ctrlKey,
281
+ })) {
282
+ evt.preventDefault();
283
+ }
284
+ });
236
285
  }
237
286
  // Adds to history by default
238
287
  dispatch(command, addToHistory = true) {
@@ -243,7 +292,7 @@ export class Editor {
243
292
  else {
244
293
  command.apply(this);
245
294
  }
246
- this.announceForAccessibility(command.description(this.localization));
295
+ this.announceForAccessibility(command.description(this, this.localization));
247
296
  }
248
297
  // Dispatches a command without announcing it. By default, does not add to history.
249
298
  dispatchNoAnnounce(command, addToHistory = false) {
@@ -420,7 +469,7 @@ export class Editor {
420
469
  viewport.resetTransform(origTransform);
421
470
  editor.queueRerender();
422
471
  }
423
- description(localizationTable) {
472
+ description(_editor, localizationTable) {
424
473
  return localizationTable.resizeOutputCommand(imageRect);
425
474
  }
426
475
  };
@@ -2,7 +2,7 @@ import AbstractRenderer from './rendering/renderers/AbstractRenderer';
2
2
  import Command from './commands/Command';
3
3
  import Viewport from './Viewport';
4
4
  import AbstractComponent from './components/AbstractComponent';
5
- import Rect2 from './geometry/Rect2';
5
+ import Rect2 from './math/Rect2';
6
6
  import RenderingCache from './rendering/caching/RenderingCache';
7
7
  export declare const sortLeavesByZIndex: (leaves: Array<ImageNode>) => void;
8
8
  export default class EditorImage {
@@ -1,6 +1,6 @@
1
1
  var _a;
2
2
  import AbstractComponent from './components/AbstractComponent';
3
- import Rect2 from './geometry/Rect2';
3
+ import Rect2 from './math/Rect2';
4
4
  import SerializableCommand from './commands/SerializableCommand';
5
5
  export const sortLeavesByZIndex = (leaves) => {
6
6
  leaves.sort((a, b) => a.getContent().getZIndex() - b.getContent().getZIndex());
@@ -83,7 +83,7 @@ EditorImage.AddElementCommand = (_a = class extends SerializableCommand {
83
83
  container === null || container === void 0 ? void 0 : container.remove();
84
84
  editor.queueRerender();
85
85
  }
86
- description(localization) {
86
+ description(editor, localization) {
87
87
  return localization.addElementAction(this.element.description(localization));
88
88
  }
89
89
  serializeToString() {
@@ -1,4 +1,4 @@
1
- import { Point2 } from './geometry/Vec2';
1
+ import { Point2 } from './math/Vec2';
2
2
  import Viewport from './Viewport';
3
3
  export declare enum PointerDevice {
4
4
  Pen = 0,
@@ -1,4 +1,4 @@
1
- import { Vec2 } from './geometry/Vec2';
1
+ import { Vec2 } from './math/Vec2';
2
2
  export var PointerDevice;
3
3
  (function (PointerDevice) {
4
4
  PointerDevice[PointerDevice["Pen"] = 0] = "Pen";
@@ -1,4 +1,4 @@
1
- import Rect2 from './geometry/Rect2';
1
+ import Rect2 from './math/Rect2';
2
2
  import { ComponentAddedListener, ImageLoader, OnDetermineExportRectListener, OnProgressListener } from './types';
3
3
  export declare const defaultSVGViewRect: Rect2;
4
4
  export declare const svgAttributesDataKey = "svgAttrs";
@@ -12,10 +12,10 @@ import Stroke from './components/Stroke';
12
12
  import SVGGlobalAttributesObject from './components/SVGGlobalAttributesObject';
13
13
  import Text from './components/Text';
14
14
  import UnknownSVGObject from './components/UnknownSVGObject';
15
- import Mat33 from './geometry/Mat33';
16
- import Path from './geometry/Path';
17
- import Rect2 from './geometry/Rect2';
18
- import { Vec2 } from './geometry/Vec2';
15
+ import Mat33 from './math/Mat33';
16
+ import Path from './math/Path';
17
+ import Rect2 from './math/Rect2';
18
+ import { Vec2 } from './math/Vec2';
19
19
  // Size of a loaded image if no size is specified.
20
20
  export const defaultSVGViewRect = new Rect2(0, 0, 500, 500);
21
21
  // Key to retrieve unrecognised attributes from an AbstractComponent
@@ -171,8 +171,16 @@ export default class SVGLoader {
171
171
  if (transformProperty === '' || transformProperty === 'none') {
172
172
  transformProperty = elem.style.transform || 'none';
173
173
  }
174
- // Compute transform matrix
175
- let transform = Mat33.fromCSSMatrix(transformProperty);
174
+ // Compute transform matrix. Prefer the actual .style.transform
175
+ // to the computed stylesheet -- in some browsers, the computedStyles version
176
+ // can have lower precision.
177
+ let transform;
178
+ try {
179
+ transform = Mat33.fromCSSMatrix(elem.style.transform);
180
+ }
181
+ catch (_e) {
182
+ transform = Mat33.fromCSSMatrix(transformProperty);
183
+ }
176
184
  const supportedAttrs = [];
177
185
  const elemX = elem.getAttribute('x');
178
186
  const elemY = elem.getAttribute('y');
@@ -20,6 +20,9 @@ class UndoRedoHistory {
20
20
  command.apply(this.editor);
21
21
  }
22
22
  this.undoStack.push(command);
23
+ for (const elem of this.redoStack) {
24
+ elem.onDrop(this.editor);
25
+ }
23
26
  this.redoStack = [];
24
27
  this.fireUpdateEvent();
25
28
  }
@@ -1,31 +1,16 @@
1
1
  import Command from './commands/Command';
2
- import { CommandLocalization } from './commands/localization';
3
- import Editor from './Editor';
4
- import Mat33 from './geometry/Mat33';
5
- import Rect2 from './geometry/Rect2';
6
- import { Point2, Vec2 } from './geometry/Vec2';
2
+ import Mat33 from './math/Mat33';
3
+ import Rect2 from './math/Rect2';
4
+ import { Point2, Vec2 } from './math/Vec2';
7
5
  import { StrokeDataPoint } from './types';
8
6
  import { EditorNotifier } from './types';
9
7
  declare type PointDataType<T extends Point2 | StrokeDataPoint | number> = T extends Point2 ? Point2 : number;
8
+ export declare abstract class ViewportTransform extends Command {
9
+ abstract readonly transform: Mat33;
10
+ }
10
11
  export declare class Viewport {
11
12
  private notifier;
12
- static ViewportTransform: {
13
- new (transform: Mat33): {
14
- readonly "__#679@#inverseTransform": Mat33;
15
- readonly transform: Mat33;
16
- apply(editor: Editor): void;
17
- unapply(editor: Editor): void;
18
- description(localizationTable: CommandLocalization): string;
19
- onDrop(_editor: Editor): void;
20
- };
21
- union(a: Command, b: Command): Command;
22
- readonly empty: {
23
- description(_localizationTable: import("./localization").EditorLocalization): string;
24
- apply(_editor: Editor): void;
25
- unapply(_editor: Editor): void;
26
- onDrop(_editor: Editor): void;
27
- };
28
- };
13
+ private static ViewportTransform;
29
14
  private transform;
30
15
  private inverseTransform;
31
16
  private screenRect;
@@ -34,6 +19,7 @@ export declare class Viewport {
34
19
  get visibleRect(): Rect2;
35
20
  screenToCanvas(screenPoint: Point2): Point2;
36
21
  canvasToScreen(canvasPoint: Point2): Point2;
22
+ static transformBy(transform: Mat33): ViewportTransform;
37
23
  resetTransform(newTransform?: Mat33): void;
38
24
  get screenToCanvasTransform(): Mat33;
39
25
  get canvasToScreenTransform(): Mat33;
@@ -45,7 +31,4 @@ export declare class Viewport {
45
31
  roundPoint(point: Point2): Point2;
46
32
  zoomTo(toMakeVisible: Rect2, allowZoomIn?: boolean, allowZoomOut?: boolean): Command;
47
33
  }
48
- export declare namespace Viewport {
49
- type ViewportTransform = typeof Viewport.ViewportTransform.prototype;
50
- }
51
34
  export default Viewport;
@@ -11,11 +11,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
11
11
  };
12
12
  var _inverseTransform, _a;
13
13
  import Command from './commands/Command';
14
- import Mat33 from './geometry/Mat33';
15
- import Rect2 from './geometry/Rect2';
16
- import { Vec2 } from './geometry/Vec2';
17
- import Vec3 from './geometry/Vec3';
14
+ import Mat33 from './math/Mat33';
15
+ import Rect2 from './math/Rect2';
16
+ import { Vec2 } from './math/Vec2';
17
+ import Vec3 from './math/Vec3';
18
18
  import { EditorEventType } from './types';
19
+ export class ViewportTransform extends Command {
20
+ }
19
21
  export class Viewport {
20
22
  constructor(notifier) {
21
23
  this.notifier = notifier;
@@ -35,14 +37,19 @@ export class Viewport {
35
37
  canvasToScreen(canvasPoint) {
36
38
  return this.transform.transformVec2(canvasPoint);
37
39
  }
38
- // Updates the transformation directly. Using ViewportTransform is preferred.
40
+ static transformBy(transform) {
41
+ return new Viewport.ViewportTransform(transform);
42
+ }
43
+ // Updates the transformation directly. Using transformBy is preferred.
39
44
  // [newTransform] should map from canvas coordinates to screen coordinates.
40
45
  resetTransform(newTransform = Mat33.identity) {
46
+ const oldTransform = this.transform;
41
47
  this.transform = newTransform;
42
48
  this.inverseTransform = newTransform.inverse();
43
49
  this.notifier.dispatch(EditorEventType.ViewportChanged, {
44
50
  kind: EditorEventType.ViewportChanged,
45
51
  newTransform,
52
+ oldTransform,
46
53
  });
47
54
  }
48
55
  get screenToCanvasTransform() {
@@ -130,7 +137,7 @@ export class Viewport {
130
137
  }
131
138
  }
132
139
  // Command that translates/scales the viewport.
133
- Viewport.ViewportTransform = (_a = class extends Command {
140
+ Viewport.ViewportTransform = (_a = class extends ViewportTransform {
134
141
  constructor(transform) {
135
142
  super();
136
143
  this.transform = transform;
@@ -147,13 +154,13 @@ Viewport.ViewportTransform = (_a = class extends Command {
147
154
  viewport.resetTransform(viewport.transform.rightMul(__classPrivateFieldGet(this, _inverseTransform, "f")));
148
155
  editor.queueRerender();
149
156
  }
150
- description(localizationTable) {
157
+ description(editor, localizationTable) {
151
158
  const result = [];
152
159
  // Describe the transformation's affect on the viewport (note that transformation transforms
153
160
  // the **elements** within the viewport). Assumes the transformation only does rotation/scale/translation.
154
- const origVec = Vec2.unitX;
161
+ const origVec = editor.viewport.visibleRect.center;
155
162
  const linearTransformedVec = this.transform.transformVec3(Vec2.unitX);
156
- const affineTransformedVec = this.transform.transformVec2(Vec2.unitX);
163
+ const affineTransformedVec = this.transform.transformVec2(origVec);
157
164
  const scale = linearTransformedVec.magnitude();
158
165
  const rotation = 180 / Math.PI * linearTransformedVec.angle();
159
166
  const translation = affineTransformedVec.minus(origVec);
@@ -173,7 +180,7 @@ Viewport.ViewportTransform = (_a = class extends Command {
173
180
  else if (translation.x < -minTranslation) {
174
181
  result.push(localizationTable.movedRight);
175
182
  }
176
- if (translation.y < minTranslation) {
183
+ if (translation.y < -minTranslation) {
177
184
  result.push(localizationTable.movedDown);
178
185
  }
179
186
  else if (translation.y > minTranslation) {
@@ -1,4 +1,5 @@
1
1
  import '../styles';
2
2
  import Editor from '../Editor';
3
+ import getLocalizationTable from '../localizations/getLocalizationTable';
3
4
  export default Editor;
4
- export { Editor };
5
+ export { Editor, getLocalizationTable };
@@ -1,5 +1,6 @@
1
1
  // Main entrypoint for Webpack when building a bundle for release.
2
2
  import '../styles';
3
3
  import Editor from '../Editor';
4
+ import getLocalizationTable from '../localizations/getLocalizationTable';
4
5
  export default Editor;
5
- export { Editor };
6
+ export { Editor, getLocalizationTable };
@@ -4,10 +4,10 @@ export declare abstract class Command {
4
4
  abstract apply(editor: Editor): void;
5
5
  abstract unapply(editor: Editor): void;
6
6
  onDrop(_editor: Editor): void;
7
- abstract description(localizationTable: EditorLocalization): string;
7
+ abstract description(editor: Editor, localizationTable: EditorLocalization): string;
8
8
  static union(a: Command, b: Command): Command;
9
9
  static readonly empty: {
10
- description(_localizationTable: EditorLocalization): string;
10
+ description(_editor: Editor, _localizationTable: EditorLocalization): string;
11
11
  apply(_editor: Editor): void;
12
12
  unapply(_editor: Editor): void;
13
13
  onDrop(_editor: Editor): void;
@@ -11,9 +11,9 @@ export class Command {
11
11
  b.unapply(editor);
12
12
  a.unapply(editor);
13
13
  }
14
- description(localizationTable) {
15
- const aDescription = a.description(localizationTable);
16
- const bDescription = b.description(localizationTable);
14
+ description(editor, localizationTable) {
15
+ const aDescription = a.description(editor, localizationTable);
16
+ const bDescription = b.description(editor, localizationTable);
17
17
  if (aDescription === bDescription) {
18
18
  return aDescription;
19
19
  }
@@ -23,7 +23,7 @@ export class Command {
23
23
  }
24
24
  }
25
25
  Command.empty = new class extends Command {
26
- description(_localizationTable) { return ''; }
26
+ description(_editor, _localizationTable) { return ''; }
27
27
  apply(_editor) { }
28
28
  unapply(_editor) { }
29
29
  };
@@ -9,6 +9,6 @@ export default class Duplicate extends SerializableCommand {
9
9
  constructor(toDuplicate: AbstractComponent[]);
10
10
  apply(editor: Editor): void;
11
11
  unapply(editor: Editor): void;
12
- description(localizationTable: EditorLocalization): string;
12
+ description(_editor: Editor, localizationTable: EditorLocalization): string;
13
13
  protected serializeToString(): string;
14
14
  }
@@ -14,7 +14,7 @@ export default class Duplicate extends SerializableCommand {
14
14
  unapply(editor) {
15
15
  this.reverse.apply(editor);
16
16
  }
17
- description(localizationTable) {
17
+ description(_editor, localizationTable) {
18
18
  var _a;
19
19
  if (this.duplicates.length === 0) {
20
20
  return localizationTable.duplicatedNoElements;
@@ -9,6 +9,6 @@ export default class Erase extends SerializableCommand {
9
9
  apply(editor: Editor): void;
10
10
  unapply(editor: Editor): void;
11
11
  onDrop(editor: Editor): void;
12
- description(localizationTable: EditorLocalization): string;
12
+ description(_editor: Editor, localizationTable: EditorLocalization): string;
13
13
  protected serializeToString(): string;
14
14
  }
@@ -34,7 +34,7 @@ export default class Erase extends SerializableCommand {
34
34
  }
35
35
  }
36
36
  }
37
- description(localizationTable) {
37
+ description(_editor, localizationTable) {
38
38
  var _a;
39
39
  if (this.toRemove.length === 0) {
40
40
  return localizationTable.erasedNoElements;
@@ -1,4 +1,4 @@
1
- import Rect2 from '../geometry/Rect2';
1
+ import Rect2 from '../math/Rect2';
2
2
  export interface CommandLocalization {
3
3
  movedLeft: string;
4
4
  movedUp: string;
@@ -1,7 +1,7 @@
1
1
  import Command from '../commands/Command';
2
- import LineSegment2 from '../geometry/LineSegment2';
3
- import Mat33 from '../geometry/Mat33';
4
- import Rect2 from '../geometry/Rect2';
2
+ import LineSegment2 from '../math/LineSegment2';
3
+ import Mat33 from '../math/Mat33';
4
+ import Rect2 from '../math/Rect2';
5
5
  import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
6
6
  import { ImageComponentLocalization } from './localization';
7
7
  declare type LoadSaveData = (string[] | Record<symbol, string | number>);
@@ -1,7 +1,7 @@
1
1
  var _a;
2
2
  import SerializableCommand from '../commands/SerializableCommand';
3
3
  import EditorImage from '../EditorImage';
4
- import Mat33 from '../geometry/Mat33';
4
+ import Mat33 from '../math/Mat33';
5
5
  export default class AbstractComponent {
6
6
  constructor(
7
7
  // A unique identifier for the type of component
@@ -132,7 +132,7 @@ AbstractComponent.TransformElementCommand = (_a = class extends SerializableComm
132
132
  this.updateTransform(editor, this.affineTransfm.inverse());
133
133
  editor.queueRerender();
134
134
  }
135
- description(localizationTable) {
135
+ description(_editor, localizationTable) {
136
136
  return localizationTable.transformedElements(1);
137
137
  }
138
138
  serializeToString() {
@@ -1,6 +1,6 @@
1
- import LineSegment2 from '../geometry/LineSegment2';
2
- import Mat33 from '../geometry/Mat33';
3
- import Rect2 from '../geometry/Rect2';
1
+ import LineSegment2 from '../math/LineSegment2';
2
+ import Mat33 from '../math/Mat33';
3
+ import Rect2 from '../math/Rect2';
4
4
  import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
5
5
  import AbstractComponent from './AbstractComponent';
6
6
  import { ImageComponentLocalization } from './localization';
@@ -1,4 +1,4 @@
1
- import Rect2 from '../geometry/Rect2';
1
+ import Rect2 from '../math/Rect2';
2
2
  import SVGRenderer from '../rendering/renderers/SVGRenderer';
3
3
  import AbstractComponent from './AbstractComponent';
4
4
  const componentKind = 'svg-global-attributes';
@@ -1,7 +1,7 @@
1
- import LineSegment2 from '../geometry/LineSegment2';
2
- import Mat33 from '../geometry/Mat33';
3
- import Path from '../geometry/Path';
4
- import Rect2 from '../geometry/Rect2';
1
+ import LineSegment2 from '../math/LineSegment2';
2
+ import Mat33 from '../math/Mat33';
3
+ import Path from '../math/Path';
4
+ import Rect2 from '../math/Rect2';
5
5
  import AbstractRenderer, { RenderablePathSpec } from '../rendering/renderers/AbstractRenderer';
6
6
  import AbstractComponent from './AbstractComponent';
7
7
  import { ImageComponentLocalization } from './localization';
@@ -1,5 +1,5 @@
1
- import Path from '../geometry/Path';
2
- import Rect2 from '../geometry/Rect2';
1
+ import Path from '../math/Path';
2
+ import Rect2 from '../math/Rect2';
3
3
  import { styleFromJSON, styleToJSON } from '../rendering/RenderingStyle';
4
4
  import AbstractComponent from './AbstractComponent';
5
5
  export default class Stroke extends AbstractComponent {
@@ -1,6 +1,6 @@
1
- import LineSegment2 from '../geometry/LineSegment2';
2
- import Mat33 from '../geometry/Mat33';
3
- import Rect2 from '../geometry/Rect2';
1
+ import LineSegment2 from '../math/LineSegment2';
2
+ import Mat33 from '../math/Mat33';
3
+ import Rect2 from '../math/Rect2';
4
4
  import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
5
5
  import RenderingStyle from '../rendering/RenderingStyle';
6
6
  import AbstractComponent from './AbstractComponent';
@@ -1,6 +1,6 @@
1
- import LineSegment2 from '../geometry/LineSegment2';
2
- import Mat33 from '../geometry/Mat33';
3
- import Rect2 from '../geometry/Rect2';
1
+ import LineSegment2 from '../math/LineSegment2';
2
+ import Mat33 from '../math/Mat33';
3
+ import Rect2 from '../math/Rect2';
4
4
  import { styleFromJSON, styleToJSON } from '../rendering/RenderingStyle';
5
5
  import AbstractComponent from './AbstractComponent';
6
6
  const componentTypeId = 'text';