@textbus/platform-browser 5.2.1 → 5.2.3
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/dist/index.esm.js +1723 -1019
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2380 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.esm.js
CHANGED
|
@@ -1,105 +1,149 @@
|
|
|
1
|
-
import { Slot
|
|
2
|
-
import { filter
|
|
3
|
-
import { InjectionToken
|
|
4
|
-
function
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { Slot, ContentType, Event, invokeListener, Adapter, NativeSelectionBridge, FocusManager, Component, Registry, makeError } from "@textbus/core";
|
|
2
|
+
import { filter, fromEvent, Subject, delay, Subscription, distinctUntilChanged, merge, map, Observable } from "@tanbo/stream";
|
|
3
|
+
import { InjectionToken, Injectable, Inject, Optional } from "@viewfly/core";
|
|
4
|
+
function createElement(tagName, options = {}) {
|
|
5
|
+
const el = document.createElement(tagName);
|
|
6
|
+
if (options.classes) {
|
|
7
|
+
el.classList.add(...options.classes);
|
|
8
|
+
}
|
|
9
|
+
if (options.attrs) {
|
|
10
|
+
Object.keys(options.attrs).forEach((key) => {
|
|
11
|
+
el.setAttribute(key, options.attrs[key]);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (options.props) {
|
|
15
|
+
Object.keys(options.props).forEach((key) => {
|
|
16
|
+
el[key] = options.props[key];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (options.styles) {
|
|
20
|
+
Object.assign(el.style, options.styles);
|
|
21
|
+
}
|
|
22
|
+
if (options.children) {
|
|
23
|
+
options.children.filter((i) => i).forEach((item) => {
|
|
24
|
+
el.appendChild(item);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (options.on) {
|
|
28
|
+
Object.keys(options.on).forEach((key) => {
|
|
29
|
+
el.addEventListener(key, options.on[key]);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return el;
|
|
15
33
|
}
|
|
16
|
-
function
|
|
17
|
-
let { startContainer
|
|
18
|
-
if (
|
|
19
|
-
if (
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
function getLayoutRectByRange(range) {
|
|
35
|
+
let { startContainer, startOffset } = range;
|
|
36
|
+
if (startContainer.nodeType === Node.TEXT_NODE) {
|
|
37
|
+
if (startOffset > 0) {
|
|
38
|
+
return range.getBoundingClientRect();
|
|
39
|
+
}
|
|
40
|
+
const parentNode = startContainer.parentNode;
|
|
41
|
+
startOffset = Array.from(parentNode.childNodes).indexOf(startContainer);
|
|
42
|
+
startContainer = parentNode;
|
|
43
|
+
}
|
|
44
|
+
const beforeNode = startContainer.childNodes[startOffset - 1];
|
|
45
|
+
if (beforeNode) {
|
|
46
|
+
if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== "br") {
|
|
47
|
+
const rect2 = beforeNode.getBoundingClientRect();
|
|
28
48
|
return {
|
|
29
|
-
left:
|
|
30
|
-
top:
|
|
31
|
-
width:
|
|
32
|
-
height:
|
|
49
|
+
left: rect2.right,
|
|
50
|
+
top: rect2.top,
|
|
51
|
+
width: range.collapsed ? 1 : rect2.width,
|
|
52
|
+
height: rect2.height
|
|
33
53
|
};
|
|
34
|
-
} else if (
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
} else if (beforeNode.nodeType === Node.TEXT_NODE) {
|
|
55
|
+
const range2 = document.createRange();
|
|
56
|
+
range2.setStart(beforeNode, beforeNode.textContent.length);
|
|
57
|
+
range2.setEnd(beforeNode, beforeNode.textContent.length);
|
|
58
|
+
const rect2 = range2.getBoundingClientRect();
|
|
38
59
|
return {
|
|
39
|
-
left:
|
|
40
|
-
top:
|
|
41
|
-
width:
|
|
42
|
-
height:
|
|
60
|
+
left: rect2.right,
|
|
61
|
+
top: rect2.top,
|
|
62
|
+
width: range.collapsed ? 1 : rect2.width,
|
|
63
|
+
height: rect2.height
|
|
43
64
|
};
|
|
44
65
|
}
|
|
45
66
|
}
|
|
46
|
-
const
|
|
47
|
-
let
|
|
48
|
-
if (!
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
51
|
-
const
|
|
67
|
+
const offsetNode = startContainer.childNodes[startOffset];
|
|
68
|
+
let isInsertBefore = false;
|
|
69
|
+
if (!offsetNode) {
|
|
70
|
+
const lastChild = startContainer.lastChild;
|
|
71
|
+
if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) {
|
|
72
|
+
const rect2 = lastChild.getBoundingClientRect();
|
|
52
73
|
return {
|
|
53
|
-
left:
|
|
54
|
-
top:
|
|
55
|
-
width:
|
|
56
|
-
height:
|
|
74
|
+
left: rect2.right,
|
|
75
|
+
top: rect2.top,
|
|
76
|
+
width: range.collapsed ? 1 : rect2.width,
|
|
77
|
+
height: rect2.height
|
|
57
78
|
};
|
|
58
79
|
}
|
|
59
80
|
}
|
|
60
|
-
if (
|
|
61
|
-
if (
|
|
62
|
-
const
|
|
81
|
+
if (offsetNode) {
|
|
82
|
+
if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== "br") {
|
|
83
|
+
const rect2 = offsetNode.getBoundingClientRect();
|
|
63
84
|
return {
|
|
64
|
-
left:
|
|
65
|
-
top:
|
|
66
|
-
width:
|
|
67
|
-
height:
|
|
85
|
+
left: rect2.left,
|
|
86
|
+
top: rect2.top,
|
|
87
|
+
width: range.collapsed ? 1 : rect2.width,
|
|
88
|
+
height: rect2.height
|
|
68
89
|
};
|
|
69
90
|
}
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
91
|
+
isInsertBefore = true;
|
|
92
|
+
}
|
|
93
|
+
const span = startContainer.ownerDocument.createElement("span");
|
|
94
|
+
span.innerText = "";
|
|
95
|
+
span.style.display = "inline-block";
|
|
96
|
+
if (isInsertBefore) {
|
|
97
|
+
startContainer.insertBefore(span, offsetNode);
|
|
98
|
+
} else {
|
|
99
|
+
startContainer.appendChild(span);
|
|
100
|
+
}
|
|
101
|
+
const rect = span.getBoundingClientRect();
|
|
102
|
+
startContainer.removeChild(span);
|
|
103
|
+
return {
|
|
104
|
+
left: rect.left,
|
|
105
|
+
top: rect.top,
|
|
106
|
+
width: range.collapsed ? 1 : rect.width,
|
|
107
|
+
height: rect.height
|
|
80
108
|
};
|
|
81
109
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
|
|
111
|
+
const isMac = () => /mac os/i.test(navigator.userAgent);
|
|
112
|
+
const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
|
|
113
|
+
const isFirefox = () => /Firefox/.test(navigator.userAgent);
|
|
114
|
+
const isMobileBrowser = () => /Android|iPhone|iPad/.test(navigator.userAgent);
|
|
115
|
+
const EDITOR_OPTIONS = new InjectionToken("EDITOR_OPTIONS");
|
|
116
|
+
const VIEW_CONTAINER = new InjectionToken("VIEW_CONTAINER");
|
|
117
|
+
const VIEW_DOCUMENT = new InjectionToken("VIEW_DOCUMENT");
|
|
118
|
+
const VIEW_MASK = new InjectionToken("VIEW_MASK");
|
|
119
|
+
var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
|
|
120
|
+
var __decorateClass$4 = (decorators, target, key, kind) => {
|
|
121
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
|
|
122
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
123
|
+
if (decorator = decorators[i])
|
|
124
|
+
result = decorator(result) || result;
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
var __decorateParam$2 = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
128
|
+
let Parser = class {
|
|
129
|
+
constructor(options, textbus) {
|
|
130
|
+
this.textbus = textbus;
|
|
131
|
+
const componentLoaders = [
|
|
132
|
+
...options.componentLoaders || []
|
|
97
133
|
];
|
|
98
|
-
|
|
134
|
+
const formatLoaders = [
|
|
135
|
+
...options.formatLoaders || []
|
|
136
|
+
];
|
|
137
|
+
const attributeLoaders = [
|
|
138
|
+
...options.attributeLoaders || []
|
|
139
|
+
];
|
|
140
|
+
this.componentLoaders = componentLoaders;
|
|
141
|
+
this.formatLoaders = formatLoaders;
|
|
142
|
+
this.attributeLoaders = attributeLoaders;
|
|
99
143
|
}
|
|
100
144
|
textbus;
|
|
101
|
-
static parseHTML(
|
|
102
|
-
return new DOMParser().parseFromString(
|
|
145
|
+
static parseHTML(html) {
|
|
146
|
+
return new DOMParser().parseFromString(html, "text/html").body;
|
|
103
147
|
}
|
|
104
148
|
componentLoaders;
|
|
105
149
|
formatLoaders;
|
|
@@ -109,12 +153,14 @@ let O = class {
|
|
|
109
153
|
* @param html
|
|
110
154
|
* @param rootComponentLoader
|
|
111
155
|
*/
|
|
112
|
-
parseDoc(
|
|
113
|
-
const
|
|
114
|
-
return
|
|
115
|
-
|
|
156
|
+
parseDoc(html, rootComponentLoader) {
|
|
157
|
+
const element = typeof html === "string" ? Parser.parseHTML(html) : html;
|
|
158
|
+
return rootComponentLoader.read(
|
|
159
|
+
element,
|
|
116
160
|
this.textbus,
|
|
117
|
-
(
|
|
161
|
+
(childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
|
|
162
|
+
return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
|
|
163
|
+
}
|
|
118
164
|
);
|
|
119
165
|
}
|
|
120
166
|
/**
|
|
@@ -122,102 +168,154 @@ let O = class {
|
|
|
122
168
|
* @param html
|
|
123
169
|
* @param rootSlot
|
|
124
170
|
*/
|
|
125
|
-
parse(
|
|
126
|
-
const
|
|
127
|
-
return this.readFormats(
|
|
128
|
-
}
|
|
129
|
-
readComponent(
|
|
130
|
-
if (
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
`);
|
|
171
|
+
parse(html, rootSlot) {
|
|
172
|
+
const element = typeof html === "string" ? Parser.parseHTML(html) : html;
|
|
173
|
+
return this.readFormats(element, rootSlot);
|
|
174
|
+
}
|
|
175
|
+
readComponent(el, slot) {
|
|
176
|
+
if (el.nodeType === Node.ELEMENT_NODE) {
|
|
177
|
+
if (el.tagName === "BR") {
|
|
178
|
+
slot.insert("\n");
|
|
134
179
|
return;
|
|
135
180
|
}
|
|
136
|
-
const
|
|
137
|
-
for (const
|
|
138
|
-
if (
|
|
139
|
-
const
|
|
140
|
-
|
|
181
|
+
const schema = [...slot.schema];
|
|
182
|
+
for (const t of this.componentLoaders) {
|
|
183
|
+
if (t.match(el, schema)) {
|
|
184
|
+
const result = t.read(
|
|
185
|
+
el,
|
|
141
186
|
this.textbus,
|
|
142
|
-
(
|
|
187
|
+
(childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
|
|
188
|
+
return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
|
|
189
|
+
}
|
|
143
190
|
);
|
|
144
|
-
if (!
|
|
191
|
+
if (!result) {
|
|
145
192
|
return;
|
|
146
|
-
|
|
147
|
-
|
|
193
|
+
}
|
|
194
|
+
if (result instanceof Slot) {
|
|
195
|
+
result.toDelta().forEach((i) => slot.insert(i.insert, i.formats));
|
|
148
196
|
return;
|
|
149
197
|
}
|
|
150
|
-
|
|
198
|
+
slot.insert(result);
|
|
151
199
|
return;
|
|
152
200
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
201
|
+
}
|
|
202
|
+
this.readFormats(el, slot);
|
|
203
|
+
} else if (el.nodeType === Node.TEXT_NODE) {
|
|
204
|
+
this.readText(slot, el);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
readText(slot, el) {
|
|
208
|
+
const textContent = el.textContent;
|
|
209
|
+
if (/^\s*[\r\n\u200b]+\s*$/.test(textContent)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
slot.insert(textContent);
|
|
213
|
+
}
|
|
214
|
+
readFormats(el, slot) {
|
|
215
|
+
const formats = this.formatLoaders.filter((f) => {
|
|
216
|
+
return f.match(el);
|
|
217
|
+
}).map((f) => {
|
|
218
|
+
return f.read(el);
|
|
219
|
+
});
|
|
220
|
+
const startIndex = slot.index;
|
|
221
|
+
let startNode = el.firstChild;
|
|
222
|
+
while (startNode) {
|
|
223
|
+
this.readComponent(startNode, slot);
|
|
224
|
+
startNode = startNode.nextSibling;
|
|
225
|
+
}
|
|
226
|
+
const endIndex = slot.index;
|
|
227
|
+
this.applyFormats(slot, formats.map((i) => {
|
|
228
|
+
return {
|
|
229
|
+
formatter: i.formatter,
|
|
230
|
+
value: i.value,
|
|
231
|
+
startIndex,
|
|
232
|
+
endIndex
|
|
233
|
+
};
|
|
234
|
+
}));
|
|
235
|
+
slot.retain(endIndex);
|
|
236
|
+
return slot;
|
|
237
|
+
}
|
|
238
|
+
readSlot(childSlot, slotRootElement, slotContentElement) {
|
|
239
|
+
if (slotRootElement.nodeType === Node.ELEMENT_NODE) {
|
|
240
|
+
this.attributeLoaders.filter((a) => {
|
|
241
|
+
return a.match(slotRootElement);
|
|
242
|
+
}).forEach((a) => {
|
|
243
|
+
const r = a.read(slotRootElement);
|
|
244
|
+
childSlot.setAttribute(r.attribute, r.value);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (slotContentElement.nodeType === Node.ELEMENT_NODE) {
|
|
248
|
+
this.readFormats(slotContentElement, childSlot);
|
|
249
|
+
} else {
|
|
250
|
+
this.readText(childSlot, slotContentElement);
|
|
251
|
+
}
|
|
252
|
+
return childSlot;
|
|
253
|
+
}
|
|
254
|
+
applyFormats(slot, formatItems) {
|
|
255
|
+
slot.background(() => {
|
|
256
|
+
formatItems.forEach((i) => {
|
|
257
|
+
slot.retain(i.startIndex);
|
|
258
|
+
slot.retain(i.endIndex - i.startIndex, i.formatter, i.value);
|
|
183
259
|
});
|
|
184
260
|
});
|
|
185
261
|
}
|
|
186
262
|
};
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
],
|
|
191
|
-
var
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
263
|
+
Parser = __decorateClass$4([
|
|
264
|
+
Injectable(),
|
|
265
|
+
__decorateParam$2(0, Inject(EDITOR_OPTIONS))
|
|
266
|
+
], Parser);
|
|
267
|
+
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
268
|
+
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
269
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
270
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
271
|
+
if (decorator = decorators[i])
|
|
272
|
+
result = decorator(result) || result;
|
|
273
|
+
return result;
|
|
274
|
+
};
|
|
275
|
+
var __decorateParam$1 = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
276
|
+
let SelectionBridge = class {
|
|
277
|
+
constructor(config, textbus, controller, selection, rootComponentRef, input, scheduler, domAdapter) {
|
|
278
|
+
this.config = config;
|
|
279
|
+
this.selection = selection;
|
|
280
|
+
this.rootComponentRef = rootComponentRef;
|
|
281
|
+
this.input = input;
|
|
282
|
+
this.scheduler = scheduler;
|
|
283
|
+
this.domAdapter = domAdapter;
|
|
284
|
+
this.docContainer = textbus.get(VIEW_DOCUMENT);
|
|
285
|
+
this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {
|
|
286
|
+
return !controller.readonly;
|
|
287
|
+
}));
|
|
288
|
+
this.sub = this.onSelectionChange.subscribe((r) => {
|
|
289
|
+
if (r) {
|
|
290
|
+
input.focus(r, this.changeFromUser);
|
|
291
|
+
} else {
|
|
292
|
+
input.blur();
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
this.sub.add(
|
|
296
|
+
fromEvent(document, "focusin").subscribe((ev) => {
|
|
297
|
+
let target = ev.target;
|
|
298
|
+
if (/^(input|textarea|select)$/i.test(target.nodeName)) {
|
|
299
|
+
if (target.tagName.toLowerCase() === "input" && /^(range|date)$/.test(target.type)) {
|
|
205
300
|
return;
|
|
206
|
-
|
|
301
|
+
}
|
|
302
|
+
this.ignoreSelectionChange = true;
|
|
207
303
|
return;
|
|
208
304
|
}
|
|
209
|
-
if (!
|
|
210
|
-
|
|
211
|
-
if (
|
|
212
|
-
this.ignoreSelectionChange =
|
|
305
|
+
if (!config.useContentEditable) {
|
|
306
|
+
while (target) {
|
|
307
|
+
if (target.contentEditable === "true") {
|
|
308
|
+
this.ignoreSelectionChange = true;
|
|
213
309
|
return;
|
|
214
310
|
}
|
|
215
|
-
|
|
311
|
+
target = target.parentNode;
|
|
216
312
|
}
|
|
313
|
+
}
|
|
217
314
|
})
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
|
|
315
|
+
);
|
|
316
|
+
this.sub.add(
|
|
317
|
+
fromEvent(document, "focusout").subscribe(() => {
|
|
318
|
+
this.ignoreSelectionChange = false;
|
|
221
319
|
})
|
|
222
320
|
);
|
|
223
321
|
}
|
|
@@ -229,141 +327,202 @@ let P = class {
|
|
|
229
327
|
domAdapter;
|
|
230
328
|
onSelectionChange;
|
|
231
329
|
nativeSelection = document.getSelection();
|
|
232
|
-
syncSelectionFromNativeSelectionChange =
|
|
233
|
-
selectionChangeEvent = new
|
|
330
|
+
syncSelectionFromNativeSelectionChange = true;
|
|
331
|
+
selectionChangeEvent = new Subject();
|
|
234
332
|
subs = [];
|
|
235
333
|
sub;
|
|
236
334
|
connector = null;
|
|
237
|
-
ignoreSelectionChange =
|
|
238
|
-
changeFromUser =
|
|
335
|
+
ignoreSelectionChange = false;
|
|
336
|
+
changeFromUser = false;
|
|
239
337
|
docContainer;
|
|
240
338
|
cacheCaretPositionTimer;
|
|
241
339
|
oldCaretPosition;
|
|
242
|
-
connect(
|
|
243
|
-
this.disConnect()
|
|
340
|
+
connect(connector) {
|
|
341
|
+
this.disConnect();
|
|
342
|
+
this.connector = connector;
|
|
343
|
+
this.syncSelection(connector);
|
|
344
|
+
this.listen(connector);
|
|
244
345
|
}
|
|
245
346
|
disConnect() {
|
|
246
|
-
this.connector = null
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
347
|
+
this.connector = null;
|
|
348
|
+
this.unListen();
|
|
349
|
+
}
|
|
350
|
+
getRect(location) {
|
|
351
|
+
const { focus, anchor } = this.getPositionByRange({
|
|
352
|
+
focusOffset: location.offset,
|
|
353
|
+
anchorOffset: location.offset,
|
|
354
|
+
focusSlot: location.slot,
|
|
355
|
+
anchorSlot: location.slot
|
|
254
356
|
});
|
|
255
|
-
if (!
|
|
357
|
+
if (!focus || !anchor) {
|
|
256
358
|
return null;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
359
|
+
}
|
|
360
|
+
const nativeRange = document.createRange();
|
|
361
|
+
nativeRange.setStart(focus.node, focus.offset);
|
|
362
|
+
nativeRange.collapse();
|
|
363
|
+
return getLayoutRectByRange(nativeRange);
|
|
364
|
+
}
|
|
365
|
+
restore(abstractSelection, fromLocal) {
|
|
366
|
+
this.changeFromUser = fromLocal;
|
|
367
|
+
if (this.ignoreSelectionChange || !this.connector) {
|
|
262
368
|
return;
|
|
263
|
-
|
|
264
|
-
|
|
369
|
+
}
|
|
370
|
+
this.unListen();
|
|
371
|
+
if (!abstractSelection) {
|
|
372
|
+
this.nativeSelection.removeAllRanges();
|
|
373
|
+
this.selectionChangeEvent.next(null);
|
|
374
|
+
this.listen(this.connector);
|
|
265
375
|
return;
|
|
266
376
|
}
|
|
267
|
-
const { focus
|
|
268
|
-
if (!
|
|
269
|
-
this.nativeSelection.removeAllRanges()
|
|
377
|
+
const { focus, anchor } = this.getPositionByRange(abstractSelection);
|
|
378
|
+
if (!focus || !anchor) {
|
|
379
|
+
this.nativeSelection.removeAllRanges();
|
|
380
|
+
this.selectionChangeEvent.next(null);
|
|
381
|
+
this.listen(this.connector);
|
|
270
382
|
return;
|
|
271
383
|
}
|
|
272
|
-
function
|
|
273
|
-
if (
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
384
|
+
function tryOffset(position) {
|
|
385
|
+
if (!position.node) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (position.node.nodeType === Node.TEXT_NODE) {
|
|
389
|
+
const len = position.node.textContent.length;
|
|
390
|
+
if (position.offset > len) {
|
|
391
|
+
position.offset = len;
|
|
392
|
+
}
|
|
393
|
+
} else if (position.node.nodeType === Node.ELEMENT_NODE) {
|
|
394
|
+
const len = position.node.childNodes.length;
|
|
395
|
+
if (position.offset > len) {
|
|
396
|
+
position.offset = len;
|
|
280
397
|
}
|
|
281
398
|
}
|
|
282
399
|
}
|
|
283
400
|
try {
|
|
284
|
-
|
|
285
|
-
|
|
401
|
+
tryOffset(focus);
|
|
402
|
+
tryOffset(anchor);
|
|
403
|
+
this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
|
|
404
|
+
} catch (e) {
|
|
286
405
|
setTimeout(() => {
|
|
287
|
-
throw
|
|
406
|
+
throw e;
|
|
288
407
|
});
|
|
289
408
|
}
|
|
290
409
|
if (this.nativeSelection.rangeCount) {
|
|
291
|
-
const
|
|
292
|
-
this.selectionChangeEvent.next(
|
|
293
|
-
} else
|
|
410
|
+
const nativeRange = this.nativeSelection.getRangeAt(0);
|
|
411
|
+
this.selectionChangeEvent.next(nativeRange);
|
|
412
|
+
} else {
|
|
294
413
|
this.selectionChangeEvent.next(null);
|
|
295
|
-
|
|
296
|
-
|
|
414
|
+
}
|
|
415
|
+
const bind = () => {
|
|
416
|
+
if (this.connector) {
|
|
417
|
+
this.listen(this.connector);
|
|
418
|
+
}
|
|
297
419
|
};
|
|
298
|
-
if (
|
|
299
|
-
Promise.resolve().then(
|
|
420
|
+
if (fromLocal) {
|
|
421
|
+
Promise.resolve().then(bind);
|
|
300
422
|
return;
|
|
301
423
|
}
|
|
302
|
-
typeof requestIdleCallback
|
|
424
|
+
if (typeof requestIdleCallback === "function") {
|
|
425
|
+
requestIdleCallback(bind);
|
|
426
|
+
} else {
|
|
427
|
+
setTimeout(bind, 30);
|
|
428
|
+
}
|
|
303
429
|
}
|
|
304
430
|
destroy() {
|
|
305
|
-
this.subs.forEach((
|
|
431
|
+
this.subs.forEach((i) => i.unsubscribe());
|
|
432
|
+
this.sub.unsubscribe();
|
|
306
433
|
}
|
|
307
|
-
getPositionByRange(
|
|
308
|
-
let
|
|
434
|
+
getPositionByRange(abstractSelection) {
|
|
435
|
+
let focus;
|
|
436
|
+
let anchor;
|
|
309
437
|
try {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
438
|
+
focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot, abstractSelection.focusOffset);
|
|
439
|
+
anchor = focus;
|
|
440
|
+
if (abstractSelection.anchorSlot !== abstractSelection.focusSlot || abstractSelection.anchorOffset !== abstractSelection.focusOffset) {
|
|
441
|
+
anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot, abstractSelection.anchorOffset);
|
|
442
|
+
}
|
|
443
|
+
return {
|
|
444
|
+
focus,
|
|
445
|
+
anchor
|
|
313
446
|
};
|
|
314
|
-
} catch {
|
|
447
|
+
} catch (e) {
|
|
315
448
|
return {
|
|
316
449
|
focus: null,
|
|
317
450
|
anchor: null
|
|
318
451
|
};
|
|
319
452
|
}
|
|
320
453
|
}
|
|
321
|
-
getPreviousLinePositionByCurrent(
|
|
322
|
-
return this.getLinePosition(
|
|
454
|
+
getPreviousLinePositionByCurrent(position) {
|
|
455
|
+
return this.getLinePosition(position, false);
|
|
323
456
|
}
|
|
324
|
-
getNextLinePositionByCurrent(
|
|
325
|
-
return this.getLinePosition(
|
|
457
|
+
getNextLinePositionByCurrent(position) {
|
|
458
|
+
return this.getLinePosition(position, true);
|
|
326
459
|
}
|
|
327
|
-
getLinePosition(
|
|
460
|
+
getLinePosition(currentPosition, toNext) {
|
|
328
461
|
clearTimeout(this.cacheCaretPositionTimer);
|
|
329
|
-
let
|
|
330
|
-
|
|
462
|
+
let p;
|
|
463
|
+
if (this.oldCaretPosition) {
|
|
464
|
+
p = toNext ? this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) : this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
|
|
465
|
+
} else {
|
|
466
|
+
this.oldCaretPosition = this.getRect(currentPosition);
|
|
467
|
+
p = toNext ? this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) : this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
|
|
468
|
+
}
|
|
469
|
+
this.cacheCaretPositionTimer = setTimeout(() => {
|
|
331
470
|
this.oldCaretPosition = null;
|
|
332
|
-
}, 3e3)
|
|
471
|
+
}, 3e3);
|
|
472
|
+
return p;
|
|
333
473
|
}
|
|
334
474
|
/**
|
|
335
475
|
* 获取选区向上移动一行的位置。
|
|
336
476
|
* @param currentPosition
|
|
337
477
|
* @param startLeft 参考位置。
|
|
338
478
|
*/
|
|
339
|
-
getPreviousLinePositionByOffset(
|
|
340
|
-
let
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
479
|
+
getPreviousLinePositionByOffset(currentPosition, startLeft) {
|
|
480
|
+
let isToPrevLine = false;
|
|
481
|
+
let loopCount = 0;
|
|
482
|
+
let minLeft = startLeft;
|
|
483
|
+
let focusSlot = currentPosition.slot;
|
|
484
|
+
let focusOffset = currentPosition.offset;
|
|
485
|
+
let minTop = this.getRect({
|
|
486
|
+
slot: focusSlot,
|
|
487
|
+
offset: focusOffset
|
|
488
|
+
}).top;
|
|
489
|
+
let position;
|
|
490
|
+
let oldPosition;
|
|
491
|
+
let oldLeft = 0;
|
|
492
|
+
while (true) {
|
|
493
|
+
loopCount++;
|
|
494
|
+
position = this.selection.getPreviousPositionByPosition(focusSlot, focusOffset);
|
|
495
|
+
focusSlot = position.slot;
|
|
496
|
+
focusOffset = position.offset;
|
|
497
|
+
const rect2 = this.getRect(position);
|
|
498
|
+
if (!isToPrevLine) {
|
|
499
|
+
if (rect2.left > minLeft || rect2.top + rect2.height <= minTop) {
|
|
500
|
+
isToPrevLine = true;
|
|
501
|
+
} else if (rect2.left === minLeft && rect2.top === minTop) {
|
|
502
|
+
return position;
|
|
503
|
+
}
|
|
504
|
+
minLeft = rect2.left;
|
|
505
|
+
minTop = rect2.top;
|
|
353
506
|
}
|
|
354
|
-
if (
|
|
355
|
-
if (
|
|
356
|
-
return
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
507
|
+
if (isToPrevLine) {
|
|
508
|
+
if (rect2.left <= startLeft) {
|
|
509
|
+
return position;
|
|
510
|
+
}
|
|
511
|
+
if (oldPosition) {
|
|
512
|
+
if (rect2.left >= oldLeft) {
|
|
513
|
+
return oldPosition;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
oldLeft = rect2.left;
|
|
517
|
+
oldPosition = position;
|
|
360
518
|
}
|
|
361
|
-
if (
|
|
519
|
+
if (loopCount > 1e4) {
|
|
362
520
|
break;
|
|
521
|
+
}
|
|
363
522
|
}
|
|
364
|
-
return
|
|
523
|
+
return position || {
|
|
365
524
|
offset: 0,
|
|
366
|
-
slot:
|
|
525
|
+
slot: focusSlot
|
|
367
526
|
};
|
|
368
527
|
}
|
|
369
528
|
/**
|
|
@@ -371,242 +530,341 @@ let P = class {
|
|
|
371
530
|
* @param currentPosition
|
|
372
531
|
* @param startLeft 参考位置。
|
|
373
532
|
*/
|
|
374
|
-
getNextLinePositionByOffset(
|
|
375
|
-
let
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
533
|
+
getNextLinePositionByOffset(currentPosition, startLeft) {
|
|
534
|
+
let isToNextLine = false;
|
|
535
|
+
let loopCount = 0;
|
|
536
|
+
let maxRight = startLeft;
|
|
537
|
+
let focusSlot = currentPosition.slot;
|
|
538
|
+
let focusOffset = currentPosition.offset;
|
|
539
|
+
const rect = this.getRect({
|
|
540
|
+
slot: focusSlot,
|
|
541
|
+
offset: focusOffset
|
|
379
542
|
});
|
|
380
|
-
let
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
543
|
+
let minTop = rect.top;
|
|
544
|
+
let oldPosition;
|
|
545
|
+
let oldLeft = 0;
|
|
546
|
+
while (true) {
|
|
547
|
+
loopCount++;
|
|
548
|
+
const position = this.selection.getNextPositionByPosition(focusSlot, focusOffset);
|
|
549
|
+
focusSlot = position.slot;
|
|
550
|
+
focusOffset = position.offset;
|
|
551
|
+
const rect2 = this.getRect(position);
|
|
552
|
+
if (!isToNextLine) {
|
|
553
|
+
if (rect2.left < maxRight || rect2.top >= minTop + rect.height) {
|
|
554
|
+
isToNextLine = true;
|
|
555
|
+
} else if (rect2.left === maxRight && rect2.top === minTop) {
|
|
556
|
+
return position;
|
|
557
|
+
}
|
|
558
|
+
maxRight = rect2.left;
|
|
559
|
+
minTop = rect2.top;
|
|
560
|
+
oldPosition = position;
|
|
392
561
|
}
|
|
393
|
-
if (
|
|
394
|
-
if (
|
|
395
|
-
return
|
|
396
|
-
|
|
562
|
+
if (isToNextLine) {
|
|
563
|
+
if (rect2.left > startLeft) {
|
|
564
|
+
return oldPosition;
|
|
565
|
+
}
|
|
566
|
+
if (oldPosition) {
|
|
567
|
+
if (rect2.left <= oldLeft) {
|
|
568
|
+
return oldPosition;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
oldPosition = position;
|
|
572
|
+
oldLeft = rect2.left;
|
|
397
573
|
}
|
|
398
|
-
if (
|
|
574
|
+
if (loopCount > 1e4) {
|
|
399
575
|
break;
|
|
576
|
+
}
|
|
400
577
|
}
|
|
401
|
-
return
|
|
402
|
-
offset:
|
|
403
|
-
slot:
|
|
578
|
+
return oldPosition || {
|
|
579
|
+
offset: focusSlot.length,
|
|
580
|
+
slot: focusSlot
|
|
404
581
|
};
|
|
405
582
|
}
|
|
406
583
|
unListen() {
|
|
407
|
-
this.subs.forEach((
|
|
584
|
+
this.subs.forEach((i) => i.unsubscribe());
|
|
585
|
+
this.subs = [];
|
|
408
586
|
}
|
|
409
|
-
listen(
|
|
587
|
+
listen(connector) {
|
|
410
588
|
if (!this.config.useContentEditable) {
|
|
411
|
-
const
|
|
589
|
+
const selection = this.nativeSelection;
|
|
412
590
|
this.subs.push(
|
|
413
|
-
|
|
414
|
-
this.ignoreSelectionChange ||
|
|
591
|
+
fromEvent(this.docContainer, "mousedown").subscribe((ev) => {
|
|
592
|
+
if (this.ignoreSelectionChange || ev.button === 2) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (!ev.shiftKey) {
|
|
596
|
+
selection.removeAllRanges();
|
|
597
|
+
}
|
|
415
598
|
})
|
|
416
599
|
);
|
|
417
600
|
}
|
|
418
|
-
let
|
|
601
|
+
let isUpdating = false;
|
|
419
602
|
this.subs.push(
|
|
420
603
|
this.scheduler.onDocChange.subscribe(() => {
|
|
421
|
-
|
|
604
|
+
isUpdating = true;
|
|
422
605
|
}),
|
|
423
|
-
this.scheduler.onDocChanged.pipe(
|
|
424
|
-
|
|
606
|
+
this.scheduler.onDocChanged.pipe(delay()).subscribe(() => {
|
|
607
|
+
isUpdating = false;
|
|
425
608
|
}),
|
|
426
|
-
|
|
427
|
-
|
|
609
|
+
fromEvent(document, "selectionchange").subscribe(() => {
|
|
610
|
+
if (isUpdating) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (this.syncSelectionFromNativeSelectionChange) {
|
|
614
|
+
this.syncSelection(connector);
|
|
615
|
+
}
|
|
428
616
|
})
|
|
429
617
|
);
|
|
430
618
|
}
|
|
431
|
-
syncSelection(
|
|
432
|
-
const
|
|
433
|
-
|
|
619
|
+
syncSelection(connector) {
|
|
620
|
+
const selection = this.nativeSelection;
|
|
621
|
+
this.changeFromUser = true;
|
|
622
|
+
if (this.ignoreSelectionChange || this.input.composition || selection.rangeCount === 0 || !this.docContainer.contains(selection.anchorNode) || this.rootComponentRef.component.slots.length === 0) {
|
|
434
623
|
return;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
624
|
+
}
|
|
625
|
+
const rawRange = selection.getRangeAt(0);
|
|
626
|
+
const nativeRange = rawRange.cloneRange();
|
|
627
|
+
const isFocusEnd = selection.focusNode === nativeRange.endContainer && selection.focusOffset === nativeRange.endOffset;
|
|
628
|
+
const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset;
|
|
629
|
+
if (!this.docContainer.contains(selection.focusNode)) {
|
|
630
|
+
if (isFocusEnd) {
|
|
631
|
+
const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(0));
|
|
632
|
+
if (!nativeNode) {
|
|
440
633
|
return;
|
|
441
|
-
|
|
634
|
+
}
|
|
635
|
+
nativeRange.setEndAfter(nativeNode.lastChild);
|
|
442
636
|
} else {
|
|
443
|
-
const
|
|
444
|
-
if (!
|
|
637
|
+
const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(-1));
|
|
638
|
+
if (!nativeNode) {
|
|
445
639
|
return;
|
|
446
|
-
|
|
640
|
+
}
|
|
641
|
+
nativeRange.setStartBefore(nativeNode.firstChild);
|
|
447
642
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
643
|
+
}
|
|
644
|
+
const startPosition = this.getCorrectedPosition(nativeRange.startContainer, nativeRange.startOffset, isFocusStart);
|
|
645
|
+
const endPosition = nativeRange.collapsed ? startPosition : this.getCorrectedPosition(nativeRange.endContainer, nativeRange.endOffset, isFocusEnd);
|
|
646
|
+
if ([Node.ELEMENT_NODE, Node.TEXT_NODE].includes(nativeRange.commonAncestorContainer?.nodeType) && startPosition && endPosition) {
|
|
647
|
+
const abstractSelection = connector.beforeChange(isFocusEnd ? {
|
|
648
|
+
anchorSlot: startPosition.slot,
|
|
649
|
+
anchorOffset: startPosition.offset,
|
|
650
|
+
focusSlot: endPosition.slot,
|
|
651
|
+
focusOffset: endPosition.offset
|
|
455
652
|
} : {
|
|
456
|
-
focusSlot:
|
|
457
|
-
focusOffset:
|
|
458
|
-
anchorSlot:
|
|
459
|
-
anchorOffset:
|
|
653
|
+
focusSlot: startPosition.slot,
|
|
654
|
+
focusOffset: startPosition.offset,
|
|
655
|
+
anchorSlot: endPosition.slot,
|
|
656
|
+
anchorOffset: endPosition.offset
|
|
460
657
|
});
|
|
461
|
-
if (!
|
|
462
|
-
this.selectionChangeEvent.next(null)
|
|
658
|
+
if (!abstractSelection) {
|
|
659
|
+
this.selectionChangeEvent.next(null);
|
|
660
|
+
connector.setSelection(null);
|
|
463
661
|
return;
|
|
464
662
|
}
|
|
465
|
-
const { focus
|
|
466
|
-
if (
|
|
467
|
-
let
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
663
|
+
const { focus, anchor } = this.getPositionByRange(abstractSelection);
|
|
664
|
+
if (focus && anchor) {
|
|
665
|
+
let start = anchor;
|
|
666
|
+
let end = focus;
|
|
667
|
+
if (isFocusStart) {
|
|
668
|
+
start = focus;
|
|
669
|
+
end = anchor;
|
|
670
|
+
}
|
|
671
|
+
if (nativeRange.startContainer !== start.node || nativeRange.startOffset !== start.offset) {
|
|
672
|
+
nativeRange.setStart(start.node, start.offset);
|
|
673
|
+
}
|
|
674
|
+
if (nativeRange.endContainer !== end.node || nativeRange.endOffset !== end.offset) {
|
|
675
|
+
nativeRange.setEnd(end.node, end.offset);
|
|
676
|
+
}
|
|
677
|
+
connector.setSelection(abstractSelection);
|
|
678
|
+
if (selection.isCollapsed && (rawRange.startContainer !== start.node || rawRange.startOffset !== start.offset || rawRange.endContainer !== end.node || rawRange.endOffset !== end.offset)) {
|
|
679
|
+
rawRange.setStart(start.node, start.offset);
|
|
680
|
+
rawRange.setEnd(end.node, end.offset);
|
|
681
|
+
}
|
|
682
|
+
this.selectionChangeEvent.next(nativeRange);
|
|
683
|
+
} else {
|
|
684
|
+
connector.setSelection(null);
|
|
685
|
+
}
|
|
471
686
|
return;
|
|
472
687
|
}
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
findSelectedNodeAndOffset(
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
688
|
+
connector.setSelection(null);
|
|
689
|
+
}
|
|
690
|
+
findSelectedNodeAndOffset(slot, offset) {
|
|
691
|
+
const prev = slot.getContentAtIndex(offset - 1);
|
|
692
|
+
const nodes = this.domAdapter.getNodesBySlot(slot);
|
|
693
|
+
if (prev) {
|
|
694
|
+
if (typeof prev !== "string") {
|
|
695
|
+
const nativeNode = this.domAdapter.getNativeNodeByComponent(prev);
|
|
480
696
|
return {
|
|
481
|
-
node:
|
|
482
|
-
offset: Array.from(
|
|
697
|
+
node: nativeNode.parentNode,
|
|
698
|
+
offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode) + 1
|
|
483
699
|
};
|
|
484
|
-
} else if (
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
700
|
+
} else if (prev === "\n") {
|
|
701
|
+
for (const node of nodes) {
|
|
702
|
+
if (node instanceof Text) {
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
if (node.nodeName === "BR") {
|
|
706
|
+
const position = this.domAdapter.getLocationByNativeNode(node);
|
|
707
|
+
if (position) {
|
|
708
|
+
if (position.endIndex === offset) {
|
|
709
|
+
const parentNode = node.parentNode;
|
|
710
|
+
return {
|
|
711
|
+
node: parentNode,
|
|
712
|
+
offset: Array.from(parentNode.childNodes).indexOf(node) + 1
|
|
713
|
+
};
|
|
714
|
+
}
|
|
495
715
|
}
|
|
496
716
|
}
|
|
717
|
+
}
|
|
497
718
|
}
|
|
498
719
|
}
|
|
499
|
-
const
|
|
500
|
-
if (
|
|
501
|
-
const
|
|
720
|
+
const current = slot.getContentAtIndex(offset);
|
|
721
|
+
if (current && typeof current !== "string") {
|
|
722
|
+
const nativeNode = this.domAdapter.getNativeNodeByComponent(current);
|
|
502
723
|
return {
|
|
503
|
-
node:
|
|
504
|
-
offset: Array.from(
|
|
724
|
+
node: nativeNode.parentNode,
|
|
725
|
+
offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode)
|
|
505
726
|
};
|
|
506
727
|
}
|
|
507
|
-
for (const
|
|
508
|
-
if (
|
|
509
|
-
if (
|
|
510
|
-
const
|
|
511
|
-
if (
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
728
|
+
for (const node of nodes) {
|
|
729
|
+
if (node instanceof Element) {
|
|
730
|
+
if (node.tagName === "BR") {
|
|
731
|
+
const position2 = this.domAdapter.getLocationByNativeNode(node);
|
|
732
|
+
if (position2) {
|
|
733
|
+
if (position2.startIndex === offset) {
|
|
734
|
+
const parentNode = node.parentNode;
|
|
735
|
+
return {
|
|
736
|
+
node: parentNode,
|
|
737
|
+
offset: Array.from(parentNode.childNodes).indexOf(node)
|
|
738
|
+
};
|
|
739
|
+
}
|
|
517
740
|
}
|
|
518
741
|
}
|
|
519
742
|
continue;
|
|
520
743
|
}
|
|
521
|
-
const
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
744
|
+
const position = this.domAdapter.getLocationByNativeNode(node);
|
|
745
|
+
if (position) {
|
|
746
|
+
if (offset >= position.startIndex && offset <= position.endIndex) {
|
|
747
|
+
return {
|
|
748
|
+
node,
|
|
749
|
+
offset: offset - position.startIndex
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
}
|
|
527
753
|
}
|
|
528
754
|
return null;
|
|
529
755
|
}
|
|
530
|
-
getCorrectedPosition(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
756
|
+
getCorrectedPosition(node, offset, toAfter, excludeNodes = []) {
|
|
757
|
+
excludeNodes.push(node);
|
|
758
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
759
|
+
const containerPosition = this.domAdapter.getLocationByNativeNode(node);
|
|
760
|
+
const childNode = node.childNodes[offset];
|
|
761
|
+
if (childNode) {
|
|
762
|
+
const childPosition = this.domAdapter.getLocationByNativeNode(childNode);
|
|
763
|
+
if (childPosition) {
|
|
764
|
+
if (containerPosition) {
|
|
765
|
+
return {
|
|
766
|
+
slot: childPosition.slot,
|
|
767
|
+
offset: childPosition.startIndex
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
return this.findFocusNode(childNode, toAfter, excludeNodes);
|
|
771
|
+
}
|
|
772
|
+
return this.findFocusNode(childNode, toAfter, excludeNodes);
|
|
539
773
|
}
|
|
540
|
-
const
|
|
541
|
-
if (
|
|
542
|
-
const
|
|
543
|
-
if (
|
|
774
|
+
const prevNode = node.childNodes[offset - 1];
|
|
775
|
+
if (prevNode) {
|
|
776
|
+
const prevPosition = this.domAdapter.getLocationByNativeNode(prevNode);
|
|
777
|
+
if (prevPosition && containerPosition) {
|
|
544
778
|
return {
|
|
545
|
-
slot:
|
|
546
|
-
offset:
|
|
779
|
+
slot: prevPosition.slot,
|
|
780
|
+
offset: prevPosition.endIndex
|
|
547
781
|
};
|
|
782
|
+
}
|
|
548
783
|
}
|
|
549
|
-
if (
|
|
784
|
+
if (containerPosition) {
|
|
550
785
|
return {
|
|
551
|
-
slot:
|
|
552
|
-
offset:
|
|
786
|
+
slot: containerPosition.slot,
|
|
787
|
+
offset: containerPosition.endIndex
|
|
553
788
|
};
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
789
|
+
}
|
|
790
|
+
const nextNode = toAfter ? node.nextSibling : node.previousSibling;
|
|
791
|
+
if (nextNode) {
|
|
792
|
+
return this.findFocusNode(nextNode, toAfter, excludeNodes);
|
|
793
|
+
}
|
|
794
|
+
return this.findFocusNodeByParent(node, toAfter, excludeNodes);
|
|
795
|
+
} else if (node.nodeType === Node.TEXT_NODE) {
|
|
796
|
+
const containerPosition = this.domAdapter.getLocationByNativeNode(node);
|
|
797
|
+
if (containerPosition) {
|
|
559
798
|
return {
|
|
560
|
-
slot:
|
|
561
|
-
offset:
|
|
799
|
+
slot: containerPosition.slot,
|
|
800
|
+
offset: containerPosition.startIndex + offset
|
|
562
801
|
};
|
|
563
|
-
|
|
564
|
-
|
|
802
|
+
}
|
|
803
|
+
const nextNode = toAfter ? node.nextSibling : node.previousSibling;
|
|
804
|
+
if (nextNode) {
|
|
805
|
+
return this.findFocusNode(nextNode, toAfter, excludeNodes);
|
|
806
|
+
}
|
|
807
|
+
return this.findFocusNodeByParent(node, toAfter, excludeNodes);
|
|
565
808
|
}
|
|
566
809
|
return null;
|
|
567
810
|
}
|
|
568
|
-
findFocusNode(
|
|
569
|
-
if (
|
|
570
|
-
const
|
|
571
|
-
|
|
811
|
+
findFocusNode(node, toAfter = false, excludeNodes = []) {
|
|
812
|
+
if (excludeNodes.includes(node)) {
|
|
813
|
+
const next = toAfter ? node.nextSibling : node.previousSibling;
|
|
814
|
+
if (next) {
|
|
815
|
+
return this.findFocusNode(next, toAfter, excludeNodes);
|
|
816
|
+
}
|
|
817
|
+
return this.findFocusNodeByParent(node, toAfter, excludeNodes);
|
|
572
818
|
}
|
|
573
|
-
|
|
574
|
-
const
|
|
575
|
-
if (
|
|
819
|
+
excludeNodes.push(node);
|
|
820
|
+
const position = this.domAdapter.getLocationByNativeNode(node);
|
|
821
|
+
if (position) {
|
|
576
822
|
return {
|
|
577
|
-
slot:
|
|
578
|
-
offset:
|
|
823
|
+
slot: position.slot,
|
|
824
|
+
offset: toAfter ? position.startIndex : position.endIndex
|
|
579
825
|
};
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
826
|
+
}
|
|
827
|
+
const firstChild = toAfter ? node.firstChild : node.lastChild;
|
|
828
|
+
if (firstChild) {
|
|
829
|
+
return this.findFocusNode(firstChild, toAfter, excludeNodes);
|
|
830
|
+
}
|
|
831
|
+
const nextSibling = toAfter ? node.nextSibling : node.previousSibling;
|
|
832
|
+
if (nextSibling) {
|
|
833
|
+
return this.findFocusNode(nextSibling, toAfter, excludeNodes);
|
|
834
|
+
}
|
|
835
|
+
return this.findFocusNodeByParent(node, toAfter, excludeNodes);
|
|
836
|
+
}
|
|
837
|
+
findFocusNodeByParent(node, toAfter, excludeNodes) {
|
|
838
|
+
const parentNode = node.parentNode;
|
|
839
|
+
if (parentNode) {
|
|
840
|
+
const parentPosition = this.domAdapter.getLocationByNativeNode(parentNode);
|
|
841
|
+
if (parentPosition) {
|
|
842
|
+
return {
|
|
843
|
+
slot: parentPosition.slot,
|
|
844
|
+
offset: toAfter ? parentPosition.endIndex : parentPosition.startIndex
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
excludeNodes.push(node);
|
|
848
|
+
return this.findFocusNode(parentNode, toAfter, excludeNodes);
|
|
594
849
|
}
|
|
595
850
|
return null;
|
|
596
851
|
}
|
|
597
852
|
};
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
],
|
|
602
|
-
class
|
|
853
|
+
SelectionBridge = __decorateClass$3([
|
|
854
|
+
Injectable(),
|
|
855
|
+
__decorateParam$1(0, Inject(EDITOR_OPTIONS))
|
|
856
|
+
], SelectionBridge);
|
|
857
|
+
class Input {
|
|
603
858
|
}
|
|
604
|
-
var
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
859
|
+
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
860
|
+
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
861
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
862
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
863
|
+
if (decorator = decorators[i])
|
|
864
|
+
result = decorator(result) || result;
|
|
865
|
+
return result;
|
|
608
866
|
};
|
|
609
|
-
const
|
|
867
|
+
const iframeHTML = `
|
|
610
868
|
<!DOCTYPE html>
|
|
611
869
|
<html>
|
|
612
870
|
<head>
|
|
@@ -625,16 +883,21 @@ const Ct = `
|
|
|
625
883
|
</body>
|
|
626
884
|
</html>
|
|
627
885
|
`;
|
|
628
|
-
class
|
|
629
|
-
constructor(
|
|
630
|
-
this.domRenderer =
|
|
886
|
+
class ExperimentalCaret {
|
|
887
|
+
constructor(domRenderer, scheduler, editorMask) {
|
|
888
|
+
this.domRenderer = domRenderer;
|
|
889
|
+
this.scheduler = scheduler;
|
|
890
|
+
this.editorMask = editorMask;
|
|
891
|
+
this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
|
|
892
|
+
this.onStyleChange = this.styleChangeEvent.asObservable();
|
|
893
|
+
this.elementRef = createElement("div", {
|
|
631
894
|
styles: {
|
|
632
895
|
position: "absolute",
|
|
633
896
|
width: "2px",
|
|
634
897
|
pointerEvents: "none"
|
|
635
898
|
},
|
|
636
899
|
children: [
|
|
637
|
-
this.caret =
|
|
900
|
+
this.caret = createElement("span", {
|
|
638
901
|
styles: {
|
|
639
902
|
width: "100%",
|
|
640
903
|
height: "100%",
|
|
@@ -644,14 +907,16 @@ class xt {
|
|
|
644
907
|
}
|
|
645
908
|
})
|
|
646
909
|
]
|
|
647
|
-
})
|
|
648
|
-
|
|
649
|
-
|
|
910
|
+
});
|
|
911
|
+
this.subscription.add(
|
|
912
|
+
fromEvent(document, "mousedown").subscribe(() => {
|
|
913
|
+
this.flashing = false;
|
|
650
914
|
}),
|
|
651
|
-
|
|
652
|
-
this.flashing =
|
|
915
|
+
fromEvent(document, "mouseup").subscribe(() => {
|
|
916
|
+
this.flashing = true;
|
|
653
917
|
})
|
|
654
|
-
)
|
|
918
|
+
);
|
|
919
|
+
this.editorMask.appendChild(this.elementRef);
|
|
655
920
|
}
|
|
656
921
|
domRenderer;
|
|
657
922
|
scheduler;
|
|
@@ -659,7 +924,7 @@ class xt {
|
|
|
659
924
|
onPositionChange;
|
|
660
925
|
onStyleChange;
|
|
661
926
|
elementRef;
|
|
662
|
-
changeFromSelf =
|
|
927
|
+
changeFromSelf = false;
|
|
663
928
|
getLimit = function() {
|
|
664
929
|
return {
|
|
665
930
|
top: 0,
|
|
@@ -671,116 +936,191 @@ class xt {
|
|
|
671
936
|
}
|
|
672
937
|
timer = null;
|
|
673
938
|
caret;
|
|
674
|
-
set display(
|
|
675
|
-
this._display =
|
|
939
|
+
set display(v) {
|
|
940
|
+
this._display = v;
|
|
941
|
+
this.caret.style.visibility = v ? "visible" : "hidden";
|
|
676
942
|
}
|
|
677
943
|
get display() {
|
|
678
944
|
return this._display;
|
|
679
945
|
}
|
|
680
|
-
_display =
|
|
681
|
-
flashing =
|
|
682
|
-
subscription = new
|
|
683
|
-
positionChangeEvent = new
|
|
684
|
-
styleChangeEvent = new
|
|
946
|
+
_display = true;
|
|
947
|
+
flashing = true;
|
|
948
|
+
subscription = new Subscription();
|
|
949
|
+
positionChangeEvent = new Subject();
|
|
950
|
+
styleChangeEvent = new Subject();
|
|
685
951
|
oldRange = null;
|
|
686
952
|
refresh() {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
953
|
+
if (this.oldRange) {
|
|
954
|
+
this.show(this.oldRange, false);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
show(range, restart) {
|
|
958
|
+
this.oldRange = range;
|
|
959
|
+
if (restart || this.scheduler.lastChangesHasLocalUpdate) {
|
|
960
|
+
clearTimeout(this.timer);
|
|
961
|
+
}
|
|
962
|
+
this.updateCursorPosition(range);
|
|
963
|
+
if (range.collapsed) {
|
|
964
|
+
if (restart || this.scheduler.lastChangesHasLocalUpdate) {
|
|
965
|
+
this.display = true;
|
|
966
|
+
const toggleShowHide = () => {
|
|
967
|
+
this.display = !this.display || !this.flashing;
|
|
968
|
+
this.timer = setTimeout(toggleShowHide, 400);
|
|
695
969
|
};
|
|
696
|
-
clearTimeout(this.timer)
|
|
970
|
+
clearTimeout(this.timer);
|
|
971
|
+
this.timer = setTimeout(toggleShowHide, 400);
|
|
697
972
|
}
|
|
698
|
-
} else
|
|
699
|
-
this.display =
|
|
973
|
+
} else {
|
|
974
|
+
this.display = false;
|
|
975
|
+
clearTimeout(this.timer);
|
|
976
|
+
}
|
|
700
977
|
}
|
|
701
978
|
hide() {
|
|
702
|
-
this.display =
|
|
979
|
+
this.display = false;
|
|
980
|
+
clearTimeout(this.timer);
|
|
981
|
+
this.positionChangeEvent.next(null);
|
|
703
982
|
}
|
|
704
983
|
destroy() {
|
|
705
|
-
clearTimeout(this.timer)
|
|
984
|
+
clearTimeout(this.timer);
|
|
985
|
+
this.subscription.unsubscribe();
|
|
706
986
|
}
|
|
707
|
-
updateCursorPosition(
|
|
708
|
-
const
|
|
709
|
-
|
|
987
|
+
updateCursorPosition(nativeRange) {
|
|
988
|
+
const startContainer = nativeRange.startContainer;
|
|
989
|
+
const node = startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentNode;
|
|
990
|
+
if (node?.nodeType !== Node.ELEMENT_NODE) {
|
|
710
991
|
this.positionChangeEvent.next(null);
|
|
711
992
|
return;
|
|
712
993
|
}
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
const p = document.createElement("span");
|
|
729
|
-
p.style.cssText = "display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size; writing-mode: inherit";
|
|
730
|
-
const g = document.createElement("span");
|
|
731
|
-
g.style.cssText = "position: absolute; left: 0; top: 0; width:0;height:0", p.append(g), e.append(p);
|
|
732
|
-
const y = g.getBoundingClientRect();
|
|
733
|
-
g.style.right = "0", g.style.left = "";
|
|
734
|
-
const R = g.getBoundingClientRect(), A = y.x - R.x, I = y.y - R.y;
|
|
735
|
-
C = Math.atan2(I, A) * 180 / Math.PI, p.remove();
|
|
736
|
-
}
|
|
737
|
-
if ((l === "vertical-lr" || l === "vertical-rl") && (C += 90), Object.assign(this.elementRef.style, {
|
|
738
|
-
left: E + "px",
|
|
739
|
-
top: _ + "px",
|
|
740
|
-
height: h + "px",
|
|
741
|
-
lineHeight: h + "px",
|
|
742
|
-
fontSize: r,
|
|
743
|
-
transform: `rotate(${C}deg)`
|
|
744
|
-
}), this.caret.style.backgroundColor = c === "rgba(0, 0, 0, 0)" ? "#000" : c, this.styleChangeEvent.next({
|
|
745
|
-
height: h + "px",
|
|
746
|
-
lineHeight: h + "px",
|
|
747
|
-
fontSize: r
|
|
748
|
-
}), this.positionChangeEvent.next({
|
|
749
|
-
left: E,
|
|
750
|
-
top: d,
|
|
751
|
-
height: h
|
|
752
|
-
}), this.changeFromSelf) {
|
|
753
|
-
this.changeFromSelf = !1;
|
|
754
|
-
const p = this.elementRef.getBoundingClientRect(), g = this.getScrollContainer(i), y = g === document.documentElement ? { top: 0, bottom: document.documentElement.clientHeight } : g.getBoundingClientRect(), R = this.getLimit(), A = Math.max(R.top, y.top), I = Math.min(R.bottom, y.bottom);
|
|
755
|
-
p.top < A ? g.scrollTop -= A - p.top : p.bottom > I && (g.scrollTop += p.bottom - I);
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
getScrollContainer(t) {
|
|
759
|
-
for (; t; ) {
|
|
760
|
-
if (t instanceof Element) {
|
|
761
|
-
const i = getComputedStyle(t);
|
|
762
|
-
if (i.overflow !== "visible" || i.overflowX !== "visible" || i.overflowY !== "visible")
|
|
763
|
-
return t;
|
|
994
|
+
const compositionNode = this.domRenderer.compositionNode;
|
|
995
|
+
if (compositionNode) {
|
|
996
|
+
nativeRange = nativeRange.cloneRange();
|
|
997
|
+
nativeRange.selectNodeContents(compositionNode);
|
|
998
|
+
nativeRange.collapse();
|
|
999
|
+
}
|
|
1000
|
+
const rect = getLayoutRectByRange(nativeRange);
|
|
1001
|
+
const { fontSize, lineHeight, color, writingMode } = getComputedStyle(node);
|
|
1002
|
+
let height;
|
|
1003
|
+
if (isNaN(+lineHeight)) {
|
|
1004
|
+
const f = parseFloat(lineHeight);
|
|
1005
|
+
if (isNaN(f)) {
|
|
1006
|
+
height = parseFloat(fontSize);
|
|
1007
|
+
} else {
|
|
1008
|
+
height = f;
|
|
764
1009
|
}
|
|
765
|
-
|
|
1010
|
+
} else {
|
|
1011
|
+
height = parseFloat(fontSize) * parseFloat(lineHeight);
|
|
1012
|
+
}
|
|
1013
|
+
const boxHeight = Math.max(Math.floor(Math.max(height, rect.height)), 12);
|
|
1014
|
+
let rectTop = rect.top;
|
|
1015
|
+
if (rect.height < height) {
|
|
1016
|
+
rectTop -= (height - rect.height) / 2;
|
|
1017
|
+
}
|
|
1018
|
+
rectTop = Math.floor(rectTop);
|
|
1019
|
+
const containerRect = this.editorMask.getBoundingClientRect();
|
|
1020
|
+
const top = Math.floor(rectTop - containerRect.top);
|
|
1021
|
+
const left = Math.floor(rect.left + rect.width / 2 - containerRect.left);
|
|
1022
|
+
let rotate = 0;
|
|
1023
|
+
if (nativeRange.collapsed) {
|
|
1024
|
+
rotate = Math.round(Math.atan2(rect.width, rect.height) * 180 / Math.PI);
|
|
1025
|
+
if (rotate !== 0) {
|
|
1026
|
+
const hackEle = document.createElement("span");
|
|
1027
|
+
hackEle.style.cssText = "display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size; writing-mode: inherit";
|
|
1028
|
+
const pointEle = document.createElement("span");
|
|
1029
|
+
pointEle.style.cssText = "position: absolute; left: 0; top: 0; width:0;height:0";
|
|
1030
|
+
hackEle.append(pointEle);
|
|
1031
|
+
node.append(hackEle);
|
|
1032
|
+
const p1 = pointEle.getBoundingClientRect();
|
|
1033
|
+
pointEle.style.right = "0";
|
|
1034
|
+
pointEle.style.left = "";
|
|
1035
|
+
const p2 = pointEle.getBoundingClientRect();
|
|
1036
|
+
const x = p1.x - p2.x;
|
|
1037
|
+
const y = p1.y - p2.y;
|
|
1038
|
+
rotate = Math.atan2(y, x) * 180 / Math.PI;
|
|
1039
|
+
hackEle.remove();
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
if (writingMode === "vertical-lr" || writingMode === "vertical-rl") {
|
|
1043
|
+
rotate += 90;
|
|
1044
|
+
}
|
|
1045
|
+
Object.assign(this.elementRef.style, {
|
|
1046
|
+
left: left + "px",
|
|
1047
|
+
top: top + "px",
|
|
1048
|
+
height: boxHeight + "px",
|
|
1049
|
+
lineHeight: boxHeight + "px",
|
|
1050
|
+
fontSize,
|
|
1051
|
+
transform: `rotate(${rotate}deg)`
|
|
1052
|
+
});
|
|
1053
|
+
this.caret.style.backgroundColor = color === "rgba(0, 0, 0, 0)" ? "#000" : color;
|
|
1054
|
+
this.styleChangeEvent.next({
|
|
1055
|
+
height: boxHeight + "px",
|
|
1056
|
+
lineHeight: boxHeight + "px",
|
|
1057
|
+
fontSize
|
|
1058
|
+
});
|
|
1059
|
+
this.positionChangeEvent.next({
|
|
1060
|
+
left,
|
|
1061
|
+
top: rectTop,
|
|
1062
|
+
height: boxHeight
|
|
1063
|
+
});
|
|
1064
|
+
if (this.changeFromSelf) {
|
|
1065
|
+
this.changeFromSelf = false;
|
|
1066
|
+
const selfRect = this.elementRef.getBoundingClientRect();
|
|
1067
|
+
const scrollContainer = this.getScrollContainer(startContainer);
|
|
1068
|
+
const scrollRect = scrollContainer === document.documentElement ? { top: 0, bottom: document.documentElement.clientHeight } : scrollContainer.getBoundingClientRect();
|
|
1069
|
+
const limit = this.getLimit();
|
|
1070
|
+
const top2 = Math.max(limit.top, scrollRect.top);
|
|
1071
|
+
const bottom = Math.min(limit.bottom, scrollRect.bottom);
|
|
1072
|
+
if (selfRect.top < top2) {
|
|
1073
|
+
scrollContainer.scrollTop -= top2 - selfRect.top;
|
|
1074
|
+
} else if (selfRect.bottom > bottom) {
|
|
1075
|
+
scrollContainer.scrollTop += selfRect.bottom - bottom;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
getScrollContainer(container) {
|
|
1080
|
+
while (container) {
|
|
1081
|
+
if (container instanceof Element) {
|
|
1082
|
+
const styles = getComputedStyle(container);
|
|
1083
|
+
if (styles.overflow !== "visible" || styles.overflowX !== "visible" || styles.overflowY !== "visible") {
|
|
1084
|
+
return container;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
container = container.parentNode;
|
|
766
1088
|
}
|
|
767
1089
|
return document.documentElement;
|
|
768
1090
|
}
|
|
769
1091
|
}
|
|
770
|
-
let
|
|
1092
|
+
let MagicInput = class extends Input {
|
|
771
1093
|
// 有 bug 版本搜狗拼音
|
|
772
|
-
constructor(
|
|
773
|
-
super()
|
|
1094
|
+
constructor(domAdapter, parser, keyboard, commander, selection, controller, scheduler, textbus) {
|
|
1095
|
+
super();
|
|
1096
|
+
this.domAdapter = domAdapter;
|
|
1097
|
+
this.parser = parser;
|
|
1098
|
+
this.keyboard = keyboard;
|
|
1099
|
+
this.commander = commander;
|
|
1100
|
+
this.selection = selection;
|
|
1101
|
+
this.controller = controller;
|
|
1102
|
+
this.scheduler = scheduler;
|
|
1103
|
+
this.textbus = textbus;
|
|
1104
|
+
this.caret = new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK));
|
|
1105
|
+
this.onReady = new Promise((resolve) => {
|
|
774
1106
|
this.subscription.add(
|
|
775
|
-
|
|
776
|
-
const
|
|
777
|
-
|
|
1107
|
+
fromEvent(this.container, "load").subscribe(() => {
|
|
1108
|
+
const doc = this.container.contentDocument;
|
|
1109
|
+
doc.open();
|
|
1110
|
+
doc.write(iframeHTML);
|
|
1111
|
+
doc.close();
|
|
1112
|
+
this.doc = doc;
|
|
1113
|
+
this.init();
|
|
1114
|
+
resolve();
|
|
778
1115
|
}),
|
|
779
|
-
|
|
780
|
-
|
|
1116
|
+
controller.onReadonlyStateChange.subscribe(() => {
|
|
1117
|
+
if (controller.readonly) {
|
|
1118
|
+
this.blur();
|
|
1119
|
+
}
|
|
781
1120
|
})
|
|
782
1121
|
);
|
|
783
|
-
})
|
|
1122
|
+
});
|
|
1123
|
+
this.caret.elementRef.append(this.container);
|
|
784
1124
|
}
|
|
785
1125
|
domAdapter;
|
|
786
1126
|
parser;
|
|
@@ -790,186 +1130,320 @@ let $ = class extends N {
|
|
|
790
1130
|
controller;
|
|
791
1131
|
scheduler;
|
|
792
1132
|
textbus;
|
|
793
|
-
composition =
|
|
1133
|
+
composition = false;
|
|
794
1134
|
onReady;
|
|
795
1135
|
caret;
|
|
796
|
-
set disabled(
|
|
797
|
-
this._disabled =
|
|
1136
|
+
set disabled(b) {
|
|
1137
|
+
this._disabled = b;
|
|
1138
|
+
if (b && this.textarea) {
|
|
1139
|
+
this.textarea.disabled = b;
|
|
1140
|
+
}
|
|
798
1141
|
}
|
|
799
1142
|
get disabled() {
|
|
800
1143
|
return this._disabled;
|
|
801
1144
|
}
|
|
802
|
-
isSafari =
|
|
803
|
-
isFirefox =
|
|
804
|
-
isMac =
|
|
805
|
-
isWindows =
|
|
806
|
-
_disabled =
|
|
1145
|
+
isSafari = isSafari();
|
|
1146
|
+
isFirefox = isFirefox();
|
|
1147
|
+
isMac = isMac();
|
|
1148
|
+
isWindows = isWindows();
|
|
1149
|
+
_disabled = false;
|
|
807
1150
|
container = this.createEditableFrame();
|
|
808
|
-
subscription = new
|
|
1151
|
+
subscription = new Subscription();
|
|
809
1152
|
doc;
|
|
810
1153
|
textarea = null;
|
|
811
|
-
isFocus =
|
|
812
|
-
nativeFocus =
|
|
813
|
-
ignoreComposition =
|
|
814
|
-
focus(
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
}
|
|
1154
|
+
isFocus = false;
|
|
1155
|
+
nativeFocus = false;
|
|
1156
|
+
ignoreComposition = false;
|
|
1157
|
+
focus(range, restart) {
|
|
1158
|
+
if (!this.disabled) {
|
|
1159
|
+
this.caret.show(range, restart);
|
|
1160
|
+
}
|
|
1161
|
+
if (this.controller.readonly) {
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
if (!this.isFocus) {
|
|
1165
|
+
this.textarea?.focus();
|
|
1166
|
+
setTimeout(() => {
|
|
1167
|
+
if (!this.nativeFocus && this.isFocus) {
|
|
1168
|
+
this.reInit();
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
this.isFocus = true;
|
|
818
1173
|
}
|
|
819
1174
|
blur() {
|
|
820
|
-
this.caret.hide()
|
|
1175
|
+
this.caret.hide();
|
|
1176
|
+
this.textarea?.blur();
|
|
1177
|
+
this.isFocus = false;
|
|
821
1178
|
}
|
|
822
1179
|
destroy() {
|
|
823
|
-
this.caret.destroy()
|
|
1180
|
+
this.caret.destroy();
|
|
1181
|
+
this.subscription.unsubscribe();
|
|
824
1182
|
}
|
|
825
|
-
reInit(
|
|
826
|
-
this.subscription.unsubscribe()
|
|
1183
|
+
reInit(delay2 = false) {
|
|
1184
|
+
this.subscription.unsubscribe();
|
|
1185
|
+
this.textarea?.parentNode?.removeChild(this.textarea);
|
|
1186
|
+
this.subscription = new Subscription();
|
|
1187
|
+
this.init();
|
|
1188
|
+
if (delay2) {
|
|
1189
|
+
setTimeout(() => {
|
|
1190
|
+
this.textarea?.focus();
|
|
1191
|
+
});
|
|
1192
|
+
} else {
|
|
827
1193
|
this.textarea?.focus();
|
|
828
|
-
}
|
|
1194
|
+
}
|
|
829
1195
|
}
|
|
830
1196
|
init() {
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1197
|
+
const doc = this.doc;
|
|
1198
|
+
const contentBody = doc.body;
|
|
1199
|
+
const textarea = doc.createElement("textarea");
|
|
1200
|
+
textarea.disabled = this.disabled;
|
|
1201
|
+
contentBody.appendChild(textarea);
|
|
1202
|
+
this.textarea = textarea;
|
|
1203
|
+
this.subscription.add(
|
|
1204
|
+
fromEvent(textarea, "blur").subscribe(() => {
|
|
1205
|
+
this.isFocus = false;
|
|
1206
|
+
this.nativeFocus = false;
|
|
1207
|
+
this.caret.hide();
|
|
1208
|
+
if (this.domAdapter.composition) {
|
|
1209
|
+
const slot = this.domAdapter.composition.slot;
|
|
1210
|
+
this.domAdapter.composition = null;
|
|
1211
|
+
this.domAdapter.compositionNode = null;
|
|
1212
|
+
slot.__changeMarker__.forceMarkDirtied();
|
|
837
1213
|
}
|
|
838
1214
|
}),
|
|
839
|
-
|
|
840
|
-
this.nativeFocus =
|
|
1215
|
+
fromEvent(textarea, "focus").subscribe(() => {
|
|
1216
|
+
this.nativeFocus = true;
|
|
841
1217
|
}),
|
|
842
|
-
this.caret.onStyleChange.subscribe((
|
|
843
|
-
Object.assign(
|
|
1218
|
+
this.caret.onStyleChange.subscribe((style) => {
|
|
1219
|
+
Object.assign(textarea.style, style);
|
|
844
1220
|
})
|
|
845
|
-
)
|
|
1221
|
+
);
|
|
1222
|
+
this.handleInput(textarea);
|
|
1223
|
+
this.handleShortcut(textarea);
|
|
1224
|
+
this.handleDefaultActions(textarea);
|
|
846
1225
|
}
|
|
847
|
-
handleDefaultActions(
|
|
1226
|
+
handleDefaultActions(textarea) {
|
|
848
1227
|
this.subscription.add(
|
|
849
|
-
|
|
850
|
-
this.copyHandler(
|
|
1228
|
+
fromEvent(isFirefox() ? textarea : document, "copy").subscribe((ev) => {
|
|
1229
|
+
this.copyHandler(ev);
|
|
851
1230
|
}),
|
|
852
|
-
|
|
853
|
-
this.pasteHandler(
|
|
1231
|
+
fromEvent(textarea, "paste").subscribe((ev) => {
|
|
1232
|
+
this.pasteHandler(ev);
|
|
854
1233
|
})
|
|
855
1234
|
);
|
|
856
1235
|
}
|
|
857
|
-
copyHandler(
|
|
858
|
-
const
|
|
859
|
-
if (
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1236
|
+
copyHandler(ev) {
|
|
1237
|
+
const selection = this.selection;
|
|
1238
|
+
if (!selection.isSelected) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
|
|
1242
|
+
const content = selection.startSlot.getContentAtIndex(selection.startOffset);
|
|
1243
|
+
if (typeof content === "object") {
|
|
1244
|
+
const clipboardData = ev.clipboardData;
|
|
1245
|
+
const nativeSelection = document.getSelection();
|
|
1246
|
+
const range = nativeSelection.getRangeAt(0);
|
|
1247
|
+
const div = document.createElement("div");
|
|
1248
|
+
const fragment = range.cloneContents();
|
|
1249
|
+
div.append(fragment);
|
|
1250
|
+
clipboardData.setData("text/html", div.innerHTML);
|
|
1251
|
+
clipboardData.setData("text", div.innerText);
|
|
1252
|
+
ev.preventDefault();
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
pasteHandler(ev) {
|
|
1257
|
+
const text = ev.clipboardData.getData("Text");
|
|
1258
|
+
const types = Array.from(ev.clipboardData.types || []);
|
|
1259
|
+
const files = Array.from(ev.clipboardData.files);
|
|
1260
|
+
if (types.every((type) => type === "Files") && files.length) {
|
|
1261
|
+
Promise.all(files.filter((i) => {
|
|
1262
|
+
return /image/i.test(i.type);
|
|
1263
|
+
}).map((item) => {
|
|
1264
|
+
const reader = new FileReader();
|
|
1265
|
+
return new Promise((resolve) => {
|
|
1266
|
+
reader.onload = (event) => {
|
|
1267
|
+
resolve(event.target.result);
|
|
1268
|
+
};
|
|
1269
|
+
reader.readAsDataURL(item);
|
|
873
1270
|
});
|
|
874
|
-
})).then((
|
|
875
|
-
const
|
|
876
|
-
|
|
877
|
-
|
|
1271
|
+
})).then((urls) => {
|
|
1272
|
+
const html = urls.map((i) => {
|
|
1273
|
+
return `<img src=${i}>`;
|
|
1274
|
+
}).join("");
|
|
1275
|
+
this.paste(html, text);
|
|
1276
|
+
});
|
|
1277
|
+
ev.preventDefault();
|
|
878
1278
|
return;
|
|
879
1279
|
}
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
1280
|
+
const div = this.doc.createElement("div");
|
|
1281
|
+
div.style.cssText = "width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0";
|
|
1282
|
+
div.contentEditable = "true";
|
|
1283
|
+
this.doc.body.appendChild(div);
|
|
1284
|
+
div.focus();
|
|
1285
|
+
setTimeout(() => {
|
|
1286
|
+
this.doc.body.removeChild(div);
|
|
1287
|
+
div.style.cssText = "";
|
|
1288
|
+
this.paste(div, text);
|
|
883
1289
|
});
|
|
884
1290
|
}
|
|
885
|
-
paste(
|
|
886
|
-
const
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1291
|
+
paste(dom, text) {
|
|
1292
|
+
const slot = this.parser.parse(dom, new Slot([
|
|
1293
|
+
ContentType.BlockComponent,
|
|
1294
|
+
ContentType.InlineComponent,
|
|
1295
|
+
ContentType.Text
|
|
890
1296
|
]));
|
|
891
|
-
this.commander.paste(
|
|
1297
|
+
this.commander.paste(slot, text);
|
|
892
1298
|
}
|
|
893
|
-
handleShortcut(
|
|
894
|
-
let
|
|
1299
|
+
handleShortcut(textarea) {
|
|
1300
|
+
let isWriting = false;
|
|
1301
|
+
let isIgnore = false;
|
|
895
1302
|
this.subscription.add(
|
|
896
|
-
|
|
897
|
-
|
|
1303
|
+
fromEvent(textarea, "compositionstart").subscribe(() => {
|
|
1304
|
+
isWriting = true;
|
|
898
1305
|
}),
|
|
899
|
-
|
|
900
|
-
|
|
1306
|
+
fromEvent(textarea, "compositionend").subscribe(() => {
|
|
1307
|
+
isWriting = false;
|
|
901
1308
|
}),
|
|
902
|
-
|
|
903
|
-
this.ignoreComposition =
|
|
1309
|
+
fromEvent(textarea, "beforeinput").subscribe((ev) => {
|
|
1310
|
+
this.ignoreComposition = false;
|
|
1311
|
+
if (this.isSafari) {
|
|
1312
|
+
if (ev.inputType === "insertFromComposition") {
|
|
1313
|
+
isIgnore = true;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
904
1316
|
}),
|
|
905
|
-
|
|
906
|
-
this.
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1317
|
+
fromEvent(textarea, "keydown").pipe(filter(() => {
|
|
1318
|
+
if (this.isSafari && isIgnore) {
|
|
1319
|
+
isIgnore = false;
|
|
1320
|
+
return false;
|
|
1321
|
+
}
|
|
1322
|
+
return !isWriting;
|
|
1323
|
+
})).subscribe((ev) => {
|
|
1324
|
+
this.ignoreComposition = false;
|
|
1325
|
+
let key = ev.key;
|
|
1326
|
+
const keys = ")!@#$%^Z&*(";
|
|
1327
|
+
const b = key === "Process" && /Digit\d/.test(ev.code) && ev.shiftKey;
|
|
1328
|
+
if (b) {
|
|
1329
|
+
key = keys.charAt(+ev.code.substring(5));
|
|
1330
|
+
ev.preventDefault();
|
|
1331
|
+
}
|
|
1332
|
+
this.caret.changeFromSelf = true;
|
|
1333
|
+
const is = this.keyboard.execShortcut({
|
|
1334
|
+
key,
|
|
1335
|
+
altKey: ev.altKey,
|
|
1336
|
+
shiftKey: ev.shiftKey,
|
|
1337
|
+
modKey: this.isMac ? ev.metaKey : ev.ctrlKey,
|
|
913
1338
|
agent: {
|
|
914
|
-
key:
|
|
915
|
-
code:
|
|
916
|
-
keyCode:
|
|
1339
|
+
key: ev.key,
|
|
1340
|
+
code: ev.code,
|
|
1341
|
+
keyCode: ev.keyCode
|
|
917
1342
|
}
|
|
918
|
-
})
|
|
1343
|
+
});
|
|
1344
|
+
if (is) {
|
|
1345
|
+
this.ignoreComposition = true;
|
|
1346
|
+
ev.preventDefault();
|
|
1347
|
+
} else {
|
|
1348
|
+
this.caret.changeFromSelf = false;
|
|
1349
|
+
}
|
|
919
1350
|
})
|
|
920
1351
|
);
|
|
921
1352
|
}
|
|
922
|
-
handleInput(
|
|
923
|
-
let
|
|
1353
|
+
handleInput(textarea) {
|
|
1354
|
+
let startIndex = 0;
|
|
924
1355
|
this.subscription.add(
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1356
|
+
fromEvent(textarea, "compositionstart").pipe(filter(() => {
|
|
1357
|
+
return !this.ignoreComposition;
|
|
1358
|
+
})).subscribe(() => {
|
|
1359
|
+
if (!this.selection.isCollapsed) {
|
|
1360
|
+
this.caret.changeFromSelf = true;
|
|
1361
|
+
this.commander.delete();
|
|
1362
|
+
}
|
|
1363
|
+
this.composition = true;
|
|
1364
|
+
startIndex = this.selection.startOffset;
|
|
1365
|
+
const startSlot = this.selection.startSlot;
|
|
1366
|
+
const event = new Event(startSlot, {
|
|
1367
|
+
index: startIndex
|
|
929
1368
|
});
|
|
930
|
-
|
|
1369
|
+
invokeListener(startSlot.parent, "onCompositionStart", event);
|
|
931
1370
|
}),
|
|
932
|
-
|
|
933
|
-
|
|
1371
|
+
fromEvent(textarea, "compositionupdate").pipe(filter(() => {
|
|
1372
|
+
return !this.ignoreComposition;
|
|
1373
|
+
})).pipe(distinctUntilChanged((prev, next) => {
|
|
1374
|
+
return prev.data !== next.data;
|
|
1375
|
+
})).subscribe((ev) => {
|
|
1376
|
+
if (ev.data === " ") {
|
|
934
1377
|
return;
|
|
935
|
-
|
|
1378
|
+
}
|
|
1379
|
+
const startSlot = this.selection.startSlot;
|
|
936
1380
|
this.domAdapter.composition = {
|
|
937
|
-
slot:
|
|
938
|
-
text:
|
|
939
|
-
offset:
|
|
940
|
-
index:
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1381
|
+
slot: startSlot,
|
|
1382
|
+
text: ev.data,
|
|
1383
|
+
offset: ev.data.length,
|
|
1384
|
+
index: startIndex
|
|
1385
|
+
};
|
|
1386
|
+
this.caret.changeFromSelf = true;
|
|
1387
|
+
this.caret.refresh();
|
|
1388
|
+
const event = new Event(startSlot, {
|
|
1389
|
+
index: startIndex,
|
|
1390
|
+
data: ev.data
|
|
945
1391
|
});
|
|
946
|
-
|
|
1392
|
+
invokeListener(startSlot.parent, "onCompositionUpdate", event);
|
|
1393
|
+
startSlot.__changeMarker__.forceMarkDirtied();
|
|
947
1394
|
})
|
|
948
1395
|
);
|
|
949
|
-
let
|
|
1396
|
+
let isCompositionEnd = false;
|
|
950
1397
|
this.subscription.add(
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1398
|
+
merge(
|
|
1399
|
+
fromEvent(textarea, "beforeinput").pipe(
|
|
1400
|
+
filter((ev) => {
|
|
1401
|
+
ev.preventDefault();
|
|
1402
|
+
if (this.isFirefox && ev.inputType === "insertFromPaste") {
|
|
1403
|
+
return false;
|
|
1404
|
+
}
|
|
1405
|
+
if (this.isSafari) {
|
|
1406
|
+
isCompositionEnd = ev.inputType === "insertFromComposition";
|
|
1407
|
+
return ev.inputType === "insertText" || ev.inputType === "insertFromComposition";
|
|
1408
|
+
}
|
|
1409
|
+
return !ev.isComposing && !!ev.data;
|
|
1410
|
+
}),
|
|
1411
|
+
map((ev) => {
|
|
1412
|
+
return ev.data;
|
|
1413
|
+
})
|
|
955
1414
|
),
|
|
956
|
-
this.isSafari ? new
|
|
957
|
-
|
|
1415
|
+
this.isSafari ? new Observable() : fromEvent(textarea, "compositionend").pipe(filter(() => {
|
|
1416
|
+
return !this.ignoreComposition;
|
|
1417
|
+
})).pipe(
|
|
1418
|
+
map((ev) => {
|
|
1419
|
+
isCompositionEnd = true;
|
|
1420
|
+
ev.preventDefault();
|
|
1421
|
+
textarea.value = "";
|
|
1422
|
+
return ev.data;
|
|
1423
|
+
})
|
|
958
1424
|
)
|
|
959
|
-
).subscribe((
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1425
|
+
).subscribe((text) => {
|
|
1426
|
+
this.composition = false;
|
|
1427
|
+
this.domAdapter.composition = null;
|
|
1428
|
+
if (text) {
|
|
1429
|
+
this.caret.changeFromSelf = true;
|
|
1430
|
+
this.commander.write(text);
|
|
1431
|
+
} else {
|
|
1432
|
+
this.selection.startSlot?.__changeMarker__.forceMarkDirtied();
|
|
1433
|
+
}
|
|
1434
|
+
if (isCompositionEnd) {
|
|
1435
|
+
const startSlot = this.selection.startSlot;
|
|
1436
|
+
if (startSlot) {
|
|
1437
|
+
const event = new Event(startSlot, null);
|
|
1438
|
+
invokeListener(startSlot.parent, "onCompositionEnd", event);
|
|
965
1439
|
}
|
|
966
1440
|
}
|
|
967
|
-
|
|
1441
|
+
isCompositionEnd = false;
|
|
968
1442
|
})
|
|
969
1443
|
);
|
|
970
1444
|
}
|
|
971
1445
|
createEditableFrame() {
|
|
972
|
-
return
|
|
1446
|
+
return createElement("iframe", {
|
|
973
1447
|
attrs: {
|
|
974
1448
|
scrolling: "no"
|
|
975
1449
|
},
|
|
@@ -984,23 +1458,41 @@ let $ = class extends N {
|
|
|
984
1458
|
});
|
|
985
1459
|
}
|
|
986
1460
|
};
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
],
|
|
990
|
-
var
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1461
|
+
MagicInput = __decorateClass$2([
|
|
1462
|
+
Injectable()
|
|
1463
|
+
], MagicInput);
|
|
1464
|
+
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
1465
|
+
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
1466
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
1467
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
1468
|
+
if (decorator = decorators[i])
|
|
1469
|
+
result = decorator(result) || result;
|
|
1470
|
+
return result;
|
|
1471
|
+
};
|
|
1472
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
1473
|
+
class CollaborateSelectionAwarenessDelegate {
|
|
996
1474
|
}
|
|
997
|
-
let
|
|
998
|
-
constructor(
|
|
999
|
-
this.nativeSelection =
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1475
|
+
let CollaborateCursor = class {
|
|
1476
|
+
constructor(textbus, nativeSelection, scheduler, selection, awarenessDelegate) {
|
|
1477
|
+
this.nativeSelection = nativeSelection;
|
|
1478
|
+
this.scheduler = scheduler;
|
|
1479
|
+
this.selection = selection;
|
|
1480
|
+
this.awarenessDelegate = awarenessDelegate;
|
|
1481
|
+
this.container = textbus.get(VIEW_CONTAINER);
|
|
1482
|
+
this.canvasContainer.append(this.canvas);
|
|
1483
|
+
this.host.append(this.canvasContainer, this.tooltips);
|
|
1484
|
+
this.container.prepend(this.host);
|
|
1485
|
+
this.subscription.add(this.onRectsChange.subscribe((rects) => {
|
|
1486
|
+
for (const rect of rects) {
|
|
1487
|
+
this.context.fillStyle = rect.color;
|
|
1488
|
+
this.context.beginPath();
|
|
1489
|
+
this.context.rect(rect.left, rect.top, rect.width, rect.height);
|
|
1490
|
+
this.context.fill();
|
|
1491
|
+
this.context.closePath();
|
|
1492
|
+
}
|
|
1493
|
+
}), fromEvent(window, "resize").subscribe(() => {
|
|
1494
|
+
this.canvas.style.height = document.documentElement.clientHeight + "px";
|
|
1495
|
+
this.refresh();
|
|
1004
1496
|
}), this.scheduler.onDocChanged.subscribe(() => {
|
|
1005
1497
|
this.refresh();
|
|
1006
1498
|
}));
|
|
@@ -1009,7 +1501,7 @@ let k = class {
|
|
|
1009
1501
|
scheduler;
|
|
1010
1502
|
selection;
|
|
1011
1503
|
awarenessDelegate;
|
|
1012
|
-
host =
|
|
1504
|
+
host = createElement("div", {
|
|
1013
1505
|
styles: {
|
|
1014
1506
|
position: "absolute",
|
|
1015
1507
|
left: 0,
|
|
@@ -1020,7 +1512,7 @@ let k = class {
|
|
|
1020
1512
|
zIndex: 1
|
|
1021
1513
|
}
|
|
1022
1514
|
});
|
|
1023
|
-
canvasContainer =
|
|
1515
|
+
canvasContainer = createElement("div", {
|
|
1024
1516
|
styles: {
|
|
1025
1517
|
position: "absolute",
|
|
1026
1518
|
left: 0,
|
|
@@ -1030,7 +1522,7 @@ let k = class {
|
|
|
1030
1522
|
overflow: "hidden"
|
|
1031
1523
|
}
|
|
1032
1524
|
});
|
|
1033
|
-
canvas =
|
|
1525
|
+
canvas = createElement("canvas", {
|
|
1034
1526
|
styles: {
|
|
1035
1527
|
position: "absolute",
|
|
1036
1528
|
opacity: 0.5,
|
|
@@ -1042,7 +1534,7 @@ let k = class {
|
|
|
1042
1534
|
}
|
|
1043
1535
|
});
|
|
1044
1536
|
context = this.canvas.getContext("2d");
|
|
1045
|
-
tooltips =
|
|
1537
|
+
tooltips = createElement("div", {
|
|
1046
1538
|
styles: {
|
|
1047
1539
|
position: "absolute",
|
|
1048
1540
|
left: 0,
|
|
@@ -1054,8 +1546,8 @@ let k = class {
|
|
|
1054
1546
|
zIndex: 10
|
|
1055
1547
|
}
|
|
1056
1548
|
});
|
|
1057
|
-
onRectsChange = new
|
|
1058
|
-
subscription = new
|
|
1549
|
+
onRectsChange = new Subject();
|
|
1550
|
+
subscription = new Subscription();
|
|
1059
1551
|
selectionCursors = [];
|
|
1060
1552
|
container;
|
|
1061
1553
|
ratio = window.devicePixelRatio || 1;
|
|
@@ -1072,89 +1564,122 @@ let k = class {
|
|
|
1072
1564
|
* 根据远程用户光标位置,绘制协作光标
|
|
1073
1565
|
* @param paths
|
|
1074
1566
|
*/
|
|
1075
|
-
draw(
|
|
1076
|
-
this.selectionCursors =
|
|
1077
|
-
const
|
|
1078
|
-
this.canvas.style.top =
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1567
|
+
draw(paths) {
|
|
1568
|
+
this.selectionCursors = paths;
|
|
1569
|
+
const containerRect = this.container.getBoundingClientRect();
|
|
1570
|
+
this.canvas.style.top = containerRect.top * -1 + "px";
|
|
1571
|
+
this.canvas.width = this.canvas.offsetWidth * this.ratio;
|
|
1572
|
+
this.canvas.height = this.canvas.offsetHeight * this.ratio;
|
|
1573
|
+
this.context.scale(this.ratio, this.ratio);
|
|
1574
|
+
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
1575
|
+
const users = [];
|
|
1576
|
+
paths.filter((i) => {
|
|
1577
|
+
return i.selection.anchor.length && i.selection.focus.length;
|
|
1578
|
+
}).forEach((item) => {
|
|
1579
|
+
const anchorPaths = [...item.selection.anchor];
|
|
1580
|
+
const focusPaths = [...item.selection.focus];
|
|
1581
|
+
const anchorOffset = anchorPaths.pop();
|
|
1582
|
+
const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
|
|
1583
|
+
const focusOffset = focusPaths.pop();
|
|
1584
|
+
const focusSlot = this.selection.findSlotByPaths(focusPaths);
|
|
1585
|
+
if (!anchorSlot || !focusSlot) {
|
|
1083
1586
|
return;
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1587
|
+
}
|
|
1588
|
+
const { focus, anchor } = this.nativeSelection.getPositionByRange({
|
|
1589
|
+
focusOffset,
|
|
1590
|
+
anchorOffset,
|
|
1591
|
+
focusSlot,
|
|
1592
|
+
anchorSlot
|
|
1089
1593
|
});
|
|
1090
|
-
if (!
|
|
1594
|
+
if (!focus || !anchor) {
|
|
1091
1595
|
return;
|
|
1092
|
-
|
|
1596
|
+
}
|
|
1597
|
+
const nativeRange = document.createRange();
|
|
1093
1598
|
try {
|
|
1094
|
-
|
|
1095
|
-
|
|
1599
|
+
nativeRange.setStart(anchor.node, anchor.offset);
|
|
1600
|
+
nativeRange.setEnd(focus.node, focus.offset);
|
|
1601
|
+
} catch (e) {
|
|
1096
1602
|
return;
|
|
1097
1603
|
}
|
|
1098
|
-
(
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1604
|
+
if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
|
|
1605
|
+
nativeRange.setStart(focus.node, focus.offset);
|
|
1606
|
+
nativeRange.setEnd(anchor.node, anchor.offset);
|
|
1607
|
+
}
|
|
1608
|
+
let rects = false;
|
|
1609
|
+
if (this.awarenessDelegate) {
|
|
1610
|
+
rects = this.awarenessDelegate.getRects({
|
|
1611
|
+
focusOffset,
|
|
1612
|
+
anchorOffset,
|
|
1613
|
+
focusSlot,
|
|
1614
|
+
anchorSlot
|
|
1615
|
+
}, nativeRange, item);
|
|
1616
|
+
}
|
|
1617
|
+
if (!rects) {
|
|
1618
|
+
rects = nativeRange.getClientRects();
|
|
1619
|
+
}
|
|
1620
|
+
const selectionRects = [];
|
|
1621
|
+
for (let i = rects.length - 1; i >= 0; i--) {
|
|
1622
|
+
const rect2 = rects[i];
|
|
1623
|
+
selectionRects.push({
|
|
1624
|
+
color: item.color,
|
|
1625
|
+
username: item.username,
|
|
1626
|
+
left: rect2.left - containerRect.left,
|
|
1627
|
+
top: rect2.top,
|
|
1628
|
+
width: rect2.width,
|
|
1629
|
+
height: rect2.height
|
|
1116
1630
|
});
|
|
1117
1631
|
}
|
|
1118
|
-
this.onRectsChange.next(
|
|
1119
|
-
const
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1632
|
+
this.onRectsChange.next(selectionRects);
|
|
1633
|
+
const cursorRange = nativeRange.cloneRange();
|
|
1634
|
+
cursorRange.setStart(focus.node, focus.offset);
|
|
1635
|
+
cursorRange.collapse(true);
|
|
1636
|
+
const cursorRect = getLayoutRectByRange(cursorRange);
|
|
1637
|
+
const rect = {
|
|
1638
|
+
username: item.username,
|
|
1639
|
+
color: item.color,
|
|
1640
|
+
left: cursorRect.left - containerRect.left,
|
|
1641
|
+
top: cursorRect.top - containerRect.top,
|
|
1126
1642
|
width: 1,
|
|
1127
|
-
height:
|
|
1643
|
+
height: cursorRect.height
|
|
1128
1644
|
};
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1645
|
+
if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
users.push(rect);
|
|
1649
|
+
});
|
|
1650
|
+
this.drawUserCursor(users);
|
|
1651
|
+
}
|
|
1652
|
+
drawUserCursor(rects) {
|
|
1653
|
+
for (let i = 0; i < rects.length; i++) {
|
|
1654
|
+
const rect = rects[i];
|
|
1655
|
+
const { cursor, userTip, anchor } = this.getUserCursor(i);
|
|
1656
|
+
Object.assign(cursor.style, {
|
|
1657
|
+
left: rect.left + "px",
|
|
1658
|
+
top: rect.top + "px",
|
|
1659
|
+
width: rect.width + "px",
|
|
1660
|
+
height: rect.height + "px",
|
|
1661
|
+
background: rect.color,
|
|
1141
1662
|
display: "block"
|
|
1142
|
-
})
|
|
1663
|
+
});
|
|
1664
|
+
anchor.style.background = rect.color;
|
|
1665
|
+
userTip.innerText = rect.username;
|
|
1666
|
+
userTip.style.background = rect.color;
|
|
1667
|
+
}
|
|
1668
|
+
for (let i = rects.length; i < this.tooltips.children.length; i++) {
|
|
1669
|
+
this.tooltips.removeChild(this.tooltips.children[i]);
|
|
1143
1670
|
}
|
|
1144
|
-
for (let t = s.length; t < this.tooltips.children.length; t++)
|
|
1145
|
-
this.tooltips.removeChild(this.tooltips.children[t]);
|
|
1146
1671
|
}
|
|
1147
|
-
getUserCursor(
|
|
1148
|
-
let
|
|
1149
|
-
if (
|
|
1150
|
-
const
|
|
1672
|
+
getUserCursor(index) {
|
|
1673
|
+
let child = this.tooltips.children[index];
|
|
1674
|
+
if (child) {
|
|
1675
|
+
const anchor2 = child.children[0];
|
|
1151
1676
|
return {
|
|
1152
|
-
cursor:
|
|
1153
|
-
anchor:
|
|
1154
|
-
userTip:
|
|
1677
|
+
cursor: child,
|
|
1678
|
+
anchor: anchor2,
|
|
1679
|
+
userTip: anchor2.children[0]
|
|
1155
1680
|
};
|
|
1156
1681
|
}
|
|
1157
|
-
const
|
|
1682
|
+
const userTip = createElement("span", {
|
|
1158
1683
|
styles: {
|
|
1159
1684
|
position: "absolute",
|
|
1160
1685
|
left: "50%",
|
|
@@ -1169,7 +1694,8 @@ let k = class {
|
|
|
1169
1694
|
padding: "3px 5px",
|
|
1170
1695
|
pointerEvents: "none"
|
|
1171
1696
|
}
|
|
1172
|
-
})
|
|
1697
|
+
});
|
|
1698
|
+
const anchor = createElement("span", {
|
|
1173
1699
|
styles: {
|
|
1174
1700
|
position: "absolute",
|
|
1175
1701
|
top: "-2px",
|
|
@@ -1180,53 +1706,61 @@ let k = class {
|
|
|
1180
1706
|
pointerEvents: "auto",
|
|
1181
1707
|
pointer: "cursor"
|
|
1182
1708
|
},
|
|
1183
|
-
children: [
|
|
1709
|
+
children: [userTip]
|
|
1184
1710
|
});
|
|
1185
|
-
|
|
1711
|
+
child = createElement("span", {
|
|
1186
1712
|
styles: {
|
|
1187
1713
|
position: "absolute"
|
|
1188
1714
|
},
|
|
1189
1715
|
children: [
|
|
1190
|
-
|
|
1716
|
+
anchor
|
|
1191
1717
|
]
|
|
1192
|
-
})
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1718
|
+
});
|
|
1719
|
+
this.tooltips.append(child);
|
|
1720
|
+
return {
|
|
1721
|
+
cursor: child,
|
|
1722
|
+
anchor,
|
|
1723
|
+
userTip
|
|
1196
1724
|
};
|
|
1197
1725
|
}
|
|
1198
1726
|
};
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
],
|
|
1203
|
-
var
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1727
|
+
CollaborateCursor = __decorateClass$1([
|
|
1728
|
+
Injectable(),
|
|
1729
|
+
__decorateParam(4, Optional())
|
|
1730
|
+
], CollaborateCursor);
|
|
1731
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1732
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
1733
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
1734
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
1735
|
+
if (decorator = decorators[i])
|
|
1736
|
+
result = decorator(result) || result;
|
|
1737
|
+
return result;
|
|
1207
1738
|
};
|
|
1208
|
-
class
|
|
1739
|
+
class NativeCaret {
|
|
1209
1740
|
onPositionChange;
|
|
1210
|
-
set nativeRange(
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1741
|
+
set nativeRange(range) {
|
|
1742
|
+
this._nativeRange = range;
|
|
1743
|
+
if (range) {
|
|
1744
|
+
const r = range.cloneRange();
|
|
1745
|
+
r.collapse(true);
|
|
1746
|
+
const rect = getLayoutRectByRange(r);
|
|
1215
1747
|
this.positionChangeEvent.next({
|
|
1216
|
-
left:
|
|
1217
|
-
top:
|
|
1218
|
-
height:
|
|
1748
|
+
left: rect.left,
|
|
1749
|
+
top: rect.top,
|
|
1750
|
+
height: rect.height
|
|
1219
1751
|
});
|
|
1220
|
-
} else
|
|
1752
|
+
} else {
|
|
1221
1753
|
this.positionChangeEvent.next(null);
|
|
1754
|
+
}
|
|
1222
1755
|
}
|
|
1223
1756
|
get nativeRange() {
|
|
1224
1757
|
return this._nativeRange;
|
|
1225
1758
|
}
|
|
1226
1759
|
get rect() {
|
|
1227
1760
|
if (this.nativeRange) {
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1761
|
+
const range = this.nativeRange.cloneRange();
|
|
1762
|
+
range.collapse(true);
|
|
1763
|
+
return getLayoutRectByRange(range);
|
|
1230
1764
|
}
|
|
1231
1765
|
return {
|
|
1232
1766
|
left: 0,
|
|
@@ -1237,24 +1771,39 @@ class Tt {
|
|
|
1237
1771
|
}
|
|
1238
1772
|
_nativeRange = null;
|
|
1239
1773
|
subs = [];
|
|
1240
|
-
positionChangeEvent = new
|
|
1774
|
+
positionChangeEvent = new Subject();
|
|
1241
1775
|
constructor() {
|
|
1242
|
-
this.onPositionChange = this.positionChangeEvent.pipe(
|
|
1776
|
+
this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
|
|
1243
1777
|
}
|
|
1244
1778
|
refresh() {
|
|
1245
1779
|
}
|
|
1246
1780
|
destroy() {
|
|
1247
|
-
this.subs.forEach((
|
|
1781
|
+
this.subs.forEach((i) => i.unsubscribe());
|
|
1782
|
+
this.subs = [];
|
|
1248
1783
|
}
|
|
1249
1784
|
}
|
|
1250
|
-
let
|
|
1785
|
+
let NativeInput = class extends Input {
|
|
1251
1786
|
// 有 bug 版本搜狗拼音
|
|
1252
|
-
constructor(
|
|
1253
|
-
super()
|
|
1254
|
-
|
|
1255
|
-
|
|
1787
|
+
constructor(textbus, parser, selection, keyboard, domAdapter, commander, controller) {
|
|
1788
|
+
super();
|
|
1789
|
+
this.parser = parser;
|
|
1790
|
+
this.selection = selection;
|
|
1791
|
+
this.keyboard = keyboard;
|
|
1792
|
+
this.domAdapter = domAdapter;
|
|
1793
|
+
this.commander = commander;
|
|
1794
|
+
this.controller = controller;
|
|
1795
|
+
this.documentView = textbus.get(VIEW_DOCUMENT);
|
|
1796
|
+
if (!controller.readonly) {
|
|
1797
|
+
this.documentView.contentEditable = "true";
|
|
1798
|
+
}
|
|
1799
|
+
this.subscription.add(
|
|
1800
|
+
controller.onReadonlyStateChange.subscribe(() => {
|
|
1801
|
+
this.documentView.contentEditable = controller.readonly ? "false" : "true";
|
|
1256
1802
|
})
|
|
1257
|
-
)
|
|
1803
|
+
);
|
|
1804
|
+
this.handleShortcut(this.documentView);
|
|
1805
|
+
this.handleInput(this.documentView);
|
|
1806
|
+
this.handleDefaultActions(this.documentView);
|
|
1258
1807
|
}
|
|
1259
1808
|
parser;
|
|
1260
1809
|
selection;
|
|
@@ -1262,261 +1811,393 @@ let W = class extends N {
|
|
|
1262
1811
|
domAdapter;
|
|
1263
1812
|
commander;
|
|
1264
1813
|
controller;
|
|
1265
|
-
caret = new
|
|
1266
|
-
composition =
|
|
1814
|
+
caret = new NativeCaret();
|
|
1815
|
+
composition = false;
|
|
1267
1816
|
// compositionState: CompositionState | null = null
|
|
1268
1817
|
onReady = Promise.resolve();
|
|
1269
|
-
set disabled(
|
|
1270
|
-
|
|
1818
|
+
set disabled(b) {
|
|
1819
|
+
this._disabled = b;
|
|
1820
|
+
if (this.controller.readonly) {
|
|
1271
1821
|
this.documentView.contentEditable = "false";
|
|
1272
1822
|
return;
|
|
1273
1823
|
}
|
|
1274
|
-
this.documentView.contentEditable =
|
|
1824
|
+
this.documentView.contentEditable = b ? "false" : "true";
|
|
1275
1825
|
}
|
|
1276
1826
|
get disabled() {
|
|
1277
1827
|
return this._disabled;
|
|
1278
1828
|
}
|
|
1279
|
-
_disabled =
|
|
1829
|
+
_disabled = false;
|
|
1280
1830
|
documentView;
|
|
1281
1831
|
nativeSelection = document.getSelection();
|
|
1282
|
-
subscription = new
|
|
1832
|
+
subscription = new Subscription();
|
|
1283
1833
|
nativeRange = null;
|
|
1284
|
-
isSafari =
|
|
1285
|
-
isMac =
|
|
1286
|
-
isMobileBrowser =
|
|
1287
|
-
ignoreComposition =
|
|
1288
|
-
focus(
|
|
1289
|
-
this.controller.readonly
|
|
1834
|
+
isSafari = isSafari();
|
|
1835
|
+
isMac = isMac();
|
|
1836
|
+
isMobileBrowser = isMobileBrowser();
|
|
1837
|
+
ignoreComposition = false;
|
|
1838
|
+
focus(nativeRange) {
|
|
1839
|
+
if (this.controller.readonly) {
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
this.caret.nativeRange = nativeRange;
|
|
1843
|
+
this.nativeRange = nativeRange;
|
|
1290
1844
|
}
|
|
1291
1845
|
blur() {
|
|
1292
|
-
if (this.nativeRange && this.nativeSelection.rangeCount > 0
|
|
1293
|
-
this.nativeSelection.
|
|
1294
|
-
|
|
1846
|
+
if (this.nativeRange && this.nativeSelection.rangeCount > 0) {
|
|
1847
|
+
const current = this.nativeSelection.getRangeAt(0);
|
|
1848
|
+
if (current === this.nativeRange) {
|
|
1849
|
+
this.nativeSelection.removeAllRanges();
|
|
1850
|
+
this.nativeRange = null;
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1295
1853
|
}
|
|
1296
1854
|
}
|
|
1297
1855
|
destroy() {
|
|
1298
|
-
this.caret.destroy()
|
|
1856
|
+
this.caret.destroy();
|
|
1857
|
+
this.subscription.unsubscribe();
|
|
1299
1858
|
}
|
|
1300
|
-
handleDefaultActions(
|
|
1859
|
+
handleDefaultActions(textarea) {
|
|
1301
1860
|
this.subscription.add(
|
|
1302
|
-
|
|
1303
|
-
this.copyHandler(
|
|
1861
|
+
fromEvent(isFirefox() ? textarea : document, "copy").subscribe((ev) => {
|
|
1862
|
+
this.copyHandler(ev);
|
|
1304
1863
|
}),
|
|
1305
|
-
|
|
1306
|
-
this.pasteHandler(
|
|
1864
|
+
fromEvent(textarea, "paste").subscribe((ev) => {
|
|
1865
|
+
this.pasteHandler(ev);
|
|
1307
1866
|
})
|
|
1308
1867
|
);
|
|
1309
1868
|
}
|
|
1310
|
-
copyHandler(
|
|
1311
|
-
const
|
|
1312
|
-
if (
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
const
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1869
|
+
copyHandler(ev) {
|
|
1870
|
+
const selection = this.selection;
|
|
1871
|
+
if (!selection.isSelected) {
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
|
|
1875
|
+
const content = selection.startSlot.getContentAtIndex(selection.startOffset);
|
|
1876
|
+
if (typeof content === "object") {
|
|
1877
|
+
const clipboardData = ev.clipboardData;
|
|
1878
|
+
const nativeSelection = document.getSelection();
|
|
1879
|
+
const range = nativeSelection.getRangeAt(0);
|
|
1880
|
+
const div = document.createElement("div");
|
|
1881
|
+
const fragment = range.cloneContents();
|
|
1882
|
+
div.append(fragment);
|
|
1883
|
+
clipboardData.setData("text/html", div.innerHTML);
|
|
1884
|
+
clipboardData.setData("text", div.innerText);
|
|
1885
|
+
ev.preventDefault();
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
pasteHandler(ev) {
|
|
1890
|
+
const text = ev.clipboardData.getData("Text");
|
|
1891
|
+
const types = Array.from(ev.clipboardData.types || []);
|
|
1892
|
+
const files = Array.from(ev.clipboardData.files);
|
|
1893
|
+
if (types.every((type) => type === "Files") && files.length) {
|
|
1894
|
+
Promise.all(files.filter((i) => {
|
|
1895
|
+
return /image/i.test(i.type);
|
|
1896
|
+
}).map((item) => {
|
|
1897
|
+
const reader = new FileReader();
|
|
1898
|
+
return new Promise((resolve) => {
|
|
1899
|
+
reader.onload = (event) => {
|
|
1900
|
+
resolve(event.target.result);
|
|
1901
|
+
};
|
|
1902
|
+
reader.readAsDataURL(item);
|
|
1326
1903
|
});
|
|
1327
|
-
})).then((
|
|
1328
|
-
const
|
|
1329
|
-
|
|
1330
|
-
|
|
1904
|
+
})).then((urls) => {
|
|
1905
|
+
const html = urls.map((i) => {
|
|
1906
|
+
return `<img src=${i}>`;
|
|
1907
|
+
}).join("");
|
|
1908
|
+
this.paste(html, text);
|
|
1909
|
+
});
|
|
1910
|
+
ev.preventDefault();
|
|
1331
1911
|
return;
|
|
1332
1912
|
}
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1913
|
+
const div = document.createElement("div");
|
|
1914
|
+
div.style.cssText = "width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0";
|
|
1915
|
+
div.contentEditable = "true";
|
|
1916
|
+
document.body.appendChild(div);
|
|
1917
|
+
div.focus();
|
|
1918
|
+
setTimeout(() => {
|
|
1919
|
+
document.body.removeChild(div);
|
|
1920
|
+
div.style.cssText = "";
|
|
1921
|
+
this.paste(div, text);
|
|
1336
1922
|
});
|
|
1337
1923
|
}
|
|
1338
|
-
paste(
|
|
1339
|
-
const
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1924
|
+
paste(dom, text) {
|
|
1925
|
+
const slot = this.parser.parse(dom, new Slot([
|
|
1926
|
+
ContentType.BlockComponent,
|
|
1927
|
+
ContentType.InlineComponent,
|
|
1928
|
+
ContentType.Text
|
|
1343
1929
|
]));
|
|
1344
|
-
this.commander.paste(
|
|
1930
|
+
this.commander.paste(slot, text);
|
|
1345
1931
|
}
|
|
1346
|
-
handleShortcut(
|
|
1347
|
-
let
|
|
1932
|
+
handleShortcut(input) {
|
|
1933
|
+
let isWriting = false;
|
|
1934
|
+
let isIgnore = false;
|
|
1348
1935
|
this.subscription.add(
|
|
1349
|
-
|
|
1350
|
-
|
|
1936
|
+
fromEvent(input, "compositionstart").subscribe(() => {
|
|
1937
|
+
isWriting = true;
|
|
1351
1938
|
}),
|
|
1352
|
-
|
|
1353
|
-
|
|
1939
|
+
fromEvent(input, "compositionend").subscribe(() => {
|
|
1940
|
+
isWriting = false;
|
|
1354
1941
|
}),
|
|
1355
|
-
|
|
1356
|
-
this.isSafari
|
|
1942
|
+
fromEvent(input, "beforeinput").subscribe((ev) => {
|
|
1943
|
+
if (this.isSafari) {
|
|
1944
|
+
if (ev.inputType === "insertFromComposition") {
|
|
1945
|
+
isIgnore = true;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1357
1948
|
}),
|
|
1358
|
-
|
|
1359
|
-
this.
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1949
|
+
fromEvent(input, "keydown").pipe(filter(() => {
|
|
1950
|
+
if (this.isSafari && isIgnore) {
|
|
1951
|
+
isIgnore = false;
|
|
1952
|
+
return false;
|
|
1953
|
+
}
|
|
1954
|
+
return !isWriting;
|
|
1955
|
+
})).subscribe((ev) => {
|
|
1956
|
+
this.ignoreComposition = false;
|
|
1957
|
+
let key = ev.key;
|
|
1958
|
+
const keys = ")!@#$%^Z&*(";
|
|
1959
|
+
const b = key === "Process" && /Digit\d/.test(ev.code) && ev.shiftKey;
|
|
1960
|
+
if (b) {
|
|
1961
|
+
key = keys.charAt(+ev.code.substring(5));
|
|
1962
|
+
ev.preventDefault();
|
|
1963
|
+
}
|
|
1964
|
+
const is = this.keyboard.execShortcut({
|
|
1965
|
+
key,
|
|
1966
|
+
altKey: ev.altKey,
|
|
1967
|
+
shiftKey: ev.shiftKey,
|
|
1968
|
+
modKey: this.isMac ? ev.metaKey : ev.ctrlKey,
|
|
1366
1969
|
agent: {
|
|
1367
|
-
key:
|
|
1368
|
-
keyCode:
|
|
1369
|
-
code:
|
|
1970
|
+
key: ev.key,
|
|
1971
|
+
keyCode: ev.keyCode,
|
|
1972
|
+
code: ev.code
|
|
1370
1973
|
}
|
|
1371
|
-
})
|
|
1974
|
+
});
|
|
1975
|
+
if (is) {
|
|
1976
|
+
this.ignoreComposition = true;
|
|
1977
|
+
ev.preventDefault();
|
|
1978
|
+
}
|
|
1372
1979
|
})
|
|
1373
1980
|
);
|
|
1374
1981
|
}
|
|
1375
|
-
handleInput(
|
|
1376
|
-
this.isMobileBrowser
|
|
1982
|
+
handleInput(input) {
|
|
1983
|
+
if (this.isMobileBrowser) {
|
|
1984
|
+
this.handleMobileInput(input);
|
|
1985
|
+
} else {
|
|
1986
|
+
this.handlePCInput(input);
|
|
1987
|
+
}
|
|
1377
1988
|
}
|
|
1378
|
-
handleMobileInput(
|
|
1379
|
-
let
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1989
|
+
handleMobileInput(input) {
|
|
1990
|
+
let isCompositionStart = true;
|
|
1991
|
+
let startIndex;
|
|
1992
|
+
const compositionStart = () => {
|
|
1993
|
+
this.composition = true;
|
|
1994
|
+
startIndex = this.selection.startOffset;
|
|
1995
|
+
const startSlot = this.selection.startSlot;
|
|
1996
|
+
const event = new Event(startSlot, {
|
|
1997
|
+
index: startIndex
|
|
1384
1998
|
});
|
|
1385
|
-
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1999
|
+
invokeListener(startSlot.parent, "onCompositionStart", event);
|
|
2000
|
+
};
|
|
2001
|
+
const compositionUpdate = (data) => {
|
|
2002
|
+
const startSlot = this.selection.startSlot;
|
|
2003
|
+
const event = new Event(startSlot, {
|
|
2004
|
+
index: startIndex,
|
|
2005
|
+
data
|
|
1390
2006
|
});
|
|
1391
|
-
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
if (
|
|
1396
|
-
|
|
1397
|
-
|
|
2007
|
+
invokeListener(startSlot.parent, "onCompositionUpdate", event);
|
|
2008
|
+
};
|
|
2009
|
+
const compositionEnd = (data) => {
|
|
2010
|
+
this.composition = false;
|
|
2011
|
+
if (data) {
|
|
2012
|
+
this.commander.write(data);
|
|
2013
|
+
}
|
|
2014
|
+
const startSlot = this.selection.startSlot;
|
|
2015
|
+
if (startSlot) {
|
|
2016
|
+
const event = new Event(startSlot, null);
|
|
2017
|
+
invokeListener(startSlot.parent, "onCompositionEnd", event);
|
|
1398
2018
|
}
|
|
1399
2019
|
};
|
|
1400
2020
|
this.subscription.add(
|
|
1401
|
-
|
|
1402
|
-
|
|
2021
|
+
fromEvent(input, "compositionstart").subscribe(() => {
|
|
2022
|
+
compositionStart();
|
|
1403
2023
|
}),
|
|
1404
|
-
|
|
1405
|
-
|
|
2024
|
+
fromEvent(input, "compositionupdate").subscribe((ev) => {
|
|
2025
|
+
compositionUpdate(ev.data);
|
|
1406
2026
|
}),
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
const
|
|
1410
|
-
|
|
2027
|
+
fromEvent(input, "compositionend").subscribe((ev) => {
|
|
2028
|
+
compositionEnd(ev.data);
|
|
2029
|
+
const startContainer = this.nativeSelection.focusNode;
|
|
2030
|
+
if (startContainer instanceof Text && startContainer.textContent === ev.data) {
|
|
2031
|
+
startContainer.remove();
|
|
2032
|
+
}
|
|
1411
2033
|
}),
|
|
1412
|
-
|
|
1413
|
-
switch (
|
|
2034
|
+
fromEvent(input, "beforeinput").subscribe((ev) => {
|
|
2035
|
+
switch (ev.inputType) {
|
|
1414
2036
|
case "insertText":
|
|
1415
|
-
|
|
2037
|
+
if (ev.data) {
|
|
2038
|
+
this.commander.write(ev.data);
|
|
2039
|
+
ev.preventDefault();
|
|
2040
|
+
}
|
|
1416
2041
|
break;
|
|
1417
2042
|
case "insertCompositionText":
|
|
1418
|
-
|
|
2043
|
+
if (isCompositionStart) {
|
|
2044
|
+
isCompositionStart = false;
|
|
2045
|
+
compositionStart();
|
|
2046
|
+
} else {
|
|
2047
|
+
compositionUpdate(ev.data || "");
|
|
2048
|
+
}
|
|
1419
2049
|
break;
|
|
1420
2050
|
case "deleteCompositionText":
|
|
1421
|
-
this.composition =
|
|
2051
|
+
this.composition = false;
|
|
1422
2052
|
break;
|
|
1423
2053
|
case "deleteContentBackward": {
|
|
1424
|
-
this.composition =
|
|
1425
|
-
const
|
|
1426
|
-
if (!
|
|
2054
|
+
this.composition = false;
|
|
2055
|
+
const range = ev.getTargetRanges()[0];
|
|
2056
|
+
if (!range) {
|
|
1427
2057
|
break;
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
2058
|
+
}
|
|
2059
|
+
const location = this.domAdapter.getLocationByNativeNode(range.startContainer);
|
|
2060
|
+
const startSlot = this.selection.startSlot;
|
|
2061
|
+
if (startSlot) {
|
|
2062
|
+
this.selection.setBaseAndExtent(
|
|
2063
|
+
startSlot,
|
|
2064
|
+
location.startIndex + range.startOffset,
|
|
2065
|
+
startSlot,
|
|
2066
|
+
location.startIndex + range.endOffset
|
|
2067
|
+
);
|
|
2068
|
+
this.commander.delete();
|
|
2069
|
+
}
|
|
1435
2070
|
break;
|
|
1436
2071
|
}
|
|
1437
2072
|
case "insertReplacementText": {
|
|
1438
|
-
this.composition =
|
|
1439
|
-
const
|
|
2073
|
+
this.composition = false;
|
|
2074
|
+
const range = ev.getTargetRanges()[0];
|
|
2075
|
+
const location = this.domAdapter.getLocationByNativeNode(range.startContainer);
|
|
2076
|
+
const startSlot = this.selection.startSlot;
|
|
1440
2077
|
this.selection.setBaseAndExtent(
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
)
|
|
1446
|
-
|
|
1447
|
-
|
|
2078
|
+
startSlot,
|
|
2079
|
+
location.startIndex + range.startOffset,
|
|
2080
|
+
startSlot,
|
|
2081
|
+
location.startIndex + range.endOffset
|
|
2082
|
+
);
|
|
2083
|
+
this.commander.delete();
|
|
2084
|
+
const text = ev.dataTransfer?.getData("text") || ev.data || null;
|
|
2085
|
+
if (text) {
|
|
2086
|
+
this.commander.write(text);
|
|
2087
|
+
}
|
|
1448
2088
|
break;
|
|
1449
2089
|
}
|
|
1450
2090
|
}
|
|
1451
2091
|
})
|
|
1452
2092
|
);
|
|
1453
2093
|
}
|
|
1454
|
-
handlePCInput(
|
|
1455
|
-
let
|
|
2094
|
+
handlePCInput(input) {
|
|
2095
|
+
let startIndex = 0;
|
|
2096
|
+
let isCompositionEnd = false;
|
|
1456
2097
|
this.subscription.add(
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
2098
|
+
fromEvent(input, "compositionstart").pipe(filter(() => {
|
|
2099
|
+
return !this.ignoreComposition;
|
|
2100
|
+
})).subscribe(() => {
|
|
2101
|
+
this.composition = true;
|
|
2102
|
+
startIndex = this.selection.startOffset;
|
|
2103
|
+
const startSlot = this.selection.startSlot;
|
|
2104
|
+
const event = new Event(startSlot, {
|
|
2105
|
+
index: startIndex
|
|
1461
2106
|
});
|
|
1462
|
-
|
|
2107
|
+
invokeListener(startSlot.parent, "onCompositionStart", event);
|
|
1463
2108
|
}),
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
2109
|
+
fromEvent(input, "compositionupdate").pipe(filter(() => {
|
|
2110
|
+
return !this.ignoreComposition;
|
|
2111
|
+
})).subscribe((ev) => {
|
|
2112
|
+
const startSlot = this.selection.startSlot;
|
|
2113
|
+
const event = new Event(startSlot, {
|
|
2114
|
+
index: startIndex,
|
|
2115
|
+
data: ev.data
|
|
1468
2116
|
});
|
|
1469
|
-
|
|
2117
|
+
invokeListener(startSlot.parent, "onCompositionUpdate", event);
|
|
1470
2118
|
}),
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
2119
|
+
merge(
|
|
2120
|
+
fromEvent(input, "beforeinput").pipe(
|
|
2121
|
+
map((ev) => {
|
|
2122
|
+
ev.preventDefault();
|
|
2123
|
+
if (ev.inputType === "insertCompositionText") {
|
|
2124
|
+
return null;
|
|
2125
|
+
}
|
|
2126
|
+
if (ev.inputType === "insertReplacementText") {
|
|
2127
|
+
const range = ev.getTargetRanges()[0];
|
|
2128
|
+
const location = this.domAdapter.getLocationByNativeNode(range.startContainer);
|
|
2129
|
+
const startSlot = this.selection.startSlot;
|
|
2130
|
+
this.selection.setBaseAndExtent(
|
|
2131
|
+
startSlot,
|
|
2132
|
+
location.startIndex + range.startOffset,
|
|
2133
|
+
startSlot,
|
|
2134
|
+
location.startIndex + range.endOffset
|
|
2135
|
+
);
|
|
2136
|
+
this.commander.delete();
|
|
2137
|
+
return ev.dataTransfer?.getData("text") || ev.data || null;
|
|
2138
|
+
}
|
|
2139
|
+
isCompositionEnd = ev.inputType === "insertFromComposition";
|
|
2140
|
+
if (isCompositionEnd && this.composition) {
|
|
1475
2141
|
return null;
|
|
1476
|
-
if (e.inputType === "insertReplacementText") {
|
|
1477
|
-
const o = e.getTargetRanges()[0], n = this.domAdapter.getLocationByNativeNode(o.startContainer), r = this.selection.startSlot;
|
|
1478
|
-
return this.selection.setBaseAndExtent(
|
|
1479
|
-
r,
|
|
1480
|
-
n.startIndex + o.startOffset,
|
|
1481
|
-
r,
|
|
1482
|
-
n.startIndex + o.endOffset
|
|
1483
|
-
), this.commander.delete(), e.dataTransfer?.getData("text") || e.data || null;
|
|
1484
2142
|
}
|
|
1485
|
-
|
|
2143
|
+
if (this.isSafari) {
|
|
2144
|
+
if (ev.inputType === "insertText" || isCompositionEnd) {
|
|
2145
|
+
return ev.data;
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
if (!ev.isComposing && !!ev.data) {
|
|
2149
|
+
return ev.data;
|
|
2150
|
+
}
|
|
2151
|
+
return null;
|
|
1486
2152
|
}),
|
|
1487
|
-
|
|
2153
|
+
filter((text) => {
|
|
2154
|
+
return text;
|
|
2155
|
+
})
|
|
1488
2156
|
),
|
|
1489
|
-
this.isSafari ? new
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
2157
|
+
this.isSafari ? new Observable() : fromEvent(input, "compositionend").pipe(filter(() => {
|
|
2158
|
+
return !this.ignoreComposition;
|
|
2159
|
+
})).pipe(
|
|
2160
|
+
filter(() => {
|
|
2161
|
+
return this.composition;
|
|
2162
|
+
}),
|
|
2163
|
+
map((ev) => {
|
|
2164
|
+
isCompositionEnd = true;
|
|
2165
|
+
ev.preventDefault();
|
|
2166
|
+
return ev.data;
|
|
2167
|
+
}),
|
|
2168
|
+
filter(() => {
|
|
2169
|
+
const b = this.ignoreComposition;
|
|
2170
|
+
this.ignoreComposition = false;
|
|
2171
|
+
return !b;
|
|
1495
2172
|
})
|
|
1496
2173
|
)
|
|
1497
|
-
).subscribe((
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
2174
|
+
).subscribe((text) => {
|
|
2175
|
+
this.composition = false;
|
|
2176
|
+
if (text) {
|
|
2177
|
+
const startContainer = this.nativeSelection.focusNode;
|
|
2178
|
+
if (startContainer instanceof Text && startContainer.textContent === text) {
|
|
2179
|
+
startContainer.remove();
|
|
2180
|
+
}
|
|
2181
|
+
this.commander.write(text);
|
|
1501
2182
|
}
|
|
1502
|
-
if (
|
|
1503
|
-
const
|
|
1504
|
-
if (
|
|
1505
|
-
const
|
|
1506
|
-
|
|
2183
|
+
if (isCompositionEnd) {
|
|
2184
|
+
const startSlot = this.selection.startSlot;
|
|
2185
|
+
if (startSlot) {
|
|
2186
|
+
const event = new Event(startSlot, null);
|
|
2187
|
+
invokeListener(startSlot.parent, "onCompositionEnd", event);
|
|
1507
2188
|
}
|
|
1508
2189
|
}
|
|
1509
|
-
|
|
2190
|
+
isCompositionEnd = false;
|
|
1510
2191
|
})
|
|
1511
2192
|
);
|
|
1512
2193
|
}
|
|
1513
2194
|
};
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
],
|
|
1517
|
-
class
|
|
1518
|
-
onViewUpdated = new
|
|
1519
|
-
host =
|
|
2195
|
+
NativeInput = __decorateClass([
|
|
2196
|
+
Injectable()
|
|
2197
|
+
], NativeInput);
|
|
2198
|
+
class DomAdapter extends Adapter {
|
|
2199
|
+
onViewUpdated = new Subject();
|
|
2200
|
+
host = createElement("div", {
|
|
1520
2201
|
styles: {
|
|
1521
2202
|
cursor: "text",
|
|
1522
2203
|
wordBreak: "break-all",
|
|
@@ -1525,71 +2206,82 @@ class Ot extends Y {
|
|
|
1525
2206
|
outline: "none"
|
|
1526
2207
|
},
|
|
1527
2208
|
attrs: {
|
|
1528
|
-
"data-textbus-view":
|
|
2209
|
+
"data-textbus-view": VIEW_DOCUMENT
|
|
1529
2210
|
},
|
|
1530
2211
|
props: {
|
|
1531
2212
|
id: "textbus-" + Number((Math.random() + "").substring(2)).toString(16)
|
|
1532
2213
|
}
|
|
1533
2214
|
});
|
|
1534
2215
|
}
|
|
1535
|
-
const
|
|
1536
|
-
class
|
|
1537
|
-
constructor(
|
|
1538
|
-
this.config =
|
|
1539
|
-
const { mask
|
|
1540
|
-
|
|
2216
|
+
const browserErrorFn = makeError("BrowserModule");
|
|
2217
|
+
class BrowserModule {
|
|
2218
|
+
constructor(config) {
|
|
2219
|
+
this.config = config;
|
|
2220
|
+
const { mask, wrapper } = BrowserModule.createLayout();
|
|
2221
|
+
wrapper.prepend(config.adapter.host);
|
|
2222
|
+
if (config.minHeight) {
|
|
2223
|
+
config.adapter.host.style.minHeight = config.minHeight;
|
|
2224
|
+
}
|
|
2225
|
+
this.providers = [
|
|
1541
2226
|
{
|
|
1542
|
-
provide:
|
|
1543
|
-
useValue:
|
|
2227
|
+
provide: EDITOR_OPTIONS,
|
|
2228
|
+
useValue: config
|
|
1544
2229
|
},
|
|
1545
2230
|
{
|
|
1546
|
-
provide:
|
|
1547
|
-
useValue:
|
|
2231
|
+
provide: VIEW_CONTAINER,
|
|
2232
|
+
useValue: wrapper
|
|
1548
2233
|
},
|
|
1549
2234
|
{
|
|
1550
|
-
provide:
|
|
1551
|
-
useValue:
|
|
2235
|
+
provide: VIEW_DOCUMENT,
|
|
2236
|
+
useValue: config.adapter.host
|
|
1552
2237
|
},
|
|
1553
2238
|
{
|
|
1554
|
-
provide:
|
|
1555
|
-
useValue:
|
|
2239
|
+
provide: VIEW_MASK,
|
|
2240
|
+
useValue: mask
|
|
1556
2241
|
},
|
|
1557
2242
|
{
|
|
1558
|
-
provide:
|
|
1559
|
-
useExisting:
|
|
2243
|
+
provide: NativeSelectionBridge,
|
|
2244
|
+
useExisting: SelectionBridge
|
|
1560
2245
|
},
|
|
1561
2246
|
{
|
|
1562
|
-
provide:
|
|
1563
|
-
useClass:
|
|
2247
|
+
provide: Input,
|
|
2248
|
+
useClass: config.useContentEditable ? NativeInput : MagicInput
|
|
1564
2249
|
},
|
|
1565
2250
|
{
|
|
1566
|
-
provide:
|
|
1567
|
-
useValue:
|
|
2251
|
+
provide: Adapter,
|
|
2252
|
+
useValue: config.adapter
|
|
1568
2253
|
},
|
|
1569
2254
|
{
|
|
1570
|
-
provide:
|
|
1571
|
-
useValue:
|
|
2255
|
+
provide: DomAdapter,
|
|
2256
|
+
useValue: config.adapter
|
|
1572
2257
|
},
|
|
1573
2258
|
{
|
|
1574
|
-
provide:
|
|
1575
|
-
useFactory: (
|
|
1576
|
-
const
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
2259
|
+
provide: FocusManager,
|
|
2260
|
+
useFactory: (input) => {
|
|
2261
|
+
const focusEvent = new Subject();
|
|
2262
|
+
const blurEvent = new Subject();
|
|
2263
|
+
input.caret.onPositionChange.pipe(
|
|
2264
|
+
map((p) => !!p),
|
|
2265
|
+
distinctUntilChanged()
|
|
2266
|
+
).subscribe((b) => {
|
|
2267
|
+
if (b) {
|
|
2268
|
+
focusEvent.next();
|
|
2269
|
+
} else {
|
|
2270
|
+
blurEvent.next();
|
|
2271
|
+
}
|
|
2272
|
+
});
|
|
2273
|
+
return {
|
|
2274
|
+
onFocus: focusEvent,
|
|
2275
|
+
onBlur: blurEvent
|
|
1585
2276
|
};
|
|
1586
2277
|
},
|
|
1587
|
-
deps: [
|
|
2278
|
+
deps: [Input]
|
|
1588
2279
|
},
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
]
|
|
2280
|
+
Parser,
|
|
2281
|
+
SelectionBridge,
|
|
2282
|
+
CollaborateCursor
|
|
2283
|
+
];
|
|
2284
|
+
this.workbench = wrapper;
|
|
1593
2285
|
}
|
|
1594
2286
|
config;
|
|
1595
2287
|
providers;
|
|
@@ -1600,11 +2292,13 @@ class et {
|
|
|
1600
2292
|
* @param rootComponentLoader 文档根组件加载器
|
|
1601
2293
|
* @param textbus
|
|
1602
2294
|
*/
|
|
1603
|
-
readDocumentByHTML(
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
2295
|
+
readDocumentByHTML(html, rootComponentLoader, textbus) {
|
|
2296
|
+
const parser = textbus.get(Parser);
|
|
2297
|
+
const doc = parser.parseDoc(html, rootComponentLoader);
|
|
2298
|
+
if (doc instanceof Component) {
|
|
2299
|
+
return doc;
|
|
2300
|
+
}
|
|
2301
|
+
throw browserErrorFn("rootComponentLoader must return a component instance.");
|
|
1608
2302
|
}
|
|
1609
2303
|
/**
|
|
1610
2304
|
* 将组件数据解析到组件实例中
|
|
@@ -1612,27 +2306,35 @@ class et {
|
|
|
1612
2306
|
* @param rootComponent 根组件
|
|
1613
2307
|
* @param textbus
|
|
1614
2308
|
*/
|
|
1615
|
-
readDocumentByComponentLiteral(
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
2309
|
+
readDocumentByComponentLiteral(data, rootComponent, textbus) {
|
|
2310
|
+
const registry = textbus.get(Registry);
|
|
2311
|
+
return registry.createComponentByFactory(data, rootComponent);
|
|
2312
|
+
}
|
|
2313
|
+
async setup(textbus) {
|
|
2314
|
+
const host = this.config.renderTo();
|
|
2315
|
+
if (!(host instanceof HTMLElement)) {
|
|
2316
|
+
throw browserErrorFn("view container is not a HTMLElement");
|
|
2317
|
+
}
|
|
2318
|
+
host.append(this.workbench);
|
|
2319
|
+
await textbus.get(Input).onReady;
|
|
2320
|
+
return () => {
|
|
1623
2321
|
this.workbench.remove();
|
|
1624
2322
|
};
|
|
1625
2323
|
}
|
|
1626
|
-
onAfterStartup(
|
|
1627
|
-
this.config.autoFocus
|
|
2324
|
+
onAfterStartup(textbus) {
|
|
2325
|
+
if (this.config.autoFocus) {
|
|
2326
|
+
textbus.focus();
|
|
2327
|
+
}
|
|
1628
2328
|
}
|
|
1629
|
-
onDestroy(
|
|
1630
|
-
|
|
2329
|
+
onDestroy(textbus) {
|
|
2330
|
+
textbus.get(Input).destroy();
|
|
2331
|
+
textbus.get(SelectionBridge).destroy();
|
|
2332
|
+
textbus.get(CollaborateCursor).destroy();
|
|
1631
2333
|
}
|
|
1632
2334
|
static createLayout() {
|
|
1633
|
-
const
|
|
2335
|
+
const mask = createElement("div", {
|
|
1634
2336
|
attrs: {
|
|
1635
|
-
"data-textbus-view":
|
|
2337
|
+
"data-textbus-view": VIEW_MASK
|
|
1636
2338
|
},
|
|
1637
2339
|
styles: {
|
|
1638
2340
|
position: "absolute",
|
|
@@ -1643,7 +2345,8 @@ class et {
|
|
|
1643
2345
|
pointerEvents: "none"
|
|
1644
2346
|
// overflow: 'hidden'
|
|
1645
2347
|
}
|
|
1646
|
-
})
|
|
2348
|
+
});
|
|
2349
|
+
const maskWrapper = createElement("div", {
|
|
1647
2350
|
styles: {
|
|
1648
2351
|
position: "absolute",
|
|
1649
2352
|
left: 0,
|
|
@@ -1655,45 +2358,46 @@ class et {
|
|
|
1655
2358
|
pointerEvents: "none",
|
|
1656
2359
|
overflow: "hidden"
|
|
1657
2360
|
},
|
|
1658
|
-
children: [
|
|
2361
|
+
children: [mask]
|
|
2362
|
+
});
|
|
2363
|
+
const wrapper = createElement("div", {
|
|
2364
|
+
attrs: {
|
|
2365
|
+
"data-textbus-view": VIEW_CONTAINER
|
|
2366
|
+
},
|
|
2367
|
+
styles: {
|
|
2368
|
+
display: "flex",
|
|
2369
|
+
minHeight: "100%",
|
|
2370
|
+
position: "relative",
|
|
2371
|
+
flexDirection: "column"
|
|
2372
|
+
},
|
|
2373
|
+
children: [maskWrapper]
|
|
1659
2374
|
});
|
|
1660
2375
|
return {
|
|
1661
|
-
wrapper
|
|
1662
|
-
|
|
1663
|
-
"data-textbus-view": j
|
|
1664
|
-
},
|
|
1665
|
-
styles: {
|
|
1666
|
-
display: "flex",
|
|
1667
|
-
minHeight: "100%",
|
|
1668
|
-
position: "relative",
|
|
1669
|
-
flexDirection: "column"
|
|
1670
|
-
},
|
|
1671
|
-
children: [i]
|
|
1672
|
-
}),
|
|
1673
|
-
mask: t
|
|
2376
|
+
wrapper,
|
|
2377
|
+
mask
|
|
1674
2378
|
};
|
|
1675
2379
|
}
|
|
1676
2380
|
}
|
|
1677
2381
|
export {
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
2382
|
+
BrowserModule,
|
|
2383
|
+
CollaborateCursor,
|
|
2384
|
+
CollaborateSelectionAwarenessDelegate,
|
|
2385
|
+
DomAdapter,
|
|
2386
|
+
EDITOR_OPTIONS,
|
|
2387
|
+
Input,
|
|
2388
|
+
MagicInput,
|
|
2389
|
+
NativeInput,
|
|
2390
|
+
Parser,
|
|
2391
|
+
SelectionBridge,
|
|
2392
|
+
VIEW_CONTAINER,
|
|
2393
|
+
VIEW_DOCUMENT,
|
|
2394
|
+
VIEW_MASK,
|
|
2395
|
+
createElement,
|
|
2396
|
+
getLayoutRectByRange,
|
|
2397
|
+
isFirefox,
|
|
2398
|
+
isMac,
|
|
2399
|
+
isMobileBrowser,
|
|
2400
|
+
isSafari,
|
|
2401
|
+
isWindows
|
|
1698
2402
|
};
|
|
1699
2403
|
//# sourceMappingURL=index.esm.js.map
|