UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

221 lines (216 loc) 9.42 kB
import _extends from "@babel/runtime/helpers/extends"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import { injectIntl } from 'react-intl'; import { ACTION, ACTION_SUBJECT, CONTENT_COMPONENT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { Popup } from '@atlaskit/editor-common/ui'; import { closestElement } from '@atlaskit/editor-common/utils'; import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils'; import { akEditorTableCellOnStickyHeaderZIndex } from '@atlaskit/editor-shared-styles'; import { CellSelection } from '@atlaskit/editor-tables/cell-selection'; import { TableMap } from '@atlaskit/editor-tables/table-map'; import { findTable } from '@atlaskit/editor-tables/utils'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { insertColumnWithAnalytics, insertRowWithAnalytics } from '../../pm-plugins/commands/commands-with-analytics'; import { checkIfNumberColumnEnabled } from '../../pm-plugins/utils/nodes'; import { TableCssClassName as ClassName } from '../../types'; import getPopupOptions from './getPopupOptions'; import InsertButton, { DragAndDropInsertButton } from './InsertButton'; // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/react/no-class-components, @typescript-eslint/no-explicit-any export class FloatingInsertButton extends React.Component { constructor(props) { super(props); this.insertColumn = this.insertColumn.bind(this); this.insertRow = this.insertRow.bind(this); } render() { const { tableNode, editorView, insertColumnButtonIndex, insertRowButtonIndex, tableRef, mountPoint, boundariesElement, isHeaderColumnEnabled, isHeaderRowEnabled, isDragAndDropEnabled, dispatchAnalyticsEvent, isChromelessEditor } = this.props; // TODO: ED-26961 - temporarily disable insert button for first column and row https://atlassian.slack.com/archives/C05U8HRQM50/p1698363744682219?thread_ts=1698209039.104909&cid=C05U8HRQM50 if (isDragAndDropEnabled && (insertColumnButtonIndex === 0 || insertRowButtonIndex === 0)) { return null; } const type = typeof insertColumnButtonIndex !== 'undefined' ? 'column' : typeof insertRowButtonIndex !== 'undefined' ? 'row' : null; if (!tableNode || !tableRef || !type) { return null; } // We can’t display the insert button for row|colum index 0 // when the header row|colum is enabled, this feature will be change on the future if (type === 'column' && isHeaderColumnEnabled && insertColumnButtonIndex === 0 || type === 'row' && isHeaderRowEnabled && insertRowButtonIndex === 0) { return null; } const { state: { tr } } = editorView; if (tr.selection instanceof CellSelection && (tr.selection.isColSelection() || tr.selection.isRowSelection())) { return null; } const tablePos = findTable(tr.selection); if (!tablePos) { return null; } // the tableNode props is not always latest (when you type some text in a cell, it's not updated yet) // we need to get the latest one by calling findTable(tr.selection) const cellPosition = this.getCellPosition(type, tablePos === null || tablePos === void 0 ? void 0 : tablePos.node); if (!cellPosition) { return null; } const domAtPos = editorView.domAtPos.bind(editorView); const pos = cellPosition + tablePos.start + 1; let target; try { target = findDomRefAtPos(pos, domAtPos); } catch (error) { // eslint-disable-next-line no-console console.warn(error); if (dispatchAnalyticsEvent) { const payload = { action: ACTION.ERRORED, actionSubject: ACTION_SUBJECT.CONTENT_COMPONENT, eventType: EVENT_TYPE.OPERATIONAL, attributes: { component: CONTENT_COMPONENT.FLOATING_INSERT_BUTTON, selection: editorView.state.selection.toJSON(), position: pos, docSize: editorView.state.doc.nodeSize, // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any error: error === null || error === void 0 ? void 0 : error.toString() } }; dispatchAnalyticsEvent(payload); } } if (!target || !(target instanceof HTMLElement)) { return null; } const targetCellRef = type === 'row' ? closestElement(target, 'tr') : closestElement(target, 'td, th'); if (!targetCellRef) { return null; } const tableContainerWrapper = closestElement(targetCellRef, `.${ClassName.TABLE_CONTAINER}`); const tableWrapper = closestElement(targetCellRef, `.${ClassName.TABLE_NODE_WRAPPER}`); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const index = type === 'column' ? insertColumnButtonIndex : insertRowButtonIndex; const hasNumberedColumns = checkIfNumberColumnEnabled(editorView.state.selection); // Fixed the 'add column button' not visible issue when sticky header is enabled // By setting the Popup z-index higher than the sticky header z-index ( common-styles.ts tr.sticky) // Only when inserting a column, otherwise set to undefined // Need to set z-index in the Popup, set z-index in the <InsertButton /> will not work const zIndex = expValEquals('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') || type === 'column' ? akEditorTableCellOnStickyHeaderZIndex : undefined; return /*#__PURE__*/React.createElement(Popup, _extends({ target: targetCellRef, mountTo: tableContainerWrapper || mountPoint, boundariesElement: tableContainerWrapper || boundariesElement // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , scrollableElement: tableWrapper, forcePlacement: true, allowOutOfBounds: true // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading }, getPopupOptions(type, index, hasNumberedColumns, !!isDragAndDropEnabled, tableContainerWrapper), { zIndex: zIndex }), isDragAndDropEnabled ? /*#__PURE__*/React.createElement(DragAndDropInsertButton, { type: type, tableRef: tableRef, onMouseDown: type === 'column' ? this.insertColumn : this.insertRow, hasStickyHeaders: this.props.hasStickyHeaders || false, isChromelessEditor: isChromelessEditor }) : /*#__PURE__*/React.createElement(InsertButton, { type: type, tableRef: tableRef, onMouseDown: type === 'column' ? this.insertColumn : this.insertRow, hasStickyHeaders: this.props.hasStickyHeaders || false })); } getCellPosition(type, tableNode) { const { insertColumnButtonIndex, insertRowButtonIndex } = this.props; const tableMap = TableMap.get(tableNode); if (type === 'column') { // This condition is to make typescript happy. // Previously insertColumnButtonIndex - 1 would produce NaN and return null anyway. if (insertColumnButtonIndex === undefined) { return null; } const columnIndex = insertColumnButtonIndex === 0 ? 0 : insertColumnButtonIndex - 1; if (columnIndex > tableMap.width - 1) { return null; } return tableMap.positionAt(0, columnIndex, tableNode); } else { // This condition is to make typescript happy. // Previously insertRowButtonIndex - 1 would produce NaN and return null anyway. if (insertRowButtonIndex === undefined) { return null; } const rowIndex = insertRowButtonIndex === 0 ? 0 : insertRowButtonIndex - 1; if (rowIndex > tableMap.height - 1) { return null; } return tableMap.positionAt(rowIndex, 0, tableNode); } } insertRow(event) { const { editorView, insertRowButtonIndex, editorAnalyticsAPI } = this.props; if (typeof insertRowButtonIndex !== 'undefined') { event.preventDefault(); const { state, dispatch } = editorView; insertRowWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.BUTTON, { index: insertRowButtonIndex, moveCursorToInsertedRow: true })(state, dispatch); } } insertColumn(event) { const { editorView, insertColumnButtonIndex, editorAnalyticsAPI, getEditorFeatureFlags, isTableScalingEnabled, isCommentEditor } = this.props; if (typeof insertColumnButtonIndex !== 'undefined') { event.preventDefault(); const { tableWithFixedColumnWidthsOption = false } = getEditorFeatureFlags ? getEditorFeatureFlags() : {}; const shouldUseIncreasedScalingPercent = isTableScalingEnabled && (tableWithFixedColumnWidthsOption || isCommentEditor); const { state, dispatch } = editorView; insertColumnWithAnalytics(this.props.api, editorAnalyticsAPI, isTableScalingEnabled, tableWithFixedColumnWidthsOption, shouldUseIncreasedScalingPercent, isCommentEditor)(INPUT_METHOD.BUTTON, insertColumnButtonIndex)(state, dispatch, editorView); } } } _defineProperty(FloatingInsertButton, "displayName", 'FloatingInsertButton'); export default injectIntl(FloatingInsertButton);