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.
@@ -955,179 +955,709 @@ const fallbackCopyText = async (text) => {
955
955
  });
956
956
  };
957
957
 
958
- const ELEMENT_KEY_TO_HEIGHTS = new WeakMap();
959
- const EDITOR_TO_BUSINESS_TOP = new WeakMap();
960
- const getBusinessTop = (editor) => {
961
- return EDITOR_TO_BUSINESS_TOP.get(editor) ?? 0;
962
- };
963
- const getRealHeightByElement = (editor, element, defaultHeight = VIRTUAL_SCROLL_DEFAULT_BLOCK_HEIGHT) => {
964
- const isVisible = editor.isVisible(element);
965
- if (!isVisible) {
966
- return 0;
967
- }
968
- if (!element) {
969
- return defaultHeight;
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
- return { heights, accumulatedHeights };
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
- const anchorIndex = children.findIndex(item => item === element);
1000
- if (anchorIndex < 0) {
1001
- return;
974
+ static syncScrollTop(doc, value) {
975
+ const instance = this.getInstance(doc);
976
+ instance.setScrollTopValue(value);
1002
977
  }
1003
- const { accumulatedHeights } = buildHeightsAndAccumulatedHeights(editor);
1004
- scrollTo((accumulatedHeights[anchorIndex] ?? 0) + getBusinessTop(editor));
1005
- };
1006
-
1007
- const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1008
- let e = editor;
1009
- let { apply } = e;
1010
- e = withDOM(e, clipboardFormatKey);
1011
- e.setFragmentData = (dataTransfer, originEvent) => {
1012
- const { selection } = e;
1013
- if (!selection) {
1014
- return;
1015
- }
1016
- const [start, end] = Range.edges(selection);
1017
- const startVoid = Editor.void(e, { at: start.path });
1018
- const endVoid = Editor.void(e, { at: end.path });
1019
- if (Range.isCollapsed(selection) && !startVoid) {
1020
- return;
1021
- }
1022
- // Create a fake selection so that we can add a Base64-encoded copy of the
1023
- // fragment to the HTML, to decode on future pastes.
1024
- let domRange;
1025
- if (AngularEditor.isEnabledVirtualScroll(e)) {
1026
- const virtualScrollSelection = EDITOR_TO_VIRTUAL_SCROLL_SELECTION.get(e);
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
- domRange = domRange ?? AngularEditor.toDOMRange(e, selection);
1032
- let contents = domRange.cloneContents();
1033
- let attach = contents.childNodes[0];
1034
- // Make sure attach is non-empty, since empty nodes will not get copied.
1035
- const contentsArray = Array.from(contents.children);
1036
- contentsArray.forEach(node => {
1037
- if (node.textContent && node.textContent.trim() !== '') {
1038
- attach = node;
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
- // COMPAT: If the end node is a void node, we need to move the end of the
1042
- // range from the void node's spacer span, to the end of the void node's
1043
- // content, since the spacer is before void's content in the DOM.
1044
- if (endVoid) {
1045
- const [voidNode] = endVoid;
1046
- const r = domRange.cloneRange();
1047
- const domNode = AngularEditor.toDOMNode(e, voidNode);
1048
- r.setEndAfter(domNode);
1049
- contents = r.cloneContents();
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
- else {
1098
- const node = Node.parent(editor, selection.anchor.path);
1099
- if (Element.isElement(node) && Editor.isVoid(editor, node)) {
1100
- Transforms.delete(editor);
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
- e.insertData = async (data) => {
1106
- if (!(await e.customInsertFragmentData(data, null))) {
1107
- e.insertTextData(data);
1054
+ else {
1055
+ this.applyState();
1108
1056
  }
1109
- };
1110
- e.customInsertFragmentData = async (data, contextClipboardData) => {
1111
- /**
1112
- * Checking copied fragment from application/x-slate-fragment or data-slate-fragment
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
- return false;
1120
- };
1121
- e.customInsertTextData = async (data) => {
1122
- const clipboardData = await getClipboardData(data);
1123
- if (clipboardData && clipboardData.text) {
1124
- const lines = clipboardData.text.split(/\r\n|\r|\n/);
1125
- let split = false;
1126
- for (const line of lines) {
1127
- if (split) {
1128
- Transforms.splitNodes(e, { always: true });
1129
- }
1130
- e.insertText(line);
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 DefaultTextFlavour extends BaseTextFlavour {
2321
- render() {
2322
- const { nativeElement } = createText(this.text.text);
2323
- this.nativeElement = nativeElement;
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 { nativeElement } = createText(this.text.text);
2330
- this.nativeElement = nativeElement;
2331
- this.nativeElement.setAttribute('data-slate-spacer', 'true');
2332
- this.nativeElement.classList.add('slate-spacer');
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 createText = (text) => {
2337
- const nativeElement = document.createElement('span');
2338
- nativeElement.setAttribute('data-slate-node', 'text');
2339
- return { nativeElement };
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 ListRender {
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
- else {
2557
- const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
2558
- const isLeafBlock = AngularEditor.isLeafBlock(viewContext.editor, childrenContext.parent);
2559
- const textContext = {
2560
- decorations: computedContext.decorations,
2561
- isLast: isLeafBlock && index === childrenContext.parent.children.length - 1,
2562
- parent: childrenContext.parent,
2563
- text: item
2564
- };
2565
- return textContext;
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
- function getCommonContext(index, item, parentPath, viewContext, childrenContext) {
2569
- const p = parentPath.concat(index);
2570
- try {
2571
- const ds = childrenContext.decorate([item, p]);
2572
- // [list-render] performance optimization: reduce the number of calls to the `Editor.range(viewContext.editor, p)` method
2573
- if (childrenContext.selection || childrenContext.decorations.length > 0) {
2574
- const range = Editor.range(viewContext.editor, p);
2575
- const sel = childrenContext.selection && Range.intersection(range, childrenContext.selection);
2576
- for (const dec of childrenContext.decorations) {
2577
- const d = Range.intersection(dec, range);
2578
- if (d) {
2579
- ds.push(d);
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
- return { selection: sel, decorations: ds };
2583
- }
2584
- else {
2585
- return { selection: null, decorations: ds };
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
- catch (error) {
2589
- viewContext.editor.onError({
2590
- code: SlateErrorCode.GetStartPointError,
2591
- nativeError: error
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 { selection: null, decorations: [] };
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
- else {
2601
- const isVoid = viewContext.editor.isVoid(parent);
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 createBlockCard(item, view, viewContext) {
2606
- const isBlockCard = viewContext.editor.isBlockCard(item);
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 trackBy(viewContext) {
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 viewContext.trackBy(node) || AngularEditor.findKey(viewContext.editor, node);
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 VirtualScrollDebugOverlay {
2663
- static { this.storageKey = 'slate_virtual_scroll_debug_overlay_state'; }
2664
- static { this.minWidth = 320; }
2665
- static { this.minHeight = 240; }
2666
- static { this.defaultWidth = 410; }
2667
- static { this.defaultHeight = 480; }
2668
- static getInstance(doc) {
2669
- if (!this.instance) {
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
- init() {
2755
- if (!this.container) {
2756
- this.createContainer();
2757
- }
2758
- else {
2759
- this.applyState();
2760
- }
2818
+ get text() {
2819
+ return this._context && this._context.text;
2761
2820
  }
2762
- log(type, ...args) {
2763
- this.init();
2764
- if (type === 'warn') {
2765
- this.originalConsoleWarn(...args);
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
- else {
2768
- this.originalConsoleLog(...args);
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.appendLog(type, ...args);
2844
+ this.rerender();
2845
+ this.updateWeakMap();
2846
+ this.leavesRender.update(this.context);
2771
2847
  }
2772
- dispose() {
2773
- this.container?.remove();
2774
- this.container = undefined;
2775
- this.contentWrapper = undefined;
2776
- this.bubble = undefined;
2777
- this.logList = undefined;
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
- createContainer() {
2790
- this.loadState();
2791
- const doc = this.doc;
2792
- const container = doc.createElement('div');
2793
- container.style.position = 'fixed';
2794
- container.style.right = 'auto';
2795
- container.style.bottom = 'auto';
2796
- container.style.boxSizing = 'border-box';
2797
- container.style.background = 'rgba(17, 24, 39, 0.95)';
2798
- container.style.color = '#e5e7eb';
2799
- container.style.fontSize = '12px';
2800
- container.style.border = '1px solid #1f2937';
2801
- container.style.borderRadius = '10px';
2802
- container.style.fontFamily = 'Menlo, Consolas, monospace';
2803
- container.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.35)';
2804
- container.style.zIndex = '9999';
2805
- container.style.display = 'flex';
2806
- container.style.flexDirection = 'column';
2807
- container.style.gap = '10px';
2808
- container.style.minWidth = `${VirtualScrollDebugOverlay.minWidth}px`;
2809
- container.style.minHeight = `${VirtualScrollDebugOverlay.minHeight}px`;
2810
- container.style.maxHeight = '80vh';
2811
- container.style.cursor = 'default';
2812
- container.addEventListener('mousedown', event => {
2813
- if (this.state.collapsed) {
2814
- this.startDrag(event);
2815
- }
2816
- });
2817
- const header = doc.createElement('div');
2818
- header.style.display = 'flex';
2819
- header.style.alignItems = 'center';
2820
- header.style.justifyContent = 'space-between';
2821
- header.style.cursor = 'move';
2822
- header.addEventListener('mousedown', event => {
2823
- this.startDrag(event);
2824
- });
2825
- const title = doc.createElement('div');
2826
- title.textContent = 'Virtual Scroll Debug';
2827
- title.style.fontWeight = '600';
2828
- title.style.letterSpacing = '0.3px';
2829
- const actions = doc.createElement('div');
2830
- actions.style.display = 'flex';
2831
- actions.style.gap = '6px';
2832
- const collapseButton = doc.createElement('button');
2833
- collapseButton.type = 'button';
2834
- collapseButton.textContent = '折叠';
2835
- collapseButton.style.background = '#1f2937';
2836
- collapseButton.style.color = '#e5e7eb';
2837
- collapseButton.style.border = '1px solid #374151';
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
- container.appendChild(resizeHandle);
2974
- doc.body.appendChild(container);
2975
- this.container = container;
2976
- this.contentWrapper = contentWrapper;
2977
- this.bubble = bubble;
2978
- this.logList = logList;
2979
- this.selectorInput = selectorInput;
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
- startDrag(event) {
2986
- if (event.button !== 0) {
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.container) {
2990
- return;
2918
+ if (!this.differ) {
2919
+ throw new Error('Exception: Can not find differ ');
2991
2920
  }
2992
- const rect = this.container.getBoundingClientRect();
2993
- this.isDragging = true;
2994
- this.wasDragged = false;
2995
- this.dragMoved = false;
2996
- this.dragOffsetX = event.clientX - rect.left;
2997
- this.dragOffsetY = event.clientY - rect.top;
2998
- this.container.style.transition = 'none';
2999
- this.doc.addEventListener('mousemove', this.onDragging);
3000
- this.doc.addEventListener('mouseup', this.onDragEnd);
3001
- if (!this.state.collapsed) {
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
- startResize(event) {
3006
- if (event.button !== 0 || this.state.collapsed) {
3007
- return;
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
- if (!this.container) {
3010
- return;
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
- const rect = this.container.getBoundingClientRect();
3013
- this.isResizing = true;
3014
- this.resizeStartX = event.clientX;
3015
- this.resizeStartY = event.clientY;
3016
- this.resizeStartWidth = rect.width;
3017
- this.resizeStartHeight = rect.height;
3018
- this.doc.addEventListener('mousemove', this.onResizing);
3019
- this.doc.addEventListener('mouseup', this.onResizeEnd);
3020
- event.preventDefault();
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
- applySize() {
3031
- if (!this.container) {
3032
- return;
3033
- }
3034
- const width = Math.max(VirtualScrollDebugOverlay.minWidth, this.state.width || VirtualScrollDebugOverlay.defaultWidth);
3035
- const height = Math.max(VirtualScrollDebugOverlay.minHeight, this.state.height || VirtualScrollDebugOverlay.defaultHeight);
3036
- this.state.width = width;
3037
- this.state.height = height;
3038
- this.container.style.width = `${width}px`;
3039
- this.container.style.height = `${height}px`;
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
- applyCollapsedState() {
3042
- if (!this.container || !this.contentWrapper || !this.bubble || !this.collapseToggle) {
3043
- return;
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 (this.state.collapsed) {
3046
- this.container.style.width = '36px';
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
- else {
3063
- this.applySize();
3064
- this.container.style.padding = '12px';
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
- setCollapsed(collapsed) {
3077
- this.state.collapsed = collapsed;
3078
- this.applyCollapsedState();
3079
- this.persistState();
3080
- }
3081
- applyState() {
3082
- this.applyPosition();
3083
- this.applyCollapsedState();
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
- loadState() {
3086
- try {
3087
- const raw = this.doc.defaultView?.localStorage?.getItem(VirtualScrollDebugOverlay.storageKey);
3088
- if (raw) {
3089
- const parsed = JSON.parse(raw);
3090
- if (typeof parsed.left === 'number') {
3091
- this.state.left = parsed.left;
3092
- }
3093
- if (typeof parsed.top === 'number') {
3094
- this.state.top = parsed.top;
3095
- }
3096
- if (typeof parsed.collapsed === 'boolean') {
3097
- this.state.collapsed = parsed.collapsed;
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
- catch {
3108
- // ignore storage errors
3114
+ else {
3115
+ return { selection: null, decorations: ds };
3109
3116
  }
3110
3117
  }
3111
- persistState() {
3112
- try {
3113
- this.doc.defaultView?.localStorage?.setItem(VirtualScrollDebugOverlay.storageKey, JSON.stringify(this.state));
3114
- }
3115
- catch {
3116
- // ignore storage errors
3117
- }
3118
+ catch (error) {
3119
+ viewContext.editor.onError({
3120
+ code: SlateErrorCode.GetStartPointError,
3121
+ nativeError: error
3122
+ });
3123
+ return { selection: null, decorations: [] };
3118
3124
  }
3119
- appendLog(type, ...args) {
3120
- if (!this.logList) {
3121
- return;
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
- formatValue(value) {
3142
- if (typeof value === 'string') {
3143
- return value;
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
- setScrollTopValue(value) {
3153
- if (this.distanceInput) {
3154
- this.distanceInput.value = String(value ?? 0);
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
- this.debugLog('log', 'virtualScrollConfig scrollTop:', config.scrollTop);
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
- this.debugLog('log', `selection is not in visible range, selection: ${JSON.stringify(selection)}, intersectedSelection: ${JSON.stringify(intersectedSelection)}`);
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.remeasureHeightByIndics(remeasureIndics);
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.remeasureHeightByIndics(remeasureIndics);
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
- this.debugLog('log', 'tryUpdateVirtualViewport');
3675
+ debugLog('log', 'tryUpdateVirtualViewport');
3654
3676
  }
3655
3677
  this.tryUpdateVirtualViewportAnimId && cancelAnimationFrame(this.tryUpdateVirtualViewportAnimId);
3656
3678
  this.tryUpdateVirtualViewportAnimId = requestAnimationFrame(() => {
3657
3679
  if (isDebug) {
3658
- this.debugLog('log', 'tryUpdateVirtualViewport Anim start');
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
- this.debugLog('log', 'update top height: ', virtualView.top - topHeight, 'start index', this.inViewportIndics[0]);
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
- this.debugLog('log', 'tryUpdateVirtualViewport Anim end');
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
- this.debugLog('log', 'businessTop', businessTop);
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
- this.debugLog('log', `====== diffVirtualViewport stage: ${stage} ======`);
3850
- this.debugLog('log', 'oldIndexesInViewport:', oldIndexesInViewport);
3851
- this.debugLog('log', 'newIndexesInViewport:', newIndexesInViewport);
3852
- this.debugLog('log', 'changedIndexesOfTop:', needRemoveOnTop ? '-' : needAddOnTop ? '+' : '-', changedIndexesOfTop, changedIndexesOfTop.map(index => getRealHeightByElement(this.editor, this.editor.children[index], 0)));
3853
- this.debugLog('log', 'changedIndexesOfBottom:', needAddOnBottom ? '+' : needRemoveOnBottom ? '-' : '+', changedIndexesOfBottom, changedIndexesOfBottom.map(index => getRealHeightByElement(this.editor, this.editor.children[index], 0)));
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
- this.debugLog('log', needTop - parseFloat(this.virtualTopHeightElement.style.height), 'newTopHeight:', needTop, 'prevTopHeight:', parseFloat(this.virtualTopHeightElement.style.height));
3859
- this.debugLog('log', 'newBottomHeight:', needBottom, 'prevBottomHeight:', parseFloat(this.virtualBottomHeightElement.style.height));
3860
- this.debugLog('warn', '=========== Dividing line ===========');
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