slate-angular 20.2.0-next.25 → 20.2.0-next.27
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 +1194 -1236
- package/fesm2022/slate-angular.mjs.map +1 -1
- package/index.d.ts +6 -5
- package/package.json +1 -1
|
@@ -955,179 +955,709 @@ const fallbackCopyText = async (text) => {
|
|
|
955
955
|
});
|
|
956
956
|
};
|
|
957
957
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
return
|
|
970
|
-
}
|
|
971
|
-
const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
|
|
972
|
-
const key = AngularEditor.findKey(editor, element);
|
|
973
|
-
const height = heights?.get(key.id);
|
|
974
|
-
if (typeof height === 'number') {
|
|
975
|
-
return height;
|
|
976
|
-
}
|
|
977
|
-
if (heights?.has(key.id)) {
|
|
978
|
-
console.error('getBlockHeight: invalid height value', key.id, height);
|
|
979
|
-
}
|
|
980
|
-
return defaultHeight;
|
|
981
|
-
};
|
|
982
|
-
const buildHeightsAndAccumulatedHeights = (editor) => {
|
|
983
|
-
const children = (editor.children || []);
|
|
984
|
-
const heights = new Array(children.length);
|
|
985
|
-
const accumulatedHeights = new Array(children.length + 1);
|
|
986
|
-
accumulatedHeights[0] = 0;
|
|
987
|
-
for (let i = 0; i < children.length; i++) {
|
|
988
|
-
const height = getRealHeightByElement(editor, children[i]);
|
|
989
|
-
heights[i] = height;
|
|
990
|
-
accumulatedHeights[i + 1] = accumulatedHeights[i] + height;
|
|
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;
|
|
991
970
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
const scrollToElement = (editor, element, scrollTo) => {
|
|
995
|
-
const children = editor.children;
|
|
996
|
-
if (!children.length) {
|
|
997
|
-
return;
|
|
971
|
+
static log(doc, type, ...args) {
|
|
972
|
+
this.getInstance(doc).log(type, ...args);
|
|
998
973
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
974
|
+
static syncScrollTop(doc, value) {
|
|
975
|
+
const instance = this.getInstance(doc);
|
|
976
|
+
instance.setScrollTopValue(value);
|
|
1002
977
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
if (virtualScrollSelection) {
|
|
1028
|
-
domRange = AngularEditor.toDOMRange(e, virtualScrollSelection);
|
|
978
|
+
constructor(doc) {
|
|
979
|
+
this.doc = doc;
|
|
980
|
+
this.state = {
|
|
981
|
+
left: 16,
|
|
982
|
+
top: 16,
|
|
983
|
+
collapsed: false,
|
|
984
|
+
width: VirtualScrollDebugOverlay.defaultWidth,
|
|
985
|
+
height: VirtualScrollDebugOverlay.defaultHeight
|
|
986
|
+
};
|
|
987
|
+
this.originalConsoleLog = console.log.bind(console);
|
|
988
|
+
this.originalConsoleWarn = console.warn.bind(console);
|
|
989
|
+
this.dragOffsetX = 0;
|
|
990
|
+
this.dragOffsetY = 0;
|
|
991
|
+
this.isDragging = false;
|
|
992
|
+
this.isResizing = false;
|
|
993
|
+
this.resizeStartX = 0;
|
|
994
|
+
this.resizeStartY = 0;
|
|
995
|
+
this.resizeStartWidth = 0;
|
|
996
|
+
this.resizeStartHeight = 0;
|
|
997
|
+
this.dragMoved = false;
|
|
998
|
+
this.wasDragged = false;
|
|
999
|
+
this.onDragging = (event) => {
|
|
1000
|
+
if (!this.isDragging || !this.container) {
|
|
1001
|
+
return;
|
|
1029
1002
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1003
|
+
this.dragMoved = true;
|
|
1004
|
+
const nextLeft = event.clientX - this.dragOffsetX;
|
|
1005
|
+
const nextTop = event.clientY - this.dragOffsetY;
|
|
1006
|
+
this.container.style.left = `${nextLeft}px`;
|
|
1007
|
+
this.container.style.top = `${nextTop}px`;
|
|
1008
|
+
this.container.style.right = 'auto';
|
|
1009
|
+
this.container.style.bottom = 'auto';
|
|
1010
|
+
};
|
|
1011
|
+
this.onDragEnd = () => {
|
|
1012
|
+
if (!this.isDragging) {
|
|
1013
|
+
return;
|
|
1039
1014
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
// COMPAT: If the start node is a void node, we need to attach the encoded
|
|
1052
|
-
// fragment to the void node's content node instead of the spacer, because
|
|
1053
|
-
// attaching it to empty `<div>/<span>` nodes will end up having it erased by
|
|
1054
|
-
// most browsers. (2018/04/27)
|
|
1055
|
-
if (startVoid) {
|
|
1056
|
-
attach = contents.querySelector('[data-slate-spacer]');
|
|
1057
|
-
}
|
|
1058
|
-
// Remove any zero-width space spans from the cloned DOM so that they don't
|
|
1059
|
-
// show up elsewhere when pasted.
|
|
1060
|
-
Array.from(contents.querySelectorAll('[data-slate-zero-width]')).forEach(zw => {
|
|
1061
|
-
const isNewline = zw.getAttribute('data-slate-zero-width') === 'n';
|
|
1062
|
-
zw.textContent = isNewline ? '\n' : '';
|
|
1063
|
-
});
|
|
1064
|
-
// Set a `data-slate-fragment` attribute on a non-empty node, so it shows up
|
|
1065
|
-
// in the HTML, and can be used for intra-Slate pasting. If it's a text
|
|
1066
|
-
// node, wrap it in a `<span>` so we have something to set an attribute on.
|
|
1067
|
-
if (isDOMText(attach)) {
|
|
1068
|
-
const span = attach.ownerDocument.createElement('span');
|
|
1069
|
-
// COMPAT: In Chrome and Safari, if we don't add the `white-space` style
|
|
1070
|
-
// then leading and trailing spaces will be ignored. (2017/09/21)
|
|
1071
|
-
span.style.whiteSpace = 'pre';
|
|
1072
|
-
span.appendChild(attach);
|
|
1073
|
-
contents.appendChild(span);
|
|
1074
|
-
attach = span;
|
|
1075
|
-
}
|
|
1076
|
-
const fragment = e.getFragment();
|
|
1077
|
-
// Add the content to a <div> so that we can get its inner HTML.
|
|
1078
|
-
const div = contents.ownerDocument.createElement('div');
|
|
1079
|
-
const attachWrapper = document.createElement('div');
|
|
1080
|
-
const elements = Array.from(contents.children);
|
|
1081
|
-
if (isInvalidTable(elements)) {
|
|
1082
|
-
contents = completeTable(contents.cloneNode(true));
|
|
1083
|
-
}
|
|
1084
|
-
attachWrapper.appendChild(contents);
|
|
1085
|
-
div.appendChild(attachWrapper);
|
|
1086
|
-
div.setAttribute('hidden', 'true');
|
|
1087
|
-
contents.ownerDocument.body.appendChild(div);
|
|
1088
|
-
setClipboardData({ text: getPlainText(div), elements: fragment }, div, attachWrapper, dataTransfer);
|
|
1089
|
-
contents.ownerDocument.body.removeChild(div);
|
|
1090
|
-
};
|
|
1091
|
-
e.deleteCutData = () => {
|
|
1092
|
-
const { selection } = editor;
|
|
1093
|
-
if (selection) {
|
|
1094
|
-
if (Range.isExpanded(selection)) {
|
|
1095
|
-
Editor.deleteFragment(editor);
|
|
1015
|
+
this.isDragging = false;
|
|
1016
|
+
this.wasDragged = this.dragMoved;
|
|
1017
|
+
this.dragMoved = false;
|
|
1018
|
+
this.doc.removeEventListener('mousemove', this.onDragging);
|
|
1019
|
+
this.doc.removeEventListener('mouseup', this.onDragEnd);
|
|
1020
|
+
if (this.container) {
|
|
1021
|
+
const rect = this.container.getBoundingClientRect();
|
|
1022
|
+
this.state.left = rect.left;
|
|
1023
|
+
this.state.top = rect.top;
|
|
1024
|
+
this.persistState();
|
|
1025
|
+
this.container.style.transition = '';
|
|
1096
1026
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1027
|
+
};
|
|
1028
|
+
this.onResizing = (event) => {
|
|
1029
|
+
if (!this.isResizing || !this.container) {
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
const deltaX = event.clientX - this.resizeStartX;
|
|
1033
|
+
const deltaY = event.clientY - this.resizeStartY;
|
|
1034
|
+
const nextWidth = Math.max(VirtualScrollDebugOverlay.minWidth, this.resizeStartWidth + deltaX);
|
|
1035
|
+
const nextHeight = Math.max(VirtualScrollDebugOverlay.minHeight, this.resizeStartHeight + deltaY);
|
|
1036
|
+
this.state.width = nextWidth;
|
|
1037
|
+
this.state.height = nextHeight;
|
|
1038
|
+
this.applySize();
|
|
1039
|
+
};
|
|
1040
|
+
this.onResizeEnd = () => {
|
|
1041
|
+
if (!this.isResizing) {
|
|
1042
|
+
return;
|
|
1102
1043
|
}
|
|
1044
|
+
this.isResizing = false;
|
|
1045
|
+
this.doc.removeEventListener('mousemove', this.onResizing);
|
|
1046
|
+
this.doc.removeEventListener('mouseup', this.onResizeEnd);
|
|
1047
|
+
this.persistState();
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
init() {
|
|
1051
|
+
if (!this.container) {
|
|
1052
|
+
this.createContainer();
|
|
1103
1053
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
if (!(await e.customInsertFragmentData(data, null))) {
|
|
1107
|
-
e.insertTextData(data);
|
|
1054
|
+
else {
|
|
1055
|
+
this.applyState();
|
|
1108
1056
|
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
const clipboardData = contextClipboardData || (await getClipboardData(data));
|
|
1115
|
-
if (clipboardData && clipboardData.elements) {
|
|
1116
|
-
e.insertFragment(clipboardData.elements);
|
|
1117
|
-
return true;
|
|
1057
|
+
}
|
|
1058
|
+
log(type, ...args) {
|
|
1059
|
+
this.init();
|
|
1060
|
+
if (type === 'warn') {
|
|
1061
|
+
this.originalConsoleWarn(...args);
|
|
1118
1062
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1063
|
+
else {
|
|
1064
|
+
this.originalConsoleLog(...args);
|
|
1065
|
+
}
|
|
1066
|
+
this.appendLog(type, ...args);
|
|
1067
|
+
}
|
|
1068
|
+
dispose() {
|
|
1069
|
+
this.container?.remove();
|
|
1070
|
+
this.container = undefined;
|
|
1071
|
+
this.contentWrapper = undefined;
|
|
1072
|
+
this.bubble = undefined;
|
|
1073
|
+
this.logList = undefined;
|
|
1074
|
+
this.selectorInput = undefined;
|
|
1075
|
+
this.distanceInput = undefined;
|
|
1076
|
+
this.collapseToggle = undefined;
|
|
1077
|
+
this.resizeHandle = undefined;
|
|
1078
|
+
this.doc.removeEventListener('mousemove', this.onDragging);
|
|
1079
|
+
this.doc.removeEventListener('mouseup', this.onDragEnd);
|
|
1080
|
+
this.doc.removeEventListener('mousemove', this.onResizing);
|
|
1081
|
+
this.doc.removeEventListener('mouseup', this.onResizeEnd);
|
|
1082
|
+
this.isDragging = false;
|
|
1083
|
+
this.isResizing = false;
|
|
1084
|
+
}
|
|
1085
|
+
createContainer() {
|
|
1086
|
+
this.loadState();
|
|
1087
|
+
const doc = this.doc;
|
|
1088
|
+
const container = doc.createElement('div');
|
|
1089
|
+
container.style.position = 'fixed';
|
|
1090
|
+
container.style.right = 'auto';
|
|
1091
|
+
container.style.bottom = 'auto';
|
|
1092
|
+
container.style.boxSizing = 'border-box';
|
|
1093
|
+
container.style.background = 'rgba(17, 24, 39, 0.95)';
|
|
1094
|
+
container.style.color = '#e5e7eb';
|
|
1095
|
+
container.style.fontSize = '12px';
|
|
1096
|
+
container.style.border = '1px solid #1f2937';
|
|
1097
|
+
container.style.borderRadius = '10px';
|
|
1098
|
+
container.style.fontFamily = 'Menlo, Consolas, monospace';
|
|
1099
|
+
container.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.35)';
|
|
1100
|
+
container.style.zIndex = '9999';
|
|
1101
|
+
container.style.display = 'flex';
|
|
1102
|
+
container.style.flexDirection = 'column';
|
|
1103
|
+
container.style.gap = '10px';
|
|
1104
|
+
container.style.minWidth = `${VirtualScrollDebugOverlay.minWidth}px`;
|
|
1105
|
+
container.style.minHeight = `${VirtualScrollDebugOverlay.minHeight}px`;
|
|
1106
|
+
container.style.maxHeight = '80vh';
|
|
1107
|
+
container.style.cursor = 'default';
|
|
1108
|
+
container.addEventListener('mousedown', event => {
|
|
1109
|
+
if (this.state.collapsed) {
|
|
1110
|
+
this.startDrag(event);
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
const header = doc.createElement('div');
|
|
1114
|
+
header.style.display = 'flex';
|
|
1115
|
+
header.style.alignItems = 'center';
|
|
1116
|
+
header.style.justifyContent = 'space-between';
|
|
1117
|
+
header.style.cursor = 'move';
|
|
1118
|
+
header.addEventListener('mousedown', event => {
|
|
1119
|
+
this.startDrag(event);
|
|
1120
|
+
});
|
|
1121
|
+
const title = doc.createElement('div');
|
|
1122
|
+
title.textContent = 'Virtual Scroll Debug';
|
|
1123
|
+
title.style.fontWeight = '600';
|
|
1124
|
+
title.style.letterSpacing = '0.3px';
|
|
1125
|
+
const actions = doc.createElement('div');
|
|
1126
|
+
actions.style.display = 'flex';
|
|
1127
|
+
actions.style.gap = '6px';
|
|
1128
|
+
const collapseButton = doc.createElement('button');
|
|
1129
|
+
collapseButton.type = 'button';
|
|
1130
|
+
collapseButton.textContent = '折叠';
|
|
1131
|
+
collapseButton.style.background = '#1f2937';
|
|
1132
|
+
collapseButton.style.color = '#e5e7eb';
|
|
1133
|
+
collapseButton.style.border = '1px solid #374151';
|
|
1134
|
+
collapseButton.style.borderRadius = '6px';
|
|
1135
|
+
collapseButton.style.padding = '4px 8px';
|
|
1136
|
+
collapseButton.style.cursor = 'pointer';
|
|
1137
|
+
collapseButton.addEventListener('click', () => {
|
|
1138
|
+
this.setCollapsed(!this.state.collapsed);
|
|
1139
|
+
});
|
|
1140
|
+
const clearButton = doc.createElement('button');
|
|
1141
|
+
clearButton.type = 'button';
|
|
1142
|
+
clearButton.textContent = '清除日志';
|
|
1143
|
+
clearButton.style.background = '#374151';
|
|
1144
|
+
clearButton.style.color = '#e5e7eb';
|
|
1145
|
+
clearButton.style.border = '1px solid #4b5563';
|
|
1146
|
+
clearButton.style.borderRadius = '6px';
|
|
1147
|
+
clearButton.style.padding = '4px 10px';
|
|
1148
|
+
clearButton.style.cursor = 'pointer';
|
|
1149
|
+
clearButton.addEventListener('click', () => {
|
|
1150
|
+
if (this.logList) {
|
|
1151
|
+
this.logList.innerHTML = '';
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
actions.appendChild(collapseButton);
|
|
1155
|
+
actions.appendChild(clearButton);
|
|
1156
|
+
header.appendChild(title);
|
|
1157
|
+
header.appendChild(actions);
|
|
1158
|
+
const scrollForm = doc.createElement('div');
|
|
1159
|
+
scrollForm.style.display = 'grid';
|
|
1160
|
+
scrollForm.style.gridTemplateColumns = '1fr 110px 50px';
|
|
1161
|
+
scrollForm.style.gap = '6px';
|
|
1162
|
+
scrollForm.style.alignItems = 'center';
|
|
1163
|
+
const selectorInput = doc.createElement('input');
|
|
1164
|
+
selectorInput.placeholder = '滚动容器 selector';
|
|
1165
|
+
selectorInput.style.padding = '6px 8px';
|
|
1166
|
+
selectorInput.style.borderRadius = '6px';
|
|
1167
|
+
selectorInput.style.border = '1px solid #4b5563';
|
|
1168
|
+
selectorInput.style.background = '#111827';
|
|
1169
|
+
selectorInput.style.color = '#e5e7eb';
|
|
1170
|
+
selectorInput.autocomplete = 'off';
|
|
1171
|
+
const distanceInput = doc.createElement('input');
|
|
1172
|
+
distanceInput.placeholder = '滚动距离(px)';
|
|
1173
|
+
distanceInput.type = 'number';
|
|
1174
|
+
distanceInput.style.padding = '6px 8px';
|
|
1175
|
+
distanceInput.style.borderRadius = '6px';
|
|
1176
|
+
distanceInput.style.border = '1px solid #4b5563';
|
|
1177
|
+
distanceInput.style.background = '#111827';
|
|
1178
|
+
distanceInput.style.color = '#e5e7eb';
|
|
1179
|
+
const scrollButton = doc.createElement('button');
|
|
1180
|
+
scrollButton.type = 'button';
|
|
1181
|
+
scrollButton.textContent = '滚动';
|
|
1182
|
+
scrollButton.style.background = '#10b981';
|
|
1183
|
+
scrollButton.style.color = '#0b1c15';
|
|
1184
|
+
scrollButton.style.border = 'none';
|
|
1185
|
+
scrollButton.style.borderRadius = '6px';
|
|
1186
|
+
scrollButton.style.padding = '6px 10px';
|
|
1187
|
+
scrollButton.style.cursor = 'pointer';
|
|
1188
|
+
scrollButton.addEventListener('click', () => {
|
|
1189
|
+
const selector = selectorInput.value.trim();
|
|
1190
|
+
const distanceValue = Number(distanceInput.value ?? 0);
|
|
1191
|
+
const distance = Number.isFinite(distanceValue) ? distanceValue : 0;
|
|
1192
|
+
if (!selector) {
|
|
1193
|
+
this.log('warn', '请先填写滚动容器 selector');
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
const target = doc.querySelector(selector);
|
|
1197
|
+
if (!target) {
|
|
1198
|
+
this.log('warn', `未找到滚动容器: ${selector}`);
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (typeof target.scrollTo === 'function') {
|
|
1202
|
+
target.scrollTo({ top: distance, behavior: 'auto' });
|
|
1203
|
+
}
|
|
1204
|
+
else if (Object.prototype.hasOwnProperty.call(target, 'scrollTop')) {
|
|
1205
|
+
target.scrollTop = distance;
|
|
1206
|
+
}
|
|
1207
|
+
else {
|
|
1208
|
+
this.log('warn', '目标元素不支持滚动:', selector);
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
this.log('log', `已将 ${selector} 滚动到`, distance);
|
|
1212
|
+
});
|
|
1213
|
+
scrollForm.appendChild(selectorInput);
|
|
1214
|
+
scrollForm.appendChild(distanceInput);
|
|
1215
|
+
scrollForm.appendChild(scrollButton);
|
|
1216
|
+
const logList = doc.createElement('div');
|
|
1217
|
+
logList.style.height = '260px';
|
|
1218
|
+
logList.style.overflowY = 'auto';
|
|
1219
|
+
logList.style.background = '#0b1220';
|
|
1220
|
+
logList.style.border = '1px solid #1f2937';
|
|
1221
|
+
logList.style.borderRadius = '8px';
|
|
1222
|
+
logList.style.padding = '8px';
|
|
1223
|
+
logList.style.display = 'flex';
|
|
1224
|
+
logList.style.flexDirection = 'column';
|
|
1225
|
+
logList.style.gap = '6px';
|
|
1226
|
+
logList.style.flex = '1';
|
|
1227
|
+
logList.style.minHeight = '160px';
|
|
1228
|
+
const bubble = doc.createElement('div');
|
|
1229
|
+
bubble.textContent = 'VS';
|
|
1230
|
+
bubble.style.display = 'none';
|
|
1231
|
+
bubble.style.alignItems = 'center';
|
|
1232
|
+
bubble.style.justifyContent = 'center';
|
|
1233
|
+
bubble.style.fontWeight = '700';
|
|
1234
|
+
bubble.style.fontSize = '14px';
|
|
1235
|
+
bubble.style.letterSpacing = '0.5px';
|
|
1236
|
+
bubble.style.width = '100%';
|
|
1237
|
+
bubble.style.height = '100%';
|
|
1238
|
+
bubble.style.userSelect = 'none';
|
|
1239
|
+
bubble.addEventListener('click', () => {
|
|
1240
|
+
if (this.wasDragged) {
|
|
1241
|
+
this.wasDragged = false;
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
this.setCollapsed(false);
|
|
1245
|
+
});
|
|
1246
|
+
const contentWrapper = doc.createElement('div');
|
|
1247
|
+
contentWrapper.style.display = 'flex';
|
|
1248
|
+
contentWrapper.style.flexDirection = 'column';
|
|
1249
|
+
contentWrapper.style.gap = '10px';
|
|
1250
|
+
contentWrapper.style.width = '100%';
|
|
1251
|
+
contentWrapper.style.height = '100%';
|
|
1252
|
+
contentWrapper.appendChild(header);
|
|
1253
|
+
contentWrapper.appendChild(scrollForm);
|
|
1254
|
+
contentWrapper.appendChild(logList);
|
|
1255
|
+
container.appendChild(contentWrapper);
|
|
1256
|
+
container.appendChild(bubble);
|
|
1257
|
+
const resizeHandle = doc.createElement('div');
|
|
1258
|
+
resizeHandle.style.position = 'absolute';
|
|
1259
|
+
resizeHandle.style.right = '6px';
|
|
1260
|
+
resizeHandle.style.bottom = '6px';
|
|
1261
|
+
resizeHandle.style.width = '14px';
|
|
1262
|
+
resizeHandle.style.height = '14px';
|
|
1263
|
+
resizeHandle.style.cursor = 'nwse-resize';
|
|
1264
|
+
resizeHandle.style.borderRight = '2px solid #4b5563';
|
|
1265
|
+
resizeHandle.style.borderBottom = '2px solid #4b5563';
|
|
1266
|
+
resizeHandle.addEventListener('mousedown', event => {
|
|
1267
|
+
this.startResize(event);
|
|
1268
|
+
});
|
|
1269
|
+
container.appendChild(resizeHandle);
|
|
1270
|
+
doc.body.appendChild(container);
|
|
1271
|
+
this.container = container;
|
|
1272
|
+
this.contentWrapper = contentWrapper;
|
|
1273
|
+
this.bubble = bubble;
|
|
1274
|
+
this.logList = logList;
|
|
1275
|
+
this.selectorInput = selectorInput;
|
|
1276
|
+
this.distanceInput = distanceInput;
|
|
1277
|
+
this.collapseToggle = collapseButton;
|
|
1278
|
+
this.resizeHandle = resizeHandle;
|
|
1279
|
+
this.applyState();
|
|
1280
|
+
}
|
|
1281
|
+
startDrag(event) {
|
|
1282
|
+
if (event.button !== 0) {
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
if (!this.container) {
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
const rect = this.container.getBoundingClientRect();
|
|
1289
|
+
this.isDragging = true;
|
|
1290
|
+
this.wasDragged = false;
|
|
1291
|
+
this.dragMoved = false;
|
|
1292
|
+
this.dragOffsetX = event.clientX - rect.left;
|
|
1293
|
+
this.dragOffsetY = event.clientY - rect.top;
|
|
1294
|
+
this.container.style.transition = 'none';
|
|
1295
|
+
this.doc.addEventListener('mousemove', this.onDragging);
|
|
1296
|
+
this.doc.addEventListener('mouseup', this.onDragEnd);
|
|
1297
|
+
if (!this.state.collapsed) {
|
|
1298
|
+
event.preventDefault();
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
startResize(event) {
|
|
1302
|
+
if (event.button !== 0 || this.state.collapsed) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
if (!this.container) {
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
const rect = this.container.getBoundingClientRect();
|
|
1309
|
+
this.isResizing = true;
|
|
1310
|
+
this.resizeStartX = event.clientX;
|
|
1311
|
+
this.resizeStartY = event.clientY;
|
|
1312
|
+
this.resizeStartWidth = rect.width;
|
|
1313
|
+
this.resizeStartHeight = rect.height;
|
|
1314
|
+
this.doc.addEventListener('mousemove', this.onResizing);
|
|
1315
|
+
this.doc.addEventListener('mouseup', this.onResizeEnd);
|
|
1316
|
+
event.preventDefault();
|
|
1317
|
+
event.stopPropagation();
|
|
1318
|
+
}
|
|
1319
|
+
applyPosition() {
|
|
1320
|
+
if (!this.container) {
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
this.container.style.left = `${this.state.left}px`;
|
|
1324
|
+
this.container.style.top = `${this.state.top}px`;
|
|
1325
|
+
}
|
|
1326
|
+
applySize() {
|
|
1327
|
+
if (!this.container) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const width = Math.max(VirtualScrollDebugOverlay.minWidth, this.state.width || VirtualScrollDebugOverlay.defaultWidth);
|
|
1331
|
+
const height = Math.max(VirtualScrollDebugOverlay.minHeight, this.state.height || VirtualScrollDebugOverlay.defaultHeight);
|
|
1332
|
+
this.state.width = width;
|
|
1333
|
+
this.state.height = height;
|
|
1334
|
+
this.container.style.width = `${width}px`;
|
|
1335
|
+
this.container.style.height = `${height}px`;
|
|
1336
|
+
}
|
|
1337
|
+
applyCollapsedState() {
|
|
1338
|
+
if (!this.container || !this.contentWrapper || !this.bubble || !this.collapseToggle) {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
if (this.state.collapsed) {
|
|
1342
|
+
this.container.style.width = '36px';
|
|
1343
|
+
this.container.style.height = '36px';
|
|
1344
|
+
this.container.style.minWidth = '';
|
|
1345
|
+
this.container.style.minHeight = '';
|
|
1346
|
+
this.container.style.padding = '0';
|
|
1347
|
+
this.container.style.borderRadius = '50%';
|
|
1348
|
+
this.container.style.display = 'flex';
|
|
1349
|
+
this.container.style.flexDirection = 'row';
|
|
1350
|
+
this.container.style.alignItems = 'center';
|
|
1351
|
+
this.container.style.justifyContent = 'center';
|
|
1352
|
+
this.container.style.cursor = 'move';
|
|
1353
|
+
this.contentWrapper.style.display = 'none';
|
|
1354
|
+
this.bubble.style.display = 'flex';
|
|
1355
|
+
this.collapseToggle.textContent = '展开';
|
|
1356
|
+
this.resizeHandle.style.display = 'none';
|
|
1357
|
+
}
|
|
1358
|
+
else {
|
|
1359
|
+
this.applySize();
|
|
1360
|
+
this.container.style.padding = '12px';
|
|
1361
|
+
this.container.style.borderRadius = '10px';
|
|
1362
|
+
this.container.style.display = 'flex';
|
|
1363
|
+
this.container.style.flexDirection = 'column';
|
|
1364
|
+
this.container.style.gap = '10px';
|
|
1365
|
+
this.container.style.cursor = 'default';
|
|
1366
|
+
this.contentWrapper.style.display = 'flex';
|
|
1367
|
+
this.bubble.style.display = 'none';
|
|
1368
|
+
this.collapseToggle.textContent = '折叠';
|
|
1369
|
+
this.resizeHandle.style.display = 'block';
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
setCollapsed(collapsed) {
|
|
1373
|
+
this.state.collapsed = collapsed;
|
|
1374
|
+
this.applyCollapsedState();
|
|
1375
|
+
this.persistState();
|
|
1376
|
+
}
|
|
1377
|
+
applyState() {
|
|
1378
|
+
this.applyPosition();
|
|
1379
|
+
this.applyCollapsedState();
|
|
1380
|
+
}
|
|
1381
|
+
loadState() {
|
|
1382
|
+
try {
|
|
1383
|
+
const raw = this.doc.defaultView?.localStorage?.getItem(VirtualScrollDebugOverlay.storageKey);
|
|
1384
|
+
if (raw) {
|
|
1385
|
+
const parsed = JSON.parse(raw);
|
|
1386
|
+
if (typeof parsed.left === 'number') {
|
|
1387
|
+
this.state.left = parsed.left;
|
|
1388
|
+
}
|
|
1389
|
+
if (typeof parsed.top === 'number') {
|
|
1390
|
+
this.state.top = parsed.top;
|
|
1391
|
+
}
|
|
1392
|
+
if (typeof parsed.collapsed === 'boolean') {
|
|
1393
|
+
this.state.collapsed = parsed.collapsed;
|
|
1394
|
+
}
|
|
1395
|
+
if (typeof parsed.width === 'number') {
|
|
1396
|
+
this.state.width = parsed.width;
|
|
1397
|
+
}
|
|
1398
|
+
if (typeof parsed.height === 'number') {
|
|
1399
|
+
this.state.height = parsed.height;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
catch {
|
|
1404
|
+
// ignore storage errors
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
persistState() {
|
|
1408
|
+
try {
|
|
1409
|
+
this.doc.defaultView?.localStorage?.setItem(VirtualScrollDebugOverlay.storageKey, JSON.stringify(this.state));
|
|
1410
|
+
}
|
|
1411
|
+
catch {
|
|
1412
|
+
// ignore storage errors
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
appendLog(type, ...args) {
|
|
1416
|
+
if (!this.logList) {
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
const item = this.doc.createElement('div');
|
|
1420
|
+
item.style.display = 'flex';
|
|
1421
|
+
item.style.gap = '6px';
|
|
1422
|
+
item.style.alignItems = 'flex-start';
|
|
1423
|
+
item.style.wordBreak = 'break-all';
|
|
1424
|
+
item.style.color = type === 'warn' ? '#fbbf24' : '#9ca3af';
|
|
1425
|
+
const time = this.doc.createElement('span');
|
|
1426
|
+
time.textContent = new Date().toLocaleTimeString();
|
|
1427
|
+
time.style.color = '#6b7280';
|
|
1428
|
+
time.style.flexShrink = '0';
|
|
1429
|
+
time.style.width = '72px';
|
|
1430
|
+
const text = this.doc.createElement('span');
|
|
1431
|
+
text.textContent = `[${type}] ${args.map(arg => this.formatValue(arg)).join(' ')}`;
|
|
1432
|
+
item.appendChild(time);
|
|
1433
|
+
item.appendChild(text);
|
|
1434
|
+
this.logList.appendChild(item);
|
|
1435
|
+
this.logList.scrollTop = this.logList.scrollHeight;
|
|
1436
|
+
}
|
|
1437
|
+
formatValue(value) {
|
|
1438
|
+
if (typeof value === 'string') {
|
|
1439
|
+
return value;
|
|
1440
|
+
}
|
|
1441
|
+
try {
|
|
1442
|
+
return JSON.stringify(value);
|
|
1443
|
+
}
|
|
1444
|
+
catch (error) {
|
|
1445
|
+
return String(value);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
setScrollTopValue(value) {
|
|
1449
|
+
if (this.distanceInput) {
|
|
1450
|
+
this.distanceInput.value = String(value ?? 0);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
const isDebug = localStorage.getItem(SLATE_DEBUG_KEY) === 'true';
|
|
1456
|
+
const isDebugScrollTop = localStorage.getItem(SLATE_DEBUG_KEY_SCROLL_TOP) === 'true';
|
|
1457
|
+
const ELEMENT_KEY_TO_HEIGHTS = new WeakMap();
|
|
1458
|
+
const EDITOR_TO_BUSINESS_TOP = new WeakMap();
|
|
1459
|
+
const debugLog = (type, ...args) => {
|
|
1460
|
+
const doc = document;
|
|
1461
|
+
VirtualScrollDebugOverlay.log(doc, type, ...args);
|
|
1462
|
+
};
|
|
1463
|
+
const measureHeightByElement = (editor, element) => {
|
|
1464
|
+
const key = AngularEditor.findKey(editor, element);
|
|
1465
|
+
const view = ELEMENT_TO_COMPONENT.get(element);
|
|
1466
|
+
if (!view) {
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
const ret = view.getRealHeight();
|
|
1470
|
+
const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
|
|
1471
|
+
heights.set(key.id, ret);
|
|
1472
|
+
return ret;
|
|
1473
|
+
};
|
|
1474
|
+
const measureHeightByIndics = (editor, indics, force = false) => {
|
|
1475
|
+
let hasChanged = false;
|
|
1476
|
+
indics.forEach((index, i) => {
|
|
1477
|
+
const element = editor.children[index];
|
|
1478
|
+
const preHeight = getRealHeightByElement(editor, element, 0);
|
|
1479
|
+
if (preHeight && !force) {
|
|
1480
|
+
if (isDebug) {
|
|
1481
|
+
const height = measureHeightByElement(editor, element);
|
|
1482
|
+
if (height !== preHeight) {
|
|
1483
|
+
debugLog('warn', 'measureHeightByElement: height not equal, index: ', index, 'preHeight: ', preHeight, 'height: ', height);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
hasChanged = true;
|
|
1489
|
+
measureHeightByElement(editor, element);
|
|
1490
|
+
});
|
|
1491
|
+
return hasChanged;
|
|
1492
|
+
};
|
|
1493
|
+
const getBusinessTop = (editor) => {
|
|
1494
|
+
return EDITOR_TO_BUSINESS_TOP.get(editor) ?? 0;
|
|
1495
|
+
};
|
|
1496
|
+
const getRealHeightByElement = (editor, element, defaultHeight = VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT) => {
|
|
1497
|
+
const isVisible = editor.isVisible(element);
|
|
1498
|
+
if (!isVisible) {
|
|
1499
|
+
return 0;
|
|
1500
|
+
}
|
|
1501
|
+
const heights = ELEMENT_KEY_TO_HEIGHTS.get(editor);
|
|
1502
|
+
const key = AngularEditor.findKey(editor, element);
|
|
1503
|
+
const height = heights?.get(key.id);
|
|
1504
|
+
if (typeof height === 'number') {
|
|
1505
|
+
return height;
|
|
1506
|
+
}
|
|
1507
|
+
if (heights?.has(key.id)) {
|
|
1508
|
+
console.error('getBlockHeight: invalid height value', key.id, height);
|
|
1509
|
+
}
|
|
1510
|
+
return defaultHeight;
|
|
1511
|
+
};
|
|
1512
|
+
const buildHeightsAndAccumulatedHeights = (editor) => {
|
|
1513
|
+
const children = (editor.children || []);
|
|
1514
|
+
const heights = new Array(children.length);
|
|
1515
|
+
const accumulatedHeights = new Array(children.length + 1);
|
|
1516
|
+
accumulatedHeights[0] = 0;
|
|
1517
|
+
for (let i = 0; i < children.length; i++) {
|
|
1518
|
+
const height = getRealHeightByElement(editor, children[i]);
|
|
1519
|
+
heights[i] = height;
|
|
1520
|
+
accumulatedHeights[i + 1] = accumulatedHeights[i] + height;
|
|
1521
|
+
}
|
|
1522
|
+
return { heights, accumulatedHeights };
|
|
1523
|
+
};
|
|
1524
|
+
const scrollToElement = (editor, element, scrollTo) => {
|
|
1525
|
+
const children = editor.children;
|
|
1526
|
+
if (!children.length) {
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
const anchorIndex = children.findIndex(item => item === element);
|
|
1530
|
+
if (anchorIndex < 0) {
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
const { accumulatedHeights } = buildHeightsAndAccumulatedHeights(editor);
|
|
1534
|
+
scrollTo((accumulatedHeights[anchorIndex] ?? 0) + getBusinessTop(editor));
|
|
1535
|
+
};
|
|
1536
|
+
|
|
1537
|
+
const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
|
|
1538
|
+
let e = editor;
|
|
1539
|
+
let { apply } = e;
|
|
1540
|
+
e = withDOM(e, clipboardFormatKey);
|
|
1541
|
+
e.setFragmentData = (dataTransfer, originEvent) => {
|
|
1542
|
+
const { selection } = e;
|
|
1543
|
+
if (!selection) {
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
const [start, end] = Range.edges(selection);
|
|
1547
|
+
const startVoid = Editor.void(e, { at: start.path });
|
|
1548
|
+
const endVoid = Editor.void(e, { at: end.path });
|
|
1549
|
+
if (Range.isCollapsed(selection) && !startVoid) {
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
// Create a fake selection so that we can add a Base64-encoded copy of the
|
|
1553
|
+
// fragment to the HTML, to decode on future pastes.
|
|
1554
|
+
let domRange;
|
|
1555
|
+
if (AngularEditor.isEnabledVirtualScroll(e)) {
|
|
1556
|
+
const virtualScrollSelection = EDITOR_TO_VIRTUAL_SCROLL_SELECTION.get(e);
|
|
1557
|
+
if (virtualScrollSelection) {
|
|
1558
|
+
domRange = AngularEditor.toDOMRange(e, virtualScrollSelection);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
domRange = domRange ?? AngularEditor.toDOMRange(e, selection);
|
|
1562
|
+
let contents = domRange.cloneContents();
|
|
1563
|
+
let attach = contents.childNodes[0];
|
|
1564
|
+
// Make sure attach is non-empty, since empty nodes will not get copied.
|
|
1565
|
+
const contentsArray = Array.from(contents.children);
|
|
1566
|
+
contentsArray.forEach(node => {
|
|
1567
|
+
if (node.textContent && node.textContent.trim() !== '') {
|
|
1568
|
+
attach = node;
|
|
1569
|
+
}
|
|
1570
|
+
});
|
|
1571
|
+
// COMPAT: If the end node is a void node, we need to move the end of the
|
|
1572
|
+
// range from the void node's spacer span, to the end of the void node's
|
|
1573
|
+
// content, since the spacer is before void's content in the DOM.
|
|
1574
|
+
if (endVoid) {
|
|
1575
|
+
const [voidNode] = endVoid;
|
|
1576
|
+
const r = domRange.cloneRange();
|
|
1577
|
+
const domNode = AngularEditor.toDOMNode(e, voidNode);
|
|
1578
|
+
r.setEndAfter(domNode);
|
|
1579
|
+
contents = r.cloneContents();
|
|
1580
|
+
}
|
|
1581
|
+
// COMPAT: If the start node is a void node, we need to attach the encoded
|
|
1582
|
+
// fragment to the void node's content node instead of the spacer, because
|
|
1583
|
+
// attaching it to empty `<div>/<span>` nodes will end up having it erased by
|
|
1584
|
+
// most browsers. (2018/04/27)
|
|
1585
|
+
if (startVoid) {
|
|
1586
|
+
attach = contents.querySelector('[data-slate-spacer]');
|
|
1587
|
+
}
|
|
1588
|
+
// Remove any zero-width space spans from the cloned DOM so that they don't
|
|
1589
|
+
// show up elsewhere when pasted.
|
|
1590
|
+
Array.from(contents.querySelectorAll('[data-slate-zero-width]')).forEach(zw => {
|
|
1591
|
+
const isNewline = zw.getAttribute('data-slate-zero-width') === 'n';
|
|
1592
|
+
zw.textContent = isNewline ? '\n' : '';
|
|
1593
|
+
});
|
|
1594
|
+
// Set a `data-slate-fragment` attribute on a non-empty node, so it shows up
|
|
1595
|
+
// in the HTML, and can be used for intra-Slate pasting. If it's a text
|
|
1596
|
+
// node, wrap it in a `<span>` so we have something to set an attribute on.
|
|
1597
|
+
if (isDOMText(attach)) {
|
|
1598
|
+
const span = attach.ownerDocument.createElement('span');
|
|
1599
|
+
// COMPAT: In Chrome and Safari, if we don't add the `white-space` style
|
|
1600
|
+
// then leading and trailing spaces will be ignored. (2017/09/21)
|
|
1601
|
+
span.style.whiteSpace = 'pre';
|
|
1602
|
+
span.appendChild(attach);
|
|
1603
|
+
contents.appendChild(span);
|
|
1604
|
+
attach = span;
|
|
1605
|
+
}
|
|
1606
|
+
const fragment = e.getFragment();
|
|
1607
|
+
// Add the content to a <div> so that we can get its inner HTML.
|
|
1608
|
+
const div = contents.ownerDocument.createElement('div');
|
|
1609
|
+
const attachWrapper = document.createElement('div');
|
|
1610
|
+
const elements = Array.from(contents.children);
|
|
1611
|
+
if (isInvalidTable(elements)) {
|
|
1612
|
+
contents = completeTable(contents.cloneNode(true));
|
|
1613
|
+
}
|
|
1614
|
+
attachWrapper.appendChild(contents);
|
|
1615
|
+
div.appendChild(attachWrapper);
|
|
1616
|
+
div.setAttribute('hidden', 'true');
|
|
1617
|
+
contents.ownerDocument.body.appendChild(div);
|
|
1618
|
+
setClipboardData({ text: getPlainText(div), elements: fragment }, div, attachWrapper, dataTransfer);
|
|
1619
|
+
contents.ownerDocument.body.removeChild(div);
|
|
1620
|
+
};
|
|
1621
|
+
e.deleteCutData = () => {
|
|
1622
|
+
const { selection } = editor;
|
|
1623
|
+
if (selection) {
|
|
1624
|
+
if (Range.isExpanded(selection)) {
|
|
1625
|
+
Editor.deleteFragment(editor);
|
|
1626
|
+
}
|
|
1627
|
+
else {
|
|
1628
|
+
const node = Node.parent(editor, selection.anchor.path);
|
|
1629
|
+
if (Element.isElement(node) && Editor.isVoid(editor, node)) {
|
|
1630
|
+
Transforms.delete(editor);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
e.insertData = async (data) => {
|
|
1636
|
+
if (!(await e.customInsertFragmentData(data, null))) {
|
|
1637
|
+
e.insertTextData(data);
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
e.customInsertFragmentData = async (data, contextClipboardData) => {
|
|
1641
|
+
/**
|
|
1642
|
+
* Checking copied fragment from application/x-slate-fragment or data-slate-fragment
|
|
1643
|
+
*/
|
|
1644
|
+
const clipboardData = contextClipboardData || (await getClipboardData(data));
|
|
1645
|
+
if (clipboardData && clipboardData.elements) {
|
|
1646
|
+
e.insertFragment(clipboardData.elements);
|
|
1647
|
+
return true;
|
|
1648
|
+
}
|
|
1649
|
+
return false;
|
|
1650
|
+
};
|
|
1651
|
+
e.customInsertTextData = async (data) => {
|
|
1652
|
+
const clipboardData = await getClipboardData(data);
|
|
1653
|
+
if (clipboardData && clipboardData.text) {
|
|
1654
|
+
const lines = clipboardData.text.split(/\r\n|\r|\n/);
|
|
1655
|
+
let split = false;
|
|
1656
|
+
for (const line of lines) {
|
|
1657
|
+
if (split) {
|
|
1658
|
+
Transforms.splitNodes(e, { always: true });
|
|
1659
|
+
}
|
|
1660
|
+
e.insertText(line);
|
|
1131
1661
|
split = true;
|
|
1132
1662
|
}
|
|
1133
1663
|
return true;
|
|
@@ -2141,1030 +2671,531 @@ const createLineBreakEmptyStringDOM = (elementStringLength) => {
|
|
|
2141
2671
|
*/
|
|
2142
2672
|
const isEmpty = (editor, element) => {
|
|
2143
2673
|
const { children } = element;
|
|
2144
|
-
const [first] = children;
|
|
2145
|
-
return children.length === 0 || (children.length === 1 && Text$1.isText(first) && first.text === '' && !editor.isVoid(element));
|
|
2146
|
-
};
|
|
2147
|
-
|
|
2148
|
-
class DefaultLeafFlavour extends BaseLeafFlavour {
|
|
2149
|
-
constructor() {
|
|
2150
|
-
super(...arguments);
|
|
2151
|
-
this.stringRender = null;
|
|
2152
|
-
}
|
|
2153
|
-
render() {
|
|
2154
|
-
const leafNode = createDefaultLeafNode();
|
|
2155
|
-
this.stringRender = new SlateStringRender(this.context, this.viewContext);
|
|
2156
|
-
const stringNode = this.stringRender.render();
|
|
2157
|
-
leafNode.appendChild(stringNode);
|
|
2158
|
-
this.nativeElement = leafNode;
|
|
2159
|
-
}
|
|
2160
|
-
rerender() {
|
|
2161
|
-
this.stringRender?.update(this.context, this.viewContext);
|
|
2162
|
-
}
|
|
2163
|
-
}
|
|
2164
|
-
const createDefaultLeafNode = () => {
|
|
2165
|
-
const span = document.createElement('span');
|
|
2166
|
-
span.setAttribute('data-slate-leaf', 'true');
|
|
2167
|
-
return span;
|
|
2168
|
-
};
|
|
2169
|
-
|
|
2170
|
-
class LeavesRender {
|
|
2171
|
-
constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
|
|
2172
|
-
this.viewContext = viewContext;
|
|
2173
|
-
this.viewContainerRef = viewContainerRef;
|
|
2174
|
-
this.getOutletParent = getOutletParent;
|
|
2175
|
-
this.getOutletElement = getOutletElement;
|
|
2176
|
-
this.views = [];
|
|
2177
|
-
this.contexts = [];
|
|
2178
|
-
this.viewTypes = [];
|
|
2179
|
-
}
|
|
2180
|
-
initialize(context) {
|
|
2181
|
-
const { decoratedLeaves, contexts } = this.getLeaves(context);
|
|
2182
|
-
this.decoratedLeaves = decoratedLeaves;
|
|
2183
|
-
this.contexts = contexts;
|
|
2184
|
-
this.decoratedLeaves.forEach((leaf, index) => {
|
|
2185
|
-
const context = getContext$1(index, this.contexts);
|
|
2186
|
-
const viewType = getViewType$1(context, this.viewContext);
|
|
2187
|
-
const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2188
|
-
this.views.push(view);
|
|
2189
|
-
this.contexts.push(context);
|
|
2190
|
-
this.viewTypes.push(viewType);
|
|
2191
|
-
});
|
|
2192
|
-
mount(this.views, null, this.getOutletParent(), this.getOutletElement());
|
|
2193
|
-
const newDiffers = this.viewContext.editor.injector.get(IterableDiffers);
|
|
2194
|
-
this.differ = newDiffers.find(this.decoratedLeaves).create(trackBy$1(this.viewContext));
|
|
2195
|
-
this.differ.diff(this.decoratedLeaves);
|
|
2196
|
-
}
|
|
2197
|
-
update(context) {
|
|
2198
|
-
const { decoratedLeaves, contexts } = this.getLeaves(context);
|
|
2199
|
-
const outletParent = this.getOutletParent();
|
|
2200
|
-
const diffResult = this.differ.diff(decoratedLeaves);
|
|
2201
|
-
if (diffResult) {
|
|
2202
|
-
let firstRootNode = getRootNodes(this.views[0])[0];
|
|
2203
|
-
const newContexts = [];
|
|
2204
|
-
const newViewTypes = [];
|
|
2205
|
-
const newViews = [];
|
|
2206
|
-
diffResult.forEachItem(record => {
|
|
2207
|
-
let context = getContext$1(record.currentIndex, contexts);
|
|
2208
|
-
const viewType = getViewType$1(context, this.viewContext);
|
|
2209
|
-
newViewTypes.push(viewType);
|
|
2210
|
-
let view;
|
|
2211
|
-
if (record.previousIndex === null) {
|
|
2212
|
-
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2213
|
-
newContexts.push(context);
|
|
2214
|
-
newViews.push(view);
|
|
2215
|
-
mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
|
|
2216
|
-
}
|
|
2217
|
-
else {
|
|
2218
|
-
const previousView = this.views[record.previousIndex];
|
|
2219
|
-
const previousViewType = this.viewTypes[record.previousIndex];
|
|
2220
|
-
if (previousViewType !== viewType) {
|
|
2221
|
-
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2222
|
-
const firstRootNode = getRootNodes(previousView, null)[0];
|
|
2223
|
-
const newRootNodes = getRootNodes(view, null);
|
|
2224
|
-
firstRootNode.replaceWith(...newRootNodes);
|
|
2225
|
-
previousView.destroy();
|
|
2226
|
-
}
|
|
2227
|
-
else {
|
|
2228
|
-
view = previousView;
|
|
2229
|
-
updateContext(previousView, context, this.viewContext);
|
|
2230
|
-
}
|
|
2231
|
-
newContexts.push(context);
|
|
2232
|
-
newViews.push(view);
|
|
2233
|
-
}
|
|
2234
|
-
});
|
|
2235
|
-
diffResult.forEachRemovedItem(record => {
|
|
2236
|
-
const view = this.views[record.previousIndex];
|
|
2237
|
-
view.destroy();
|
|
2238
|
-
});
|
|
2239
|
-
diffResult.forEachMovedItem(record => {
|
|
2240
|
-
mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
|
|
2241
|
-
});
|
|
2242
|
-
this.viewTypes = newViewTypes;
|
|
2243
|
-
this.views = newViews;
|
|
2244
|
-
this.contexts = newContexts;
|
|
2245
|
-
this.decoratedLeaves = decoratedLeaves;
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
getLeaves(context) {
|
|
2249
|
-
const decoratedLeaves = Text$1.decorations(context.text, context.decorations);
|
|
2250
|
-
const contexts = decoratedLeaves.map((decoratedLeaf, index) => {
|
|
2251
|
-
return {
|
|
2252
|
-
leaf: decoratedLeaf.leaf,
|
|
2253
|
-
leafPosition: decoratedLeaf.position,
|
|
2254
|
-
text: context.text,
|
|
2255
|
-
parent: context.parent,
|
|
2256
|
-
index,
|
|
2257
|
-
isLast: context.isLast && index === decoratedLeaves.length - 1
|
|
2258
|
-
};
|
|
2259
|
-
});
|
|
2260
|
-
return { decoratedLeaves, contexts };
|
|
2261
|
-
}
|
|
2262
|
-
destroy() {
|
|
2263
|
-
this.views.forEach(view => view.destroy());
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
function getContext$1(index, leafContexts) {
|
|
2267
|
-
return leafContexts[index];
|
|
2268
|
-
}
|
|
2269
|
-
function getViewType$1(leafContext, viewContext) {
|
|
2270
|
-
return (viewContext.renderLeaf && viewContext.renderLeaf(leafContext.leaf)) || DefaultLeafFlavour;
|
|
2271
|
-
}
|
|
2272
|
-
function trackBy$1(viewContext) {
|
|
2273
|
-
return (index, node) => {
|
|
2274
|
-
return index;
|
|
2275
|
-
};
|
|
2276
|
-
}
|
|
2277
|
-
|
|
2278
|
-
class BaseTextFlavour extends BaseFlavour {
|
|
2279
|
-
constructor() {
|
|
2280
|
-
super(...arguments);
|
|
2281
|
-
this.getOutletParent = () => {
|
|
2282
|
-
return this.nativeElement;
|
|
2283
|
-
};
|
|
2284
|
-
this.getOutletElement = () => {
|
|
2285
|
-
return this.nativeElement.querySelector('.children-outlet');
|
|
2286
|
-
};
|
|
2287
|
-
}
|
|
2288
|
-
get text() {
|
|
2289
|
-
return this._context && this._context.text;
|
|
2290
|
-
}
|
|
2291
|
-
onInit() {
|
|
2292
|
-
this.render();
|
|
2293
|
-
this.updateWeakMap();
|
|
2294
|
-
this.initialized = true;
|
|
2295
|
-
this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
|
|
2296
|
-
this.leavesRender.initialize(this.context);
|
|
2297
|
-
}
|
|
2298
|
-
updateWeakMap() {
|
|
2299
|
-
ELEMENT_TO_NODE.set(this.nativeElement, this.text);
|
|
2300
|
-
NODE_TO_ELEMENT.set(this.text, this.nativeElement);
|
|
2301
|
-
}
|
|
2302
|
-
onDestroy() {
|
|
2303
|
-
if (NODE_TO_ELEMENT.get(this.text) === this.nativeElement) {
|
|
2304
|
-
NODE_TO_ELEMENT.delete(this.text);
|
|
2305
|
-
}
|
|
2306
|
-
ELEMENT_TO_NODE.delete(this.nativeElement);
|
|
2307
|
-
this.leavesRender.destroy();
|
|
2308
|
-
this.nativeElement?.remove();
|
|
2309
|
-
}
|
|
2310
|
-
onContextChange() {
|
|
2311
|
-
if (!this.initialized) {
|
|
2312
|
-
return;
|
|
2313
|
-
}
|
|
2314
|
-
this.rerender();
|
|
2315
|
-
this.updateWeakMap();
|
|
2316
|
-
this.leavesRender.update(this.context);
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2674
|
+
const [first] = children;
|
|
2675
|
+
return children.length === 0 || (children.length === 1 && Text$1.isText(first) && first.text === '' && !editor.isVoid(element));
|
|
2676
|
+
};
|
|
2319
2677
|
|
|
2320
|
-
class
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
this.
|
|
2678
|
+
class DefaultLeafFlavour extends BaseLeafFlavour {
|
|
2679
|
+
constructor() {
|
|
2680
|
+
super(...arguments);
|
|
2681
|
+
this.stringRender = null;
|
|
2324
2682
|
}
|
|
2325
|
-
rerender() { }
|
|
2326
|
-
}
|
|
2327
|
-
class VoidTextFlavour extends BaseTextFlavour {
|
|
2328
2683
|
render() {
|
|
2329
|
-
const
|
|
2330
|
-
this.
|
|
2331
|
-
this.
|
|
2332
|
-
|
|
2684
|
+
const leafNode = createDefaultLeafNode();
|
|
2685
|
+
this.stringRender = new SlateStringRender(this.context, this.viewContext);
|
|
2686
|
+
const stringNode = this.stringRender.render();
|
|
2687
|
+
leafNode.appendChild(stringNode);
|
|
2688
|
+
this.nativeElement = leafNode;
|
|
2689
|
+
}
|
|
2690
|
+
rerender() {
|
|
2691
|
+
this.stringRender?.update(this.context, this.viewContext);
|
|
2333
2692
|
}
|
|
2334
|
-
rerender() { }
|
|
2335
2693
|
}
|
|
2336
|
-
const
|
|
2337
|
-
const
|
|
2338
|
-
|
|
2339
|
-
return
|
|
2694
|
+
const createDefaultLeafNode = () => {
|
|
2695
|
+
const span = document.createElement('span');
|
|
2696
|
+
span.setAttribute('data-slate-leaf', 'true');
|
|
2697
|
+
return span;
|
|
2340
2698
|
};
|
|
2341
2699
|
|
|
2342
|
-
class
|
|
2700
|
+
class LeavesRender {
|
|
2343
2701
|
constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
|
|
2344
2702
|
this.viewContext = viewContext;
|
|
2345
2703
|
this.viewContainerRef = viewContainerRef;
|
|
2346
2704
|
this.getOutletParent = getOutletParent;
|
|
2347
2705
|
this.getOutletElement = getOutletElement;
|
|
2348
|
-
this.children = [];
|
|
2349
|
-
this.views = [];
|
|
2350
|
-
this.blockCards = [];
|
|
2351
|
-
this.contexts = [];
|
|
2352
|
-
this.viewTypes = [];
|
|
2353
|
-
this.differ = null;
|
|
2354
|
-
this.initialized = false;
|
|
2355
|
-
this.preRenderingHTMLElement = [];
|
|
2356
|
-
}
|
|
2357
|
-
initialize(children, parent, childrenContext, preRenderingCount = 0) {
|
|
2358
|
-
this.initialized = true;
|
|
2359
|
-
this.children = children;
|
|
2360
|
-
const isRoot = parent === this.viewContext.editor;
|
|
2361
|
-
const firstIndex = isRoot ? this.viewContext.editor.children.indexOf(children[0]) : 0;
|
|
2362
|
-
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2363
|
-
children.forEach((descendant, _index) => {
|
|
2364
|
-
NODE_TO_INDEX.set(descendant, firstIndex + _index);
|
|
2365
|
-
NODE_TO_PARENT.set(descendant, parent);
|
|
2366
|
-
const context = getContext(firstIndex + _index, descendant, parentPath, childrenContext, this.viewContext);
|
|
2367
|
-
const viewType = getViewType(descendant, parent, this.viewContext);
|
|
2368
|
-
const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2369
|
-
const blockCard = createBlockCard(descendant, view, this.viewContext);
|
|
2370
|
-
this.views.push(view);
|
|
2371
|
-
this.contexts.push(context);
|
|
2372
|
-
this.viewTypes.push(viewType);
|
|
2373
|
-
this.blockCards.push(blockCard);
|
|
2374
|
-
});
|
|
2375
|
-
mount(this.views, this.blockCards, this.getOutletParent(), this.getOutletElement());
|
|
2376
|
-
const newDiffers = this.viewContext.editor.injector.get(IterableDiffers);
|
|
2377
|
-
this.differ = newDiffers.find(children).create(trackBy(this.viewContext));
|
|
2378
|
-
this.differ.diff(children);
|
|
2379
|
-
if (parent === this.viewContext.editor) {
|
|
2380
|
-
executeAfterViewInit(this.viewContext.editor);
|
|
2381
|
-
}
|
|
2382
|
-
}
|
|
2383
|
-
update(children, parent, childrenContext, preRenderingCount = 0) {
|
|
2384
|
-
if (!this.initialized || this.children.length === 0) {
|
|
2385
|
-
this.initialize(children, parent, childrenContext, preRenderingCount);
|
|
2386
|
-
return;
|
|
2387
|
-
}
|
|
2388
|
-
if (!this.differ) {
|
|
2389
|
-
throw new Error('Exception: Can not find differ ');
|
|
2390
|
-
}
|
|
2391
|
-
const outletParent = this.getOutletParent();
|
|
2392
|
-
if (this.preRenderingHTMLElement.length > 0) {
|
|
2393
|
-
const preRenderingElement = [...this.preRenderingHTMLElement];
|
|
2394
|
-
preRenderingElement.forEach((rootNodes, index) => {
|
|
2395
|
-
rootNodes.forEach(rootNode => {
|
|
2396
|
-
rootNode.style.position = '';
|
|
2397
|
-
rootNode.style.top = '';
|
|
2398
|
-
rootNode.style.width = '';
|
|
2399
|
-
});
|
|
2400
|
-
});
|
|
2401
|
-
this.preRenderingHTMLElement = [];
|
|
2402
|
-
}
|
|
2403
|
-
const diffResult = this.differ.diff(children);
|
|
2404
|
-
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2405
|
-
const isRoot = parent === this.viewContext.editor;
|
|
2406
|
-
const firstIndex = isRoot ? this.viewContext.editor.children.indexOf(children[0]) : 0;
|
|
2407
|
-
if (diffResult) {
|
|
2408
|
-
let firstRootNode = getRootNodes(this.views[0], this.blockCards[0])[0];
|
|
2409
|
-
const newContexts = [];
|
|
2410
|
-
const newViewTypes = [];
|
|
2411
|
-
const newViews = [];
|
|
2412
|
-
const newBlockCards = [];
|
|
2413
|
-
diffResult.forEachItem(record => {
|
|
2414
|
-
const currentIndex = firstIndex + record.currentIndex;
|
|
2415
|
-
NODE_TO_INDEX.set(record.item, currentIndex);
|
|
2416
|
-
NODE_TO_PARENT.set(record.item, parent);
|
|
2417
|
-
let context = getContext(currentIndex, record.item, parentPath, childrenContext, this.viewContext);
|
|
2418
|
-
const viewType = getViewType(record.item, parent, this.viewContext);
|
|
2419
|
-
newViewTypes.push(viewType);
|
|
2420
|
-
let view;
|
|
2421
|
-
let blockCard;
|
|
2422
|
-
if (record.previousIndex === null) {
|
|
2423
|
-
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2424
|
-
blockCard = createBlockCard(record.item, view, this.viewContext);
|
|
2425
|
-
newContexts.push(context);
|
|
2426
|
-
newViews.push(view);
|
|
2427
|
-
newBlockCards.push(blockCard);
|
|
2428
|
-
mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
|
|
2429
|
-
}
|
|
2430
|
-
else {
|
|
2431
|
-
const previousView = this.views[record.previousIndex];
|
|
2432
|
-
const previousViewType = this.viewTypes[record.previousIndex];
|
|
2433
|
-
const previousContext = this.contexts[record.previousIndex];
|
|
2434
|
-
const previousBlockCard = this.blockCards[record.previousIndex];
|
|
2435
|
-
if (previousViewType !== viewType) {
|
|
2436
|
-
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2437
|
-
blockCard = createBlockCard(record.item, view, this.viewContext);
|
|
2438
|
-
const firstRootNode = getRootNodes(previousView, previousBlockCard)[0];
|
|
2439
|
-
const newRootNodes = getRootNodes(view, blockCard);
|
|
2440
|
-
firstRootNode.replaceWith(...newRootNodes);
|
|
2441
|
-
previousView.destroy();
|
|
2442
|
-
previousBlockCard?.destroy();
|
|
2443
|
-
}
|
|
2444
|
-
else {
|
|
2445
|
-
view = previousView;
|
|
2446
|
-
blockCard = previousBlockCard;
|
|
2447
|
-
if (memoizedContext(this.viewContext, record.item, previousContext, context)) {
|
|
2448
|
-
context = previousContext;
|
|
2449
|
-
}
|
|
2450
|
-
else {
|
|
2451
|
-
updateContext(previousView, context, this.viewContext);
|
|
2452
|
-
}
|
|
2453
|
-
}
|
|
2454
|
-
newContexts.push(context);
|
|
2455
|
-
newViews.push(view);
|
|
2456
|
-
newBlockCards.push(blockCard);
|
|
2457
|
-
}
|
|
2458
|
-
});
|
|
2459
|
-
diffResult.forEachOperation(record => {
|
|
2460
|
-
// removed
|
|
2461
|
-
if (record.currentIndex === null) {
|
|
2462
|
-
const view = this.views[record.previousIndex];
|
|
2463
|
-
const blockCard = this.blockCards[record.previousIndex];
|
|
2464
|
-
view.destroy();
|
|
2465
|
-
blockCard?.destroy();
|
|
2466
|
-
}
|
|
2467
|
-
// moved
|
|
2468
|
-
if (record.previousIndex !== null && record.currentIndex !== null) {
|
|
2469
|
-
mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
|
|
2470
|
-
// Solve the block-card DOMElement loss when moving nodes
|
|
2471
|
-
newBlockCards[record.currentIndex]?.instance.append();
|
|
2472
|
-
}
|
|
2473
|
-
});
|
|
2474
|
-
this.viewTypes = newViewTypes;
|
|
2475
|
-
this.views = newViews;
|
|
2476
|
-
this.contexts = newContexts;
|
|
2477
|
-
this.children = children;
|
|
2478
|
-
this.blockCards = newBlockCards;
|
|
2479
|
-
if (parent === this.viewContext.editor) {
|
|
2480
|
-
executeAfterViewInit(this.viewContext.editor);
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
2483
|
-
else {
|
|
2484
|
-
const newContexts = [];
|
|
2485
|
-
this.children.forEach((child, _index) => {
|
|
2486
|
-
NODE_TO_INDEX.set(child, firstIndex + _index);
|
|
2487
|
-
NODE_TO_PARENT.set(child, parent);
|
|
2488
|
-
let context = getContext(firstIndex + _index, child, parentPath, childrenContext, this.viewContext);
|
|
2489
|
-
const previousContext = this.contexts[_index];
|
|
2490
|
-
if (memoizedContext(this.viewContext, child, previousContext, context)) {
|
|
2491
|
-
context = previousContext;
|
|
2492
|
-
}
|
|
2493
|
-
else {
|
|
2494
|
-
updateContext(this.views[_index], context, this.viewContext);
|
|
2495
|
-
}
|
|
2496
|
-
newContexts.push(context);
|
|
2497
|
-
});
|
|
2498
|
-
this.contexts = newContexts;
|
|
2499
|
-
}
|
|
2500
|
-
if (preRenderingCount > 0) {
|
|
2501
|
-
for (let i = 0; i < preRenderingCount; i++) {
|
|
2502
|
-
const rootNodes = [...getRootNodes(this.views[i], this.blockCards[i])];
|
|
2503
|
-
rootNodes.forEach(rootNode => {
|
|
2504
|
-
rootNode.style = `position: absolute;top: -100%;`;
|
|
2505
|
-
});
|
|
2506
|
-
this.preRenderingHTMLElement.push(rootNodes);
|
|
2507
|
-
}
|
|
2508
|
-
}
|
|
2509
|
-
}
|
|
2510
|
-
destroy() {
|
|
2511
|
-
this.children.forEach((element, index) => {
|
|
2512
|
-
if (this.views[index]) {
|
|
2513
|
-
this.views[index].destroy();
|
|
2514
|
-
}
|
|
2515
|
-
if (this.blockCards[index]) {
|
|
2516
|
-
this.blockCards[index].destroy();
|
|
2517
|
-
}
|
|
2518
|
-
});
|
|
2519
|
-
this.children = [];
|
|
2520
2706
|
this.views = [];
|
|
2521
|
-
this.blockCards = [];
|
|
2522
2707
|
this.contexts = [];
|
|
2523
2708
|
this.viewTypes = [];
|
|
2524
|
-
this.initialized = false;
|
|
2525
|
-
this.differ = null;
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
function getContext(index, item, parentPath, childrenContext, viewContext) {
|
|
2529
|
-
if (Element.isElement(item)) {
|
|
2530
|
-
const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
|
|
2531
|
-
const key = AngularEditor.findKey(viewContext.editor, item);
|
|
2532
|
-
const isInline = viewContext.editor.isInline(item);
|
|
2533
|
-
const isVoid = viewContext.editor.isVoid(item);
|
|
2534
|
-
const elementContext = {
|
|
2535
|
-
element: item,
|
|
2536
|
-
...computedContext,
|
|
2537
|
-
attributes: {
|
|
2538
|
-
'data-slate-node': 'element',
|
|
2539
|
-
'data-slate-key': key.id
|
|
2540
|
-
},
|
|
2541
|
-
decorate: childrenContext.decorate,
|
|
2542
|
-
readonly: childrenContext.readonly
|
|
2543
|
-
};
|
|
2544
|
-
if (isInline) {
|
|
2545
|
-
elementContext.attributes['data-slate-inline'] = true;
|
|
2546
|
-
}
|
|
2547
|
-
if (isVoid) {
|
|
2548
|
-
elementContext.attributes['data-slate-void'] = true;
|
|
2549
|
-
}
|
|
2550
|
-
// add contentEditable for block element only to avoid chinese input be broken
|
|
2551
|
-
if (isVoid && !isInline) {
|
|
2552
|
-
elementContext.contentEditable = false;
|
|
2553
|
-
}
|
|
2554
|
-
return elementContext;
|
|
2555
2709
|
}
|
|
2556
|
-
|
|
2557
|
-
const
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2710
|
+
initialize(context) {
|
|
2711
|
+
const { decoratedLeaves, contexts } = this.getLeaves(context);
|
|
2712
|
+
this.decoratedLeaves = decoratedLeaves;
|
|
2713
|
+
this.contexts = contexts;
|
|
2714
|
+
this.decoratedLeaves.forEach((leaf, index) => {
|
|
2715
|
+
const context = getContext$1(index, this.contexts);
|
|
2716
|
+
const viewType = getViewType$1(context, this.viewContext);
|
|
2717
|
+
const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2718
|
+
this.views.push(view);
|
|
2719
|
+
this.contexts.push(context);
|
|
2720
|
+
this.viewTypes.push(viewType);
|
|
2721
|
+
});
|
|
2722
|
+
mount(this.views, null, this.getOutletParent(), this.getOutletElement());
|
|
2723
|
+
const newDiffers = this.viewContext.editor.injector.get(IterableDiffers);
|
|
2724
|
+
this.differ = newDiffers.find(this.decoratedLeaves).create(trackBy$1(this.viewContext));
|
|
2725
|
+
this.differ.diff(this.decoratedLeaves);
|
|
2566
2726
|
}
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
const
|
|
2575
|
-
const
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2727
|
+
update(context) {
|
|
2728
|
+
const { decoratedLeaves, contexts } = this.getLeaves(context);
|
|
2729
|
+
const outletParent = this.getOutletParent();
|
|
2730
|
+
const diffResult = this.differ.diff(decoratedLeaves);
|
|
2731
|
+
if (diffResult) {
|
|
2732
|
+
let firstRootNode = getRootNodes(this.views[0])[0];
|
|
2733
|
+
const newContexts = [];
|
|
2734
|
+
const newViewTypes = [];
|
|
2735
|
+
const newViews = [];
|
|
2736
|
+
diffResult.forEachItem(record => {
|
|
2737
|
+
let context = getContext$1(record.currentIndex, contexts);
|
|
2738
|
+
const viewType = getViewType$1(context, this.viewContext);
|
|
2739
|
+
newViewTypes.push(viewType);
|
|
2740
|
+
let view;
|
|
2741
|
+
if (record.previousIndex === null) {
|
|
2742
|
+
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2743
|
+
newContexts.push(context);
|
|
2744
|
+
newViews.push(view);
|
|
2745
|
+
mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
|
|
2580
2746
|
}
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2747
|
+
else {
|
|
2748
|
+
const previousView = this.views[record.previousIndex];
|
|
2749
|
+
const previousViewType = this.viewTypes[record.previousIndex];
|
|
2750
|
+
if (previousViewType !== viewType) {
|
|
2751
|
+
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2752
|
+
const firstRootNode = getRootNodes(previousView, null)[0];
|
|
2753
|
+
const newRootNodes = getRootNodes(view, null);
|
|
2754
|
+
firstRootNode.replaceWith(...newRootNodes);
|
|
2755
|
+
previousView.destroy();
|
|
2756
|
+
}
|
|
2757
|
+
else {
|
|
2758
|
+
view = previousView;
|
|
2759
|
+
updateContext(previousView, context, this.viewContext);
|
|
2760
|
+
}
|
|
2761
|
+
newContexts.push(context);
|
|
2762
|
+
newViews.push(view);
|
|
2763
|
+
}
|
|
2764
|
+
});
|
|
2765
|
+
diffResult.forEachRemovedItem(record => {
|
|
2766
|
+
const view = this.views[record.previousIndex];
|
|
2767
|
+
view.destroy();
|
|
2768
|
+
});
|
|
2769
|
+
diffResult.forEachMovedItem(record => {
|
|
2770
|
+
mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
|
|
2771
|
+
});
|
|
2772
|
+
this.viewTypes = newViewTypes;
|
|
2773
|
+
this.views = newViews;
|
|
2774
|
+
this.contexts = newContexts;
|
|
2775
|
+
this.decoratedLeaves = decoratedLeaves;
|
|
2586
2776
|
}
|
|
2587
2777
|
}
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2778
|
+
getLeaves(context) {
|
|
2779
|
+
const decoratedLeaves = Text$1.decorations(context.text, context.decorations);
|
|
2780
|
+
const contexts = decoratedLeaves.map((decoratedLeaf, index) => {
|
|
2781
|
+
return {
|
|
2782
|
+
leaf: decoratedLeaf.leaf,
|
|
2783
|
+
leafPosition: decoratedLeaf.position,
|
|
2784
|
+
text: context.text,
|
|
2785
|
+
parent: context.parent,
|
|
2786
|
+
index,
|
|
2787
|
+
isLast: context.isLast && index === decoratedLeaves.length - 1
|
|
2788
|
+
};
|
|
2592
2789
|
});
|
|
2593
|
-
return {
|
|
2594
|
-
}
|
|
2595
|
-
}
|
|
2596
|
-
function getViewType(item, parent, viewContext) {
|
|
2597
|
-
if (Element.isElement(item)) {
|
|
2598
|
-
return (viewContext.renderElement && viewContext.renderElement(item)) || DefaultElementFlavour;
|
|
2790
|
+
return { decoratedLeaves, contexts };
|
|
2599
2791
|
}
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
return isVoid ? VoidTextFlavour : (viewContext.renderText && viewContext.renderText(item)) || DefaultTextFlavour;
|
|
2792
|
+
destroy() {
|
|
2793
|
+
this.views.forEach(view => view.destroy());
|
|
2603
2794
|
}
|
|
2604
2795
|
}
|
|
2605
|
-
function
|
|
2606
|
-
|
|
2607
|
-
if (isBlockCard) {
|
|
2608
|
-
const rootNodes = getRootNodes(view);
|
|
2609
|
-
const blockCardRef = new BlockCardRef();
|
|
2610
|
-
blockCardRef.instance = new SlateBlockCard();
|
|
2611
|
-
blockCardRef.instance.onInit();
|
|
2612
|
-
blockCardRef.instance.initializeCenter(rootNodes);
|
|
2613
|
-
return blockCardRef;
|
|
2614
|
-
}
|
|
2615
|
-
else {
|
|
2616
|
-
return null;
|
|
2617
|
-
}
|
|
2796
|
+
function getContext$1(index, leafContexts) {
|
|
2797
|
+
return leafContexts[index];
|
|
2618
2798
|
}
|
|
2619
|
-
function
|
|
2799
|
+
function getViewType$1(leafContext, viewContext) {
|
|
2800
|
+
return (viewContext.renderLeaf && viewContext.renderLeaf(leafContext.leaf)) || DefaultLeafFlavour;
|
|
2801
|
+
}
|
|
2802
|
+
function trackBy$1(viewContext) {
|
|
2620
2803
|
return (index, node) => {
|
|
2621
|
-
return
|
|
2804
|
+
return index;
|
|
2622
2805
|
};
|
|
2623
2806
|
}
|
|
2624
|
-
function memoizedContext(viewContext, descendant, prev, next) {
|
|
2625
|
-
if (Element.isElement(descendant)) {
|
|
2626
|
-
return memoizedElementContext(viewContext, prev, next);
|
|
2627
|
-
}
|
|
2628
|
-
else {
|
|
2629
|
-
return memoizedTextContext(prev, next);
|
|
2630
|
-
}
|
|
2631
|
-
}
|
|
2632
|
-
function memoizedElementContext(viewContext, prev, next) {
|
|
2633
|
-
return (prev.element === next.element &&
|
|
2634
|
-
(!viewContext.isStrictDecorate || prev.decorate === next.decorate) &&
|
|
2635
|
-
prev.readonly === next.readonly &&
|
|
2636
|
-
isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
|
|
2637
|
-
(prev.selection === next.selection || (!!prev.selection && !!next.selection && Range.equals(prev.selection, next.selection))));
|
|
2638
|
-
}
|
|
2639
|
-
function memoizedTextContext(prev, next) {
|
|
2640
|
-
return (next.parent === prev.parent &&
|
|
2641
|
-
next.isLast === prev.isLast &&
|
|
2642
|
-
next.text === prev.text &&
|
|
2643
|
-
isDecoratorRangeListEqual(next.decorations, prev.decorations));
|
|
2644
|
-
}
|
|
2645
|
-
function addAfterViewInitQueue(editor, afterViewInitCallback) {
|
|
2646
|
-
const queue = getAfterViewInitQueue(editor);
|
|
2647
|
-
queue.push(afterViewInitCallback);
|
|
2648
|
-
EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, queue);
|
|
2649
|
-
}
|
|
2650
|
-
function getAfterViewInitQueue(editor) {
|
|
2651
|
-
return EDITOR_TO_AFTER_VIEW_INIT_QUEUE.get(editor) || [];
|
|
2652
|
-
}
|
|
2653
|
-
function clearAfterViewInitQueue(editor) {
|
|
2654
|
-
EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, []);
|
|
2655
|
-
}
|
|
2656
|
-
function executeAfterViewInit(editor) {
|
|
2657
|
-
const queue = getAfterViewInitQueue(editor);
|
|
2658
|
-
queue.forEach(callback => callback());
|
|
2659
|
-
clearAfterViewInitQueue(editor);
|
|
2660
|
-
}
|
|
2661
2807
|
|
|
2662
|
-
class
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
this.instance = new VirtualScrollDebugOverlay(doc);
|
|
2671
|
-
}
|
|
2672
|
-
this.instance.init();
|
|
2673
|
-
return this.instance;
|
|
2674
|
-
}
|
|
2675
|
-
static log(doc, type, ...args) {
|
|
2676
|
-
this.getInstance(doc).log(type, ...args);
|
|
2677
|
-
}
|
|
2678
|
-
static syncScrollTop(doc, value) {
|
|
2679
|
-
const instance = this.getInstance(doc);
|
|
2680
|
-
instance.setScrollTopValue(value);
|
|
2681
|
-
}
|
|
2682
|
-
constructor(doc) {
|
|
2683
|
-
this.doc = doc;
|
|
2684
|
-
this.state = {
|
|
2685
|
-
left: 16,
|
|
2686
|
-
top: 16,
|
|
2687
|
-
collapsed: false,
|
|
2688
|
-
width: VirtualScrollDebugOverlay.defaultWidth,
|
|
2689
|
-
height: VirtualScrollDebugOverlay.defaultHeight
|
|
2690
|
-
};
|
|
2691
|
-
this.originalConsoleLog = console.log.bind(console);
|
|
2692
|
-
this.originalConsoleWarn = console.warn.bind(console);
|
|
2693
|
-
this.dragOffsetX = 0;
|
|
2694
|
-
this.dragOffsetY = 0;
|
|
2695
|
-
this.isDragging = false;
|
|
2696
|
-
this.isResizing = false;
|
|
2697
|
-
this.resizeStartX = 0;
|
|
2698
|
-
this.resizeStartY = 0;
|
|
2699
|
-
this.resizeStartWidth = 0;
|
|
2700
|
-
this.resizeStartHeight = 0;
|
|
2701
|
-
this.dragMoved = false;
|
|
2702
|
-
this.wasDragged = false;
|
|
2703
|
-
this.onDragging = (event) => {
|
|
2704
|
-
if (!this.isDragging || !this.container) {
|
|
2705
|
-
return;
|
|
2706
|
-
}
|
|
2707
|
-
this.dragMoved = true;
|
|
2708
|
-
const nextLeft = event.clientX - this.dragOffsetX;
|
|
2709
|
-
const nextTop = event.clientY - this.dragOffsetY;
|
|
2710
|
-
this.container.style.left = `${nextLeft}px`;
|
|
2711
|
-
this.container.style.top = `${nextTop}px`;
|
|
2712
|
-
this.container.style.right = 'auto';
|
|
2713
|
-
this.container.style.bottom = 'auto';
|
|
2714
|
-
};
|
|
2715
|
-
this.onDragEnd = () => {
|
|
2716
|
-
if (!this.isDragging) {
|
|
2717
|
-
return;
|
|
2718
|
-
}
|
|
2719
|
-
this.isDragging = false;
|
|
2720
|
-
this.wasDragged = this.dragMoved;
|
|
2721
|
-
this.dragMoved = false;
|
|
2722
|
-
this.doc.removeEventListener('mousemove', this.onDragging);
|
|
2723
|
-
this.doc.removeEventListener('mouseup', this.onDragEnd);
|
|
2724
|
-
if (this.container) {
|
|
2725
|
-
const rect = this.container.getBoundingClientRect();
|
|
2726
|
-
this.state.left = rect.left;
|
|
2727
|
-
this.state.top = rect.top;
|
|
2728
|
-
this.persistState();
|
|
2729
|
-
this.container.style.transition = '';
|
|
2730
|
-
}
|
|
2731
|
-
};
|
|
2732
|
-
this.onResizing = (event) => {
|
|
2733
|
-
if (!this.isResizing || !this.container) {
|
|
2734
|
-
return;
|
|
2735
|
-
}
|
|
2736
|
-
const deltaX = event.clientX - this.resizeStartX;
|
|
2737
|
-
const deltaY = event.clientY - this.resizeStartY;
|
|
2738
|
-
const nextWidth = Math.max(VirtualScrollDebugOverlay.minWidth, this.resizeStartWidth + deltaX);
|
|
2739
|
-
const nextHeight = Math.max(VirtualScrollDebugOverlay.minHeight, this.resizeStartHeight + deltaY);
|
|
2740
|
-
this.state.width = nextWidth;
|
|
2741
|
-
this.state.height = nextHeight;
|
|
2742
|
-
this.applySize();
|
|
2743
|
-
};
|
|
2744
|
-
this.onResizeEnd = () => {
|
|
2745
|
-
if (!this.isResizing) {
|
|
2746
|
-
return;
|
|
2747
|
-
}
|
|
2748
|
-
this.isResizing = false;
|
|
2749
|
-
this.doc.removeEventListener('mousemove', this.onResizing);
|
|
2750
|
-
this.doc.removeEventListener('mouseup', this.onResizeEnd);
|
|
2751
|
-
this.persistState();
|
|
2808
|
+
class BaseTextFlavour extends BaseFlavour {
|
|
2809
|
+
constructor() {
|
|
2810
|
+
super(...arguments);
|
|
2811
|
+
this.getOutletParent = () => {
|
|
2812
|
+
return this.nativeElement;
|
|
2813
|
+
};
|
|
2814
|
+
this.getOutletElement = () => {
|
|
2815
|
+
return this.nativeElement.querySelector('.children-outlet');
|
|
2752
2816
|
};
|
|
2753
2817
|
}
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
this.createContainer();
|
|
2757
|
-
}
|
|
2758
|
-
else {
|
|
2759
|
-
this.applyState();
|
|
2760
|
-
}
|
|
2818
|
+
get text() {
|
|
2819
|
+
return this._context && this._context.text;
|
|
2761
2820
|
}
|
|
2762
|
-
|
|
2763
|
-
this.
|
|
2764
|
-
|
|
2765
|
-
|
|
2821
|
+
onInit() {
|
|
2822
|
+
this.render();
|
|
2823
|
+
this.updateWeakMap();
|
|
2824
|
+
this.initialized = true;
|
|
2825
|
+
this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
|
|
2826
|
+
this.leavesRender.initialize(this.context);
|
|
2827
|
+
}
|
|
2828
|
+
updateWeakMap() {
|
|
2829
|
+
ELEMENT_TO_NODE.set(this.nativeElement, this.text);
|
|
2830
|
+
NODE_TO_ELEMENT.set(this.text, this.nativeElement);
|
|
2831
|
+
}
|
|
2832
|
+
onDestroy() {
|
|
2833
|
+
if (NODE_TO_ELEMENT.get(this.text) === this.nativeElement) {
|
|
2834
|
+
NODE_TO_ELEMENT.delete(this.text);
|
|
2766
2835
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2836
|
+
ELEMENT_TO_NODE.delete(this.nativeElement);
|
|
2837
|
+
this.leavesRender.destroy();
|
|
2838
|
+
this.nativeElement?.remove();
|
|
2839
|
+
}
|
|
2840
|
+
onContextChange() {
|
|
2841
|
+
if (!this.initialized) {
|
|
2842
|
+
return;
|
|
2769
2843
|
}
|
|
2770
|
-
this.
|
|
2844
|
+
this.rerender();
|
|
2845
|
+
this.updateWeakMap();
|
|
2846
|
+
this.leavesRender.update(this.context);
|
|
2771
2847
|
}
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
this.
|
|
2778
|
-
this.selectorInput = undefined;
|
|
2779
|
-
this.distanceInput = undefined;
|
|
2780
|
-
this.collapseToggle = undefined;
|
|
2781
|
-
this.resizeHandle = undefined;
|
|
2782
|
-
this.doc.removeEventListener('mousemove', this.onDragging);
|
|
2783
|
-
this.doc.removeEventListener('mouseup', this.onDragEnd);
|
|
2784
|
-
this.doc.removeEventListener('mousemove', this.onResizing);
|
|
2785
|
-
this.doc.removeEventListener('mouseup', this.onResizeEnd);
|
|
2786
|
-
this.isDragging = false;
|
|
2787
|
-
this.isResizing = false;
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
class DefaultTextFlavour extends BaseTextFlavour {
|
|
2851
|
+
render() {
|
|
2852
|
+
const { nativeElement } = createText(this.text.text);
|
|
2853
|
+
this.nativeElement = nativeElement;
|
|
2788
2854
|
}
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
const
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
collapseButton.style.borderRadius = '6px';
|
|
2839
|
-
collapseButton.style.padding = '4px 8px';
|
|
2840
|
-
collapseButton.style.cursor = 'pointer';
|
|
2841
|
-
collapseButton.addEventListener('click', () => {
|
|
2842
|
-
this.setCollapsed(!this.state.collapsed);
|
|
2843
|
-
});
|
|
2844
|
-
const clearButton = doc.createElement('button');
|
|
2845
|
-
clearButton.type = 'button';
|
|
2846
|
-
clearButton.textContent = '清除日志';
|
|
2847
|
-
clearButton.style.background = '#374151';
|
|
2848
|
-
clearButton.style.color = '#e5e7eb';
|
|
2849
|
-
clearButton.style.border = '1px solid #4b5563';
|
|
2850
|
-
clearButton.style.borderRadius = '6px';
|
|
2851
|
-
clearButton.style.padding = '4px 10px';
|
|
2852
|
-
clearButton.style.cursor = 'pointer';
|
|
2853
|
-
clearButton.addEventListener('click', () => {
|
|
2854
|
-
if (this.logList) {
|
|
2855
|
-
this.logList.innerHTML = '';
|
|
2856
|
-
}
|
|
2857
|
-
});
|
|
2858
|
-
actions.appendChild(collapseButton);
|
|
2859
|
-
actions.appendChild(clearButton);
|
|
2860
|
-
header.appendChild(title);
|
|
2861
|
-
header.appendChild(actions);
|
|
2862
|
-
const scrollForm = doc.createElement('div');
|
|
2863
|
-
scrollForm.style.display = 'grid';
|
|
2864
|
-
scrollForm.style.gridTemplateColumns = '1fr 110px 50px';
|
|
2865
|
-
scrollForm.style.gap = '6px';
|
|
2866
|
-
scrollForm.style.alignItems = 'center';
|
|
2867
|
-
const selectorInput = doc.createElement('input');
|
|
2868
|
-
selectorInput.placeholder = '滚动容器 selector';
|
|
2869
|
-
selectorInput.style.padding = '6px 8px';
|
|
2870
|
-
selectorInput.style.borderRadius = '6px';
|
|
2871
|
-
selectorInput.style.border = '1px solid #4b5563';
|
|
2872
|
-
selectorInput.style.background = '#111827';
|
|
2873
|
-
selectorInput.style.color = '#e5e7eb';
|
|
2874
|
-
selectorInput.autocomplete = 'off';
|
|
2875
|
-
const distanceInput = doc.createElement('input');
|
|
2876
|
-
distanceInput.placeholder = '滚动距离(px)';
|
|
2877
|
-
distanceInput.type = 'number';
|
|
2878
|
-
distanceInput.style.padding = '6px 8px';
|
|
2879
|
-
distanceInput.style.borderRadius = '6px';
|
|
2880
|
-
distanceInput.style.border = '1px solid #4b5563';
|
|
2881
|
-
distanceInput.style.background = '#111827';
|
|
2882
|
-
distanceInput.style.color = '#e5e7eb';
|
|
2883
|
-
const scrollButton = doc.createElement('button');
|
|
2884
|
-
scrollButton.type = 'button';
|
|
2885
|
-
scrollButton.textContent = '滚动';
|
|
2886
|
-
scrollButton.style.background = '#10b981';
|
|
2887
|
-
scrollButton.style.color = '#0b1c15';
|
|
2888
|
-
scrollButton.style.border = 'none';
|
|
2889
|
-
scrollButton.style.borderRadius = '6px';
|
|
2890
|
-
scrollButton.style.padding = '6px 10px';
|
|
2891
|
-
scrollButton.style.cursor = 'pointer';
|
|
2892
|
-
scrollButton.addEventListener('click', () => {
|
|
2893
|
-
const selector = selectorInput.value.trim();
|
|
2894
|
-
const distanceValue = Number(distanceInput.value ?? 0);
|
|
2895
|
-
const distance = Number.isFinite(distanceValue) ? distanceValue : 0;
|
|
2896
|
-
if (!selector) {
|
|
2897
|
-
this.log('warn', '请先填写滚动容器 selector');
|
|
2898
|
-
return;
|
|
2899
|
-
}
|
|
2900
|
-
const target = doc.querySelector(selector);
|
|
2901
|
-
if (!target) {
|
|
2902
|
-
this.log('warn', `未找到滚动容器: ${selector}`);
|
|
2903
|
-
return;
|
|
2904
|
-
}
|
|
2905
|
-
if (typeof target.scrollTo === 'function') {
|
|
2906
|
-
target.scrollTo({ top: distance, behavior: 'auto' });
|
|
2907
|
-
}
|
|
2908
|
-
else if (Object.prototype.hasOwnProperty.call(target, 'scrollTop')) {
|
|
2909
|
-
target.scrollTop = distance;
|
|
2910
|
-
}
|
|
2911
|
-
else {
|
|
2912
|
-
this.log('warn', '目标元素不支持滚动:', selector);
|
|
2913
|
-
return;
|
|
2914
|
-
}
|
|
2915
|
-
this.log('log', `已将 ${selector} 滚动到`, distance);
|
|
2916
|
-
});
|
|
2917
|
-
scrollForm.appendChild(selectorInput);
|
|
2918
|
-
scrollForm.appendChild(distanceInput);
|
|
2919
|
-
scrollForm.appendChild(scrollButton);
|
|
2920
|
-
const logList = doc.createElement('div');
|
|
2921
|
-
logList.style.height = '260px';
|
|
2922
|
-
logList.style.overflowY = 'auto';
|
|
2923
|
-
logList.style.background = '#0b1220';
|
|
2924
|
-
logList.style.border = '1px solid #1f2937';
|
|
2925
|
-
logList.style.borderRadius = '8px';
|
|
2926
|
-
logList.style.padding = '8px';
|
|
2927
|
-
logList.style.display = 'flex';
|
|
2928
|
-
logList.style.flexDirection = 'column';
|
|
2929
|
-
logList.style.gap = '6px';
|
|
2930
|
-
logList.style.flex = '1';
|
|
2931
|
-
logList.style.minHeight = '160px';
|
|
2932
|
-
const bubble = doc.createElement('div');
|
|
2933
|
-
bubble.textContent = 'VS';
|
|
2934
|
-
bubble.style.display = 'none';
|
|
2935
|
-
bubble.style.alignItems = 'center';
|
|
2936
|
-
bubble.style.justifyContent = 'center';
|
|
2937
|
-
bubble.style.fontWeight = '700';
|
|
2938
|
-
bubble.style.fontSize = '14px';
|
|
2939
|
-
bubble.style.letterSpacing = '0.5px';
|
|
2940
|
-
bubble.style.width = '100%';
|
|
2941
|
-
bubble.style.height = '100%';
|
|
2942
|
-
bubble.style.userSelect = 'none';
|
|
2943
|
-
bubble.addEventListener('click', () => {
|
|
2944
|
-
if (this.wasDragged) {
|
|
2945
|
-
this.wasDragged = false;
|
|
2946
|
-
return;
|
|
2947
|
-
}
|
|
2948
|
-
this.setCollapsed(false);
|
|
2949
|
-
});
|
|
2950
|
-
const contentWrapper = doc.createElement('div');
|
|
2951
|
-
contentWrapper.style.display = 'flex';
|
|
2952
|
-
contentWrapper.style.flexDirection = 'column';
|
|
2953
|
-
contentWrapper.style.gap = '10px';
|
|
2954
|
-
contentWrapper.style.width = '100%';
|
|
2955
|
-
contentWrapper.style.height = '100%';
|
|
2956
|
-
contentWrapper.appendChild(header);
|
|
2957
|
-
contentWrapper.appendChild(scrollForm);
|
|
2958
|
-
contentWrapper.appendChild(logList);
|
|
2959
|
-
container.appendChild(contentWrapper);
|
|
2960
|
-
container.appendChild(bubble);
|
|
2961
|
-
const resizeHandle = doc.createElement('div');
|
|
2962
|
-
resizeHandle.style.position = 'absolute';
|
|
2963
|
-
resizeHandle.style.right = '6px';
|
|
2964
|
-
resizeHandle.style.bottom = '6px';
|
|
2965
|
-
resizeHandle.style.width = '14px';
|
|
2966
|
-
resizeHandle.style.height = '14px';
|
|
2967
|
-
resizeHandle.style.cursor = 'nwse-resize';
|
|
2968
|
-
resizeHandle.style.borderRight = '2px solid #4b5563';
|
|
2969
|
-
resizeHandle.style.borderBottom = '2px solid #4b5563';
|
|
2970
|
-
resizeHandle.addEventListener('mousedown', event => {
|
|
2971
|
-
this.startResize(event);
|
|
2855
|
+
rerender() { }
|
|
2856
|
+
}
|
|
2857
|
+
class VoidTextFlavour extends BaseTextFlavour {
|
|
2858
|
+
render() {
|
|
2859
|
+
const { nativeElement } = createText(this.text.text);
|
|
2860
|
+
this.nativeElement = nativeElement;
|
|
2861
|
+
this.nativeElement.setAttribute('data-slate-spacer', 'true');
|
|
2862
|
+
this.nativeElement.classList.add('slate-spacer');
|
|
2863
|
+
}
|
|
2864
|
+
rerender() { }
|
|
2865
|
+
}
|
|
2866
|
+
const createText = (text) => {
|
|
2867
|
+
const nativeElement = document.createElement('span');
|
|
2868
|
+
nativeElement.setAttribute('data-slate-node', 'text');
|
|
2869
|
+
return { nativeElement };
|
|
2870
|
+
};
|
|
2871
|
+
|
|
2872
|
+
class ListRender {
|
|
2873
|
+
constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
|
|
2874
|
+
this.viewContext = viewContext;
|
|
2875
|
+
this.viewContainerRef = viewContainerRef;
|
|
2876
|
+
this.getOutletParent = getOutletParent;
|
|
2877
|
+
this.getOutletElement = getOutletElement;
|
|
2878
|
+
this.children = [];
|
|
2879
|
+
this.views = [];
|
|
2880
|
+
this.blockCards = [];
|
|
2881
|
+
this.contexts = [];
|
|
2882
|
+
this.viewTypes = [];
|
|
2883
|
+
this.differ = null;
|
|
2884
|
+
this.initialized = false;
|
|
2885
|
+
this.preRenderingHTMLElement = [];
|
|
2886
|
+
}
|
|
2887
|
+
initialize(children, parent, childrenContext, preRenderingCount = 0) {
|
|
2888
|
+
this.initialized = true;
|
|
2889
|
+
this.children = children;
|
|
2890
|
+
const isRoot = parent === this.viewContext.editor;
|
|
2891
|
+
const firstIndex = isRoot ? this.viewContext.editor.children.indexOf(children[0]) : 0;
|
|
2892
|
+
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2893
|
+
children.forEach((descendant, _index) => {
|
|
2894
|
+
NODE_TO_INDEX.set(descendant, firstIndex + _index);
|
|
2895
|
+
NODE_TO_PARENT.set(descendant, parent);
|
|
2896
|
+
const context = getContext(firstIndex + _index, descendant, parentPath, childrenContext, this.viewContext);
|
|
2897
|
+
const viewType = getViewType(descendant, parent, this.viewContext);
|
|
2898
|
+
const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2899
|
+
const blockCard = createBlockCard(descendant, view, this.viewContext);
|
|
2900
|
+
this.views.push(view);
|
|
2901
|
+
this.contexts.push(context);
|
|
2902
|
+
this.viewTypes.push(viewType);
|
|
2903
|
+
this.blockCards.push(blockCard);
|
|
2972
2904
|
});
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
this.
|
|
2976
|
-
this.
|
|
2977
|
-
this.
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
this.distanceInput = distanceInput;
|
|
2981
|
-
this.collapseToggle = collapseButton;
|
|
2982
|
-
this.resizeHandle = resizeHandle;
|
|
2983
|
-
this.applyState();
|
|
2905
|
+
mount(this.views, this.blockCards, this.getOutletParent(), this.getOutletElement());
|
|
2906
|
+
const newDiffers = this.viewContext.editor.injector.get(IterableDiffers);
|
|
2907
|
+
this.differ = newDiffers.find(children).create(trackBy(this.viewContext));
|
|
2908
|
+
this.differ.diff(children);
|
|
2909
|
+
if (parent === this.viewContext.editor) {
|
|
2910
|
+
executeAfterViewInit(this.viewContext.editor);
|
|
2911
|
+
}
|
|
2984
2912
|
}
|
|
2985
|
-
|
|
2986
|
-
if (
|
|
2913
|
+
update(children, parent, childrenContext, preRenderingCount = 0) {
|
|
2914
|
+
if (!this.initialized || this.children.length === 0) {
|
|
2915
|
+
this.initialize(children, parent, childrenContext, preRenderingCount);
|
|
2987
2916
|
return;
|
|
2988
2917
|
}
|
|
2989
|
-
if (!this.
|
|
2990
|
-
|
|
2918
|
+
if (!this.differ) {
|
|
2919
|
+
throw new Error('Exception: Can not find differ ');
|
|
2991
2920
|
}
|
|
2992
|
-
const
|
|
2993
|
-
this.
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
event.preventDefault();
|
|
2921
|
+
const outletParent = this.getOutletParent();
|
|
2922
|
+
if (this.preRenderingHTMLElement.length > 0) {
|
|
2923
|
+
const preRenderingElement = [...this.preRenderingHTMLElement];
|
|
2924
|
+
preRenderingElement.forEach((rootNodes, index) => {
|
|
2925
|
+
rootNodes.forEach(rootNode => {
|
|
2926
|
+
rootNode.style.position = '';
|
|
2927
|
+
rootNode.style.top = '';
|
|
2928
|
+
});
|
|
2929
|
+
});
|
|
2930
|
+
this.preRenderingHTMLElement = [];
|
|
3003
2931
|
}
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
2932
|
+
const diffResult = this.differ.diff(children);
|
|
2933
|
+
const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
|
|
2934
|
+
const isRoot = parent === this.viewContext.editor;
|
|
2935
|
+
const firstIndex = isRoot ? this.viewContext.editor.children.indexOf(children[0]) : 0;
|
|
2936
|
+
if (diffResult) {
|
|
2937
|
+
let firstRootNode = getRootNodes(this.views[0], this.blockCards[0])[0];
|
|
2938
|
+
const newContexts = [];
|
|
2939
|
+
const newViewTypes = [];
|
|
2940
|
+
const newViews = [];
|
|
2941
|
+
const newBlockCards = [];
|
|
2942
|
+
diffResult.forEachItem(record => {
|
|
2943
|
+
const currentIndex = firstIndex + record.currentIndex;
|
|
2944
|
+
NODE_TO_INDEX.set(record.item, currentIndex);
|
|
2945
|
+
NODE_TO_PARENT.set(record.item, parent);
|
|
2946
|
+
let context = getContext(currentIndex, record.item, parentPath, childrenContext, this.viewContext);
|
|
2947
|
+
const viewType = getViewType(record.item, parent, this.viewContext);
|
|
2948
|
+
newViewTypes.push(viewType);
|
|
2949
|
+
let view;
|
|
2950
|
+
let blockCard;
|
|
2951
|
+
if (record.previousIndex === null) {
|
|
2952
|
+
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2953
|
+
blockCard = createBlockCard(record.item, view, this.viewContext);
|
|
2954
|
+
newContexts.push(context);
|
|
2955
|
+
newViews.push(view);
|
|
2956
|
+
newBlockCards.push(blockCard);
|
|
2957
|
+
mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
|
|
2958
|
+
}
|
|
2959
|
+
else {
|
|
2960
|
+
const previousView = this.views[record.previousIndex];
|
|
2961
|
+
const previousViewType = this.viewTypes[record.previousIndex];
|
|
2962
|
+
const previousContext = this.contexts[record.previousIndex];
|
|
2963
|
+
const previousBlockCard = this.blockCards[record.previousIndex];
|
|
2964
|
+
if (previousViewType !== viewType) {
|
|
2965
|
+
view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
|
|
2966
|
+
blockCard = createBlockCard(record.item, view, this.viewContext);
|
|
2967
|
+
const firstRootNode = getRootNodes(previousView, previousBlockCard)[0];
|
|
2968
|
+
const newRootNodes = getRootNodes(view, blockCard);
|
|
2969
|
+
firstRootNode.replaceWith(...newRootNodes);
|
|
2970
|
+
previousView.destroy();
|
|
2971
|
+
previousBlockCard?.destroy();
|
|
2972
|
+
}
|
|
2973
|
+
else {
|
|
2974
|
+
view = previousView;
|
|
2975
|
+
blockCard = previousBlockCard;
|
|
2976
|
+
if (memoizedContext(this.viewContext, record.item, previousContext, context)) {
|
|
2977
|
+
context = previousContext;
|
|
2978
|
+
}
|
|
2979
|
+
else {
|
|
2980
|
+
updateContext(previousView, context, this.viewContext);
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
newContexts.push(context);
|
|
2984
|
+
newViews.push(view);
|
|
2985
|
+
newBlockCards.push(blockCard);
|
|
2986
|
+
}
|
|
2987
|
+
});
|
|
2988
|
+
diffResult.forEachOperation(record => {
|
|
2989
|
+
// removed
|
|
2990
|
+
if (record.currentIndex === null) {
|
|
2991
|
+
const view = this.views[record.previousIndex];
|
|
2992
|
+
const blockCard = this.blockCards[record.previousIndex];
|
|
2993
|
+
view.destroy();
|
|
2994
|
+
blockCard?.destroy();
|
|
2995
|
+
}
|
|
2996
|
+
// moved
|
|
2997
|
+
if (record.previousIndex !== null && record.currentIndex !== null) {
|
|
2998
|
+
mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
|
|
2999
|
+
// Solve the block-card DOMElement loss when moving nodes
|
|
3000
|
+
newBlockCards[record.currentIndex]?.instance.append();
|
|
3001
|
+
}
|
|
3002
|
+
});
|
|
3003
|
+
this.viewTypes = newViewTypes;
|
|
3004
|
+
this.views = newViews;
|
|
3005
|
+
this.contexts = newContexts;
|
|
3006
|
+
this.children = children;
|
|
3007
|
+
this.blockCards = newBlockCards;
|
|
3008
|
+
if (parent === this.viewContext.editor) {
|
|
3009
|
+
executeAfterViewInit(this.viewContext.editor);
|
|
3010
|
+
}
|
|
3008
3011
|
}
|
|
3009
|
-
|
|
3010
|
-
|
|
3012
|
+
else {
|
|
3013
|
+
const newContexts = [];
|
|
3014
|
+
this.children.forEach((child, _index) => {
|
|
3015
|
+
NODE_TO_INDEX.set(child, firstIndex + _index);
|
|
3016
|
+
NODE_TO_PARENT.set(child, parent);
|
|
3017
|
+
let context = getContext(firstIndex + _index, child, parentPath, childrenContext, this.viewContext);
|
|
3018
|
+
const previousContext = this.contexts[_index];
|
|
3019
|
+
if (memoizedContext(this.viewContext, child, previousContext, context)) {
|
|
3020
|
+
context = previousContext;
|
|
3021
|
+
}
|
|
3022
|
+
else {
|
|
3023
|
+
updateContext(this.views[_index], context, this.viewContext);
|
|
3024
|
+
}
|
|
3025
|
+
newContexts.push(context);
|
|
3026
|
+
});
|
|
3027
|
+
this.contexts = newContexts;
|
|
3011
3028
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
event.stopPropagation();
|
|
3022
|
-
}
|
|
3023
|
-
applyPosition() {
|
|
3024
|
-
if (!this.container) {
|
|
3025
|
-
return;
|
|
3029
|
+
if (preRenderingCount > 0) {
|
|
3030
|
+
for (let i = 0; i < preRenderingCount; i++) {
|
|
3031
|
+
const rootNodes = [...getRootNodes(this.views[i], this.blockCards[i])];
|
|
3032
|
+
rootNodes.forEach(rootNode => {
|
|
3033
|
+
rootNode.style.top = '-100%';
|
|
3034
|
+
rootNode.style.position = 'absolute';
|
|
3035
|
+
});
|
|
3036
|
+
this.preRenderingHTMLElement.push(rootNodes);
|
|
3037
|
+
}
|
|
3026
3038
|
}
|
|
3027
|
-
this.container.style.left = `${this.state.left}px`;
|
|
3028
|
-
this.container.style.top = `${this.state.top}px`;
|
|
3029
3039
|
}
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
this.
|
|
3040
|
+
destroy() {
|
|
3041
|
+
this.children.forEach((element, index) => {
|
|
3042
|
+
if (this.views[index]) {
|
|
3043
|
+
this.views[index].destroy();
|
|
3044
|
+
}
|
|
3045
|
+
if (this.blockCards[index]) {
|
|
3046
|
+
this.blockCards[index].destroy();
|
|
3047
|
+
}
|
|
3048
|
+
});
|
|
3049
|
+
this.children = [];
|
|
3050
|
+
this.views = [];
|
|
3051
|
+
this.blockCards = [];
|
|
3052
|
+
this.contexts = [];
|
|
3053
|
+
this.viewTypes = [];
|
|
3054
|
+
this.initialized = false;
|
|
3055
|
+
this.differ = null;
|
|
3040
3056
|
}
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3057
|
+
}
|
|
3058
|
+
function getContext(index, item, parentPath, childrenContext, viewContext) {
|
|
3059
|
+
if (Element.isElement(item)) {
|
|
3060
|
+
const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
|
|
3061
|
+
const key = AngularEditor.findKey(viewContext.editor, item);
|
|
3062
|
+
const isInline = viewContext.editor.isInline(item);
|
|
3063
|
+
const isVoid = viewContext.editor.isVoid(item);
|
|
3064
|
+
const elementContext = {
|
|
3065
|
+
element: item,
|
|
3066
|
+
...computedContext,
|
|
3067
|
+
attributes: {
|
|
3068
|
+
'data-slate-node': 'element',
|
|
3069
|
+
'data-slate-key': key.id
|
|
3070
|
+
},
|
|
3071
|
+
decorate: childrenContext.decorate,
|
|
3072
|
+
readonly: childrenContext.readonly
|
|
3073
|
+
};
|
|
3074
|
+
if (isInline) {
|
|
3075
|
+
elementContext.attributes['data-slate-inline'] = true;
|
|
3044
3076
|
}
|
|
3045
|
-
if (
|
|
3046
|
-
|
|
3047
|
-
this.container.style.height = '36px';
|
|
3048
|
-
this.container.style.minWidth = '';
|
|
3049
|
-
this.container.style.minHeight = '';
|
|
3050
|
-
this.container.style.padding = '0';
|
|
3051
|
-
this.container.style.borderRadius = '50%';
|
|
3052
|
-
this.container.style.display = 'flex';
|
|
3053
|
-
this.container.style.flexDirection = 'row';
|
|
3054
|
-
this.container.style.alignItems = 'center';
|
|
3055
|
-
this.container.style.justifyContent = 'center';
|
|
3056
|
-
this.container.style.cursor = 'move';
|
|
3057
|
-
this.contentWrapper.style.display = 'none';
|
|
3058
|
-
this.bubble.style.display = 'flex';
|
|
3059
|
-
this.collapseToggle.textContent = '展开';
|
|
3060
|
-
this.resizeHandle.style.display = 'none';
|
|
3077
|
+
if (isVoid) {
|
|
3078
|
+
elementContext.attributes['data-slate-void'] = true;
|
|
3061
3079
|
}
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
this.container.style.borderRadius = '10px';
|
|
3066
|
-
this.container.style.display = 'flex';
|
|
3067
|
-
this.container.style.flexDirection = 'column';
|
|
3068
|
-
this.container.style.gap = '10px';
|
|
3069
|
-
this.container.style.cursor = 'default';
|
|
3070
|
-
this.contentWrapper.style.display = 'flex';
|
|
3071
|
-
this.bubble.style.display = 'none';
|
|
3072
|
-
this.collapseToggle.textContent = '折叠';
|
|
3073
|
-
this.resizeHandle.style.display = 'block';
|
|
3080
|
+
// add contentEditable for block element only to avoid chinese input be broken
|
|
3081
|
+
if (isVoid && !isInline) {
|
|
3082
|
+
elementContext.contentEditable = false;
|
|
3074
3083
|
}
|
|
3084
|
+
return elementContext;
|
|
3075
3085
|
}
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3086
|
+
else {
|
|
3087
|
+
const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
|
|
3088
|
+
const isLeafBlock = AngularEditor.isLeafBlock(viewContext.editor, childrenContext.parent);
|
|
3089
|
+
const textContext = {
|
|
3090
|
+
decorations: computedContext.decorations,
|
|
3091
|
+
isLast: isLeafBlock && index === childrenContext.parent.children.length - 1,
|
|
3092
|
+
parent: childrenContext.parent,
|
|
3093
|
+
text: item
|
|
3094
|
+
};
|
|
3095
|
+
return textContext;
|
|
3084
3096
|
}
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
if (
|
|
3097
|
-
|
|
3098
|
-
}
|
|
3099
|
-
if (typeof parsed.width === 'number') {
|
|
3100
|
-
this.state.width = parsed.width;
|
|
3101
|
-
}
|
|
3102
|
-
if (typeof parsed.height === 'number') {
|
|
3103
|
-
this.state.height = parsed.height;
|
|
3097
|
+
}
|
|
3098
|
+
function getCommonContext(index, item, parentPath, viewContext, childrenContext) {
|
|
3099
|
+
const p = parentPath.concat(index);
|
|
3100
|
+
try {
|
|
3101
|
+
const ds = childrenContext.decorate([item, p]);
|
|
3102
|
+
// [list-render] performance optimization: reduce the number of calls to the `Editor.range(viewContext.editor, p)` method
|
|
3103
|
+
if (childrenContext.selection || childrenContext.decorations.length > 0) {
|
|
3104
|
+
const range = Editor.range(viewContext.editor, p);
|
|
3105
|
+
const sel = childrenContext.selection && Range.intersection(range, childrenContext.selection);
|
|
3106
|
+
for (const dec of childrenContext.decorations) {
|
|
3107
|
+
const d = Range.intersection(dec, range);
|
|
3108
|
+
if (d) {
|
|
3109
|
+
ds.push(d);
|
|
3104
3110
|
}
|
|
3105
3111
|
}
|
|
3112
|
+
return { selection: sel, decorations: ds };
|
|
3106
3113
|
}
|
|
3107
|
-
|
|
3108
|
-
|
|
3114
|
+
else {
|
|
3115
|
+
return { selection: null, decorations: ds };
|
|
3109
3116
|
}
|
|
3110
3117
|
}
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
}
|
|
3118
|
+
catch (error) {
|
|
3119
|
+
viewContext.editor.onError({
|
|
3120
|
+
code: SlateErrorCode.GetStartPointError,
|
|
3121
|
+
nativeError: error
|
|
3122
|
+
});
|
|
3123
|
+
return { selection: null, decorations: [] };
|
|
3118
3124
|
}
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
const item = this.doc.createElement('div');
|
|
3124
|
-
item.style.display = 'flex';
|
|
3125
|
-
item.style.gap = '6px';
|
|
3126
|
-
item.style.alignItems = 'flex-start';
|
|
3127
|
-
item.style.wordBreak = 'break-all';
|
|
3128
|
-
item.style.color = type === 'warn' ? '#fbbf24' : '#9ca3af';
|
|
3129
|
-
const time = this.doc.createElement('span');
|
|
3130
|
-
time.textContent = new Date().toLocaleTimeString();
|
|
3131
|
-
time.style.color = '#6b7280';
|
|
3132
|
-
time.style.flexShrink = '0';
|
|
3133
|
-
time.style.width = '72px';
|
|
3134
|
-
const text = this.doc.createElement('span');
|
|
3135
|
-
text.textContent = `[${type}] ${args.map(arg => this.formatValue(arg)).join(' ')}`;
|
|
3136
|
-
item.appendChild(time);
|
|
3137
|
-
item.appendChild(text);
|
|
3138
|
-
this.logList.appendChild(item);
|
|
3139
|
-
this.logList.scrollTop = this.logList.scrollHeight;
|
|
3125
|
+
}
|
|
3126
|
+
function getViewType(item, parent, viewContext) {
|
|
3127
|
+
if (Element.isElement(item)) {
|
|
3128
|
+
return (viewContext.renderElement && viewContext.renderElement(item)) || DefaultElementFlavour;
|
|
3140
3129
|
}
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
}
|
|
3145
|
-
try {
|
|
3146
|
-
return JSON.stringify(value);
|
|
3147
|
-
}
|
|
3148
|
-
catch (error) {
|
|
3149
|
-
return String(value);
|
|
3150
|
-
}
|
|
3130
|
+
else {
|
|
3131
|
+
const isVoid = viewContext.editor.isVoid(parent);
|
|
3132
|
+
return isVoid ? VoidTextFlavour : (viewContext.renderText && viewContext.renderText(item)) || DefaultTextFlavour;
|
|
3151
3133
|
}
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3134
|
+
}
|
|
3135
|
+
function createBlockCard(item, view, viewContext) {
|
|
3136
|
+
const isBlockCard = viewContext.editor.isBlockCard(item);
|
|
3137
|
+
if (isBlockCard) {
|
|
3138
|
+
const rootNodes = getRootNodes(view);
|
|
3139
|
+
const blockCardRef = new BlockCardRef();
|
|
3140
|
+
blockCardRef.instance = new SlateBlockCard();
|
|
3141
|
+
blockCardRef.instance.onInit();
|
|
3142
|
+
blockCardRef.instance.initializeCenter(rootNodes);
|
|
3143
|
+
return blockCardRef;
|
|
3144
|
+
}
|
|
3145
|
+
else {
|
|
3146
|
+
return null;
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
function trackBy(viewContext) {
|
|
3150
|
+
return (index, node) => {
|
|
3151
|
+
return viewContext.trackBy(node) || AngularEditor.findKey(viewContext.editor, node);
|
|
3152
|
+
};
|
|
3153
|
+
}
|
|
3154
|
+
function memoizedContext(viewContext, descendant, prev, next) {
|
|
3155
|
+
if (Element.isElement(descendant)) {
|
|
3156
|
+
return memoizedElementContext(viewContext, prev, next);
|
|
3156
3157
|
}
|
|
3158
|
+
else {
|
|
3159
|
+
return memoizedTextContext(prev, next);
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
function memoizedElementContext(viewContext, prev, next) {
|
|
3163
|
+
return (prev.element === next.element &&
|
|
3164
|
+
(!viewContext.isStrictDecorate || prev.decorate === next.decorate) &&
|
|
3165
|
+
prev.readonly === next.readonly &&
|
|
3166
|
+
isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
|
|
3167
|
+
(prev.selection === next.selection || (!!prev.selection && !!next.selection && Range.equals(prev.selection, next.selection))));
|
|
3168
|
+
}
|
|
3169
|
+
function memoizedTextContext(prev, next) {
|
|
3170
|
+
return (next.parent === prev.parent &&
|
|
3171
|
+
next.isLast === prev.isLast &&
|
|
3172
|
+
next.text === prev.text &&
|
|
3173
|
+
isDecoratorRangeListEqual(next.decorations, prev.decorations));
|
|
3174
|
+
}
|
|
3175
|
+
function addAfterViewInitQueue(editor, afterViewInitCallback) {
|
|
3176
|
+
const queue = getAfterViewInitQueue(editor);
|
|
3177
|
+
queue.push(afterViewInitCallback);
|
|
3178
|
+
EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, queue);
|
|
3179
|
+
}
|
|
3180
|
+
function getAfterViewInitQueue(editor) {
|
|
3181
|
+
return EDITOR_TO_AFTER_VIEW_INIT_QUEUE.get(editor) || [];
|
|
3182
|
+
}
|
|
3183
|
+
function clearAfterViewInitQueue(editor) {
|
|
3184
|
+
EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, []);
|
|
3185
|
+
}
|
|
3186
|
+
function executeAfterViewInit(editor) {
|
|
3187
|
+
const queue = getAfterViewInitQueue(editor);
|
|
3188
|
+
queue.forEach(callback => callback());
|
|
3189
|
+
clearAfterViewInitQueue(editor);
|
|
3157
3190
|
}
|
|
3158
3191
|
|
|
3159
3192
|
// not correctly clipboardData on beforeinput
|
|
3160
3193
|
const forceOnDOMPaste = IS_SAFARI;
|
|
3161
|
-
const isDebug = localStorage.getItem(SLATE_DEBUG_KEY) === 'true';
|
|
3162
|
-
const isDebugScrollTop = localStorage.getItem(SLATE_DEBUG_KEY_SCROLL_TOP) === 'true';
|
|
3163
3194
|
class SlateEditable {
|
|
3164
3195
|
set virtualScroll(config) {
|
|
3165
3196
|
this.virtualScrollConfig = config;
|
|
3166
3197
|
if (isDebugScrollTop) {
|
|
3167
|
-
|
|
3198
|
+
debugLog('log', 'virtualScrollConfig scrollTop:', config.scrollTop);
|
|
3168
3199
|
}
|
|
3169
3200
|
IS_ENABLED_VIRTUAL_SCROLL.set(this.editor, config.enabled);
|
|
3170
3201
|
if (this.isEnabledVirtualScroll()) {
|
|
@@ -3291,7 +3322,6 @@ class SlateEditable {
|
|
|
3291
3322
|
const { preRenderingCount, childrenWithPreRendering } = this.handlePreRendering();
|
|
3292
3323
|
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount);
|
|
3293
3324
|
}
|
|
3294
|
-
this.tryMeasureInViewportChildrenHeights();
|
|
3295
3325
|
}
|
|
3296
3326
|
else {
|
|
3297
3327
|
if (!this.listRender.initialized) {
|
|
@@ -3345,7 +3375,7 @@ class SlateEditable {
|
|
|
3345
3375
|
EDITOR_TO_VIRTUAL_SCROLL_SELECTION.set(this.editor, intersectedSelection);
|
|
3346
3376
|
if (!intersectedSelection || !Range.equals(intersectedSelection, forwardSelection)) {
|
|
3347
3377
|
if (isDebug) {
|
|
3348
|
-
|
|
3378
|
+
debugLog('log', `selection is not in visible range, selection: ${JSON.stringify(selection)}, intersectedSelection: ${JSON.stringify(intersectedSelection)}`);
|
|
3349
3379
|
}
|
|
3350
3380
|
return intersectedSelection;
|
|
3351
3381
|
}
|
|
@@ -3516,7 +3546,7 @@ class SlateEditable {
|
|
|
3516
3546
|
if (isDebug && remeasureIndics.length > 0) {
|
|
3517
3547
|
console.log('remeasure height by indics: ', remeasureIndics);
|
|
3518
3548
|
}
|
|
3519
|
-
this.
|
|
3549
|
+
measureHeightByIndics(this.editor, remeasureIndics, true);
|
|
3520
3550
|
}
|
|
3521
3551
|
updateContext() {
|
|
3522
3552
|
const decorations = this.generateDecorations();
|
|
@@ -3604,14 +3634,10 @@ class SlateEditable {
|
|
|
3604
3634
|
editorResizeObserverRectWidth = entries[0].contentRect.width;
|
|
3605
3635
|
this.keyHeightMap.clear();
|
|
3606
3636
|
const remeasureIndics = this.inViewportIndics;
|
|
3607
|
-
this.
|
|
3637
|
+
measureHeightByIndics(this.editor, remeasureIndics, true);
|
|
3608
3638
|
}
|
|
3609
3639
|
});
|
|
3610
3640
|
this.editorResizeObserver.observe(this.elementRef.nativeElement);
|
|
3611
|
-
if (isDebug) {
|
|
3612
|
-
const doc = this.elementRef?.nativeElement?.ownerDocument ?? document;
|
|
3613
|
-
VirtualScrollDebugOverlay.getInstance(doc);
|
|
3614
|
-
}
|
|
3615
3641
|
}
|
|
3616
3642
|
}
|
|
3617
3643
|
setVirtualSpaceHeight(topHeight, bottomHeight) {
|
|
@@ -3629,10 +3655,6 @@ class SlateEditable {
|
|
|
3629
3655
|
}
|
|
3630
3656
|
return parseFloat(this.virtualTopHeightElement.style.height.replace('px', ''));
|
|
3631
3657
|
}
|
|
3632
|
-
debugLog(type, ...args) {
|
|
3633
|
-
const doc = this.elementRef?.nativeElement?.ownerDocument ?? document;
|
|
3634
|
-
VirtualScrollDebugOverlay.log(doc, type, ...args);
|
|
3635
|
-
}
|
|
3636
3658
|
handlePreRendering() {
|
|
3637
3659
|
let preRenderingCount = 1;
|
|
3638
3660
|
const childrenWithPreRendering = [...this.inViewportChildren];
|
|
@@ -3650,51 +3672,62 @@ class SlateEditable {
|
|
|
3650
3672
|
}
|
|
3651
3673
|
tryUpdateVirtualViewport() {
|
|
3652
3674
|
if (isDebug) {
|
|
3653
|
-
|
|
3675
|
+
debugLog('log', 'tryUpdateVirtualViewport');
|
|
3654
3676
|
}
|
|
3655
3677
|
this.tryUpdateVirtualViewportAnimId && cancelAnimationFrame(this.tryUpdateVirtualViewportAnimId);
|
|
3656
3678
|
this.tryUpdateVirtualViewportAnimId = requestAnimationFrame(() => {
|
|
3657
3679
|
if (isDebug) {
|
|
3658
|
-
|
|
3680
|
+
debugLog('log', 'tryUpdateVirtualViewport Anim start');
|
|
3659
3681
|
}
|
|
3660
3682
|
let virtualView = this.calculateVirtualViewport();
|
|
3661
3683
|
let diff = this.diffVirtualViewport(virtualView);
|
|
3684
|
+
if (diff.isDifferent && diff.needRemoveOnTop) {
|
|
3685
|
+
const remeasureIndics = diff.changedIndexesOfTop;
|
|
3686
|
+
const changed = measureHeightByIndics(this.editor, remeasureIndics);
|
|
3687
|
+
if (changed) {
|
|
3688
|
+
virtualView = this.calculateVirtualViewport();
|
|
3689
|
+
diff = this.diffVirtualViewport(virtualView, 'second');
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3662
3692
|
if (diff.isDifferent) {
|
|
3663
3693
|
this.applyVirtualView(virtualView);
|
|
3664
3694
|
if (this.listRender.initialized) {
|
|
3665
3695
|
const { preRenderingCount, childrenWithPreRendering } = this.handlePreRendering();
|
|
3666
3696
|
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount);
|
|
3697
|
+
if (diff.needAddOnTop) {
|
|
3698
|
+
const remeasureAddedIndics = diff.changedIndexesOfTop;
|
|
3699
|
+
if (isDebug) {
|
|
3700
|
+
debugLog('log', 'needAddOnTop to remeasure heights: ', remeasureAddedIndics);
|
|
3701
|
+
}
|
|
3702
|
+
const startIndexBeforeAdd = diff.changedIndexesOfTop[diff.changedIndexesOfTop.length - 1] + 1;
|
|
3703
|
+
const topHeightBeforeAdd = virtualView.accumulatedHeights[startIndexBeforeAdd];
|
|
3704
|
+
const changed = measureHeightByIndics(this.editor, remeasureAddedIndics);
|
|
3705
|
+
if (changed) {
|
|
3706
|
+
const newHeights = buildHeightsAndAccumulatedHeights(this.editor);
|
|
3707
|
+
const actualTopHeightAfterAdd = newHeights.accumulatedHeights[startIndexBeforeAdd];
|
|
3708
|
+
const newTopHeight = virtualView.top - (actualTopHeightAfterAdd - topHeightBeforeAdd);
|
|
3709
|
+
this.setVirtualSpaceHeight(newTopHeight);
|
|
3710
|
+
if (isDebug) {
|
|
3711
|
+
debugLog('log', `update top height since will add element in top(正数减去高度,负数代表增加高度): ${actualTopHeightAfterAdd - topHeightBeforeAdd}`);
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3667
3715
|
if (!AngularEditor.isReadOnly(this.editor) && this.editor.selection) {
|
|
3668
3716
|
this.toNativeSelection();
|
|
3669
3717
|
}
|
|
3670
3718
|
}
|
|
3671
|
-
if (diff.needAddOnTop) {
|
|
3672
|
-
const remeasureAddedIndics = diff.changedIndexesOfTop;
|
|
3673
|
-
if (isDebug) {
|
|
3674
|
-
this.debugLog('log', 'needAddOnTop to remeasure heights: ', remeasureAddedIndics);
|
|
3675
|
-
}
|
|
3676
|
-
const startIndexBeforeAdd = diff.changedIndexesOfTop[diff.changedIndexesOfTop.length - 1] + 1;
|
|
3677
|
-
const topHeightBeforeAdd = virtualView.accumulatedHeights[startIndexBeforeAdd];
|
|
3678
|
-
const result = this.remeasureHeightByIndics(remeasureAddedIndics);
|
|
3679
|
-
if (result) {
|
|
3680
|
-
const newHeights = buildHeightsAndAccumulatedHeights(this.editor);
|
|
3681
|
-
const actualTopHeightAfterAdd = newHeights.accumulatedHeights[startIndexBeforeAdd];
|
|
3682
|
-
const newTopHeight = virtualView.top - (actualTopHeightAfterAdd - topHeightBeforeAdd);
|
|
3683
|
-
this.setVirtualSpaceHeight(newTopHeight);
|
|
3684
|
-
this.debugLog('log', `update top height cause added element in top, 减去: ${actualTopHeightAfterAdd - topHeightBeforeAdd}`);
|
|
3685
|
-
}
|
|
3686
|
-
}
|
|
3687
|
-
this.tryMeasureInViewportChildrenHeights();
|
|
3688
3719
|
}
|
|
3689
3720
|
else {
|
|
3690
3721
|
const topHeight = this.getVirtualTopHeight();
|
|
3691
3722
|
if (virtualView.top !== topHeight) {
|
|
3692
|
-
|
|
3723
|
+
if (isDebug) {
|
|
3724
|
+
debugLog('log', 'update top height since invalid status(正数减去高度,负数代表增加高度): ', topHeight - virtualView.top);
|
|
3725
|
+
}
|
|
3693
3726
|
this.setVirtualSpaceHeight(virtualView.top);
|
|
3694
3727
|
}
|
|
3695
3728
|
}
|
|
3696
3729
|
if (isDebug) {
|
|
3697
|
-
|
|
3730
|
+
debugLog('log', 'tryUpdateVirtualViewport Anim end');
|
|
3698
3731
|
}
|
|
3699
3732
|
});
|
|
3700
3733
|
}
|
|
@@ -3734,7 +3767,7 @@ class SlateEditable {
|
|
|
3734
3767
|
Math.floor(this.virtualScrollConfig.viewportBoundingTop);
|
|
3735
3768
|
EDITOR_TO_BUSINESS_TOP.set(this.editor, businessTop);
|
|
3736
3769
|
if (isDebug) {
|
|
3737
|
-
|
|
3770
|
+
debugLog('log', 'businessTop', businessTop);
|
|
3738
3771
|
}
|
|
3739
3772
|
}, 100);
|
|
3740
3773
|
}
|
|
@@ -3846,18 +3879,18 @@ class SlateEditable {
|
|
|
3846
3879
|
}
|
|
3847
3880
|
}
|
|
3848
3881
|
if (isDebug) {
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3882
|
+
debugLog('log', `====== diffVirtualViewport stage: ${stage} ======`);
|
|
3883
|
+
debugLog('log', 'oldIndexesInViewport:', oldIndexesInViewport);
|
|
3884
|
+
debugLog('log', 'newIndexesInViewport:', newIndexesInViewport);
|
|
3885
|
+
debugLog('log', 'changedIndexesOfTop:', needRemoveOnTop ? '-' : needAddOnTop ? '+' : '-', changedIndexesOfTop, changedIndexesOfTop.map(index => getRealHeightByElement(this.editor, this.editor.children[index], 0)));
|
|
3886
|
+
debugLog('log', 'changedIndexesOfBottom:', needAddOnBottom ? '+' : needRemoveOnBottom ? '-' : '+', changedIndexesOfBottom, changedIndexesOfBottom.map(index => getRealHeightByElement(this.editor, this.editor.children[index], 0)));
|
|
3854
3887
|
const needTop = virtualView.heights.slice(0, newIndexesInViewport[0]).reduce((acc, height) => acc + height, 0);
|
|
3855
3888
|
const needBottom = virtualView.heights
|
|
3856
3889
|
.slice(newIndexesInViewport[newIndexesInViewport.length - 1] + 1)
|
|
3857
3890
|
.reduce((acc, height) => acc + height, 0);
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3891
|
+
debugLog('log', needTop - parseFloat(this.virtualTopHeightElement.style.height), 'newTopHeight:', needTop, 'prevTopHeight:', parseFloat(this.virtualTopHeightElement.style.height));
|
|
3892
|
+
debugLog('log', 'newBottomHeight:', needBottom, 'prevBottomHeight:', parseFloat(this.virtualBottomHeightElement.style.height));
|
|
3893
|
+
debugLog('warn', '=========== Dividing line ===========');
|
|
3861
3894
|
}
|
|
3862
3895
|
return {
|
|
3863
3896
|
isDifferent: true,
|
|
@@ -3875,81 +3908,6 @@ class SlateEditable {
|
|
|
3875
3908
|
changedIndexesOfBottom: []
|
|
3876
3909
|
};
|
|
3877
3910
|
}
|
|
3878
|
-
tryMeasureInViewportChildrenHeights() {
|
|
3879
|
-
if (!this.isEnabledVirtualScroll()) {
|
|
3880
|
-
return;
|
|
3881
|
-
}
|
|
3882
|
-
this.tryMeasureInViewportChildrenHeightsAnimId && cancelAnimationFrame(this.tryMeasureInViewportChildrenHeightsAnimId);
|
|
3883
|
-
this.tryMeasureInViewportChildrenHeightsAnimId = requestAnimationFrame(() => {
|
|
3884
|
-
this.measureVisibleHeights();
|
|
3885
|
-
});
|
|
3886
|
-
}
|
|
3887
|
-
measureVisibleHeights() {
|
|
3888
|
-
const children = (this.editor.children || []);
|
|
3889
|
-
const inViewportIndics = [...this.inViewportIndics];
|
|
3890
|
-
inViewportIndics.forEach(index => {
|
|
3891
|
-
const node = children[index];
|
|
3892
|
-
if (!node) {
|
|
3893
|
-
return;
|
|
3894
|
-
}
|
|
3895
|
-
const key = AngularEditor.findKey(this.editor, node);
|
|
3896
|
-
// 跳过已测过的块,除非强制测量
|
|
3897
|
-
if (this.keyHeightMap.has(key.id)) {
|
|
3898
|
-
return;
|
|
3899
|
-
}
|
|
3900
|
-
const view = ELEMENT_TO_COMPONENT.get(node);
|
|
3901
|
-
if (!view) {
|
|
3902
|
-
return;
|
|
3903
|
-
}
|
|
3904
|
-
const ret = view.getRealHeight();
|
|
3905
|
-
if (ret instanceof Promise) {
|
|
3906
|
-
ret.then(height => {
|
|
3907
|
-
this.keyHeightMap.set(key.id, height);
|
|
3908
|
-
});
|
|
3909
|
-
}
|
|
3910
|
-
else {
|
|
3911
|
-
this.keyHeightMap.set(key.id, ret);
|
|
3912
|
-
}
|
|
3913
|
-
});
|
|
3914
|
-
}
|
|
3915
|
-
remeasureHeightByIndics(indics) {
|
|
3916
|
-
const children = (this.editor.children || []);
|
|
3917
|
-
let isHeightChanged = false;
|
|
3918
|
-
indics.forEach((index, i) => {
|
|
3919
|
-
const node = children[index];
|
|
3920
|
-
if (!node) {
|
|
3921
|
-
return;
|
|
3922
|
-
}
|
|
3923
|
-
const key = AngularEditor.findKey(this.editor, node);
|
|
3924
|
-
const view = ELEMENT_TO_COMPONENT.get(node);
|
|
3925
|
-
if (!view) {
|
|
3926
|
-
return;
|
|
3927
|
-
}
|
|
3928
|
-
const prevHeight = this.keyHeightMap.get(key.id);
|
|
3929
|
-
const ret = view.getRealHeight();
|
|
3930
|
-
if (ret instanceof Promise) {
|
|
3931
|
-
ret.then(height => {
|
|
3932
|
-
this.keyHeightMap.set(key.id, height);
|
|
3933
|
-
if (height !== prevHeight) {
|
|
3934
|
-
isHeightChanged = true;
|
|
3935
|
-
if (isDebug) {
|
|
3936
|
-
this.debugLog('log', `remeasure element height, index: ${index} prevHeight: ${prevHeight} newHeight: ${height}`);
|
|
3937
|
-
}
|
|
3938
|
-
}
|
|
3939
|
-
});
|
|
3940
|
-
}
|
|
3941
|
-
else {
|
|
3942
|
-
this.keyHeightMap.set(key.id, ret);
|
|
3943
|
-
if (ret !== prevHeight) {
|
|
3944
|
-
isHeightChanged = true;
|
|
3945
|
-
if (isDebug) {
|
|
3946
|
-
this.debugLog('log', `remeasure element height, index: ${index} prevHeight: ${prevHeight} newHeight: ${ret}`);
|
|
3947
|
-
}
|
|
3948
|
-
}
|
|
3949
|
-
}
|
|
3950
|
-
});
|
|
3951
|
-
return isHeightChanged;
|
|
3952
|
-
}
|
|
3953
3911
|
//#region event proxy
|
|
3954
3912
|
addEventListener(eventName, listener, target = this.elementRef.nativeElement) {
|
|
3955
3913
|
this.manualListeners.push(this.renderer2.listen(target, eventName, (event) => {
|
|
@@ -5182,5 +5140,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
5182
5140
|
* Generated bundle index. Do not edit.
|
|
5183
5141
|
*/
|
|
5184
5142
|
|
|
5185
|
-
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_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, check, completeTable, createClipboardData, createText, createThrottleRAF, 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, isDecoratorRangeListEqual, isFlavourType, isInvalidTable, isTemplateRef, isValid, normalize, scrollToElement, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
|
|
5143
|
+
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_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, 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 };
|
|
5186
5144
|
//# sourceMappingURL=slate-angular.mjs.map
|