js-draw 1.2.2 → 1.3.1

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 (111) hide show
  1. package/README.md +29 -29
  2. package/dist/Editor.css +65 -4
  3. package/dist/bundle.js +2 -2
  4. package/dist/bundledStyles.js +1 -1
  5. package/dist/cjs/Editor.d.ts +73 -40
  6. package/dist/cjs/Editor.js +90 -24
  7. package/dist/cjs/EditorImage.d.ts +58 -6
  8. package/dist/cjs/EditorImage.js +336 -60
  9. package/dist/cjs/SVGLoader.d.ts +10 -4
  10. package/dist/cjs/SVGLoader.js +67 -32
  11. package/dist/cjs/UndoRedoHistory.d.ts +2 -2
  12. package/dist/cjs/UndoRedoHistory.js +4 -2
  13. package/dist/cjs/Viewport.d.ts +2 -1
  14. package/dist/cjs/Viewport.js +12 -3
  15. package/dist/cjs/commands/Command.d.ts +1 -0
  16. package/dist/cjs/commands/Command.js +1 -0
  17. package/dist/cjs/commands/Erase.js +1 -1
  18. package/dist/cjs/commands/SerializableCommand.d.ts +1 -1
  19. package/dist/cjs/commands/SerializableCommand.js +16 -2
  20. package/dist/cjs/commands/localization.d.ts +2 -0
  21. package/dist/cjs/commands/localization.js +2 -0
  22. package/dist/cjs/components/AbstractComponent.d.ts +38 -0
  23. package/dist/cjs/components/AbstractComponent.js +31 -0
  24. package/dist/cjs/components/BackgroundComponent.d.ts +10 -1
  25. package/dist/cjs/components/BackgroundComponent.js +61 -6
  26. package/dist/cjs/components/SVGGlobalAttributesObject.d.ts +2 -1
  27. package/dist/cjs/components/SVGGlobalAttributesObject.js +30 -1
  28. package/dist/cjs/components/Stroke.d.ts +1 -0
  29. package/dist/cjs/components/Stroke.js +44 -0
  30. package/dist/cjs/components/UnknownSVGObject.d.ts +2 -1
  31. package/dist/cjs/components/UnknownSVGObject.js +30 -1
  32. package/dist/cjs/lib.d.ts +2 -45
  33. package/dist/cjs/lib.js +2 -45
  34. package/dist/cjs/rendering/RenderingStyle.d.ts +1 -0
  35. package/dist/cjs/rendering/renderers/AbstractRenderer.js +1 -1
  36. package/dist/cjs/rendering/renderers/SVGRenderer.js +8 -19
  37. package/dist/cjs/rendering/renderers/SVGRenderer.test.d.ts +1 -0
  38. package/dist/cjs/shortcuts/KeyboardShortcutManager.d.ts +2 -2
  39. package/dist/cjs/shortcuts/KeyboardShortcutManager.js +2 -2
  40. package/dist/cjs/toolbar/localization.d.ts +1 -0
  41. package/dist/cjs/toolbar/localization.js +1 -0
  42. package/dist/cjs/toolbar/widgets/BaseWidget.js +5 -0
  43. package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +54 -25
  44. package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +8 -0
  45. package/dist/cjs/tools/PanZoom.js +13 -8
  46. package/dist/cjs/tools/ScrollbarTool.d.ts +18 -0
  47. package/dist/cjs/tools/ScrollbarTool.js +85 -0
  48. package/dist/cjs/tools/SelectionTool/SelectionTool.selecting.test.d.ts +1 -0
  49. package/dist/cjs/tools/ToolController.js +2 -0
  50. package/dist/cjs/types.d.ts +3 -1
  51. package/dist/cjs/util/assertions.d.ts +4 -0
  52. package/dist/cjs/util/assertions.js +12 -1
  53. package/dist/cjs/version.js +1 -1
  54. package/dist/mjs/Editor.d.ts +73 -40
  55. package/dist/mjs/Editor.mjs +90 -24
  56. package/dist/mjs/EditorImage.d.ts +58 -6
  57. package/dist/mjs/EditorImage.mjs +313 -61
  58. package/dist/mjs/SVGLoader.d.ts +10 -4
  59. package/dist/mjs/SVGLoader.mjs +66 -31
  60. package/dist/mjs/UndoRedoHistory.d.ts +2 -2
  61. package/dist/mjs/UndoRedoHistory.mjs +4 -2
  62. package/dist/mjs/Viewport.d.ts +2 -1
  63. package/dist/mjs/Viewport.mjs +12 -3
  64. package/dist/mjs/commands/Command.d.ts +1 -0
  65. package/dist/mjs/commands/Command.mjs +1 -0
  66. package/dist/mjs/commands/Erase.mjs +1 -1
  67. package/dist/mjs/commands/SerializableCommand.d.ts +1 -1
  68. package/dist/mjs/commands/SerializableCommand.mjs +16 -2
  69. package/dist/mjs/commands/localization.d.ts +2 -0
  70. package/dist/mjs/commands/localization.mjs +2 -0
  71. package/dist/mjs/components/AbstractComponent.d.ts +38 -0
  72. package/dist/mjs/components/AbstractComponent.mjs +30 -0
  73. package/dist/mjs/components/BackgroundComponent.d.ts +10 -1
  74. package/dist/mjs/components/BackgroundComponent.mjs +38 -6
  75. package/dist/mjs/components/SVGGlobalAttributesObject.d.ts +2 -1
  76. package/dist/mjs/components/SVGGlobalAttributesObject.mjs +7 -1
  77. package/dist/mjs/components/Stroke.d.ts +1 -0
  78. package/dist/mjs/components/Stroke.mjs +44 -0
  79. package/dist/mjs/components/UnknownSVGObject.d.ts +2 -1
  80. package/dist/mjs/components/UnknownSVGObject.mjs +7 -1
  81. package/dist/mjs/lib.d.ts +2 -45
  82. package/dist/mjs/lib.mjs +2 -45
  83. package/dist/mjs/rendering/RenderingStyle.d.ts +1 -0
  84. package/dist/mjs/rendering/renderers/AbstractRenderer.mjs +1 -1
  85. package/dist/mjs/rendering/renderers/SVGRenderer.mjs +8 -19
  86. package/dist/mjs/rendering/renderers/SVGRenderer.test.d.ts +1 -0
  87. package/dist/mjs/shortcuts/KeyboardShortcutManager.d.ts +2 -2
  88. package/dist/mjs/shortcuts/KeyboardShortcutManager.mjs +2 -2
  89. package/dist/mjs/toolbar/localization.d.ts +1 -0
  90. package/dist/mjs/toolbar/localization.mjs +1 -0
  91. package/dist/mjs/toolbar/widgets/BaseWidget.mjs +5 -0
  92. package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +54 -25
  93. package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +8 -0
  94. package/dist/mjs/tools/PanZoom.mjs +13 -8
  95. package/dist/mjs/tools/ScrollbarTool.d.ts +18 -0
  96. package/dist/mjs/tools/ScrollbarTool.mjs +79 -0
  97. package/dist/mjs/tools/SelectionTool/SelectionTool.selecting.test.d.ts +1 -0
  98. package/dist/mjs/tools/ToolController.mjs +2 -0
  99. package/dist/mjs/types.d.ts +3 -1
  100. package/dist/mjs/util/assertions.d.ts +4 -0
  101. package/dist/mjs/util/assertions.mjs +10 -0
  102. package/dist/mjs/version.mjs +1 -1
  103. package/package.json +3 -4
  104. package/src/Editor.scss +8 -0
  105. package/src/dialogs/dialogs.scss +2 -1
  106. package/src/toolbar/EdgeToolbar.scss +4 -1
  107. package/src/toolbar/widgets/DocumentPropertiesWidget.scss +12 -0
  108. package/src/toolbar/widgets/components/makeGridSelector.scss +1 -1
  109. package/src/tools/ScrollbarTool.scss +57 -0
  110. package/src/tools/{SoundUITool.css → SoundUITool.scss} +4 -0
  111. package/src/tools/tools.scss +2 -1
@@ -0,0 +1,79 @@
1
+ import { Rect2 } from '@js-draw/math';
2
+ import { EditorEventType } from '../types.mjs';
3
+ import BaseTool from './BaseTool.mjs';
4
+ /**
5
+ * This tool, when enabled, renders scrollbars reflecting the current position
6
+ * of the view relative to the import/export area of the image.
7
+ *
8
+ * **Note**: These scrollbars are currently not draggable. This may change in
9
+ * a future release.
10
+ */
11
+ export default class ScrollbarTool extends BaseTool {
12
+ constructor(editor) {
13
+ super(editor.notifier, 'scrollbar');
14
+ this.editor = editor;
15
+ this.fadeOutTimeout = null;
16
+ this.scrollbarOverlay = document.createElement('div');
17
+ this.scrollbarOverlay.classList.add('ScrollbarTool-overlay');
18
+ this.verticalScrollbar = document.createElement('div');
19
+ this.verticalScrollbar.classList.add('vertical-scrollbar');
20
+ this.horizontalScrollbar = document.createElement('div');
21
+ this.horizontalScrollbar.classList.add('horizontal-scrollbar');
22
+ this.scrollbarOverlay.replaceChildren(this.verticalScrollbar, this.horizontalScrollbar);
23
+ let overlay = null;
24
+ let viewportListener = null;
25
+ this.enabledValue().onUpdateAndNow(enabled => {
26
+ overlay?.remove();
27
+ viewportListener?.remove();
28
+ viewportListener = null;
29
+ overlay = null;
30
+ if (enabled) {
31
+ viewportListener = editor.notifier.on(EditorEventType.ViewportChanged, _event => {
32
+ this.updateScrollbars();
33
+ });
34
+ this.updateScrollbars();
35
+ overlay = editor.createHTMLOverlay(this.scrollbarOverlay);
36
+ }
37
+ });
38
+ }
39
+ updateScrollbars() {
40
+ const viewport = this.editor.viewport;
41
+ const screenSize = viewport.getScreenRectSize();
42
+ const screenRect = new Rect2(0, 0, screenSize.x, screenSize.y);
43
+ const imageRect = this.editor.getImportExportRect()
44
+ // The scrollbars are positioned in screen coordinates, so the exportRect also needs
45
+ // to be in screen coordinates
46
+ .transformedBoundingBox(viewport.canvasToScreenTransform)
47
+ // If the screenRect is outside of the exportRect, expand the image rectangle
48
+ .union(screenRect);
49
+ const scrollbarWidth = screenRect.width / imageRect.width * screenSize.x;
50
+ const scrollbarHeight = screenRect.height / imageRect.height * screenSize.y;
51
+ const scrollbarX = (screenRect.x - imageRect.x) / imageRect.width * (screenSize.x);
52
+ const scrollbarY = (screenRect.y - imageRect.y) / imageRect.height * (screenSize.y);
53
+ this.horizontalScrollbar.style.width = `${scrollbarWidth}px`;
54
+ this.verticalScrollbar.style.height = `${scrollbarHeight}px`;
55
+ this.horizontalScrollbar.style.marginLeft = `${scrollbarX}px`;
56
+ this.verticalScrollbar.style.marginTop = `${scrollbarY}px`;
57
+ // Style the scrollbars differently when there's no scroll (all content visible)
58
+ const handleNoScrollStyling = (scrollbar, size, fillSize) => {
59
+ const fillsWindowClass = 'represents-no-scroll';
60
+ if (Math.abs(size - fillSize) < 1e-8) {
61
+ scrollbar.classList.add(fillsWindowClass);
62
+ }
63
+ else {
64
+ scrollbar.classList.remove(fillsWindowClass);
65
+ }
66
+ };
67
+ handleNoScrollStyling(this.horizontalScrollbar, scrollbarWidth, screenSize.x);
68
+ handleNoScrollStyling(this.verticalScrollbar, scrollbarHeight, screenSize.y);
69
+ // Fade out after a delay.
70
+ if (this.fadeOutTimeout !== null) {
71
+ clearTimeout(this.fadeOutTimeout);
72
+ }
73
+ const fadeOutDelay = 3000;
74
+ this.fadeOutTimeout = setTimeout(() => {
75
+ this.scrollbarOverlay.classList.remove('just-updated');
76
+ }, fadeOutDelay);
77
+ this.scrollbarOverlay.classList.add('just-updated');
78
+ }
79
+ }
@@ -18,6 +18,7 @@ import SoundUITool from './SoundUITool.mjs';
18
18
  import { InputEvtType } from '../inputEvents.mjs';
19
19
  import InputPipeline from './InputFilter/InputPipeline.mjs';
20
20
  import InputStabilizer from './InputFilter/InputStabilizer.mjs';
21
+ import ScrollbarTool from './ScrollbarTool.mjs';
21
22
  export default class ToolController {
22
23
  /** @internal */
23
24
  constructor(editor, localization) {
@@ -51,6 +52,7 @@ export default class ToolController {
51
52
  const soundExplorer = new SoundUITool(editor, localization.soundExplorer);
52
53
  soundExplorer.setEnabled(false);
53
54
  this.tools = [
55
+ new ScrollbarTool(editor),
54
56
  new PipetteTool(editor, localization.pipetteTool),
55
57
  soundExplorer,
56
58
  panZoomTool,
@@ -82,7 +82,9 @@ export interface ToolbarDropdownShownEvent {
82
82
  export type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | SelectionUpdated | ColorPickerToggled | ColorPickerColorSelected | ToolbarDropdownShownEvent;
83
83
  export type OnProgressListener = (amountProcessed: number, totalToProcess: number) => Promise<void> | null | void;
84
84
  export type ComponentAddedListener = (component: AbstractComponent) => Promise<void> | void;
85
- export type OnDetermineExportRectListener = (exportRect: Rect2) => void;
85
+ export type OnDetermineExportRectListener = (exportRect: Rect2, options?: {
86
+ autoresize: boolean;
87
+ }) => void;
86
88
  export interface ImageLoader {
87
89
  start(onAddComponent: ComponentAddedListener, onProgressListener: OnProgressListener, onDetermineExportRect?: OnDetermineExportRectListener): Promise<void>;
88
90
  }
@@ -21,3 +21,7 @@ export declare const assertIsNumber: (value: any, allowNaN?: boolean) => value i
21
21
  * Throws if any of `values` is not of type number.
22
22
  */
23
23
  export declare const assertIsNumberArray: (values: any[], allowNaN?: boolean) => values is number[];
24
+ /**
25
+ * Throws an exception if `typeof value` is not a boolean.
26
+ */
27
+ export declare const assertIsBoolean: (value: any) => value is boolean;
@@ -43,3 +43,13 @@ export const assertIsNumberArray = (values, allowNaN = false) => {
43
43
  }
44
44
  return true;
45
45
  };
46
+ /**
47
+ * Throws an exception if `typeof value` is not a boolean.
48
+ */
49
+ export const assertIsBoolean = (value) => {
50
+ if (typeof value !== 'boolean') {
51
+ throw new Error('Given value is not a boolean');
52
+ // return false;
53
+ }
54
+ return true;
55
+ };
@@ -1,3 +1,3 @@
1
1
  export default {
2
- number: '1.2.2',
2
+ number: '1.3.1',
3
3
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-draw",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
4
4
  "description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
5
5
  "types": "./dist/mjs/lib.d.ts",
6
6
  "main": "./dist/cjs/lib.js",
@@ -64,12 +64,11 @@
64
64
  "postpack": "ts-node tools/copyREADME.ts revert"
65
65
  },
66
66
  "dependencies": {
67
- "@js-draw/math": "^1.2.2",
67
+ "@js-draw/math": "^1.3.1",
68
68
  "@melloware/coloris": "0.21.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@js-draw/build-tool": "^1.0.2",
72
- "@types/bezier-js": "4.1.0",
73
72
  "@types/jest": "29.5.3",
74
73
  "@types/jsdom": "21.1.1"
75
74
  },
@@ -87,5 +86,5 @@
87
86
  "freehand",
88
87
  "svg"
89
88
  ],
90
- "gitHead": "ced98ae289f299c44b54515571d0087aa6d32cdc"
89
+ "gitHead": "65af7ec944f70b69b2a4b07d98e5bb92eeeca029"
91
90
  }
package/src/Editor.scss CHANGED
@@ -136,6 +136,14 @@
136
136
  z-index: 5;
137
137
  }
138
138
 
139
+ // TODO: Apply this change during a future major release.
140
+ // So as not to change the position of other overlays, all overlays should have
141
+ // 0 height.
142
+ // Uses the alternate overlay class name to decrease specificity.
143
+ // .js-draw-editor-overlay {
144
+ // //height: 0;
145
+ // }
146
+
139
147
  @media print {
140
148
  .imageEditorContainer .loadingMessage {
141
149
  display: none;
@@ -1,7 +1,8 @@
1
1
 
2
2
  @use './makeAboutDialog.scss';
3
3
 
4
- .dialog-container {
4
+ // Repeat to increase specificity -- dialog containers are often overlays
5
+ .dialog-container.dialog-container {
5
6
  background-color: var( --background-color-transparent);
6
7
 
7
8
  backdrop-filter: blur(5px);
@@ -480,6 +480,8 @@
480
480
  .toolbar-spacedList {
481
481
  box-sizing: border-box;
482
482
 
483
+ --align-items-to-x: 105px;
484
+
483
485
  & > div {
484
486
  display: flex;
485
487
  align-items: center;
@@ -491,7 +493,7 @@
491
493
  // Align inputs (assumes labels come first)
492
494
  & > label {
493
495
  padding-right: 35px;
494
- min-width: 105px;
496
+ min-width: var(--align-items-to-x);
495
497
  flex-shrink: 1;
496
498
  box-sizing: border-box;
497
499
  }
@@ -499,6 +501,7 @@
499
501
  & > input[type="checkbox"] {
500
502
  width: 20px;
501
503
  height: 20px;
504
+ margin-left: 0;
502
505
  }
503
506
 
504
507
  // If checkboxes have flex-grow, the checkbox region can become centered.
@@ -4,4 +4,16 @@
4
4
  width: 100%;
5
5
  text-align: end;
6
6
  }
7
+
8
+ & > * {
9
+ --align-items-to-x: 120px;
10
+ }
11
+
12
+ .js-draw-size-input-row.js-draw-size-input-row {
13
+ display: flex;
14
+
15
+ &.size-input-row--automatic-size {
16
+ display: none;
17
+ }
18
+ }
7
19
  }
@@ -20,7 +20,7 @@
20
20
  flex-shrink: 1;
21
21
  margin: 2px;
22
22
 
23
- &:focus-within {
23
+ &.focus-visible {
24
24
  outline: 2px solid var(--foreground-color-1);
25
25
  }
26
26
 
@@ -0,0 +1,57 @@
1
+
2
+ .ScrollbarTool-overlay {
3
+ width: 0;
4
+ height: 0;
5
+ overflow: visible;
6
+
7
+ $visible-opacity: 0.2;
8
+ opacity: $visible-opacity;
9
+ pointer-events: none;
10
+
11
+ --fade-out-animation: 1s ease 0s fade-out;
12
+
13
+ @media (prefers-reduced-motion: reduce) {
14
+ --fade-out-animation: none !important;
15
+ }
16
+
17
+ @keyframes fade-out {
18
+ from { opacity: $visible-opacity; }
19
+ to { opacity: 0; }
20
+ }
21
+
22
+ &:not(.just-updated) {
23
+ animation: var(--fade-out-animation);
24
+ opacity: 0;
25
+ }
26
+
27
+ --scrollbar-size: 3px;
28
+
29
+ .vertical-scrollbar, .horizontal-scrollbar {
30
+ width: var(--scrollbar-size);
31
+ height: var(--scrollbar-size);
32
+
33
+ min-width: var(--scrollbar-size);
34
+ min-height: var(--scrollbar-size);
35
+
36
+ background-color: var(--foreground-color-1);
37
+ border-radius: var(--scrollbar-size);
38
+ position: absolute;
39
+
40
+ &.represents-no-scroll {
41
+ animation: var(--fade-out-animation);
42
+ opacity: 0;
43
+ }
44
+ }
45
+
46
+ &:not(.scrollbar-left) {
47
+ .vertical-scrollbar {
48
+ margin-left: calc(var(--editor-current-display-width-px) - var(--scrollbar-size));
49
+ }
50
+ }
51
+
52
+ &:not(.scrollbar-top) {
53
+ .horizontal-scrollbar {
54
+ margin-top: calc(var(--editor-current-display-height-px) - var(--scrollbar-size));
55
+ }
56
+ }
57
+ }
@@ -5,6 +5,10 @@
5
5
  overflow: hidden;
6
6
  }
7
7
 
8
+ .js-draw-sound-ui-toggle button {
9
+ margin-top: 1px;
10
+ }
11
+
8
12
  .js-draw-sound-ui-toggle:focus-within, .js-draw-sound-ui-toggle.sound-ui-tool-enabled {
9
13
  overflow: visible;
10
14
  z-index: 5;
@@ -1,4 +1,5 @@
1
1
 
2
+ @use "./ScrollbarTool.scss";
2
3
  @use "./SelectionTool/SelectionTool.css";
3
4
  @use "./FindTool.css";
4
- @use "./SoundUITool.css";
5
+ @use "./SoundUITool.scss";