js-draw 0.18.2 → 0.20.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 (269) hide show
  1. package/.eslintrc.js +1 -0
  2. package/CHANGELOG.md +10 -0
  3. package/dist/bundle.js +2 -2
  4. package/dist/bundledStyles.js +1 -0
  5. package/dist/cjs/src/Color4.d.ts +8 -0
  6. package/dist/cjs/src/Color4.js +67 -0
  7. package/dist/cjs/src/Editor.d.ts +2 -2
  8. package/dist/cjs/src/Editor.js +7 -7
  9. package/dist/cjs/src/SVGLoader.js +77 -12
  10. package/dist/cjs/src/Viewport.d.ts +2 -0
  11. package/dist/cjs/src/Viewport.js +6 -2
  12. package/dist/cjs/src/components/AbstractComponent.d.ts +2 -2
  13. package/dist/cjs/src/components/AbstractComponent.js +3 -3
  14. package/dist/cjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
  15. package/dist/cjs/src/components/BackgroundComponent.js +309 -0
  16. package/dist/cjs/src/components/RestylableComponent.d.ts +21 -2
  17. package/dist/cjs/src/components/Stroke.d.ts +35 -0
  18. package/dist/cjs/src/components/Stroke.js +37 -3
  19. package/dist/cjs/src/components/TextComponent.d.ts +27 -17
  20. package/dist/cjs/src/components/TextComponent.js +23 -1
  21. package/dist/cjs/src/components/lib.d.ts +4 -3
  22. package/dist/cjs/src/components/lib.js +2 -2
  23. package/dist/cjs/src/components/util/StrokeSmoother.js +25 -15
  24. package/dist/cjs/src/lib.d.ts +30 -0
  25. package/dist/cjs/src/lib.js +30 -0
  26. package/dist/cjs/src/localizations/de.js +1 -1
  27. package/dist/cjs/src/localizations/es.js +1 -1
  28. package/dist/cjs/src/math/Path.js +1 -1
  29. package/dist/cjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
  30. package/dist/cjs/src/math/polynomial/QuadraticBezier.js +115 -0
  31. package/dist/cjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
  32. package/dist/cjs/src/math/polynomial/solveQuadratic.js +36 -0
  33. package/dist/cjs/src/rendering/RenderingStyle.d.ts +4 -4
  34. package/dist/cjs/src/rendering/TextRenderingStyle.d.ts +10 -10
  35. package/dist/cjs/src/rendering/lib.d.ts +2 -0
  36. package/dist/cjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
  37. package/dist/cjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
  38. package/dist/cjs/src/rendering/renderers/CanvasRenderer.js +5 -3
  39. package/dist/cjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
  40. package/dist/cjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
  41. package/dist/cjs/src/rendering/renderers/SVGRenderer.js +15 -6
  42. package/dist/cjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
  43. package/dist/cjs/src/toolbar/IconProvider.d.ts +2 -2
  44. package/dist/cjs/src/toolbar/localization.d.ts +2 -1
  45. package/dist/cjs/src/toolbar/localization.js +3 -2
  46. package/dist/cjs/src/toolbar/widgets/BaseWidget.js +1 -1
  47. package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
  48. package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.js +77 -2
  49. package/dist/cjs/src/toolbar/widgets/PenToolWidget.js +1 -1
  50. package/dist/cjs/src/tools/FindTool.js +1 -1
  51. package/dist/cjs/src/tools/SoundUITool.d.ts +24 -0
  52. package/dist/cjs/src/tools/SoundUITool.js +164 -0
  53. package/dist/cjs/src/tools/TextTool.d.ts +2 -2
  54. package/dist/cjs/src/tools/ToolController.js +6 -1
  55. package/dist/cjs/src/tools/lib.d.ts +1 -0
  56. package/dist/cjs/src/tools/lib.js +3 -1
  57. package/dist/cjs/src/tools/localization.d.ts +3 -0
  58. package/dist/cjs/src/tools/localization.js +3 -0
  59. package/dist/mjs/src/Color4.d.ts +8 -0
  60. package/dist/mjs/src/Color4.mjs +64 -0
  61. package/dist/mjs/src/Editor.d.ts +2 -2
  62. package/dist/mjs/src/Editor.mjs +6 -6
  63. package/dist/mjs/src/SVGLoader.mjs +76 -11
  64. package/dist/mjs/src/Viewport.d.ts +2 -0
  65. package/dist/mjs/src/Viewport.mjs +6 -2
  66. package/dist/mjs/src/components/AbstractComponent.d.ts +2 -2
  67. package/dist/mjs/src/components/AbstractComponent.mjs +3 -3
  68. package/dist/mjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
  69. package/dist/mjs/src/components/BackgroundComponent.mjs +279 -0
  70. package/dist/mjs/src/components/RestylableComponent.d.ts +21 -2
  71. package/dist/mjs/src/components/Stroke.d.ts +35 -0
  72. package/dist/mjs/src/components/Stroke.mjs +37 -3
  73. package/dist/mjs/src/components/TextComponent.d.ts +27 -17
  74. package/dist/mjs/src/components/TextComponent.mjs +23 -1
  75. package/dist/mjs/src/components/lib.d.ts +4 -3
  76. package/dist/mjs/src/components/lib.mjs +2 -2
  77. package/dist/mjs/src/components/util/StrokeSmoother.mjs +25 -15
  78. package/dist/mjs/src/lib.d.ts +30 -0
  79. package/dist/mjs/src/lib.mjs +30 -0
  80. package/dist/mjs/src/localizations/de.mjs +1 -1
  81. package/dist/mjs/src/localizations/es.mjs +1 -1
  82. package/dist/mjs/src/math/Path.mjs +1 -1
  83. package/dist/mjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
  84. package/dist/mjs/src/math/polynomial/QuadraticBezier.mjs +109 -0
  85. package/dist/mjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
  86. package/dist/mjs/src/math/polynomial/solveQuadratic.mjs +34 -0
  87. package/dist/mjs/src/rendering/RenderingStyle.d.ts +4 -4
  88. package/dist/mjs/src/rendering/TextRenderingStyle.d.ts +10 -10
  89. package/dist/mjs/src/rendering/lib.d.ts +2 -0
  90. package/dist/mjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
  91. package/dist/mjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
  92. package/dist/mjs/src/rendering/renderers/CanvasRenderer.mjs +5 -3
  93. package/dist/mjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
  94. package/dist/mjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
  95. package/dist/mjs/src/rendering/renderers/SVGRenderer.mjs +15 -6
  96. package/dist/mjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
  97. package/dist/mjs/src/toolbar/IconProvider.d.ts +2 -2
  98. package/dist/mjs/src/toolbar/localization.d.ts +2 -1
  99. package/dist/mjs/src/toolbar/localization.mjs +3 -2
  100. package/dist/mjs/src/toolbar/widgets/BaseWidget.mjs +1 -1
  101. package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
  102. package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.mjs +54 -2
  103. package/dist/mjs/src/toolbar/widgets/PenToolWidget.mjs +1 -1
  104. package/dist/mjs/src/tools/FindTool.mjs +1 -1
  105. package/dist/mjs/src/tools/SoundUITool.d.ts +24 -0
  106. package/dist/mjs/src/tools/SoundUITool.mjs +158 -0
  107. package/dist/mjs/src/tools/TextTool.d.ts +2 -2
  108. package/dist/mjs/src/tools/ToolController.mjs +6 -1
  109. package/dist/mjs/src/tools/lib.d.ts +1 -0
  110. package/dist/mjs/src/tools/lib.mjs +1 -0
  111. package/dist/mjs/src/tools/localization.d.ts +3 -0
  112. package/dist/mjs/src/tools/localization.mjs +3 -0
  113. package/jest.config.js +1 -1
  114. package/package.json +19 -17
  115. package/src/Editor.css +2 -2
  116. package/src/tools/SoundUITool.css +15 -0
  117. package/src/tools/tools.css +4 -0
  118. package/dist/cjs/src/components/ImageBackground.js +0 -146
  119. package/dist/mjs/src/components/ImageBackground.mjs +0 -139
  120. package/src/Color4.test.ts +0 -40
  121. package/src/Color4.ts +0 -236
  122. package/src/Editor.loadFrom.test.ts +0 -24
  123. package/src/Editor.toSVG.test.ts +0 -111
  124. package/src/Editor.ts +0 -1122
  125. package/src/EditorImage.test.ts +0 -120
  126. package/src/EditorImage.ts +0 -603
  127. package/src/EventDispatcher.test.ts +0 -123
  128. package/src/EventDispatcher.ts +0 -71
  129. package/src/Pointer.ts +0 -127
  130. package/src/SVGLoader.test.ts +0 -114
  131. package/src/SVGLoader.ts +0 -511
  132. package/src/UndoRedoHistory.test.ts +0 -33
  133. package/src/UndoRedoHistory.ts +0 -102
  134. package/src/Viewport.ts +0 -319
  135. package/src/bundle/bundled.ts +0 -7
  136. package/src/commands/Command.ts +0 -45
  137. package/src/commands/Duplicate.ts +0 -48
  138. package/src/commands/Erase.ts +0 -74
  139. package/src/commands/SerializableCommand.ts +0 -49
  140. package/src/commands/UnresolvedCommand.ts +0 -37
  141. package/src/commands/invertCommand.ts +0 -51
  142. package/src/commands/lib.ts +0 -16
  143. package/src/commands/localization.ts +0 -47
  144. package/src/commands/uniteCommands.test.ts +0 -23
  145. package/src/commands/uniteCommands.ts +0 -135
  146. package/src/components/AbstractComponent.transformBy.test.ts +0 -22
  147. package/src/components/AbstractComponent.ts +0 -364
  148. package/src/components/ImageBackground.test.ts +0 -35
  149. package/src/components/ImageBackground.ts +0 -176
  150. package/src/components/ImageComponent.ts +0 -171
  151. package/src/components/RestylableComponent.ts +0 -142
  152. package/src/components/SVGGlobalAttributesObject.ts +0 -81
  153. package/src/components/Stroke.test.ts +0 -139
  154. package/src/components/Stroke.ts +0 -245
  155. package/src/components/TextComponent.test.ts +0 -99
  156. package/src/components/TextComponent.ts +0 -315
  157. package/src/components/UnknownSVGObject.test.ts +0 -10
  158. package/src/components/UnknownSVGObject.ts +0 -60
  159. package/src/components/builders/ArrowBuilder.ts +0 -107
  160. package/src/components/builders/FreehandLineBuilder.ts +0 -212
  161. package/src/components/builders/LineBuilder.ts +0 -77
  162. package/src/components/builders/PressureSensitiveFreehandLineBuilder.ts +0 -454
  163. package/src/components/builders/RectangleBuilder.ts +0 -74
  164. package/src/components/builders/types.ts +0 -15
  165. package/src/components/lib.ts +0 -25
  166. package/src/components/localization.ts +0 -22
  167. package/src/components/util/StrokeSmoother.ts +0 -293
  168. package/src/components/util/describeComponentList.ts +0 -18
  169. package/src/lib.ts +0 -37
  170. package/src/localization.ts +0 -34
  171. package/src/localizations/de.ts +0 -98
  172. package/src/localizations/en.ts +0 -8
  173. package/src/localizations/es.ts +0 -74
  174. package/src/localizations/getLocalizationTable.test.ts +0 -27
  175. package/src/localizations/getLocalizationTable.ts +0 -55
  176. package/src/math/LineSegment2.test.ts +0 -99
  177. package/src/math/LineSegment2.ts +0 -160
  178. package/src/math/Mat33.test.ts +0 -244
  179. package/src/math/Mat33.ts +0 -437
  180. package/src/math/Path.fromString.test.ts +0 -223
  181. package/src/math/Path.test.ts +0 -198
  182. package/src/math/Path.toString.test.ts +0 -77
  183. package/src/math/Path.ts +0 -790
  184. package/src/math/Rect2.test.ts +0 -204
  185. package/src/math/Rect2.ts +0 -315
  186. package/src/math/Triangle.ts +0 -29
  187. package/src/math/Vec2.test.ts +0 -30
  188. package/src/math/Vec2.ts +0 -18
  189. package/src/math/Vec3.test.ts +0 -44
  190. package/src/math/Vec3.ts +0 -218
  191. package/src/math/lib.ts +0 -15
  192. package/src/math/rounding.test.ts +0 -65
  193. package/src/math/rounding.ts +0 -156
  194. package/src/rendering/Display.ts +0 -249
  195. package/src/rendering/RenderingStyle.test.ts +0 -68
  196. package/src/rendering/RenderingStyle.ts +0 -55
  197. package/src/rendering/TextRenderingStyle.ts +0 -45
  198. package/src/rendering/caching/CacheRecord.test.ts +0 -49
  199. package/src/rendering/caching/CacheRecord.ts +0 -77
  200. package/src/rendering/caching/CacheRecordManager.ts +0 -71
  201. package/src/rendering/caching/RenderingCache.test.ts +0 -44
  202. package/src/rendering/caching/RenderingCache.ts +0 -66
  203. package/src/rendering/caching/RenderingCacheNode.ts +0 -405
  204. package/src/rendering/caching/testUtils.ts +0 -35
  205. package/src/rendering/caching/types.ts +0 -34
  206. package/src/rendering/lib.ts +0 -6
  207. package/src/rendering/localization.ts +0 -20
  208. package/src/rendering/renderers/AbstractRenderer.ts +0 -222
  209. package/src/rendering/renderers/CanvasRenderer.ts +0 -296
  210. package/src/rendering/renderers/DummyRenderer.test.ts +0 -42
  211. package/src/rendering/renderers/DummyRenderer.ts +0 -136
  212. package/src/rendering/renderers/SVGRenderer.ts +0 -354
  213. package/src/rendering/renderers/TextOnlyRenderer.ts +0 -70
  214. package/src/testing/beforeEachFile.ts +0 -8
  215. package/src/testing/createEditor.ts +0 -11
  216. package/src/testing/global.d.ts +0 -17
  217. package/src/testing/lib.ts +0 -3
  218. package/src/testing/loadExpectExtensions.ts +0 -25
  219. package/src/testing/sendPenEvent.ts +0 -31
  220. package/src/testing/sendTouchEvent.ts +0 -78
  221. package/src/toolbar/HTMLToolbar.ts +0 -492
  222. package/src/toolbar/IconProvider.ts +0 -736
  223. package/src/toolbar/lib.ts +0 -4
  224. package/src/toolbar/localization.ts +0 -106
  225. package/src/toolbar/makeColorInput.ts +0 -145
  226. package/src/toolbar/types.ts +0 -5
  227. package/src/toolbar/widgets/ActionButtonWidget.ts +0 -39
  228. package/src/toolbar/widgets/BaseToolWidget.ts +0 -56
  229. package/src/toolbar/widgets/BaseWidget.ts +0 -377
  230. package/src/toolbar/widgets/DocumentPropertiesWidget.ts +0 -167
  231. package/src/toolbar/widgets/EraserToolWidget.ts +0 -85
  232. package/src/toolbar/widgets/HandToolWidget.ts +0 -250
  233. package/src/toolbar/widgets/InsertImageWidget.ts +0 -223
  234. package/src/toolbar/widgets/OverflowWidget.ts +0 -92
  235. package/src/toolbar/widgets/PenToolWidget.ts +0 -288
  236. package/src/toolbar/widgets/SelectionToolWidget.ts +0 -190
  237. package/src/toolbar/widgets/TextToolWidget.ts +0 -145
  238. package/src/toolbar/widgets/lib.ts +0 -13
  239. package/src/tools/BaseTool.ts +0 -76
  240. package/src/tools/Eraser.test.ts +0 -103
  241. package/src/tools/Eraser.ts +0 -139
  242. package/src/tools/FindTool.ts +0 -152
  243. package/src/tools/PanZoom.test.ts +0 -310
  244. package/src/tools/PanZoom.ts +0 -520
  245. package/src/tools/PasteHandler.ts +0 -95
  246. package/src/tools/Pen.test.ts +0 -194
  247. package/src/tools/Pen.ts +0 -226
  248. package/src/tools/PipetteTool.ts +0 -55
  249. package/src/tools/SelectionTool/SelectAllShortcutHandler.ts +0 -28
  250. package/src/tools/SelectionTool/Selection.ts +0 -607
  251. package/src/tools/SelectionTool/SelectionHandle.ts +0 -108
  252. package/src/tools/SelectionTool/SelectionTool.test.ts +0 -261
  253. package/src/tools/SelectionTool/SelectionTool.ts +0 -480
  254. package/src/tools/SelectionTool/TransformMode.ts +0 -114
  255. package/src/tools/SelectionTool/types.ts +0 -11
  256. package/src/tools/TextTool.ts +0 -326
  257. package/src/tools/ToolController.ts +0 -178
  258. package/src/tools/ToolEnabledGroup.ts +0 -14
  259. package/src/tools/ToolSwitcherShortcut.ts +0 -39
  260. package/src/tools/ToolbarShortcutHandler.ts +0 -34
  261. package/src/tools/UndoRedoShortcut.test.ts +0 -56
  262. package/src/tools/UndoRedoShortcut.ts +0 -25
  263. package/src/tools/lib.ts +0 -21
  264. package/src/tools/localization.ts +0 -66
  265. package/src/types.ts +0 -234
  266. package/src/util/assertions.ts +0 -55
  267. package/src/util/fileToBase64.ts +0 -18
  268. package/src/util/untilNextAnimationFrame.ts +0 -9
  269. package/src/util/waitForTimeout.ts +0 -9
@@ -1,288 +0,0 @@
1
- import { makeArrowBuilder } from '../../components/builders/ArrowBuilder';
2
- import { makeFreehandLineBuilder } from '../../components/builders/FreehandLineBuilder';
3
- import { makePressureSensitiveFreehandLineBuilder } from '../../components/builders/PressureSensitiveFreehandLineBuilder';
4
- import { makeLineBuilder } from '../../components/builders/LineBuilder';
5
- import { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from '../../components/builders/RectangleBuilder';
6
- import { ComponentBuilderFactory } from '../../components/builders/types';
7
- import Editor from '../../Editor';
8
- import Pen from '../../tools/Pen';
9
- import { EditorEventType, KeyPressEvent } from '../../types';
10
- import { toolbarCSSPrefix } from '../HTMLToolbar';
11
- import { ToolbarLocalization } from '../localization';
12
- import makeColorInput from '../makeColorInput';
13
- import BaseToolWidget from './BaseToolWidget';
14
- import Color4 from '../../Color4';
15
- import { SavedToolbuttonState } from './BaseWidget';
16
-
17
-
18
- export interface PenTypeRecord {
19
- // Description of the factory (e.g. 'Freehand line')
20
- name: string;
21
-
22
- // A unique ID for the facotory (e.g. 'chisel-tip-pen')
23
- id: string;
24
-
25
- // Creates an `AbstractComponent` from pen input.
26
- factory: ComponentBuilderFactory;
27
- }
28
-
29
- export default class PenToolWidget extends BaseToolWidget {
30
- private updateInputs: ()=> void = () => {};
31
- protected penTypes: PenTypeRecord[];
32
-
33
- public constructor(
34
- editor: Editor, private tool: Pen, localization?: ToolbarLocalization
35
- ) {
36
- super(editor, tool, 'pen', localization);
37
-
38
- // Default pen types
39
- this.penTypes = [
40
- {
41
- name: this.localizationTable.pressureSensitiveFreehandPen,
42
- id: 'pressure-sensitive-pen',
43
-
44
- factory: makePressureSensitiveFreehandLineBuilder,
45
- },
46
- {
47
- name: this.localizationTable.freehandPen,
48
- id: 'freehand-pen',
49
-
50
- factory: makeFreehandLineBuilder,
51
- },
52
- {
53
- name: this.localizationTable.arrowPen,
54
- id: 'arrow',
55
-
56
- factory: makeArrowBuilder,
57
- },
58
- {
59
- name: this.localizationTable.linePen,
60
- id: 'line',
61
-
62
- factory: makeLineBuilder,
63
- },
64
- {
65
- name: this.localizationTable.filledRectanglePen,
66
- id: 'filled-rectangle',
67
-
68
- factory: makeFilledRectangleBuilder,
69
- },
70
- {
71
- name: this.localizationTable.outlinedRectanglePen,
72
- id: 'outlined-rectangle',
73
-
74
- factory: makeOutlinedRectangleBuilder,
75
- },
76
- ];
77
-
78
- this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
79
- if (toolEvt.kind !== EditorEventType.ToolUpdated) {
80
- throw new Error('Invalid event type!');
81
- }
82
-
83
- // The button icon may depend on tool properties.
84
- if (toolEvt.tool === this.tool) {
85
- this.updateIcon();
86
- this.updateInputs();
87
- }
88
- });
89
- }
90
-
91
- protected getTitle(): string {
92
- return this.targetTool.description;
93
- }
94
-
95
- // Return the index of this tool's stroke factory in the list of
96
- // all stroke factories.
97
- //
98
- // Returns -1 if the stroke factory is not in the list of all stroke factories.
99
- private getCurrentPenTypeIdx(): number {
100
- const currentFactory = this.tool.getStrokeFactory();
101
-
102
- for (let i = 0; i < this.penTypes.length; i ++) {
103
- if (this.penTypes[i].factory === currentFactory) {
104
- return i;
105
- }
106
- }
107
- return -1;
108
- }
109
-
110
- private getCurrentPenType(): PenTypeRecord|null {
111
- for (const penType of this.penTypes) {
112
- if (penType.factory === this.tool.getStrokeFactory()) {
113
- return penType;
114
- }
115
- }
116
- return null;
117
- }
118
-
119
- protected createIcon(): Element {
120
- const strokeFactory = this.tool.getStrokeFactory();
121
- if (strokeFactory === makeFreehandLineBuilder || strokeFactory === makePressureSensitiveFreehandLineBuilder) {
122
- // Use a square-root scale to prevent the pen's tip from overflowing.
123
- const scale = Math.round(Math.sqrt(this.tool.getThickness()) * 4);
124
- const color = this.tool.getColor();
125
- const roundedTip = strokeFactory === makeFreehandLineBuilder;
126
-
127
- return this.editor.icons.makePenIcon(scale, color.toHexString(), roundedTip);
128
- } else {
129
- const strokeFactory = this.tool.getStrokeFactory();
130
- return this.editor.icons.makeIconFromFactory(this.tool, strokeFactory);
131
- }
132
- }
133
-
134
- private static idCounter: number = 0;
135
- protected fillDropdown(dropdown: HTMLElement): boolean {
136
- const container = document.createElement('div');
137
- container.classList.add(`${toolbarCSSPrefix}spacedList`);
138
-
139
- const thicknessRow = document.createElement('div');
140
- const objectTypeRow = document.createElement('div');
141
-
142
- // Thickness: Value of the input is squared to allow for finer control/larger values.
143
- const thicknessLabel = document.createElement('label');
144
- const thicknessInput = document.createElement('input');
145
- const objectSelectLabel = document.createElement('label');
146
- const objectTypeSelect = document.createElement('select');
147
-
148
- // Give inputs IDs so we can label them with a <label for=...>Label text</label>
149
- thicknessInput.id = `${toolbarCSSPrefix}penThicknessInput${PenToolWidget.idCounter++}`;
150
- objectTypeSelect.id = `${toolbarCSSPrefix}penBuilderSelect${PenToolWidget.idCounter++}`;
151
-
152
- thicknessLabel.innerText = this.localizationTable.thicknessLabel;
153
- thicknessLabel.setAttribute('for', thicknessInput.id);
154
- objectSelectLabel.innerText = this.localizationTable.selectObjectType;
155
- objectSelectLabel.setAttribute('for', objectTypeSelect.id);
156
-
157
- // Use a logarithmic scale for thicknessInput (finer control over thinner strokewidths.)
158
- const inverseThicknessInputFn = (t: number) => Math.log10(t);
159
- const thicknessInputFn = (t: number) => 10**t;
160
-
161
- thicknessInput.type = 'range';
162
- thicknessInput.min = `${inverseThicknessInputFn(2)}`;
163
- thicknessInput.max = `${inverseThicknessInputFn(400)}`;
164
- thicknessInput.step = '0.1';
165
- thicknessInput.oninput = () => {
166
- this.tool.setThickness(thicknessInputFn(parseFloat(thicknessInput.value)));
167
- };
168
- thicknessRow.appendChild(thicknessLabel);
169
- thicknessRow.appendChild(thicknessInput);
170
-
171
- objectTypeSelect.oninput = () => {
172
- const penTypeIdx = parseInt(objectTypeSelect.value);
173
- if (penTypeIdx < 0 || penTypeIdx >= this.penTypes.length) {
174
- console.error('Invalid pen type index', penTypeIdx);
175
- return;
176
- }
177
-
178
- this.tool.setStrokeFactory(this.penTypes[penTypeIdx].factory);
179
- };
180
- objectTypeRow.appendChild(objectSelectLabel);
181
- objectTypeRow.appendChild(objectTypeSelect);
182
-
183
- const colorRow = document.createElement('div');
184
- const colorLabel = document.createElement('label');
185
- const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
186
- this.tool.setColor(color);
187
- });
188
-
189
- colorInput.id = `${toolbarCSSPrefix}colorInput${PenToolWidget.idCounter++}`;
190
- colorLabel.innerText = this.localizationTable.colorLabel;
191
- colorLabel.setAttribute('for', colorInput.id);
192
-
193
- colorRow.appendChild(colorLabel);
194
- colorRow.appendChild(colorInputContainer);
195
-
196
- this.updateInputs = () => {
197
- setColorInputValue(this.tool.getColor());
198
- thicknessInput.value = inverseThicknessInputFn(this.tool.getThickness()).toString();
199
-
200
- // Update the list of stroke factories
201
- objectTypeSelect.replaceChildren();
202
- for (let i = 0; i < this.penTypes.length; i ++) {
203
- const penType = this.penTypes[i];
204
- const option = document.createElement('option');
205
- option.value = i.toString();
206
- option.innerText = penType.name;
207
-
208
- objectTypeSelect.appendChild(option);
209
- }
210
-
211
- // Update the selected stroke factory.
212
- const strokeFactoryIdx = this.getCurrentPenTypeIdx();
213
- if (strokeFactoryIdx === -1) {
214
- objectTypeSelect.value = '';
215
- } else {
216
- objectTypeSelect.value = strokeFactoryIdx.toString();
217
- }
218
- };
219
- this.updateInputs();
220
-
221
- container.replaceChildren(colorRow, thicknessRow, objectTypeRow);
222
- dropdown.replaceChildren(container);
223
- return true;
224
- }
225
-
226
- protected onKeyPress(event: KeyPressEvent): boolean {
227
- if (!this.isSelected()) {
228
- return false;
229
- }
230
-
231
- // Map alt+0-9 to different pen types.
232
- if (/^[0-9]$/.exec(event.key) && event.ctrlKey) {
233
- const penTypeIdx = parseInt(event.key) - 1;
234
- if (penTypeIdx >= 0 && penTypeIdx < this.penTypes.length) {
235
- this.tool.setStrokeFactory(this.penTypes[penTypeIdx].factory);
236
- return true;
237
- }
238
- }
239
-
240
- return false;
241
- }
242
-
243
- public serializeState(): SavedToolbuttonState {
244
- return {
245
- ...super.serializeState(),
246
-
247
- color: this.tool.getColor().toHexString(),
248
- thickness: this.tool.getThickness(),
249
- strokeFactoryId: this.getCurrentPenType()?.id,
250
- };
251
- }
252
-
253
- public deserializeFrom(state: SavedToolbuttonState) {
254
- super.deserializeFrom(state);
255
-
256
- const verifyPropertyType = (propertyName: string, expectedType: 'string'|'number'|'object') => {
257
- const actualType = typeof(state[propertyName]);
258
- if (actualType !== expectedType) {
259
- throw new Error(
260
- `Deserializing property ${propertyName}: Invalid type. Expected ${expectedType},` +
261
- ` was ${actualType}.`
262
- );
263
- }
264
- };
265
-
266
- if (state.color) {
267
- verifyPropertyType('color', 'string');
268
- this.tool.setColor(Color4.fromHex(state.color));
269
- }
270
-
271
- if (state.thickness) {
272
- verifyPropertyType('thickness', 'number');
273
- this.tool.setThickness(state.thickness);
274
- }
275
-
276
- if (state.strokeFactoryId) {
277
- verifyPropertyType('strokeFactoryId', 'string');
278
-
279
- const factoryId: string = state.strokeFactoryId;
280
- for (const penType of this.penTypes) {
281
- if (factoryId === penType.id) {
282
- this.tool.setStrokeFactory(penType.factory);
283
- break;
284
- }
285
- }
286
- }
287
- }
288
- }
@@ -1,190 +0,0 @@
1
- import Color4 from '../../Color4';
2
- import { isRestylableComponent } from '../../components/RestylableComponent';
3
- import Editor from '../../Editor';
4
- import uniteCommands from '../../commands/uniteCommands';
5
- import SelectionTool from '../../tools/SelectionTool/SelectionTool';
6
- import { EditorEventType, KeyPressEvent } from '../../types';
7
- import { ToolbarLocalization } from '../localization';
8
- import makeColorInput from '../makeColorInput';
9
- import ActionButtonWidget from './ActionButtonWidget';
10
- import BaseToolWidget from './BaseToolWidget';
11
- import BaseWidget from './BaseWidget';
12
-
13
- class RestyleSelectionWidget extends BaseWidget {
14
- private updateFormatData: ()=>void = () => {};
15
-
16
- public constructor(editor: Editor, private selectionTool: SelectionTool, localizationTable?: ToolbarLocalization) {
17
- super(editor, 'restyle-selection', localizationTable);
18
-
19
- // Allow showing the dropdown even if this widget isn't selected yet
20
- this.container.classList.add('dropdownShowable');
21
-
22
- this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
23
- if (toolEvt.kind !== EditorEventType.ToolUpdated) {
24
- throw new Error('Invalid event type!');
25
- }
26
-
27
- if (toolEvt.tool === this.selectionTool) {
28
- this.updateFormatData();
29
- }
30
- });
31
- }
32
-
33
- protected getTitle(): string {
34
- return this.localizationTable.reformatSelection;
35
- }
36
-
37
- protected createIcon(){
38
- return this.editor.icons.makeFormatSelectionIcon();
39
- }
40
-
41
- protected handleClick(): void {
42
- this.setDropdownVisible(!this.isDropdownVisible());
43
- }
44
-
45
- protected fillDropdown(dropdown: HTMLElement): boolean {
46
- const container = document.createElement('div');
47
- const colorRow = document.createElement('div');
48
- const colorLabel = document.createElement('label');
49
- const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
50
- const selection = this.selectionTool.getSelection();
51
-
52
- if (selection) {
53
- const updateStyleCommands = [];
54
-
55
- for (const elem of selection.getSelectedObjects()) {
56
- if (isRestylableComponent(elem)) {
57
- updateStyleCommands.push(elem.updateStyle({ color }));
58
- }
59
- }
60
-
61
- const unitedCommand = uniteCommands(updateStyleCommands);
62
- this.editor.dispatch(unitedCommand);
63
- }
64
- });
65
-
66
- colorLabel.innerText = this.localizationTable.colorLabel;
67
-
68
- this.updateFormatData = () => {
69
- const selection = this.selectionTool.getSelection();
70
- if (selection) {
71
- colorInput.disabled = false;
72
-
73
- const colors = [];
74
- for (const elem of selection.getSelectedObjects()) {
75
- if (isRestylableComponent(elem)) {
76
- const color = elem.getStyle().color;
77
- if (color) {
78
- colors.push(color);
79
- }
80
- }
81
- }
82
- setColorInputValue(Color4.average(colors));
83
- } else {
84
- colorInput.disabled = true;
85
- }
86
- };
87
-
88
- colorRow.replaceChildren(colorLabel, colorInputContainer);
89
- container.replaceChildren(colorRow);
90
- dropdown.replaceChildren(container);
91
- return true;
92
- }
93
- }
94
-
95
- export default class SelectionToolWidget extends BaseToolWidget {
96
- public constructor(
97
- editor: Editor, private tool: SelectionTool, localization?: ToolbarLocalization
98
- ) {
99
- super(editor, tool, 'selection-tool-widget', localization);
100
-
101
- const resizeButton = new ActionButtonWidget(
102
- editor, 'resize-btn',
103
- () => editor.icons.makeResizeViewportIcon(),
104
- this.localizationTable.resizeImageToSelection,
105
- () => {
106
- this.resizeImageToSelection();
107
- },
108
- localization,
109
- );
110
- const deleteButton = new ActionButtonWidget(
111
- editor, 'delete-btn',
112
- () => editor.icons.makeDeleteSelectionIcon(),
113
- this.localizationTable.deleteSelection,
114
- () => {
115
- const selection = this.tool.getSelection();
116
- this.editor.dispatch(selection!.deleteSelectedObjects());
117
- this.tool.clearSelection();
118
- },
119
- localization,
120
- );
121
- const duplicateButton = new ActionButtonWidget(
122
- editor, 'duplicate-btn',
123
- () => editor.icons.makeDuplicateSelectionIcon(),
124
- this.localizationTable.duplicateSelection,
125
- async () => {
126
- const selection = this.tool.getSelection();
127
- this.editor.dispatch(await selection!.duplicateSelectedObjects());
128
- },
129
- localization,
130
- );
131
- const restyleButton = new RestyleSelectionWidget(
132
- editor,
133
- this.tool,
134
- localization,
135
- );
136
-
137
- this.addSubWidget(resizeButton);
138
- this.addSubWidget(deleteButton);
139
- this.addSubWidget(duplicateButton);
140
- this.addSubWidget(restyleButton);
141
-
142
- const updateDisabled = (disabled: boolean) => {
143
- resizeButton.setDisabled(disabled);
144
- deleteButton.setDisabled(disabled);
145
- duplicateButton.setDisabled(disabled);
146
- restyleButton.setDisabled(disabled);
147
- };
148
- updateDisabled(true);
149
-
150
- // Enable/disable actions based on whether items are selected
151
- this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
152
- if (toolEvt.kind !== EditorEventType.ToolUpdated) {
153
- throw new Error('Invalid event type!');
154
- }
155
-
156
- if (toolEvt.tool === this.tool) {
157
- const selection = this.tool.getSelection();
158
- const hasSelection = selection && selection.getSelectedItemCount() > 0;
159
-
160
- updateDisabled(!hasSelection);
161
- }
162
- });
163
- }
164
-
165
- private resizeImageToSelection() {
166
- const selection = this.tool.getSelection();
167
- if (selection) {
168
- this.editor.dispatch(this.editor.setImportExportRect(selection.region));
169
- }
170
- }
171
-
172
- protected onKeyPress(event: KeyPressEvent): boolean {
173
- // Resize image to selection:
174
- // Other keys are handled directly by the selection tool.
175
- if (event.ctrlKey && event.key === 'r') {
176
- this.resizeImageToSelection();
177
- return true;
178
- }
179
-
180
- return false;
181
- }
182
-
183
- protected getTitle(): string {
184
- return this.localizationTable.select;
185
- }
186
-
187
- protected createIcon(): Element {
188
- return this.editor.icons.makeSelectionIcon();
189
- }
190
- }
@@ -1,145 +0,0 @@
1
- import Color4 from '../../Color4';
2
- import Editor from '../../Editor';
3
- import TextTool from '../../tools/TextTool';
4
- import { EditorEventType } from '../../types';
5
- import { toolbarCSSPrefix } from '../HTMLToolbar';
6
- import { ToolbarLocalization } from '../localization';
7
- import makeColorInput from '../makeColorInput';
8
- import BaseToolWidget from './BaseToolWidget';
9
- import { SavedToolbuttonState } from './BaseWidget';
10
-
11
- export default class TextToolWidget extends BaseToolWidget {
12
- private updateDropdownInputs: (()=>void)|null = null;
13
- public constructor(editor: Editor, private tool: TextTool, localization?: ToolbarLocalization) {
14
- super(editor, tool, 'text-tool-widget', localization);
15
-
16
- editor.notifier.on(EditorEventType.ToolUpdated, evt => {
17
- if (evt.kind === EditorEventType.ToolUpdated && evt.tool === tool) {
18
- this.updateIcon();
19
- this.updateDropdownInputs?.();
20
- }
21
- });
22
- }
23
-
24
- protected getTitle(): string {
25
- return this.targetTool.description;
26
- }
27
-
28
- protected createIcon(): Element {
29
- const textStyle = this.tool.getTextStyle();
30
- return this.editor.icons.makeTextIcon(textStyle);
31
- }
32
-
33
- private static idCounter: number = 0;
34
- protected fillDropdown(dropdown: HTMLElement): boolean {
35
- const container = document.createElement('div');
36
- container.classList.add(`${toolbarCSSPrefix}spacedList`);
37
- const fontRow = document.createElement('div');
38
- const colorRow = document.createElement('div');
39
- const sizeRow = document.createElement('div');
40
-
41
- const fontInput = document.createElement('select');
42
- const fontLabel = document.createElement('label');
43
-
44
- const sizeInput = document.createElement('input');
45
- const sizeLabel = document.createElement('label');
46
-
47
- const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
48
- this.tool.setColor(color);
49
- });
50
- const colorLabel = document.createElement('label');
51
-
52
- const fontsInInput = new Set();
53
- const addFontToInput = (fontName: string) => {
54
- const option = document.createElement('option');
55
- option.value = fontName;
56
- option.textContent = fontName;
57
- fontInput.appendChild(option);
58
- fontsInInput.add(fontName);
59
- };
60
-
61
- sizeInput.setAttribute('type', 'number');
62
- sizeInput.min = '1';
63
- sizeInput.max = '128';
64
-
65
- fontLabel.innerText = this.localizationTable.fontLabel;
66
- colorLabel.innerText = this.localizationTable.colorLabel;
67
- sizeLabel.innerText = this.localizationTable.textSize;
68
-
69
- colorInput.id = `${toolbarCSSPrefix}-text-color-input-${TextToolWidget.idCounter++}`;
70
- colorLabel.setAttribute('for', colorInput.id);
71
-
72
- sizeInput.id = `${toolbarCSSPrefix}-text-size-input-${TextToolWidget.idCounter++}`;
73
- sizeLabel.setAttribute('for', sizeInput.id);
74
-
75
- addFontToInput('monospace');
76
- addFontToInput('serif');
77
- addFontToInput('sans-serif');
78
- fontInput.id = `${toolbarCSSPrefix}-text-font-input-${TextToolWidget.idCounter++}`;
79
- fontLabel.setAttribute('for', fontInput.id);
80
-
81
- fontInput.onchange = () => {
82
- this.tool.setFontFamily(fontInput.value);
83
- };
84
-
85
- sizeInput.onchange = () => {
86
- const size = parseInt(sizeInput.value);
87
- if (!isNaN(size) && size > 0) {
88
- this.tool.setFontSize(size);
89
- }
90
- };
91
-
92
- colorRow.appendChild(colorLabel);
93
- colorRow.appendChild(colorInputContainer);
94
-
95
- fontRow.appendChild(fontLabel);
96
- fontRow.appendChild(fontInput);
97
-
98
- sizeRow.appendChild(sizeLabel);
99
- sizeRow.appendChild(sizeInput);
100
-
101
- this.updateDropdownInputs = () => {
102
- const style = this.tool.getTextStyle();
103
- setColorInputValue(style.renderingStyle.fill);
104
-
105
- if (!fontsInInput.has(style.fontFamily)) {
106
- addFontToInput(style.fontFamily);
107
- }
108
- fontInput.value = style.fontFamily;
109
- sizeInput.value = `${style.size}`;
110
- };
111
- this.updateDropdownInputs();
112
-
113
- container.replaceChildren(colorRow, sizeRow, fontRow);
114
- dropdown.appendChild(container);
115
- return true;
116
- }
117
-
118
- public serializeState(): SavedToolbuttonState {
119
- const textStyle = this.tool.getTextStyle();
120
-
121
- return {
122
- ...super.serializeState(),
123
-
124
- fontFamily: textStyle.fontFamily,
125
- textSize: textStyle.size,
126
- color: textStyle.renderingStyle.fill.toHexString(),
127
- };
128
- }
129
-
130
- public deserializeFrom(state: SavedToolbuttonState) {
131
- if (state.fontFamily && typeof(state.fontFamily) === 'string') {
132
- this.tool.setFontFamily(state.fontFamily);
133
- }
134
-
135
- if (state.color && typeof(state.color) === 'string') {
136
- this.tool.setColor(Color4.fromHex(state.color));
137
- }
138
-
139
- if (state.textSize && typeof(state.textSize) === 'number') {
140
- this.tool.setFontSize(state.textSize);
141
- }
142
-
143
- super.deserializeFrom(state);
144
- }
145
- }
@@ -1,13 +0,0 @@
1
-
2
- export { default as ActionButtonWidget } from './ActionButtonWidget';
3
- export { default as BaseToolWidget } from './BaseToolWidget';
4
- export { default as BaseWidget } from './BaseWidget';
5
-
6
- export { default as PenToolWidget } from './PenToolWidget';
7
- export { default as TextToolWidget } from './TextToolWidget';
8
- export { default as HandToolWidget } from './HandToolWidget';
9
- export { default as SelectionToolWidget } from './SelectionToolWidget';
10
- export { default as EraserToolWidget } from './EraserToolWidget';
11
-
12
- export { default as InsertImageWidget } from './InsertImageWidget';
13
- export { default as DocumentPropertiesWidget } from './DocumentPropertiesWidget';