@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
265 lines (260 loc) • 14.3 kB
JavaScript
"use strict";
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ColumnControls = void 0;
var _react = _interopRequireWildcard(require("react"));
var _hooks = require("@atlaskit/editor-common/hooks");
var _styles = require("@atlaskit/editor-common/styles");
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
var _editorTables = require("@atlaskit/editor-tables");
var _utils = require("@atlaskit/editor-tables/utils");
var _commands = require("../../../pm-plugins/commands");
var _commands2 = require("../../../pm-plugins/drag-and-drop/commands");
var _rowControls = require("../../../pm-plugins/utils/row-controls");
var _selection = require("../../../pm-plugins/utils/selection");
var _types = require("../../../types");
var _DragHandle = require("../../DragHandle");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
/* eslint-disable @atlaskit/design-system/prefer-primitives */
var getSelectedColumns = function getSelectedColumns(selection) {
if (selection instanceof _editorTables.CellSelection && selection.isColSelection()) {
var rect = (0, _utils.getSelectionRect)(selection);
if (!rect) {
return [];
}
return (0, _selection.getSelectedColumnIndexes)(rect);
}
return [];
};
var ColumnControls = exports.ColumnControls = function ColumnControls(_ref) {
var _colWidths$map$join;
var editorView = _ref.editorView,
tableActive = _ref.tableActive,
tableRef = _ref.tableRef,
hoveredCell = _ref.hoveredCell,
stickyTop = _ref.stickyTop,
localId = _ref.localId,
isInDanger = _ref.isInDanger,
rowHeights = _ref.rowHeights,
colWidths = _ref.colWidths,
isTableHovered = _ref.isTableHovered,
tableContainerWidth = _ref.tableContainerWidth,
isNumberColumnEnabled = _ref.isNumberColumnEnabled,
isDragging = _ref.isDragging,
getScrollOffset = _ref.getScrollOffset,
api = _ref.api;
var columnControlsRef = (0, _react.useRef)(null);
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['selection'], function (states) {
var _states$selectionStat;
return {
selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection
};
}),
selection = _useSharedPluginState.selection;
var widths = (_colWidths$map$join = colWidths === null || colWidths === void 0 ? void 0 : colWidths.map(function (width) {
return (
// when there is sticky header, a `margin-right: -1px` applied to `tr.sticky th` so it causes colWidths to be 1px wider
// we need to reduce the width by 1px to avoid misalignment of column controls.
width ? stickyTop ? "".concat(width - 2, "px") : "".concat(width - 1, "px") : '0px'
);
}).join(' ')) !== null && _colWidths$map$join !== void 0 ? _colWidths$map$join : '0px';
// TODO: ED-26961 - reusing getRowsParams here because it's generic enough to work for columns -> rename
var columnParams = (0, _rowControls.getRowsParams)(colWidths !== null && colWidths !== void 0 ? colWidths : []);
var colIndex = hoveredCell === null || hoveredCell === void 0 ? void 0 : hoveredCell.colIndex;
var selectedColIndexes = getSelectedColumns(selection || editorView.state.selection);
var firstRow = tableRef.querySelector('tr');
var hasHeaderRow = firstRow ? firstRow.getAttribute('data-header-row') : false;
var rowControlStickyTop = 45;
var marginTop = hasHeaderRow && stickyTop !== undefined ? rowControlStickyTop !== null && rowControlStickyTop !== void 0 ? rowControlStickyTop : 0 : 0;
var handleClick = (0, _react.useCallback)(function (event) {
var state = editorView.state,
dispatch = editorView.dispatch;
var isClickOutsideSelectedCols =
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
selectedColIndexes.length >= 1 && !selectedColIndexes.includes(colIndex);
if (!selectedColIndexes || selectedColIndexes.length === 0 || isClickOutsideSelectedCols) {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(0, _commands.selectColumn)(colIndex, event.shiftKey)(state, dispatch);
}
if (selectedColIndexes.length > 1 &&
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
selectedColIndexes.includes(colIndex) && !event.shiftKey) {
(0, _commands.selectColumns)(selectedColIndexes)(state, dispatch);
}
}, [colIndex, selectedColIndexes, editorView]);
var handleMouseOver = (0, _react.useCallback)(function () {
var state = editorView.state,
dispatch = editorView.dispatch;
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(0, _commands.hoverColumns)([colIndex])(state, dispatch);
}, [colIndex, editorView]);
var handleMouseMove = (0, _react.useCallback)(function (e) {
var isParentDragControls = e.nativeEvent.target.closest(".".concat(_types.TableCssClassName.DRAG_COLUMN_CONTROLS));
var colIndex = e.nativeEvent.target.getAttribute('data-start-index');
// avoid updating if event target is not related
if (!isParentDragControls || !colIndex) {
return;
}
// update hovered cell location
var state = editorView.state,
dispatch = editorView.dispatch;
if (tableActive) {
// For context: Whenever we mouse over a column or row drag handle, we will ALWAYS be hovering over the 0 index
// of the opposite dimension. For example; here when we mouse over the column drag handle then we're technically
// also hovering over row 0 index. And vice-versa with rows. This means we don't need to worry about knowing the
// current row index. We can just force it to 0.
(0, _commands.hoverCell)(0, Number(colIndex))(state, dispatch);
}
}, [editorView, tableActive]);
var handleMouseOut = (0, _react.useCallback)(function () {
if (tableActive) {
var state = editorView.state,
dispatch = editorView.dispatch;
(0, _commands.clearHoverSelection)()(state, dispatch);
}
}, [editorView, tableActive]);
var toggleDragMenuHandler = (0, _react.useCallback)(function (trigger, event) {
var state = editorView.state,
dispatch = editorView.dispatch;
if (event !== null && event !== void 0 && event.shiftKey) {
return;
}
(0, _commands2.toggleDragMenu)(undefined, 'column', colIndex, trigger)(state, dispatch);
}, [editorView, colIndex]);
var colIndexes = (0, _react.useMemo)(function () {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return [colIndex];
}, [colIndex]);
if (stickyTop && columnControlsRef.current) {
var _getScrollOffset;
columnControlsRef.current.scrollLeft = (_getScrollOffset = getScrollOffset === null || getScrollOffset === void 0 ? void 0 : getScrollOffset()) !== null && _getScrollOffset !== void 0 ? _getScrollOffset : 0;
}
var generateHandleByType = function generateHandleByType(type, appearance, gridColumn, indexes) {
var _rowHeights$reduce, _colWidths$reduce;
var isHover = type === 'hover';
var isPlaceholder = appearance === 'placeholder';
var previewHeight = (_rowHeights$reduce = rowHeights === null || rowHeights === void 0 ? void 0 : rowHeights.reduce(function (sum, cur) {
return sum + cur;
}, 0)) !== null && _rowHeights$reduce !== void 0 ? _rowHeights$reduce : 0;
var previewWidth = (_colWidths$reduce = colWidths === null || colWidths === void 0 ? void 0 : colWidths.reduce(function (sum, v, i) {
return sum + (v !== null && v !== void 0 ? v : _styles.tableCellMinWidth) * (indexes.includes(i) ? 1 : 0);
}, 0)) !== null && _colWidths$reduce !== void 0 ? _colWidths$reduce : _styles.tableCellMinWidth;
return /*#__PURE__*/_react.default.createElement("div", {
contentEditable: false,
key: type,
style: {
gridColumn: gridColumn,
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
gridRow: '1',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
display: 'flex',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
justifyContent: 'center',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
alignItems: 'center',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
height: 'fit-content',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
placeSelf: 'center',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
zIndex: 99,
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
width: '100%',
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
position: 'relative'
},
"data-testid": "table-floating-column-".concat(isHover ? colIndex : isPlaceholder ? appearance : selectedColIndexes[0], "-drag-handle")
}, /*#__PURE__*/_react.default.createElement(_DragHandle.DragHandle, {
isDragMenuTarget: !isHover,
direction: "column",
tableLocalId: localId || '',
indexes: indexes,
hoveredCell: hoveredCell,
previewWidth: previewWidth,
forceDefaultHandle: !isHover,
previewHeight: previewHeight,
appearance: appearance,
onClick: handleClick,
onMouseOver: handleMouseOver,
onMouseOut: handleMouseOut,
toggleDragMenu: toggleDragMenuHandler,
editorView: editorView
}));
};
var columnHandles = function columnHandles() {
var handles = [];
var isColumnSelected = selectedColIndexes.length > 0;
var isEntireTableSelected = (colWidths || []).length > selectedColIndexes.length;
if (!tableActive) {
return null;
}
var selectedAppearance = isColumnSelected && isEntireTableSelected ? isInDanger ? 'danger' : 'selected' : 'placeholder';
// placeholder / selected need to always render at least one handle
// so it can be focused via keyboard shortcuts
handles.push(generateHandleByType('selected', selectedAppearance,
// always position placeholder in first column to avoid overflow issues
selectedAppearance === 'placeholder' ? '1 / span 1' : "".concat(selectedColIndexes[0] + 1, " / span ").concat(selectedColIndexes.length), selectedColIndexes));
if (hoveredCell && isTableHovered && colIndex !== undefined && !selectedColIndexes.includes(colIndex)) {
handles.push(
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
generateHandleByType('hover', 'default', "".concat(colIndex + 1, " / span 1"), colIndexes));
}
return handles;
};
var containerWidth = isNumberColumnEnabled && tableContainerWidth ? tableContainerWidth - _editorSharedStyles.akEditorTableNumberColumnWidth : tableContainerWidth;
return /*#__PURE__*/_react.default.createElement("div", {
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
className: _types.TableCssClassName.DRAG_COLUMN_CONTROLS,
onMouseMove: handleMouseMove
}, /*#__PURE__*/_react.default.createElement("div", {
ref: columnControlsRef
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
,
className: _types.TableCssClassName.DRAG_COLUMN_CONTROLS_INNER,
"data-testid": "table-floating-column-controls",
style: {
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
gridTemplateColumns: widths,
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview, @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
marginTop: marginTop,
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview
width: stickyTop ? containerWidth : undefined,
overflowX: stickyTop ? 'hidden' : 'visible',
pointerEvents: isDragging ? 'none' : undefined
}
}, columnParams.map(function (_ref2, index) {
var startIndex = _ref2.startIndex,
endIndex = _ref2.endIndex;
return /*#__PURE__*/_react.default.createElement("div", {
style: {
gridColumn: "".concat(startIndex + 1, " / span 1")
},
"data-start-index": startIndex,
"data-end-index": endIndex
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
,
className: _types.TableCssClassName.DRAG_COLUMN_FLOATING_INSERT_DOT_WRAPPER,
contentEditable: false
// Ignored via go/ees005
// eslint-disable-next-line react/no-array-index-key
,
key: index
}, /*#__PURE__*/_react.default.createElement("div", {
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
className: _types.TableCssClassName.DRAG_COLUMN_FLOATING_INSERT_DOT
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
,
style: columnParams.length - 1 === index ? {
right: '0'
} : {}
}));
}), columnHandles()));
};