@itwin/core-markup 4.0.0-dev.8 → 4.0.0-dev.80

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 (49) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/lib/cjs/Markup.d.ts +323 -310
  3. package/lib/cjs/Markup.d.ts.map +1 -1
  4. package/lib/cjs/Markup.js +451 -420
  5. package/lib/cjs/Markup.js.map +1 -1
  6. package/lib/cjs/MarkupTool.d.ts +38 -38
  7. package/lib/cjs/MarkupTool.js +88 -88
  8. package/lib/cjs/MarkupTool.js.map +1 -1
  9. package/lib/cjs/RedlineTool.d.ts +145 -145
  10. package/lib/cjs/RedlineTool.d.ts.map +1 -1
  11. package/lib/cjs/RedlineTool.js +498 -512
  12. package/lib/cjs/RedlineTool.js.map +1 -1
  13. package/lib/cjs/SelectTool.d.ts +126 -126
  14. package/lib/cjs/SelectTool.js +741 -741
  15. package/lib/cjs/SelectTool.js.map +1 -1
  16. package/lib/cjs/SvgJsExt.d.ts +85 -85
  17. package/lib/cjs/SvgJsExt.js +185 -185
  18. package/lib/cjs/TextEdit.d.ts +43 -43
  19. package/lib/cjs/TextEdit.js +196 -196
  20. package/lib/cjs/TextEdit.js.map +1 -1
  21. package/lib/cjs/Undo.d.ts +46 -46
  22. package/lib/cjs/Undo.js +168 -168
  23. package/lib/cjs/core-markup.d.ts +18 -18
  24. package/lib/cjs/core-markup.js +38 -34
  25. package/lib/cjs/core-markup.js.map +1 -1
  26. package/lib/esm/Markup.d.ts +323 -310
  27. package/lib/esm/Markup.d.ts.map +1 -1
  28. package/lib/esm/Markup.js +447 -415
  29. package/lib/esm/Markup.js.map +1 -1
  30. package/lib/esm/MarkupTool.d.ts +38 -38
  31. package/lib/esm/MarkupTool.js +85 -84
  32. package/lib/esm/MarkupTool.js.map +1 -1
  33. package/lib/esm/RedlineTool.d.ts +145 -145
  34. package/lib/esm/RedlineTool.d.ts.map +1 -1
  35. package/lib/esm/RedlineTool.js +494 -498
  36. package/lib/esm/RedlineTool.js.map +1 -1
  37. package/lib/esm/SelectTool.d.ts +126 -126
  38. package/lib/esm/SelectTool.js +735 -734
  39. package/lib/esm/SelectTool.js.map +1 -1
  40. package/lib/esm/SvgJsExt.d.ts +85 -85
  41. package/lib/esm/SvgJsExt.js +180 -180
  42. package/lib/esm/TextEdit.d.ts +43 -43
  43. package/lib/esm/TextEdit.js +193 -191
  44. package/lib/esm/TextEdit.js.map +1 -1
  45. package/lib/esm/Undo.d.ts +46 -46
  46. package/lib/esm/Undo.js +164 -164
  47. package/lib/esm/core-markup.d.ts +18 -18
  48. package/lib/esm/core-markup.js +22 -22
  49. package/package.json +19 -19
@@ -1,192 +1,194 @@
1
- /*---------------------------------------------------------------------------------------------
2
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
- * See LICENSE.md in the project root for license terms and full copyright notice.
4
- *--------------------------------------------------------------------------------------------*/
5
- /** @packageDocumentation
6
- * @module MarkupTools
7
- */
8
- import { CoreTools, EventHandled, IModelApp, InputSource, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, } from "@itwin/core-frontend";
9
- import { G, Text as MarkupText } from "@svgdotjs/svg.js";
10
- import { MarkupApp } from "./Markup";
11
- import { MarkupTool } from "./MarkupTool";
12
- import { RedlineTool } from "./RedlineTool";
13
- // cspell:ignore rbox
14
- /** Tool to place new text notes on a Markup.
15
- * @public
16
- */
17
- export class PlaceTextTool extends RedlineTool {
18
- constructor() {
19
- super(...arguments);
20
- this._nRequiredPoints = 1;
21
- this._minPoints = 0;
22
- }
23
- async onPostInstall() {
24
- this._value = MarkupApp.props.text.startValue; // so applications can put a default string (e.g. user's initials) in the note. Can be empty
25
- return super.onPostInstall();
26
- }
27
- showPrompt() { this.provideToolAssistance(`${MarkupTool.toolKey}Text.Place.Prompts.FirstPoint`, true); }
28
- async createMarkup(svg, ev, isDynamics) {
29
- if (isDynamics && InputSource.Touch === ev.inputSource)
30
- return;
31
- const start = MarkupApp.convertVpToVb(ev.viewPoint); // starting point in viewbox coordinates
32
- const text = new MarkupText().plain(this._value); // create a plain text element
33
- svg.put(text); // add it to the supplied container
34
- this.setCurrentTextStyle(text); // apply active text style
35
- text.translate(start.x, start.y); // and position it relative to the cursor
36
- if (isDynamics) {
37
- svg.add(text.getOutline().attr(MarkupApp.props.text.edit.textBox).addClass(MarkupApp.textOutlineClass)); // in dynamics, draw the box around the text
38
- }
39
- else {
40
- await new EditTextTool(text, true).run(); // text is now positioned, open text editor
41
- }
42
- }
43
- async onResetButtonUp(_ev) {
44
- await this.exitTool();
45
- return EventHandled.Yes;
46
- }
47
- }
48
- PlaceTextTool.toolId = "Markup.Text.Place";
49
- PlaceTextTool.iconSpec = "icon-text-medium";
50
- /** Tool for editing text. Started automatically by the place text tool and by clicking on text from the SelectTool
51
- * @public
52
- */
53
- export class EditTextTool extends MarkupTool {
54
- constructor(text, _fromPlaceTool = false) {
55
- super();
56
- this.text = text;
57
- this._fromPlaceTool = _fromPlaceTool;
58
- }
59
- showPrompt() {
60
- const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Text.Edit.Prompts.FirstPoint`));
61
- const mouseInstructions = [];
62
- const touchInstructions = [];
63
- const acceptMsg = CoreTools.translate("ElementSet.Inputs.Accept");
64
- const rejectMsg = CoreTools.translate("ElementSet.Inputs.Exit");
65
- touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, acceptMsg, false, ToolAssistanceInputMethod.Touch));
66
- mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse));
67
- touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rejectMsg, false, ToolAssistanceInputMethod.Touch));
68
- mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rejectMsg, false, ToolAssistanceInputMethod.Mouse));
69
- const sections = [];
70
- sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel));
71
- sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel));
72
- const instructions = ToolAssistance.createInstructions(mainInstruction, sections);
73
- IModelApp.notifications.setToolAssistance(instructions);
74
- }
75
- /** Open the text editor */
76
- startEditor() {
77
- let text = this.text;
78
- if (text === undefined)
79
- return;
80
- if (text instanceof G) {
81
- this.boxed = text;
82
- text = text.children()[1];
83
- if (!(text instanceof MarkupText))
84
- return;
85
- this.text = text;
86
- }
87
- const markupDiv = this.markup.markupDiv;
88
- const editDiv = this.editDiv = document.createElement("div"); // create a new DIV to hold the text editor
89
- const editProps = MarkupApp.props.text.edit;
90
- let style = editDiv.style;
91
- style.backgroundColor = editProps.background;
92
- style.top = style.left = "0";
93
- style.right = style.bottom = "100%";
94
- markupDiv.appendChild(editDiv); // add textEditor div to markup div
95
- const divRect = markupDiv.getBoundingClientRect();
96
- const outline = text.getOutline(); // use the outline rather than the text in case it's blank.
97
- text.after(outline); // we have to add it to the DOM or the rbox call doesn't work.
98
- const rbox = outline.rbox();
99
- const bbox = outline.bbox();
100
- outline.remove(); // take it out again.
101
- const editor = this.editor = document.createElement("textarea");
102
- editDiv.appendChild(editor);
103
- editor.className = MarkupApp.textEditorClass;
104
- editor.contentEditable = "true";
105
- editor.spellcheck = true;
106
- editor.wrap = "off";
107
- // so we don't send these events to the ToolAdmin and process them by tools. We want default handling
108
- const mouseListener = (ev) => (ev.stopPropagation(), true);
109
- editor.onselectstart = editor.oncontextmenu = editor.onmousedown = editor.onmouseup = mouseListener; // enable default handling for these events
110
- // Tab, Escape, ctrl-enter, or shift-enter all end the editor
111
- editor.onkeydown = async (ev) => {
112
- if (ev.key === "Tab" || ev.key === "Escape" || (ev.key === "Enter" && (ev.shiftKey || ev.ctrlKey)))
113
- this.exitTool(); // eslint-disable-line @typescript-eslint/no-floating-promises
114
- ev.stopPropagation();
115
- };
116
- const textElStyle = window.getComputedStyle(text.node);
117
- style = editor.style;
118
- style.pointerEvents = "auto";
119
- style.position = "absolute";
120
- style.top = `${(rbox.cy - (bbox.h / 2)) - divRect.top}px`; // put the editor over the middle of the text element
121
- style.left = `${(rbox.cx - (bbox.w / 2)) - divRect.left}px`;
122
- style.height = editProps.size.height;
123
- style.width = editProps.size.width;
124
- style.resize = "both";
125
- style.fontFamily = textElStyle.fontFamily; // set the font family and anchor to the same as the text element
126
- style.textAnchor = textElStyle.textAnchor;
127
- style.fontSize = editProps.fontSize; // from app.props
128
- const parentZ = parseInt(window.getComputedStyle(markupDiv).zIndex || "0", 10);
129
- style.zIndex = (parentZ + 200).toString();
130
- editor.innerHTML = text.getMarkup(); // start with existing text
131
- this.editor.focus(); // give the editor focus
132
- // if we're started from the place text tool, select the entire current value, otherwise place the cursor at the end.
133
- this.editor.setSelectionRange(this._fromPlaceTool ? 0 : editor.value.length, editor.value.length);
134
- }
135
- /** Called when EditText exits, saves the edited value into the text element */
136
- async onCleanup() {
137
- if (!this.editDiv)
138
- return;
139
- const text = this.text;
140
- const original = this.boxed ? this.boxed : text;
141
- const undo = this.markup.undo;
142
- undo.performOperation(this.keyin, () => {
143
- const newVal = this.editor.value;
144
- if (newVal.trim() === "") { // if the result of the editing is blank, just delete the text element
145
- if (!this._fromPlaceTool)
146
- undo.onDelete(original);
147
- original.remove(); // must do this *after* we call undo.onDelete
148
- return;
149
- }
150
- let newText = text.clone();
151
- const fontSize = text.getFontSize();
152
- newText.createMarkup(newVal, fontSize);
153
- if (this.boxed) {
154
- newText = this.createBoxedText(original.parent(), newText);
155
- newText.matrix(original.matrix());
156
- }
157
- original.replace(newText);
158
- if (this._fromPlaceTool)
159
- undo.onAdded(newText);
160
- else
161
- undo.onModified(newText, original);
162
- });
163
- const editSize = MarkupApp.props.text.edit.size;
164
- const style = this.editor.style;
165
- editSize.height = style.height;
166
- editSize.width = style.width;
167
- this.editDiv.remove();
168
- this.editDiv = undefined;
169
- this.editor = undefined;
170
- }
171
- async onInstall() {
172
- if (!await super.onInstall())
173
- return false;
174
- this.startEditor();
175
- return true;
176
- }
177
- async onResetButtonUp(_ev) {
178
- await this.exitTool();
179
- return EventHandled.Yes;
180
- }
181
- async onDataButtonUp(_ev) {
182
- await this.exitTool();
183
- return EventHandled.Yes;
184
- }
185
- async onMouseStartDrag(_ev) {
186
- await this.exitTool();
187
- return EventHandled.Yes;
188
- }
189
- }
190
- EditTextTool.toolId = "Markup.Text.Edit";
191
- EditTextTool.iconSpec = "icon-text-medium";
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ /** @packageDocumentation
6
+ * @module MarkupTools
7
+ */
8
+ import { CoreTools, EventHandled, IModelApp, InputSource, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, } from "@itwin/core-frontend";
9
+ import { G, Text as MarkupText } from "@svgdotjs/svg.js";
10
+ import { MarkupApp } from "./Markup";
11
+ import { MarkupTool } from "./MarkupTool";
12
+ import { RedlineTool } from "./RedlineTool";
13
+ // cspell:ignore rbox
14
+ /** Tool to place new text notes on a Markup.
15
+ * @public
16
+ */
17
+ class PlaceTextTool extends RedlineTool {
18
+ constructor() {
19
+ super(...arguments);
20
+ this._nRequiredPoints = 1;
21
+ this._minPoints = 0;
22
+ }
23
+ async onPostInstall() {
24
+ this._value = MarkupApp.props.text.startValue; // so applications can put a default string (e.g. user's initials) in the note. Can be empty
25
+ return super.onPostInstall();
26
+ }
27
+ showPrompt() { this.provideToolAssistance(`${MarkupTool.toolKey}Text.Place.Prompts.FirstPoint`, true); }
28
+ async createMarkup(svg, ev, isDynamics) {
29
+ if (isDynamics && InputSource.Touch === ev.inputSource)
30
+ return;
31
+ const start = MarkupApp.convertVpToVb(ev.viewPoint); // starting point in viewbox coordinates
32
+ const text = new MarkupText().plain(this._value); // create a plain text element
33
+ svg.put(text); // add it to the supplied container
34
+ this.setCurrentTextStyle(text); // apply active text style
35
+ text.translate(start.x, start.y); // and position it relative to the cursor
36
+ if (isDynamics) {
37
+ svg.add(text.getOutline().attr(MarkupApp.props.text.edit.textBox).addClass(MarkupApp.textOutlineClass)); // in dynamics, draw the box around the text
38
+ }
39
+ else {
40
+ await new EditTextTool(text, true).run(); // text is now positioned, open text editor
41
+ }
42
+ }
43
+ async onResetButtonUp(_ev) {
44
+ await this.exitTool();
45
+ return EventHandled.Yes;
46
+ }
47
+ }
48
+ PlaceTextTool.toolId = "Markup.Text.Place";
49
+ PlaceTextTool.iconSpec = "icon-text-medium";
50
+ export { PlaceTextTool };
51
+ /** Tool for editing text. Started automatically by the place text tool and by clicking on text from the SelectTool
52
+ * @public
53
+ */
54
+ class EditTextTool extends MarkupTool {
55
+ constructor(text, _fromPlaceTool = false) {
56
+ super();
57
+ this.text = text;
58
+ this._fromPlaceTool = _fromPlaceTool;
59
+ }
60
+ showPrompt() {
61
+ const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Text.Edit.Prompts.FirstPoint`));
62
+ const mouseInstructions = [];
63
+ const touchInstructions = [];
64
+ const acceptMsg = CoreTools.translate("ElementSet.Inputs.Accept");
65
+ const rejectMsg = CoreTools.translate("ElementSet.Inputs.Exit");
66
+ touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, acceptMsg, false, ToolAssistanceInputMethod.Touch));
67
+ mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse));
68
+ touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rejectMsg, false, ToolAssistanceInputMethod.Touch));
69
+ mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rejectMsg, false, ToolAssistanceInputMethod.Mouse));
70
+ const sections = [];
71
+ sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel));
72
+ sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel));
73
+ const instructions = ToolAssistance.createInstructions(mainInstruction, sections);
74
+ IModelApp.notifications.setToolAssistance(instructions);
75
+ }
76
+ /** Open the text editor */
77
+ startEditor() {
78
+ let text = this.text;
79
+ if (text === undefined)
80
+ return;
81
+ if (text instanceof G) {
82
+ this.boxed = text;
83
+ text = text.children()[1];
84
+ if (!(text instanceof MarkupText))
85
+ return;
86
+ this.text = text;
87
+ }
88
+ const markupDiv = this.markup.markupDiv;
89
+ const editDiv = this.editDiv = document.createElement("div"); // create a new DIV to hold the text editor
90
+ const editProps = MarkupApp.props.text.edit;
91
+ let style = editDiv.style;
92
+ style.backgroundColor = editProps.background;
93
+ style.top = style.left = "0";
94
+ style.right = style.bottom = "100%";
95
+ markupDiv.appendChild(editDiv); // add textEditor div to markup div
96
+ const divRect = markupDiv.getBoundingClientRect();
97
+ const outline = text.getOutline(); // use the outline rather than the text in case it's blank.
98
+ text.after(outline); // we have to add it to the DOM or the rbox call doesn't work.
99
+ const rbox = outline.rbox();
100
+ const bbox = outline.bbox();
101
+ outline.remove(); // take it out again.
102
+ const editor = this.editor = document.createElement("textarea");
103
+ editDiv.appendChild(editor);
104
+ editor.className = MarkupApp.textEditorClass;
105
+ editor.contentEditable = "true";
106
+ editor.spellcheck = true;
107
+ editor.wrap = "off";
108
+ // so we don't send these events to the ToolAdmin and process them by tools. We want default handling
109
+ const mouseListener = (ev) => (ev.stopPropagation(), true);
110
+ editor.onselectstart = editor.oncontextmenu = editor.onmousedown = editor.onmouseup = mouseListener; // enable default handling for these events
111
+ // Tab, Escape, ctrl-enter, or shift-enter all end the editor
112
+ editor.onkeydown = async (ev) => {
113
+ if (ev.key === "Tab" || ev.key === "Escape" || (ev.key === "Enter" && (ev.shiftKey || ev.ctrlKey)))
114
+ this.exitTool(); // eslint-disable-line @typescript-eslint/no-floating-promises
115
+ ev.stopPropagation();
116
+ };
117
+ const textElStyle = window.getComputedStyle(text.node);
118
+ style = editor.style;
119
+ style.pointerEvents = "auto";
120
+ style.position = "absolute";
121
+ style.top = `${(rbox.cy - (bbox.h / 2)) - divRect.top}px`; // put the editor over the middle of the text element
122
+ style.left = `${(rbox.cx - (bbox.w / 2)) - divRect.left}px`;
123
+ style.height = editProps.size.height;
124
+ style.width = editProps.size.width;
125
+ style.resize = "both";
126
+ style.fontFamily = textElStyle.fontFamily; // set the font family and anchor to the same as the text element
127
+ style.textAnchor = textElStyle.textAnchor;
128
+ style.fontSize = editProps.fontSize; // from app.props
129
+ const parentZ = parseInt(window.getComputedStyle(markupDiv).zIndex || "0", 10);
130
+ style.zIndex = (parentZ + 200).toString();
131
+ editor.innerHTML = text.getMarkup(); // start with existing text
132
+ this.editor.focus(); // give the editor focus
133
+ // if we're started from the place text tool, select the entire current value, otherwise place the cursor at the end.
134
+ this.editor.setSelectionRange(this._fromPlaceTool ? 0 : editor.value.length, editor.value.length);
135
+ }
136
+ /** Called when EditText exits, saves the edited value into the text element */
137
+ async onCleanup() {
138
+ if (!this.editDiv)
139
+ return;
140
+ const text = this.text;
141
+ const original = this.boxed ? this.boxed : text;
142
+ const undo = this.markup.undo;
143
+ undo.performOperation(this.keyin, () => {
144
+ const newVal = this.editor.value;
145
+ if (newVal.trim() === "") { // if the result of the editing is blank, just delete the text element
146
+ if (!this._fromPlaceTool)
147
+ undo.onDelete(original);
148
+ original.remove(); // must do this *after* we call undo.onDelete
149
+ return;
150
+ }
151
+ let newText = text.clone();
152
+ const fontSize = text.getFontSize();
153
+ newText.createMarkup(newVal, fontSize);
154
+ if (this.boxed) {
155
+ newText = this.createBoxedText(original.parent(), newText);
156
+ newText.matrix(original.matrix());
157
+ }
158
+ original.replace(newText);
159
+ if (this._fromPlaceTool)
160
+ undo.onAdded(newText);
161
+ else
162
+ undo.onModified(newText, original);
163
+ });
164
+ const editSize = MarkupApp.props.text.edit.size;
165
+ const style = this.editor.style;
166
+ editSize.height = style.height;
167
+ editSize.width = style.width;
168
+ this.editDiv.remove();
169
+ this.editDiv = undefined;
170
+ this.editor = undefined;
171
+ }
172
+ async onInstall() {
173
+ if (!await super.onInstall())
174
+ return false;
175
+ this.startEditor();
176
+ return true;
177
+ }
178
+ async onResetButtonUp(_ev) {
179
+ await this.exitTool();
180
+ return EventHandled.Yes;
181
+ }
182
+ async onDataButtonUp(_ev) {
183
+ await this.exitTool();
184
+ return EventHandled.Yes;
185
+ }
186
+ async onMouseStartDrag(_ev) {
187
+ await this.exitTool();
188
+ return EventHandled.Yes;
189
+ }
190
+ }
191
+ EditTextTool.toolId = "Markup.Text.Edit";
192
+ EditTextTool.iconSpec = "icon-text-medium";
193
+ export { EditTextTool };
192
194
  //# sourceMappingURL=TextEdit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextEdit.js","sourceRoot":"","sources":["../../src/TextEdit.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module MarkupTools\r\n */\r\n\r\nimport {\r\n BeButtonEvent, CoreTools, EventHandled, IModelApp, InputSource, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod,\r\n ToolAssistanceInstruction, ToolAssistanceSection,\r\n} from \"@itwin/core-frontend\";\r\nimport { G, Text as MarkupText } from \"@svgdotjs/svg.js\";\r\nimport { MarkupApp } from \"./Markup\";\r\nimport { MarkupTool } from \"./MarkupTool\";\r\nimport { RedlineTool } from \"./RedlineTool\";\r\n\r\n// cspell:ignore rbox\r\n\r\n/** Tool to place new text notes on a Markup.\r\n * @public\r\n */\r\nexport class PlaceTextTool extends RedlineTool {\r\n public static override toolId = \"Markup.Text.Place\";\r\n public static override iconSpec = \"icon-text-medium\";\r\n protected override _nRequiredPoints = 1;\r\n protected override _minPoints = 0;\r\n protected _value!: string;\r\n\r\n public override async onPostInstall() {\r\n this._value = MarkupApp.props.text.startValue; // so applications can put a default string (e.g. user's initials) in the note. Can be empty\r\n return super.onPostInstall();\r\n }\r\n\r\n protected override showPrompt(): void { this.provideToolAssistance(`${MarkupTool.toolKey}Text.Place.Prompts.FirstPoint`, true); }\r\n\r\n protected override async createMarkup(svg: G, ev: BeButtonEvent, isDynamics: boolean): Promise<void> {\r\n if (isDynamics && InputSource.Touch === ev.inputSource)\r\n return;\r\n const start = MarkupApp.convertVpToVb(ev.viewPoint); // starting point in viewbox coordinates\r\n const text = new MarkupText().plain(this._value); // create a plain text element\r\n svg.put(text); // add it to the supplied container\r\n this.setCurrentTextStyle(text); // apply active text style\r\n text.translate(start.x, start.y); // and position it relative to the cursor\r\n if (isDynamics) {\r\n svg.add(text.getOutline().attr(MarkupApp.props.text.edit.textBox).addClass(MarkupApp.textOutlineClass)); // in dynamics, draw the box around the text\r\n } else {\r\n await new EditTextTool(text, true).run(); // text is now positioned, open text editor\r\n }\r\n }\r\n public override async onResetButtonUp(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n}\r\n\r\n/** Tool for editing text. Started automatically by the place text tool and by clicking on text from the SelectTool\r\n * @public\r\n */\r\nexport class EditTextTool extends MarkupTool {\r\n public static override toolId = \"Markup.Text.Edit\";\r\n public static override iconSpec = \"icon-text-medium\";\r\n public editor?: HTMLTextAreaElement;\r\n public editDiv?: HTMLDivElement;\r\n public boxed?: G;\r\n constructor(public text?: MarkupText | G, private _fromPlaceTool = false) { super(); }\r\n\r\n protected override showPrompt(): void {\r\n const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Text.Edit.Prompts.FirstPoint`));\r\n const mouseInstructions: ToolAssistanceInstruction[] = [];\r\n const touchInstructions: ToolAssistanceInstruction[] = [];\r\n\r\n const acceptMsg = CoreTools.translate(\"ElementSet.Inputs.Accept\");\r\n const rejectMsg = CoreTools.translate(\"ElementSet.Inputs.Exit\");\r\n touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, acceptMsg, false, ToolAssistanceInputMethod.Touch));\r\n mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse));\r\n touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rejectMsg, false, ToolAssistanceInputMethod.Touch));\r\n mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rejectMsg, false, ToolAssistanceInputMethod.Mouse));\r\n\r\n const sections: ToolAssistanceSection[] = [];\r\n sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel));\r\n sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel));\r\n\r\n const instructions = ToolAssistance.createInstructions(mainInstruction, sections);\r\n IModelApp.notifications.setToolAssistance(instructions);\r\n }\r\n\r\n /** Open the text editor */\r\n public startEditor() {\r\n let text = this.text;\r\n if (text === undefined)\r\n return;\r\n\r\n if (text instanceof G) {\r\n this.boxed = text;\r\n text = text.children()[1] as MarkupText;\r\n if (!(text instanceof MarkupText))\r\n return;\r\n this.text = text;\r\n }\r\n const markupDiv = this.markup.markupDiv;\r\n const editDiv = this.editDiv = document.createElement(\"div\"); // create a new DIV to hold the text editor\r\n const editProps = MarkupApp.props.text.edit;\r\n let style = editDiv.style;\r\n style.backgroundColor = editProps.background;\r\n style.top = style.left = \"0\";\r\n style.right = style.bottom = \"100%\";\r\n\r\n markupDiv.appendChild(editDiv); // add textEditor div to markup div\r\n\r\n const divRect = markupDiv.getBoundingClientRect();\r\n const outline = text.getOutline(); // use the outline rather than the text in case it's blank.\r\n text.after(outline); // we have to add it to the DOM or the rbox call doesn't work.\r\n const rbox = outline.rbox();\r\n const bbox = outline.bbox();\r\n outline.remove(); // take it out again.\r\n const editor = this.editor = document.createElement(\"textarea\");\r\n editDiv.appendChild(editor);\r\n editor.className = MarkupApp.textEditorClass;\r\n editor.contentEditable = \"true\";\r\n editor.spellcheck = true;\r\n editor.wrap = \"off\";\r\n // so we don't send these events to the ToolAdmin and process them by tools. We want default handling\r\n const mouseListener = (ev: Event) => (ev.stopPropagation(), true);\r\n (editor as any).onselectstart = editor.oncontextmenu = editor.onmousedown = editor.onmouseup = mouseListener; // enable default handling for these events\r\n\r\n // Tab, Escape, ctrl-enter, or shift-enter all end the editor\r\n editor.onkeydown = async (ev: KeyboardEvent) => {\r\n if (ev.key === \"Tab\" || ev.key === \"Escape\" || (ev.key === \"Enter\" && (ev.shiftKey || ev.ctrlKey)))\r\n this.exitTool(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n ev.stopPropagation();\r\n\r\n };\r\n const textElStyle = window.getComputedStyle(text.node);\r\n\r\n style = editor.style;\r\n style.pointerEvents = \"auto\";\r\n style.position = \"absolute\";\r\n style.top = `${(rbox.cy - (bbox.h / 2)) - divRect.top}px`; // put the editor over the middle of the text element\r\n style.left = `${(rbox.cx - (bbox.w / 2)) - divRect.left}px`;\r\n style.height = editProps.size.height;\r\n style.width = editProps.size.width;\r\n style.resize = \"both\";\r\n style.fontFamily = textElStyle.fontFamily; // set the font family and anchor to the same as the text element\r\n style.textAnchor = textElStyle.textAnchor;\r\n style.fontSize = editProps.fontSize; // from app.props\r\n\r\n const parentZ = parseInt(window.getComputedStyle(markupDiv).zIndex || \"0\", 10);\r\n style.zIndex = (parentZ + 200).toString();\r\n\r\n editor.innerHTML = text.getMarkup(); // start with existing text\r\n this.editor.focus(); // give the editor focus\r\n\r\n // if we're started from the place text tool, select the entire current value, otherwise place the cursor at the end.\r\n this.editor.setSelectionRange(this._fromPlaceTool ? 0 : editor.value.length, editor.value.length);\r\n }\r\n\r\n /** Called when EditText exits, saves the edited value into the text element */\r\n public override async onCleanup() {\r\n if (!this.editDiv)\r\n return;\r\n\r\n const text = this.text! as MarkupText;\r\n const original = this.boxed ? this.boxed : text;\r\n const undo = this.markup.undo;\r\n undo.performOperation(this.keyin, () => {\r\n const newVal = this.editor!.value;\r\n if (newVal.trim() === \"\") { // if the result of the editing is blank, just delete the text element\r\n if (!this._fromPlaceTool)\r\n undo.onDelete(original);\r\n original.remove(); // must do this *after* we call undo.onDelete\r\n return;\r\n }\r\n\r\n let newText: G | MarkupText = text.clone();\r\n const fontSize = text.getFontSize();\r\n newText.createMarkup(newVal, fontSize);\r\n if (this.boxed) {\r\n newText = this.createBoxedText((original as G).parent() as G, newText);\r\n newText.matrix(original.matrix());\r\n }\r\n original.replace(newText);\r\n if (this._fromPlaceTool)\r\n undo.onAdded(newText);\r\n else\r\n undo.onModified(newText, original);\r\n });\r\n\r\n const editSize = MarkupApp.props.text.edit.size;\r\n const style = this.editor!.style;\r\n editSize.height = style.height;\r\n editSize.width = style.width;\r\n this.editDiv.remove();\r\n this.editDiv = undefined;\r\n this.editor = undefined;\r\n }\r\n\r\n public override async onInstall() {\r\n if (!await super.onInstall())\r\n return false;\r\n this.startEditor();\r\n return true;\r\n }\r\n\r\n public override async onResetButtonUp(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n\r\n public override async onDataButtonUp(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n\r\n public override async onMouseStartDrag(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"TextEdit.js","sourceRoot":"","sources":["../../src/TextEdit.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module MarkupTools\r\n */\r\n\r\nimport {\r\n BeButtonEvent, CoreTools, EventHandled, IModelApp, InputSource, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod,\r\n ToolAssistanceInstruction, ToolAssistanceSection,\r\n} from \"@itwin/core-frontend\";\r\nimport { G, Text as MarkupText } from \"@svgdotjs/svg.js\";\r\nimport { MarkupApp } from \"./Markup\";\r\nimport { MarkupTool } from \"./MarkupTool\";\r\nimport { RedlineTool } from \"./RedlineTool\";\r\n\r\n// cspell:ignore rbox\r\n\r\n/** Tool to place new text notes on a Markup.\r\n * @public\r\n */\r\nexport class PlaceTextTool extends RedlineTool {\r\n public static override toolId = \"Markup.Text.Place\";\r\n public static override iconSpec = \"icon-text-medium\";\r\n protected override _nRequiredPoints = 1;\r\n protected override _minPoints = 0;\r\n protected _value!: string;\r\n\r\n public override async onPostInstall() {\r\n this._value = MarkupApp.props.text.startValue; // so applications can put a default string (e.g. user's initials) in the note. Can be empty\r\n return super.onPostInstall();\r\n }\r\n\r\n protected override showPrompt(): void { this.provideToolAssistance(`${MarkupTool.toolKey}Text.Place.Prompts.FirstPoint`, true); }\r\n\r\n protected override async createMarkup(svg: G, ev: BeButtonEvent, isDynamics: boolean): Promise<void> {\r\n if (isDynamics && InputSource.Touch === ev.inputSource)\r\n return;\r\n const start = MarkupApp.convertVpToVb(ev.viewPoint); // starting point in viewbox coordinates\r\n const text = new MarkupText().plain(this._value); // create a plain text element\r\n svg.put(text); // add it to the supplied container\r\n this.setCurrentTextStyle(text); // apply active text style\r\n text.translate(start.x, start.y); // and position it relative to the cursor\r\n if (isDynamics) {\r\n svg.add(text.getOutline().attr(MarkupApp.props.text.edit.textBox).addClass(MarkupApp.textOutlineClass)); // in dynamics, draw the box around the text\r\n } else {\r\n await new EditTextTool(text, true).run(); // text is now positioned, open text editor\r\n }\r\n }\r\n public override async onResetButtonUp(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n}\r\n\r\n/** Tool for editing text. Started automatically by the place text tool and by clicking on text from the SelectTool\r\n * @public\r\n */\r\nexport class EditTextTool extends MarkupTool {\r\n public static override toolId = \"Markup.Text.Edit\";\r\n public static override iconSpec = \"icon-text-medium\";\r\n public editor?: HTMLTextAreaElement;\r\n public editDiv?: HTMLDivElement;\r\n public boxed?: G;\r\n constructor(public text?: MarkupText | G, private _fromPlaceTool = false) { super(); }\r\n\r\n protected override showPrompt(): void {\r\n const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Text.Edit.Prompts.FirstPoint`));\r\n const mouseInstructions: ToolAssistanceInstruction[] = [];\r\n const touchInstructions: ToolAssistanceInstruction[] = [];\r\n\r\n const acceptMsg = CoreTools.translate(\"ElementSet.Inputs.Accept\");\r\n const rejectMsg = CoreTools.translate(\"ElementSet.Inputs.Exit\");\r\n touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, acceptMsg, false, ToolAssistanceInputMethod.Touch));\r\n mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse));\r\n touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rejectMsg, false, ToolAssistanceInputMethod.Touch));\r\n mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rejectMsg, false, ToolAssistanceInputMethod.Mouse));\r\n\r\n const sections: ToolAssistanceSection[] = [];\r\n sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel));\r\n sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel));\r\n\r\n const instructions = ToolAssistance.createInstructions(mainInstruction, sections);\r\n IModelApp.notifications.setToolAssistance(instructions);\r\n }\r\n\r\n /** Open the text editor */\r\n public startEditor() {\r\n let text = this.text;\r\n if (text === undefined)\r\n return;\r\n\r\n if (text instanceof G) {\r\n this.boxed = text;\r\n text = text.children()[1] as MarkupText;\r\n if (!(text instanceof MarkupText))\r\n return;\r\n this.text = text;\r\n }\r\n const markupDiv = this.markup.markupDiv;\r\n const editDiv = this.editDiv = document.createElement(\"div\"); // create a new DIV to hold the text editor\r\n const editProps = MarkupApp.props.text.edit;\r\n let style = editDiv.style;\r\n style.backgroundColor = editProps.background;\r\n style.top = style.left = \"0\";\r\n style.right = style.bottom = \"100%\";\r\n\r\n markupDiv.appendChild(editDiv); // add textEditor div to markup div\r\n\r\n const divRect = markupDiv.getBoundingClientRect();\r\n const outline = text.getOutline(); // use the outline rather than the text in case it's blank.\r\n text.after(outline); // we have to add it to the DOM or the rbox call doesn't work.\r\n const rbox = outline.rbox();\r\n const bbox = outline.bbox();\r\n outline.remove(); // take it out again.\r\n const editor = this.editor = document.createElement(\"textarea\");\r\n editDiv.appendChild(editor);\r\n editor.className = MarkupApp.textEditorClass;\r\n editor.contentEditable = \"true\";\r\n editor.spellcheck = true;\r\n editor.wrap = \"off\";\r\n // so we don't send these events to the ToolAdmin and process them by tools. We want default handling\r\n const mouseListener = (ev: Event) => (ev.stopPropagation(), true);\r\n (editor as any).onselectstart = editor.oncontextmenu = editor.onmousedown = editor.onmouseup = mouseListener; // enable default handling for these events\r\n\r\n // Tab, Escape, ctrl-enter, or shift-enter all end the editor\r\n editor.onkeydown = async (ev: KeyboardEvent) => {\r\n if (ev.key === \"Tab\" || ev.key === \"Escape\" || (ev.key === \"Enter\" && (ev.shiftKey || ev.ctrlKey)))\r\n this.exitTool(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n ev.stopPropagation();\r\n\r\n };\r\n const textElStyle = window.getComputedStyle(text.node);\r\n\r\n style = editor.style;\r\n style.pointerEvents = \"auto\";\r\n style.position = \"absolute\";\r\n style.top = `${(rbox.cy - (bbox.h / 2)) - divRect.top}px`; // put the editor over the middle of the text element\r\n style.left = `${(rbox.cx - (bbox.w / 2)) - divRect.left}px`;\r\n style.height = editProps.size.height;\r\n style.width = editProps.size.width;\r\n style.resize = \"both\";\r\n style.fontFamily = textElStyle.fontFamily; // set the font family and anchor to the same as the text element\r\n style.textAnchor = textElStyle.textAnchor;\r\n style.fontSize = editProps.fontSize; // from app.props\r\n\r\n const parentZ = parseInt(window.getComputedStyle(markupDiv).zIndex || \"0\", 10);\r\n style.zIndex = (parentZ + 200).toString();\r\n\r\n editor.innerHTML = text.getMarkup(); // start with existing text\r\n this.editor.focus(); // give the editor focus\r\n\r\n // if we're started from the place text tool, select the entire current value, otherwise place the cursor at the end.\r\n this.editor.setSelectionRange(this._fromPlaceTool ? 0 : editor.value.length, editor.value.length);\r\n }\r\n\r\n /** Called when EditText exits, saves the edited value into the text element */\r\n public override async onCleanup() {\r\n if (!this.editDiv)\r\n return;\r\n\r\n const text = this.text! as MarkupText;\r\n const original = this.boxed ? this.boxed : text;\r\n const undo = this.markup.undo;\r\n undo.performOperation(this.keyin, () => {\r\n const newVal = this.editor!.value;\r\n if (newVal.trim() === \"\") { // if the result of the editing is blank, just delete the text element\r\n if (!this._fromPlaceTool)\r\n undo.onDelete(original);\r\n original.remove(); // must do this *after* we call undo.onDelete\r\n return;\r\n }\r\n\r\n let newText: G | MarkupText = text.clone();\r\n const fontSize = text.getFontSize();\r\n newText.createMarkup(newVal, fontSize);\r\n if (this.boxed) {\r\n newText = this.createBoxedText((original as G).parent() as G, newText);\r\n newText.matrix(original.matrix());\r\n }\r\n original.replace(newText);\r\n if (this._fromPlaceTool)\r\n undo.onAdded(newText);\r\n else\r\n undo.onModified(newText, original);\r\n });\r\n\r\n const editSize = MarkupApp.props.text.edit.size;\r\n const style = this.editor!.style;\r\n editSize.height = style.height;\r\n editSize.width = style.width;\r\n this.editDiv.remove();\r\n this.editDiv = undefined;\r\n this.editor = undefined;\r\n }\r\n\r\n public override async onInstall() {\r\n if (!await super.onInstall())\r\n return false;\r\n this.startEditor();\r\n return true;\r\n }\r\n\r\n public override async onResetButtonUp(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n\r\n public override async onDataButtonUp(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n\r\n public override async onMouseStartDrag(_ev: BeButtonEvent): Promise<EventHandled> {\r\n await this.exitTool();\r\n return EventHandled.Yes;\r\n }\r\n}\r\n"]}
package/lib/esm/Undo.d.ts CHANGED
@@ -1,47 +1,47 @@
1
- /** @packageDocumentation
2
- * @module MarkupTools
3
- */
4
- import { Element as MarkupElement } from "@svgdotjs/svg.js";
5
- /** Stores the sequence of operations performed on a Markup. Facilitates undo/redo of the operations.
6
- * @public
7
- */
8
- export declare class UndoManager {
9
- private _currentCmd;
10
- private _grouped;
11
- private _stack;
12
- private _currentPos;
13
- private _cmdName;
14
- private addAction;
15
- /** @internal */
16
- get size(): number;
17
- private startCommand;
18
- private startGroup;
19
- private endGroup;
20
- /** Perform a series of changes to markup elements that should all be reversed as a single operation.
21
- * @param fn the function that performs the changes to the elements. It must call the onXXX methods of this class to store
22
- * the operations in the undo buffer.
23
- * @note all of the onXXX methods of this class should *only* be called from within the callback function of this method.
24
- */
25
- performOperation(cmdName: string, fn: VoidFunction): void;
26
- /** call this from within a [[performOperation]] function *after* an element has been added to a markup */
27
- onAdded(elem: MarkupElement): void;
28
- /** call this from within a [[performOperation]] function *before* an element is about to be deleted from a markup */
29
- onDelete(elem: MarkupElement): void;
30
- /** call this from within a [[performOperation]] function *after* an element has been moved in display order in a markup */
31
- onRepositioned(elem: MarkupElement, oldIndex: number, oldParent: MarkupElement): void;
32
- /** call this from within a [[performOperation]] function *after* an element has been modified in a markup */
33
- onModified(newElem: MarkupElement, oldElem: MarkupElement): void;
34
- /** determine whether there are any un-reversed operations */
35
- get undoPossible(): boolean;
36
- /** determine whether there are any reversed operations */
37
- get redoPossible(): boolean;
38
- /** the name of the operation that can be undone (or undefined) */
39
- get undoString(): string | undefined;
40
- /** the name of the operation that can be redone (or undefined) */
41
- get redoString(): string | undefined;
42
- /** reverse the most recent operation, if any */
43
- doUndo(): void;
44
- /** reinstate the most recently reversed operation, if any */
45
- doRedo(): void;
46
- }
1
+ /** @packageDocumentation
2
+ * @module MarkupTools
3
+ */
4
+ import { Element as MarkupElement } from "@svgdotjs/svg.js";
5
+ /** Stores the sequence of operations performed on a Markup. Facilitates undo/redo of the operations.
6
+ * @public
7
+ */
8
+ export declare class UndoManager {
9
+ private _currentCmd;
10
+ private _grouped;
11
+ private _stack;
12
+ private _currentPos;
13
+ private _cmdName;
14
+ private addAction;
15
+ /** @internal */
16
+ get size(): number;
17
+ private startCommand;
18
+ private startGroup;
19
+ private endGroup;
20
+ /** Perform a series of changes to markup elements that should all be reversed as a single operation.
21
+ * @param fn the function that performs the changes to the elements. It must call the onXXX methods of this class to store
22
+ * the operations in the undo buffer.
23
+ * @note all of the onXXX methods of this class should *only* be called from within the callback function of this method.
24
+ */
25
+ performOperation(cmdName: string, fn: VoidFunction): void;
26
+ /** call this from within a [[performOperation]] function *after* an element has been added to a markup */
27
+ onAdded(elem: MarkupElement): void;
28
+ /** call this from within a [[performOperation]] function *before* an element is about to be deleted from a markup */
29
+ onDelete(elem: MarkupElement): void;
30
+ /** call this from within a [[performOperation]] function *after* an element has been moved in display order in a markup */
31
+ onRepositioned(elem: MarkupElement, oldIndex: number, oldParent: MarkupElement): void;
32
+ /** call this from within a [[performOperation]] function *after* an element has been modified in a markup */
33
+ onModified(newElem: MarkupElement, oldElem: MarkupElement): void;
34
+ /** determine whether there are any un-reversed operations */
35
+ get undoPossible(): boolean;
36
+ /** determine whether there are any reversed operations */
37
+ get redoPossible(): boolean;
38
+ /** the name of the operation that can be undone (or undefined) */
39
+ get undoString(): string | undefined;
40
+ /** the name of the operation that can be redone (or undefined) */
41
+ get redoString(): string | undefined;
42
+ /** reverse the most recent operation, if any */
43
+ doUndo(): void;
44
+ /** reinstate the most recently reversed operation, if any */
45
+ doRedo(): void;
46
+ }
47
47
  //# sourceMappingURL=Undo.d.ts.map