slate-angular 20.2.0-next.7 → 20.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/slate-angular.mjs +1040 -281
- package/fesm2022/slate-angular.mjs.map +1 -1
- package/index.d.ts +64 -30
- package/package.json +1 -1
- package/styles/index.scss +1 -0
|
@@ -353,6 +353,18 @@ const CustomDOMEditor = {
|
|
|
353
353
|
}
|
|
354
354
|
};
|
|
355
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Symbols.
|
|
358
|
+
*/
|
|
359
|
+
const PLACEHOLDER_SYMBOL = Symbol('placeholder');
|
|
360
|
+
/**
|
|
361
|
+
* Weak map for associating the html element with the component.
|
|
362
|
+
*/
|
|
363
|
+
const ELEMENT_TO_COMPONENT = new WeakMap();
|
|
364
|
+
const IS_ENABLED_VIRTUAL_SCROLL = new WeakMap();
|
|
365
|
+
const EDITOR_TO_VIRTUAL_SCROLL_SELECTION = new WeakMap();
|
|
366
|
+
const EDITOR_TO_AFTER_VIEW_INIT_QUEUE = new WeakMap();
|
|
367
|
+
|
|
356
368
|
const AngularEditor = {
|
|
357
369
|
...CustomDOMEditor,
|
|
358
370
|
/**
|
|
@@ -424,19 +436,12 @@ const AngularEditor = {
|
|
|
424
436
|
// FocusedContext is updated to the correct value
|
|
425
437
|
el.focus({ preventScroll: true });
|
|
426
438
|
}
|
|
439
|
+
},
|
|
440
|
+
isEnabledVirtualScroll(editor) {
|
|
441
|
+
return IS_ENABLED_VIRTUAL_SCROLL.get(editor);
|
|
427
442
|
}
|
|
428
443
|
};
|
|
429
444
|
|
|
430
|
-
/**
|
|
431
|
-
* Symbols.
|
|
432
|
-
*/
|
|
433
|
-
const PLACEHOLDER_SYMBOL = Symbol('placeholder');
|
|
434
|
-
/**
|
|
435
|
-
* Weak map for associating the html element with the component.
|
|
436
|
-
*/
|
|
437
|
-
const ELEMENT_TO_COMPONENT = new WeakMap();
|
|
438
|
-
const EDITOR_TO_AFTER_VIEW_INIT_QUEUE = new WeakMap();
|
|
439
|
-
|
|
440
445
|
const IS_IOS = typeof navigator !== 'undefined' &&
|
|
441
446
|
typeof window !== 'undefined' &&
|
|
442
447
|
/iPad|iPhone|iPod/.test(navigator.userAgent) &&
|
|
@@ -470,9 +475,9 @@ const HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
|
|
|
470
475
|
globalThis.InputEvent &&
|
|
471
476
|
// @ts-ignore The `getTargetRanges` property isn't recognized.
|
|
472
477
|
typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
|
|
473
|
-
const
|
|
474
|
-
const VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT = 40;
|
|
478
|
+
const VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT = 30;
|
|
475
479
|
const SLATE_DEBUG_KEY = '__SLATE_DEBUG__';
|
|
480
|
+
const SLATE_DEBUG_KEY_SCROLL_TOP = '__SLATE_DEBUG_SCROLL_TOP__';
|
|
476
481
|
|
|
477
482
|
/**
|
|
478
483
|
* Hotkey mappings for each platform.
|
|
@@ -950,6 +955,587 @@ const fallbackCopyText = async (text) => {
|
|
|
950
955
|
});
|
|
951
956
|
};
|
|
952
957
|
|
|
958
|
+
class VirtualScrollDebugOverlay {
|
|
959
|
+
static { this.storageKey = 'slate_virtual_scroll_debug_overlay_state'; }
|
|
960
|
+
static { this.minWidth = 320; }
|
|
961
|
+
static { this.minHeight = 240; }
|
|
962
|
+
static { this.defaultWidth = 410; }
|
|
963
|
+
static { this.defaultHeight = 480; }
|
|
964
|
+
static getInstance(doc) {
|
|
965
|
+
if (!this.instance) {
|
|
966
|
+
this.instance = new VirtualScrollDebugOverlay(doc);
|
|
967
|
+
}
|
|
968
|
+
this.instance.init();
|
|
969
|
+
return this.instance;
|
|
970
|
+
}
|
|
971
|
+
static log(doc, type, ...args) {
|
|
972
|
+
this.getInstance(doc).log(type, ...args);
|
|
973
|
+
}
|
|
974
|
+
// will trigger selectionchange and clear editor's selection
|
|
975
|
+
static syncScrollTop(doc, value) {
|
|
976
|
+
const instance = this.getInstance(doc);
|
|
977
|
+
instance.setScrollTopValue(value);
|
|
978
|
+
}
|
|
979
|
+
constructor(doc) {
|
|
980
|
+
this.doc = doc;
|
|
981
|
+
this.state = {
|
|
982
|
+
left: 16,
|
|
983
|
+
top: 16,
|
|
984
|
+
collapsed: false,
|
|
985
|
+
width: VirtualScrollDebugOverlay.defaultWidth,
|
|
986
|
+
height: VirtualScrollDebugOverlay.defaultHeight
|
|
987
|
+
};
|
|
988
|
+
this.originalConsoleLog = console.log.bind(console);
|
|
989
|
+
this.originalConsoleWarn = console.warn.bind(console);
|
|
990
|
+
this.dragOffsetX = 0;
|
|
991
|
+
this.dragOffsetY = 0;
|
|
992
|
+
this.isDragging = false;
|
|
993
|
+
this.isResizing = false;
|
|
994
|
+
this.resizeStartX = 0;
|
|
995
|
+
this.resizeStartY = 0;
|
|
996
|
+
this.resizeStartWidth = 0;
|
|
997
|
+
this.resizeStartHeight = 0;
|
|
998
|
+
this.dragMoved = false;
|
|
999
|
+
this.wasDragged = false;
|
|
1000
|
+
this.onDragging = (event) => {
|
|
1001
|
+
if (!this.isDragging || !this.container) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
this.dragMoved = true;
|
|
1005
|
+
const nextLeft = event.clientX - this.dragOffsetX;
|
|
1006
|
+
const nextTop = event.clientY - this.dragOffsetY;
|
|
1007
|
+
this.container.style.left = `${nextLeft}px`;
|
|
1008
|
+
this.container.style.top = `${nextTop}px`;
|
|
1009
|
+
this.container.style.right = 'auto';
|
|
1010
|
+
this.container.style.bottom = 'auto';
|
|
1011
|
+
};
|
|
1012
|
+
this.onDragEnd = () => {
|
|
1013
|
+
if (!this.isDragging) {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
this.isDragging = false;
|
|
1017
|
+
this.wasDragged = this.dragMoved;
|
|
1018
|
+
this.dragMoved = false;
|
|
1019
|
+
this.doc.removeEventListener('mousemove', this.onDragging);
|
|
1020
|
+
this.doc.removeEventListener('mouseup', this.onDragEnd);
|
|
1021
|
+
if (this.container) {
|
|
1022
|
+
const rect = this.container.getBoundingClientRect();
|
|
1023
|
+
this.state.left = rect.left;
|
|
1024
|
+
this.state.top = rect.top;
|
|
1025
|
+
this.persistState();
|
|
1026
|
+
this.container.style.transition = '';
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
this.onResizing = (event) => {
|
|
1030
|
+
if (!this.isResizing || !this.container) {
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
const deltaX = event.clientX - this.resizeStartX;
|
|
1034
|
+
const deltaY = event.clientY - this.resizeStartY;
|
|
1035
|
+
const nextWidth = Math.max(VirtualScrollDebugOverlay.minWidth, this.resizeStartWidth + deltaX);
|
|
1036
|
+
const nextHeight = Math.max(VirtualScrollDebugOverlay.minHeight, this.resizeStartHeight + deltaY);
|
|
1037
|
+
this.state.width = nextWidth;
|
|
1038
|
+
this.state.height = nextHeight;
|
|
1039
|
+
this.applySize();
|
|
1040
|
+
};
|
|
1041
|
+
this.onResizeEnd = () => {
|
|
1042
|
+
if (!this.isResizing) {
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
this.isResizing = false;
|
|
1046
|
+
this.doc.removeEventListener('mousemove', this.onResizing);
|
|
1047
|
+
this.doc.removeEventListener('mouseup', this.onResizeEnd);
|
|
1048
|
+
this.persistState();
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
init() {
|
|
1052
|
+
if (!this.container) {
|
|
1053
|
+
this.createContainer();
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
log(type, ...args) {
|
|
1057
|
+
this.init();
|
|
1058
|
+
if (type === 'warn') {
|
|
1059
|
+
this.originalConsoleWarn(...args);
|
|
1060
|
+
}
|
|
1061
|
+
else {
|
|
1062
|
+
this.originalConsoleLog(...args);
|
|
1063
|
+
}
|
|
1064
|
+
this.appendLog(type, ...args);
|
|
1065
|
+
}
|
|
1066
|
+
dispose() {
|
|
1067
|
+
this.container?.remove();
|
|
1068
|
+
this.container = undefined;
|
|
1069
|
+
this.contentWrapper = undefined;
|
|
1070
|
+
this.bubble = undefined;
|
|
1071
|
+
this.logList = undefined;
|
|
1072
|
+
this.selectorInput = undefined;
|
|
1073
|
+
this.distanceInput = undefined;
|
|
1074
|
+
this.collapseToggle = undefined;
|
|
1075
|
+
this.resizeHandle = undefined;
|
|
1076
|
+
this.doc.removeEventListener('mousemove', this.onDragging);
|
|
1077
|
+
this.doc.removeEventListener('mouseup', this.onDragEnd);
|
|
1078
|
+
this.doc.removeEventListener('mousemove', this.onResizing);
|
|
1079
|
+
this.doc.removeEventListener('mouseup', this.onResizeEnd);
|
|
1080
|
+
this.isDragging = false;
|
|
1081
|
+
this.isResizing = false;
|
|
1082
|
+
}
|
|
1083
|
+
createContainer() {
|
|
1084
|
+
this.loadState();
|
|
1085
|
+
const doc = this.doc;
|
|
1086
|
+
const container = doc.createElement('div');
|
|
1087
|
+
container.style.position = 'fixed';
|
|
1088
|
+
container.style.right = 'auto';
|
|
1089
|
+
container.style.bottom = 'auto';
|
|
1090
|
+
container.style.boxSizing = 'border-box';
|
|
1091
|
+
container.style.background = 'rgba(17, 24, 39, 0.95)';
|
|
1092
|
+
container.style.color = '#e5e7eb';
|
|
1093
|
+
container.style.fontSize = '12px';
|
|
1094
|
+
container.style.border = '1px solid #1f2937';
|
|
1095
|
+
container.style.borderRadius = '10px';
|
|
1096
|
+
container.style.fontFamily = 'Menlo, Consolas, monospace';
|
|
1097
|
+
container.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.35)';
|
|
1098
|
+
container.style.zIndex = '9999';
|
|
1099
|
+
container.style.display = 'flex';
|
|
1100
|
+
container.style.flexDirection = 'column';
|
|
1101
|
+
container.style.gap = '10px';
|
|
1102
|
+
container.style.minWidth = `${VirtualScrollDebugOverlay.minWidth}px`;
|
|
1103
|
+
container.style.minHeight = `${VirtualScrollDebugOverlay.minHeight}px`;
|
|
1104
|
+
container.style.maxHeight = '80vh';
|
|
1105
|
+
container.style.cursor = 'default';
|
|
1106
|
+
container.addEventListener('mousedown', event => {
|
|
1107
|
+
if (this.state.collapsed) {
|
|
1108
|
+
this.startDrag(event);
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
const header = doc.createElement('div');
|
|
1112
|
+
header.style.display = 'flex';
|
|
1113
|
+
header.style.alignItems = 'center';
|
|
1114
|
+
header.style.justifyContent = 'space-between';
|
|
1115
|
+
header.style.cursor = 'move';
|
|
1116
|
+
header.addEventListener('mousedown', event => {
|
|
1117
|
+
this.startDrag(event);
|
|
1118
|
+
});
|
|
1119
|
+
const title = doc.createElement('div');
|
|
1120
|
+
title.textContent = 'Virtual Scroll Debug';
|
|
1121
|
+
title.style.fontWeight = '600';
|
|
1122
|
+
title.style.letterSpacing = '0.3px';
|
|
1123
|
+
const actions = doc.createElement('div');
|
|
1124
|
+
actions.style.display = 'flex';
|
|
1125
|
+
actions.style.gap = '6px';
|
|
1126
|
+
const collapseButton = doc.createElement('button');
|
|
1127
|
+
collapseButton.type = 'button';
|
|
1128
|
+
collapseButton.textContent = '折叠';
|
|
1129
|
+
collapseButton.style.background = '#1f2937';
|
|
1130
|
+
collapseButton.style.color = '#e5e7eb';
|
|
1131
|
+
collapseButton.style.border = '1px solid #374151';
|
|
1132
|
+
collapseButton.style.borderRadius = '6px';
|
|
1133
|
+
collapseButton.style.padding = '4px 8px';
|
|
1134
|
+
collapseButton.style.cursor = 'pointer';
|
|
1135
|
+
collapseButton.addEventListener('click', () => {
|
|
1136
|
+
this.setCollapsed(!this.state.collapsed);
|
|
1137
|
+
});
|
|
1138
|
+
const clearButton = doc.createElement('button');
|
|
1139
|
+
clearButton.type = 'button';
|
|
1140
|
+
clearButton.textContent = '清除日志';
|
|
1141
|
+
clearButton.style.background = '#374151';
|
|
1142
|
+
clearButton.style.color = '#e5e7eb';
|
|
1143
|
+
clearButton.style.border = '1px solid #4b5563';
|
|
1144
|
+
clearButton.style.borderRadius = '6px';
|
|
1145
|
+
clearButton.style.padding = '4px 10px';
|
|
1146
|
+
clearButton.style.cursor = 'pointer';
|
|
1147
|
+
clearButton.addEventListener('click', () => {
|
|
1148
|
+
if (this.logList) {
|
|
1149
|
+
this.logList.innerHTML = '';
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
1152
|
+
actions.appendChild(collapseButton);
|
|
1153
|
+
actions.appendChild(clearButton);
|
|
1154
|
+
header.appendChild(title);
|
|
1155
|
+
header.appendChild(actions);
|
|
1156
|
+
const scrollForm = doc.createElement('div');
|
|
1157
|
+
scrollForm.style.display = 'grid';
|
|
1158
|
+
scrollForm.style.gridTemplateColumns = '1fr 110px 50px';
|
|
1159
|
+
scrollForm.style.gap = '6px';
|
|
1160
|
+
scrollForm.style.alignItems = 'center';
|
|
1161
|
+
const selectorInput = doc.createElement('input');
|
|
1162
|
+
selectorInput.placeholder = '滚动容器 selector';
|
|
1163
|
+
selectorInput.style.padding = '6px 8px';
|
|
1164
|
+
selectorInput.style.borderRadius = '6px';
|
|
1165
|
+
selectorInput.style.border = '1px solid #4b5563';
|
|
1166
|
+
selectorInput.style.background = '#111827';
|
|
1167
|
+
selectorInput.style.color = '#e5e7eb';
|
|
1168
|
+
selectorInput.autocomplete = 'off';
|
|
1169
|
+
const distanceInput = doc.createElement('input');
|
|
1170
|
+
distanceInput.placeholder = '滚动距离(px)';
|
|
1171
|
+
distanceInput.type = 'number';
|
|
1172
|
+
distanceInput.style.padding = '6px 8px';
|
|
1173
|
+
distanceInput.style.borderRadius = '6px';
|
|
1174
|
+
distanceInput.style.border = '1px solid #4b5563';
|
|
1175
|
+
distanceInput.style.background = '#111827';
|
|
1176
|
+
distanceInput.style.color = '#e5e7eb';
|
|
1177
|
+
const scrollButton = doc.createElement('button');
|
|
1178
|
+
scrollButton.type = 'button';
|
|
1179
|
+
scrollButton.textContent = '滚动';
|
|
1180
|
+
scrollButton.style.background = '#10b981';
|
|
1181
|
+
scrollButton.style.color = '#0b1c15';
|
|
1182
|
+
scrollButton.style.border = 'none';
|
|
1183
|
+
scrollButton.style.borderRadius = '6px';
|
|
1184
|
+
scrollButton.style.padding = '6px 10px';
|
|
1185
|
+
scrollButton.style.cursor = 'pointer';
|
|
1186
|
+
scrollButton.addEventListener('click', () => {
|
|
1187
|
+
const selector = selectorInput.value.trim();
|
|
1188
|
+
const distanceValue = Number(distanceInput.value ?? 0);
|
|
1189
|
+
const distance = Number.isFinite(distanceValue) ? distanceValue : 0;
|
|
1190
|
+
if (!selector) {
|
|
1191
|
+
this.log('warn', '请先填写滚动容器 selector');
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
const target = doc.querySelector(selector);
|
|
1195
|
+
if (!target) {
|
|
1196
|
+
this.log('warn', `未找到滚动容器: ${selector}`);
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (typeof target.scrollTo === 'function') {
|
|
1200
|
+
target.scrollTo({ top: distance, behavior: 'auto' });
|
|
1201
|
+
}
|
|
1202
|
+
else if (Object.prototype.hasOwnProperty.call(target, 'scrollTop')) {
|
|
1203
|
+
target.scrollTop = distance;
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
this.log('warn', '目标元素不支持滚动:', selector);
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
this.log('log', `已将 ${selector} 滚动到`, distance);
|
|
1210
|
+
});
|
|
1211
|
+
scrollForm.appendChild(selectorInput);
|
|
1212
|
+
scrollForm.appendChild(distanceInput);
|
|
1213
|
+
scrollForm.appendChild(scrollButton);
|
|
1214
|
+
const logList = doc.createElement('div');
|
|
1215
|
+
logList.style.height = '260px';
|
|
1216
|
+
logList.style.overflowY = 'auto';
|
|
1217
|
+
logList.style.background = '#0b1220';
|
|
1218
|
+
logList.style.border = '1px solid #1f2937';
|
|
1219
|
+
logList.style.borderRadius = '8px';
|
|
1220
|
+
logList.style.padding = '8px';
|
|
1221
|
+
logList.style.display = 'flex';
|
|
1222
|
+
logList.style.flexDirection = 'column';
|
|
1223
|
+
logList.style.gap = '6px';
|
|
1224
|
+
logList.style.flex = '1';
|
|
1225
|
+
logList.style.minHeight = '160px';
|
|
1226
|
+
const bubble = doc.createElement('div');
|
|
1227
|
+
bubble.textContent = 'VS';
|
|
1228
|
+
bubble.style.display = 'none';
|
|
1229
|
+
bubble.style.alignItems = 'center';
|
|
1230
|
+
bubble.style.justifyContent = 'center';
|
|
1231
|
+
bubble.style.fontWeight = '700';
|
|
1232
|
+
bubble.style.fontSize = '14px';
|
|
1233
|
+
bubble.style.letterSpacing = '0.5px';
|
|
1234
|
+
bubble.style.width = '100%';
|
|
1235
|
+
bubble.style.height = '100%';
|
|
1236
|
+
bubble.style.userSelect = 'none';
|
|
1237
|
+
bubble.addEventListener('click', () => {
|
|
1238
|
+
if (this.wasDragged) {
|
|
1239
|
+
this.wasDragged = false;
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
this.setCollapsed(false);
|
|
1243
|
+
});
|
|
1244
|
+
const contentWrapper = doc.createElement('div');
|
|
1245
|
+
contentWrapper.style.display = 'flex';
|
|
1246
|
+
contentWrapper.style.flexDirection = 'column';
|
|
1247
|
+
contentWrapper.style.gap = '10px';
|
|
1248
|
+
contentWrapper.style.width = '100%';
|
|
1249
|
+
contentWrapper.style.height = '100%';
|
|
1250
|
+
contentWrapper.appendChild(header);
|
|
1251
|
+
contentWrapper.appendChild(scrollForm);
|
|
1252
|
+
contentWrapper.appendChild(logList);
|
|
1253
|
+
container.appendChild(contentWrapper);
|
|
1254
|
+
container.appendChild(bubble);
|
|
1255
|
+
const resizeHandle = doc.createElement('div');
|
|
1256
|
+
resizeHandle.style.position = 'absolute';
|
|
1257
|
+
resizeHandle.style.right = '6px';
|
|
1258
|
+
resizeHandle.style.bottom = '6px';
|
|
1259
|
+
resizeHandle.style.width = '14px';
|
|
1260
|
+
resizeHandle.style.height = '14px';
|
|
1261
|
+
resizeHandle.style.cursor = 'nwse-resize';
|
|
1262
|
+
resizeHandle.style.borderRight = '2px solid #4b5563';
|
|
1263
|
+
resizeHandle.style.borderBottom = '2px solid #4b5563';
|
|
1264
|
+
resizeHandle.addEventListener('mousedown', event => {
|
|
1265
|
+
this.startResize(event);
|
|
1266
|
+
});
|
|
1267
|
+
container.appendChild(resizeHandle);
|
|
1268
|
+
doc.body.appendChild(container);
|
|
1269
|
+
this.container = container;
|
|
1270
|
+
this.contentWrapper = contentWrapper;
|
|
1271
|
+
this.bubble = bubble;
|
|
1272
|
+
this.logList = logList;
|
|
1273
|
+
this.selectorInput = selectorInput;
|
|
1274
|
+
this.distanceInput = distanceInput;
|
|
1275
|
+
this.collapseToggle = collapseButton;
|
|
1276
|
+
this.resizeHandle = resizeHandle;
|
|
1277
|
+
this.applyState();
|
|
1278
|
+
}
|
|
1279
|
+
startDrag(event) {
|
|
1280
|
+
if (event.button !== 0) {
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
if (!this.container) {
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
const rect = this.container.getBoundingClientRect();
|
|
1287
|
+
this.isDragging = true;
|
|
1288
|
+
this.wasDragged = false;
|
|
1289
|
+
this.dragMoved = false;
|
|
1290
|
+
this.dragOffsetX = event.clientX - rect.left;
|
|
1291
|
+
this.dragOffsetY = event.clientY - rect.top;
|
|
1292
|
+
this.container.style.transition = 'none';
|
|
1293
|
+
this.doc.addEventListener('mousemove', this.onDragging);
|
|
1294
|
+
this.doc.addEventListener('mouseup', this.onDragEnd);
|
|
1295
|
+
if (!this.state.collapsed) {
|
|
1296
|
+
event.preventDefault();
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
startResize(event) {
|
|
1300
|
+
if (event.button !== 0 || this.state.collapsed) {
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
if (!this.container) {
|
|
1304
|
+
return;
|
|
1305
|
+
}
|
|
1306
|
+
const rect = this.container.getBoundingClientRect();
|
|
1307
|
+
this.isResizing = true;
|
|
1308
|
+
this.resizeStartX = event.clientX;
|
|
1309
|
+
this.resizeStartY = event.clientY;
|
|
1310
|
+
this.resizeStartWidth = rect.width;
|
|
1311
|
+
this.resizeStartHeight = rect.height;
|
|
1312
|
+
this.doc.addEventListener('mousemove', this.onResizing);
|
|
1313
|
+
this.doc.addEventListener('mouseup', this.onResizeEnd);
|
|
1314
|
+
event.preventDefault();
|
|
1315
|
+
event.stopPropagation();
|
|
1316
|
+
}
|
|
1317
|
+
applyPosition() {
|
|
1318
|
+
if (!this.container) {
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
this.container.style.left = `${this.state.left}px`;
|
|
1322
|
+
this.container.style.top = `${this.state.top}px`;
|
|
1323
|
+
}
|
|
1324
|
+
applySize() {
|
|
1325
|
+
if (!this.container) {
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
const width = Math.max(VirtualScrollDebugOverlay.minWidth, this.state.width || VirtualScrollDebugOverlay.defaultWidth);
|
|
1329
|
+
const height = Math.max(VirtualScrollDebugOverlay.minHeight, this.state.height || VirtualScrollDebugOverlay.defaultHeight);
|
|
1330
|
+
this.state.width = width;
|
|
1331
|
+
this.state.height = height;
|
|
1332
|
+
this.container.style.width = `${width}px`;
|
|
1333
|
+
this.container.style.height = `${height}px`;
|
|
1334
|
+
}
|
|
1335
|
+
applyCollapsedState() {
|
|
1336
|
+
if (!this.container || !this.contentWrapper || !this.bubble || !this.collapseToggle) {
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
if (this.state.collapsed) {
|
|
1340
|
+
this.container.style.width = '36px';
|
|
1341
|
+
this.container.style.height = '36px';
|
|
1342
|
+
this.container.style.minWidth = '';
|
|
1343
|
+
this.container.style.minHeight = '';
|
|
1344
|
+
this.container.style.padding = '0';
|
|
1345
|
+
this.container.style.borderRadius = '50%';
|
|
1346
|
+
this.container.style.display = 'flex';
|
|
1347
|
+
this.container.style.flexDirection = 'row';
|
|
1348
|
+
this.container.style.alignItems = 'center';
|
|
1349
|
+
this.container.style.justifyContent = 'center';
|
|
1350
|
+
this.container.style.cursor = 'move';
|
|
1351
|
+
this.contentWrapper.style.display = 'none';
|
|
1352
|
+
this.bubble.style.display = 'flex';
|
|
1353
|
+
this.collapseToggle.textContent = '展开';
|
|
1354
|
+
this.resizeHandle.style.display = 'none';
|
|
1355
|
+
}
|
|
1356
|
+
else {
|
|
1357
|
+
this.applySize();
|
|
1358
|
+
this.container.style.padding = '12px';
|
|
1359
|
+
this.container.style.borderRadius = '10px';
|
|
1360
|
+
this.container.style.display = 'flex';
|
|
1361
|
+
this.container.style.flexDirection = 'column';
|
|
1362
|
+
this.container.style.gap = '10px';
|
|
1363
|
+
this.container.style.cursor = 'default';
|
|
1364
|
+
this.contentWrapper.style.display = 'flex';
|
|
1365
|
+
this.bubble.style.display = 'none';
|
|
1366
|
+
this.collapseToggle.textContent = '折叠';
|
|
1367
|
+
this.resizeHandle.style.display = 'block';
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
setCollapsed(collapsed) {
|
|
1371
|
+
this.state.collapsed = collapsed;
|
|
1372
|
+
this.applyCollapsedState();
|
|
1373
|
+
this.persistState();
|
|
1374
|
+
}
|
|
1375
|
+
applyState() {
|
|
1376
|
+
this.applyPosition();
|
|
1377
|
+
this.applyCollapsedState();
|
|
1378
|
+
}
|
|
1379
|
+
loadState() {
|
|
1380
|
+
try {
|
|
1381
|
+
const raw = this.doc.defaultView?.localStorage?.getItem(VirtualScrollDebugOverlay.storageKey);
|
|
1382
|
+
if (raw) {
|
|
1383
|
+
const parsed = JSON.parse(raw);
|
|
1384
|
+
if (typeof parsed.left === 'number') {
|
|
1385
|
+
this.state.left = parsed.left;
|
|
1386
|
+
}
|
|
1387
|
+
if (typeof parsed.top === 'number') {
|
|
1388
|
+
this.state.top = parsed.top;
|
|
1389
|
+
}
|
|
1390
|
+
if (typeof parsed.collapsed === 'boolean') {
|
|
1391
|
+
this.state.collapsed = parsed.collapsed;
|
|
1392
|
+
}
|
|
1393
|
+
if (typeof parsed.width === 'number') {
|
|
1394
|
+
this.state.width = parsed.width;
|
|
1395
|
+
}
|
|
1396
|
+
if (typeof parsed.height === 'number') {
|
|
1397
|
+
this.state.height = parsed.height;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
catch {
|
|
1402
|
+
// ignore storage errors
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
persistState() {
|
|
1406
|
+
try {
|
|
1407
|
+
this.doc.defaultView?.localStorage?.setItem(VirtualScrollDebugOverlay.storageKey, JSON.stringify(this.state));
|
|
1408
|
+
}
|
|
1409
|
+
catch {
|
|
1410
|
+
// ignore storage errors
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
appendLog(type, ...args) {
|
|
1414
|
+
if (!this.logList) {
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
const item = this.doc.createElement('div');
|
|
1418
|
+
item.style.display = 'flex';
|
|
1419
|
+
item.style.gap = '6px';
|
|
1420
|
+
item.style.alignItems = 'flex-start';
|
|
1421
|
+
item.style.wordBreak = 'break-all';
|
|
1422
|
+
item.style.color = type === 'warn' ? '#fbbf24' : '#9ca3af';
|
|
1423
|
+
const time = this.doc.createElement('span');
|
|
1424
|
+
time.textContent = new Date().toLocaleTimeString();
|
|
1425
|
+
time.style.color = '#6b7280';
|
|
1426
|
+
time.style.flexShrink = '0';
|
|
1427
|
+
time.style.width = '72px';
|
|
1428
|
+
const text = this.doc.createElement('span');
|
|
1429
|
+
text.textContent = `[${type}] ${args.map(arg => this.formatValue(arg)).join(' ')}`;
|
|
1430
|
+
item.appendChild(time);
|
|
1431
|
+
item.appendChild(text);
|
|
1432
|
+
this.logList.appendChild(item);
|
|
1433
|
+
}
|
|
1434
|
+
formatValue(value) {
|
|
1435
|
+
if (typeof value === 'string') {
|
|
1436
|
+
return value;
|
|
1437
|
+
}
|
|
1438
|
+
try {
|
|
1439
|
+
return JSON.stringify(value);
|
|
1440
|
+
}
|
|
1441
|
+
catch (error) {
|
|
1442
|
+
return String(value);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
setScrollTopValue(value) {
|
|
1446
|
+
if (this.distanceInput) {
|
|
1447
|
+
this.distanceInput.value = String(value ?? 0);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
const isDebug = localStorage.getItem(SLATE_DEBUG_KEY) === 'true';
|
|
1453
|
+
const isDebugScrollTop = localStorage.getItem(SLATE_DEBUG_KEY_SCROLL_TOP) === 'true';
|
|
1454
|
+
const ELEMENT_KEY_TO_HEIGHTS = new WeakMap();
|
|
1455
|
+
const EDITOR_TO_BUSINESS_TOP = new WeakMap();
|
|
1456
|
+
const EDITOR_TO_ROOT_NODE_WIDTH = new WeakMap();
|
|
1457
|
+
const debugLog = (type, ...args) => {
|
|
1458
|
+
const doc = document;
|
|
1459
|
+
VirtualScrollDebugOverlay.log(doc, type, ...args);
|
|
1460
|
+
};
|
|
1461
|
+
const measureHeightByElement = (editor, element) => {
|
|
1462
|
+
const key = AngularEditor.findKey(editor, element);
|
|
1463
|
+
const view = ELEMENT_TO_COMPONENT.get(element);
|
|
1464
|
+
if (!view) {
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
const ret = view.getRealHeight();
|
|
1468
|
+
const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
|
|
1469
|
+
heights.set(key.id, ret);
|
|
1470
|
+
return ret;
|
|
1471
|
+
};
|
|
1472
|
+
const measureHeightByIndics = (editor, indics, force = false) => {
|
|
1473
|
+
let hasChanged = false;
|
|
1474
|
+
indics.forEach((index, i) => {
|
|
1475
|
+
const element = editor.children[index];
|
|
1476
|
+
const preHeight = getRealHeightByElement(editor, element, 0);
|
|
1477
|
+
if (preHeight && !force) {
|
|
1478
|
+
if (isDebug) {
|
|
1479
|
+
const height = measureHeightByElement(editor, element);
|
|
1480
|
+
if (height !== preHeight) {
|
|
1481
|
+
debugLog('warn', 'measureHeightByElement: height not equal, index: ', index, 'preHeight: ', preHeight, 'height: ', height);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
hasChanged = true;
|
|
1487
|
+
measureHeightByElement(editor, element);
|
|
1488
|
+
});
|
|
1489
|
+
return hasChanged;
|
|
1490
|
+
};
|
|
1491
|
+
const getBusinessTop = (editor) => {
|
|
1492
|
+
return EDITOR_TO_BUSINESS_TOP.get(editor) ?? 0;
|
|
1493
|
+
};
|
|
1494
|
+
const getRealHeightByElement = (editor, element, defaultHeight = VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT) => {
|
|
1495
|
+
const isVisible = editor.isVisible(element);
|
|
1496
|
+
if (!isVisible) {
|
|
1497
|
+
return 0;
|
|
1498
|
+
}
|
|
1499
|
+
const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
|
|
1500
|
+
const key = AngularEditor.findKey(editor, element);
|
|
1501
|
+
const height = heights?.get(key.id);
|
|
1502
|
+
if (typeof height === 'number') {
|
|
1503
|
+
return height;
|
|
1504
|
+
}
|
|
1505
|
+
if (heights?.has(key.id)) {
|
|
1506
|
+
console.error('getBlockHeight: invalid height value', key.id, height);
|
|
1507
|
+
}
|
|
1508
|
+
return defaultHeight;
|
|
1509
|
+
};
|
|
1510
|
+
const buildHeightsAndAccumulatedHeights = (editor) => {
|
|
1511
|
+
const children = (editor.children || []);
|
|
1512
|
+
const heights = new Array(children.length);
|
|
1513
|
+
const accumulatedHeights = new Array(children.length + 1);
|
|
1514
|
+
accumulatedHeights[0] = 0;
|
|
1515
|
+
for (let i = 0; i < children.length; i++) {
|
|
1516
|
+
const height = getRealHeightByElement(editor, children[i]);
|
|
1517
|
+
heights[i] = height;
|
|
1518
|
+
accumulatedHeights[i + 1] = accumulatedHeights[i] + height;
|
|
1519
|
+
}
|
|
1520
|
+
return { heights, accumulatedHeights };
|
|
1521
|
+
};
|
|
1522
|
+
const calculateVirtualTopHeight = (editor, startIndex) => {
|
|
1523
|
+
const { accumulatedHeights } = buildHeightsAndAccumulatedHeights(editor);
|
|
1524
|
+
return accumulatedHeights[startIndex] ?? 0;
|
|
1525
|
+
};
|
|
1526
|
+
const scrollToElement = (editor, element, scrollTo) => {
|
|
1527
|
+
const children = editor.children;
|
|
1528
|
+
if (!children.length) {
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
const anchorIndex = children.findIndex(item => item === element);
|
|
1532
|
+
if (anchorIndex < 0) {
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
const { accumulatedHeights } = buildHeightsAndAccumulatedHeights(editor);
|
|
1536
|
+
scrollTo((accumulatedHeights[anchorIndex] ?? 0) + getBusinessTop(editor));
|
|
1537
|
+
};
|
|
1538
|
+
|
|
953
1539
|
const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
|
|
954
1540
|
let e = editor;
|
|
955
1541
|
let { apply } = e;
|
|
@@ -967,7 +1553,14 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
|
|
|
967
1553
|
}
|
|
968
1554
|
// Create a fake selection so that we can add a Base64-encoded copy of the
|
|
969
1555
|
// fragment to the HTML, to decode on future pastes.
|
|
970
|
-
|
|
1556
|
+
let domRange;
|
|
1557
|
+
if (AngularEditor.isEnabledVirtualScroll(e)) {
|
|
1558
|
+
const virtualScrollSelection = EDITOR_TO_VIRTUAL_SCROLL_SELECTION.get(e);
|
|
1559
|
+
if (virtualScrollSelection) {
|
|
1560
|
+
domRange = AngularEditor.toDOMRange(e, virtualScrollSelection);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
domRange = domRange ?? AngularEditor.toDOMRange(e, selection);
|
|
971
1564
|
let contents = domRange.cloneContents();
|
|
972
1565
|
let attach = contents.childNodes[0];
|
|
973
1566
|
// Make sure attach is non-empty, since empty nodes will not get copied.
|
|
@@ -1138,6 +1731,9 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
|
|
|
1138
1731
|
e.selectAll = () => {
|
|
1139
1732
|
Transforms.select(e, []);
|
|
1140
1733
|
};
|
|
1734
|
+
e.isVisible = element => {
|
|
1735
|
+
return true;
|
|
1736
|
+
};
|
|
1141
1737
|
return e;
|
|
1142
1738
|
};
|
|
1143
1739
|
|
|
@@ -1798,6 +2394,7 @@ class BaseElementFlavour extends BaseFlavour {
|
|
|
1798
2394
|
if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
|
|
1799
2395
|
ELEMENT_TO_COMPONENT.delete(this.element);
|
|
1800
2396
|
}
|
|
2397
|
+
this.listRender.destroy();
|
|
1801
2398
|
this.nativeElement?.remove();
|
|
1802
2399
|
}
|
|
1803
2400
|
onContextChange() {
|
|
@@ -2194,6 +2791,9 @@ class LeavesRender {
|
|
|
2194
2791
|
});
|
|
2195
2792
|
return { decoratedLeaves, contexts };
|
|
2196
2793
|
}
|
|
2794
|
+
destroy() {
|
|
2795
|
+
this.views.forEach(view => view.destroy());
|
|
2796
|
+
}
|
|
2197
2797
|
}
|
|
2198
2798
|
function getContext$1(index, leafContexts) {
|
|
2199
2799
|
return leafContexts[index];
|
|
@@ -2236,6 +2836,7 @@ class BaseTextFlavour extends BaseFlavour {
|
|
|
2236
2836
|
NODE_TO_ELEMENT.delete(this.text);
|
|
2237
2837
|
}
|
|
2238
2838
|
ELEMENT_TO_NODE.delete(this.nativeElement);
|
|
2839
|
+
this.leavesRender.destroy();
|
|
2239
2840
|
this.nativeElement?.remove();
|
|
2240
2841
|
}
|
|
2241
2842
|
onContextChange() {
|
|
@@ -2270,20 +2871,39 @@ const createText = (text) => {
|
|
|
2270
2871
|
return { nativeElement };
|
|
2271
2872
|
};
|
|
2272
2873
|
|
|
2874
|
+
const setPreRenderingElementStyle = (editor, rootNode, isClear = false) => {
|
|
2875
|
+
if (isClear) {
|
|
2876
|
+
rootNode.style.top = '';
|
|
2877
|
+
rootNode.style.width = '';
|
|
2878
|
+
rootNode.style.position = '';
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2881
|
+
const preRenderingWidth = EDITOR_TO_ROOT_NODE_WIDTH.get(editor) ?? 0;
|
|
2882
|
+
rootNode.style.top = '-100%';
|
|
2883
|
+
if (preRenderingWidth) {
|
|
2884
|
+
rootNode.style.width = `${preRenderingWidth}px`;
|
|
2885
|
+
}
|
|
2886
|
+
else {
|
|
2887
|
+
rootNode.style.width = '100%';
|
|
2888
|
+
}
|
|
2889
|
+
rootNode.style.position = 'absolute';
|
|
2890
|
+
};
|
|
2273
2891
|
class ListRender {
|
|
2274
2892
|
constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
|
|
2275
2893
|
this.viewContext = viewContext;
|
|
2276
2894
|
this.viewContainerRef = viewContainerRef;
|
|
2277
2895
|
this.getOutletParent = getOutletParent;
|
|
2278
2896
|
this.getOutletElement = getOutletElement;
|
|
2897
|
+
this.children = [];
|
|
2279
2898
|
this.views = [];
|
|
2280
2899
|
this.blockCards = [];
|
|
2281
2900
|
this.contexts = [];
|
|
2282
2901
|
this.viewTypes = [];
|
|
2283
2902
|
this.differ = null;
|
|
2284
2903
|
this.initialized = false;
|
|
2904
|
+
this.preRenderingHTMLElement = [];
|
|
2285
2905
|
}
|
|
2286
|
-
initialize(children, parent, childrenContext) {
|
|
2906
|
+
initialize(children, parent, childrenContext, preRenderingCount = 0) {
|
|
2287
2907
|
this.initialized = true;
|
|
2288
2908
|
this.children = children;
|
|
2289
2909
|
const isRoot = parent === this.viewContext.editor;
|
|
@@ -2309,15 +2929,35 @@ class ListRender {
|
|
|
2309
2929
|
executeAfterViewInit(this.viewContext.editor);
|
|
2310
2930
|
}
|
|
2311
2931
|
}
|
|
2312
|
-
update(children, parent, childrenContext) {
|
|
2932
|
+
update(children, parent, childrenContext, preRenderingCount = 0) {
|
|
2313
2933
|
if (!this.initialized || this.children.length === 0) {
|
|
2314
|
-
this.initialize(children, parent, childrenContext);
|
|
2934
|
+
this.initialize(children, parent, childrenContext, preRenderingCount);
|
|
2315
2935
|
return;
|
|
2316
2936
|
}
|
|
2317
2937
|
if (!this.differ) {
|
|
2318
2938
|
throw new Error('Exception: Can not find differ ');
|
|
2319
2939
|
}
|
|
2320
2940
|
const outletParent = this.getOutletParent();
|
|
2941
|
+
if (this.preRenderingHTMLElement.length > 0) {
|
|
2942
|
+
const preRenderingElement = [...this.preRenderingHTMLElement];
|
|
2943
|
+
preRenderingElement.forEach((rootNodes, index) => {
|
|
2944
|
+
const slateElement = this.children[index];
|
|
2945
|
+
if (slateElement && children.indexOf(slateElement) >= 0) {
|
|
2946
|
+
rootNodes.forEach(rootNode => {
|
|
2947
|
+
setPreRenderingElementStyle(this.viewContext.editor, rootNode, true);
|
|
2948
|
+
});
|
|
2949
|
+
if (isDebug) {
|
|
2950
|
+
debugLog('log', 'preRenderingHTMLElement index: ', this.viewContext.editor.children.indexOf(this.children[index]), 'is clear true');
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
else {
|
|
2954
|
+
if (isDebug) {
|
|
2955
|
+
debugLog('log', 'preRenderingHTMLElement index: ', this.viewContext.editor.children.indexOf(this.children[index]), 'do not clear since it would be removed soon');
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
});
|
|
2959
|
+
this.preRenderingHTMLElement = [];
|
|
2960
|
+
}
|
|
2321
2961
|
const diffResult = this.differ.diff(children);
|
|
2322
2962
|
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2323
2963
|
const isRoot = parent === this.viewContext.editor;
|
|
@@ -2415,6 +3055,29 @@ class ListRender {
|
|
|
2415
3055
|
});
|
|
2416
3056
|
this.contexts = newContexts;
|
|
2417
3057
|
}
|
|
3058
|
+
if (preRenderingCount > 0) {
|
|
3059
|
+
for (let i = 0; i < preRenderingCount; i++) {
|
|
3060
|
+
const rootNodes = [...getRootNodes(this.views[i], this.blockCards[i])];
|
|
3061
|
+
rootNodes.forEach(rootNode => {
|
|
3062
|
+
setPreRenderingElementStyle(this.viewContext.editor, rootNode);
|
|
3063
|
+
});
|
|
3064
|
+
this.preRenderingHTMLElement.push(rootNodes);
|
|
3065
|
+
if (isDebug) {
|
|
3066
|
+
debugLog('log', 'preRenderingHTMLElement index: ', this.viewContext.editor.children.indexOf(children[i]));
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
if (isDebug) {
|
|
3071
|
+
for (let i = 0; i < children.length; i++) {
|
|
3072
|
+
const rootNodes = [...getRootNodes(this.views[i], this.blockCards[i])];
|
|
3073
|
+
const index = this.viewContext.editor.children.indexOf(children[i]);
|
|
3074
|
+
const height = getRealHeightByElement(this.viewContext.editor, children[i]);
|
|
3075
|
+
rootNodes.forEach(rootNode => {
|
|
3076
|
+
rootNode.setAttribute('debug-index', index.toString());
|
|
3077
|
+
rootNode.setAttribute('debug-height', height.toString());
|
|
3078
|
+
});
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
2418
3081
|
}
|
|
2419
3082
|
destroy() {
|
|
2420
3083
|
this.children.forEach((element, index) => {
|
|
@@ -2425,6 +3088,7 @@ class ListRender {
|
|
|
2425
3088
|
this.blockCards[index].destroy();
|
|
2426
3089
|
}
|
|
2427
3090
|
});
|
|
3091
|
+
this.children = [];
|
|
2428
3092
|
this.views = [];
|
|
2429
3093
|
this.blockCards = [];
|
|
2430
3094
|
this.contexts = [];
|
|
@@ -2567,39 +3231,18 @@ function executeAfterViewInit(editor) {
|
|
|
2567
3231
|
clearAfterViewInitQueue(editor);
|
|
2568
3232
|
}
|
|
2569
3233
|
|
|
2570
|
-
const JUST_NOW_UPDATED_VIRTUAL_VIEW = new WeakMap();
|
|
2571
3234
|
// not correctly clipboardData on beforeinput
|
|
2572
3235
|
const forceOnDOMPaste = IS_SAFARI;
|
|
2573
|
-
const isDebug = localStorage.getItem(SLATE_DEBUG_KEY) === 'true';
|
|
2574
3236
|
class SlateEditable {
|
|
2575
3237
|
set virtualScroll(config) {
|
|
2576
|
-
this.
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
if (diff.isMissingTop) {
|
|
2585
|
-
const result = this.remeasureHeightByIndics(diff.diffTopRenderedIndexes);
|
|
2586
|
-
if (result) {
|
|
2587
|
-
virtualView = this.refreshVirtualView();
|
|
2588
|
-
diff = this.diffVirtualView(virtualView, 'second');
|
|
2589
|
-
if (!diff.isDiff) {
|
|
2590
|
-
return;
|
|
2591
|
-
}
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
this.applyVirtualView(virtualView);
|
|
2595
|
-
if (this.listRender.initialized) {
|
|
2596
|
-
this.listRender.update(virtualView.renderedChildren, this.editor, this.context);
|
|
2597
|
-
if (!AngularEditor.isReadOnly(this.editor) && this.editor.selection) {
|
|
2598
|
-
this.toNativeSelection();
|
|
2599
|
-
}
|
|
2600
|
-
}
|
|
2601
|
-
this.scheduleMeasureVisibleHeights();
|
|
2602
|
-
});
|
|
3238
|
+
this.virtualScrollConfig = config;
|
|
3239
|
+
if (isDebugScrollTop) {
|
|
3240
|
+
debugLog('log', 'virtualScrollConfig scrollTop:', config.scrollTop);
|
|
3241
|
+
}
|
|
3242
|
+
IS_ENABLED_VIRTUAL_SCROLL.set(this.editor, config.enabled);
|
|
3243
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3244
|
+
this.tryUpdateVirtualViewport();
|
|
3245
|
+
}
|
|
2603
3246
|
}
|
|
2604
3247
|
get hasBeforeInputSupport() {
|
|
2605
3248
|
return HAS_BEFORE_INPUT_SUPPORT;
|
|
@@ -2644,16 +3287,16 @@ class SlateEditable {
|
|
|
2644
3287
|
return null;
|
|
2645
3288
|
}
|
|
2646
3289
|
};
|
|
2647
|
-
this.
|
|
3290
|
+
this.virtualScrollConfig = {
|
|
2648
3291
|
enabled: false,
|
|
2649
3292
|
scrollTop: 0,
|
|
2650
|
-
viewportHeight: 0
|
|
3293
|
+
viewportHeight: 0,
|
|
3294
|
+
viewportBoundingTop: 0,
|
|
3295
|
+
scrollContainer: null
|
|
2651
3296
|
};
|
|
2652
|
-
this.
|
|
2653
|
-
this.
|
|
2654
|
-
this.
|
|
2655
|
-
// the height from scroll container top to editor top height element
|
|
2656
|
-
this.businessHeight = 0;
|
|
3297
|
+
this.inViewportChildren = [];
|
|
3298
|
+
this.inViewportIndics = [];
|
|
3299
|
+
this.keyHeightMap = new Map();
|
|
2657
3300
|
this.virtualScrollInitialized = false;
|
|
2658
3301
|
}
|
|
2659
3302
|
ngOnInit() {
|
|
@@ -2665,6 +3308,7 @@ class SlateEditable {
|
|
|
2665
3308
|
NODE_TO_ELEMENT.set(this.editor, this.elementRef.nativeElement);
|
|
2666
3309
|
ELEMENT_TO_NODE.set(this.elementRef.nativeElement, this.editor);
|
|
2667
3310
|
IS_READ_ONLY.set(this.editor, this.readonly);
|
|
3311
|
+
ELEMENT_KEY_TO_HEIGHTS.set(this.editor, this.keyHeightMap);
|
|
2668
3312
|
EDITOR_TO_ON_CHANGE.set(this.editor, () => {
|
|
2669
3313
|
this.ngZone.run(() => {
|
|
2670
3314
|
this.onChange();
|
|
@@ -2678,7 +3322,7 @@ class SlateEditable {
|
|
|
2678
3322
|
// add browser class
|
|
2679
3323
|
let browserClass = IS_FIREFOX ? 'firefox' : IS_SAFARI ? 'safari' : '';
|
|
2680
3324
|
browserClass && this.elementRef.nativeElement.classList.add(browserClass);
|
|
2681
|
-
this.
|
|
3325
|
+
this.initializeVirtualScroll();
|
|
2682
3326
|
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
|
|
2683
3327
|
}
|
|
2684
3328
|
ngOnChanges(simpleChanges) {
|
|
@@ -2710,16 +3354,29 @@ class SlateEditable {
|
|
|
2710
3354
|
if (value && value.length) {
|
|
2711
3355
|
this.editor.children = value;
|
|
2712
3356
|
this.initializeContext();
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
3357
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3358
|
+
const virtualView = this.calculateVirtualViewport();
|
|
3359
|
+
this.applyVirtualView(virtualView);
|
|
3360
|
+
const childrenForRender = virtualView.inViewportChildren;
|
|
3361
|
+
if (isDebug) {
|
|
3362
|
+
debugLog('log', 'writeValue calculate: ', virtualView.inViewportIndics, 'initialized: ', this.listRender.initialized);
|
|
3363
|
+
}
|
|
3364
|
+
if (!this.listRender.initialized) {
|
|
3365
|
+
this.listRender.initialize(childrenForRender, this.editor, this.context);
|
|
3366
|
+
}
|
|
3367
|
+
else {
|
|
3368
|
+
const { preRenderingCount, childrenWithPreRendering } = this.handlePreRendering();
|
|
3369
|
+
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount);
|
|
3370
|
+
}
|
|
2718
3371
|
}
|
|
2719
3372
|
else {
|
|
2720
|
-
this.listRender.
|
|
3373
|
+
if (!this.listRender.initialized) {
|
|
3374
|
+
this.listRender.initialize(this.editor.children, this.editor, this.context);
|
|
3375
|
+
}
|
|
3376
|
+
else {
|
|
3377
|
+
this.listRender.update(this.editor.children, this.editor, this.context);
|
|
3378
|
+
}
|
|
2721
3379
|
}
|
|
2722
|
-
this.scheduleMeasureVisibleHeights();
|
|
2723
3380
|
this.cdr.markForCheck();
|
|
2724
3381
|
}
|
|
2725
3382
|
}
|
|
@@ -2750,26 +3407,45 @@ class SlateEditable {
|
|
|
2750
3407
|
this.addEventListener(event.name, () => { });
|
|
2751
3408
|
});
|
|
2752
3409
|
}
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
3410
|
+
calculateVirtualScrollSelection(selection) {
|
|
3411
|
+
if (selection) {
|
|
3412
|
+
const isBlockCardCursor = AngularEditor.isBlockCardLeftCursor(this.editor) || AngularEditor.isBlockCardRightCursor(this.editor);
|
|
3413
|
+
const indics = this.inViewportIndics;
|
|
3414
|
+
if (indics.length > 0) {
|
|
3415
|
+
const currentVisibleRange = {
|
|
3416
|
+
anchor: Editor.start(this.editor, [indics[0]]),
|
|
3417
|
+
focus: Editor.end(this.editor, [indics[indics.length - 1]])
|
|
3418
|
+
};
|
|
3419
|
+
const [start, end] = Range.edges(selection);
|
|
3420
|
+
let forwardSelection = { anchor: start, focus: end };
|
|
3421
|
+
if (!isBlockCardCursor) {
|
|
3422
|
+
forwardSelection = { anchor: start, focus: end };
|
|
3423
|
+
}
|
|
3424
|
+
else {
|
|
3425
|
+
forwardSelection = { anchor: { path: start.path, offset: 0 }, focus: { path: end.path, offset: 0 } };
|
|
3426
|
+
}
|
|
3427
|
+
const intersectedSelection = Range.intersection(forwardSelection, currentVisibleRange);
|
|
3428
|
+
if (intersectedSelection && isBlockCardCursor) {
|
|
3429
|
+
return selection;
|
|
3430
|
+
}
|
|
3431
|
+
EDITOR_TO_VIRTUAL_SCROLL_SELECTION.set(this.editor, intersectedSelection);
|
|
3432
|
+
if (!intersectedSelection || !Range.equals(intersectedSelection, forwardSelection)) {
|
|
3433
|
+
if (isDebug) {
|
|
3434
|
+
debugLog('log', `selection is not in visible range, selection: ${JSON.stringify(selection)}, currentVisibleRange: ${JSON.stringify(currentVisibleRange)}, intersectedSelection: ${JSON.stringify(intersectedSelection)}`);
|
|
2771
3435
|
}
|
|
3436
|
+
return intersectedSelection;
|
|
2772
3437
|
}
|
|
3438
|
+
return selection;
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
EDITOR_TO_VIRTUAL_SCROLL_SELECTION.set(this.editor, null);
|
|
3442
|
+
return selection;
|
|
3443
|
+
}
|
|
3444
|
+
toNativeSelection(autoScroll = true) {
|
|
3445
|
+
try {
|
|
3446
|
+
let { selection } = this.editor;
|
|
3447
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3448
|
+
selection = this.calculateVirtualScrollSelection(selection);
|
|
2773
3449
|
}
|
|
2774
3450
|
const root = AngularEditor.findDocumentOrShadowRoot(this.editor);
|
|
2775
3451
|
const { activeElement } = root;
|
|
@@ -2831,13 +3507,24 @@ class SlateEditable {
|
|
|
2831
3507
|
domSelection.removeAllRanges();
|
|
2832
3508
|
}
|
|
2833
3509
|
setTimeout(() => {
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
3510
|
+
if (this.isEnabledVirtualScroll() &&
|
|
3511
|
+
!selection &&
|
|
3512
|
+
this.editor.selection &&
|
|
3513
|
+
autoScroll &&
|
|
3514
|
+
this.virtualScrollConfig.scrollContainer) {
|
|
3515
|
+
this.virtualScrollConfig.scrollContainer.scrollTop = this.virtualScrollConfig.scrollContainer.scrollTop + 100;
|
|
3516
|
+
this.isUpdatingSelection = false;
|
|
3517
|
+
return;
|
|
3518
|
+
}
|
|
3519
|
+
else {
|
|
3520
|
+
// handle scrolling in setTimeout because of
|
|
3521
|
+
// dom should not have updated immediately after listRender's updating
|
|
3522
|
+
newDomRange && autoScroll && this.scrollSelectionIntoView(this.editor, newDomRange);
|
|
3523
|
+
// COMPAT: In Firefox, it's not enough to create a range, you also need
|
|
3524
|
+
// to focus the contenteditable element too. (2016/11/16)
|
|
3525
|
+
if (newDomRange && IS_FIREFOX) {
|
|
3526
|
+
el.focus();
|
|
3527
|
+
}
|
|
2841
3528
|
}
|
|
2842
3529
|
this.isUpdatingSelection = false;
|
|
2843
3530
|
});
|
|
@@ -2858,10 +3545,12 @@ class SlateEditable {
|
|
|
2858
3545
|
ngDoCheck() { }
|
|
2859
3546
|
forceRender() {
|
|
2860
3547
|
this.updateContext();
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
3548
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3549
|
+
this.updateListRenderAndRemeasureHeights();
|
|
3550
|
+
}
|
|
3551
|
+
else {
|
|
3552
|
+
this.listRender.update(this.editor.children, this.editor, this.context);
|
|
3553
|
+
}
|
|
2865
3554
|
// repair collaborative editing when Chinese input is interrupted by other users' cursors
|
|
2866
3555
|
// when the DOMElement where the selection is located is removed
|
|
2867
3556
|
// the compositionupdate and compositionend events will no longer be fired
|
|
@@ -2900,10 +3589,29 @@ class SlateEditable {
|
|
|
2900
3589
|
render() {
|
|
2901
3590
|
const changed = this.updateContext();
|
|
2902
3591
|
if (changed) {
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
3592
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3593
|
+
this.updateListRenderAndRemeasureHeights();
|
|
3594
|
+
}
|
|
3595
|
+
else {
|
|
3596
|
+
this.listRender.update(this.editor.children, this.editor, this.context);
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
updateListRenderAndRemeasureHeights() {
|
|
3601
|
+
const virtualView = this.calculateVirtualViewport();
|
|
3602
|
+
const oldInViewportChildren = this.inViewportChildren;
|
|
3603
|
+
this.applyVirtualView(virtualView);
|
|
3604
|
+
const { preRenderingCount, childrenWithPreRendering } = this.handlePreRendering();
|
|
3605
|
+
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount);
|
|
3606
|
+
// 新增或者修改的才需要重算,计算出这个结果
|
|
3607
|
+
const remeasureIndics = [];
|
|
3608
|
+
this.inViewportChildren.forEach((child, index) => {
|
|
3609
|
+
if (oldInViewportChildren.indexOf(child) === -1) {
|
|
3610
|
+
remeasureIndics.push(this.inViewportIndics[index]);
|
|
3611
|
+
}
|
|
3612
|
+
});
|
|
3613
|
+
if (isDebug && remeasureIndics.length > 0) {
|
|
3614
|
+
console.log('remeasure height by indics: ', remeasureIndics);
|
|
2907
3615
|
}
|
|
2908
3616
|
}
|
|
2909
3617
|
updateContext() {
|
|
@@ -2966,14 +3674,14 @@ class SlateEditable {
|
|
|
2966
3674
|
decorations.push(...placeholderDecorations);
|
|
2967
3675
|
return decorations;
|
|
2968
3676
|
}
|
|
2969
|
-
|
|
2970
|
-
return !!(this.
|
|
3677
|
+
isEnabledVirtualScroll() {
|
|
3678
|
+
return !!(this.virtualScrollConfig && this.virtualScrollConfig.enabled);
|
|
2971
3679
|
}
|
|
2972
|
-
|
|
3680
|
+
initializeVirtualScroll() {
|
|
2973
3681
|
if (this.virtualScrollInitialized) {
|
|
2974
3682
|
return;
|
|
2975
3683
|
}
|
|
2976
|
-
if (this.
|
|
3684
|
+
if (this.isEnabledVirtualScroll()) {
|
|
2977
3685
|
this.virtualScrollInitialized = true;
|
|
2978
3686
|
this.virtualTopHeightElement = document.createElement('div');
|
|
2979
3687
|
this.virtualTopHeightElement.classList.add('virtual-top-height');
|
|
@@ -2986,140 +3694,256 @@ class SlateEditable {
|
|
|
2986
3694
|
this.elementRef.nativeElement.appendChild(this.virtualTopHeightElement);
|
|
2987
3695
|
this.elementRef.nativeElement.appendChild(this.virtualCenterOutlet);
|
|
2988
3696
|
this.elementRef.nativeElement.appendChild(this.virtualBottomHeightElement);
|
|
2989
|
-
|
|
3697
|
+
let editorResizeObserverRectWidth = this.elementRef.nativeElement.getBoundingClientRect().width;
|
|
3698
|
+
EDITOR_TO_ROOT_NODE_WIDTH.set(this.editor, this.virtualTopHeightElement.getBoundingClientRect().width);
|
|
3699
|
+
this.editorResizeObserver = new ResizeObserver(entries => {
|
|
3700
|
+
if (entries.length > 0 && entries[0].contentRect.width !== editorResizeObserverRectWidth) {
|
|
3701
|
+
editorResizeObserverRectWidth = entries[0].contentRect.width;
|
|
3702
|
+
this.keyHeightMap.clear();
|
|
3703
|
+
const remeasureIndics = this.inViewportIndics;
|
|
3704
|
+
measureHeightByIndics(this.editor, remeasureIndics, true);
|
|
3705
|
+
EDITOR_TO_ROOT_NODE_WIDTH.set(this.editor, this.virtualTopHeightElement.getBoundingClientRect().width);
|
|
3706
|
+
if (isDebug) {
|
|
3707
|
+
debugLog('log', 'editorResizeObserverRectWidth: ', editorResizeObserverRectWidth, 'EDITOR_TO_ROOT_NODE_WIDTH: ', EDITOR_TO_ROOT_NODE_WIDTH.get(this.editor));
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
});
|
|
3711
|
+
this.editorResizeObserver.observe(this.elementRef.nativeElement);
|
|
2990
3712
|
}
|
|
2991
3713
|
}
|
|
2992
|
-
|
|
3714
|
+
setVirtualSpaceHeight(topHeight, bottomHeight) {
|
|
2993
3715
|
if (!this.virtualScrollInitialized) {
|
|
2994
3716
|
return;
|
|
2995
3717
|
}
|
|
2996
3718
|
this.virtualTopHeightElement.style.height = `${topHeight}px`;
|
|
2997
|
-
|
|
3719
|
+
if (bottomHeight !== undefined) {
|
|
3720
|
+
this.virtualBottomHeightElement.style.height = `${bottomHeight}px`;
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
getActualVirtualTopHeight() {
|
|
3724
|
+
if (!this.virtualScrollInitialized) {
|
|
3725
|
+
return 0;
|
|
3726
|
+
}
|
|
3727
|
+
return parseFloat(this.virtualTopHeightElement.style.height.replace('px', ''));
|
|
3728
|
+
}
|
|
3729
|
+
handlePreRendering() {
|
|
3730
|
+
let preRenderingCount = 1;
|
|
3731
|
+
const childrenWithPreRendering = [...this.inViewportChildren];
|
|
3732
|
+
if (this.inViewportIndics[0] !== 0) {
|
|
3733
|
+
childrenWithPreRendering.unshift(this.editor.children[this.inViewportIndics[0] - 1]);
|
|
3734
|
+
}
|
|
3735
|
+
else {
|
|
3736
|
+
preRenderingCount = 0;
|
|
3737
|
+
}
|
|
3738
|
+
const lastIndex = this.inViewportIndics[this.inViewportIndics.length - 1];
|
|
3739
|
+
if (lastIndex !== this.editor.children.length - 1) {
|
|
3740
|
+
childrenWithPreRendering.push(this.editor.children[lastIndex + 1]);
|
|
3741
|
+
}
|
|
3742
|
+
return { preRenderingCount, childrenWithPreRendering };
|
|
3743
|
+
}
|
|
3744
|
+
tryUpdateVirtualViewport() {
|
|
3745
|
+
if (isDebug) {
|
|
3746
|
+
debugLog('log', 'tryUpdateVirtualViewport');
|
|
3747
|
+
}
|
|
3748
|
+
if (this.inViewportIndics.length > 0) {
|
|
3749
|
+
const topHeight = this.getActualVirtualTopHeight();
|
|
3750
|
+
const refreshVirtualTopHeight = calculateVirtualTopHeight(this.editor, this.inViewportIndics[0]);
|
|
3751
|
+
if (topHeight !== refreshVirtualTopHeight) {
|
|
3752
|
+
if (isDebug) {
|
|
3753
|
+
debugLog('log', 'update top height since dirty state(正数减去高度,负数代表增加高度): ', topHeight - refreshVirtualTopHeight);
|
|
3754
|
+
}
|
|
3755
|
+
this.setVirtualSpaceHeight(refreshVirtualTopHeight);
|
|
3756
|
+
return;
|
|
3757
|
+
}
|
|
3758
|
+
}
|
|
3759
|
+
this.tryUpdateVirtualViewportAnimId && cancelAnimationFrame(this.tryUpdateVirtualViewportAnimId);
|
|
3760
|
+
this.tryUpdateVirtualViewportAnimId = requestAnimationFrame(() => {
|
|
3761
|
+
if (isDebug) {
|
|
3762
|
+
debugLog('log', 'tryUpdateVirtualViewport Anim start');
|
|
3763
|
+
}
|
|
3764
|
+
let virtualView = this.calculateVirtualViewport();
|
|
3765
|
+
let diff = this.diffVirtualViewport(virtualView);
|
|
3766
|
+
if (diff.isDifferent && diff.needRemoveOnTop) {
|
|
3767
|
+
const remeasureIndics = diff.changedIndexesOfTop;
|
|
3768
|
+
const changed = measureHeightByIndics(this.editor, remeasureIndics);
|
|
3769
|
+
if (changed) {
|
|
3770
|
+
virtualView = this.calculateVirtualViewport();
|
|
3771
|
+
diff = this.diffVirtualViewport(virtualView, 'second');
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
if (diff.isDifferent) {
|
|
3775
|
+
this.applyVirtualView(virtualView);
|
|
3776
|
+
if (this.listRender.initialized) {
|
|
3777
|
+
const { preRenderingCount, childrenWithPreRendering } = this.handlePreRendering();
|
|
3778
|
+
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount);
|
|
3779
|
+
if (diff.needAddOnTop) {
|
|
3780
|
+
const remeasureAddedIndics = diff.changedIndexesOfTop;
|
|
3781
|
+
if (isDebug) {
|
|
3782
|
+
debugLog('log', 'needAddOnTop to remeasure heights: ', remeasureAddedIndics);
|
|
3783
|
+
}
|
|
3784
|
+
const startIndexBeforeAdd = diff.changedIndexesOfTop[diff.changedIndexesOfTop.length - 1] + 1;
|
|
3785
|
+
const topHeightBeforeAdd = virtualView.accumulatedHeights[startIndexBeforeAdd];
|
|
3786
|
+
const changed = measureHeightByIndics(this.editor, remeasureAddedIndics);
|
|
3787
|
+
if (changed) {
|
|
3788
|
+
const newHeights = buildHeightsAndAccumulatedHeights(this.editor);
|
|
3789
|
+
const actualTopHeightAfterAdd = newHeights.accumulatedHeights[startIndexBeforeAdd];
|
|
3790
|
+
const newTopHeight = virtualView.top - (actualTopHeightAfterAdd - topHeightBeforeAdd);
|
|
3791
|
+
this.setVirtualSpaceHeight(newTopHeight);
|
|
3792
|
+
if (isDebug) {
|
|
3793
|
+
debugLog('log', `update top height since will add element in top(正数减去高度,负数代表增加高度): ${actualTopHeightAfterAdd - topHeightBeforeAdd}`);
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
if (!AngularEditor.isReadOnly(this.editor) && this.editor.selection) {
|
|
3798
|
+
this.toNativeSelection(false);
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
if (isDebug) {
|
|
3803
|
+
debugLog('log', 'tryUpdateVirtualViewport Anim end');
|
|
3804
|
+
}
|
|
3805
|
+
});
|
|
2998
3806
|
}
|
|
2999
|
-
|
|
3807
|
+
calculateVirtualViewport() {
|
|
3000
3808
|
const children = (this.editor.children || []);
|
|
3001
|
-
if (!children.length || !this.
|
|
3809
|
+
if (!children.length || !this.isEnabledVirtualScroll()) {
|
|
3002
3810
|
return {
|
|
3003
|
-
|
|
3004
|
-
|
|
3811
|
+
inViewportChildren: children,
|
|
3812
|
+
inViewportIndics: [],
|
|
3005
3813
|
top: 0,
|
|
3006
3814
|
bottom: 0,
|
|
3007
3815
|
heights: []
|
|
3008
3816
|
};
|
|
3009
3817
|
}
|
|
3010
|
-
const scrollTop = this.
|
|
3011
|
-
const viewportHeight = this.
|
|
3818
|
+
const scrollTop = this.virtualScrollConfig.scrollTop;
|
|
3819
|
+
const viewportHeight = this.virtualScrollConfig.viewportHeight ?? 0;
|
|
3012
3820
|
if (!viewportHeight) {
|
|
3013
3821
|
return {
|
|
3014
|
-
|
|
3015
|
-
|
|
3822
|
+
inViewportChildren: [],
|
|
3823
|
+
inViewportIndics: [],
|
|
3016
3824
|
top: 0,
|
|
3017
3825
|
bottom: 0,
|
|
3018
3826
|
heights: []
|
|
3019
3827
|
};
|
|
3020
3828
|
}
|
|
3021
3829
|
const elementLength = children.length;
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3830
|
+
if (!EDITOR_TO_BUSINESS_TOP.has(this.editor)) {
|
|
3831
|
+
EDITOR_TO_BUSINESS_TOP.set(this.editor, 0);
|
|
3832
|
+
setTimeout(() => {
|
|
3833
|
+
const virtualTopBoundingTop = this.virtualTopHeightElement.getBoundingClientRect()?.top ?? 0;
|
|
3834
|
+
const businessTop = Math.ceil(virtualTopBoundingTop) +
|
|
3835
|
+
Math.ceil(this.virtualScrollConfig.scrollTop) -
|
|
3836
|
+
Math.floor(this.virtualScrollConfig.viewportBoundingTop);
|
|
3837
|
+
EDITOR_TO_BUSINESS_TOP.set(this.editor, businessTop);
|
|
3838
|
+
if (isDebug) {
|
|
3839
|
+
debugLog('log', 'businessTop', businessTop);
|
|
3840
|
+
}
|
|
3841
|
+
}, 100);
|
|
3842
|
+
}
|
|
3843
|
+
const adjustedScrollTop = Math.max(0, scrollTop - getBusinessTop(this.editor));
|
|
3844
|
+
const { heights, accumulatedHeights } = buildHeightsAndAccumulatedHeights(this.editor);
|
|
3025
3845
|
const totalHeight = accumulatedHeights[elementLength];
|
|
3026
3846
|
const maxScrollTop = Math.max(0, totalHeight - viewportHeight);
|
|
3027
3847
|
const limitedScrollTop = Math.min(adjustedScrollTop, maxScrollTop);
|
|
3028
|
-
const viewBottom = limitedScrollTop + viewportHeight
|
|
3848
|
+
const viewBottom = limitedScrollTop + viewportHeight;
|
|
3029
3849
|
let accumulatedOffset = 0;
|
|
3030
|
-
let
|
|
3850
|
+
let inViewportStartIndex = -1;
|
|
3031
3851
|
const visible = [];
|
|
3032
|
-
const
|
|
3852
|
+
const inViewportIndics = [];
|
|
3033
3853
|
for (let i = 0; i < elementLength && accumulatedOffset < viewBottom; i++) {
|
|
3034
3854
|
const currentHeight = heights[i];
|
|
3035
3855
|
const nextOffset = accumulatedOffset + currentHeight;
|
|
3036
3856
|
// 可视区域有交集,加入渲染
|
|
3037
3857
|
if (nextOffset > limitedScrollTop && accumulatedOffset < viewBottom) {
|
|
3038
|
-
if (
|
|
3039
|
-
|
|
3858
|
+
if (inViewportStartIndex === -1)
|
|
3859
|
+
inViewportStartIndex = i; // 第一个相交起始位置
|
|
3040
3860
|
visible.push(children[i]);
|
|
3041
|
-
|
|
3861
|
+
inViewportIndics.push(i);
|
|
3042
3862
|
}
|
|
3043
3863
|
accumulatedOffset = nextOffset;
|
|
3044
3864
|
}
|
|
3045
|
-
if (
|
|
3046
|
-
|
|
3047
|
-
visible.push(children[
|
|
3048
|
-
|
|
3865
|
+
if (inViewportStartIndex === -1 && elementLength) {
|
|
3866
|
+
inViewportStartIndex = elementLength - 1;
|
|
3867
|
+
visible.push(children[inViewportStartIndex]);
|
|
3868
|
+
inViewportIndics.push(inViewportStartIndex);
|
|
3049
3869
|
}
|
|
3050
|
-
const
|
|
3051
|
-
const top =
|
|
3052
|
-
const bottom = totalHeight - accumulatedHeights[
|
|
3870
|
+
const inViewportEndIndex = inViewportStartIndex === -1 ? elementLength - 1 : (inViewportIndics[inViewportIndics.length - 1] ?? inViewportStartIndex);
|
|
3871
|
+
const top = inViewportStartIndex === -1 ? 0 : accumulatedHeights[inViewportStartIndex];
|
|
3872
|
+
const bottom = totalHeight - accumulatedHeights[inViewportEndIndex + 1];
|
|
3053
3873
|
return {
|
|
3054
|
-
|
|
3055
|
-
|
|
3874
|
+
inViewportChildren: visible.length ? visible : children,
|
|
3875
|
+
inViewportIndics,
|
|
3056
3876
|
top,
|
|
3057
3877
|
bottom,
|
|
3058
|
-
heights
|
|
3878
|
+
heights,
|
|
3879
|
+
accumulatedHeights
|
|
3059
3880
|
};
|
|
3060
3881
|
}
|
|
3061
3882
|
applyVirtualView(virtualView) {
|
|
3062
|
-
this.
|
|
3063
|
-
this.
|
|
3064
|
-
this.
|
|
3883
|
+
this.inViewportChildren = virtualView.inViewportChildren;
|
|
3884
|
+
this.setVirtualSpaceHeight(virtualView.top, virtualView.bottom);
|
|
3885
|
+
this.inViewportIndics = virtualView.inViewportIndics;
|
|
3065
3886
|
}
|
|
3066
|
-
|
|
3067
|
-
if (!this.
|
|
3887
|
+
diffVirtualViewport(virtualView, stage = 'first') {
|
|
3888
|
+
if (!this.inViewportChildren.length) {
|
|
3889
|
+
if (isDebug) {
|
|
3890
|
+
debugLog('log', 'diffVirtualViewport', stage, 'empty inViewportChildren', virtualView.inViewportIndics);
|
|
3891
|
+
}
|
|
3068
3892
|
return {
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3893
|
+
isDifferent: true,
|
|
3894
|
+
changedIndexesOfTop: [],
|
|
3895
|
+
changedIndexesOfBottom: []
|
|
3072
3896
|
};
|
|
3073
3897
|
}
|
|
3074
|
-
const
|
|
3075
|
-
const
|
|
3076
|
-
const firstNewIndex =
|
|
3077
|
-
const lastNewIndex =
|
|
3078
|
-
const firstOldIndex =
|
|
3079
|
-
const lastOldIndex =
|
|
3898
|
+
const oldIndexesInViewport = [...this.inViewportIndics];
|
|
3899
|
+
const newIndexesInViewport = [...virtualView.inViewportIndics];
|
|
3900
|
+
const firstNewIndex = newIndexesInViewport[0];
|
|
3901
|
+
const lastNewIndex = newIndexesInViewport[newIndexesInViewport.length - 1];
|
|
3902
|
+
const firstOldIndex = oldIndexesInViewport[0];
|
|
3903
|
+
const lastOldIndex = oldIndexesInViewport[oldIndexesInViewport.length - 1];
|
|
3080
3904
|
if (firstNewIndex !== firstOldIndex || lastNewIndex !== lastOldIndex) {
|
|
3081
|
-
const
|
|
3082
|
-
const
|
|
3083
|
-
const
|
|
3084
|
-
const
|
|
3085
|
-
const
|
|
3086
|
-
const
|
|
3087
|
-
if (
|
|
3905
|
+
const changedIndexesOfTop = [];
|
|
3906
|
+
const changedIndexesOfBottom = [];
|
|
3907
|
+
const needRemoveOnTop = firstNewIndex !== firstOldIndex && firstNewIndex > firstOldIndex;
|
|
3908
|
+
const needAddOnTop = firstNewIndex !== firstOldIndex && firstNewIndex < firstOldIndex;
|
|
3909
|
+
const needRemoveOnBottom = lastNewIndex !== lastOldIndex && lastOldIndex > lastNewIndex;
|
|
3910
|
+
const needAddOnBottom = lastNewIndex !== lastOldIndex && lastOldIndex < lastNewIndex;
|
|
3911
|
+
if (needRemoveOnTop || needAddOnBottom) {
|
|
3088
3912
|
// 向下
|
|
3089
|
-
for (let index = 0; index <
|
|
3090
|
-
const element =
|
|
3091
|
-
if (!
|
|
3092
|
-
|
|
3913
|
+
for (let index = 0; index < oldIndexesInViewport.length; index++) {
|
|
3914
|
+
const element = oldIndexesInViewport[index];
|
|
3915
|
+
if (!newIndexesInViewport.includes(element)) {
|
|
3916
|
+
changedIndexesOfTop.push(element);
|
|
3093
3917
|
}
|
|
3094
3918
|
else {
|
|
3095
3919
|
break;
|
|
3096
3920
|
}
|
|
3097
3921
|
}
|
|
3098
|
-
for (let index =
|
|
3099
|
-
const element =
|
|
3100
|
-
if (!
|
|
3101
|
-
|
|
3922
|
+
for (let index = newIndexesInViewport.length - 1; index >= 0; index--) {
|
|
3923
|
+
const element = newIndexesInViewport[index];
|
|
3924
|
+
if (!oldIndexesInViewport.includes(element)) {
|
|
3925
|
+
changedIndexesOfBottom.push(element);
|
|
3102
3926
|
}
|
|
3103
3927
|
else {
|
|
3104
3928
|
break;
|
|
3105
3929
|
}
|
|
3106
3930
|
}
|
|
3107
3931
|
}
|
|
3108
|
-
else if (
|
|
3932
|
+
else if (needAddOnTop || needRemoveOnBottom) {
|
|
3109
3933
|
// 向上
|
|
3110
|
-
for (let index = 0; index <
|
|
3111
|
-
const element =
|
|
3112
|
-
if (!
|
|
3113
|
-
|
|
3934
|
+
for (let index = 0; index < newIndexesInViewport.length; index++) {
|
|
3935
|
+
const element = newIndexesInViewport[index];
|
|
3936
|
+
if (!oldIndexesInViewport.includes(element)) {
|
|
3937
|
+
changedIndexesOfTop.push(element);
|
|
3114
3938
|
}
|
|
3115
3939
|
else {
|
|
3116
3940
|
break;
|
|
3117
3941
|
}
|
|
3118
3942
|
}
|
|
3119
|
-
for (let index =
|
|
3120
|
-
const element =
|
|
3121
|
-
if (!
|
|
3122
|
-
|
|
3943
|
+
for (let index = oldIndexesInViewport.length - 1; index >= 0; index--) {
|
|
3944
|
+
const element = oldIndexesInViewport[index];
|
|
3945
|
+
if (!newIndexesInViewport.includes(element)) {
|
|
3946
|
+
changedIndexesOfBottom.push(element);
|
|
3123
3947
|
}
|
|
3124
3948
|
else {
|
|
3125
3949
|
break;
|
|
@@ -3127,125 +3951,35 @@ class SlateEditable {
|
|
|
3127
3951
|
}
|
|
3128
3952
|
}
|
|
3129
3953
|
if (isDebug) {
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
const needTop = virtualView.heights.slice(0,
|
|
3954
|
+
debugLog('log', `====== diffVirtualViewport stage: ${stage} ======`);
|
|
3955
|
+
debugLog('log', 'oldIndexesInViewport:', oldIndexesInViewport);
|
|
3956
|
+
debugLog('log', 'newIndexesInViewport:', newIndexesInViewport);
|
|
3957
|
+
debugLog('log', 'changedIndexesOfTop:', needRemoveOnTop ? '-' : needAddOnTop ? '+' : '-', changedIndexesOfTop, changedIndexesOfTop.map(index => getRealHeightByElement(this.editor, this.editor.children[index], 0)));
|
|
3958
|
+
debugLog('log', 'changedIndexesOfBottom:', needAddOnBottom ? '+' : needRemoveOnBottom ? '-' : '+', changedIndexesOfBottom, changedIndexesOfBottom.map(index => getRealHeightByElement(this.editor, this.editor.children[index], 0)));
|
|
3959
|
+
const needTop = virtualView.heights.slice(0, newIndexesInViewport[0]).reduce((acc, height) => acc + height, 0);
|
|
3136
3960
|
const needBottom = virtualView.heights
|
|
3137
|
-
.slice(
|
|
3961
|
+
.slice(newIndexesInViewport[newIndexesInViewport.length - 1] + 1)
|
|
3138
3962
|
.reduce((acc, height) => acc + height, 0);
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3963
|
+
debugLog('log', needTop - parseFloat(this.virtualTopHeightElement.style.height), 'newTopHeight:', needTop, 'prevTopHeight:', parseFloat(this.virtualTopHeightElement.style.height));
|
|
3964
|
+
debugLog('log', 'newBottomHeight:', needBottom, 'prevBottomHeight:', parseFloat(this.virtualBottomHeightElement.style.height));
|
|
3965
|
+
debugLog('warn', '=========== Dividing line ===========');
|
|
3142
3966
|
}
|
|
3143
3967
|
return {
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3968
|
+
isDifferent: true,
|
|
3969
|
+
needRemoveOnTop,
|
|
3970
|
+
needAddOnTop,
|
|
3971
|
+
needRemoveOnBottom,
|
|
3972
|
+
needAddOnBottom,
|
|
3973
|
+
changedIndexesOfTop,
|
|
3974
|
+
changedIndexesOfBottom
|
|
3151
3975
|
};
|
|
3152
3976
|
}
|
|
3153
3977
|
return {
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3978
|
+
isDifferent: false,
|
|
3979
|
+
changedIndexesOfTop: [],
|
|
3980
|
+
changedIndexesOfBottom: []
|
|
3157
3981
|
};
|
|
3158
3982
|
}
|
|
3159
|
-
getBlockHeight(index, defaultHeight = VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT) {
|
|
3160
|
-
const node = this.editor.children[index];
|
|
3161
|
-
if (!node) {
|
|
3162
|
-
return defaultHeight;
|
|
3163
|
-
}
|
|
3164
|
-
const key = AngularEditor.findKey(this.editor, node);
|
|
3165
|
-
return this.measuredHeights.get(key.id) ?? defaultHeight;
|
|
3166
|
-
}
|
|
3167
|
-
buildAccumulatedHeight(heights) {
|
|
3168
|
-
const accumulatedHeights = new Array(heights.length + 1).fill(0);
|
|
3169
|
-
for (let i = 0; i < heights.length; i++) {
|
|
3170
|
-
// 存储前 i 个的累计高度
|
|
3171
|
-
accumulatedHeights[i + 1] = accumulatedHeights[i] + heights[i];
|
|
3172
|
-
}
|
|
3173
|
-
return accumulatedHeights;
|
|
3174
|
-
}
|
|
3175
|
-
scheduleMeasureVisibleHeights() {
|
|
3176
|
-
if (!this.shouldUseVirtual()) {
|
|
3177
|
-
return;
|
|
3178
|
-
}
|
|
3179
|
-
this.measureVisibleHeightsAnimId && cancelAnimationFrame(this.measureVisibleHeightsAnimId);
|
|
3180
|
-
this.measureVisibleHeightsAnimId = requestAnimationFrame(() => {
|
|
3181
|
-
this.measureVisibleHeights();
|
|
3182
|
-
});
|
|
3183
|
-
}
|
|
3184
|
-
measureVisibleHeights() {
|
|
3185
|
-
const children = (this.editor.children || []);
|
|
3186
|
-
this.virtualVisibleIndexes.forEach(index => {
|
|
3187
|
-
const node = children[index];
|
|
3188
|
-
if (!node) {
|
|
3189
|
-
return;
|
|
3190
|
-
}
|
|
3191
|
-
const key = AngularEditor.findKey(this.editor, node);
|
|
3192
|
-
// 跳过已测过的块
|
|
3193
|
-
if (this.measuredHeights.has(key.id)) {
|
|
3194
|
-
return;
|
|
3195
|
-
}
|
|
3196
|
-
const view = ELEMENT_TO_COMPONENT.get(node);
|
|
3197
|
-
if (!view) {
|
|
3198
|
-
return;
|
|
3199
|
-
}
|
|
3200
|
-
const ret = view.getRealHeight();
|
|
3201
|
-
if (ret instanceof Promise) {
|
|
3202
|
-
ret.then(height => {
|
|
3203
|
-
this.measuredHeights.set(key.id, height);
|
|
3204
|
-
});
|
|
3205
|
-
}
|
|
3206
|
-
else {
|
|
3207
|
-
this.measuredHeights.set(key.id, ret);
|
|
3208
|
-
}
|
|
3209
|
-
});
|
|
3210
|
-
}
|
|
3211
|
-
remeasureHeightByIndics(indics) {
|
|
3212
|
-
const children = (this.editor.children || []);
|
|
3213
|
-
let isHeightChanged = false;
|
|
3214
|
-
indics.forEach(index => {
|
|
3215
|
-
const node = children[index];
|
|
3216
|
-
if (!node) {
|
|
3217
|
-
return;
|
|
3218
|
-
}
|
|
3219
|
-
const key = AngularEditor.findKey(this.editor, node);
|
|
3220
|
-
const view = ELEMENT_TO_COMPONENT.get(node);
|
|
3221
|
-
if (!view) {
|
|
3222
|
-
return;
|
|
3223
|
-
}
|
|
3224
|
-
const prevHeight = this.measuredHeights.get(key.id);
|
|
3225
|
-
const ret = view.getRealHeight();
|
|
3226
|
-
if (ret instanceof Promise) {
|
|
3227
|
-
ret.then(height => {
|
|
3228
|
-
if (height !== prevHeight) {
|
|
3229
|
-
this.measuredHeights.set(key.id, height);
|
|
3230
|
-
isHeightChanged = true;
|
|
3231
|
-
if (isDebug) {
|
|
3232
|
-
console.log(`remeasureHeightByIndics, index: ${index} prevHeight: ${prevHeight} newHeight: ${height}`);
|
|
3233
|
-
}
|
|
3234
|
-
}
|
|
3235
|
-
});
|
|
3236
|
-
}
|
|
3237
|
-
else {
|
|
3238
|
-
if (ret !== prevHeight) {
|
|
3239
|
-
this.measuredHeights.set(key.id, ret);
|
|
3240
|
-
isHeightChanged = true;
|
|
3241
|
-
if (isDebug) {
|
|
3242
|
-
console.log(`remeasureHeightByIndics, index: ${index} prevHeight: ${prevHeight} newHeight: ${ret}`);
|
|
3243
|
-
}
|
|
3244
|
-
}
|
|
3245
|
-
}
|
|
3246
|
-
});
|
|
3247
|
-
return isHeightChanged;
|
|
3248
|
-
}
|
|
3249
3983
|
//#region event proxy
|
|
3250
3984
|
addEventListener(eventName, listener, target = this.elementRef.nativeElement) {
|
|
3251
3985
|
this.manualListeners.push(this.renderer2.listen(target, eventName, (event) => {
|
|
@@ -3286,7 +4020,7 @@ class SlateEditable {
|
|
|
3286
4020
|
if (this.editor.selection && Range.equals(range, this.editor.selection) && !hasStringTarget(domSelection)) {
|
|
3287
4021
|
if (!isTargetInsideVoid(this.editor, activeElement)) {
|
|
3288
4022
|
// force adjust DOMSelection
|
|
3289
|
-
this.toNativeSelection();
|
|
4023
|
+
this.toNativeSelection(false);
|
|
3290
4024
|
}
|
|
3291
4025
|
}
|
|
3292
4026
|
else {
|
|
@@ -3942,6 +4676,7 @@ class SlateEditable {
|
|
|
3942
4676
|
}
|
|
3943
4677
|
//#endregion
|
|
3944
4678
|
ngOnDestroy() {
|
|
4679
|
+
this.editorResizeObserver?.disconnect();
|
|
3945
4680
|
NODE_TO_ELEMENT.delete(this.editor);
|
|
3946
4681
|
this.manualListeners.forEach(manualListener => {
|
|
3947
4682
|
manualListener();
|
|
@@ -4130,16 +4865,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
4130
4865
|
}]
|
|
4131
4866
|
}], ctorParameters: () => [{ type: i0.ElementRef }] });
|
|
4132
4867
|
|
|
4868
|
+
class SlateString {
|
|
4869
|
+
ngOnInit() { }
|
|
4870
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateString, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4871
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: SlateString, isStandalone: true, selector: "span[slateString]", inputs: { context: "context", viewContext: "viewContext" }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4872
|
+
}
|
|
4873
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateString, decorators: [{
|
|
4874
|
+
type: Component,
|
|
4875
|
+
args: [{
|
|
4876
|
+
selector: 'span[slateString]',
|
|
4877
|
+
template: '',
|
|
4878
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4879
|
+
standalone: true
|
|
4880
|
+
}]
|
|
4881
|
+
}], propDecorators: { context: [{
|
|
4882
|
+
type: Input
|
|
4883
|
+
}], viewContext: [{
|
|
4884
|
+
type: Input
|
|
4885
|
+
}] } });
|
|
4886
|
+
|
|
4133
4887
|
class SlateModule {
|
|
4134
4888
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
4135
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, imports: [CommonModule, SlateEditable, SlateChildrenOutlet], exports: [SlateEditable, SlateChildrenOutlet] }); }
|
|
4889
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, imports: [CommonModule, SlateEditable, SlateChildrenOutlet, SlateString], exports: [SlateEditable, SlateChildrenOutlet, SlateString] }); }
|
|
4136
4890
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, imports: [CommonModule] }); }
|
|
4137
4891
|
}
|
|
4138
4892
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: SlateModule, decorators: [{
|
|
4139
4893
|
type: NgModule,
|
|
4140
4894
|
args: [{
|
|
4141
|
-
imports: [CommonModule, SlateEditable, SlateChildrenOutlet],
|
|
4142
|
-
exports: [SlateEditable, SlateChildrenOutlet],
|
|
4895
|
+
imports: [CommonModule, SlateEditable, SlateChildrenOutlet, SlateString],
|
|
4896
|
+
exports: [SlateEditable, SlateChildrenOutlet, SlateString],
|
|
4143
4897
|
providers: []
|
|
4144
4898
|
}]
|
|
4145
4899
|
}] });
|
|
@@ -4255,6 +5009,7 @@ class BaseElementComponent extends BaseComponent {
|
|
|
4255
5009
|
if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
|
|
4256
5010
|
ELEMENT_TO_COMPONENT.delete(this.element);
|
|
4257
5011
|
}
|
|
5012
|
+
this.listRender.destroy();
|
|
4258
5013
|
}
|
|
4259
5014
|
onContextChange() {
|
|
4260
5015
|
this.childrenContext = this.getChildrenContext();
|
|
@@ -4342,6 +5097,7 @@ class BaseTextComponent extends BaseComponent {
|
|
|
4342
5097
|
NODE_TO_ELEMENT.delete(this.text);
|
|
4343
5098
|
}
|
|
4344
5099
|
ELEMENT_TO_NODE.delete(this.nativeElement);
|
|
5100
|
+
this.leavesRender.destroy();
|
|
4345
5101
|
}
|
|
4346
5102
|
onContextChange() {
|
|
4347
5103
|
this.updateWeakMap();
|
|
@@ -4367,6 +5123,9 @@ class BaseLeafComponent extends BaseComponent {
|
|
|
4367
5123
|
super(...arguments);
|
|
4368
5124
|
this.stringRender = null;
|
|
4369
5125
|
this.isSlateLeaf = true;
|
|
5126
|
+
this.getOutletParent = () => {
|
|
5127
|
+
return this.elementRef.nativeElement;
|
|
5128
|
+
};
|
|
4370
5129
|
}
|
|
4371
5130
|
get text() {
|
|
4372
5131
|
return this.context && this.context.text;
|
|
@@ -4381,7 +5140,7 @@ class BaseLeafComponent extends BaseComponent {
|
|
|
4381
5140
|
if (!this.initialized) {
|
|
4382
5141
|
this.stringRender = new SlateStringRender(this.context, this.viewContext);
|
|
4383
5142
|
const stringNode = this.stringRender.render();
|
|
4384
|
-
this.
|
|
5143
|
+
this.getOutletParent().appendChild(stringNode);
|
|
4385
5144
|
}
|
|
4386
5145
|
else {
|
|
4387
5146
|
this.stringRender?.update(this.context, this.viewContext);
|
|
@@ -4453,5 +5212,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
4453
5212
|
* Generated bundle index. Do not edit.
|
|
4454
5213
|
*/
|
|
4455
5214
|
|
|
4456
|
-
export { AngularEditor, BaseComponent, BaseElementComponent, BaseElementFlavour, BaseFlavour, BaseLeafComponent, BaseLeafFlavour, BaseTextComponent, BaseTextFlavour, BlockCardRef, DEFAULT_ELEMENT_HEIGHT, DefaultTextFlavour, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, ELEMENT_TO_COMPONENT, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, FlavourRef, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_IOS, IS_QQBROWSER, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER,
|
|
5215
|
+
export { AngularEditor, BaseComponent, BaseElementComponent, BaseElementFlavour, BaseFlavour, BaseLeafComponent, BaseLeafFlavour, BaseTextComponent, BaseTextFlavour, BlockCardRef, DEFAULT_ELEMENT_HEIGHT, DefaultTextFlavour, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, EDITOR_TO_BUSINESS_TOP, EDITOR_TO_ROOT_NODE_WIDTH, EDITOR_TO_VIRTUAL_SCROLL_SELECTION, ELEMENT_KEY_TO_HEIGHTS, ELEMENT_TO_COMPONENT, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, FlavourRef, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_ENABLED_VIRTUAL_SCROLL, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_IOS, IS_QQBROWSER, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, PLACEHOLDER_SYMBOL, SLATE_BLOCK_CARD_CLASS_NAME, SLATE_DEBUG_KEY, SLATE_DEBUG_KEY_SCROLL_TOP, SlateBlockCard, SlateChildrenOutlet, SlateEditable, SlateErrorCode, SlateFragmentAttributeKey, SlateModule, SlateString, VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT, VoidTextFlavour, blobAsString, buildHTMLText, buildHeightsAndAccumulatedHeights, calculateVirtualTopHeight, check, completeTable, createClipboardData, createText, createThrottleRAF, debugLog, defaultScrollSelectionIntoView, fallbackCopyText, getBlockCardByNativeElement, getBusinessTop, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getContentHeight, getDataTransferClipboard, getDataTransferClipboardText, getNavigatorClipboard, getPlainText, getRealHeightByElement, getSelection, getSlateFragmentAttribute, getZeroTextNode, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isClipboardFile, isClipboardReadSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isComponentType, isDOMText, isDebug, isDebugScrollTop, isDecoratorRangeListEqual, isFlavourType, isInvalidTable, isTemplateRef, isValid, measureHeightByElement, measureHeightByIndics, normalize, scrollToElement, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
|
|
4457
5216
|
//# sourceMappingURL=slate-angular.mjs.map
|