@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
277 lines (272 loc) • 14 kB
JavaScript
import { ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD, TABLE_ACTION, TABLE_OVERFLOW_CHANGE_TRIGGER } from '@atlaskit/editor-common/analytics';
import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
import { TableMap } from '@atlaskit/editor-tables/table-map';
import { getSelectionRect } from '@atlaskit/editor-tables/utils';
import { insm } from '@atlaskit/insm';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { stopKeyboardColumnResizing } from '../commands/column-resize';
import { updateResizeHandleDecorations } from '../commands/misc';
import { getPluginState as getTablePluginState } from '../plugin-factory';
import { META_KEYS } from '../table-analytics';
import { updateColumnWidths } from '../transforms/column-width';
import { tablesHaveDifferentNoOfColumns } from '../utils/nodes';
import { getSelectedColumnIndexes } from '../utils/selection';
import { evenColumns, setDragging, stopResizing } from './commands';
import { getPluginState } from './plugin-factory';
import { TABLE_OFFSET_IN_COMMENT_EDITOR } from './utils/consts';
import { updateControls } from './utils/dom';
import { currentColWidth, getTableMaxWidth, pointsAtCell, getScalingPercentForTableWithoutWidth, getTableScalingPercent } from './utils/misc';
import { resizeColumn } from './utils/resize-column';
import { getResizeState } from './utils/resize-state';
export var handleMouseDown = function handleMouseDown(view, event, localResizeHandlePos, getEditorContainerWidth, getEditorFeatureFlags, isTableScalingEnabled, api, nodeViewPortalProviderAPI, editorAnalyticsAPI, isCommentEditor) {
var _originalTable$attrs;
var state = view.state,
dispatch = view.dispatch;
var editorDisabled = !view.editable;
var domAtPos = view.domAtPos.bind(view);
var _getEditorContainerWi = getEditorContainerWidth(),
editorWidth = _getEditorContainerWi.width;
if (editorDisabled || localResizeHandlePos === null || !pointsAtCell(state.doc.resolve(localResizeHandlePos))) {
return false;
}
var _getTablePluginState = getTablePluginState(state),
isKeyboardResize = _getTablePluginState.isKeyboardResize;
event.preventDefault();
if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) {
var _insm$session;
(_insm$session = insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('tableColumnResize');
}
var tr = view.state.tr;
tr.setMeta(META_KEYS.OVERFLOW_TRIGGER, {
name: TABLE_OVERFLOW_CHANGE_TRIGGER.RESIZED_COLUMN
});
dispatch(tr);
var mouseDownTime = event.timeStamp;
var cell = state.doc.nodeAt(localResizeHandlePos);
var $cell = state.doc.resolve(localResizeHandlePos);
var originalTable = $cell.node(-1);
var start = $cell.start(-1);
var tablePos = state.doc.resolve(start).start(-1);
var tableDepth = state.doc.resolve(tablePos).depth;
var dom = domAtPos(start).node;
if (dom && dom.nodeName !== 'TABLE') {
dom = dom.closest('table');
}
var maxSize = 0;
if (isTableScalingEnabled && isCommentEditor && !((_originalTable$attrs = originalTable.attrs) !== null && _originalTable$attrs !== void 0 && _originalTable$attrs.width)) {
maxSize = editorWidth - TABLE_OFFSET_IN_COMMENT_EDITOR;
} else {
maxSize = getTableMaxWidth({
table: originalTable,
tableStart: start,
state: state,
layout: originalTable.attrs.layout,
getEditorContainerWidth: getEditorContainerWidth
});
}
var shouldScale = tableDepth === 0 && isTableScalingEnabled;
var _getEditorFeatureFlag = getEditorFeatureFlags(),
_getEditorFeatureFlag2 = _getEditorFeatureFlag.tableWithFixedColumnWidthsOption,
tableWithFixedColumnWidthsOption = _getEditorFeatureFlag2 === void 0 ? false : _getEditorFeatureFlag2;
var isTableScalingWithFixedColumnWidthsOptionEnabled = isTableScalingEnabled && tableWithFixedColumnWidthsOption;
if (isTableScalingWithFixedColumnWidthsOptionEnabled) {
shouldScale = shouldScale && originalTable.attrs.displayMode !== 'fixed';
}
var shouldUseIncreasedScalingPercent = isTableScalingWithFixedColumnWidthsOptionEnabled;
if (isTableScalingEnabled && isCommentEditor) {
shouldScale = tableDepth === 0;
shouldUseIncreasedScalingPercent = true;
}
var resizeState = getResizeState({
minWidth: tableCellMinWidth,
maxSize: maxSize,
table: originalTable,
tableRef: dom,
start: start,
domAtPos: domAtPos,
isTableScalingEnabled: shouldScale,
shouldUseIncreasedScalingPercent: shouldUseIncreasedScalingPercent,
isCommentEditor: isCommentEditor || false
});
if (evenColumns({
resizeState: resizeState,
table: originalTable,
start: start,
event: event,
api: api
})(state, dispatch)) {
finish(event);
return true;
}
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var width = currentColWidth(view, localResizeHandlePos, cell.attrs);
setDragging({
startX: event.clientX,
startWidth: width
})(state, dispatch);
// When we start resizing a column we need to ensure the underlying tooltip is removed from the decoration to avoid
// unnecessary tooltips being displayed during drag.
updateResizeHandleDecorations(nodeViewPortalProviderAPI, undefined, undefined, false)(state, dispatch);
function finish(event) {
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
window.removeEventListener('mouseup', finish);
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
window.removeEventListener('mousemove', move);
var clientX = event.clientX;
var state = view.state,
dispatch = view.dispatch;
var _getPluginState = getPluginState(state),
dragging = _getPluginState.dragging,
resizeHandlePos = _getPluginState.resizeHandlePos;
var _getTablePluginState2 = getTablePluginState(state),
isTableHovered = _getTablePluginState2.isTableHovered;
if (resizeHandlePos === null) {
if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) {
var _insm$session2;
(_insm$session2 = insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('tableColumnResize');
}
return stopResizing()(state, dispatch);
}
if (!pointsAtCell(state.doc.resolve(resizeHandlePos))) {
if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) {
var _insm$session3;
(_insm$session3 = insm.session) === null || _insm$session3 === void 0 || _insm$session3.endFeature('tableColumnResize');
}
return;
}
// resizeHandlePos could be remapped via a collab change.
// Fetch a fresh reference of the table.
var $cell = state.doc.resolve(resizeHandlePos);
var start = $cell.start(-1);
var table = $cell.node(-1);
var tablePos = state.doc.resolve(start).start(-1);
var tableDepth = state.doc.resolve(tablePos).depth;
// If we let go in the same place we started, don't need to do anything.
if (dragging && clientX === dragging.startX) {
if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) {
var _insm$session4;
(_insm$session4 = insm.session) === null || _insm$session4 === void 0 || _insm$session4.endFeature('tableColumnResize');
}
if (isKeyboardResize || !isTableHovered) {
/** if column resize had started via keyboard but continued by mouse
* or mouse pointer leaves the table but mouse button still pressed
*/
return stopKeyboardColumnResizing({})(state, dispatch, view);
} else {
return stopResizing()(state, dispatch);
}
}
var tr = state.tr;
if (dragging) {
var startX = dragging.startX;
// If the dimensions of the table have changed through a remote modification by another
// person for example don't persist the new column widths as we couldn't reliably remap them
// For example, if a table col is deleted
// There may be a more elegant solution to this, to avoid a jarring experience. This used to
// be an equality check but that caused issues when a nested table would change (eg. when it
// dynamically updates its width on resize)
if (!tablesHaveDifferentNoOfColumns(originalTable, table)) {
var _table$attrs;
var map = TableMap.get(table);
var colIndex = map.colCount($cell.pos - start) + ($cell.nodeAfter ? $cell.nodeAfter.attrs.colspan : 1) - 1;
var selectionRect = getSelectionRect(state.selection);
var selectedColumns = selectionRect ? getSelectedColumnIndexes(selectionRect) : [];
// only selected (or selected - 1) columns should be distributed
var resizingSelectedColumns = selectedColumns.indexOf(colIndex) > -1 || selectedColumns.indexOf(colIndex + 1) > -1;
var _shouldScale = tableDepth === 0 && isTableScalingEnabled;
if (isTableScalingWithFixedColumnWidthsOptionEnabled) {
_shouldScale = _shouldScale && originalTable.attrs.displayMode !== 'fixed';
}
var resizedDelta = clientX - startX;
var _shouldUseIncreasedScalingPercent = isTableScalingWithFixedColumnWidthsOptionEnabled || isTableScalingEnabled && !!isCommentEditor;
var scalePercent = isTableScalingEnabled && isCommentEditor && !((_table$attrs = table.attrs) !== null && _table$attrs !== void 0 && _table$attrs.width) ? getScalingPercentForTableWithoutWidth(originalTable, dom) : getTableScalingPercent(originalTable, dom, _shouldUseIncreasedScalingPercent);
var newResizeState = resizeColumn(resizeState, colIndex, resizedDelta, dom, originalTable, resizingSelectedColumns ? selectedColumns : undefined, _shouldScale, scalePercent);
tr = updateColumnWidths(newResizeState, table, start, api)(tr);
if (colIndex === map.width - 1) {
var mouseUpTime = event.timeStamp;
editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
action: TABLE_ACTION.ATTEMPTED_TABLE_WIDTH_CHANGE,
actionSubject: ACTION_SUBJECT.TABLE,
actionSubjectId: null,
attributes: {
type: 'table-border',
position: 'right',
duration: mouseUpTime - mouseDownTime,
delta: Math.abs(resizedDelta)
},
eventType: EVENT_TYPE.UI
})(tr);
}
editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
action: TABLE_ACTION.COLUMN_RESIZED,
actionSubject: ACTION_SUBJECT.TABLE,
eventType: EVENT_TYPE.TRACK,
attributes: {
colIndex: colIndex,
resizedDelta: resizedDelta,
isLastColumn: colIndex === map.width - 1,
tableWidth: table.attrs.width,
inputMethod: INPUT_METHOD.MOUSE,
totalRowCount: map.height,
totalColumnCount: map.width
}
})(tr);
}
if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) {
var _insm$session5;
(_insm$session5 = insm.session) === null || _insm$session5 === void 0 || _insm$session5.endFeature('tableColumnResize');
}
if (isKeyboardResize || !isTableHovered) {
/** if column resize had started via keyboard but continued by mouse
* or mouse pointer leaves the table but mouse button still pressed
*/
return stopKeyboardColumnResizing({
originalTr: tr
})(state, dispatch, view);
} else {
return stopResizing(tr)(state, dispatch);
}
}
}
function move(event) {
var _table$attrs2;
var clientX = event.clientX,
which = event.which;
var state = view.state;
var _getPluginState2 = getPluginState(state),
dragging = _getPluginState2.dragging,
resizeHandlePos = _getPluginState2.resizeHandlePos;
var _getTablePluginState3 = getTablePluginState(state),
isTableHovered = _getTablePluginState3.isTableHovered;
var tablePos = state.doc.resolve(start).start(-1);
if (!which || !dragging || resizeHandlePos === null || !pointsAtCell(state.doc.resolve(resizeHandlePos)) || !isTableHovered) {
return finish(event);
}
var $cell = state.doc.resolve(resizeHandlePos);
var table = $cell.node(-1);
var tableDepth = state.doc.resolve(tablePos).depth;
var map = TableMap.get(table);
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var colIndex = map.colCount($cell.pos - $cell.start(-1)) + $cell.nodeAfter.attrs.colspan - 1;
var shouldScale = tableDepth === 0 && isTableScalingEnabled;
var shouldUseIncreasedScalingPercent = isTableScalingWithFixedColumnWidthsOptionEnabled || isTableScalingEnabled && isCommentEditor;
if (isTableScalingWithFixedColumnWidthsOptionEnabled) {
shouldScale = shouldScale && originalTable.attrs.displayMode !== 'fixed';
}
var resizedDelta = clientX - dragging.startX;
var scalePercent = isTableScalingEnabled && isCommentEditor && !((_table$attrs2 = table.attrs) !== null && _table$attrs2 !== void 0 && _table$attrs2.width) ? getScalingPercentForTableWithoutWidth(table, dom) : getTableScalingPercent(originalTable, dom, shouldUseIncreasedScalingPercent);
resizeColumn(resizeState, colIndex, resizedDelta, dom, table, undefined, shouldScale, scalePercent);
updateControls()(state);
}
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
window.addEventListener('mouseup', finish);
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
window.addEventListener('mousemove', move);
return true;
};