@lexical/table 0.48.0 → 0.48.1-nightly.20260720.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LexicalTable.dev.js +311 -113
- package/dist/LexicalTable.dev.mjs +311 -115
- package/dist/LexicalTable.js.flow +5 -6
- package/dist/LexicalTable.mjs +2 -0
- package/dist/LexicalTable.node.mjs +2 -0
- package/dist/LexicalTable.prod.js +1 -1
- package/dist/LexicalTable.prod.mjs +1 -1
- package/dist/LexicalTableCellNode.d.ts +28 -5
- package/dist/LexicalTableExtension.d.ts +13 -0
- package/dist/LexicalTableNode.d.ts +30 -7
- package/dist/LexicalTableRowNode.d.ts +21 -6
- package/dist/LexicalTableSelection.d.ts +12 -0
- package/dist/LexicalTableUtils.d.ts +4 -0
- package/dist/index.d.ts +3 -2
- package/package.json +7 -7
- package/src/LexicalTableCellNode.ts +14 -29
- package/src/LexicalTableExtension.ts +100 -0
- package/src/LexicalTableNode.ts +234 -43
- package/src/LexicalTableRowNode.ts +13 -21
- package/src/LexicalTableSelection.ts +17 -7
- package/src/LexicalTableSelectionHelpers.ts +2 -62
- package/src/LexicalTableUtils.ts +4 -0
- package/src/index.ts +3 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { ElementNode, $getDocument, addClassNamesToElement, isHTMLElement, $isInlineElementOrDecoratorNode, $isTextNode, $isLineBreakNode, $createParagraphNode, $applyNodeReplacement, createCommand, $createTextNode, $getSelection, $isRangeSelection, $findMatchingParent, $isParagraphNode, $createPoint, $getNodeByKey, $isElementNode, $normalizeSelection__EXPERIMENTAL, isCurrentlyReadOnlyMode, TEXT_TYPE_TO_FORMAT, $getEditor, $setSelection, SELECTION_CHANGE_COMMAND, removeClassNamesFromElement, getDOMSelection, $createRangeSelection, $isRootNode, INSERT_PARAGRAPH_COMMAND, registerEventListener, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, COMMAND_PRIORITY_HIGH, KEY_ESCAPE_COMMAND, DELETE_WORD_COMMAND, DELETE_LINE_COMMAND, DELETE_CHARACTER_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, CUT_COMMAND, PASTE_COMMAND, getComposedEventTarget, isDOMNode, getActiveElement, COPY_COMMAND, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, CONTROLLED_TEXT_INSERTION_COMMAND, KEY_TAB_COMMAND, FOCUS_COMMAND, $getNearestNodeFromDOMNode, $isRootOrShadowRoot, getDOMSelectionRange, getDOMSelectionPoints, $getPreviousSelection, $caretFromPoint, $isExtendableTextPointCaret, $extendCaretToRange, $isSiblingCaret, $getSiblingCaret, $setPointFromCaret, $normalizeCaret, $createRangeSelectionFromDom, $isChildCaret, $getChildCaret, $getAdjacentChildCaret, IS_FIREFOX, $getNodeByKeyOrThrow, isDOMDocumentNode, isDOMShadowRoot, setDOMStyleFromCSS, setDOMUnmanaged, mergeRegister, COMMAND_PRIORITY_EDITOR, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, COMMAND_PRIORITY_LOW, CLICK_COMMAND, $getRoot, isHTMLTableRowElement, IS_BOLD, IS_ITALIC, IS_UNDERLINE, IS_STRIKETHROUGH, defineExtension, $fullReconcile, configExtension, safeCast } from 'lexical';
|
|
10
|
-
import { signal, effect, namedSignals } from '@lexical/extension';
|
|
10
|
+
import { getPeerDependencyFromEditor, signal, effect, namedSignals } from '@lexical/extension';
|
|
11
11
|
import { defineImportRule, sel, ImportTextFormat, ImportTextStyle, contextValue, $propagateTextAlignToBlockChildren, CoreImportExtension, DOMImportExtension } from '@lexical/html';
|
|
12
12
|
import { $descendantsMatching, objectKlassEquals, $insertFirst as $insertFirst$1, $insertNodeToNearestRoot, $dfs, $unwrapAndFilterDescendants } from '@lexical/utils';
|
|
13
13
|
import { copyToClipboard, $getClipboardDataFromSelection } from '@lexical/clipboard';
|
|
@@ -54,11 +54,20 @@ class TableCellNode extends ElementNode {
|
|
|
54
54
|
__backgroundColor;
|
|
55
55
|
/** @internal */
|
|
56
56
|
__verticalAlign;
|
|
57
|
-
|
|
58
|
-
return 'tablecell'
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
$config() {
|
|
58
|
+
return this.config('tablecell', {
|
|
59
|
+
extends: ElementNode,
|
|
60
|
+
importDOM: {
|
|
61
|
+
td: () => ({
|
|
62
|
+
conversion: $convertTableCellNodeElement,
|
|
63
|
+
priority: 0
|
|
64
|
+
}),
|
|
65
|
+
th: () => ({
|
|
66
|
+
conversion: $convertTableCellNodeElement,
|
|
67
|
+
priority: 0
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
});
|
|
62
71
|
}
|
|
63
72
|
afterCloneFrom(node) {
|
|
64
73
|
super.afterCloneFrom(node);
|
|
@@ -69,21 +78,6 @@ class TableCellNode extends ElementNode {
|
|
|
69
78
|
this.__headerState = node.__headerState;
|
|
70
79
|
this.__width = node.__width;
|
|
71
80
|
}
|
|
72
|
-
static importDOM() {
|
|
73
|
-
return {
|
|
74
|
-
td: node => ({
|
|
75
|
-
conversion: $convertTableCellNodeElement,
|
|
76
|
-
priority: 0
|
|
77
|
-
}),
|
|
78
|
-
th: node => ({
|
|
79
|
-
conversion: $convertTableCellNodeElement,
|
|
80
|
-
priority: 0
|
|
81
|
-
})
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
static importJSON(serializedNode) {
|
|
85
|
-
return $createTableCellNode().updateFromJSON(serializedNode);
|
|
86
|
-
}
|
|
87
81
|
updateFromJSON(serializedNode) {
|
|
88
82
|
return super.updateFromJSON(serializedNode).setHeaderStyles(serializedNode.headerState).setColSpan(serializedNode.colSpan || 1).setRowSpan(serializedNode.rowSpan || 1).setWidth(serializedNode.width || undefined).setBackgroundColor(serializedNode.backgroundColor || null).setVerticalAlign(serializedNode.verticalAlign || undefined);
|
|
89
83
|
}
|
|
@@ -381,31 +375,28 @@ function formatDevErrorMessage(message) {
|
|
|
381
375
|
class TableRowNode extends ElementNode {
|
|
382
376
|
/** @internal */
|
|
383
377
|
__height;
|
|
384
|
-
|
|
385
|
-
return 'tablerow'
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
378
|
+
$config() {
|
|
379
|
+
return this.config('tablerow', {
|
|
380
|
+
extends: ElementNode,
|
|
381
|
+
importDOM: {
|
|
382
|
+
tr: () => ({
|
|
383
|
+
conversion: $convertTableRowElement,
|
|
384
|
+
priority: 0
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
});
|
|
389
388
|
}
|
|
390
389
|
afterCloneFrom(prevNode) {
|
|
391
390
|
super.afterCloneFrom(prevNode);
|
|
392
391
|
this.__height = prevNode.__height;
|
|
393
392
|
}
|
|
394
|
-
static importDOM() {
|
|
395
|
-
return {
|
|
396
|
-
tr: node => ({
|
|
397
|
-
conversion: $convertTableRowElement,
|
|
398
|
-
priority: 0
|
|
399
|
-
})
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
static importJSON(serializedNode) {
|
|
403
|
-
return $createTableRowNode().updateFromJSON(serializedNode);
|
|
404
|
-
}
|
|
405
393
|
updateFromJSON(serializedNode) {
|
|
406
394
|
return super.updateFromJSON(serializedNode).setHeight(serializedNode.height);
|
|
407
395
|
}
|
|
408
|
-
|
|
396
|
+
|
|
397
|
+
// `height` carries an explicit `undefined` default so the constructor reports
|
|
398
|
+
// zero required arguments and `$config` can synthesize the static `clone`.
|
|
399
|
+
constructor(height = undefined, key) {
|
|
409
400
|
super(key);
|
|
410
401
|
this.__height = height;
|
|
411
402
|
}
|
|
@@ -1389,6 +1380,11 @@ function $computeTableCellRectSpans(map, boundary) {
|
|
|
1389
1380
|
topSpan
|
|
1390
1381
|
};
|
|
1391
1382
|
}
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* Compute the bounding rectangle of two table cells in a table map,
|
|
1386
|
+
* expanding iteratively to include any merged cells that overlap the boundary.
|
|
1387
|
+
*/
|
|
1392
1388
|
function $computeTableCellRectBoundary(map, cellAMap, cellBMap) {
|
|
1393
1389
|
// Initial boundaries based on the anchor and focus cells
|
|
1394
1390
|
let minColumn = Math.min(cellAMap.startColumn, cellBMap.startColumn);
|
|
@@ -1897,7 +1893,7 @@ class TableSelection {
|
|
|
1897
1893
|
selection.insertNodes(nodes);
|
|
1898
1894
|
}
|
|
1899
1895
|
|
|
1900
|
-
|
|
1896
|
+
/** @deprecated Use {@link $computeTableMap} and {@link $computeTableCellRectBoundary} directly. */
|
|
1901
1897
|
getShape() {
|
|
1902
1898
|
const {
|
|
1903
1899
|
anchorCell,
|
|
@@ -2009,19 +2005,28 @@ class TableSelection {
|
|
|
2009
2005
|
return textContent;
|
|
2010
2006
|
}
|
|
2011
2007
|
}
|
|
2008
|
+
|
|
2009
|
+
/** Type guard for {@link TableSelection}. */
|
|
2012
2010
|
function $isTableSelection(x) {
|
|
2013
2011
|
return x instanceof TableSelection;
|
|
2014
2012
|
}
|
|
2013
|
+
|
|
2014
|
+
/** @deprecated Use {@link $createTableSelectionFrom} instead. */
|
|
2015
2015
|
function $createTableSelection() {
|
|
2016
|
-
// TODO this is a suboptimal design, it doesn't make sense to have
|
|
2017
|
-
// a table selection that isn't associated with a table. This
|
|
2018
|
-
// constructor should have required arguments and in __DEV__ we
|
|
2019
|
-
// should check that they point to a table and are element points to
|
|
2020
|
-
// cell nodes of that table.
|
|
2021
2016
|
const anchor = $createPoint('root', 0, 'element');
|
|
2022
2017
|
const focus = $createPoint('root', 0, 'element');
|
|
2023
2018
|
return new TableSelection('root', anchor, focus);
|
|
2024
2019
|
}
|
|
2020
|
+
|
|
2021
|
+
/**
|
|
2022
|
+
* Creates a {@link TableSelection} spanning from `anchorCell` to `focusCell`
|
|
2023
|
+
* within `tableNode`. In `__DEV__` mode, validates that both cells belong to
|
|
2024
|
+
* the given table and that the table is attached to the editor state.
|
|
2025
|
+
*
|
|
2026
|
+
* If the current selection is already a TableSelection, it clones and
|
|
2027
|
+
* re-targets it (preserving identity for dirty-checking); otherwise it
|
|
2028
|
+
* constructs a fresh one.
|
|
2029
|
+
*/
|
|
2025
2030
|
function $createTableSelectionFrom(tableNode, anchorCell, focusCell) {
|
|
2026
2031
|
const tableNodeKey = tableNode.getKey();
|
|
2027
2032
|
const anchorCellKey = anchorCell.getKey();
|
|
@@ -2038,7 +2043,7 @@ function $createTableSelectionFrom(tableNode, anchorCell, focusCell) {
|
|
|
2038
2043
|
} // TODO: Check for rectangular grid
|
|
2039
2044
|
}
|
|
2040
2045
|
const prevSelection = $getSelection();
|
|
2041
|
-
const nextSelection = $isTableSelection(prevSelection) ? prevSelection.clone() : $
|
|
2046
|
+
const nextSelection = $isTableSelection(prevSelection) ? prevSelection.clone() : new TableSelection('root', $createPoint('root', 0, 'element'), $createPoint('root', 0, 'element'));
|
|
2042
2047
|
nextSelection.set(tableNode.getKey(), anchorCell.getKey(), focusCell.getKey());
|
|
2043
2048
|
return nextSelection;
|
|
2044
2049
|
}
|
|
@@ -2897,7 +2902,7 @@ function applyTableHandlers(tableNode, element, editor, hasTabHandler, tableObse
|
|
|
2897
2902
|
}
|
|
2898
2903
|
return false;
|
|
2899
2904
|
}, COMMAND_PRIORITY_HIGH));
|
|
2900
|
-
const deleteTextHandler =
|
|
2905
|
+
const $deleteTextHandler = () => {
|
|
2901
2906
|
const selection = $getSelection();
|
|
2902
2907
|
if (!$isSelectionInTable(selection, tableNode)) {
|
|
2903
2908
|
return false;
|
|
@@ -2905,34 +2910,11 @@ function applyTableHandlers(tableNode, element, editor, hasTabHandler, tableObse
|
|
|
2905
2910
|
if ($isTableSelection(selection)) {
|
|
2906
2911
|
tableObserver.$clearText();
|
|
2907
2912
|
return true;
|
|
2908
|
-
} else if ($isRangeSelection(selection)) {
|
|
2909
|
-
const tableCellNode = $findParentTableCellNodeInTable(tableNode, selection.anchor.getNode());
|
|
2910
|
-
if (!$isTableCellNode(tableCellNode)) {
|
|
2911
|
-
return false;
|
|
2912
|
-
}
|
|
2913
|
-
const anchorNode = selection.anchor.getNode();
|
|
2914
|
-
const focusNode = selection.focus.getNode();
|
|
2915
|
-
const isAnchorInside = tableNode.isParentOf(anchorNode);
|
|
2916
|
-
const isFocusInside = tableNode.isParentOf(focusNode);
|
|
2917
|
-
const selectionContainsPartialTable = isAnchorInside && !isFocusInside || isFocusInside && !isAnchorInside;
|
|
2918
|
-
if (selectionContainsPartialTable) {
|
|
2919
|
-
tableObserver.$clearText();
|
|
2920
|
-
return true;
|
|
2921
|
-
}
|
|
2922
|
-
const nearestElementNode = $findMatchingParent(selection.anchor.getNode(), n => $isElementNode(n));
|
|
2923
|
-
const topLevelCellElementNode = nearestElementNode && $findMatchingParent(nearestElementNode, n => $isElementNode(n) && $isTableCellNode(n.getParent()));
|
|
2924
|
-
if (!$isElementNode(topLevelCellElementNode) || !$isElementNode(nearestElementNode)) {
|
|
2925
|
-
return false;
|
|
2926
|
-
}
|
|
2927
|
-
if (command === DELETE_LINE_COMMAND && topLevelCellElementNode.getPreviousSibling() === null) {
|
|
2928
|
-
// TODO: Fix Delete Line in Table Cells.
|
|
2929
|
-
return true;
|
|
2930
|
-
}
|
|
2931
2913
|
}
|
|
2932
2914
|
return false;
|
|
2933
2915
|
};
|
|
2934
2916
|
for (const command of DELETE_TEXT_COMMANDS) {
|
|
2935
|
-
tableObserver.listenersToRemove.add(editor.registerCommand(command, deleteTextHandler
|
|
2917
|
+
tableObserver.listenersToRemove.add(editor.registerCommand(command, $deleteTextHandler, COMMAND_PRIORITY_HIGH));
|
|
2936
2918
|
}
|
|
2937
2919
|
const $deleteCellHandler = event => {
|
|
2938
2920
|
const selection = $getSelection();
|
|
@@ -3045,11 +3027,6 @@ function applyTableHandlers(tableNode, element, editor, hasTabHandler, tableObse
|
|
|
3045
3027
|
if ($isTableSelection(selection)) {
|
|
3046
3028
|
tableObserver.$formatCells(payload);
|
|
3047
3029
|
return true;
|
|
3048
|
-
} else if ($isRangeSelection(selection)) {
|
|
3049
|
-
const tableCellNode = $findMatchingParent(selection.anchor.getNode(), n => $isTableCellNode(n));
|
|
3050
|
-
if (!$isTableCellNode(tableCellNode)) {
|
|
3051
|
-
return false;
|
|
3052
|
-
}
|
|
3053
3030
|
}
|
|
3054
3031
|
return false;
|
|
3055
3032
|
}, COMMAND_PRIORITY_HIGH));
|
|
@@ -4195,10 +4172,167 @@ function alignTableElement(dom, config, formatType) {
|
|
|
4195
4172
|
removeClassNamesFromElement(dom, ...removeClasses);
|
|
4196
4173
|
addClassNamesToElement(dom, ...addClasses);
|
|
4197
4174
|
}
|
|
4175
|
+
function $createScrollableWrapper(tableElement, config, hideNativeScrollbar) {
|
|
4176
|
+
const wrapper = $getDocument().createElement('div');
|
|
4177
|
+
const classes = config.theme.tableScrollableWrapper;
|
|
4178
|
+
if (classes) {
|
|
4179
|
+
addClassNamesToElement(wrapper, classes);
|
|
4180
|
+
} else {
|
|
4181
|
+
wrapper.style.overflowX = 'auto';
|
|
4182
|
+
}
|
|
4183
|
+
if (hideNativeScrollbar) {
|
|
4184
|
+
wrapper.style.scrollbarWidth = 'none';
|
|
4185
|
+
}
|
|
4186
|
+
wrapper.appendChild(tableElement);
|
|
4187
|
+
return wrapper;
|
|
4188
|
+
}
|
|
4189
|
+
function $createStickyScrollbar(config) {
|
|
4190
|
+
const doc = $getDocument();
|
|
4191
|
+
const scrollbar = doc.createElement('div');
|
|
4192
|
+
const classes = config.theme.tableStickyScrollbar;
|
|
4193
|
+
if (classes) {
|
|
4194
|
+
addClassNamesToElement(scrollbar, classes);
|
|
4195
|
+
} else {
|
|
4196
|
+
scrollbar.style.position = 'sticky';
|
|
4197
|
+
scrollbar.style.bottom = '0';
|
|
4198
|
+
scrollbar.style.overflowX = 'scroll';
|
|
4199
|
+
scrollbar.style.overflowY = 'hidden';
|
|
4200
|
+
}
|
|
4201
|
+
scrollbar.style.display = 'none';
|
|
4202
|
+
scrollbar.setAttribute('aria-hidden', 'true');
|
|
4203
|
+
scrollbar.tabIndex = -1;
|
|
4204
|
+
const spacer = doc.createElement('div');
|
|
4205
|
+
spacer.style.height = '1px';
|
|
4206
|
+
spacer.style.width = '0px';
|
|
4207
|
+
scrollbar.appendChild(spacer);
|
|
4208
|
+
return scrollbar;
|
|
4209
|
+
}
|
|
4210
|
+
// Unthemed sticky scrollbars whose environment cannot render a persistent
|
|
4211
|
+
// proxy scrollbar (overlay scrollbars reserve no height and show no idle
|
|
4212
|
+
// thumb), permanently hidden in favor of the wrapper's native scrollbar.
|
|
4213
|
+
const overlayStickyScrollbars = new WeakSet();
|
|
4214
|
+
function measureScrollbarThickness(scrollbar) {
|
|
4215
|
+
const prevDisplay = scrollbar.style.display;
|
|
4216
|
+
scrollbar.style.display = '';
|
|
4217
|
+
const thickness = scrollbar.offsetHeight - scrollbar.clientHeight;
|
|
4218
|
+
scrollbar.style.display = prevDisplay;
|
|
4219
|
+
return thickness;
|
|
4220
|
+
}
|
|
4221
|
+
function attachStickyScrollbarListeners(elements) {
|
|
4222
|
+
const {
|
|
4223
|
+
scrollable,
|
|
4224
|
+
scrollbar,
|
|
4225
|
+
tableElement
|
|
4226
|
+
} = elements;
|
|
4227
|
+
// A themed scrollbar (theme.tableStickyScrollbar, detectable by its
|
|
4228
|
+
// classes) is the integrator's responsibility to keep visible (e.g. via
|
|
4229
|
+
// ::-webkit-scrollbar height or scrollbar-width). The unthemed fallback
|
|
4230
|
+
// relies on classic native scrollbars for its height, so where the
|
|
4231
|
+
// environment renders overlay scrollbars (no reserved thickness — e.g.
|
|
4232
|
+
// macOS "show scrollbars when scrolling", or non-layout environments like
|
|
4233
|
+
// jsdom) the proxy would be an invisible strip: keep it hidden and
|
|
4234
|
+
// restore the wrapper's native scrollbar instead of presenting no scroll
|
|
4235
|
+
// affordance at all.
|
|
4236
|
+
if (scrollbar.classList.length === 0 && measureScrollbarThickness(scrollbar) === 0) {
|
|
4237
|
+
overlayStickyScrollbars.add(scrollbar);
|
|
4238
|
+
scrollbar.style.display = 'none';
|
|
4239
|
+
scrollable.style.scrollbarWidth = 'auto';
|
|
4240
|
+
return () => {};
|
|
4241
|
+
}
|
|
4242
|
+
const onWrapperScroll = () => {
|
|
4243
|
+
if (scrollbar.scrollLeft !== scrollable.scrollLeft) {
|
|
4244
|
+
scrollbar.scrollLeft = scrollable.scrollLeft;
|
|
4245
|
+
}
|
|
4246
|
+
};
|
|
4247
|
+
const onScrollbarScroll = () => {
|
|
4248
|
+
if (scrollable.scrollLeft !== scrollbar.scrollLeft) {
|
|
4249
|
+
scrollable.scrollLeft = scrollbar.scrollLeft;
|
|
4250
|
+
}
|
|
4251
|
+
};
|
|
4252
|
+
scrollable.addEventListener('scroll', onWrapperScroll, {
|
|
4253
|
+
passive: true
|
|
4254
|
+
});
|
|
4255
|
+
scrollbar.addEventListener('scroll', onScrollbarScroll, {
|
|
4256
|
+
passive: true
|
|
4257
|
+
});
|
|
4258
|
+
let resizeObserver = null;
|
|
4259
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
4260
|
+
resizeObserver = new ResizeObserver(() => {
|
|
4261
|
+
syncStickyScrollbar(scrollable, scrollbar);
|
|
4262
|
+
});
|
|
4263
|
+
resizeObserver.observe(scrollable);
|
|
4264
|
+
resizeObserver.observe(tableElement);
|
|
4265
|
+
}
|
|
4266
|
+
const cleanup = () => {
|
|
4267
|
+
scrollable.removeEventListener('scroll', onWrapperScroll);
|
|
4268
|
+
scrollbar.removeEventListener('scroll', onScrollbarScroll);
|
|
4269
|
+
if (resizeObserver) {
|
|
4270
|
+
resizeObserver.disconnect();
|
|
4271
|
+
}
|
|
4272
|
+
};
|
|
4273
|
+
syncStickyScrollbar(scrollable, scrollbar);
|
|
4274
|
+
return cleanup;
|
|
4275
|
+
}
|
|
4276
|
+
function syncStickyScrollbar(scrollable, scrollbar) {
|
|
4277
|
+
if (overlayStickyScrollbars.has(scrollbar)) {
|
|
4278
|
+
return;
|
|
4279
|
+
}
|
|
4280
|
+
const spacer = scrollbar.firstElementChild;
|
|
4281
|
+
if (!spacer || !isHTMLElement(spacer) || !scrollable.isConnected) {
|
|
4282
|
+
return;
|
|
4283
|
+
}
|
|
4284
|
+
const view = scrollable.ownerDocument.defaultView;
|
|
4285
|
+
if (!view) {
|
|
4286
|
+
scrollbar.style.display = 'none';
|
|
4287
|
+
return;
|
|
4288
|
+
}
|
|
4289
|
+
// All layout reads happen before any write so a sync forces at most one
|
|
4290
|
+
// reflow, and both metrics come from the same element so their rounding
|
|
4291
|
+
// can't disagree at fractional zoom levels.
|
|
4292
|
+
const overflowX = view.getComputedStyle(scrollable).overflowX;
|
|
4293
|
+
const isScrollable = overflowX === 'auto' || overflowX === 'scroll';
|
|
4294
|
+
const scrollWidth = scrollable.scrollWidth;
|
|
4295
|
+
const clientWidth = scrollable.clientWidth;
|
|
4296
|
+
const spacerWidth = scrollWidth + 'px';
|
|
4297
|
+
if (spacer.style.width !== spacerWidth) {
|
|
4298
|
+
spacer.style.width = spacerWidth;
|
|
4299
|
+
}
|
|
4300
|
+
const hasOverflow = isScrollable && scrollWidth > clientWidth;
|
|
4301
|
+
scrollbar.style.display = hasOverflow ? '' : 'none';
|
|
4302
|
+
}
|
|
4303
|
+
function findStickyScrollbarElements(dom) {
|
|
4304
|
+
if (!dom.hasAttribute('data-lexical-sticky-scrollbar')) {
|
|
4305
|
+
return null;
|
|
4306
|
+
}
|
|
4307
|
+
const firstChild = dom.firstElementChild;
|
|
4308
|
+
if (!isHTMLDivElement(firstChild)) {
|
|
4309
|
+
return null;
|
|
4310
|
+
}
|
|
4311
|
+
const tableElement = firstChild.querySelector(':scope > table');
|
|
4312
|
+
if (!isHTMLTableElement(tableElement)) {
|
|
4313
|
+
return null;
|
|
4314
|
+
}
|
|
4315
|
+
const scrollbar = firstChild.nextElementSibling;
|
|
4316
|
+
if (!isHTMLDivElement(scrollbar)) {
|
|
4317
|
+
return null;
|
|
4318
|
+
}
|
|
4319
|
+
return {
|
|
4320
|
+
scrollable: firstChild,
|
|
4321
|
+
scrollbar,
|
|
4322
|
+
tableElement
|
|
4323
|
+
};
|
|
4324
|
+
}
|
|
4198
4325
|
const scrollableEditors = new WeakSet();
|
|
4199
4326
|
function $isScrollableTablesActive(editor = $getEditor()) {
|
|
4200
4327
|
return scrollableEditors.has(editor);
|
|
4201
4328
|
}
|
|
4329
|
+
function $isStickyScrollbarActive(editor = $getEditor()) {
|
|
4330
|
+
const dep = getPeerDependencyFromEditor(editor, '@lexical/table/Table');
|
|
4331
|
+
// peek() so a reconcile that runs inside a signals effect (e.g. via a
|
|
4332
|
+
// discrete update or force-commit read) does not subscribe that effect to
|
|
4333
|
+
// the table config; re-rendering on change is the TableExtension's job.
|
|
4334
|
+
return dep ? dep.output.hasStickyScrollbar.peek() && dep.output.hasHorizontalScroll.peek() : false;
|
|
4335
|
+
}
|
|
4202
4336
|
function setScrollableTablesActive(editor, active) {
|
|
4203
4337
|
if (active) {
|
|
4204
4338
|
if (!editor._config.theme.tableScrollableWrapper) {
|
|
@@ -4213,12 +4347,24 @@ function setScrollableTablesActive(editor, active) {
|
|
|
4213
4347
|
/** @noInheritDoc */
|
|
4214
4348
|
class TableNode extends ElementNode {
|
|
4215
4349
|
/** @internal */
|
|
4216
|
-
__rowStriping;
|
|
4217
|
-
__frozenColumnCount;
|
|
4218
|
-
__frozenRowCount;
|
|
4219
|
-
__colWidths
|
|
4220
|
-
|
|
4221
|
-
|
|
4350
|
+
__rowStriping = false;
|
|
4351
|
+
__frozenColumnCount = 0;
|
|
4352
|
+
__frozenRowCount = 0;
|
|
4353
|
+
// Initialized unconditionally (not `__colWidths?: ...`) so a freshly
|
|
4354
|
+
// constructed instance always has the own property — `@lexical/yjs` derives a
|
|
4355
|
+
// node's syncable properties from `Object.keys(new Klass())`, so an
|
|
4356
|
+
// uninitialized optional field would silently drop out of collab sync.
|
|
4357
|
+
__colWidths = undefined;
|
|
4358
|
+
$config() {
|
|
4359
|
+
return this.config('table', {
|
|
4360
|
+
extends: ElementNode,
|
|
4361
|
+
importDOM: {
|
|
4362
|
+
table: () => ({
|
|
4363
|
+
conversion: $convertTableElement,
|
|
4364
|
+
priority: 1
|
|
4365
|
+
})
|
|
4366
|
+
}
|
|
4367
|
+
});
|
|
4222
4368
|
}
|
|
4223
4369
|
getColWidths() {
|
|
4224
4370
|
const self = this.getLatest();
|
|
@@ -4230,9 +4376,6 @@ class TableNode extends ElementNode {
|
|
|
4230
4376
|
self.__colWidths = colWidths !== undefined && __DEV__ ? Object.freeze(colWidths) : colWidths;
|
|
4231
4377
|
return self;
|
|
4232
4378
|
}
|
|
4233
|
-
static clone(node) {
|
|
4234
|
-
return new TableNode(node.__key);
|
|
4235
|
-
}
|
|
4236
4379
|
afterCloneFrom(prevNode) {
|
|
4237
4380
|
super.afterCloneFrom(prevNode);
|
|
4238
4381
|
this.__colWidths = prevNode.__colWidths;
|
|
@@ -4240,27 +4383,9 @@ class TableNode extends ElementNode {
|
|
|
4240
4383
|
this.__frozenColumnCount = prevNode.__frozenColumnCount;
|
|
4241
4384
|
this.__frozenRowCount = prevNode.__frozenRowCount;
|
|
4242
4385
|
}
|
|
4243
|
-
static importDOM() {
|
|
4244
|
-
return {
|
|
4245
|
-
table: _node => ({
|
|
4246
|
-
conversion: $convertTableElement,
|
|
4247
|
-
priority: 1
|
|
4248
|
-
})
|
|
4249
|
-
};
|
|
4250
|
-
}
|
|
4251
|
-
static importJSON(serializedNode) {
|
|
4252
|
-
return $createTableNode().updateFromJSON(serializedNode);
|
|
4253
|
-
}
|
|
4254
4386
|
updateFromJSON(serializedNode) {
|
|
4255
4387
|
return super.updateFromJSON(serializedNode).setRowStriping(serializedNode.rowStriping || false).setFrozenColumns(serializedNode.frozenColumnCount || 0).setFrozenRows(serializedNode.frozenRowCount || 0).setColWidths(serializedNode.colWidths);
|
|
4256
4388
|
}
|
|
4257
|
-
constructor(key) {
|
|
4258
|
-
super(key);
|
|
4259
|
-
this.__rowStriping = false;
|
|
4260
|
-
this.__frozenColumnCount = 0;
|
|
4261
|
-
this.__frozenRowCount = 0;
|
|
4262
|
-
this.__colWidths = undefined;
|
|
4263
|
-
}
|
|
4264
4389
|
exportJSON() {
|
|
4265
4390
|
return {
|
|
4266
4391
|
...super.exportJSON(),
|
|
@@ -4291,16 +4416,19 @@ class TableNode extends ElementNode {
|
|
|
4291
4416
|
addClassNamesToElement(tableElement, config.theme.table);
|
|
4292
4417
|
this.updateTableElement(null, tableElement, config);
|
|
4293
4418
|
if ($isScrollableTablesActive(editor)) {
|
|
4294
|
-
const
|
|
4295
|
-
const
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4419
|
+
const hasStickyScrollbar = $isStickyScrollbarActive(editor);
|
|
4420
|
+
const scrollableWrapper = $createScrollableWrapper(tableElement, config, hasStickyScrollbar);
|
|
4421
|
+
this.updateTableWrapper(null, scrollableWrapper, tableElement, config);
|
|
4422
|
+
if (hasStickyScrollbar) {
|
|
4423
|
+
const stickyScrollbar = $createStickyScrollbar(config);
|
|
4424
|
+
const outerWrapper = $getDocument().createElement('div');
|
|
4425
|
+
outerWrapper.setAttribute('data-lexical-sticky-scrollbar', 'true');
|
|
4426
|
+
outerWrapper.appendChild(scrollableWrapper);
|
|
4427
|
+
outerWrapper.appendChild(stickyScrollbar);
|
|
4428
|
+
setDOMUnmanaged(stickyScrollbar);
|
|
4429
|
+
return outerWrapper;
|
|
4430
|
+
}
|
|
4431
|
+
return scrollableWrapper;
|
|
4304
4432
|
}
|
|
4305
4433
|
return tableElement;
|
|
4306
4434
|
}
|
|
@@ -4332,7 +4460,16 @@ class TableNode extends ElementNode {
|
|
|
4332
4460
|
return true;
|
|
4333
4461
|
}
|
|
4334
4462
|
if (isHTMLDivElement(dom)) {
|
|
4335
|
-
|
|
4463
|
+
const hasStickyDom = dom.hasAttribute('data-lexical-sticky-scrollbar');
|
|
4464
|
+
if (hasStickyDom !== $isStickyScrollbarActive()) {
|
|
4465
|
+
return true;
|
|
4466
|
+
}
|
|
4467
|
+
// The scrollable wrapper is the table's immediate parent in both
|
|
4468
|
+
// layouts (the inner div in sticky mode, dom itself otherwise).
|
|
4469
|
+
const scrollable = tableElement.parentElement;
|
|
4470
|
+
if (isHTMLDivElement(scrollable)) {
|
|
4471
|
+
this.updateTableWrapper(prevNode, scrollable, tableElement, config);
|
|
4472
|
+
}
|
|
4336
4473
|
}
|
|
4337
4474
|
this.updateTableElement(prevNode, tableElement, config);
|
|
4338
4475
|
return false;
|
|
@@ -5155,6 +5292,51 @@ const TableImportRules = [TableRule, TableRowRule, TableCellRule];
|
|
|
5155
5292
|
*
|
|
5156
5293
|
*/
|
|
5157
5294
|
|
|
5295
|
+
function registerStickyScrollbar(editor) {
|
|
5296
|
+
const attached = new Map();
|
|
5297
|
+
const detachAll = () => {
|
|
5298
|
+
for (const {
|
|
5299
|
+
cleanup
|
|
5300
|
+
} of attached.values()) {
|
|
5301
|
+
cleanup();
|
|
5302
|
+
}
|
|
5303
|
+
attached.clear();
|
|
5304
|
+
};
|
|
5305
|
+
return mergeRegister(detachAll, editor.registerMutationListener(TableNode, nodeMutations => {
|
|
5306
|
+
for (const [nodeKey, mutation] of nodeMutations) {
|
|
5307
|
+
const prev = attached.get(nodeKey);
|
|
5308
|
+
if (mutation === 'destroyed') {
|
|
5309
|
+
if (prev) {
|
|
5310
|
+
prev.cleanup();
|
|
5311
|
+
attached.delete(nodeKey);
|
|
5312
|
+
}
|
|
5313
|
+
continue;
|
|
5314
|
+
}
|
|
5315
|
+
const dom = editor.getElementByKey(nodeKey);
|
|
5316
|
+
const parts = dom && isHTMLElement(dom) ? findStickyScrollbarElements(dom) : null;
|
|
5317
|
+
if (prev && parts && prev.parts.scrollable === parts.scrollable && prev.parts.scrollbar === parts.scrollbar && prev.parts.tableElement === parts.tableElement) {
|
|
5318
|
+
// Same DOM: keep the listeners, but resync since the
|
|
5319
|
+
// update may still change scrollability (e.g. a frozen
|
|
5320
|
+
// rows toggle switches the wrapper to overflow-x: clip).
|
|
5321
|
+
syncStickyScrollbar(parts.scrollable, parts.scrollbar);
|
|
5322
|
+
continue;
|
|
5323
|
+
}
|
|
5324
|
+
if (prev) {
|
|
5325
|
+
prev.cleanup();
|
|
5326
|
+
attached.delete(nodeKey);
|
|
5327
|
+
}
|
|
5328
|
+
if (parts) {
|
|
5329
|
+
attached.set(nodeKey, {
|
|
5330
|
+
cleanup: attachStickyScrollbarListeners(parts),
|
|
5331
|
+
parts
|
|
5332
|
+
});
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5335
|
+
}, {
|
|
5336
|
+
skipInitialization: false
|
|
5337
|
+
}));
|
|
5338
|
+
}
|
|
5339
|
+
|
|
5158
5340
|
/**
|
|
5159
5341
|
* Configures {@link TableNode}, {@link TableRowNode}, {@link TableCellNode} and
|
|
5160
5342
|
* registers table behaviors (see {@link TableConfig})
|
|
@@ -5168,6 +5350,7 @@ const TableExtension = /* @__PURE__ */defineExtension({
|
|
|
5168
5350
|
hasCellMerge: true,
|
|
5169
5351
|
hasHorizontalScroll: true,
|
|
5170
5352
|
hasNestedTables: false,
|
|
5353
|
+
hasStickyScrollbar: false,
|
|
5171
5354
|
hasTabHandler: true
|
|
5172
5355
|
}),
|
|
5173
5356
|
dependencies: [
|
|
@@ -5181,18 +5364,31 @@ const TableExtension = /* @__PURE__ */defineExtension({
|
|
|
5181
5364
|
nodes: () => [TableNode, TableRowNode, TableCellNode],
|
|
5182
5365
|
register(editor, config, state) {
|
|
5183
5366
|
const stores = state.getOutput();
|
|
5367
|
+
let prevStickyScrollbar = false;
|
|
5184
5368
|
return mergeRegister(effect(() => {
|
|
5185
5369
|
const hasHorizontalScroll = stores.hasHorizontalScroll.value;
|
|
5370
|
+
const hasStickyScrollbar = stores.hasStickyScrollbar.value && hasHorizontalScroll;
|
|
5186
5371
|
const hadHorizontalScroll = $isScrollableTablesActive(editor);
|
|
5187
5372
|
if (hadHorizontalScroll !== hasHorizontalScroll) {
|
|
5188
5373
|
setScrollableTablesActive(editor, hasHorizontalScroll);
|
|
5374
|
+
}
|
|
5375
|
+
if (hadHorizontalScroll !== hasHorizontalScroll || prevStickyScrollbar !== hasStickyScrollbar) {
|
|
5189
5376
|
// Re-render existing tables through the new scroll-wrapper config
|
|
5190
5377
|
// without cloning every TableNode the way marking them dirty would. A
|
|
5191
5378
|
// full reconcile marks no nodes dirty, so it's deferred (no
|
|
5192
5379
|
// synchronous render from this effect) and produces no history entry.
|
|
5193
5380
|
editor.update($fullReconcile);
|
|
5194
5381
|
}
|
|
5195
|
-
|
|
5382
|
+
prevStickyScrollbar = hasStickyScrollbar;
|
|
5383
|
+
}), registerTablePlugin(editor, stores), effect(() => registerTableSelectionObserver(editor, stores.hasTabHandler.value)), effect(() => {
|
|
5384
|
+
if (stores.hasStickyScrollbar.value && stores.hasHorizontalScroll.value) {
|
|
5385
|
+
return editor.registerRootListener(rootElement => {
|
|
5386
|
+
if (rootElement) {
|
|
5387
|
+
return registerStickyScrollbar(editor);
|
|
5388
|
+
}
|
|
5389
|
+
});
|
|
5390
|
+
}
|
|
5391
|
+
}), effect(() => stores.hasCellMerge.value ? undefined : registerTableCellUnmergeTransform(editor)), effect(() => stores.hasCellBackgroundColor.value ? undefined : editor.registerNodeTransform(TableCellNode, node => {
|
|
5196
5392
|
if (node.getBackgroundColor() !== null) {
|
|
5197
5393
|
node.setBackgroundColor(null);
|
|
5198
5394
|
}
|
|
@@ -5214,4 +5410,4 @@ const TableImportExtension = /* @__PURE__ */defineExtension({
|
|
|
5214
5410
|
name: '@lexical/table/Import'
|
|
5215
5411
|
});
|
|
5216
5412
|
|
|
5217
|
-
export { $computeTableMap, $computeTableMapSkipCellCheck, $createTableCellNode, $createTableNode, $createTableNodeWithDimensions, $createTableRowNode, $createTableSelection, $createTableSelectionFrom, $deleteTableColumn, $deleteTableColumnAtSelection, $deleteTableColumn__EXPERIMENTAL, $deleteTableRowAtSelection, $deleteTableRow__EXPERIMENTAL, $findCellNode, $findTableNode, $getElementForTableNode, $getNodeTriplet, $getTableAndElementByKey, $getTableCellNodeFromLexicalNode, $getTableCellNodeRect, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $getTableRowNodeFromTableCellNodeOrThrow, $insertTableColumn, $insertTableColumnAtNode, $insertTableColumnAtSelection, $insertTableColumn__EXPERIMENTAL, $insertTableRow, $insertTableRowAtNode, $insertTableRowAtSelection, $insertTableRow__EXPERIMENTAL, $isScrollableTablesActive, $isSimpleTable, $isTableCellNode, $isTableNode, $isTableRowNode, $isTableSelection, $mergeCells, $moveTableColumn, $moveTableRow, $removeTableRowAtIndex, $setTableColumnIsHeader, $setTableRowIsHeader, $unmergeCell, $unmergeCellNode, INSERT_TABLE_COMMAND, TableCellHeaderStates, TableCellNode, TableExtension, TableImportExtension, TableImportRules, TableNode, TableObserver, TableRowNode, TableRowSchema, TableSchema, applyTableHandlers, getDOMCellFromTarget, getTableElement, getTableObserverFromTableElement, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive };
|
|
5413
|
+
export { $computeTableCellRectBoundary, $computeTableMap, $computeTableMapSkipCellCheck, $createTableCellNode, $createTableNode, $createTableNodeWithDimensions, $createTableRowNode, $createTableSelection, $createTableSelectionFrom, $deleteTableColumn, $deleteTableColumnAtSelection, $deleteTableColumn__EXPERIMENTAL, $deleteTableRowAtSelection, $deleteTableRow__EXPERIMENTAL, $findCellNode, $findTableNode, $getElementForTableNode, $getNodeTriplet, $getTableAndElementByKey, $getTableCellNodeFromLexicalNode, $getTableCellNodeRect, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $getTableRowNodeFromTableCellNodeOrThrow, $insertTableColumn, $insertTableColumnAtNode, $insertTableColumnAtSelection, $insertTableColumn__EXPERIMENTAL, $insertTableRow, $insertTableRowAtNode, $insertTableRowAtSelection, $insertTableRow__EXPERIMENTAL, $isScrollableTablesActive, $isSimpleTable, $isStickyScrollbarActive, $isTableCellNode, $isTableNode, $isTableRowNode, $isTableSelection, $mergeCells, $moveTableColumn, $moveTableRow, $removeTableRowAtIndex, $setTableColumnIsHeader, $setTableRowIsHeader, $unmergeCell, $unmergeCellNode, INSERT_TABLE_COMMAND, TableCellHeaderStates, TableCellNode, TableExtension, TableImportExtension, TableImportRules, TableNode, TableObserver, TableRowNode, TableRowSchema, TableSchema, applyTableHandlers, getDOMCellFromTarget, getTableElement, getTableObserverFromTableElement, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive };
|
|
@@ -47,8 +47,6 @@ declare export class TableCellNode extends ElementNode {
|
|
|
47
47
|
__headerState: TableCellHeaderState;
|
|
48
48
|
__width?: number;
|
|
49
49
|
__backgroundColor: null | string;
|
|
50
|
-
static getType(): string;
|
|
51
|
-
static clone(node: TableCellNode): TableCellNode;
|
|
52
50
|
constructor(
|
|
53
51
|
headerState?: TableCellHeaderState,
|
|
54
52
|
colSpan?: number,
|
|
@@ -97,8 +95,6 @@ export type TableMapValueType = {
|
|
|
97
95
|
export type TableMapType = TableMapValueType[][];
|
|
98
96
|
|
|
99
97
|
declare export class TableNode extends ElementNode {
|
|
100
|
-
static getType(): string;
|
|
101
|
-
static clone(node: TableNode): TableNode;
|
|
102
98
|
constructor(key?: NodeKey): void;
|
|
103
99
|
createDOM(config: EditorConfig): HTMLElement;
|
|
104
100
|
insertNewAfter(selection: RangeSelection): null | ParagraphNode | TableNode;
|
|
@@ -122,6 +118,9 @@ declare export function $isTableNode(
|
|
|
122
118
|
declare export function $isScrollableTablesActive(
|
|
123
119
|
editor?: LexicalEditor
|
|
124
120
|
): boolean;
|
|
121
|
+
declare export function $isStickyScrollbarActive(
|
|
122
|
+
editor?: LexicalEditor
|
|
123
|
+
): boolean;
|
|
125
124
|
declare export function setScrollableTablesActive(
|
|
126
125
|
editor: LexicalEditor,
|
|
127
126
|
active: boolean,
|
|
@@ -139,8 +138,6 @@ declare export function $getTableAndElementByKey(
|
|
|
139
138
|
*/
|
|
140
139
|
|
|
141
140
|
declare export class TableRowNode extends ElementNode {
|
|
142
|
-
static getType(): string;
|
|
143
|
-
static clone(node: TableRowNode): TableRowNode;
|
|
144
141
|
constructor(height?: ?number, key?: NodeKey): void;
|
|
145
142
|
createDOM(config: EditorConfig): HTMLElement;
|
|
146
143
|
setHeight(height: number): ?number;
|
|
@@ -467,6 +464,8 @@ export type TableConfig = {
|
|
|
467
464
|
hasCellBackgroundColor: boolean;
|
|
468
465
|
hasTabHandler: boolean;
|
|
469
466
|
hasHorizontalScroll: boolean;
|
|
467
|
+
hasStickyScrollbar: boolean;
|
|
468
|
+
hasNestedTables: boolean;
|
|
470
469
|
};
|
|
471
470
|
|
|
472
471
|
|
package/dist/LexicalTable.mjs
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import * as modDev from './LexicalTable.dev.mjs';
|
|
10
10
|
import * as modProd from './LexicalTable.prod.mjs';
|
|
11
11
|
const mod = process.env.NODE_ENV !== 'production' ? modDev : modProd;
|
|
12
|
+
export const $computeTableCellRectBoundary = mod.$computeTableCellRectBoundary;
|
|
12
13
|
export const $computeTableMap = mod.$computeTableMap;
|
|
13
14
|
export const $computeTableMapSkipCellCheck = mod.$computeTableMapSkipCellCheck;
|
|
14
15
|
export const $createTableCellNode = mod.$createTableCellNode;
|
|
@@ -43,6 +44,7 @@ export const $insertTableRowAtSelection = mod.$insertTableRowAtSelection;
|
|
|
43
44
|
export const $insertTableRow__EXPERIMENTAL = mod.$insertTableRow__EXPERIMENTAL;
|
|
44
45
|
export const $isScrollableTablesActive = mod.$isScrollableTablesActive;
|
|
45
46
|
export const $isSimpleTable = mod.$isSimpleTable;
|
|
47
|
+
export const $isStickyScrollbarActive = mod.$isStickyScrollbarActive;
|
|
46
48
|
export const $isTableCellNode = mod.$isTableCellNode;
|
|
47
49
|
export const $isTableNode = mod.$isTableNode;
|
|
48
50
|
export const $isTableRowNode = mod.$isTableRowNode;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const mod = await (process.env.NODE_ENV !== 'production' ? import('./LexicalTable.dev.mjs') : import('./LexicalTable.prod.mjs'));
|
|
10
|
+
export const $computeTableCellRectBoundary = mod.$computeTableCellRectBoundary;
|
|
10
11
|
export const $computeTableMap = mod.$computeTableMap;
|
|
11
12
|
export const $computeTableMapSkipCellCheck = mod.$computeTableMapSkipCellCheck;
|
|
12
13
|
export const $createTableCellNode = mod.$createTableCellNode;
|
|
@@ -41,6 +42,7 @@ export const $insertTableRowAtSelection = mod.$insertTableRowAtSelection;
|
|
|
41
42
|
export const $insertTableRow__EXPERIMENTAL = mod.$insertTableRow__EXPERIMENTAL;
|
|
42
43
|
export const $isScrollableTablesActive = mod.$isScrollableTablesActive;
|
|
43
44
|
export const $isSimpleTable = mod.$isSimpleTable;
|
|
45
|
+
export const $isStickyScrollbarActive = mod.$isStickyScrollbarActive;
|
|
44
46
|
export const $isTableCellNode = mod.$isTableCellNode;
|
|
45
47
|
export const $isTableNode = mod.$isTableNode;
|
|
46
48
|
export const $isTableRowNode = mod.$isTableRowNode;
|