@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
324 lines (318 loc) • 16.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _reactDom = require("react-dom");
var _analytics = require("@atlaskit/editor-common/analytics");
var _messages = require("@atlaskit/editor-common/messages");
var _ui = require("@atlaskit/editor-common/ui");
var _utils = require("@atlaskit/editor-common/utils");
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
var _utils2 = require("@atlaskit/editor-tables/utils");
var _commands = require("../../pm-plugins/commands");
var _commandsWithAnalytics = require("../../pm-plugins/commands/commands-with-analytics");
var _pluginFactory = require("../../pm-plugins/plugin-factory");
var _columnControls = require("../../pm-plugins/utils/column-controls");
var _rowControls = require("../../pm-plugins/utils/row-controls");
var _types = require("../../types");
var _consts = require("../consts");
var _DeleteButton = _interopRequireDefault(require("./DeleteButton"));
var _getPopUpOptions = _interopRequireDefault(require("./getPopUpOptions"));
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); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function getSelectionType(selection) {
if (!(0, _utils2.isTableSelected)(selection) && selection instanceof _cellSelection.CellSelection) {
if (selection.isRowSelection()) {
return 'row';
}
if (selection.isColSelection()) {
return 'column';
}
}
return;
}
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/react/no-class-components
var FloatingDeleteButton = /*#__PURE__*/function (_Component) {
function FloatingDeleteButton(props) {
var _this;
(0, _classCallCheck2.default)(this, FloatingDeleteButton);
_this = _callSuper(this, FloatingDeleteButton, [props]);
(0, _defineProperty2.default)(_this, "wrapper", null);
(0, _defineProperty2.default)(_this, "updateWrapper", function () {
var tableWrapper = (0, _utils.closestElement)(_this.props.tableRef, ".".concat(_types.TableCssClassName.TABLE_NODE_WRAPPER));
if (tableWrapper) {
_this.wrapper = tableWrapper;
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
_this.wrapper.addEventListener('scroll', _this.onWrapperScrolled);
_this.setState({
scrollLeft: tableWrapper.scrollLeft
});
} else {
if (_this.wrapper) {
// unsubscribe if we previously had one and it just went away
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
_this.wrapper.removeEventListener('scroll', _this.onWrapperScrolled);
// and reset scroll position
_this.setState({
scrollLeft: 0
});
}
_this.wrapper = null;
}
});
(0, _defineProperty2.default)(_this, "onWrapperScrolled", function (e) {
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
var wrapper = e.target;
_this.setState({
scrollLeft: wrapper.scrollLeft
});
});
(0, _defineProperty2.default)(_this, "handleMouseEnter", function () {
var _this$props$editorVie = _this.props.editorView,
state = _this$props$editorVie.state,
dispatch = _this$props$editorVie.dispatch;
switch (_this.state.selectionType) {
case 'row':
{
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return (0, _commands.hoverRows)(_this.state.indexes, true)(state, dispatch, _this.props.editorView);
}
case 'column':
{
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return (0, _commands.hoverColumns)(_this.state.indexes, true)(state, dispatch, _this.props.editorView);
}
}
return false;
});
(0, _defineProperty2.default)(_this, "handleMouseLeave", function () {
var _this$props$editorVie2 = _this.props.editorView,
state = _this$props$editorVie2.state,
dispatch = _this$props$editorVie2.dispatch;
return (0, _commands.clearHoverSelection)()(state, dispatch);
});
/**
*
*
* @private
* @memberof FloatingDeleteButton
*/
(0, _defineProperty2.default)(_this, "handleClick", function (event) {
event.preventDefault();
var editorAnalyticsAPI = _this.props.editorAnalyticsAPI;
var _this$props$editorVie3 = _this.props.editorView,
state = _this$props$editorVie3.state,
dispatch = _this$props$editorVie3.dispatch;
var _getTablePluginState = (0, _pluginFactory.getPluginState)(state),
isHeaderRowRequired = _getTablePluginState.pluginConfig.isHeaderRowRequired;
var rect = (0, _utils2.getSelectionRect)(state.selection);
if (rect) {
switch (_this.state.selectionType) {
case 'column':
{
(0, _commandsWithAnalytics.deleteColumnsWithAnalytics)(editorAnalyticsAPI, _this.props.api)(_analytics.INPUT_METHOD.BUTTON, rect)(state, dispatch, _this.props.editorView);
return;
}
case 'row':
{
(0, _commandsWithAnalytics.deleteRowsWithAnalytics)(editorAnalyticsAPI)(_analytics.INPUT_METHOD.BUTTON, rect, !!isHeaderRowRequired)(state, dispatch);
return;
}
}
}
var _this$props$editorVie4 = _this.props.editorView;
state = _this$props$editorVie4.state;
dispatch = _this$props$editorVie4.dispatch;
(0, _commands.clearHoverSelection)()(state, dispatch);
});
_this.state = {
selectionType: undefined,
top: 0,
left: 0,
indexes: [],
scrollLeft: 0
};
return _this;
}
(0, _inherits2.default)(FloatingDeleteButton, _Component);
return (0, _createClass2.default)(FloatingDeleteButton, [{
key: "shouldComponentUpdate",
value: function shouldComponentUpdate(_, nextState) {
return this.state.selectionType !== nextState.selectionType || this.state.left !== nextState.left || this.state.top !== nextState.top || this.state.scrollLeft !== nextState.scrollLeft;
}
}, {
key: "componentDidMount",
value: function componentDidMount() {
this.updateWrapper();
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
this.updateWrapper();
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
if (this.wrapper) {
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
this.wrapper.removeEventListener('scroll', this.onWrapperScrolled);
}
}
}, {
key: "render",
value: function render() {
var _this$props = this.props,
mountPoint = _this$props.mountPoint,
boundariesElement = _this$props.boundariesElement,
tableRef = _this$props.tableRef;
var selectionType = this.state.selectionType;
if (!selectionType || !tableRef) {
return null;
}
var tableContainerWrapper = (0, _utils.closestElement)(tableRef, ".".concat(_types.TableCssClassName.TABLE_CONTAINER));
var button = /*#__PURE__*/_react.default.createElement(_DeleteButton.default, {
removeLabel: selectionType === 'column' ? _messages.tableMessages.removeColumns : _messages.tableMessages.removeRows,
onClick: this.handleClick,
onMouseEnter: this.handleMouseEnter,
onMouseLeave: this.handleMouseLeave
});
var popupOpts = (0, _getPopUpOptions.default)({
left: this.state.left,
top: this.state.top,
selectionType: this.state.selectionType,
tableWrapper: this.wrapper
});
var mountTo = tableContainerWrapper || mountPoint;
if (this.state.position === 'sticky' && mountTo) {
var headerRow = tableRef.querySelector('tr.sticky');
if (headerRow) {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var rect = headerRow.getBoundingClientRect();
var calculatePosition = popupOpts.onPositionCalculated || function (pos) {
return pos;
};
var pos = calculatePosition({
left: this.state.left,
top: this.state.top
});
return /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement("div", {
style: {
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
position: 'fixed',
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview
top: pos.top,
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
zIndex: _consts.stickyRowZIndex,
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview
left: rect.left + (pos.left || 0) - (this.state.selectionType === 'column' ? this.state.scrollLeft : 0) - (
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
this.props.isNumberColumnEnabled ? _editorSharedStyles.akEditorTableNumberColumnWidth : 0)
}
}, button), mountTo);
}
}
return /*#__PURE__*/_react.default.createElement(_ui.Popup, (0, _extends2.default)({
target: tableRef,
mountTo: mountTo,
boundariesElement: tableContainerWrapper || boundariesElement,
scrollableElement: this.wrapper || undefined,
forcePlacement: true,
allowOutOfBounds: true
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
}, popupOpts), button);
}
}], [{
key: "getDerivedStateFromProps",
value:
/**
* We derivate the button state from the properties passed.
* We do this in here because we need this information in different places
* and this prevent to do multiple width calculations in the same component.
*/
function getDerivedStateFromProps(nextProps, prevState) {
var selectionType = getSelectionType(nextProps.selection);
var inStickyMode = nextProps.stickyHeaders && nextProps.stickyHeaders.sticky;
var rect = (0, _utils2.getSelectionRect)(nextProps.selection);
// only tie row delete to sticky header if it's the only thing
// in the selection, otherwise the row delete will hover around
// the rest of the selection
var firstRowInSelection = rect && rect.top === 0 && rect.bottom === 1;
var shouldStickyButton = inStickyMode && firstRowInSelection;
var stickyTop = nextProps.stickyHeaders ? nextProps.stickyHeaders.top + nextProps.stickyHeaders.padding : 0;
if (selectionType) {
switch (selectionType) {
case 'column':
{
// Calculate the button position and indexes for columns
var columnsWidths = (0, _columnControls.getColumnsWidths)(nextProps.editorView);
var deleteBtnParams = (0, _columnControls.getColumnDeleteButtonParams)(columnsWidths, nextProps.editorView.state.selection);
if (deleteBtnParams) {
return _objectSpread(_objectSpread({}, deleteBtnParams), {}, {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
top: inStickyMode ? nextProps.stickyHeaders.top : 0,
position: inStickyMode ? 'sticky' : undefined,
selectionType: selectionType
});
}
return null;
}
case 'row':
{
// Calculate the button position and indexes for rows
if (nextProps.tableRef) {
var rowHeights = (0, _rowControls.getRowHeights)(nextProps.tableRef);
var offsetTop = inStickyMode ? -rowHeights[0] : 0;
var _deleteBtnParams = (0, _rowControls.getRowDeleteButtonParams)(rowHeights, nextProps.editorView.state.selection, shouldStickyButton ? stickyTop : offsetTop);
if (_deleteBtnParams) {
return _objectSpread(_objectSpread({}, _deleteBtnParams), {}, {
position: shouldStickyButton ? 'sticky' : undefined,
left: 0,
selectionType: selectionType
});
}
}
return null;
}
}
}
// Clean state if no type
if (prevState.selectionType !== selectionType) {
return {
selectionType: undefined,
top: 0,
left: 0,
indexes: []
};
}
// Do nothing if doesn't change anything
return null;
}
}]);
}(_react.Component);
(0, _defineProperty2.default)(FloatingDeleteButton, "displayName", 'FloatingDeleteButton');
var _default = exports.default = FloatingDeleteButton;