@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
157 lines (150 loc) • 6.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.goToNextCellVertical = exports.goToNextCell = void 0;
var _analytics = require("@atlaskit/editor-common/analytics");
var _nesting = require("@atlaskit/editor-common/nesting");
var _state = require("@atlaskit/editor-prosemirror/state");
var _utils = require("@atlaskit/editor-prosemirror/utils");
var _tableMap = require("@atlaskit/editor-tables/table-map");
var _utils2 = require("@atlaskit/editor-tables/utils");
var _pluginFactory = require("../plugin-factory");
var _columnResize = require("./column-resize");
var _commandsWithAnalytics = require("./commands-with-analytics");
var TAB_FORWARD_DIRECTION = 1;
var TAB_BACKWARD_DIRECTION = -1;
var goToNextCell = exports.goToNextCell = function goToNextCell(editorAnalyticsAPI, ariaNotify, getIntl) {
return function (direction) {
return function (state, dispatch, view) {
var _getPluginState;
var table = (0, _utils2.findTable)(state.selection);
if (!table) {
return false;
}
var isColumnResizing = (_getPluginState = (0, _pluginFactory.getPluginState)(state)) === null || _getPluginState === void 0 ? void 0 : _getPluginState.isKeyboardResize;
if (isColumnResizing) {
(0, _columnResize.stopKeyboardColumnResizing)({
ariaNotify: ariaNotify,
getIntl: getIntl
})(state, dispatch, view);
return true;
}
var map = _tableMap.TableMap.get(table.node);
var _state$schema$nodes = state.schema.nodes,
tableCell = _state$schema$nodes.tableCell,
tableHeader = _state$schema$nodes.tableHeader;
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var cell = (0, _utils.findParentNodeOfType)([tableCell, tableHeader])(state.selection);
var firstCellPos = map.positionAt(0, 0, table.node) + table.start;
var lastCellPos = map.positionAt(map.height - 1, map.width - 1, table.node) + table.start;
// When tabbing backwards at first cell (top left), insert row at the start of table
if (firstCellPos === cell.pos && direction === TAB_BACKWARD_DIRECTION) {
(0, _commandsWithAnalytics.insertRowWithAnalytics)(editorAnalyticsAPI)(_analytics.INPUT_METHOD.KEYBOARD, {
index: 0,
moveCursorToInsertedRow: true
})(state, dispatch);
return true;
}
// When tabbing forwards at last cell (bottom right), insert row at the end of table
if (lastCellPos === cell.pos && direction === TAB_FORWARD_DIRECTION) {
(0, _commandsWithAnalytics.insertRowWithAnalytics)(editorAnalyticsAPI)(_analytics.INPUT_METHOD.KEYBOARD, {
index: map.height,
moveCursorToInsertedRow: true
})(state, dispatch);
return true;
}
if (dispatch) {
return (0, _utils2.goToNextCell)(direction)(state, dispatch);
}
return true;
};
};
};
/**
* Moves the cursor vertically from a NodeSelection within a table cell.
* - If content exists above/below within the cell, lets ProseMirror handle it.
* - Otherwise, moves to the next cell (down to start, up to last line).
*/
var goToNextCellVertical = exports.goToNextCellVertical = function goToNextCellVertical(direction) {
return function (state, dispatch) {
var selection = state.selection;
var nestedTableSelection = (0, _nesting.isSelectionTableNestedInTable)(state);
if (!(selection instanceof _state.NodeSelection) && !nestedTableSelection) {
return false; // Let ProseMirror handle other selection types
}
var table = (0, _utils2.findTable)(selection);
var cell = (0, _utils2.findCellClosestToPos)(state.doc.resolve(selection.from));
var selectionPos = selection.from;
// Handle when we have nested table fully selected
if (table && nestedTableSelection && (0, _utils2.isTableSelected)(selection)) {
var parentTablePos = table.pos;
table = (0, _utils2.findTableClosestToPos)(state.doc.resolve(parentTablePos));
cell = (0, _utils2.findCellClosestToPos)(state.doc.resolve(parentTablePos));
selectionPos = parentTablePos;
}
if (!table || !cell || !cell.pos) {
return false;
}
var _state$schema$nodes2 = state.schema.nodes,
tableCell = _state$schema$nodes2.tableCell,
tableHeader = _state$schema$nodes2.tableHeader;
// Let ProseMirror handle movement within the cell if content exists above/below
if (cellHasContentInDirection(cell.node, cell.pos, selectionPos, direction)) {
return false;
}
// Move to the next cell vertically
var map = _tableMap.TableMap.get(table.node);
var nextCellPos = map.nextCell(cell.pos - table.start, 'vert', direction);
if (dispatch && nextCellPos) {
var _$nextCell$nodeAfter, _$nextCell$nodeAfter2;
var nextCellStart = table.start + nextCellPos;
var $nextCell = state.doc.resolve(nextCellStart);
if ((_$nextCell$nodeAfter = $nextCell.nodeAfter) !== null && _$nextCell$nodeAfter !== void 0 && _$nextCell$nodeAfter.type && [tableCell, tableHeader].includes((_$nextCell$nodeAfter2 = $nextCell.nodeAfter) === null || _$nextCell$nodeAfter2 === void 0 ? void 0 : _$nextCell$nodeAfter2.type)) {
var contentPos = getTargetPositionInNextCell($nextCell.nodeAfter, nextCellStart, direction);
dispatch(state.tr.setSelection(_state.TextSelection.create(state.doc, contentPos)));
return true;
}
return false;
}
return false; // No next cell found
};
};
function cellHasContentInDirection(cellNode, cellPos, selectionPos, direction) {
var hasContent = false;
cellNode.content.forEach(function (node, offset) {
var nodeStart = cellPos + 1 + offset;
var nodeEnd = nodeStart + node.nodeSize;
if (direction === 1 && nodeStart > selectionPos && node.isBlock) {
hasContent = true; // Content below
} else if (direction === -1 && nodeEnd <= selectionPos && node.isBlock) {
hasContent = true; // Content above
}
});
return hasContent;
}
function getTargetPositionInNextCell(cellNode, nextCellStart, direction) {
var contentPos = nextCellStart + 1; // Default: just inside the cell
if (cellNode.content.size > 0) {
if (direction === 1) {
var firstChild = cellNode.firstChild;
if (firstChild && firstChild.isBlock) {
contentPos = nextCellStart + 1 + (firstChild.isLeaf ? 0 : 1); // Down: Start of first block
}
} else if (direction === -1) {
var lastBlock;
var lastOffset = 0;
cellNode.content.forEach(function (node, offset) {
if (node.isBlock) {
lastBlock = node;
lastOffset = offset;
}
});
if (lastBlock) {
contentPos = nextCellStart + 1 + lastOffset + (lastBlock.isLeaf ? 0 : lastBlock.nodeSize - 1);
}
}
}
return contentPos;
}