js-draw 0.18.2 → 0.20.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/.eslintrc.js +1 -0
- package/CHANGELOG.md +10 -0
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -0
- package/dist/cjs/src/Color4.d.ts +8 -0
- package/dist/cjs/src/Color4.js +67 -0
- package/dist/cjs/src/Editor.d.ts +2 -2
- package/dist/cjs/src/Editor.js +7 -7
- package/dist/cjs/src/SVGLoader.js +77 -12
- package/dist/cjs/src/Viewport.d.ts +2 -0
- package/dist/cjs/src/Viewport.js +6 -2
- package/dist/cjs/src/components/AbstractComponent.d.ts +2 -2
- package/dist/cjs/src/components/AbstractComponent.js +3 -3
- package/dist/cjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
- package/dist/cjs/src/components/BackgroundComponent.js +309 -0
- package/dist/cjs/src/components/RestylableComponent.d.ts +21 -2
- package/dist/cjs/src/components/Stroke.d.ts +35 -0
- package/dist/cjs/src/components/Stroke.js +37 -3
- package/dist/cjs/src/components/TextComponent.d.ts +27 -17
- package/dist/cjs/src/components/TextComponent.js +23 -1
- package/dist/cjs/src/components/lib.d.ts +4 -3
- package/dist/cjs/src/components/lib.js +2 -2
- package/dist/cjs/src/components/util/StrokeSmoother.js +25 -15
- package/dist/cjs/src/lib.d.ts +30 -0
- package/dist/cjs/src/lib.js +30 -0
- package/dist/cjs/src/localizations/de.js +1 -1
- package/dist/cjs/src/localizations/es.js +1 -1
- package/dist/cjs/src/math/Path.js +1 -1
- package/dist/cjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/cjs/src/math/polynomial/QuadraticBezier.js +115 -0
- package/dist/cjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
- package/dist/cjs/src/math/polynomial/solveQuadratic.js +36 -0
- package/dist/cjs/src/rendering/RenderingStyle.d.ts +4 -4
- package/dist/cjs/src/rendering/TextRenderingStyle.d.ts +10 -10
- package/dist/cjs/src/rendering/lib.d.ts +2 -0
- package/dist/cjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/CanvasRenderer.js +5 -3
- package/dist/cjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
- package/dist/cjs/src/rendering/renderers/SVGRenderer.js +15 -6
- package/dist/cjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
- package/dist/cjs/src/toolbar/IconProvider.d.ts +2 -2
- package/dist/cjs/src/toolbar/localization.d.ts +2 -1
- package/dist/cjs/src/toolbar/localization.js +3 -2
- package/dist/cjs/src/toolbar/widgets/BaseWidget.js +1 -1
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.js +77 -2
- package/dist/cjs/src/toolbar/widgets/PenToolWidget.js +1 -1
- package/dist/cjs/src/tools/FindTool.js +1 -1
- package/dist/cjs/src/tools/SoundUITool.d.ts +24 -0
- package/dist/cjs/src/tools/SoundUITool.js +164 -0
- package/dist/cjs/src/tools/TextTool.d.ts +2 -2
- package/dist/cjs/src/tools/ToolController.js +6 -1
- package/dist/cjs/src/tools/lib.d.ts +1 -0
- package/dist/cjs/src/tools/lib.js +3 -1
- package/dist/cjs/src/tools/localization.d.ts +3 -0
- package/dist/cjs/src/tools/localization.js +3 -0
- package/dist/mjs/src/Color4.d.ts +8 -0
- package/dist/mjs/src/Color4.mjs +64 -0
- package/dist/mjs/src/Editor.d.ts +2 -2
- package/dist/mjs/src/Editor.mjs +6 -6
- package/dist/mjs/src/SVGLoader.mjs +76 -11
- package/dist/mjs/src/Viewport.d.ts +2 -0
- package/dist/mjs/src/Viewport.mjs +6 -2
- package/dist/mjs/src/components/AbstractComponent.d.ts +2 -2
- package/dist/mjs/src/components/AbstractComponent.mjs +3 -3
- package/dist/mjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
- package/dist/mjs/src/components/BackgroundComponent.mjs +279 -0
- package/dist/mjs/src/components/RestylableComponent.d.ts +21 -2
- package/dist/mjs/src/components/Stroke.d.ts +35 -0
- package/dist/mjs/src/components/Stroke.mjs +37 -3
- package/dist/mjs/src/components/TextComponent.d.ts +27 -17
- package/dist/mjs/src/components/TextComponent.mjs +23 -1
- package/dist/mjs/src/components/lib.d.ts +4 -3
- package/dist/mjs/src/components/lib.mjs +2 -2
- package/dist/mjs/src/components/util/StrokeSmoother.mjs +25 -15
- package/dist/mjs/src/lib.d.ts +30 -0
- package/dist/mjs/src/lib.mjs +30 -0
- package/dist/mjs/src/localizations/de.mjs +1 -1
- package/dist/mjs/src/localizations/es.mjs +1 -1
- package/dist/mjs/src/math/Path.mjs +1 -1
- package/dist/mjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/mjs/src/math/polynomial/QuadraticBezier.mjs +109 -0
- package/dist/mjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
- package/dist/mjs/src/math/polynomial/solveQuadratic.mjs +34 -0
- package/dist/mjs/src/rendering/RenderingStyle.d.ts +4 -4
- package/dist/mjs/src/rendering/TextRenderingStyle.d.ts +10 -10
- package/dist/mjs/src/rendering/lib.d.ts +2 -0
- package/dist/mjs/src/rendering/renderers/AbstractRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/CanvasRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/CanvasRenderer.mjs +5 -3
- package/dist/mjs/src/rendering/renderers/DummyRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/SVGRenderer.d.ts +2 -2
- package/dist/mjs/src/rendering/renderers/SVGRenderer.mjs +15 -6
- package/dist/mjs/src/rendering/renderers/TextOnlyRenderer.d.ts +2 -2
- package/dist/mjs/src/toolbar/IconProvider.d.ts +2 -2
- package/dist/mjs/src/toolbar/localization.d.ts +2 -1
- package/dist/mjs/src/toolbar/localization.mjs +3 -2
- package/dist/mjs/src/toolbar/widgets/BaseWidget.mjs +1 -1
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.mjs +54 -2
- package/dist/mjs/src/toolbar/widgets/PenToolWidget.mjs +1 -1
- package/dist/mjs/src/tools/FindTool.mjs +1 -1
- package/dist/mjs/src/tools/SoundUITool.d.ts +24 -0
- package/dist/mjs/src/tools/SoundUITool.mjs +158 -0
- package/dist/mjs/src/tools/TextTool.d.ts +2 -2
- package/dist/mjs/src/tools/ToolController.mjs +6 -1
- package/dist/mjs/src/tools/lib.d.ts +1 -0
- package/dist/mjs/src/tools/lib.mjs +1 -0
- package/dist/mjs/src/tools/localization.d.ts +3 -0
- package/dist/mjs/src/tools/localization.mjs +3 -0
- package/jest.config.js +1 -1
- package/package.json +19 -17
- package/src/Editor.css +2 -2
- package/src/tools/SoundUITool.css +15 -0
- package/src/tools/tools.css +4 -0
- package/dist/cjs/src/components/ImageBackground.js +0 -146
- package/dist/mjs/src/components/ImageBackground.mjs +0 -139
- package/src/Color4.test.ts +0 -40
- package/src/Color4.ts +0 -236
- package/src/Editor.loadFrom.test.ts +0 -24
- package/src/Editor.toSVG.test.ts +0 -111
- package/src/Editor.ts +0 -1122
- package/src/EditorImage.test.ts +0 -120
- package/src/EditorImage.ts +0 -603
- package/src/EventDispatcher.test.ts +0 -123
- package/src/EventDispatcher.ts +0 -71
- package/src/Pointer.ts +0 -127
- package/src/SVGLoader.test.ts +0 -114
- package/src/SVGLoader.ts +0 -511
- package/src/UndoRedoHistory.test.ts +0 -33
- package/src/UndoRedoHistory.ts +0 -102
- package/src/Viewport.ts +0 -319
- package/src/bundle/bundled.ts +0 -7
- package/src/commands/Command.ts +0 -45
- package/src/commands/Duplicate.ts +0 -48
- package/src/commands/Erase.ts +0 -74
- package/src/commands/SerializableCommand.ts +0 -49
- package/src/commands/UnresolvedCommand.ts +0 -37
- package/src/commands/invertCommand.ts +0 -51
- package/src/commands/lib.ts +0 -16
- package/src/commands/localization.ts +0 -47
- package/src/commands/uniteCommands.test.ts +0 -23
- package/src/commands/uniteCommands.ts +0 -135
- package/src/components/AbstractComponent.transformBy.test.ts +0 -22
- package/src/components/AbstractComponent.ts +0 -364
- package/src/components/ImageBackground.test.ts +0 -35
- package/src/components/ImageBackground.ts +0 -176
- package/src/components/ImageComponent.ts +0 -171
- package/src/components/RestylableComponent.ts +0 -142
- package/src/components/SVGGlobalAttributesObject.ts +0 -81
- package/src/components/Stroke.test.ts +0 -139
- package/src/components/Stroke.ts +0 -245
- package/src/components/TextComponent.test.ts +0 -99
- package/src/components/TextComponent.ts +0 -315
- package/src/components/UnknownSVGObject.test.ts +0 -10
- package/src/components/UnknownSVGObject.ts +0 -60
- package/src/components/builders/ArrowBuilder.ts +0 -107
- package/src/components/builders/FreehandLineBuilder.ts +0 -212
- package/src/components/builders/LineBuilder.ts +0 -77
- package/src/components/builders/PressureSensitiveFreehandLineBuilder.ts +0 -454
- package/src/components/builders/RectangleBuilder.ts +0 -74
- package/src/components/builders/types.ts +0 -15
- package/src/components/lib.ts +0 -25
- package/src/components/localization.ts +0 -22
- package/src/components/util/StrokeSmoother.ts +0 -293
- package/src/components/util/describeComponentList.ts +0 -18
- package/src/lib.ts +0 -37
- package/src/localization.ts +0 -34
- package/src/localizations/de.ts +0 -98
- package/src/localizations/en.ts +0 -8
- package/src/localizations/es.ts +0 -74
- package/src/localizations/getLocalizationTable.test.ts +0 -27
- package/src/localizations/getLocalizationTable.ts +0 -55
- package/src/math/LineSegment2.test.ts +0 -99
- package/src/math/LineSegment2.ts +0 -160
- package/src/math/Mat33.test.ts +0 -244
- package/src/math/Mat33.ts +0 -437
- package/src/math/Path.fromString.test.ts +0 -223
- package/src/math/Path.test.ts +0 -198
- package/src/math/Path.toString.test.ts +0 -77
- package/src/math/Path.ts +0 -790
- package/src/math/Rect2.test.ts +0 -204
- package/src/math/Rect2.ts +0 -315
- package/src/math/Triangle.ts +0 -29
- package/src/math/Vec2.test.ts +0 -30
- package/src/math/Vec2.ts +0 -18
- package/src/math/Vec3.test.ts +0 -44
- package/src/math/Vec3.ts +0 -218
- package/src/math/lib.ts +0 -15
- package/src/math/rounding.test.ts +0 -65
- package/src/math/rounding.ts +0 -156
- package/src/rendering/Display.ts +0 -249
- package/src/rendering/RenderingStyle.test.ts +0 -68
- package/src/rendering/RenderingStyle.ts +0 -55
- package/src/rendering/TextRenderingStyle.ts +0 -45
- package/src/rendering/caching/CacheRecord.test.ts +0 -49
- package/src/rendering/caching/CacheRecord.ts +0 -77
- package/src/rendering/caching/CacheRecordManager.ts +0 -71
- package/src/rendering/caching/RenderingCache.test.ts +0 -44
- package/src/rendering/caching/RenderingCache.ts +0 -66
- package/src/rendering/caching/RenderingCacheNode.ts +0 -405
- package/src/rendering/caching/testUtils.ts +0 -35
- package/src/rendering/caching/types.ts +0 -34
- package/src/rendering/lib.ts +0 -6
- package/src/rendering/localization.ts +0 -20
- package/src/rendering/renderers/AbstractRenderer.ts +0 -222
- package/src/rendering/renderers/CanvasRenderer.ts +0 -296
- package/src/rendering/renderers/DummyRenderer.test.ts +0 -42
- package/src/rendering/renderers/DummyRenderer.ts +0 -136
- package/src/rendering/renderers/SVGRenderer.ts +0 -354
- package/src/rendering/renderers/TextOnlyRenderer.ts +0 -70
- package/src/testing/beforeEachFile.ts +0 -8
- package/src/testing/createEditor.ts +0 -11
- package/src/testing/global.d.ts +0 -17
- package/src/testing/lib.ts +0 -3
- package/src/testing/loadExpectExtensions.ts +0 -25
- package/src/testing/sendPenEvent.ts +0 -31
- package/src/testing/sendTouchEvent.ts +0 -78
- package/src/toolbar/HTMLToolbar.ts +0 -492
- package/src/toolbar/IconProvider.ts +0 -736
- package/src/toolbar/lib.ts +0 -4
- package/src/toolbar/localization.ts +0 -106
- package/src/toolbar/makeColorInput.ts +0 -145
- package/src/toolbar/types.ts +0 -5
- package/src/toolbar/widgets/ActionButtonWidget.ts +0 -39
- package/src/toolbar/widgets/BaseToolWidget.ts +0 -56
- package/src/toolbar/widgets/BaseWidget.ts +0 -377
- package/src/toolbar/widgets/DocumentPropertiesWidget.ts +0 -167
- package/src/toolbar/widgets/EraserToolWidget.ts +0 -85
- package/src/toolbar/widgets/HandToolWidget.ts +0 -250
- package/src/toolbar/widgets/InsertImageWidget.ts +0 -223
- package/src/toolbar/widgets/OverflowWidget.ts +0 -92
- package/src/toolbar/widgets/PenToolWidget.ts +0 -288
- package/src/toolbar/widgets/SelectionToolWidget.ts +0 -190
- package/src/toolbar/widgets/TextToolWidget.ts +0 -145
- package/src/toolbar/widgets/lib.ts +0 -13
- package/src/tools/BaseTool.ts +0 -76
- package/src/tools/Eraser.test.ts +0 -103
- package/src/tools/Eraser.ts +0 -139
- package/src/tools/FindTool.ts +0 -152
- package/src/tools/PanZoom.test.ts +0 -310
- package/src/tools/PanZoom.ts +0 -520
- package/src/tools/PasteHandler.ts +0 -95
- package/src/tools/Pen.test.ts +0 -194
- package/src/tools/Pen.ts +0 -226
- package/src/tools/PipetteTool.ts +0 -55
- package/src/tools/SelectionTool/SelectAllShortcutHandler.ts +0 -28
- package/src/tools/SelectionTool/Selection.ts +0 -607
- package/src/tools/SelectionTool/SelectionHandle.ts +0 -108
- package/src/tools/SelectionTool/SelectionTool.test.ts +0 -261
- package/src/tools/SelectionTool/SelectionTool.ts +0 -480
- package/src/tools/SelectionTool/TransformMode.ts +0 -114
- package/src/tools/SelectionTool/types.ts +0 -11
- package/src/tools/TextTool.ts +0 -326
- package/src/tools/ToolController.ts +0 -178
- package/src/tools/ToolEnabledGroup.ts +0 -14
- package/src/tools/ToolSwitcherShortcut.ts +0 -39
- package/src/tools/ToolbarShortcutHandler.ts +0 -34
- package/src/tools/UndoRedoShortcut.test.ts +0 -56
- package/src/tools/UndoRedoShortcut.ts +0 -25
- package/src/tools/lib.ts +0 -21
- package/src/tools/localization.ts +0 -66
- package/src/types.ts +0 -234
- package/src/util/assertions.ts +0 -55
- package/src/util/fileToBase64.ts +0 -18
- package/src/util/untilNextAnimationFrame.ts +0 -9
- package/src/util/waitForTimeout.ts +0 -9
@@ -1,288 +0,0 @@
|
|
1
|
-
import { makeArrowBuilder } from '../../components/builders/ArrowBuilder';
|
2
|
-
import { makeFreehandLineBuilder } from '../../components/builders/FreehandLineBuilder';
|
3
|
-
import { makePressureSensitiveFreehandLineBuilder } from '../../components/builders/PressureSensitiveFreehandLineBuilder';
|
4
|
-
import { makeLineBuilder } from '../../components/builders/LineBuilder';
|
5
|
-
import { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from '../../components/builders/RectangleBuilder';
|
6
|
-
import { ComponentBuilderFactory } from '../../components/builders/types';
|
7
|
-
import Editor from '../../Editor';
|
8
|
-
import Pen from '../../tools/Pen';
|
9
|
-
import { EditorEventType, KeyPressEvent } from '../../types';
|
10
|
-
import { toolbarCSSPrefix } from '../HTMLToolbar';
|
11
|
-
import { ToolbarLocalization } from '../localization';
|
12
|
-
import makeColorInput from '../makeColorInput';
|
13
|
-
import BaseToolWidget from './BaseToolWidget';
|
14
|
-
import Color4 from '../../Color4';
|
15
|
-
import { SavedToolbuttonState } from './BaseWidget';
|
16
|
-
|
17
|
-
|
18
|
-
export interface PenTypeRecord {
|
19
|
-
// Description of the factory (e.g. 'Freehand line')
|
20
|
-
name: string;
|
21
|
-
|
22
|
-
// A unique ID for the facotory (e.g. 'chisel-tip-pen')
|
23
|
-
id: string;
|
24
|
-
|
25
|
-
// Creates an `AbstractComponent` from pen input.
|
26
|
-
factory: ComponentBuilderFactory;
|
27
|
-
}
|
28
|
-
|
29
|
-
export default class PenToolWidget extends BaseToolWidget {
|
30
|
-
private updateInputs: ()=> void = () => {};
|
31
|
-
protected penTypes: PenTypeRecord[];
|
32
|
-
|
33
|
-
public constructor(
|
34
|
-
editor: Editor, private tool: Pen, localization?: ToolbarLocalization
|
35
|
-
) {
|
36
|
-
super(editor, tool, 'pen', localization);
|
37
|
-
|
38
|
-
// Default pen types
|
39
|
-
this.penTypes = [
|
40
|
-
{
|
41
|
-
name: this.localizationTable.pressureSensitiveFreehandPen,
|
42
|
-
id: 'pressure-sensitive-pen',
|
43
|
-
|
44
|
-
factory: makePressureSensitiveFreehandLineBuilder,
|
45
|
-
},
|
46
|
-
{
|
47
|
-
name: this.localizationTable.freehandPen,
|
48
|
-
id: 'freehand-pen',
|
49
|
-
|
50
|
-
factory: makeFreehandLineBuilder,
|
51
|
-
},
|
52
|
-
{
|
53
|
-
name: this.localizationTable.arrowPen,
|
54
|
-
id: 'arrow',
|
55
|
-
|
56
|
-
factory: makeArrowBuilder,
|
57
|
-
},
|
58
|
-
{
|
59
|
-
name: this.localizationTable.linePen,
|
60
|
-
id: 'line',
|
61
|
-
|
62
|
-
factory: makeLineBuilder,
|
63
|
-
},
|
64
|
-
{
|
65
|
-
name: this.localizationTable.filledRectanglePen,
|
66
|
-
id: 'filled-rectangle',
|
67
|
-
|
68
|
-
factory: makeFilledRectangleBuilder,
|
69
|
-
},
|
70
|
-
{
|
71
|
-
name: this.localizationTable.outlinedRectanglePen,
|
72
|
-
id: 'outlined-rectangle',
|
73
|
-
|
74
|
-
factory: makeOutlinedRectangleBuilder,
|
75
|
-
},
|
76
|
-
];
|
77
|
-
|
78
|
-
this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
|
79
|
-
if (toolEvt.kind !== EditorEventType.ToolUpdated) {
|
80
|
-
throw new Error('Invalid event type!');
|
81
|
-
}
|
82
|
-
|
83
|
-
// The button icon may depend on tool properties.
|
84
|
-
if (toolEvt.tool === this.tool) {
|
85
|
-
this.updateIcon();
|
86
|
-
this.updateInputs();
|
87
|
-
}
|
88
|
-
});
|
89
|
-
}
|
90
|
-
|
91
|
-
protected getTitle(): string {
|
92
|
-
return this.targetTool.description;
|
93
|
-
}
|
94
|
-
|
95
|
-
// Return the index of this tool's stroke factory in the list of
|
96
|
-
// all stroke factories.
|
97
|
-
//
|
98
|
-
// Returns -1 if the stroke factory is not in the list of all stroke factories.
|
99
|
-
private getCurrentPenTypeIdx(): number {
|
100
|
-
const currentFactory = this.tool.getStrokeFactory();
|
101
|
-
|
102
|
-
for (let i = 0; i < this.penTypes.length; i ++) {
|
103
|
-
if (this.penTypes[i].factory === currentFactory) {
|
104
|
-
return i;
|
105
|
-
}
|
106
|
-
}
|
107
|
-
return -1;
|
108
|
-
}
|
109
|
-
|
110
|
-
private getCurrentPenType(): PenTypeRecord|null {
|
111
|
-
for (const penType of this.penTypes) {
|
112
|
-
if (penType.factory === this.tool.getStrokeFactory()) {
|
113
|
-
return penType;
|
114
|
-
}
|
115
|
-
}
|
116
|
-
return null;
|
117
|
-
}
|
118
|
-
|
119
|
-
protected createIcon(): Element {
|
120
|
-
const strokeFactory = this.tool.getStrokeFactory();
|
121
|
-
if (strokeFactory === makeFreehandLineBuilder || strokeFactory === makePressureSensitiveFreehandLineBuilder) {
|
122
|
-
// Use a square-root scale to prevent the pen's tip from overflowing.
|
123
|
-
const scale = Math.round(Math.sqrt(this.tool.getThickness()) * 4);
|
124
|
-
const color = this.tool.getColor();
|
125
|
-
const roundedTip = strokeFactory === makeFreehandLineBuilder;
|
126
|
-
|
127
|
-
return this.editor.icons.makePenIcon(scale, color.toHexString(), roundedTip);
|
128
|
-
} else {
|
129
|
-
const strokeFactory = this.tool.getStrokeFactory();
|
130
|
-
return this.editor.icons.makeIconFromFactory(this.tool, strokeFactory);
|
131
|
-
}
|
132
|
-
}
|
133
|
-
|
134
|
-
private static idCounter: number = 0;
|
135
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
136
|
-
const container = document.createElement('div');
|
137
|
-
container.classList.add(`${toolbarCSSPrefix}spacedList`);
|
138
|
-
|
139
|
-
const thicknessRow = document.createElement('div');
|
140
|
-
const objectTypeRow = document.createElement('div');
|
141
|
-
|
142
|
-
// Thickness: Value of the input is squared to allow for finer control/larger values.
|
143
|
-
const thicknessLabel = document.createElement('label');
|
144
|
-
const thicknessInput = document.createElement('input');
|
145
|
-
const objectSelectLabel = document.createElement('label');
|
146
|
-
const objectTypeSelect = document.createElement('select');
|
147
|
-
|
148
|
-
// Give inputs IDs so we can label them with a <label for=...>Label text</label>
|
149
|
-
thicknessInput.id = `${toolbarCSSPrefix}penThicknessInput${PenToolWidget.idCounter++}`;
|
150
|
-
objectTypeSelect.id = `${toolbarCSSPrefix}penBuilderSelect${PenToolWidget.idCounter++}`;
|
151
|
-
|
152
|
-
thicknessLabel.innerText = this.localizationTable.thicknessLabel;
|
153
|
-
thicknessLabel.setAttribute('for', thicknessInput.id);
|
154
|
-
objectSelectLabel.innerText = this.localizationTable.selectObjectType;
|
155
|
-
objectSelectLabel.setAttribute('for', objectTypeSelect.id);
|
156
|
-
|
157
|
-
// Use a logarithmic scale for thicknessInput (finer control over thinner strokewidths.)
|
158
|
-
const inverseThicknessInputFn = (t: number) => Math.log10(t);
|
159
|
-
const thicknessInputFn = (t: number) => 10**t;
|
160
|
-
|
161
|
-
thicknessInput.type = 'range';
|
162
|
-
thicknessInput.min = `${inverseThicknessInputFn(2)}`;
|
163
|
-
thicknessInput.max = `${inverseThicknessInputFn(400)}`;
|
164
|
-
thicknessInput.step = '0.1';
|
165
|
-
thicknessInput.oninput = () => {
|
166
|
-
this.tool.setThickness(thicknessInputFn(parseFloat(thicknessInput.value)));
|
167
|
-
};
|
168
|
-
thicknessRow.appendChild(thicknessLabel);
|
169
|
-
thicknessRow.appendChild(thicknessInput);
|
170
|
-
|
171
|
-
objectTypeSelect.oninput = () => {
|
172
|
-
const penTypeIdx = parseInt(objectTypeSelect.value);
|
173
|
-
if (penTypeIdx < 0 || penTypeIdx >= this.penTypes.length) {
|
174
|
-
console.error('Invalid pen type index', penTypeIdx);
|
175
|
-
return;
|
176
|
-
}
|
177
|
-
|
178
|
-
this.tool.setStrokeFactory(this.penTypes[penTypeIdx].factory);
|
179
|
-
};
|
180
|
-
objectTypeRow.appendChild(objectSelectLabel);
|
181
|
-
objectTypeRow.appendChild(objectTypeSelect);
|
182
|
-
|
183
|
-
const colorRow = document.createElement('div');
|
184
|
-
const colorLabel = document.createElement('label');
|
185
|
-
const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
|
186
|
-
this.tool.setColor(color);
|
187
|
-
});
|
188
|
-
|
189
|
-
colorInput.id = `${toolbarCSSPrefix}colorInput${PenToolWidget.idCounter++}`;
|
190
|
-
colorLabel.innerText = this.localizationTable.colorLabel;
|
191
|
-
colorLabel.setAttribute('for', colorInput.id);
|
192
|
-
|
193
|
-
colorRow.appendChild(colorLabel);
|
194
|
-
colorRow.appendChild(colorInputContainer);
|
195
|
-
|
196
|
-
this.updateInputs = () => {
|
197
|
-
setColorInputValue(this.tool.getColor());
|
198
|
-
thicknessInput.value = inverseThicknessInputFn(this.tool.getThickness()).toString();
|
199
|
-
|
200
|
-
// Update the list of stroke factories
|
201
|
-
objectTypeSelect.replaceChildren();
|
202
|
-
for (let i = 0; i < this.penTypes.length; i ++) {
|
203
|
-
const penType = this.penTypes[i];
|
204
|
-
const option = document.createElement('option');
|
205
|
-
option.value = i.toString();
|
206
|
-
option.innerText = penType.name;
|
207
|
-
|
208
|
-
objectTypeSelect.appendChild(option);
|
209
|
-
}
|
210
|
-
|
211
|
-
// Update the selected stroke factory.
|
212
|
-
const strokeFactoryIdx = this.getCurrentPenTypeIdx();
|
213
|
-
if (strokeFactoryIdx === -1) {
|
214
|
-
objectTypeSelect.value = '';
|
215
|
-
} else {
|
216
|
-
objectTypeSelect.value = strokeFactoryIdx.toString();
|
217
|
-
}
|
218
|
-
};
|
219
|
-
this.updateInputs();
|
220
|
-
|
221
|
-
container.replaceChildren(colorRow, thicknessRow, objectTypeRow);
|
222
|
-
dropdown.replaceChildren(container);
|
223
|
-
return true;
|
224
|
-
}
|
225
|
-
|
226
|
-
protected onKeyPress(event: KeyPressEvent): boolean {
|
227
|
-
if (!this.isSelected()) {
|
228
|
-
return false;
|
229
|
-
}
|
230
|
-
|
231
|
-
// Map alt+0-9 to different pen types.
|
232
|
-
if (/^[0-9]$/.exec(event.key) && event.ctrlKey) {
|
233
|
-
const penTypeIdx = parseInt(event.key) - 1;
|
234
|
-
if (penTypeIdx >= 0 && penTypeIdx < this.penTypes.length) {
|
235
|
-
this.tool.setStrokeFactory(this.penTypes[penTypeIdx].factory);
|
236
|
-
return true;
|
237
|
-
}
|
238
|
-
}
|
239
|
-
|
240
|
-
return false;
|
241
|
-
}
|
242
|
-
|
243
|
-
public serializeState(): SavedToolbuttonState {
|
244
|
-
return {
|
245
|
-
...super.serializeState(),
|
246
|
-
|
247
|
-
color: this.tool.getColor().toHexString(),
|
248
|
-
thickness: this.tool.getThickness(),
|
249
|
-
strokeFactoryId: this.getCurrentPenType()?.id,
|
250
|
-
};
|
251
|
-
}
|
252
|
-
|
253
|
-
public deserializeFrom(state: SavedToolbuttonState) {
|
254
|
-
super.deserializeFrom(state);
|
255
|
-
|
256
|
-
const verifyPropertyType = (propertyName: string, expectedType: 'string'|'number'|'object') => {
|
257
|
-
const actualType = typeof(state[propertyName]);
|
258
|
-
if (actualType !== expectedType) {
|
259
|
-
throw new Error(
|
260
|
-
`Deserializing property ${propertyName}: Invalid type. Expected ${expectedType},` +
|
261
|
-
` was ${actualType}.`
|
262
|
-
);
|
263
|
-
}
|
264
|
-
};
|
265
|
-
|
266
|
-
if (state.color) {
|
267
|
-
verifyPropertyType('color', 'string');
|
268
|
-
this.tool.setColor(Color4.fromHex(state.color));
|
269
|
-
}
|
270
|
-
|
271
|
-
if (state.thickness) {
|
272
|
-
verifyPropertyType('thickness', 'number');
|
273
|
-
this.tool.setThickness(state.thickness);
|
274
|
-
}
|
275
|
-
|
276
|
-
if (state.strokeFactoryId) {
|
277
|
-
verifyPropertyType('strokeFactoryId', 'string');
|
278
|
-
|
279
|
-
const factoryId: string = state.strokeFactoryId;
|
280
|
-
for (const penType of this.penTypes) {
|
281
|
-
if (factoryId === penType.id) {
|
282
|
-
this.tool.setStrokeFactory(penType.factory);
|
283
|
-
break;
|
284
|
-
}
|
285
|
-
}
|
286
|
-
}
|
287
|
-
}
|
288
|
-
}
|
@@ -1,190 +0,0 @@
|
|
1
|
-
import Color4 from '../../Color4';
|
2
|
-
import { isRestylableComponent } from '../../components/RestylableComponent';
|
3
|
-
import Editor from '../../Editor';
|
4
|
-
import uniteCommands from '../../commands/uniteCommands';
|
5
|
-
import SelectionTool from '../../tools/SelectionTool/SelectionTool';
|
6
|
-
import { EditorEventType, KeyPressEvent } from '../../types';
|
7
|
-
import { ToolbarLocalization } from '../localization';
|
8
|
-
import makeColorInput from '../makeColorInput';
|
9
|
-
import ActionButtonWidget from './ActionButtonWidget';
|
10
|
-
import BaseToolWidget from './BaseToolWidget';
|
11
|
-
import BaseWidget from './BaseWidget';
|
12
|
-
|
13
|
-
class RestyleSelectionWidget extends BaseWidget {
|
14
|
-
private updateFormatData: ()=>void = () => {};
|
15
|
-
|
16
|
-
public constructor(editor: Editor, private selectionTool: SelectionTool, localizationTable?: ToolbarLocalization) {
|
17
|
-
super(editor, 'restyle-selection', localizationTable);
|
18
|
-
|
19
|
-
// Allow showing the dropdown even if this widget isn't selected yet
|
20
|
-
this.container.classList.add('dropdownShowable');
|
21
|
-
|
22
|
-
this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
|
23
|
-
if (toolEvt.kind !== EditorEventType.ToolUpdated) {
|
24
|
-
throw new Error('Invalid event type!');
|
25
|
-
}
|
26
|
-
|
27
|
-
if (toolEvt.tool === this.selectionTool) {
|
28
|
-
this.updateFormatData();
|
29
|
-
}
|
30
|
-
});
|
31
|
-
}
|
32
|
-
|
33
|
-
protected getTitle(): string {
|
34
|
-
return this.localizationTable.reformatSelection;
|
35
|
-
}
|
36
|
-
|
37
|
-
protected createIcon(){
|
38
|
-
return this.editor.icons.makeFormatSelectionIcon();
|
39
|
-
}
|
40
|
-
|
41
|
-
protected handleClick(): void {
|
42
|
-
this.setDropdownVisible(!this.isDropdownVisible());
|
43
|
-
}
|
44
|
-
|
45
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
46
|
-
const container = document.createElement('div');
|
47
|
-
const colorRow = document.createElement('div');
|
48
|
-
const colorLabel = document.createElement('label');
|
49
|
-
const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
|
50
|
-
const selection = this.selectionTool.getSelection();
|
51
|
-
|
52
|
-
if (selection) {
|
53
|
-
const updateStyleCommands = [];
|
54
|
-
|
55
|
-
for (const elem of selection.getSelectedObjects()) {
|
56
|
-
if (isRestylableComponent(elem)) {
|
57
|
-
updateStyleCommands.push(elem.updateStyle({ color }));
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
const unitedCommand = uniteCommands(updateStyleCommands);
|
62
|
-
this.editor.dispatch(unitedCommand);
|
63
|
-
}
|
64
|
-
});
|
65
|
-
|
66
|
-
colorLabel.innerText = this.localizationTable.colorLabel;
|
67
|
-
|
68
|
-
this.updateFormatData = () => {
|
69
|
-
const selection = this.selectionTool.getSelection();
|
70
|
-
if (selection) {
|
71
|
-
colorInput.disabled = false;
|
72
|
-
|
73
|
-
const colors = [];
|
74
|
-
for (const elem of selection.getSelectedObjects()) {
|
75
|
-
if (isRestylableComponent(elem)) {
|
76
|
-
const color = elem.getStyle().color;
|
77
|
-
if (color) {
|
78
|
-
colors.push(color);
|
79
|
-
}
|
80
|
-
}
|
81
|
-
}
|
82
|
-
setColorInputValue(Color4.average(colors));
|
83
|
-
} else {
|
84
|
-
colorInput.disabled = true;
|
85
|
-
}
|
86
|
-
};
|
87
|
-
|
88
|
-
colorRow.replaceChildren(colorLabel, colorInputContainer);
|
89
|
-
container.replaceChildren(colorRow);
|
90
|
-
dropdown.replaceChildren(container);
|
91
|
-
return true;
|
92
|
-
}
|
93
|
-
}
|
94
|
-
|
95
|
-
export default class SelectionToolWidget extends BaseToolWidget {
|
96
|
-
public constructor(
|
97
|
-
editor: Editor, private tool: SelectionTool, localization?: ToolbarLocalization
|
98
|
-
) {
|
99
|
-
super(editor, tool, 'selection-tool-widget', localization);
|
100
|
-
|
101
|
-
const resizeButton = new ActionButtonWidget(
|
102
|
-
editor, 'resize-btn',
|
103
|
-
() => editor.icons.makeResizeViewportIcon(),
|
104
|
-
this.localizationTable.resizeImageToSelection,
|
105
|
-
() => {
|
106
|
-
this.resizeImageToSelection();
|
107
|
-
},
|
108
|
-
localization,
|
109
|
-
);
|
110
|
-
const deleteButton = new ActionButtonWidget(
|
111
|
-
editor, 'delete-btn',
|
112
|
-
() => editor.icons.makeDeleteSelectionIcon(),
|
113
|
-
this.localizationTable.deleteSelection,
|
114
|
-
() => {
|
115
|
-
const selection = this.tool.getSelection();
|
116
|
-
this.editor.dispatch(selection!.deleteSelectedObjects());
|
117
|
-
this.tool.clearSelection();
|
118
|
-
},
|
119
|
-
localization,
|
120
|
-
);
|
121
|
-
const duplicateButton = new ActionButtonWidget(
|
122
|
-
editor, 'duplicate-btn',
|
123
|
-
() => editor.icons.makeDuplicateSelectionIcon(),
|
124
|
-
this.localizationTable.duplicateSelection,
|
125
|
-
async () => {
|
126
|
-
const selection = this.tool.getSelection();
|
127
|
-
this.editor.dispatch(await selection!.duplicateSelectedObjects());
|
128
|
-
},
|
129
|
-
localization,
|
130
|
-
);
|
131
|
-
const restyleButton = new RestyleSelectionWidget(
|
132
|
-
editor,
|
133
|
-
this.tool,
|
134
|
-
localization,
|
135
|
-
);
|
136
|
-
|
137
|
-
this.addSubWidget(resizeButton);
|
138
|
-
this.addSubWidget(deleteButton);
|
139
|
-
this.addSubWidget(duplicateButton);
|
140
|
-
this.addSubWidget(restyleButton);
|
141
|
-
|
142
|
-
const updateDisabled = (disabled: boolean) => {
|
143
|
-
resizeButton.setDisabled(disabled);
|
144
|
-
deleteButton.setDisabled(disabled);
|
145
|
-
duplicateButton.setDisabled(disabled);
|
146
|
-
restyleButton.setDisabled(disabled);
|
147
|
-
};
|
148
|
-
updateDisabled(true);
|
149
|
-
|
150
|
-
// Enable/disable actions based on whether items are selected
|
151
|
-
this.editor.notifier.on(EditorEventType.ToolUpdated, toolEvt => {
|
152
|
-
if (toolEvt.kind !== EditorEventType.ToolUpdated) {
|
153
|
-
throw new Error('Invalid event type!');
|
154
|
-
}
|
155
|
-
|
156
|
-
if (toolEvt.tool === this.tool) {
|
157
|
-
const selection = this.tool.getSelection();
|
158
|
-
const hasSelection = selection && selection.getSelectedItemCount() > 0;
|
159
|
-
|
160
|
-
updateDisabled(!hasSelection);
|
161
|
-
}
|
162
|
-
});
|
163
|
-
}
|
164
|
-
|
165
|
-
private resizeImageToSelection() {
|
166
|
-
const selection = this.tool.getSelection();
|
167
|
-
if (selection) {
|
168
|
-
this.editor.dispatch(this.editor.setImportExportRect(selection.region));
|
169
|
-
}
|
170
|
-
}
|
171
|
-
|
172
|
-
protected onKeyPress(event: KeyPressEvent): boolean {
|
173
|
-
// Resize image to selection:
|
174
|
-
// Other keys are handled directly by the selection tool.
|
175
|
-
if (event.ctrlKey && event.key === 'r') {
|
176
|
-
this.resizeImageToSelection();
|
177
|
-
return true;
|
178
|
-
}
|
179
|
-
|
180
|
-
return false;
|
181
|
-
}
|
182
|
-
|
183
|
-
protected getTitle(): string {
|
184
|
-
return this.localizationTable.select;
|
185
|
-
}
|
186
|
-
|
187
|
-
protected createIcon(): Element {
|
188
|
-
return this.editor.icons.makeSelectionIcon();
|
189
|
-
}
|
190
|
-
}
|
@@ -1,145 +0,0 @@
|
|
1
|
-
import Color4 from '../../Color4';
|
2
|
-
import Editor from '../../Editor';
|
3
|
-
import TextTool from '../../tools/TextTool';
|
4
|
-
import { EditorEventType } from '../../types';
|
5
|
-
import { toolbarCSSPrefix } from '../HTMLToolbar';
|
6
|
-
import { ToolbarLocalization } from '../localization';
|
7
|
-
import makeColorInput from '../makeColorInput';
|
8
|
-
import BaseToolWidget from './BaseToolWidget';
|
9
|
-
import { SavedToolbuttonState } from './BaseWidget';
|
10
|
-
|
11
|
-
export default class TextToolWidget extends BaseToolWidget {
|
12
|
-
private updateDropdownInputs: (()=>void)|null = null;
|
13
|
-
public constructor(editor: Editor, private tool: TextTool, localization?: ToolbarLocalization) {
|
14
|
-
super(editor, tool, 'text-tool-widget', localization);
|
15
|
-
|
16
|
-
editor.notifier.on(EditorEventType.ToolUpdated, evt => {
|
17
|
-
if (evt.kind === EditorEventType.ToolUpdated && evt.tool === tool) {
|
18
|
-
this.updateIcon();
|
19
|
-
this.updateDropdownInputs?.();
|
20
|
-
}
|
21
|
-
});
|
22
|
-
}
|
23
|
-
|
24
|
-
protected getTitle(): string {
|
25
|
-
return this.targetTool.description;
|
26
|
-
}
|
27
|
-
|
28
|
-
protected createIcon(): Element {
|
29
|
-
const textStyle = this.tool.getTextStyle();
|
30
|
-
return this.editor.icons.makeTextIcon(textStyle);
|
31
|
-
}
|
32
|
-
|
33
|
-
private static idCounter: number = 0;
|
34
|
-
protected fillDropdown(dropdown: HTMLElement): boolean {
|
35
|
-
const container = document.createElement('div');
|
36
|
-
container.classList.add(`${toolbarCSSPrefix}spacedList`);
|
37
|
-
const fontRow = document.createElement('div');
|
38
|
-
const colorRow = document.createElement('div');
|
39
|
-
const sizeRow = document.createElement('div');
|
40
|
-
|
41
|
-
const fontInput = document.createElement('select');
|
42
|
-
const fontLabel = document.createElement('label');
|
43
|
-
|
44
|
-
const sizeInput = document.createElement('input');
|
45
|
-
const sizeLabel = document.createElement('label');
|
46
|
-
|
47
|
-
const [ colorInput, colorInputContainer, setColorInputValue ] = makeColorInput(this.editor, color => {
|
48
|
-
this.tool.setColor(color);
|
49
|
-
});
|
50
|
-
const colorLabel = document.createElement('label');
|
51
|
-
|
52
|
-
const fontsInInput = new Set();
|
53
|
-
const addFontToInput = (fontName: string) => {
|
54
|
-
const option = document.createElement('option');
|
55
|
-
option.value = fontName;
|
56
|
-
option.textContent = fontName;
|
57
|
-
fontInput.appendChild(option);
|
58
|
-
fontsInInput.add(fontName);
|
59
|
-
};
|
60
|
-
|
61
|
-
sizeInput.setAttribute('type', 'number');
|
62
|
-
sizeInput.min = '1';
|
63
|
-
sizeInput.max = '128';
|
64
|
-
|
65
|
-
fontLabel.innerText = this.localizationTable.fontLabel;
|
66
|
-
colorLabel.innerText = this.localizationTable.colorLabel;
|
67
|
-
sizeLabel.innerText = this.localizationTable.textSize;
|
68
|
-
|
69
|
-
colorInput.id = `${toolbarCSSPrefix}-text-color-input-${TextToolWidget.idCounter++}`;
|
70
|
-
colorLabel.setAttribute('for', colorInput.id);
|
71
|
-
|
72
|
-
sizeInput.id = `${toolbarCSSPrefix}-text-size-input-${TextToolWidget.idCounter++}`;
|
73
|
-
sizeLabel.setAttribute('for', sizeInput.id);
|
74
|
-
|
75
|
-
addFontToInput('monospace');
|
76
|
-
addFontToInput('serif');
|
77
|
-
addFontToInput('sans-serif');
|
78
|
-
fontInput.id = `${toolbarCSSPrefix}-text-font-input-${TextToolWidget.idCounter++}`;
|
79
|
-
fontLabel.setAttribute('for', fontInput.id);
|
80
|
-
|
81
|
-
fontInput.onchange = () => {
|
82
|
-
this.tool.setFontFamily(fontInput.value);
|
83
|
-
};
|
84
|
-
|
85
|
-
sizeInput.onchange = () => {
|
86
|
-
const size = parseInt(sizeInput.value);
|
87
|
-
if (!isNaN(size) && size > 0) {
|
88
|
-
this.tool.setFontSize(size);
|
89
|
-
}
|
90
|
-
};
|
91
|
-
|
92
|
-
colorRow.appendChild(colorLabel);
|
93
|
-
colorRow.appendChild(colorInputContainer);
|
94
|
-
|
95
|
-
fontRow.appendChild(fontLabel);
|
96
|
-
fontRow.appendChild(fontInput);
|
97
|
-
|
98
|
-
sizeRow.appendChild(sizeLabel);
|
99
|
-
sizeRow.appendChild(sizeInput);
|
100
|
-
|
101
|
-
this.updateDropdownInputs = () => {
|
102
|
-
const style = this.tool.getTextStyle();
|
103
|
-
setColorInputValue(style.renderingStyle.fill);
|
104
|
-
|
105
|
-
if (!fontsInInput.has(style.fontFamily)) {
|
106
|
-
addFontToInput(style.fontFamily);
|
107
|
-
}
|
108
|
-
fontInput.value = style.fontFamily;
|
109
|
-
sizeInput.value = `${style.size}`;
|
110
|
-
};
|
111
|
-
this.updateDropdownInputs();
|
112
|
-
|
113
|
-
container.replaceChildren(colorRow, sizeRow, fontRow);
|
114
|
-
dropdown.appendChild(container);
|
115
|
-
return true;
|
116
|
-
}
|
117
|
-
|
118
|
-
public serializeState(): SavedToolbuttonState {
|
119
|
-
const textStyle = this.tool.getTextStyle();
|
120
|
-
|
121
|
-
return {
|
122
|
-
...super.serializeState(),
|
123
|
-
|
124
|
-
fontFamily: textStyle.fontFamily,
|
125
|
-
textSize: textStyle.size,
|
126
|
-
color: textStyle.renderingStyle.fill.toHexString(),
|
127
|
-
};
|
128
|
-
}
|
129
|
-
|
130
|
-
public deserializeFrom(state: SavedToolbuttonState) {
|
131
|
-
if (state.fontFamily && typeof(state.fontFamily) === 'string') {
|
132
|
-
this.tool.setFontFamily(state.fontFamily);
|
133
|
-
}
|
134
|
-
|
135
|
-
if (state.color && typeof(state.color) === 'string') {
|
136
|
-
this.tool.setColor(Color4.fromHex(state.color));
|
137
|
-
}
|
138
|
-
|
139
|
-
if (state.textSize && typeof(state.textSize) === 'number') {
|
140
|
-
this.tool.setFontSize(state.textSize);
|
141
|
-
}
|
142
|
-
|
143
|
-
super.deserializeFrom(state);
|
144
|
-
}
|
145
|
-
}
|
@@ -1,13 +0,0 @@
|
|
1
|
-
|
2
|
-
export { default as ActionButtonWidget } from './ActionButtonWidget';
|
3
|
-
export { default as BaseToolWidget } from './BaseToolWidget';
|
4
|
-
export { default as BaseWidget } from './BaseWidget';
|
5
|
-
|
6
|
-
export { default as PenToolWidget } from './PenToolWidget';
|
7
|
-
export { default as TextToolWidget } from './TextToolWidget';
|
8
|
-
export { default as HandToolWidget } from './HandToolWidget';
|
9
|
-
export { default as SelectionToolWidget } from './SelectionToolWidget';
|
10
|
-
export { default as EraserToolWidget } from './EraserToolWidget';
|
11
|
-
|
12
|
-
export { default as InsertImageWidget } from './InsertImageWidget';
|
13
|
-
export { default as DocumentPropertiesWidget } from './DocumentPropertiesWidget';
|