UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

324 lines (318 loc) 16.1 kB
"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;