js-draw 1.2.1 → 1.3.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.
- package/README.md +30 -30
- package/dist/Editor.css +70 -4
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.d.ts +73 -40
- package/dist/cjs/Editor.js +90 -24
- package/dist/cjs/EditorImage.d.ts +58 -6
- package/dist/cjs/EditorImage.js +336 -60
- package/dist/cjs/SVGLoader.d.ts +10 -4
- package/dist/cjs/SVGLoader.js +30 -10
- package/dist/cjs/UndoRedoHistory.d.ts +2 -2
- package/dist/cjs/UndoRedoHistory.js +4 -2
- package/dist/cjs/Viewport.d.ts +2 -1
- package/dist/cjs/Viewport.js +12 -3
- package/dist/cjs/commands/Command.d.ts +1 -0
- package/dist/cjs/commands/Command.js +1 -0
- package/dist/cjs/commands/Erase.js +1 -1
- package/dist/cjs/commands/SerializableCommand.d.ts +1 -1
- package/dist/cjs/commands/SerializableCommand.js +16 -2
- package/dist/cjs/commands/localization.d.ts +2 -0
- package/dist/cjs/commands/localization.js +2 -0
- package/dist/cjs/components/AbstractComponent.d.ts +38 -0
- package/dist/cjs/components/AbstractComponent.js +31 -0
- package/dist/cjs/components/BackgroundComponent.d.ts +10 -1
- package/dist/cjs/components/BackgroundComponent.js +60 -6
- package/dist/cjs/components/SVGGlobalAttributesObject.d.ts +2 -1
- package/dist/cjs/components/SVGGlobalAttributesObject.js +30 -1
- package/dist/cjs/components/Stroke.d.ts +1 -0
- package/dist/cjs/components/Stroke.js +44 -0
- package/dist/cjs/components/UnknownSVGObject.d.ts +2 -1
- package/dist/cjs/components/UnknownSVGObject.js +30 -1
- package/dist/cjs/components/lib.d.ts +2 -2
- package/dist/cjs/components/lib.js +15 -2
- package/dist/cjs/lib.d.ts +2 -45
- package/dist/cjs/lib.js +2 -45
- package/dist/cjs/rendering/RenderablePathSpec.d.ts +1 -0
- package/dist/cjs/rendering/RenderablePathSpec.js +1 -0
- package/dist/cjs/rendering/RenderingStyle.d.ts +1 -0
- package/dist/cjs/rendering/lib.d.ts +1 -0
- package/dist/cjs/rendering/lib.js +5 -1
- package/dist/cjs/rendering/renderers/AbstractRenderer.js +1 -1
- package/dist/cjs/shortcuts/KeyboardShortcutManager.d.ts +2 -2
- package/dist/cjs/shortcuts/KeyboardShortcutManager.js +2 -2
- package/dist/cjs/toolbar/localization.d.ts +1 -0
- package/dist/cjs/toolbar/localization.js +1 -0
- package/dist/cjs/toolbar/widgets/BaseWidget.js +5 -0
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +54 -25
- package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +8 -0
- package/dist/cjs/tools/PanZoom.js +13 -8
- package/dist/cjs/tools/ScrollbarTool.d.ts +18 -0
- package/dist/cjs/tools/ScrollbarTool.js +85 -0
- package/dist/cjs/tools/SelectionTool/SelectionTool.selecting.test.d.ts +1 -0
- package/dist/cjs/tools/ToolController.js +2 -0
- package/dist/cjs/types.d.ts +3 -1
- package/dist/cjs/util/adjustEditorThemeForContrast.js +1 -0
- package/dist/cjs/util/assertions.d.ts +4 -0
- package/dist/cjs/util/assertions.js +12 -1
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +73 -40
- package/dist/mjs/Editor.mjs +90 -24
- package/dist/mjs/EditorImage.d.ts +58 -6
- package/dist/mjs/EditorImage.mjs +313 -61
- package/dist/mjs/SVGLoader.d.ts +10 -4
- package/dist/mjs/SVGLoader.mjs +29 -9
- package/dist/mjs/UndoRedoHistory.d.ts +2 -2
- package/dist/mjs/UndoRedoHistory.mjs +4 -2
- package/dist/mjs/Viewport.d.ts +2 -1
- package/dist/mjs/Viewport.mjs +12 -3
- package/dist/mjs/commands/Command.d.ts +1 -0
- package/dist/mjs/commands/Command.mjs +1 -0
- package/dist/mjs/commands/Erase.mjs +1 -1
- package/dist/mjs/commands/SerializableCommand.d.ts +1 -1
- package/dist/mjs/commands/SerializableCommand.mjs +16 -2
- package/dist/mjs/commands/localization.d.ts +2 -0
- package/dist/mjs/commands/localization.mjs +2 -0
- package/dist/mjs/components/AbstractComponent.d.ts +38 -0
- package/dist/mjs/components/AbstractComponent.mjs +30 -0
- package/dist/mjs/components/BackgroundComponent.d.ts +10 -1
- package/dist/mjs/components/BackgroundComponent.mjs +37 -6
- package/dist/mjs/components/SVGGlobalAttributesObject.d.ts +2 -1
- package/dist/mjs/components/SVGGlobalAttributesObject.mjs +7 -1
- package/dist/mjs/components/Stroke.d.ts +1 -0
- package/dist/mjs/components/Stroke.mjs +44 -0
- package/dist/mjs/components/UnknownSVGObject.d.ts +2 -1
- package/dist/mjs/components/UnknownSVGObject.mjs +7 -1
- package/dist/mjs/components/lib.d.ts +2 -2
- package/dist/mjs/components/lib.mjs +2 -2
- package/dist/mjs/lib.d.ts +2 -45
- package/dist/mjs/lib.mjs +2 -45
- package/dist/mjs/rendering/RenderablePathSpec.d.ts +1 -0
- package/dist/mjs/rendering/RenderablePathSpec.mjs +1 -0
- package/dist/mjs/rendering/RenderingStyle.d.ts +1 -0
- package/dist/mjs/rendering/lib.d.ts +1 -0
- package/dist/mjs/rendering/lib.mjs +1 -0
- package/dist/mjs/rendering/renderers/AbstractRenderer.mjs +1 -1
- package/dist/mjs/shortcuts/KeyboardShortcutManager.d.ts +2 -2
- package/dist/mjs/shortcuts/KeyboardShortcutManager.mjs +2 -2
- package/dist/mjs/toolbar/localization.d.ts +1 -0
- package/dist/mjs/toolbar/localization.mjs +1 -0
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +5 -0
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +54 -25
- package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +8 -0
- package/dist/mjs/tools/PanZoom.mjs +13 -8
- package/dist/mjs/tools/ScrollbarTool.d.ts +18 -0
- package/dist/mjs/tools/ScrollbarTool.mjs +79 -0
- package/dist/mjs/tools/SelectionTool/SelectionTool.selecting.test.d.ts +1 -0
- package/dist/mjs/tools/ToolController.mjs +2 -0
- package/dist/mjs/types.d.ts +3 -1
- package/dist/mjs/util/adjustEditorThemeForContrast.mjs +1 -0
- package/dist/mjs/util/assertions.d.ts +4 -0
- package/dist/mjs/util/assertions.mjs +10 -0
- package/dist/mjs/version.mjs +1 -1
- package/package.json +3 -4
- package/src/Editor.scss +8 -0
- package/src/dialogs/dialogs.scss +2 -1
- package/src/toolbar/AbstractToolbar.scss +3 -0
- package/src/toolbar/EdgeToolbar.scss +4 -1
- package/src/toolbar/widgets/DocumentPropertiesWidget.scss +12 -0
- package/src/toolbar/widgets/components/makeGridSelector.scss +6 -1
- package/src/tools/ScrollbarTool.scss +57 -0
- package/src/tools/{SoundUITool.css → SoundUITool.scss} +4 -0
- package/src/tools/tools.scss +2 -1
@@ -127,6 +127,50 @@ class Stroke extends AbstractComponent_1.default {
|
|
127
127
|
}
|
128
128
|
return false;
|
129
129
|
}
|
130
|
+
intersectsRect(rect) {
|
131
|
+
// AbstractComponent::intersectsRect can be inexact for strokes with non-zero
|
132
|
+
// stroke radius (has many false negatives). As such, additional checks are
|
133
|
+
// done here, before passing to the superclass.
|
134
|
+
if (!rect.intersects(this.getBBox())) {
|
135
|
+
return false;
|
136
|
+
}
|
137
|
+
// The following check only checks for the positive case:
|
138
|
+
// Sample a set of points that are known to be within each part of this
|
139
|
+
// stroke. For example, the points marked with an "x" below:
|
140
|
+
// ___________________
|
141
|
+
// / \
|
142
|
+
// | x x |
|
143
|
+
// \_____________ |
|
144
|
+
// | x |
|
145
|
+
// \_____/
|
146
|
+
//
|
147
|
+
// Because we don't want the following case to result in selection,
|
148
|
+
// __________________
|
149
|
+
// /.___. \
|
150
|
+
// || x | x | <- /* The
|
151
|
+
// |·---· | .___.
|
152
|
+
// \____________ | | |
|
153
|
+
// | x | ·---·
|
154
|
+
// \_____/ denotes the input rectangle */
|
155
|
+
//
|
156
|
+
// we need to ensure that the rectangle intersects each point **and** the
|
157
|
+
// edge of the rectangle.
|
158
|
+
for (const part of this.parts) {
|
159
|
+
// As such, we need to shrink the input rectangle to verify that the original,
|
160
|
+
// unshrunken rectangle would have intersected the edge of the stroke if it
|
161
|
+
// intersects a point within the stroke.
|
162
|
+
const interiorRect = rect.grownBy(-(part.style.stroke?.width ?? 0));
|
163
|
+
if (interiorRect.area === 0) {
|
164
|
+
continue;
|
165
|
+
}
|
166
|
+
for (const point of part.path.startEndPoints()) {
|
167
|
+
if (interiorRect.containsPoint(point)) {
|
168
|
+
return true;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
return super.intersectsRect(rect);
|
173
|
+
}
|
130
174
|
render(canvas, visibleRect) {
|
131
175
|
canvas.startObject(this.getBBox());
|
132
176
|
for (const part of this.parts) {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { LineSegment2, Mat33, Rect2 } from '@js-draw/math';
|
2
2
|
import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
|
3
|
-
import AbstractComponent from './AbstractComponent';
|
3
|
+
import AbstractComponent, { ComponentSizingMode } from './AbstractComponent';
|
4
4
|
import { ImageComponentLocalization } from './localization';
|
5
5
|
export default class UnknownSVGObject extends AbstractComponent {
|
6
6
|
private svgObject;
|
@@ -10,6 +10,7 @@ export default class UnknownSVGObject extends AbstractComponent {
|
|
10
10
|
intersects(lineSegment: LineSegment2): boolean;
|
11
11
|
protected applyTransformation(_affineTransfm: Mat33): void;
|
12
12
|
isSelectable(): boolean;
|
13
|
+
getSizingMode(): ComponentSizingMode;
|
13
14
|
protected createClone(): AbstractComponent;
|
14
15
|
description(localization: ImageComponentLocalization): string;
|
15
16
|
protected serializeToJSON(): string | null;
|
@@ -4,13 +4,36 @@
|
|
4
4
|
// @internal
|
5
5
|
// @packageDocumentation
|
6
6
|
//
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
8
|
+
if (k2 === undefined) k2 = k;
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
12
|
+
}
|
13
|
+
Object.defineProperty(o, k2, desc);
|
14
|
+
}) : (function(o, m, k, k2) {
|
15
|
+
if (k2 === undefined) k2 = k;
|
16
|
+
o[k2] = m[k];
|
17
|
+
}));
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
20
|
+
}) : function(o, v) {
|
21
|
+
o["default"] = v;
|
22
|
+
});
|
23
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
24
|
+
if (mod && mod.__esModule) return mod;
|
25
|
+
var result = {};
|
26
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
27
|
+
__setModuleDefault(result, mod);
|
28
|
+
return result;
|
29
|
+
};
|
7
30
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
8
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
9
32
|
};
|
10
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
11
34
|
const math_1 = require("@js-draw/math");
|
12
35
|
const SVGRenderer_1 = __importDefault(require("../rendering/renderers/SVGRenderer"));
|
13
|
-
const AbstractComponent_1 =
|
36
|
+
const AbstractComponent_1 = __importStar(require("./AbstractComponent"));
|
14
37
|
const componentId = 'unknown-svg-object';
|
15
38
|
class UnknownSVGObject extends AbstractComponent_1.default {
|
16
39
|
constructor(svgObject) {
|
@@ -35,6 +58,12 @@ class UnknownSVGObject extends AbstractComponent_1.default {
|
|
35
58
|
isSelectable() {
|
36
59
|
return false;
|
37
60
|
}
|
61
|
+
getSizingMode() {
|
62
|
+
// This component can be shown anywhere (it won't be
|
63
|
+
// visible to the user, it just needs to be saved with
|
64
|
+
// the image).
|
65
|
+
return AbstractComponent_1.ComponentSizingMode.Anywhere;
|
66
|
+
}
|
38
67
|
createClone() {
|
39
68
|
return new UnknownSVGObject(this.svgObject.cloneNode(true));
|
40
69
|
}
|
@@ -10,7 +10,7 @@ import TextComponent from './TextComponent';
|
|
10
10
|
import ImageComponent from './ImageComponent';
|
11
11
|
import RestyleableComponent from './RestylableComponent';
|
12
12
|
import { createRestyleComponentCommand, isRestylableComponent, ComponentStyle as RestyleableComponentStyle } from './RestylableComponent';
|
13
|
-
import BackgroundComponent from './BackgroundComponent';
|
13
|
+
import BackgroundComponent, { BackgroundType } from './BackgroundComponent';
|
14
14
|
export { Stroke, RestyleableComponent, createRestyleComponentCommand, isRestylableComponent, RestyleableComponentStyle, TextComponent,
|
15
15
|
/** @deprecated use {@link TextComponent} */
|
16
|
-
TextComponent as Text, Stroke as StrokeComponent, BackgroundComponent, ImageComponent, };
|
16
|
+
TextComponent as Text, Stroke as StrokeComponent, BackgroundComponent, BackgroundType as BackgroundComponentBackgroundType, ImageComponent, };
|
@@ -10,14 +10,26 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
10
10
|
if (k2 === undefined) k2 = k;
|
11
11
|
o[k2] = m[k];
|
12
12
|
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
13
18
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
19
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
20
|
};
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
22
|
+
if (mod && mod.__esModule) return mod;
|
23
|
+
var result = {};
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
25
|
+
__setModuleDefault(result, mod);
|
26
|
+
return result;
|
27
|
+
};
|
16
28
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
17
29
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
30
|
};
|
19
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
-
exports.ImageComponent = exports.BackgroundComponent = exports.StrokeComponent = exports.Text = exports.TextComponent = exports.isRestylableComponent = exports.createRestyleComponentCommand = exports.Stroke = exports.AbstractComponent = exports.StrokeSmoother = exports.makeOutlinedCircleBuilder = exports.makePressureSensitiveFreehandLineBuilder = exports.makeFreehandLineBuilder = void 0;
|
32
|
+
exports.ImageComponent = exports.BackgroundComponentBackgroundType = exports.BackgroundComponent = exports.StrokeComponent = exports.Text = exports.TextComponent = exports.isRestylableComponent = exports.createRestyleComponentCommand = exports.Stroke = exports.AbstractComponent = exports.StrokeSmoother = exports.makeOutlinedCircleBuilder = exports.makePressureSensitiveFreehandLineBuilder = exports.makeFreehandLineBuilder = void 0;
|
21
33
|
__exportStar(require("./builders/types"), exports);
|
22
34
|
var FreehandLineBuilder_1 = require("./builders/FreehandLineBuilder");
|
23
35
|
Object.defineProperty(exports, "makeFreehandLineBuilder", { enumerable: true, get: function () { return FreehandLineBuilder_1.makeFreehandLineBuilder; } });
|
@@ -41,5 +53,6 @@ exports.ImageComponent = ImageComponent_1.default;
|
|
41
53
|
const RestylableComponent_1 = require("./RestylableComponent");
|
42
54
|
Object.defineProperty(exports, "createRestyleComponentCommand", { enumerable: true, get: function () { return RestylableComponent_1.createRestyleComponentCommand; } });
|
43
55
|
Object.defineProperty(exports, "isRestylableComponent", { enumerable: true, get: function () { return RestylableComponent_1.isRestylableComponent; } });
|
44
|
-
const BackgroundComponent_1 =
|
56
|
+
const BackgroundComponent_1 = __importStar(require("./BackgroundComponent"));
|
45
57
|
exports.BackgroundComponent = BackgroundComponent_1.default;
|
58
|
+
Object.defineProperty(exports, "BackgroundComponentBackgroundType", { enumerable: true, get: function () { return BackgroundComponent_1.BackgroundType; } });
|
package/dist/cjs/lib.d.ts
CHANGED
@@ -2,52 +2,9 @@
|
|
2
2
|
* The main entrypoint for the NPM package. Everything exported by this file
|
3
3
|
* is available through the [`js-draw` package](https://www.npmjs.com/package/js-draw).
|
4
4
|
*
|
5
|
-
*
|
6
|
-
* ```ts,runnable
|
7
|
-
* import { Editor, Vec3, Mat33, ToolbarWidgetTag } from 'js-draw';
|
5
|
+
* ## Example
|
8
6
|
*
|
9
|
-
*
|
10
|
-
* import { MaterialIconProvider } from '@js-draw/material-icons';
|
11
|
-
*
|
12
|
-
* // Apply js-draw CSS
|
13
|
-
* import 'js-draw/styles';
|
14
|
-
* // If your bundler doesn't support the above, try
|
15
|
-
* // import 'js-draw/bundledStyles';
|
16
|
-
*
|
17
|
-
* (async () => {
|
18
|
-
* const editor = new Editor(document.body, {
|
19
|
-
* iconProvider: new MaterialIconProvider(),
|
20
|
-
* });
|
21
|
-
* const toolbar = editor.addToolbar();
|
22
|
-
*
|
23
|
-
* // Increases the minimum height of the editor
|
24
|
-
* editor.getRootElement().style.height = '600px';
|
25
|
-
*
|
26
|
-
* // Loads from SVG data
|
27
|
-
* await editor.loadFromSVG(`
|
28
|
-
* <svg viewBox="0 0 500 500" width="500" height="500" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
|
29
|
-
* <style id="js-draw-style-sheet">path{stroke-linecap:round;stroke-linejoin:round;}text{white-space:pre;}</style>
|
30
|
-
* <path d="M500,500L500,0L0,0L0,500L500,500" fill="#aaa" class="js-draw-image-background"></path>
|
31
|
-
* <text style="transform: matrix(1, 0, 0, 1, 57, 192); font-family: serif; font-size: 32px; fill: #111;">Testing...</text>
|
32
|
-
* </svg>
|
33
|
-
* `);
|
34
|
-
*
|
35
|
-
* // Adding tags to a toolbar button allows different styles to be applied.
|
36
|
-
* // Also see addActionButton.
|
37
|
-
* const buttonLabels = [ ToolbarWidgetTag.Save ];
|
38
|
-
*
|
39
|
-
* toolbar.addSaveButton(() => {
|
40
|
-
* const saveData = editor.toSVG().outerHTML;
|
41
|
-
*
|
42
|
-
* // Do something with saveData
|
43
|
-
* });
|
44
|
-
*
|
45
|
-
* toolbar.addExitButton(() => {
|
46
|
-
* // Save/confirm exiting here?
|
47
|
-
* editor.remove();
|
48
|
-
* });
|
49
|
-
* })();
|
50
|
-
* ```
|
7
|
+
* [[include:doc-pages/inline-examples/main-js-draw-example.md]]
|
51
8
|
*
|
52
9
|
* @see
|
53
10
|
* - {@link Editor}
|
package/dist/cjs/lib.js
CHANGED
@@ -3,52 +3,9 @@
|
|
3
3
|
* The main entrypoint for the NPM package. Everything exported by this file
|
4
4
|
* is available through the [`js-draw` package](https://www.npmjs.com/package/js-draw).
|
5
5
|
*
|
6
|
-
*
|
7
|
-
* ```ts,runnable
|
8
|
-
* import { Editor, Vec3, Mat33, ToolbarWidgetTag } from 'js-draw';
|
6
|
+
* ## Example
|
9
7
|
*
|
10
|
-
*
|
11
|
-
* import { MaterialIconProvider } from '@js-draw/material-icons';
|
12
|
-
*
|
13
|
-
* // Apply js-draw CSS
|
14
|
-
* import 'js-draw/styles';
|
15
|
-
* // If your bundler doesn't support the above, try
|
16
|
-
* // import 'js-draw/bundledStyles';
|
17
|
-
*
|
18
|
-
* (async () => {
|
19
|
-
* const editor = new Editor(document.body, {
|
20
|
-
* iconProvider: new MaterialIconProvider(),
|
21
|
-
* });
|
22
|
-
* const toolbar = editor.addToolbar();
|
23
|
-
*
|
24
|
-
* // Increases the minimum height of the editor
|
25
|
-
* editor.getRootElement().style.height = '600px';
|
26
|
-
*
|
27
|
-
* // Loads from SVG data
|
28
|
-
* await editor.loadFromSVG(`
|
29
|
-
* <svg viewBox="0 0 500 500" width="500" height="500" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
|
30
|
-
* <style id="js-draw-style-sheet">path{stroke-linecap:round;stroke-linejoin:round;}text{white-space:pre;}</style>
|
31
|
-
* <path d="M500,500L500,0L0,0L0,500L500,500" fill="#aaa" class="js-draw-image-background"></path>
|
32
|
-
* <text style="transform: matrix(1, 0, 0, 1, 57, 192); font-family: serif; font-size: 32px; fill: #111;">Testing...</text>
|
33
|
-
* </svg>
|
34
|
-
* `);
|
35
|
-
*
|
36
|
-
* // Adding tags to a toolbar button allows different styles to be applied.
|
37
|
-
* // Also see addActionButton.
|
38
|
-
* const buttonLabels = [ ToolbarWidgetTag.Save ];
|
39
|
-
*
|
40
|
-
* toolbar.addSaveButton(() => {
|
41
|
-
* const saveData = editor.toSVG().outerHTML;
|
42
|
-
*
|
43
|
-
* // Do something with saveData
|
44
|
-
* });
|
45
|
-
*
|
46
|
-
* toolbar.addExitButton(() => {
|
47
|
-
* // Save/confirm exiting here?
|
48
|
-
* editor.remove();
|
49
|
-
* });
|
50
|
-
* })();
|
51
|
-
* ```
|
8
|
+
* [[include:doc-pages/inline-examples/main-js-draw-example.md]]
|
52
9
|
*
|
53
10
|
* @see
|
54
11
|
* - {@link Editor}
|
@@ -6,6 +6,7 @@ interface RenderablePathSpec {
|
|
6
6
|
style: RenderingStyle;
|
7
7
|
path?: Path;
|
8
8
|
}
|
9
|
+
/** Converts a renderable path (a path with a `startPoint`, `commands`, and `style`). */
|
9
10
|
export declare const pathFromRenderable: (renderable: RenderablePathSpec) => Path;
|
10
11
|
export declare const pathToRenderable: (path: Path, style: RenderingStyle) => RenderablePathSpec;
|
11
12
|
/**
|
@@ -2,6 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.visualEquivalent = exports.pathToRenderable = exports.pathFromRenderable = void 0;
|
4
4
|
const math_1 = require("@js-draw/math");
|
5
|
+
/** Converts a renderable path (a path with a `startPoint`, `commands`, and `style`). */
|
5
6
|
const pathFromRenderable = (renderable) => {
|
6
7
|
if (renderable.path) {
|
7
8
|
return renderable.path;
|
@@ -5,3 +5,4 @@ export { default as CanvasRenderer } from './renderers/CanvasRenderer';
|
|
5
5
|
export { default as Display, RenderingMode } from './Display';
|
6
6
|
export { default as TextRenderingStyle } from './TextRenderingStyle';
|
7
7
|
export { default as RenderingStyle } from './RenderingStyle';
|
8
|
+
export { pathToRenderable, pathFromRenderable, visualEquivalent as pathVisualEquivalent, default as RenderablePathSpec, } from './RenderablePathSpec';
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.RenderingMode = exports.Display = exports.CanvasRenderer = exports.SVGRenderer = exports.DummyRenderer = exports.AbstractRenderer = void 0;
|
6
|
+
exports.pathVisualEquivalent = exports.pathFromRenderable = exports.pathToRenderable = exports.RenderingMode = exports.Display = exports.CanvasRenderer = exports.SVGRenderer = exports.DummyRenderer = exports.AbstractRenderer = void 0;
|
7
7
|
var AbstractRenderer_1 = require("./renderers/AbstractRenderer");
|
8
8
|
Object.defineProperty(exports, "AbstractRenderer", { enumerable: true, get: function () { return __importDefault(AbstractRenderer_1).default; } });
|
9
9
|
var DummyRenderer_1 = require("./renderers/DummyRenderer");
|
@@ -15,3 +15,7 @@ Object.defineProperty(exports, "CanvasRenderer", { enumerable: true, get: functi
|
|
15
15
|
var Display_1 = require("./Display");
|
16
16
|
Object.defineProperty(exports, "Display", { enumerable: true, get: function () { return __importDefault(Display_1).default; } });
|
17
17
|
Object.defineProperty(exports, "RenderingMode", { enumerable: true, get: function () { return Display_1.RenderingMode; } });
|
18
|
+
var RenderablePathSpec_1 = require("./RenderablePathSpec");
|
19
|
+
Object.defineProperty(exports, "pathToRenderable", { enumerable: true, get: function () { return RenderablePathSpec_1.pathToRenderable; } });
|
20
|
+
Object.defineProperty(exports, "pathFromRenderable", { enumerable: true, get: function () { return RenderablePathSpec_1.pathFromRenderable; } });
|
21
|
+
Object.defineProperty(exports, "pathVisualEquivalent", { enumerable: true, get: function () { return RenderablePathSpec_1.visualEquivalent; } });
|
@@ -65,7 +65,7 @@ class AbstractRenderer {
|
|
65
65
|
drawPath(path) {
|
66
66
|
// If we're being called outside of an object,
|
67
67
|
// we can't delay rendering
|
68
|
-
if (this.objectLevel === 0) {
|
68
|
+
if (this.objectLevel === 0 || this.currentPaths === null) {
|
69
69
|
this.currentPaths = [path];
|
70
70
|
this.flushPath();
|
71
71
|
this.currentPaths = null;
|
@@ -33,8 +33,8 @@ export default class KeyboardShortcutManager {
|
|
33
33
|
* const shortcutId = 'io.github.personalizedrefrigerator.js-draw.select-all';
|
34
34
|
*
|
35
35
|
* // Associate two shortcuts with the same ID
|
36
|
-
* const shortcut1 =
|
37
|
-
* const shortcut2 =
|
36
|
+
* const shortcut1 = KeyBinding.fromString('ctrlOrMeta+a');
|
37
|
+
* const shortcut2 = KeyBinding.fromString('ctrlOrMeta+shift+a');
|
38
38
|
* KeyboardShortcutManager.registerDefaultKeyboardShortcut(
|
39
39
|
* shortcutId,
|
40
40
|
* [ shortcut1, shortcut2 ],
|
@@ -59,8 +59,8 @@ class KeyboardShortcutManager {
|
|
59
59
|
* const shortcutId = 'io.github.personalizedrefrigerator.js-draw.select-all';
|
60
60
|
*
|
61
61
|
* // Associate two shortcuts with the same ID
|
62
|
-
* const shortcut1 =
|
63
|
-
* const shortcut2 =
|
62
|
+
* const shortcut1 = KeyBinding.fromString('ctrlOrMeta+a');
|
63
|
+
* const shortcut2 = KeyBinding.fromString('ctrlOrMeta+shift+a');
|
64
64
|
* KeyboardShortcutManager.registerDefaultKeyboardShortcut(
|
65
65
|
* shortcutId,
|
66
66
|
* [ shortcut1, shortcut2 ],
|
@@ -56,6 +56,11 @@ class BaseWidget {
|
|
56
56
|
this.label = document.createElement('label');
|
57
57
|
this.button.setAttribute('role', 'button');
|
58
58
|
this.button.tabIndex = 0;
|
59
|
+
// Disable the context menu. This allows long-press gestures to trigger the button's
|
60
|
+
// tooltip instead.
|
61
|
+
this.button.oncontextmenu = event => {
|
62
|
+
event.preventDefault();
|
63
|
+
};
|
59
64
|
const toolbarShortcutHandlers = this.editor.toolController.getMatchingTools(ToolbarShortcutHandler_1.default);
|
60
65
|
// If the onKeyPress function has been extended and the editor is configured to send keypress events to
|
61
66
|
// toolbar widgets,
|
@@ -122,39 +122,49 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
122
122
|
const container = document.createElement('div');
|
123
123
|
container.classList.add(`${constants_1.toolbarCSSPrefix}spacedList`, `${constants_1.toolbarCSSPrefix}nonbutton-controls-main-list`, `${constants_1.toolbarCSSPrefix}document-properties-widget`);
|
124
124
|
// Background color input
|
125
|
-
const
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
this.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
125
|
+
const makeBackgroundColorInput = () => {
|
126
|
+
const backgroundColorRow = document.createElement('div');
|
127
|
+
const backgroundColorLabel = document.createElement('label');
|
128
|
+
backgroundColorLabel.innerText = this.localizationTable.backgroundColor;
|
129
|
+
const { input: colorInput, container: backgroundColorInputContainer, setValue: setBgColorInputValue } = (0, makeColorInput_1.default)(this.editor, color => {
|
130
|
+
if (!color.eq(this.getBackgroundColor())) {
|
131
|
+
this.setBackgroundColor(color);
|
132
|
+
}
|
133
|
+
});
|
134
|
+
colorInput.id = `${constants_1.toolbarCSSPrefix}docPropertiesColorInput-${DocumentPropertiesWidget.idCounter++}`;
|
135
|
+
backgroundColorLabel.htmlFor = colorInput.id;
|
136
|
+
backgroundColorRow.replaceChildren(backgroundColorLabel, backgroundColorInputContainer);
|
137
|
+
return { setBgColorInputValue, backgroundColorRow };
|
138
|
+
};
|
139
|
+
const { backgroundColorRow, setBgColorInputValue } = makeBackgroundColorInput();
|
140
|
+
const makeCheckboxRow = (labelText, onChange) => {
|
141
|
+
const rowContainer = document.createElement('div');
|
142
|
+
const labelElement = document.createElement('label');
|
143
|
+
const checkboxElement = document.createElement('input');
|
144
|
+
checkboxElement.id = `${constants_1.toolbarCSSPrefix}docPropertiesCheckbox-${DocumentPropertiesWidget.idCounter++}`;
|
145
|
+
labelElement.htmlFor = checkboxElement.id;
|
146
|
+
checkboxElement.type = 'checkbox';
|
147
|
+
labelElement.innerText = labelText;
|
148
|
+
checkboxElement.oninput = () => {
|
149
|
+
onChange(checkboxElement.checked);
|
150
|
+
};
|
151
|
+
rowContainer.replaceChildren(labelElement, checkboxElement);
|
152
|
+
return { container: rowContainer, checkbox: checkboxElement };
|
153
|
+
};
|
136
154
|
// Background style selector
|
137
|
-
const useGridRow =
|
138
|
-
const useGridLabel = document.createElement('label');
|
139
|
-
const useGridCheckbox = document.createElement('input');
|
140
|
-
useGridCheckbox.id = `${constants_1.toolbarCSSPrefix}docPropertiesUseGridCheckbox-${DocumentPropertiesWidget.idCounter++}`;
|
141
|
-
useGridLabel.htmlFor = useGridCheckbox.id;
|
142
|
-
useGridCheckbox.type = 'checkbox';
|
143
|
-
useGridLabel.innerText = this.localizationTable.useGridOption;
|
144
|
-
useGridCheckbox.oninput = () => {
|
155
|
+
const { container: useGridRow, checkbox: useGridCheckbox } = makeCheckboxRow(this.localizationTable.useGridOption, (checked) => {
|
145
156
|
const prevBackgroundType = this.getBackgroundType();
|
146
157
|
const wasGrid = prevBackgroundType === BackgroundComponent_1.BackgroundType.Grid;
|
147
|
-
if (wasGrid ===
|
158
|
+
if (wasGrid === checked) {
|
148
159
|
// Already the requested background type.
|
149
160
|
return;
|
150
161
|
}
|
151
162
|
let newBackgroundType = BackgroundComponent_1.BackgroundType.SolidColor;
|
152
|
-
if (
|
163
|
+
if (checked) {
|
153
164
|
newBackgroundType = BackgroundComponent_1.BackgroundType.Grid;
|
154
165
|
}
|
155
166
|
this.editor.dispatch(this.setBackgroundType(newBackgroundType));
|
156
|
-
};
|
157
|
-
useGridRow.replaceChildren(useGridLabel, useGridCheckbox);
|
167
|
+
});
|
158
168
|
// Adds a width/height input
|
159
169
|
const addDimensionRow = (labelContent, onChange) => {
|
160
170
|
const row = document.createElement('div');
|
@@ -167,15 +177,25 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
167
177
|
label.htmlFor = input.id;
|
168
178
|
input.style.flexGrow = '2';
|
169
179
|
input.style.width = '25px';
|
170
|
-
row.style.display = 'flex';
|
171
180
|
input.oninput = () => {
|
172
181
|
onChange(parseFloat(input.value));
|
173
182
|
};
|
183
|
+
row.classList.add('js-draw-size-input-row');
|
174
184
|
row.replaceChildren(label, input);
|
175
185
|
return {
|
176
186
|
setValue: (value) => {
|
177
187
|
input.value = value.toString();
|
178
188
|
},
|
189
|
+
setIsAutomaticSize: (automatic) => {
|
190
|
+
input.disabled = automatic;
|
191
|
+
const automaticSizeClass = 'size-input-row--automatic-size';
|
192
|
+
if (automatic) {
|
193
|
+
row.classList.add(automaticSizeClass);
|
194
|
+
}
|
195
|
+
else {
|
196
|
+
row.classList.remove(automaticSizeClass);
|
197
|
+
}
|
198
|
+
},
|
179
199
|
element: row,
|
180
200
|
};
|
181
201
|
};
|
@@ -185,6 +205,11 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
185
205
|
const imageHeightRow = addDimensionRow(this.localizationTable.imageHeightOption, (value) => {
|
186
206
|
this.updateImportExportRectSize({ height: value });
|
187
207
|
});
|
208
|
+
// The autoresize checkbox
|
209
|
+
const { container: auroresizeRow, checkbox: autoresizeCheckbox } = makeCheckboxRow(this.localizationTable.enableAutoresizeOption, (checked) => {
|
210
|
+
const image = this.editor.image;
|
211
|
+
this.editor.dispatch(image.setAutoresizeEnabled(checked));
|
212
|
+
});
|
188
213
|
// The "About..." button
|
189
214
|
const aboutButton = document.createElement('button');
|
190
215
|
aboutButton.classList.add('about-button');
|
@@ -194,13 +219,17 @@ class DocumentPropertiesWidget extends BaseWidget_1.default {
|
|
194
219
|
};
|
195
220
|
this.updateDropdownContent = () => {
|
196
221
|
setBgColorInputValue(this.getBackgroundColor());
|
222
|
+
const autoresize = this.editor.image.getAutoresizeEnabled();
|
197
223
|
const importExportRect = this.editor.getImportExportRect();
|
198
224
|
imageWidthRow.setValue(importExportRect.width);
|
199
225
|
imageHeightRow.setValue(importExportRect.height);
|
226
|
+
autoresizeCheckbox.checked = autoresize;
|
227
|
+
imageWidthRow.setIsAutomaticSize(autoresize);
|
228
|
+
imageHeightRow.setIsAutomaticSize(autoresize);
|
200
229
|
useGridCheckbox.checked = this.getBackgroundType() === BackgroundComponent_1.BackgroundType.Grid;
|
201
230
|
};
|
202
231
|
this.updateDropdownContent();
|
203
|
-
container.replaceChildren(backgroundColorRow, useGridRow, imageWidthRow.element, imageHeightRow.element, aboutButton);
|
232
|
+
container.replaceChildren(backgroundColorRow, useGridRow, imageWidthRow.element, imageHeightRow.element, auroresizeRow, aboutButton);
|
204
233
|
dropdown.replaceChildren(container);
|
205
234
|
return true;
|
206
235
|
}
|
@@ -73,6 +73,14 @@ labelText, defaultId, choices) => {
|
|
73
73
|
}
|
74
74
|
updateButtonCSS();
|
75
75
|
};
|
76
|
+
button.onfocus = () => {
|
77
|
+
if (buttonContainer.querySelector(':focus-visible')) {
|
78
|
+
buttonContainer.classList.add('focus-visible');
|
79
|
+
}
|
80
|
+
};
|
81
|
+
button.onblur = () => {
|
82
|
+
buttonContainer.classList.remove('focus-visible');
|
83
|
+
};
|
76
84
|
buttonContainer.replaceChildren(button, labelContainer);
|
77
85
|
menuContainer.appendChild(buttonContainer);
|
78
86
|
// Set whether the current button is checked
|
@@ -212,24 +212,26 @@ class PanZoom extends BaseTool_1.default {
|
|
212
212
|
this.lastScreenCenter = screenCenter;
|
213
213
|
this.lastDist = dist;
|
214
214
|
this.transform = Viewport_1.Viewport.transformBy(this.transform.transform.rightMul(transformUpdate));
|
215
|
+
return transformUpdate;
|
215
216
|
}
|
216
217
|
handleOneFingerMove(pointer) {
|
217
218
|
const delta = this.getCenterDelta(pointer.screenPos);
|
218
|
-
|
219
|
+
const transformUpdate = math_1.Mat33.translation(delta);
|
220
|
+
this.transform = Viewport_1.Viewport.transformBy(this.transform.transform.rightMul(transformUpdate));
|
219
221
|
this.updateVelocity(pointer.screenPos);
|
220
222
|
this.lastScreenCenter = pointer.screenPos;
|
223
|
+
return transformUpdate;
|
221
224
|
}
|
222
225
|
onPointerMove({ allPointers }) {
|
223
226
|
this.transform ??= Viewport_1.Viewport.transformBy(math_1.Mat33.identity);
|
224
|
-
|
227
|
+
let transformUpdate = math_1.Mat33.identity;
|
225
228
|
if (allPointers.length === 2) {
|
226
|
-
this.handleTwoFingerMove(allPointers);
|
229
|
+
transformUpdate = this.handleTwoFingerMove(allPointers);
|
227
230
|
}
|
228
231
|
else if (allPointers.length === 1) {
|
229
|
-
this.handleOneFingerMove(allPointers[0]);
|
232
|
+
transformUpdate = this.handleOneFingerMove(allPointers[0]);
|
230
233
|
}
|
231
|
-
|
232
|
-
this.transform.apply(this.editor);
|
234
|
+
Viewport_1.Viewport.transformBy(transformUpdate).apply(this.editor);
|
233
235
|
this.lastTimestamp = performance.now();
|
234
236
|
}
|
235
237
|
onPointerUp(event) {
|
@@ -309,8 +311,11 @@ class PanZoom extends BaseTool_1.default {
|
|
309
311
|
const toCanvas = this.editor.viewport.screenToCanvasTransform;
|
310
312
|
// Transform without including translation
|
311
313
|
const translation = toCanvas.transformVec3(math_1.Vec3.of(-delta.x, -delta.y, 0));
|
312
|
-
|
313
|
-
|
314
|
+
let pinchAmount = delta.z;
|
315
|
+
// Clamp the magnitude of pinchAmount
|
316
|
+
pinchAmount = Math.atan(pinchAmount / 2) * 2;
|
317
|
+
const pinchZoomScaleFactor = 1.04;
|
318
|
+
const transformUpdate = math_1.Mat33.scaling2D(Math.max(0.4, Math.min(Math.pow(pinchZoomScaleFactor, -pinchAmount), 4)), canvasPos).rightMul(math_1.Mat33.translation(translation));
|
314
319
|
this.updateTransform(transformUpdate, true);
|
315
320
|
return true;
|
316
321
|
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import Editor from '../Editor';
|
2
|
+
import BaseTool from './BaseTool';
|
3
|
+
/**
|
4
|
+
* This tool, when enabled, renders scrollbars reflecting the current position
|
5
|
+
* of the view relative to the import/export area of the image.
|
6
|
+
*
|
7
|
+
* **Note**: These scrollbars are currently not draggable. This may change in
|
8
|
+
* a future release.
|
9
|
+
*/
|
10
|
+
export default class ScrollbarTool extends BaseTool {
|
11
|
+
private editor;
|
12
|
+
private scrollbarOverlay;
|
13
|
+
private verticalScrollbar;
|
14
|
+
private horizontalScrollbar;
|
15
|
+
constructor(editor: Editor);
|
16
|
+
private fadeOutTimeout;
|
17
|
+
private updateScrollbars;
|
18
|
+
}
|