js-draw 1.3.1 → 1.4.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 +1 -1
- package/dist/Editor.css +55 -13
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.d.ts +36 -3
- package/dist/cjs/Editor.js +63 -26
- package/dist/cjs/commands/Erase.js +1 -1
- package/dist/cjs/commands/UnresolvedCommand.d.ts +1 -1
- package/dist/cjs/components/AbstractComponent.d.ts +1 -1
- package/dist/cjs/components/AbstractComponent.js +1 -1
- package/dist/cjs/components/BackgroundComponent.d.ts +1 -1
- package/dist/cjs/components/BackgroundComponent.js +1 -1
- package/dist/cjs/{EditorImage.d.ts → image/EditorImage.d.ts} +30 -8
- package/dist/cjs/{EditorImage.js → image/EditorImage.js} +51 -7
- package/dist/cjs/image/export/editorImageToSVG.d.ts +8 -0
- package/dist/cjs/image/export/editorImageToSVG.js +49 -0
- package/dist/cjs/image/export/setExportedSVGSize.d.ts +6 -0
- package/dist/cjs/image/export/setExportedSVGSize.js +25 -0
- package/dist/cjs/image/lib.d.ts +1 -0
- package/dist/cjs/image/lib.js +8 -0
- package/dist/cjs/lib.d.ts +1 -1
- package/dist/cjs/lib.js +2 -3
- package/dist/cjs/localizations/comments.d.ts +6 -0
- package/dist/cjs/localizations/comments.js +10 -0
- package/dist/cjs/localizations/es.js +68 -48
- package/dist/cjs/rendering/caching/RenderingCache.d.ts +1 -1
- package/dist/cjs/rendering/caching/RenderingCacheNode.d.ts +1 -1
- package/dist/cjs/rendering/caching/RenderingCacheNode.js +4 -3
- package/dist/cjs/toolbar/AbstractToolbar.d.ts +11 -3
- package/dist/cjs/toolbar/AbstractToolbar.js +20 -6
- package/dist/cjs/toolbar/EdgeToolbar.js +5 -6
- package/dist/cjs/toolbar/IconProvider.d.ts +1 -0
- package/dist/cjs/toolbar/IconProvider.js +43 -0
- package/dist/cjs/toolbar/widgets/ActionButtonWidget.d.ts +3 -1
- package/dist/cjs/toolbar/widgets/ActionButtonWidget.js +19 -1
- package/dist/cjs/toolbar/widgets/BaseToolWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/BaseToolWidget.js +3 -0
- package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +5 -0
- package/dist/cjs/toolbar/widgets/BaseWidget.js +30 -2
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +1 -1
- package/dist/cjs/toolbar/widgets/HandToolWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/HandToolWidget.js +6 -0
- package/dist/cjs/toolbar/widgets/InsertImageWidget.js +1 -1
- package/dist/cjs/toolbar/widgets/OverflowWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/OverflowWidget.js +3 -0
- package/dist/cjs/toolbar/widgets/SaveActionWidget.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/SaveActionWidget.js +3 -0
- package/dist/cjs/tools/BaseTool.d.ts +3 -0
- package/dist/cjs/tools/BaseTool.js +13 -2
- package/dist/cjs/tools/FindTool.d.ts +1 -0
- package/dist/cjs/tools/FindTool.js +4 -1
- package/dist/cjs/tools/PanZoom.d.ts +1 -0
- package/dist/cjs/tools/PanZoom.js +4 -0
- package/dist/cjs/tools/Pen.d.ts +0 -1
- package/dist/cjs/tools/Pen.js +1 -4
- package/dist/cjs/tools/PipetteTool.d.ts +1 -0
- package/dist/cjs/tools/PipetteTool.js +3 -0
- package/dist/cjs/tools/SelectionTool/SelectAllShortcutHandler.d.ts +1 -0
- package/dist/cjs/tools/SelectionTool/SelectAllShortcutHandler.js +3 -0
- package/dist/cjs/tools/SelectionTool/Selection.d.ts +2 -0
- package/dist/cjs/tools/SelectionTool/Selection.js +44 -8
- package/dist/cjs/tools/SelectionTool/SelectionHandle.d.ts +14 -6
- package/dist/cjs/tools/SelectionTool/SelectionHandle.js +26 -8
- package/dist/cjs/tools/SelectionTool/SelectionTool.js +5 -0
- package/dist/cjs/tools/SoundUITool.d.ts +1 -0
- package/dist/cjs/tools/SoundUITool.js +4 -1
- package/dist/cjs/tools/TextTool.js +2 -2
- package/dist/cjs/tools/ToolController.d.ts +2 -0
- package/dist/cjs/tools/ToolController.js +13 -2
- package/dist/cjs/tools/ToolSwitcherShortcut.d.ts +1 -0
- package/dist/cjs/tools/ToolSwitcherShortcut.js +3 -0
- package/dist/cjs/types.d.ts +9 -4
- package/dist/cjs/types.js +4 -3
- package/dist/cjs/util/ReactiveValue.d.ts +1 -1
- package/dist/cjs/util/ReactiveValue.js +2 -2
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +36 -3
- package/dist/mjs/Editor.mjs +64 -27
- package/dist/mjs/Editor.toSVGAsync.test.d.ts +1 -0
- package/dist/mjs/commands/Erase.mjs +1 -1
- package/dist/mjs/commands/UnresolvedCommand.d.ts +1 -1
- package/dist/mjs/components/AbstractComponent.d.ts +1 -1
- package/dist/mjs/components/AbstractComponent.mjs +1 -1
- package/dist/mjs/components/BackgroundComponent.d.ts +1 -1
- package/dist/mjs/components/BackgroundComponent.mjs +1 -1
- package/dist/mjs/{EditorImage.d.ts → image/EditorImage.d.ts} +30 -8
- package/dist/mjs/{EditorImage.mjs → image/EditorImage.mjs} +51 -7
- package/dist/mjs/image/EditorImage.test.d.ts +1 -0
- package/dist/mjs/image/export/editorImageToSVG.d.ts +8 -0
- package/dist/mjs/image/export/editorImageToSVG.mjs +41 -0
- package/dist/mjs/image/export/setExportedSVGSize.d.ts +6 -0
- package/dist/mjs/image/export/setExportedSVGSize.mjs +23 -0
- package/dist/mjs/image/lib.d.ts +1 -0
- package/dist/mjs/image/lib.mjs +1 -0
- package/dist/mjs/lib.d.ts +1 -1
- package/dist/mjs/lib.mjs +1 -1
- package/dist/mjs/localizations/comments.d.ts +6 -0
- package/dist/mjs/localizations/comments.mjs +8 -0
- package/dist/mjs/localizations/es.mjs +68 -48
- package/dist/mjs/rendering/caching/RenderingCache.d.ts +1 -1
- package/dist/mjs/rendering/caching/RenderingCacheNode.d.ts +1 -1
- package/dist/mjs/rendering/caching/RenderingCacheNode.mjs +4 -3
- package/dist/mjs/toolbar/AbstractToolbar.d.ts +11 -3
- package/dist/mjs/toolbar/AbstractToolbar.mjs +20 -6
- package/dist/mjs/toolbar/EdgeToolbar.mjs +5 -6
- package/dist/mjs/toolbar/IconProvider.d.ts +1 -0
- package/dist/mjs/toolbar/IconProvider.mjs +43 -0
- package/dist/mjs/toolbar/widgets/ActionButtonWidget.d.ts +3 -1
- package/dist/mjs/toolbar/widgets/ActionButtonWidget.mjs +21 -2
- package/dist/mjs/toolbar/widgets/BaseToolWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/BaseToolWidget.mjs +3 -0
- package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +5 -0
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +30 -2
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +1 -1
- package/dist/mjs/toolbar/widgets/HandToolWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +6 -0
- package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +1 -1
- package/dist/mjs/toolbar/widgets/OverflowWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/OverflowWidget.mjs +3 -0
- package/dist/mjs/toolbar/widgets/SaveActionWidget.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/SaveActionWidget.mjs +3 -0
- package/dist/mjs/tools/BaseTool.d.ts +3 -0
- package/dist/mjs/tools/BaseTool.mjs +13 -2
- package/dist/mjs/tools/FindTool.d.ts +1 -0
- package/dist/mjs/tools/FindTool.mjs +4 -1
- package/dist/mjs/tools/PanZoom.d.ts +1 -0
- package/dist/mjs/tools/PanZoom.mjs +4 -0
- package/dist/mjs/tools/Pen.d.ts +0 -1
- package/dist/mjs/tools/Pen.mjs +1 -4
- package/dist/mjs/tools/PipetteTool.d.ts +1 -0
- package/dist/mjs/tools/PipetteTool.mjs +3 -0
- package/dist/mjs/tools/SelectionTool/SelectAllShortcutHandler.d.ts +1 -0
- package/dist/mjs/tools/SelectionTool/SelectAllShortcutHandler.mjs +3 -0
- package/dist/mjs/tools/SelectionTool/Selection.d.ts +2 -0
- package/dist/mjs/tools/SelectionTool/Selection.mjs +45 -9
- package/dist/mjs/tools/SelectionTool/SelectionHandle.d.ts +14 -6
- package/dist/mjs/tools/SelectionTool/SelectionHandle.mjs +25 -7
- package/dist/mjs/tools/SelectionTool/SelectionTool.mjs +5 -0
- package/dist/mjs/tools/SoundUITool.d.ts +1 -0
- package/dist/mjs/tools/SoundUITool.mjs +4 -1
- package/dist/mjs/tools/TextTool.mjs +2 -2
- package/dist/mjs/tools/ToolController.d.ts +2 -0
- package/dist/mjs/tools/ToolController.mjs +13 -2
- package/dist/mjs/tools/ToolSwitcherShortcut.d.ts +1 -0
- package/dist/mjs/tools/ToolSwitcherShortcut.mjs +3 -0
- package/dist/mjs/types.d.ts +9 -4
- package/dist/mjs/types.mjs +4 -3
- package/dist/mjs/util/ReactiveValue.d.ts +1 -1
- package/dist/mjs/util/ReactiveValue.mjs +2 -2
- package/dist/mjs/version.mjs +1 -1
- package/package.json +5 -5
- package/src/Editor.scss +6 -0
- package/src/toolbar/EdgeToolbar.scss +19 -2
- package/src/tools/SelectionTool/SelectionTool.scss +74 -0
- package/src/tools/tools.scss +1 -1
- package/src/tools/SelectionTool/SelectionTool.css +0 -35
- /package/dist/cjs/{EditorImage.test.d.ts → Editor.toSVGAsync.test.d.ts} +0 -0
- /package/dist/{mjs → cjs/image}/EditorImage.test.d.ts +0 -0
@@ -3,13 +3,13 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
|
|
3
3
|
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
4
4
|
};
|
5
5
|
var _a, _b, _c;
|
6
|
-
import Viewport from '
|
7
|
-
import AbstractComponent, { ComponentSizingMode } from '
|
6
|
+
import Viewport from '../Viewport.mjs';
|
7
|
+
import AbstractComponent, { ComponentSizingMode } from '../components/AbstractComponent.mjs';
|
8
8
|
import { Rect2, Vec2, Mat33, Color4 } from '@js-draw/math';
|
9
|
-
import SerializableCommand from '
|
10
|
-
import EventDispatcher from '
|
11
|
-
import { assertIsBoolean, assertIsNumber, assertIsNumberArray } from '
|
12
|
-
import Command from '
|
9
|
+
import SerializableCommand from '../commands/SerializableCommand.mjs';
|
10
|
+
import EventDispatcher from '../EventDispatcher.mjs';
|
11
|
+
import { assertIsBoolean, assertIsNumber, assertIsNumberArray } from '../util/assertions.mjs';
|
12
|
+
import Command from '../commands/Command.mjs';
|
13
13
|
// @internal Sort by z-index, low to high
|
14
14
|
export const sortLeavesByZIndex = (leaves) => {
|
15
15
|
leaves.sort((a, b) => a.getContent().getZIndex() - b.getContent().getZIndex());
|
@@ -87,7 +87,27 @@ class EditorImage {
|
|
87
87
|
this.background.render(renderer, viewport?.visibleRect);
|
88
88
|
this.root.render(renderer, viewport?.visibleRect);
|
89
89
|
}
|
90
|
-
/**
|
90
|
+
/**
|
91
|
+
* Like {@link renderAll}, but can be stopped early and paused.
|
92
|
+
*
|
93
|
+
* **Note**: If the image is being edited during an async rendering, there is no
|
94
|
+
* guarantee that all nodes will be rendered correctly (some may be missing).
|
95
|
+
*
|
96
|
+
* @internal
|
97
|
+
*/
|
98
|
+
async renderAllAsync(renderer, preRenderComponent) {
|
99
|
+
const stoppedEarly = !(await this.background.renderAllAsync(renderer, preRenderComponent));
|
100
|
+
if (!stoppedEarly) {
|
101
|
+
return await this.root.renderAllAsync(renderer, preRenderComponent);
|
102
|
+
}
|
103
|
+
return false;
|
104
|
+
}
|
105
|
+
/**
|
106
|
+
* Renders all nodes, even ones not within the viewport.
|
107
|
+
*
|
108
|
+
* This can be slow for large images
|
109
|
+
* @internal
|
110
|
+
*/
|
91
111
|
renderAll(renderer) {
|
92
112
|
this.render(renderer, null);
|
93
113
|
}
|
@@ -610,6 +630,30 @@ export class ImageNode {
|
|
610
630
|
this.content = null;
|
611
631
|
this.children = [];
|
612
632
|
}
|
633
|
+
// Creates a (potentially incomplete) async rendering of this image.
|
634
|
+
// Returns false if stopped early
|
635
|
+
async renderAllAsync(renderer,
|
636
|
+
// Used to pause/stop the renderer process
|
637
|
+
preRenderComponent) {
|
638
|
+
const leaves = this.getLeaves();
|
639
|
+
sortLeavesByZIndex(leaves);
|
640
|
+
const totalLeaves = leaves.length;
|
641
|
+
for (let leafIndex = 0; leafIndex < totalLeaves; leafIndex++) {
|
642
|
+
const leaf = leaves[leafIndex];
|
643
|
+
const component = leaf.getContent();
|
644
|
+
// Even though leaf was originally a leaf, it might not be any longer --
|
645
|
+
// rendering is async and the tree can change during that time.
|
646
|
+
if (!component) {
|
647
|
+
continue;
|
648
|
+
}
|
649
|
+
const shouldContinue = await preRenderComponent(component, leafIndex, totalLeaves);
|
650
|
+
if (!shouldContinue) {
|
651
|
+
return false;
|
652
|
+
}
|
653
|
+
component.render(renderer, undefined);
|
654
|
+
}
|
655
|
+
return true;
|
656
|
+
}
|
613
657
|
render(renderer, visibleRect) {
|
614
658
|
let leaves;
|
615
659
|
if (visibleRect) {
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import EditorImage, { PreRenderComponentCallback } from '../EditorImage';
|
2
|
+
import { SVGSizingOptions } from './setExportedSVGSize';
|
3
|
+
export interface SVGExportOptions extends SVGSizingOptions {
|
4
|
+
sanitize?: boolean;
|
5
|
+
minDimension?: number;
|
6
|
+
}
|
7
|
+
export declare const editorImageToSVGSync: (image: EditorImage, options: SVGExportOptions) => SVGSVGElement;
|
8
|
+
export declare const editorImageToSVGAsync: (image: EditorImage, preRenderComponent: PreRenderComponentCallback, options: SVGExportOptions) => Promise<SVGElement>;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { Mat33 } from '@js-draw/math';
|
2
|
+
import SVGRenderer from '../../rendering/renderers/SVGRenderer.mjs';
|
3
|
+
import { svgLoaderAutoresizeClassName } from '../../SVGLoader.mjs';
|
4
|
+
import setExportedSVGSize from './setExportedSVGSize.mjs';
|
5
|
+
const toSVGInternal = (image, renderFunction, options) => {
|
6
|
+
const importExportViewport = image.getImportExportViewport().getTemporaryClone();
|
7
|
+
const { element: result, renderer } = SVGRenderer.fromViewport(importExportViewport, options.sanitize ?? false);
|
8
|
+
const origTransform = importExportViewport.canvasToScreenTransform;
|
9
|
+
// Render with (0,0) at (0,0) — we'll handle translation with
|
10
|
+
// the viewBox property.
|
11
|
+
importExportViewport.resetTransform(Mat33.identity);
|
12
|
+
// Use a callback rather than async/await to allow this function to create
|
13
|
+
// both sync and async render functions
|
14
|
+
renderFunction(renderer, () => {
|
15
|
+
importExportViewport.resetTransform(origTransform);
|
16
|
+
if (image.getAutoresizeEnabled()) {
|
17
|
+
result.classList.add(svgLoaderAutoresizeClassName);
|
18
|
+
}
|
19
|
+
else {
|
20
|
+
result.classList.remove(svgLoaderAutoresizeClassName);
|
21
|
+
}
|
22
|
+
setExportedSVGSize(result, importExportViewport, options);
|
23
|
+
return result;
|
24
|
+
});
|
25
|
+
return result;
|
26
|
+
};
|
27
|
+
export const editorImageToSVGSync = (image, options) => {
|
28
|
+
return toSVGInternal(image, (renderer, onComplete) => {
|
29
|
+
image.renderAll(renderer);
|
30
|
+
onComplete();
|
31
|
+
}, options);
|
32
|
+
};
|
33
|
+
export const editorImageToSVGAsync = (image, preRenderComponent, options) => {
|
34
|
+
return new Promise(resolve => {
|
35
|
+
toSVGInternal(image, async (renderer, onComplete) => {
|
36
|
+
await image.renderAllAsync(renderer, preRenderComponent);
|
37
|
+
const result = onComplete();
|
38
|
+
resolve(result);
|
39
|
+
}, options);
|
40
|
+
});
|
41
|
+
};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { toRoundedString } from '@js-draw/math';
|
2
|
+
// @internal
|
3
|
+
const setExportedSVGSize = (svg, viewport, options) => {
|
4
|
+
// Just show the main region
|
5
|
+
const rect = viewport.visibleRect;
|
6
|
+
svg.setAttribute('viewBox', [rect.x, rect.y, rect.w, rect.h].map(part => toRoundedString(part)).join(' '));
|
7
|
+
// Adjust the width/height as necessary
|
8
|
+
let width = rect.w;
|
9
|
+
let height = rect.h;
|
10
|
+
if (options?.minDimension && width < options.minDimension) {
|
11
|
+
const newWidth = options.minDimension;
|
12
|
+
height *= newWidth / (width || 1);
|
13
|
+
width = newWidth;
|
14
|
+
}
|
15
|
+
if (options?.minDimension && height < options.minDimension) {
|
16
|
+
const newHeight = options.minDimension;
|
17
|
+
width *= newHeight / (height || 1);
|
18
|
+
height = newHeight;
|
19
|
+
}
|
20
|
+
svg.setAttribute('width', toRoundedString(width));
|
21
|
+
svg.setAttribute('height', toRoundedString(height));
|
22
|
+
};
|
23
|
+
export default setExportedSVGSize;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as EditorImage } from './EditorImage';
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as EditorImage } from './EditorImage.mjs';
|
package/dist/mjs/lib.d.ts
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
* @packageDocumentation
|
16
16
|
*/
|
17
17
|
import Editor, { EditorSettings } from './Editor';
|
18
|
-
export
|
18
|
+
export * from './image/lib';
|
19
19
|
export * from './types';
|
20
20
|
export * from './inputEvents';
|
21
21
|
export { default as getLocalizationTable, matchingLocalizationTable } from './localizations/getLocalizationTable';
|
package/dist/mjs/lib.mjs
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
* @packageDocumentation
|
16
16
|
*/
|
17
17
|
import Editor from './Editor.mjs';
|
18
|
-
export
|
18
|
+
export * from './image/lib.mjs';
|
19
19
|
export * from './types.mjs';
|
20
20
|
export * from './inputEvents.mjs';
|
21
21
|
export { default as getLocalizationTable, matchingLocalizationTable } from './localizations/getLocalizationTable.mjs';
|
@@ -1,68 +1,88 @@
|
|
1
1
|
import { defaultEditorLocalization } from '../localization.mjs';
|
2
|
-
// A partial Spanish localization.
|
2
|
+
// A partial Spanish localization, created with /scripts/markdownTranslationFormToTs.ts
|
3
3
|
const localization = {
|
4
4
|
...defaultEditorLocalization,
|
5
|
-
// Strings for the main editor interface
|
6
|
-
// (see src/localization.ts)
|
7
|
-
loading: (percentage) => `Cargando: ${percentage}%...`,
|
8
|
-
imageEditor: 'Editor de dibujos',
|
9
|
-
undoAnnouncement: (commandDescription) => `${commandDescription} fue deshecho`,
|
10
|
-
redoAnnouncement: (commandDescription) => `${commandDescription} fue rehecho`,
|
11
|
-
undo: 'Deshace',
|
12
|
-
redo: 'Rehace',
|
13
|
-
// Strings for the toolbar
|
14
|
-
// (see src/toolbar/localization.ts)
|
15
5
|
pen: 'Lapiz',
|
16
6
|
eraser: 'Borrador',
|
17
7
|
select: 'Selecciona',
|
18
|
-
thicknessLabel: 'Tamaño',
|
19
|
-
colorLabel: 'Color',
|
20
|
-
doneLoading: 'El cargado terminó',
|
21
|
-
fontLabel: 'Fuente: ',
|
22
|
-
anyDevicePanning: 'Mover la pantalla con todo dispotivo',
|
23
|
-
touchPanning: 'Mover la pantalla con un dedo',
|
24
|
-
touchPanTool: 'Instrumento de mover la pantalla con un dedo',
|
25
|
-
outlinedRectanglePen: 'Rectángulo con nada más que un borde',
|
26
|
-
filledRectanglePen: 'Rectángulo sin borde',
|
27
|
-
linePen: 'Línea',
|
28
|
-
arrowPen: 'Flecha',
|
29
|
-
roundedTipPen: 'Lapiz Redondeado',
|
30
|
-
selectPenTip: 'Forma de dibuja',
|
31
8
|
handTool: 'Mover',
|
32
|
-
|
9
|
+
image: 'Imagen',
|
10
|
+
chooseFile: 'Seleccionar archivo',
|
11
|
+
cancel: 'Cancelar',
|
33
12
|
resetView: 'Reiniciar vista',
|
13
|
+
thicknessLabel: 'Tamaño',
|
14
|
+
fontLabel: 'Fuente:',
|
15
|
+
textSize: 'Tamaño',
|
34
16
|
resizeImageToSelection: 'Redimensionar la imagen a lo que está seleccionado',
|
35
17
|
deleteSelection: 'Borra la selección',
|
36
18
|
duplicateSelection: 'Duplica la selección',
|
19
|
+
exit: 'Salir',
|
20
|
+
save: 'Guardar',
|
21
|
+
undo: 'Deshace',
|
22
|
+
redo: 'Rehace',
|
23
|
+
selectPenTip: 'Punta',
|
24
|
+
selectShape: 'Forma',
|
37
25
|
pickColorFromScreen: 'Selecciona un color de la pantalla',
|
38
26
|
clickToPickColorAnnouncement: 'Haga un clic en la pantalla para seleccionar un color',
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
27
|
+
documentProperties: 'Fondo',
|
28
|
+
backgroundColor: 'Color de fondo',
|
29
|
+
imageWidthOption: 'Ancho',
|
30
|
+
imageHeightOption: 'Alto',
|
31
|
+
toggleOverflow: 'Más',
|
32
|
+
touchPanning: 'Mover la pantalla con un dedo',
|
33
|
+
roundedTipPen: 'Lapiz Redondeado',
|
34
|
+
arrowPen: 'Flecha',
|
35
|
+
linePen: 'Línea',
|
36
|
+
outlinedRectanglePen: 'Rectángulo delineado',
|
37
|
+
filledRectanglePen: 'Rectángulo sin borde',
|
38
|
+
lockRotation: 'Bloquea rotación',
|
39
|
+
paste: 'Pegar',
|
40
|
+
closeSidebar: (toolName) => `Close sidebar for ${toolName}`,
|
41
|
+
dropdownShown: (toolName) => `Menú por ${toolName} es visible`,
|
42
|
+
dropdownHidden: (toolName) => { return `Menú por ${toolName} fue ocultado`; },
|
43
|
+
zoomLevel: (zoomPercent) => `Zoom: ${zoomPercent}%`,
|
44
|
+
colorChangedAnnouncement: (color) => { return `Color fue cambiado a ${color}`; },
|
45
|
+
imageSize: (size, units) => `Tamaño del imagen: ${size} ${units}`,
|
46
|
+
imageLoadError: (message) => `Error cargando imagen: ${message}`,
|
47
|
+
penTool: (penId) => { return `Lapiz ${penId}`; },
|
52
48
|
selectionTool: 'Selecciona',
|
53
49
|
eraserTool: 'Borrador',
|
50
|
+
touchPanTool: 'Instrumento de mover la pantalla con un dedo',
|
51
|
+
pipetteTool: 'Seleccione un color de la pantalla',
|
52
|
+
keyboardPanZoom: 'Mover la pantalla con el teclado',
|
54
53
|
textTool: 'Texto',
|
55
54
|
enterTextToInsert: 'Entra texto',
|
56
|
-
|
55
|
+
findLabel: 'Buscar',
|
56
|
+
toNextMatch: 'Próxima',
|
57
|
+
closeDialog: 'Cerrar',
|
58
|
+
focusedFoundText: (matchIdx, totalMatches) => `Viewing match ${matchIdx} of ${totalMatches}`,
|
59
|
+
anyDevicePanning: 'Mover la pantalla con todo dispotivo',
|
60
|
+
copied: (count, description) => `Copied ${count} ${description}`,
|
61
|
+
pasted: (count, description) => `Pasted ${count} ${description}`,
|
62
|
+
toolEnabledAnnouncement: (toolName) => `${toolName} enabled`,
|
63
|
+
toolDisabledAnnouncement: (toolName) => `${toolName} disabled`,
|
64
|
+
transformedElements: (elemCount) => `Transformed ${elemCount} element${elemCount === 1 ? '' : 's'}`,
|
65
|
+
resizeOutputCommand: (newSize) => `Resized image to ${newSize.w}x${newSize.h}`,
|
66
|
+
addElementAction: (componentDescription) => `Added ${componentDescription}`,
|
67
|
+
eraseAction: (componentDescription, numElems) => `Erased ${numElems} ${componentDescription}`,
|
68
|
+
duplicateAction: (componentDescription, numElems) => `Duplicated ${numElems} ${componentDescription}`,
|
69
|
+
unionOf: (actionDescription, actionCount) => `Union: ${actionCount} ${actionDescription}`,
|
70
|
+
inverseOf: (actionDescription) => `Inverse of ${actionDescription}`,
|
71
|
+
rotatedBy: (degrees) => `Rotated by ${Math.abs(degrees)} degrees ${degrees < 0 ? 'clockwise' : 'counter-clockwise'}`,
|
72
|
+
selectedElements: (count) => `Selected ${count} element${count === 1 ? '' : 's'}`,
|
73
|
+
filledBackgroundWithColor: (color) => `Filled background (${color})`,
|
74
|
+
text: (text) => `Text object: ${text}`,
|
75
|
+
imageNode: (label) => `Image: ${label}`,
|
76
|
+
restyledElement: (elementDescription) => `Restyled ${elementDescription}`,
|
77
|
+
pathNodeCount: (count) => `There are ${count} visible path objects.`,
|
78
|
+
textNodeCount: (count) => `There are ${count} visible text nodes.`,
|
79
|
+
imageNodeCount: (nodeCount) => `There are ${nodeCount} visible image nodes.`,
|
80
|
+
textNode: (content) => `Text: ${content}`,
|
57
81
|
rerenderAsText: 'Redibuja la pantalla al texto',
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
documentProperties: 'Fondo',
|
64
|
-
imageWidthOption: 'Ancho',
|
65
|
-
imageHeightOption: 'Alto',
|
66
|
-
backgroundColor: 'Color de fondo: '
|
82
|
+
loading: (percentage) => `Cargando: ${percentage}%...`,
|
83
|
+
imageEditor: 'Editor de dibujos',
|
84
|
+
doneLoading: 'El cargado terminó',
|
85
|
+
undoAnnouncement: (commandDescription) => `${commandDescription} fue deshecho`,
|
86
|
+
redoAnnouncement: (commandDescription) => `${commandDescription} fue rehecho`,
|
67
87
|
};
|
68
88
|
export default localization;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
// A cache record with sub-nodes.
|
2
|
-
import { sortLeavesByZIndex } from '../../EditorImage.mjs';
|
2
|
+
import { sortLeavesByZIndex } from '../../image/EditorImage.mjs';
|
3
3
|
import { Rect2, Color4 } from '@js-draw/math';
|
4
4
|
// 3x3 divisions for each node.
|
5
5
|
const cacheDivisionSize = 3;
|
@@ -42,11 +42,12 @@ export default class RenderingCacheNode {
|
|
42
42
|
// Generates children, if missing.
|
43
43
|
generateChildren() {
|
44
44
|
if (this.instantiatedChildren.length === 0) {
|
45
|
-
|
46
|
-
if (this.region.size.x === 0 || this.region.size.y === 0) {
|
45
|
+
if (this.region.size.x / cacheDivisionSize === 0 || this.region.size.y / cacheDivisionSize === 0) {
|
47
46
|
console.warn('Cache element has zero size! Not generating children.');
|
48
47
|
return;
|
49
48
|
}
|
49
|
+
const childRects = this.region.divideIntoGrid(cacheDivisionSize, cacheDivisionSize);
|
50
|
+
console.assert(childRects.length === cacheDivisionSize * cacheDivisionSize, 'Warning: divideIntoGrid created the wrong number of subrectangles!');
|
50
51
|
for (const rect of childRects) {
|
51
52
|
const child = new RenderingCacheNode(rect, this.cacheState);
|
52
53
|
child.parent = this;
|
@@ -8,6 +8,10 @@ export interface SpacerOptions {
|
|
8
8
|
minSize: string;
|
9
9
|
maxSize: string;
|
10
10
|
}
|
11
|
+
export type ToolbarActionButtonOptions = {
|
12
|
+
mustBeToplevel?: boolean;
|
13
|
+
autoDisableInReadOnlyEditors?: boolean;
|
14
|
+
};
|
11
15
|
export default abstract class AbstractToolbar {
|
12
16
|
#private;
|
13
17
|
protected editor: Editor;
|
@@ -91,18 +95,22 @@ export default abstract class AbstractToolbar {
|
|
91
95
|
* @see
|
92
96
|
* {@link addActionButton}
|
93
97
|
*/
|
94
|
-
protected makeActionButton(title: string | ActionButtonIcon, command: () => void,
|
98
|
+
protected makeActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
|
95
99
|
/**
|
96
100
|
* Adds an action button with `title` to this toolbar (or to the given `parent` element).
|
97
101
|
*
|
102
|
+
* `options` can either be an object with properties `mustBeToplevel` and/or
|
103
|
+
* `autoDisableInReadOnlyEditors` or a boolean value. If a boolean, it is interpreted
|
104
|
+
* as being the value of `mustBeToplevel`.
|
105
|
+
*
|
98
106
|
* @return The added button.
|
99
107
|
*/
|
100
|
-
addActionButton(title: string | ActionButtonIcon, command: () => void,
|
108
|
+
addActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
|
101
109
|
/**
|
102
110
|
* Like {@link addActionButton}, except associates `tags` with the button that allow
|
103
111
|
* different toolbar styles to give the button tag-dependent styles.
|
104
112
|
*/
|
105
|
-
addTaggedActionButton(tags: (ToolbarWidgetTag | string)[], title: string | ActionButtonIcon, command: () => void,
|
113
|
+
addTaggedActionButton(tags: (ToolbarWidgetTag | string)[], title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
|
106
114
|
/**
|
107
115
|
* Adds a save button that, when clicked, calls `saveCallback`.
|
108
116
|
*
|
@@ -230,7 +230,15 @@ class AbstractToolbar {
|
|
230
230
|
* @see
|
231
231
|
* {@link addActionButton}
|
232
232
|
*/
|
233
|
-
makeActionButton(title, command,
|
233
|
+
makeActionButton(title, command, options = true) {
|
234
|
+
// Parse options
|
235
|
+
if (typeof options === 'boolean') {
|
236
|
+
options = {
|
237
|
+
mustBeToplevel: options,
|
238
|
+
};
|
239
|
+
}
|
240
|
+
const mustBeToplevel = options.mustBeToplevel ?? true;
|
241
|
+
const autoDisableInReadOnlyEditors = options.autoDisableInReadOnlyEditors ?? true;
|
234
242
|
const titleString = typeof title === 'string' ? title : title.label;
|
235
243
|
const widgetId = 'action-button';
|
236
244
|
const makeIcon = () => {
|
@@ -239,16 +247,20 @@ class AbstractToolbar {
|
|
239
247
|
}
|
240
248
|
return title.icon;
|
241
249
|
};
|
242
|
-
const widget = new ActionButtonWidget(this.editor, widgetId, makeIcon, titleString, command, this.editor.localization, mustBeToplevel);
|
250
|
+
const widget = new ActionButtonWidget(this.editor, widgetId, makeIcon, titleString, command, this.editor.localization, mustBeToplevel, autoDisableInReadOnlyEditors);
|
243
251
|
return widget;
|
244
252
|
}
|
245
253
|
/**
|
246
254
|
* Adds an action button with `title` to this toolbar (or to the given `parent` element).
|
247
255
|
*
|
256
|
+
* `options` can either be an object with properties `mustBeToplevel` and/or
|
257
|
+
* `autoDisableInReadOnlyEditors` or a boolean value. If a boolean, it is interpreted
|
258
|
+
* as being the value of `mustBeToplevel`.
|
259
|
+
*
|
248
260
|
* @return The added button.
|
249
261
|
*/
|
250
|
-
addActionButton(title, command,
|
251
|
-
const widget = this.makeActionButton(title, command,
|
262
|
+
addActionButton(title, command, options = true) {
|
263
|
+
const widget = this.makeActionButton(title, command, options);
|
252
264
|
this.addWidget(widget);
|
253
265
|
return widget;
|
254
266
|
}
|
@@ -256,8 +268,8 @@ class AbstractToolbar {
|
|
256
268
|
* Like {@link addActionButton}, except associates `tags` with the button that allow
|
257
269
|
* different toolbar styles to give the button tag-dependent styles.
|
258
270
|
*/
|
259
|
-
addTaggedActionButton(tags, title, command,
|
260
|
-
const widget = this.makeActionButton(title, command,
|
271
|
+
addTaggedActionButton(tags, title, command, options = true) {
|
272
|
+
const widget = this.makeActionButton(title, command, options);
|
261
273
|
widget.setTags(tags);
|
262
274
|
this.addWidget(widget);
|
263
275
|
return widget;
|
@@ -303,6 +315,8 @@ class AbstractToolbar {
|
|
303
315
|
icon: this.editor.icons.makeCloseIcon(),
|
304
316
|
}, () => {
|
305
317
|
exitCallback();
|
318
|
+
}, {
|
319
|
+
autoDisableInReadOnlyEditors: false,
|
306
320
|
});
|
307
321
|
}
|
308
322
|
/**
|
@@ -191,7 +191,6 @@ export default class EdgeToolbar extends AbstractToolbar {
|
|
191
191
|
};
|
192
192
|
const actionRowBBox = this.toolbarActionRow.getBoundingClientRect();
|
193
193
|
const toolbarRowBBox = this.toolbarToolRow.getBoundingClientRect();
|
194
|
-
const inSameRow = actionRowBBox.y === toolbarRowBBox.y;
|
195
194
|
const onDifferentRows = actionRowBBox.y + actionRowBBox.height <= toolbarRowBBox.y;
|
196
195
|
if (onDifferentRows) {
|
197
196
|
this.toolbarContainer.classList.remove('one-row');
|
@@ -201,11 +200,11 @@ export default class EdgeToolbar extends AbstractToolbar {
|
|
201
200
|
}
|
202
201
|
if (this.toolbarToolRow.clientWidth < this.toolbarToolRow.scrollWidth) {
|
203
202
|
this.toolbarToolRow.classList.add('has-scroll');
|
204
|
-
//
|
205
|
-
//
|
206
|
-
|
207
|
-
|
208
|
-
|
203
|
+
// Note: This can potentially change the size of the tool row.
|
204
|
+
// Because this is run inside of a ResizeObserver callback, special
|
205
|
+
// care must be taken to ensure that this change doesn't re-trigger
|
206
|
+
// the resize observer.
|
207
|
+
setExtraPadding();
|
209
208
|
}
|
210
209
|
else {
|
211
210
|
this.toolbarToolRow.classList.remove('has-scroll', 'extra-padding');
|
@@ -38,6 +38,7 @@ export default class IconProvider {
|
|
38
38
|
makeDropdownIcon(): IconElemType;
|
39
39
|
makeEraserIcon(eraserSize?: number): IconElemType;
|
40
40
|
makeSelectionIcon(): IconElemType;
|
41
|
+
makeRotateIcon(): IconElemType;
|
41
42
|
makeHandToolIcon(): IconElemType;
|
42
43
|
makeTouchPanningIcon(): IconElemType;
|
43
44
|
/** Unused by js-draw. @deprecated */
|
@@ -164,6 +164,49 @@ class IconProvider {
|
|
164
164
|
icon.setAttribute('viewBox', '0 0 100 100');
|
165
165
|
return icon;
|
166
166
|
}
|
167
|
+
makeRotateIcon() {
|
168
|
+
const icon = document.createElementNS(svgNamespace, 'svg');
|
169
|
+
icon.innerHTML = `
|
170
|
+
<defs>
|
171
|
+
<marker
|
172
|
+
id="arrow-marker"
|
173
|
+
viewBox="0 0 10 10"
|
174
|
+
refX="3" refY="5"
|
175
|
+
markerWidth="3" markerHeight="3"
|
176
|
+
orient="auto-start-reverse"
|
177
|
+
>
|
178
|
+
<path
|
179
|
+
d="M0,0 L8,5 L0,10z"
|
180
|
+
fill="var(--icon-color)"
|
181
|
+
/>
|
182
|
+
</marker>
|
183
|
+
</defs>
|
184
|
+
|
185
|
+
<path
|
186
|
+
marker-start="url(#arrow-marker)"
|
187
|
+
d="
|
188
|
+
M20,20
|
189
|
+
A30,30 0 1 1 80 80
|
190
|
+
"
|
191
|
+
fill="none"
|
192
|
+
stroke="var(--icon-color)"
|
193
|
+
stroke-width="12"
|
194
|
+
/>
|
195
|
+
<path
|
196
|
+
d="
|
197
|
+
M80,80
|
198
|
+
A30,30 0 1 1 20 20
|
199
|
+
"
|
200
|
+
fill="none"
|
201
|
+
stroke="var(--icon-color)"
|
202
|
+
stroke-width="12"
|
203
|
+
stroke-dasharray="30 10 20 10 20 10 10"
|
204
|
+
style="stroke-linecap: butt;"
|
205
|
+
/>
|
206
|
+
`;
|
207
|
+
icon.setAttribute('viewBox', '-5 -5 110 110');
|
208
|
+
return icon;
|
209
|
+
}
|
167
210
|
makeHandToolIcon() {
|
168
211
|
const fill = 'none';
|
169
212
|
const strokeColor = 'var(--icon-color)';
|
@@ -2,11 +2,13 @@ import Editor from '../../Editor';
|
|
2
2
|
import { ToolbarLocalization } from '../localization';
|
3
3
|
import BaseWidget from './BaseWidget';
|
4
4
|
export default class ActionButtonWidget extends BaseWidget {
|
5
|
+
#private;
|
5
6
|
protected makeIcon: () => Element | null;
|
6
7
|
protected title: string;
|
7
8
|
protected clickAction: () => void;
|
8
9
|
protected mustBeToplevel: boolean;
|
9
|
-
constructor(editor: Editor, id: string, makeIcon: () => Element | null, title: string, clickAction: () => void, localizationTable?: ToolbarLocalization, mustBeToplevel?: boolean);
|
10
|
+
constructor(editor: Editor, id: string, makeIcon: () => Element | null, title: string, clickAction: () => void, localizationTable?: ToolbarLocalization, mustBeToplevel?: boolean, autoDisableInReadOnlyEditors?: boolean);
|
11
|
+
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
10
12
|
protected handleClick(): void;
|
11
13
|
protected getTitle(): string;
|
12
14
|
protected createIcon(): Element | null;
|
@@ -1,11 +1,28 @@
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
6
|
+
};
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
11
|
+
};
|
12
|
+
var _ActionButtonWidget_autoDisableInReadOnlyEditors;
|
1
13
|
import BaseWidget from './BaseWidget.mjs';
|
2
|
-
|
3
|
-
constructor(editor, id, makeIcon, title, clickAction, localizationTable, mustBeToplevel = false) {
|
14
|
+
class ActionButtonWidget extends BaseWidget {
|
15
|
+
constructor(editor, id, makeIcon, title, clickAction, localizationTable, mustBeToplevel = false, autoDisableInReadOnlyEditors = true) {
|
4
16
|
super(editor, id, localizationTable);
|
5
17
|
this.makeIcon = makeIcon;
|
6
18
|
this.title = title;
|
7
19
|
this.clickAction = clickAction;
|
8
20
|
this.mustBeToplevel = mustBeToplevel;
|
21
|
+
_ActionButtonWidget_autoDisableInReadOnlyEditors.set(this, void 0);
|
22
|
+
__classPrivateFieldSet(this, _ActionButtonWidget_autoDisableInReadOnlyEditors, autoDisableInReadOnlyEditors, "f");
|
23
|
+
}
|
24
|
+
shouldAutoDisableInReadOnlyEditor() {
|
25
|
+
return __classPrivateFieldGet(this, _ActionButtonWidget_autoDisableInReadOnlyEditors, "f");
|
9
26
|
}
|
10
27
|
handleClick() {
|
11
28
|
this.clickAction();
|
@@ -23,3 +40,5 @@ export default class ActionButtonWidget extends BaseWidget {
|
|
23
40
|
return this.mustBeToplevel;
|
24
41
|
}
|
25
42
|
}
|
43
|
+
_ActionButtonWidget_autoDisableInReadOnlyEditors = new WeakMap();
|
44
|
+
export default ActionButtonWidget;
|
@@ -6,6 +6,7 @@ import BaseWidget from './BaseWidget';
|
|
6
6
|
export default abstract class BaseToolWidget extends BaseWidget {
|
7
7
|
protected targetTool: BaseTool;
|
8
8
|
constructor(editor: Editor, targetTool: BaseTool, id: string, localizationTable?: ToolbarLocalization);
|
9
|
+
protected shouldAutoDisableInReadOnlyEditor(): boolean;
|
9
10
|
protected handleClick(): void;
|
10
11
|
protected onKeyPress(event: KeyPressEvent): boolean;
|
11
12
|
addTo(parent: HTMLElement): HTMLElement;
|
@@ -34,6 +34,9 @@ export default class BaseToolWidget extends BaseWidget {
|
|
34
34
|
}
|
35
35
|
});
|
36
36
|
}
|
37
|
+
shouldAutoDisableInReadOnlyEditor() {
|
38
|
+
return !this.targetTool.canReceiveInputInReadOnlyEditor();
|
39
|
+
}
|
37
40
|
handleClick() {
|
38
41
|
if (this.hasDropdown) {
|
39
42
|
if (!this.targetTool.isEnabled()) {
|