js-draw 1.0.1 → 1.1.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 (197) hide show
  1. package/LICENSE +21 -0
  2. package/dist/Editor.css +1 -0
  3. package/dist/bundle.js +1 -1
  4. package/dist/bundledStyles.js +1 -1
  5. package/dist/cjs/toolbar/AbstractToolbar.d.ts +9 -13
  6. package/dist/cjs/toolbar/AbstractToolbar.js +14 -19
  7. package/dist/cjs/toolbar/widgets/SaveActionWidget.d.ts +10 -0
  8. package/dist/cjs/toolbar/widgets/SaveActionWidget.js +26 -0
  9. package/dist/cjs/toolbar/widgets/keybindings.d.ts +1 -0
  10. package/dist/cjs/toolbar/widgets/keybindings.js +4 -1
  11. package/dist/cjs/version.js +1 -1
  12. package/dist/mjs/toolbar/AbstractToolbar.d.ts +9 -13
  13. package/dist/mjs/toolbar/AbstractToolbar.mjs +14 -19
  14. package/dist/mjs/toolbar/widgets/SaveActionWidget.d.ts +10 -0
  15. package/dist/mjs/toolbar/widgets/SaveActionWidget.mjs +21 -0
  16. package/dist/mjs/toolbar/widgets/keybindings.d.ts +1 -0
  17. package/dist/mjs/toolbar/widgets/keybindings.mjs +3 -0
  18. package/dist/mjs/version.mjs +1 -1
  19. package/docs/img/readme-images/js-draw.jpg +0 -0
  20. package/docs/img/readme-images/unsupported-elements--in-editor.png +0 -0
  21. package/package.json +5 -4
  22. package/src/toolbar/EdgeToolbar.scss +1 -0
  23. package/dist-test/test_imports/package-lock.json +0 -13
  24. package/dist-test/test_imports/package.json +0 -12
  25. package/dist-test/test_imports/test-imports.js +0 -11
  26. package/dist-test/test_imports/test-require.cjs +0 -14
  27. package/src/Editor.loadFrom.test.ts +0 -24
  28. package/src/Editor.test.ts +0 -107
  29. package/src/Editor.toSVG.test.ts +0 -294
  30. package/src/Editor.ts +0 -1443
  31. package/src/EditorImage.test.ts +0 -117
  32. package/src/EditorImage.ts +0 -609
  33. package/src/EventDispatcher.test.ts +0 -123
  34. package/src/EventDispatcher.ts +0 -72
  35. package/src/Pointer.ts +0 -183
  36. package/src/SVGLoader.test.ts +0 -114
  37. package/src/SVGLoader.ts +0 -672
  38. package/src/UndoRedoHistory.test.ts +0 -34
  39. package/src/UndoRedoHistory.ts +0 -102
  40. package/src/Viewport.ts +0 -322
  41. package/src/bundle/bundled.ts +0 -7
  42. package/src/commands/Command.ts +0 -45
  43. package/src/commands/Duplicate.ts +0 -75
  44. package/src/commands/Erase.ts +0 -95
  45. package/src/commands/SerializableCommand.ts +0 -49
  46. package/src/commands/UnresolvedCommand.ts +0 -37
  47. package/src/commands/invertCommand.ts +0 -58
  48. package/src/commands/lib.ts +0 -16
  49. package/src/commands/localization.ts +0 -47
  50. package/src/commands/uniteCommands.test.ts +0 -23
  51. package/src/commands/uniteCommands.ts +0 -140
  52. package/src/components/AbstractComponent.transformBy.test.ts +0 -23
  53. package/src/components/AbstractComponent.ts +0 -383
  54. package/src/components/BackgroundComponent.test.ts +0 -44
  55. package/src/components/BackgroundComponent.ts +0 -348
  56. package/src/components/ImageComponent.ts +0 -176
  57. package/src/components/RestylableComponent.ts +0 -161
  58. package/src/components/SVGGlobalAttributesObject.ts +0 -79
  59. package/src/components/Stroke.test.ts +0 -137
  60. package/src/components/Stroke.ts +0 -294
  61. package/src/components/TextComponent.test.ts +0 -202
  62. package/src/components/TextComponent.ts +0 -429
  63. package/src/components/UnknownSVGObject.test.ts +0 -10
  64. package/src/components/UnknownSVGObject.ts +0 -60
  65. package/src/components/builders/ArrowBuilder.ts +0 -106
  66. package/src/components/builders/CircleBuilder.ts +0 -100
  67. package/src/components/builders/FreehandLineBuilder.test.ts +0 -24
  68. package/src/components/builders/FreehandLineBuilder.ts +0 -210
  69. package/src/components/builders/LineBuilder.ts +0 -77
  70. package/src/components/builders/PressureSensitiveFreehandLineBuilder.ts +0 -453
  71. package/src/components/builders/RectangleBuilder.ts +0 -73
  72. package/src/components/builders/types.ts +0 -15
  73. package/src/components/lib.ts +0 -31
  74. package/src/components/localization.ts +0 -24
  75. package/src/components/util/StrokeSmoother.ts +0 -302
  76. package/src/components/util/describeComponentList.ts +0 -18
  77. package/src/dialogs/makeAboutDialog.ts +0 -82
  78. package/src/inputEvents.ts +0 -143
  79. package/src/lib.ts +0 -91
  80. package/src/localization.ts +0 -34
  81. package/src/localizations/de.ts +0 -146
  82. package/src/localizations/en.ts +0 -8
  83. package/src/localizations/es.ts +0 -74
  84. package/src/localizations/getLocalizationTable.test.ts +0 -27
  85. package/src/localizations/getLocalizationTable.ts +0 -74
  86. package/src/rendering/Display.ts +0 -247
  87. package/src/rendering/RenderablePathSpec.ts +0 -88
  88. package/src/rendering/RenderingStyle.test.ts +0 -68
  89. package/src/rendering/RenderingStyle.ts +0 -55
  90. package/src/rendering/TextRenderingStyle.ts +0 -55
  91. package/src/rendering/caching/CacheRecord.test.ts +0 -48
  92. package/src/rendering/caching/CacheRecord.ts +0 -76
  93. package/src/rendering/caching/CacheRecordManager.ts +0 -71
  94. package/src/rendering/caching/RenderingCache.test.ts +0 -43
  95. package/src/rendering/caching/RenderingCache.ts +0 -66
  96. package/src/rendering/caching/RenderingCacheNode.ts +0 -404
  97. package/src/rendering/caching/testUtils.ts +0 -35
  98. package/src/rendering/caching/types.ts +0 -34
  99. package/src/rendering/lib.ts +0 -8
  100. package/src/rendering/localization.ts +0 -20
  101. package/src/rendering/renderers/AbstractRenderer.ts +0 -232
  102. package/src/rendering/renderers/CanvasRenderer.ts +0 -312
  103. package/src/rendering/renderers/DummyRenderer.test.ts +0 -41
  104. package/src/rendering/renderers/DummyRenderer.ts +0 -142
  105. package/src/rendering/renderers/SVGRenderer.ts +0 -434
  106. package/src/rendering/renderers/TextOnlyRenderer.test.ts +0 -34
  107. package/src/rendering/renderers/TextOnlyRenderer.ts +0 -68
  108. package/src/shortcuts/KeyBinding.test.ts +0 -61
  109. package/src/shortcuts/KeyBinding.ts +0 -257
  110. package/src/shortcuts/KeyboardShortcutManager.test.ts +0 -95
  111. package/src/shortcuts/KeyboardShortcutManager.ts +0 -163
  112. package/src/shortcuts/lib.ts +0 -3
  113. package/src/testing/createEditor.ts +0 -11
  114. package/src/testing/getUniquePointerId.ts +0 -18
  115. package/src/testing/lib.ts +0 -3
  116. package/src/testing/sendPenEvent.ts +0 -36
  117. package/src/testing/sendTouchEvent.ts +0 -71
  118. package/src/toolbar/AbstractToolbar.ts +0 -542
  119. package/src/toolbar/DropdownToolbar.ts +0 -220
  120. package/src/toolbar/EdgeToolbar.test.ts +0 -54
  121. package/src/toolbar/EdgeToolbar.ts +0 -543
  122. package/src/toolbar/IconProvider.ts +0 -861
  123. package/src/toolbar/constants.ts +0 -1
  124. package/src/toolbar/lib.ts +0 -6
  125. package/src/toolbar/localization.ts +0 -136
  126. package/src/toolbar/types.ts +0 -13
  127. package/src/toolbar/widgets/ActionButtonWidget.ts +0 -39
  128. package/src/toolbar/widgets/BaseToolWidget.ts +0 -81
  129. package/src/toolbar/widgets/BaseWidget.ts +0 -495
  130. package/src/toolbar/widgets/DocumentPropertiesWidget.ts +0 -250
  131. package/src/toolbar/widgets/EraserToolWidget.ts +0 -84
  132. package/src/toolbar/widgets/HandToolWidget.ts +0 -239
  133. package/src/toolbar/widgets/InsertImageWidget.ts +0 -248
  134. package/src/toolbar/widgets/OverflowWidget.ts +0 -92
  135. package/src/toolbar/widgets/PenToolWidget.ts +0 -369
  136. package/src/toolbar/widgets/SelectionToolWidget.ts +0 -195
  137. package/src/toolbar/widgets/TextToolWidget.ts +0 -149
  138. package/src/toolbar/widgets/components/makeColorInput.ts +0 -184
  139. package/src/toolbar/widgets/components/makeFileInput.ts +0 -128
  140. package/src/toolbar/widgets/components/makeGridSelector.ts +0 -179
  141. package/src/toolbar/widgets/components/makeSeparator.ts +0 -17
  142. package/src/toolbar/widgets/components/makeThicknessSlider.ts +0 -62
  143. package/src/toolbar/widgets/keybindings.ts +0 -19
  144. package/src/toolbar/widgets/layout/DropdownLayoutManager.ts +0 -262
  145. package/src/toolbar/widgets/layout/EdgeToolbarLayoutManager.ts +0 -71
  146. package/src/toolbar/widgets/layout/types.ts +0 -74
  147. package/src/toolbar/widgets/lib.ts +0 -13
  148. package/src/tools/BaseTool.ts +0 -169
  149. package/src/tools/Eraser.test.ts +0 -103
  150. package/src/tools/Eraser.ts +0 -173
  151. package/src/tools/FindTool.test.ts +0 -67
  152. package/src/tools/FindTool.ts +0 -153
  153. package/src/tools/InputFilter/FunctionMapper.ts +0 -17
  154. package/src/tools/InputFilter/InputMapper.ts +0 -41
  155. package/src/tools/InputFilter/InputPipeline.test.ts +0 -41
  156. package/src/tools/InputFilter/InputPipeline.ts +0 -34
  157. package/src/tools/InputFilter/InputStabilizer.ts +0 -254
  158. package/src/tools/InputFilter/StrokeKeyboardControl.ts +0 -104
  159. package/src/tools/PanZoom.test.ts +0 -339
  160. package/src/tools/PanZoom.ts +0 -525
  161. package/src/tools/PasteHandler.ts +0 -94
  162. package/src/tools/Pen.test.ts +0 -260
  163. package/src/tools/Pen.ts +0 -284
  164. package/src/tools/PipetteTool.ts +0 -84
  165. package/src/tools/SelectionTool/SelectAllShortcutHandler.ts +0 -29
  166. package/src/tools/SelectionTool/Selection.ts +0 -647
  167. package/src/tools/SelectionTool/SelectionHandle.ts +0 -142
  168. package/src/tools/SelectionTool/SelectionTool.test.ts +0 -370
  169. package/src/tools/SelectionTool/SelectionTool.ts +0 -510
  170. package/src/tools/SelectionTool/TransformMode.ts +0 -112
  171. package/src/tools/SelectionTool/types.ts +0 -11
  172. package/src/tools/SoundUITool.ts +0 -221
  173. package/src/tools/TextTool.ts +0 -339
  174. package/src/tools/ToolController.ts +0 -224
  175. package/src/tools/ToolEnabledGroup.ts +0 -14
  176. package/src/tools/ToolSwitcherShortcut.ts +0 -39
  177. package/src/tools/ToolbarShortcutHandler.ts +0 -39
  178. package/src/tools/UndoRedoShortcut.test.ts +0 -62
  179. package/src/tools/UndoRedoShortcut.ts +0 -24
  180. package/src/tools/keybindings.ts +0 -85
  181. package/src/tools/lib.ts +0 -22
  182. package/src/tools/localization.ts +0 -76
  183. package/src/types.ts +0 -151
  184. package/src/util/ReactiveValue.test.ts +0 -168
  185. package/src/util/ReactiveValue.ts +0 -241
  186. package/src/util/assertions.ts +0 -55
  187. package/src/util/fileToBase64.ts +0 -18
  188. package/src/util/guessKeyCodeFromKey.ts +0 -36
  189. package/src/util/listPrefixMatch.ts +0 -19
  190. package/src/util/stopPropagationOfScrollingWheelEvents.ts +0 -20
  191. package/src/util/untilNextAnimationFrame.ts +0 -9
  192. package/src/util/waitForAll.ts +0 -18
  193. package/src/util/waitForTimeout.ts +0 -9
  194. package/src/version.test.ts +0 -12
  195. package/src/version.ts +0 -3
  196. package/tools/allLocales.js +0 -4
  197. package/tools/copyREADME.ts +0 -62
@@ -1,302 +0,0 @@
1
- import { Point2, Vec2, Rect2, LineSegment2, QuadraticBezier } from '@js-draw/math';
2
- import { StrokeDataPoint } from '../../types';
3
-
4
- export interface Curve {
5
- startPoint: Vec2;
6
- startWidth: number;
7
-
8
- controlPoint: Vec2;
9
-
10
- endWidth: number;
11
- endPoint: Vec2;
12
- }
13
-
14
- type OnCurveAddedCallback = (curve: Curve|null)=>void;
15
-
16
- // Handles stroke smoothing
17
- export class StrokeSmoother {
18
- private isFirstSegment: boolean = true;
19
-
20
- private buffer: Point2[];
21
- private lastPoint: StrokeDataPoint;
22
- private lastExitingVec: Vec2|null = null;
23
- private currentCurve: QuadraticBezier|null = null;
24
- private curveStartWidth: number;
25
- private curveEndWidth: number;
26
-
27
- // Stroke smoothing and tangent approximation
28
- private momentum: Vec2;
29
- private bbox: Rect2;
30
-
31
- public constructor(
32
- private startPoint: StrokeDataPoint,
33
-
34
- // Maximum distance from the actual curve (irrespective of stroke width)
35
- // for which a point is considered 'part of the curve'.
36
- // Note that the maximum will be smaller if the stroke width is less than
37
- // [maxFitAllowed].
38
- private minFitAllowed: number,
39
- private maxFitAllowed: number,
40
-
41
- private onCurveAdded: OnCurveAddedCallback,
42
- ) {
43
- this.lastPoint = this.startPoint;
44
-
45
- this.buffer = [this.startPoint.pos];
46
- this.momentum = Vec2.zero;
47
- this.currentCurve = null;
48
- this.curveStartWidth = startPoint.width;
49
-
50
- this.bbox = new Rect2(this.startPoint.pos.x, this.startPoint.pos.y, 0, 0);
51
- }
52
-
53
- public getBBox(): Rect2 {
54
- return this.bbox;
55
- }
56
-
57
- public preview(): Curve|null {
58
- if (!this.currentCurve) {
59
- return null;
60
- }
61
-
62
- return this.currentSegmentToPath();
63
- }
64
-
65
- // Returns the distance between the start, control, and end points of the curve.
66
- private approxCurrentCurveLength() {
67
- if (!this.currentCurve) {
68
- return 0;
69
- }
70
- const startPt = this.currentCurve.p0;
71
- const controlPt = this.currentCurve.p1;
72
- const endPt = this.currentCurve.p2;
73
- const toControlDist = startPt.minus(controlPt).length();
74
- const toEndDist = endPt.minus(controlPt).length();
75
- return toControlDist + toEndDist;
76
- }
77
-
78
- public finalizeCurrentCurve() {
79
- // Case where no points have been added
80
- if (!this.currentCurve) {
81
- return;
82
- }
83
-
84
- this.onCurveAdded(this.currentSegmentToPath());
85
-
86
- const lastPoint = this.buffer[this.buffer.length - 1];
87
- this.lastExitingVec = this.currentCurve.p2.minus(this.currentCurve.p1);
88
- console.assert(this.lastExitingVec.magnitude() !== 0, 'lastExitingVec has zero length!');
89
-
90
- // Use the last two points to start a new curve (the last point isn't used
91
- // in the current curve and we want connected curves to share end points)
92
- this.buffer = [
93
- this.buffer[this.buffer.length - 2], lastPoint,
94
- ];
95
- this.currentCurve = null;
96
-
97
- this.isFirstSegment = false;
98
- }
99
-
100
- // Returns [upper curve, connector, lower curve]
101
- private currentSegmentToPath() {
102
- if (this.currentCurve == null) {
103
- throw new Error('Invalid State: currentCurve is null!');
104
- }
105
-
106
- const startVec = this.currentCurve.normal(0).normalized();
107
-
108
- if (!isFinite(startVec.magnitude())) {
109
- throw new Error(`startVec(${startVec}) is NaN or ∞`);
110
- }
111
-
112
- const startPt = this.currentCurve.at(0);
113
- const endPt = this.currentCurve.at(1);
114
- const controlPoint = this.currentCurve.p1;
115
-
116
- return {
117
- startPoint: startPt,
118
- controlPoint,
119
- endPoint: endPt,
120
- startWidth: this.curveStartWidth,
121
- endWidth: this.curveEndWidth,
122
- };
123
- }
124
-
125
- // Compute the direction of the velocity at the end of this.buffer
126
- private computeExitingVec(): Vec2 {
127
- return this.momentum.normalized().times(this.lastPoint.width / 2);
128
- }
129
-
130
- public addPoint(newPoint: StrokeDataPoint) {
131
- if (this.lastPoint) {
132
- // Ignore points that are identical
133
- const fuzzEq = 1e-10;
134
- const deltaTime = newPoint.time - this.lastPoint.time;
135
- if (newPoint.pos.eq(this.lastPoint.pos, fuzzEq) || deltaTime === 0) {
136
- return;
137
- } else if (isNaN(newPoint.pos.magnitude())) {
138
- console.warn('Discarding NaN point.', newPoint);
139
- return;
140
- }
141
-
142
- const threshold = Math.min(this.lastPoint.width, newPoint.width) / 3;
143
- const shouldSnapToInitial = this.startPoint.pos.minus(newPoint.pos).magnitude() < threshold
144
- && this.isFirstSegment;
145
-
146
- // Snap to the starting point if the stroke is contained within a small ball centered
147
- // at the starting point.
148
- // This allows us to create a circle/dot at the start of the stroke.
149
- if (shouldSnapToInitial) {
150
- return;
151
- }
152
-
153
- const deltaTimeSeconds = deltaTime / 1000;
154
- const velocity = newPoint.pos.minus(this.lastPoint.pos).times(1 / deltaTimeSeconds);
155
-
156
- // TODO: Do we need momentum smoothing? (this.momentum.lerp(velocity, 0.9);)
157
- this.momentum = velocity;
158
- }
159
-
160
- const lastPoint = this.lastPoint ?? newPoint;
161
- this.lastPoint = newPoint;
162
-
163
- this.buffer.push(newPoint.pos);
164
- const pointRadius = newPoint.width;
165
- const prevEndWidth = this.curveEndWidth;
166
- this.curveEndWidth = pointRadius;
167
-
168
- // recompute bbox
169
- this.bbox = this.bbox.grownToPoint(newPoint.pos, pointRadius);
170
-
171
- // If the last curve just ended or it's the first curve,
172
- if (this.currentCurve === null) {
173
- const p1 = lastPoint.pos;
174
- const p2 = lastPoint.pos.plus(this.lastExitingVec ?? Vec2.unitX);
175
- const p3 = newPoint.pos;
176
-
177
- // Quadratic Bézier curve
178
- this.currentCurve = new QuadraticBezier(p1, p2, p3);
179
- console.assert(!isNaN(p1.magnitude()) && !isNaN(p2.magnitude()) && !isNaN(p3.magnitude()), 'Expected !NaN');
180
-
181
- if (this.isFirstSegment) {
182
- // The start of a curve often lacks accurate pressure information. Update it.
183
- this.curveStartWidth = (this.curveStartWidth + pointRadius) / 2;
184
- }
185
- else {
186
- this.curveStartWidth = prevEndWidth;
187
- }
188
- }
189
-
190
- // If there isn't an entering vector (e.g. because this.isFirstCurve), approximate it.
191
- let enteringVec = this.lastExitingVec;
192
- if (!enteringVec) {
193
- let sampleIdx = Math.ceil(this.buffer.length / 2);
194
- if (sampleIdx === 0 || sampleIdx >= this.buffer.length) {
195
- sampleIdx = this.buffer.length - 1;
196
- }
197
-
198
- enteringVec = this.buffer[sampleIdx].minus(this.buffer[0]);
199
- }
200
-
201
- let exitingVec = this.computeExitingVec();
202
-
203
- // Find the intersection between the entering vector and the exiting vector
204
- const maxRelativeLength = 2.4;
205
- const segmentStart = this.buffer[0];
206
- const segmentEnd = newPoint.pos;
207
- const startEndDist = segmentEnd.minus(segmentStart).magnitude();
208
- const maxControlPointDist = maxRelativeLength * startEndDist;
209
-
210
- // Exit in cases where we would divide by zero
211
- if (maxControlPointDist === 0 || exitingVec.magnitude() === 0 || !isFinite(exitingVec.magnitude())) {
212
- return;
213
- }
214
-
215
- console.assert(isFinite(enteringVec.magnitude()), 'Pre-normalized enteringVec has NaN or ∞ magnitude!');
216
-
217
- enteringVec = enteringVec.normalized();
218
- exitingVec = exitingVec.normalized();
219
-
220
- console.assert(isFinite(enteringVec.magnitude()), 'Normalized enteringVec has NaN or ∞ magnitude!');
221
-
222
- const lineFromStart = new LineSegment2(
223
- segmentStart,
224
- segmentStart.plus(enteringVec.times(maxControlPointDist))
225
- );
226
- const lineFromEnd = new LineSegment2(
227
- segmentEnd.minus(exitingVec.times(maxControlPointDist)),
228
- segmentEnd
229
- );
230
- const intersection = lineFromEnd.intersection(lineFromStart);
231
-
232
- // Position the control point at this intersection
233
- let controlPoint: Point2|null = null;
234
- if (intersection) {
235
- controlPoint = intersection.point;
236
- }
237
-
238
- // No intersection or the intersection is one of the end points?
239
- if (!controlPoint || segmentStart.eq(controlPoint) || segmentEnd.eq(controlPoint)) {
240
- // Position the control point closer to the first -- the connecting
241
- // segment will be roughly a line.
242
- controlPoint = segmentStart.plus(enteringVec.times(startEndDist / 4));
243
- }
244
-
245
- console.assert(!segmentStart.eq(controlPoint, 1e-11), 'Start and control points are equal!');
246
- console.assert(!controlPoint.eq(segmentEnd, 1e-11), 'Control and end points are equal!');
247
-
248
- const prevCurve = this.currentCurve;
249
- this.currentCurve = new QuadraticBezier(segmentStart, controlPoint, segmentEnd);
250
-
251
- if (isNaN(this.currentCurve.normal(0).magnitude())) {
252
- console.error('NaN normal at 0. Curve:', this.currentCurve);
253
- this.currentCurve = prevCurve;
254
- }
255
-
256
- // Should we start making a new curve? Check whether all buffer points are within
257
- // ±strokeWidth of the curve.
258
- const curveMatchesPoints = (curve: QuadraticBezier): boolean => {
259
- const minFit = Math.min(Math.max(
260
- Math.min(this.curveStartWidth, this.curveEndWidth) / 4,
261
- this.minFitAllowed
262
- ), this.maxFitAllowed);
263
-
264
- // The sum of distances greater than minFit must not exceed this:
265
- const maxNonMatchingDistSum = minFit;
266
-
267
- // Sum of distances greater than minFit.
268
- let nonMatchingDistSum = 0;
269
-
270
- for (const point of this.buffer) {
271
- let dist = curve.approximateDistance(point);
272
-
273
- if (dist > minFit) {
274
- // Use the more accurate distance function
275
- dist = curve.distance(point);
276
-
277
- nonMatchingDistSum += Math.max(0, dist - minFit);
278
- if (nonMatchingDistSum > maxNonMatchingDistSum) {
279
- return false; // false: Curve doesn't match points well enough.
280
- }
281
- }
282
- }
283
- return true;
284
- };
285
-
286
- if (this.buffer.length > 3 && this.approxCurrentCurveLength() > this.curveStartWidth / 2) {
287
- if (!curveMatchesPoints(this.currentCurve)) {
288
- // Use a curve that better fits the points
289
- this.currentCurve = prevCurve;
290
- this.curveEndWidth = prevEndWidth;
291
-
292
- // Reset the last point -- the current point was not added to the curve.
293
- this.lastPoint = lastPoint;
294
-
295
- this.finalizeCurrentCurve();
296
- return;
297
- }
298
- }
299
- }
300
- }
301
-
302
- export default StrokeSmoother;
@@ -1,18 +0,0 @@
1
- import AbstractComponent from '../AbstractComponent';
2
- import { ImageComponentLocalization } from '../localization';
3
-
4
- // Returns the description of all given elements, if identical, otherwise,
5
- // returns null.
6
- export default (localizationTable: ImageComponentLocalization, elems: AbstractComponent[]) => {
7
- if (elems.length === 0) {
8
- return null;
9
- }
10
-
11
- const description = elems[0].description(localizationTable);
12
- for (const elem of elems) {
13
- if (elem.description(localizationTable) !== description) {
14
- return null;
15
- }
16
- }
17
- return description;
18
- };
@@ -1,82 +0,0 @@
1
- import type Editor from '../Editor';
2
-
3
- export interface AboutDialogLink {
4
- kind: 'link',
5
- text: string;
6
- href: string;
7
- }
8
-
9
- export interface AboutDialogEntry {
10
- heading: string|AboutDialogLink;
11
- text?: string;
12
- minimized?: boolean;
13
- }
14
-
15
- const makeAboutDialog = (editor: Editor, entries: AboutDialogEntry[]) => {
16
- const overlay = document.createElement('div');
17
- const { remove: removeOverlay } = editor.createHTMLOverlay(overlay);
18
-
19
- overlay.classList.add('dialog-container', 'about-dialog-container');
20
- const dialog = document.createElement('dialog');
21
-
22
- const heading = document.createElement('h1');
23
- heading.innerText = editor.localization.about;
24
- heading.setAttribute('autofocus', 'true');
25
-
26
- const closeButton = document.createElement('button');
27
- closeButton.innerText = editor.localization.closeDialog;
28
- closeButton.classList.add('close-button');
29
-
30
- closeButton.onclick = () => removeOverlay();
31
- overlay.onclick = event => {
32
- if (event.target === overlay) {
33
- removeOverlay();
34
- }
35
- };
36
-
37
- const licenseContainer = document.createElement('div');
38
- licenseContainer.classList.add('about-entry-container');
39
-
40
- // Allow scrolling in the license container -- don't forward wheel events.
41
- licenseContainer.onwheel = evt => evt.stopPropagation();
42
-
43
- for (const entry of entries) {
44
- const container = document.createElement(entry.minimized ? 'details' : 'div');
45
- container.classList.add('about-entry');
46
-
47
- const header = document.createElement(entry.minimized ? 'summary' : 'h2');
48
-
49
- if (typeof (entry.heading) === 'string') {
50
- header.innerText = entry.heading;
51
- } else {
52
- const link = document.createElement('a');
53
- link.href = entry.heading.href.replace(/^javascript:/i, '');
54
- link.text = entry.heading.text;
55
- header.appendChild(link);
56
- }
57
-
58
- container.appendChild(header);
59
-
60
- if (entry.text) {
61
- const bodyText = document.createElement('div');
62
- bodyText.innerText = entry.text;
63
-
64
- container.appendChild(bodyText);
65
- }
66
-
67
- licenseContainer.appendChild(container);
68
- }
69
-
70
- dialog.replaceChildren(heading, licenseContainer, closeButton);
71
- overlay.replaceChildren(dialog);
72
-
73
- dialog.show();
74
-
75
- return {
76
- close: () => {
77
- removeOverlay();
78
- },
79
- };
80
- };
81
-
82
- export default makeAboutDialog;
@@ -1,143 +0,0 @@
1
- import Pointer from './Pointer';
2
- import { Point2, Vec3 } from '@js-draw/math';
3
-
4
- export type HTMLPointerEventName = 'pointerdown'|'pointermove'|'pointerup'|'pointercancel';
5
- export type HTMLPointerEventFilter = (eventName: HTMLPointerEventName, event: PointerEvent)=>boolean;
6
-
7
- export interface PointerEvtListener {
8
- onPointerDown(event: PointerEvt): boolean;
9
- onPointerMove(event: PointerEvt): void;
10
- onPointerUp(event: PointerEvt): void;
11
-
12
- // Called if a pointer that has been captured by this listener (by returning
13
- // `true` from `onPointerDown`) is re-captured by another listener.
14
- //
15
- // When called, this method should cancel any changes being made by the current
16
- // gesture.
17
- onGestureCancel(): void;
18
- }
19
-
20
-
21
- export enum InputEvtType {
22
- PointerDownEvt,
23
- PointerMoveEvt,
24
- PointerUpEvt,
25
- GestureCancelEvt,
26
-
27
- WheelEvt,
28
- KeyPressEvent,
29
- KeyUpEvent,
30
-
31
- CopyEvent,
32
- PasteEvent,
33
- }
34
-
35
- // [delta.x] is horizontal scroll,
36
- // [delta.y] is vertical scroll,
37
- // [delta.z] is zoom scroll (ctrl+scroll or pinch zoom)
38
- export interface WheelEvt {
39
- readonly kind: InputEvtType.WheelEvt;
40
- readonly delta: Vec3;
41
- readonly screenPos: Point2;
42
- }
43
-
44
- interface BaseKeyEvent {
45
- // key, as given by an HTML `KeyboardEvent`
46
- readonly key: string;
47
- readonly code: string;
48
-
49
- // If `ctrlKey` is undefined, that is equivalent to `ctrlKey = false`.
50
- readonly ctrlKey: boolean|undefined;
51
-
52
- // If falsey, the `alt` key is not pressed.
53
- readonly altKey: boolean|undefined;
54
-
55
- // If falsey, the `shift` key is not pressed.
56
- readonly shiftKey: boolean|undefined;
57
- }
58
-
59
- /**
60
- * Represents a keydown or auto-repeated keydown event.
61
- *
62
- * Use {@link keyPressEventFromHTMLEvent} where possible rather than
63
- * constructing directly (required properties may change between minor
64
- * releases).
65
- */
66
- export interface KeyPressEvent extends BaseKeyEvent {
67
- readonly kind: InputEvtType.KeyPressEvent;
68
- }
69
-
70
- /**
71
- * Represents a key release or auto-repeated key releae event.
72
- *
73
- * Use {@link keyUpEventFromHTMLEvent} where possible rather than
74
- * constructing directly (required properties may change between minor
75
- * releases).
76
- */
77
- export interface KeyUpEvent extends BaseKeyEvent {
78
- readonly kind: InputEvtType.KeyUpEvent;
79
- }
80
-
81
- export interface CopyEvent {
82
- readonly kind: InputEvtType.CopyEvent;
83
- setData(mime: string, data: string): void;
84
- }
85
-
86
- export interface PasteEvent {
87
- readonly kind: InputEvtType.PasteEvent;
88
- readonly data: string;
89
- readonly mime: string;
90
- }
91
-
92
- // Event triggered when pointer capture is taken by a different [PointerEvtListener].
93
- export interface GestureCancelEvt {
94
- readonly kind: InputEvtType.GestureCancelEvt;
95
- }
96
-
97
- interface PointerEvtBase {
98
- readonly current: Pointer;
99
- readonly allPointers: Pointer[];
100
- }
101
-
102
- export interface PointerDownEvt extends PointerEvtBase {
103
- readonly kind: InputEvtType.PointerDownEvt;
104
- }
105
-
106
- export interface PointerMoveEvt extends PointerEvtBase {
107
- readonly kind: InputEvtType.PointerMoveEvt;
108
- }
109
-
110
- export interface PointerUpEvt extends PointerEvtBase {
111
- readonly kind: InputEvtType.PointerUpEvt;
112
- }
113
-
114
- export type PointerEvt = PointerDownEvt | PointerMoveEvt | PointerUpEvt;
115
- export type InputEvt = KeyPressEvent | KeyUpEvent | WheelEvt | GestureCancelEvt | PointerEvt | CopyEvent | PasteEvent;
116
-
117
- type KeyEventType = InputEvtType.KeyPressEvent|InputEvtType.KeyUpEvent;
118
-
119
- // Constructor
120
- const keyEventFromHTMLEvent = (kind: KeyEventType, event: KeyboardEvent): KeyPressEvent|KeyUpEvent => {
121
- return {
122
- kind,
123
- key: event.key,
124
- code: event.code,
125
- ctrlKey: event.ctrlKey || event.metaKey,
126
- altKey: event.altKey,
127
- shiftKey: event.shiftKey,
128
- };
129
- };
130
-
131
- export const keyUpEventFromHTMLEvent = (event: KeyboardEvent) => {
132
- return keyEventFromHTMLEvent(InputEvtType.KeyUpEvent, event) as KeyUpEvent;
133
- };
134
-
135
- export const keyPressEventFromHTMLEvent = (event: KeyboardEvent) => {
136
- return keyEventFromHTMLEvent(InputEvtType.KeyPressEvent, event) as KeyPressEvent;
137
- };
138
-
139
- export const isPointerEvt = (event: InputEvt): event is PointerEvt => {
140
- return event.kind === InputEvtType.PointerDownEvt
141
- || event.kind === InputEvtType.PointerMoveEvt
142
- || event.kind === InputEvtType.PointerUpEvt;
143
- };
package/src/lib.ts DELETED
@@ -1,91 +0,0 @@
1
- /**
2
- * The main entrypoint for the NPM package. Everything exported by this file
3
- * is available through the [`js-draw` package](https://www.npmjs.com/package/js-draw).
4
- *
5
- * @example
6
- * ```ts,runnable
7
- * import { Editor, Vec3, Mat33, ToolbarWidgetTag } from 'js-draw';
8
- *
9
- * // Apply js-draw CSS
10
- * import 'js-draw/styles';
11
- * // If your bundler doesn't support the above, try
12
- * // import 'js-draw/bundledStyles';
13
- *
14
- * (async () => {
15
- * const editor = new Editor(document.body);
16
- * const toolbar = editor.addToolbar();
17
- *
18
- * // Increases the minimum height of the editor
19
- * editor.getRootElement().style.height = '600px';
20
- *
21
- * // Loads from SVG data
22
- * await editor.loadFromSVG(`
23
- * <svg viewBox="0 0 500 500" width="500" height="500" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
24
- * <style id="js-draw-style-sheet">path{stroke-linecap:round;stroke-linejoin:round;}text{white-space:pre;}</style>
25
- * <path d="M500,500L500,0L0,0L0,500L500,500" fill="#423131bf" class="js-draw-image-background"></path>
26
- * <text style="transform: matrix(1, 0, 0, 1, 57, 192); font-family: serif; font-size: 32px; fill: rgb(204, 102, 51);">Testing...</text>
27
- * </svg>
28
- * `);
29
- *
30
- * // Adding tags to a toolbar button allows different styles to be applied.
31
- * // Also see addActionButton.
32
- * const buttonLabels = [ ToolbarWidgetTag.Save ];
33
- *
34
- * toolbar.addSaveButton(() => {
35
- * const saveData = editor.toSVG().outerHTML;
36
- *
37
- * // Do something with saveData
38
- * });
39
- *
40
- * toolbar.addExitButton(() => {
41
- * // Save/confirm exiting here?
42
- * editor.remove();
43
- * });
44
- * })();
45
- * ```
46
- *
47
- * @see
48
- * {@link Editor}
49
- * {@link Editor.loadFromSVG}
50
- * {@link AbstractToolbar.addActionButton }
51
- *
52
- * @packageDocumentation
53
- */
54
-
55
- import Editor, { EditorSettings } from './Editor';
56
- export { default as EditorImage } from './EditorImage';
57
- export * from './types';
58
- export * from './inputEvents';
59
- export { default as getLocalizationTable, matchingLocalizationTable } from './localizations/getLocalizationTable';
60
- export * from './localization';
61
-
62
- export { default as SVGLoader } from './SVGLoader';
63
- export { default as Viewport } from './Viewport';
64
- export * from '@js-draw/math';
65
- export * from './components/lib';
66
- export * from './commands/lib';
67
- export * from './tools/lib';
68
- export * from './toolbar/lib';
69
- export * from './rendering/lib';
70
- export * from './testing/lib';
71
- export * from './shortcuts/lib';
72
- export { default as EventDispatcher } from './EventDispatcher';
73
- export { default as Pointer, PointerDevice } from './Pointer';
74
- export { default as UndoRedoHistory } from './UndoRedoHistory';
75
-
76
- // @internal
77
- export { default as __js_draw__version } from './version';
78
-
79
- import AbstractToolbar from './toolbar/AbstractToolbar';
80
-
81
- export {
82
- Editor, EditorSettings, AbstractToolbar,
83
-
84
- /**
85
- * Using the HTMLToolbar alias is deprecated. Use
86
- * `AbstractToolbar` instead.
87
- * @deprecated
88
- */
89
- AbstractToolbar as HTMLToolbar,
90
- };
91
- export default Editor;
@@ -1,34 +0,0 @@
1
- import { CommandLocalization, defaultCommandLocalization } from './commands/localization';
2
- import { defaultComponentLocalization, ImageComponentLocalization } from './components/localization';
3
- import { defaultTextRendererLocalization, TextRendererLocalization } from './rendering/localization';
4
- import { defaultToolbarLocalization, ToolbarLocalization } from './toolbar/localization';
5
- import { defaultToolLocalization, ToolLocalization } from './tools/localization';
6
-
7
-
8
- export interface EditorLocalization extends ToolbarLocalization, ToolLocalization, CommandLocalization, ImageComponentLocalization, TextRendererLocalization {
9
- accessibilityInputInstructions: string;
10
- undoAnnouncement: (actionDescription: string)=> string;
11
- redoAnnouncement: (actionDescription: string)=> string;
12
- doneLoading: string;
13
- loading: (percentage: number)=>string;
14
- imageEditor: string;
15
- }
16
-
17
- export const defaultEditorLocalization: EditorLocalization = {
18
- ...defaultToolbarLocalization,
19
- ...defaultToolLocalization,
20
- ...defaultCommandLocalization,
21
- ...defaultComponentLocalization,
22
- ...defaultTextRendererLocalization,
23
- accessibilityInputInstructions: [
24
- 'Press "t" to read the contents of the viewport as text.',
25
- 'Use the arrow keys to move the viewport, click and drag to draw strokes.',
26
- 'Press "w" to zoom in and "s" to zoom out.',
27
- ].join(' '),
28
- loading: (percentage: number) => `Loading ${percentage}%...`,
29
- imageEditor: 'Image Editor',
30
- doneLoading: 'Done loading',
31
-
32
- undoAnnouncement: (commandDescription: string) => `Undid ${commandDescription}`,
33
- redoAnnouncement: (commandDescription: string) => `Redid ${commandDescription}`,
34
- };