js-draw 1.22.0 → 1.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/bundle.js +1 -1
  3. package/dist/cjs/Editor.d.ts +1 -3
  4. package/dist/cjs/Editor.js +2 -4
  5. package/dist/cjs/SVGLoader/SVGLoader.js +2 -0
  6. package/dist/cjs/Viewport.d.ts +1 -1
  7. package/dist/cjs/Viewport.js +1 -1
  8. package/dist/cjs/components/AbstractComponent.d.ts +1 -1
  9. package/dist/cjs/components/AbstractComponent.js +1 -1
  10. package/dist/cjs/components/builders/ArrowBuilder.d.ts +1 -1
  11. package/dist/cjs/components/builders/ArrowBuilder.js +1 -1
  12. package/dist/cjs/image/EditorImage.d.ts +30 -7
  13. package/dist/cjs/image/EditorImage.js +30 -7
  14. package/dist/cjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
  15. package/dist/cjs/rendering/renderers/CanvasRenderer.js +2 -25
  16. package/dist/cjs/rendering/renderers/SVGRenderer.js +2 -2
  17. package/dist/cjs/toolbar/AbstractToolbar.d.ts +19 -0
  18. package/dist/cjs/toolbar/AbstractToolbar.js +19 -0
  19. package/dist/cjs/toolbar/IconProvider.d.ts +5 -1
  20. package/dist/cjs/toolbar/IconProvider.js +112 -146
  21. package/dist/cjs/toolbar/localization.js +2 -2
  22. package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +1 -1
  23. package/dist/cjs/toolbar/widgets/BaseWidget.js +1 -1
  24. package/dist/cjs/tools/PanZoom.js +1 -1
  25. package/dist/cjs/tools/Pen.d.ts +13 -0
  26. package/dist/cjs/tools/Pen.js +13 -0
  27. package/dist/cjs/tools/lib.d.ts +1 -0
  28. package/dist/cjs/tools/lib.js +3 -1
  29. package/dist/cjs/util/cloneElementWithStyles.js +1 -1
  30. package/dist/cjs/util/createElement.d.ts +62 -0
  31. package/dist/cjs/util/createElement.js +53 -0
  32. package/dist/cjs/version.js +1 -1
  33. package/dist/mjs/Editor.d.ts +1 -3
  34. package/dist/mjs/Editor.mjs +2 -4
  35. package/dist/mjs/SVGLoader/SVGLoader.mjs +2 -0
  36. package/dist/mjs/Viewport.d.ts +1 -1
  37. package/dist/mjs/Viewport.mjs +1 -1
  38. package/dist/mjs/components/AbstractComponent.d.ts +1 -1
  39. package/dist/mjs/components/AbstractComponent.mjs +1 -1
  40. package/dist/mjs/components/builders/ArrowBuilder.d.ts +1 -1
  41. package/dist/mjs/components/builders/ArrowBuilder.mjs +1 -1
  42. package/dist/mjs/image/EditorImage.d.ts +30 -7
  43. package/dist/mjs/image/EditorImage.mjs +30 -7
  44. package/dist/mjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
  45. package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +2 -25
  46. package/dist/mjs/rendering/renderers/SVGRenderer.mjs +2 -2
  47. package/dist/mjs/toolbar/AbstractToolbar.d.ts +19 -0
  48. package/dist/mjs/toolbar/AbstractToolbar.mjs +19 -0
  49. package/dist/mjs/toolbar/IconProvider.d.ts +5 -1
  50. package/dist/mjs/toolbar/IconProvider.mjs +112 -146
  51. package/dist/mjs/toolbar/localization.mjs +2 -2
  52. package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +1 -1
  53. package/dist/mjs/toolbar/widgets/BaseWidget.mjs +1 -1
  54. package/dist/mjs/tools/PanZoom.mjs +1 -1
  55. package/dist/mjs/tools/Pen.d.ts +13 -0
  56. package/dist/mjs/tools/Pen.mjs +13 -0
  57. package/dist/mjs/tools/lib.d.ts +1 -0
  58. package/dist/mjs/tools/lib.mjs +1 -0
  59. package/dist/mjs/util/cloneElementWithStyles.mjs +1 -1
  60. package/dist/mjs/util/createElement.d.ts +62 -0
  61. package/dist/mjs/util/createElement.mjs +47 -0
  62. package/dist/mjs/version.mjs +1 -1
  63. package/package.json +4 -4
@@ -411,9 +411,7 @@ export declare class Editor {
411
411
  * Use this to show finalized commands that don't need to have `announceForAccessibility`
412
412
  * called.
413
413
  *
414
- * Prefer `command.apply(editor)` for incomplete commands. `dispatchNoAnnounce` may allow
415
- * clients to listen for the application of commands (e.g. `SerializableCommand`s so they can
416
- * be sent across the network), while `apply` does not.
414
+ * If `addToHistory` is `false`, this is equivalent to `command.apply(editor)`.
417
415
  *
418
416
  * @example
419
417
  * ```
@@ -137,7 +137,7 @@ class Editor {
137
137
  maxZoom: settings.maxZoom ?? 1e12,
138
138
  keyboardShortcutOverrides: settings.keyboardShortcutOverrides ?? {},
139
139
  iconProvider: settings.iconProvider ?? new IconProvider_1.default(),
140
- notices: [],
140
+ notices: settings.notices ?? [],
141
141
  appInfo: settings.appInfo ? { ...settings.appInfo } : null,
142
142
  pens: {
143
143
  additionalPenTypes: settings.pens?.additionalPenTypes ?? [],
@@ -755,9 +755,7 @@ class Editor {
755
755
  * Use this to show finalized commands that don't need to have `announceForAccessibility`
756
756
  * called.
757
757
  *
758
- * Prefer `command.apply(editor)` for incomplete commands. `dispatchNoAnnounce` may allow
759
- * clients to listen for the application of commands (e.g. `SerializableCommand`s so they can
760
- * be sent across the network), while `apply` does not.
758
+ * If `addToHistory` is `false`, this is equivalent to `command.apply(editor)`.
761
759
  *
762
760
  * @example
763
761
  * ```
@@ -561,6 +561,7 @@ class SVGLoader {
561
561
  const { svgElem, cleanUp } = (() => {
562
562
  // If the user requested an iframe load (the default) try to load with an iframe.
563
563
  // There are some cases (e.g. in a sandboxed iframe) where this doesn't work.
564
+ // TODO(v2): Use domParserLoad by default.
564
565
  if (!domParserLoad) {
565
566
  try {
566
567
  const sandbox = document.createElement('iframe');
@@ -600,6 +601,7 @@ class SVGLoader {
600
601
  `);
601
602
  sandboxDoc.close();
602
603
  const svgElem = sandboxDoc.createElementNS('http://www.w3.org/2000/svg', 'svg');
604
+ // eslint-disable-next-line no-unsanitized/property -- setting innerHTML in a sandboxed document.
603
605
  svgElem.innerHTML = text;
604
606
  sandboxDoc.body.appendChild(svgElem);
605
607
  const cleanUp = () => {
@@ -53,7 +53,7 @@ export declare class Viewport {
53
53
  /**
54
54
  * Snaps `canvasPos` to the nearest grid cell corner.
55
55
  *
56
- * @see {@link getGridSize} and {@link getScaleFactorToNearestPowerOf}.
56
+ * @see {@link getGridSize}.
57
57
  */
58
58
  snapToGrid(canvasPos: Point2): {
59
59
  readonly x: number;
@@ -107,7 +107,7 @@ class Viewport {
107
107
  /**
108
108
  * Snaps `canvasPos` to the nearest grid cell corner.
109
109
  *
110
- * @see {@link getGridSize} and {@link getScaleFactorToNearestPowerOf}.
110
+ * @see {@link getGridSize}.
111
111
  */
112
112
  snapToGrid(canvasPos) {
113
113
  const scaleFactor = this.getScaleFactorToNearestPowerOf(2);
@@ -122,7 +122,7 @@ export default abstract class AbstractComponent {
122
122
  * updates the editor.
123
123
  *
124
124
  * The transformed component is also moved to the top (use
125
- * {@link AbstractComponent.setZIndexAndTransformBy} to avoid this behavior).
125
+ * {@link AbstractComponent#setZIndexAndTransformBy} to avoid this behavior).
126
126
  */
127
127
  transformBy(affineTransfm: Mat33): SerializableCommand;
128
128
  setZIndex(newZIndex: number): SerializableCommand;
@@ -162,7 +162,7 @@ class AbstractComponent {
162
162
  * updates the editor.
163
163
  *
164
164
  * The transformed component is also moved to the top (use
165
- * {@link AbstractComponent.setZIndexAndTransformBy} to avoid this behavior).
165
+ * {@link AbstractComponent#setZIndexAndTransformBy} to avoid this behavior).
166
166
  */
167
167
  transformBy(affineTransfm) {
168
168
  return new AbstractComponent.TransformElementCommand(affineTransfm, this.getId(), this);
@@ -5,7 +5,7 @@ import Viewport from '../../Viewport';
5
5
  import AbstractComponent from '../AbstractComponent';
6
6
  import { ComponentBuilder, ComponentBuilderFactory } from './types';
7
7
  /**
8
- * Creates a stroke builder that generates arrows circles.
8
+ * Creates a stroke builder that generates arrows.
9
9
  *
10
10
  * Example:
11
11
  * [[include:doc-pages/inline-examples/changing-pen-types.md]]
@@ -8,7 +8,7 @@ const math_1 = require("@js-draw/math");
8
8
  const Stroke_1 = __importDefault(require("../Stroke"));
9
9
  const makeSnapToGridAutocorrect_1 = __importDefault(require("./autocorrect/makeSnapToGridAutocorrect"));
10
10
  /**
11
- * Creates a stroke builder that generates arrows circles.
11
+ * Creates a stroke builder that generates arrows.
12
12
  *
13
13
  * Example:
14
14
  * [[include:doc-pages/inline-examples/changing-pen-types.md]]
@@ -22,7 +22,20 @@ export type EditorImageNotifier = EventDispatcher<EditorImageEventType, {
22
22
  */
23
23
  export type PreRenderComponentCallback = (component: AbstractComponent, componentsProcessed: number, totalComponents: number) => Promise<boolean>;
24
24
  /**
25
- * Handles lookup/storage of elements in the image.
25
+ * @summary Handles lookup/storage of elements in the image.
26
+ *
27
+ * `js-draw` images are made up of a collection of {@link AbstractComponent}s (which
28
+ * includes {@link Stroke}s, {@link TextComponent}s, etc.). An `EditorImage`
29
+ * is the data structure that stores these components.
30
+ *
31
+ * Here's how to do a few common operations:
32
+ * - **Get all components in a {@link @js-draw/math!Rect2 | Rect2}**:
33
+ * {@link EditorImage.getElementsIntersectingRegion}.
34
+ * - **Draw an `EditorImage` onto a canvas/SVG**: {@link EditorImage.render}.
35
+ * - **Adding a new component**: {@link EditorImage.addElement}.
36
+ *
37
+ * **Example**:
38
+ * [[include:doc-pages/inline-examples/image-add-and-lookup.md]]
26
39
  */
27
40
  export default class EditorImage {
28
41
  private root;
@@ -40,10 +53,13 @@ export default class EditorImage {
40
53
  /** @internal */
41
54
  renderWithCache(screenRenderer: AbstractRenderer, cache: RenderingCache, viewport: Viewport): void;
42
55
  /**
43
- * Renders all nodes visible from `viewport` (or all nodes if `viewport = null`).
56
+ * Renders this image to the given `renderer`.
44
57
  *
45
- * `viewport` is used to improve rendering performance. If given, it must match
46
- * the viewport used by the `renderer` (if any).
58
+ * If `viewport` is non-null, only components that can be seen from that viewport
59
+ * will be rendered. If `viewport` is `null`, **all** components are rendered.
60
+ *
61
+ * **Example**:
62
+ * [[include:doc-pages/inline-examples/canvas-renderer.md]]
47
63
  */
48
64
  render(renderer: AbstractRenderer, viewport: Viewport | null): void;
49
65
  /**
@@ -63,14 +79,21 @@ export default class EditorImage {
63
79
  */
64
80
  renderAll(renderer: AbstractRenderer): void;
65
81
  /**
66
- * @returns all elements in the image, sorted by z-index. This can be slow for large images.
82
+ * @returns all elements in the image, sorted by z-index (low to high).
67
83
  *
68
- * Does not include background elements. See {@link getBackgroundComponents}.
84
+ * This can be slow for large images. If you only need all elemenst in part of the image,
85
+ * consider using {@link getElementsIntersectingRegion} instead.
86
+ *
87
+ * **Note**: The result does not include background elements. See {@link getBackgroundComponents}.
69
88
  */
70
89
  getAllElements(): AbstractComponent[];
71
90
  /** Returns the number of elements added to this image. @internal */
72
91
  estimateNumElements(): number;
73
- /** @returns a list of `AbstractComponent`s intersecting `region`, sorted by z-index. */
92
+ /**
93
+ * @returns a list of `AbstractComponent`s intersecting `region`, sorted by increasing z-index.
94
+ *
95
+ * Components in the background layer are only included if `includeBackground` is `true`.
96
+ */
74
97
  getElementsIntersectingRegion(region: Rect2, includeBackground?: boolean): AbstractComponent[];
75
98
  /** Called whenever (just after) an element is completely removed. @internal */
76
99
  onDestroyElement(elem: AbstractComponent): void;
@@ -51,7 +51,20 @@ var EditorImageEventType;
51
51
  })(EditorImageEventType || (exports.EditorImageEventType = EditorImageEventType = {}));
52
52
  let debugMode = false;
53
53
  /**
54
- * Handles lookup/storage of elements in the image.
54
+ * @summary Handles lookup/storage of elements in the image.
55
+ *
56
+ * `js-draw` images are made up of a collection of {@link AbstractComponent}s (which
57
+ * includes {@link Stroke}s, {@link TextComponent}s, etc.). An `EditorImage`
58
+ * is the data structure that stores these components.
59
+ *
60
+ * Here's how to do a few common operations:
61
+ * - **Get all components in a {@link @js-draw/math!Rect2 | Rect2}**:
62
+ * {@link EditorImage.getElementsIntersectingRegion}.
63
+ * - **Draw an `EditorImage` onto a canvas/SVG**: {@link EditorImage.render}.
64
+ * - **Adding a new component**: {@link EditorImage.addElement}.
65
+ *
66
+ * **Example**:
67
+ * [[include:doc-pages/inline-examples/image-add-and-lookup.md]]
55
68
  */
56
69
  class EditorImage {
57
70
  // @internal
@@ -110,10 +123,13 @@ class EditorImage {
110
123
  }
111
124
  }
112
125
  /**
113
- * Renders all nodes visible from `viewport` (or all nodes if `viewport = null`).
126
+ * Renders this image to the given `renderer`.
114
127
  *
115
- * `viewport` is used to improve rendering performance. If given, it must match
116
- * the viewport used by the `renderer` (if any).
128
+ * If `viewport` is non-null, only components that can be seen from that viewport
129
+ * will be rendered. If `viewport` is `null`, **all** components are rendered.
130
+ *
131
+ * **Example**:
132
+ * [[include:doc-pages/inline-examples/canvas-renderer.md]]
117
133
  */
118
134
  render(renderer, viewport) {
119
135
  this.background.render(renderer, viewport?.visibleRect);
@@ -144,9 +160,12 @@ class EditorImage {
144
160
  this.render(renderer, null);
145
161
  }
146
162
  /**
147
- * @returns all elements in the image, sorted by z-index. This can be slow for large images.
163
+ * @returns all elements in the image, sorted by z-index (low to high).
148
164
  *
149
- * Does not include background elements. See {@link getBackgroundComponents}.
165
+ * This can be slow for large images. If you only need all elemenst in part of the image,
166
+ * consider using {@link getElementsIntersectingRegion} instead.
167
+ *
168
+ * **Note**: The result does not include background elements. See {@link getBackgroundComponents}.
150
169
  */
151
170
  getAllElements() {
152
171
  const leaves = this.root.getLeaves();
@@ -157,7 +176,11 @@ class EditorImage {
157
176
  estimateNumElements() {
158
177
  return this.componentCount;
159
178
  }
160
- /** @returns a list of `AbstractComponent`s intersecting `region`, sorted by z-index. */
179
+ /**
180
+ * @returns a list of `AbstractComponent`s intersecting `region`, sorted by increasing z-index.
181
+ *
182
+ * Components in the background layer are only included if `includeBackground` is `true`.
183
+ */
161
184
  getElementsIntersectingRegion(region, includeBackground = false) {
162
185
  let leaves = this.root.getLeavesIntersectingRegion(region);
163
186
  if (includeBackground) {
@@ -7,31 +7,8 @@ import RenderablePathSpec from '../RenderablePathSpec';
7
7
  /**
8
8
  * Renders onto a `CanvasRenderingContext2D`.
9
9
  *
10
- * @example
11
- * ```ts,runnable
12
- * import {Editor,CanvasRenderer} from 'js-draw';
13
- *
14
- * // Create an editor and load initial data -- don't add to the body (hidden editor).
15
- * const editor = new Editor(document.createElement('div'));
16
- * await editor.loadFromSVG('<svg><path d="m0,0 l100,5 l-50,60 l30,20 z" fill="green"/></svg>');
17
- * ---visible---
18
- * // Given some editor.
19
- * // Set up the canvas to be drawn onto.
20
- * const canvas = document.createElement('canvas');
21
- * const ctx = canvas.getContext('2d');
22
- *
23
- * // Ensure that the canvas can fit the entire rendering
24
- * const viewport = editor.image.getImportExportViewport();
25
- * canvas.width = viewport.getScreenRectSize().x;
26
- * canvas.height = viewport.getScreenRectSize().y;
27
- *
28
- * // Render editor.image onto the renderer
29
- * const renderer = new CanvasRenderer(ctx, viewport);
30
- * editor.image.render(renderer, viewport);
31
- *
32
- * // Add the rendered canvas to the document.
33
- * document.body.appendChild(canvas);
34
- * ```
10
+ * **Example**:
11
+ * [[include:doc-pages/inline-examples/canvas-renderer.md]]
35
12
  */
36
13
  export default class CanvasRenderer extends AbstractRenderer {
37
14
  private ctx;
@@ -10,31 +10,8 @@ const RenderablePathSpec_1 = require("../RenderablePathSpec");
10
10
  /**
11
11
  * Renders onto a `CanvasRenderingContext2D`.
12
12
  *
13
- * @example
14
- * ```ts,runnable
15
- * import {Editor,CanvasRenderer} from 'js-draw';
16
- *
17
- * // Create an editor and load initial data -- don't add to the body (hidden editor).
18
- * const editor = new Editor(document.createElement('div'));
19
- * await editor.loadFromSVG('<svg><path d="m0,0 l100,5 l-50,60 l30,20 z" fill="green"/></svg>');
20
- * ---visible---
21
- * // Given some editor.
22
- * // Set up the canvas to be drawn onto.
23
- * const canvas = document.createElement('canvas');
24
- * const ctx = canvas.getContext('2d');
25
- *
26
- * // Ensure that the canvas can fit the entire rendering
27
- * const viewport = editor.image.getImportExportViewport();
28
- * canvas.width = viewport.getScreenRectSize().x;
29
- * canvas.height = viewport.getScreenRectSize().y;
30
- *
31
- * // Render editor.image onto the renderer
32
- * const renderer = new CanvasRenderer(ctx, viewport);
33
- * editor.image.render(renderer, viewport);
34
- *
35
- * // Add the rendered canvas to the document.
36
- * document.body.appendChild(canvas);
37
- * ```
13
+ * **Example**:
14
+ * [[include:doc-pages/inline-examples/canvas-renderer.md]]
38
15
  */
39
16
  class CanvasRenderer extends AbstractRenderer_1.default {
40
17
  /**
@@ -49,7 +49,7 @@ class SVGRenderer extends AbstractRenderer_1.default {
49
49
  if (!this.elem.querySelector(`#${exports.renderedStylesheetId}`)) {
50
50
  // Default to rounded strokes.
51
51
  const styleSheet = document.createElementNS('http://www.w3.org/2000/svg', 'style');
52
- styleSheet.innerHTML = `
52
+ styleSheet.appendChild(document.createTextNode(`
53
53
  path {
54
54
  stroke-linecap: round;
55
55
  stroke-linejoin: round;
@@ -58,7 +58,7 @@ class SVGRenderer extends AbstractRenderer_1.default {
58
58
  text {
59
59
  white-space: pre;
60
60
  }
61
- `.replace(/\s+/g, '');
61
+ `.replace(/\s+/g, '')));
62
62
  styleSheet.setAttribute('id', exports.renderedStylesheetId);
63
63
  this.elem.appendChild(styleSheet);
64
64
  }
@@ -110,6 +110,25 @@ export default abstract class AbstractToolbar {
110
110
  * as being the value of `mustBeToplevel`.
111
111
  *
112
112
  * @return The added button.
113
+ *
114
+ * **Example**:
115
+ * ```ts,runnable
116
+ * import { Editor } from 'js-draw';
117
+ * const editor = new Editor(document.body);
118
+ * const toolbar = editor.addToolbar();
119
+ *
120
+ * function makeTrashIcon() {
121
+ * const container = document.createElement('div');
122
+ * container.textContent = '🗑️';
123
+ * return container;
124
+ * }
125
+ *
126
+ * toolbar.addActionButton({
127
+ * icon: makeTrashIcon(), // can be any Element not in the DOM
128
+ * label: 'Delete all',
129
+ * }, () => {
130
+ * alert('to-do!');
131
+ * });
113
132
  */
114
133
  addActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
115
134
  /**
@@ -269,6 +269,25 @@ class AbstractToolbar {
269
269
  * as being the value of `mustBeToplevel`.
270
270
  *
271
271
  * @return The added button.
272
+ *
273
+ * **Example**:
274
+ * ```ts,runnable
275
+ * import { Editor } from 'js-draw';
276
+ * const editor = new Editor(document.body);
277
+ * const toolbar = editor.addToolbar();
278
+ *
279
+ * function makeTrashIcon() {
280
+ * const container = document.createElement('div');
281
+ * container.textContent = '🗑️';
282
+ * return container;
283
+ * }
284
+ *
285
+ * toolbar.addActionButton({
286
+ * icon: makeTrashIcon(), // can be any Element not in the DOM
287
+ * label: 'Delete all',
288
+ * }, () => {
289
+ * alert('to-do!');
290
+ * });
272
291
  */
273
292
  addActionButton(title, command, options = true) {
274
293
  const widget = this.makeActionButton(title, command, options);
@@ -80,9 +80,13 @@ export default class IconProvider {
80
80
  * @returns An object with both the definition of a checkerboard pattern and the syntax to
81
81
  * reference that pattern. The defs provided by this function should be wrapped within a
82
82
  * `<defs></defs>` element.
83
+ *
84
+ * **Note**: This function's return value includes both `patternDefElement` (which returns
85
+ * an Element) and a (deprecated) `patternDef` string. Avoid using the `patternDef` result.
83
86
  */
84
87
  protected makeCheckerboardPattern(): {
85
- patternDef: string;
88
+ patternDefElement: SVGElement;
89
+ readonly patternDef: string;
86
90
  patternRef: string;
87
91
  };
88
92
  /**