UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

257 lines (254 loc) 13.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.DragHandle = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireWildcard(require("react")); var _classnames2 = _interopRequireDefault(require("classnames")); var _reactDom = _interopRequireDefault(require("react-dom")); var _reactIntl = require("react-intl"); var _browser = require("@atlaskit/editor-common/browser"); var _messages = require("@atlaskit/editor-common/messages"); var _state = require("@atlaskit/editor-prosemirror/state"); var _editorTables = require("@atlaskit/editor-tables"); var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter"); var _setCustomNativeDragPreview = require("@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _pluginFactory = require("../../pm-plugins/drag-and-drop/plugin-factory"); var _mergedCells = require("../../pm-plugins/utils/merged-cells"); var _types = require("../../types"); var _consts = require("../consts"); var _DragPreview = require("../DragPreview"); var _HandleIconComponent = require("./HandleIconComponent"); 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/no-html-button */ var DragHandleComponent = function DragHandleComponent(_ref) { var isDragMenuTarget = _ref.isDragMenuTarget, tableLocalId = _ref.tableLocalId, _ref$direction = _ref.direction, direction = _ref$direction === void 0 ? 'row' : _ref$direction, _ref$appearance = _ref.appearance, appearance = _ref$appearance === void 0 ? 'default' : _ref$appearance, indexes = _ref.indexes, _ref$forceDefaultHand = _ref.forceDefaultHandle, forceDefaultHandle = _ref$forceDefaultHand === void 0 ? false : _ref$forceDefaultHand, previewWidth = _ref.previewWidth, previewHeight = _ref.previewHeight, _onMouseOver = _ref.onMouseOver, _onMouseOut = _ref.onMouseOut, onFocus = _ref.onFocus, onBlur = _ref.onBlur, toggleDragMenu = _ref.toggleDragMenu, hoveredCell = _ref.hoveredCell, onClick = _ref.onClick, editorView = _ref.editorView, formatMessage = _ref.intl.formatMessage; var dragHandleDivRef = (0, _react.useRef)(null); var _useState = (0, _react.useState)(null), _useState2 = (0, _slicedToArray2.default)(_useState, 2), previewContainer = _useState2[0], setPreviewContainer = _useState2[1]; var state = editorView.state, selection = editorView.state.selection; var _getDnDPluginState = (0, _pluginFactory.getPluginState)(state), _getDnDPluginState$is = _getDnDPluginState.isDragMenuOpen, isDragMenuOpen = _getDnDPluginState$is === void 0 ? false : _getDnDPluginState$is; var _useState3 = (0, _react.useState)(false), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), isHovered = _useState4[0], setIsHovered = _useState4[1]; var isRow = direction === 'row'; var isColumn = direction === 'column'; var hasMergedCells = (0, _react.useMemo)(function () { var table = (0, _editorTables.findTable)(selection); if (!table) { return false; } var map = _editorTables.TableMap.get(table === null || table === void 0 ? void 0 : table.node); if (!map.hasMergedCells() || indexes.length < 1) { return false; } var mapByColumn = map.mapByColumn, mapByRow = map.mapByRow; // this handle when hover to first column or row which has merged cells. if (hoveredCell && hoveredCell.rowIndex !== undefined && hoveredCell.colIndex !== undefined && selection instanceof _state.TextSelection) { var rowIndex = hoveredCell.rowIndex, colIndex = hoveredCell.colIndex; var mergedPositionInRow = (0, _mergedCells.findDuplicatePosition)(mapByRow[rowIndex]); var mergedPositionInCol = (0, _mergedCells.findDuplicatePosition)(mapByColumn[colIndex]); var hasMergedCellsInFirstRowOrColumn = direction === 'column' ? mergedPositionInRow.includes(mapByRow[0][colIndex]) : mergedPositionInCol.includes(mapByColumn[0][rowIndex]); var isHoveredOnFirstRowOrColumn = direction === 'column' ? hoveredCell.rowIndex === 0 && hasMergedCellsInFirstRowOrColumn : hoveredCell.colIndex === 0 && hasMergedCellsInFirstRowOrColumn; if (isHoveredOnFirstRowOrColumn) { var mergedSizes = direction === 'column' ? mapByRow[0].filter(function (el) { return el === mapByRow[0][colIndex]; }).length : mapByColumn[0].filter(function (el) { return el === mapByColumn[0][rowIndex]; }).length; var mergedSelection = (0, _mergedCells.hasMergedCellsInSelection)(direction === 'column' ? [colIndex, colIndex + mergedSizes - 1] : [rowIndex, rowIndex + mergedSizes - 1], direction)(selection); return mergedSelection; } } return (0, _mergedCells.hasMergedCellsInSelection)(indexes, direction)(selection); }, [indexes, selection, direction, hoveredCell]); var handleIconProps = { forceDefaultHandle: forceDefaultHandle, isHandleHovered: isHovered, hasMergedCells: hasMergedCells }; (0, _react.useEffect)(function () { var dragHandleDivRefCurrent = dragHandleDivRef.current; var browser = (0, _browser.getBrowserInfo)(); if (dragHandleDivRefCurrent) { return (0, _adapter.draggable)({ element: dragHandleDivRefCurrent, canDrag: function canDrag() { return !hasMergedCells; }, getInitialData: function getInitialData() { return { localId: tableLocalId, type: "table-".concat(direction), indexes: indexes }; }, onGenerateDragPreview: function onGenerateDragPreview(_ref2) { var nativeSetDragImage = _ref2.nativeSetDragImage; (0, _setCustomNativeDragPreview.setCustomNativeDragPreview)({ getOffset: function getOffset(_ref3) { var container = _ref3.container; var rect = container.getBoundingClientRect(); if (browser.safari) { // See: https://product-fabric.atlassian.net/browse/ED-21442 // We need to ensure that the preview is not overlaying screen content when the snapshot is taken, otherwise // safari will composite the screen text elements into the bitmap snapshot. The container is a wrapper which is already // positioned fixed at top/left 0. // IMPORTANT: we must not exceed more then the width of the container off-screen otherwise not preview will // be generated. container.style.left = "-".concat(rect.width - 0.0001, "px"); } if (isRow) { return { x: 12, y: rect.height / 2 }; } else { return { x: rect.width / 2 + 4, y: 12 }; } }, render: function render(_ref4) { var container = _ref4.container; setPreviewContainer(container); return function () { return setPreviewContainer(null); }; }, nativeSetDragImage: nativeSetDragImage }); } }); } }, [tableLocalId, direction, indexes, isRow, editorView.state.selection, hasMergedCells]); var showDragMenuAnchorId = isRow ? 'drag-handle-button-row' : 'drag-handle-button-column'; var browser = (0, _browser.getBrowserInfo)(); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("button", { type: "button" // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: _types.TableCssClassName.DRAG_HANDLE_BUTTON_CLICKABLE_ZONE, "data-testid": "table-drag-handle-clickable-zone-button", style: { height: isRow ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 "calc(100% - ".concat(_consts.dragTableInsertColumnButtonSize, "px)") : "var(--ds-space-200, 16px)", // 16px here because it's the size of drag handle button's large side width: isRow ? "var(--ds-space-200, 16px)" // 16px here because it's the size of drag handle button's large side : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 "calc(100% - ".concat(_consts.dragTableInsertColumnButtonSize, "px)"), left: isRow ? "var(--ds-space-050, 4px)" : undefined, bottom: isColumn ? "var(--ds-space-0, 0px)" : undefined, alignSelf: isColumn ? 'none' : 'center', zIndex: isColumn ? '-1' : 'auto', // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop pointerEvents: 'auto' }, onMouseUp: function onMouseUp(e) { // should toggle menu if current drag menu open. // return focus to editor so copying table selections whilst still works, i cannot call e.preventDefault in a mousemove event as this stops dragstart events from firing // -> this is bad for a11y but is the current standard new copy/paste keyboard shortcuts should be introduced instead editorView.focus(); if (isDragMenuOpen) { toggleDragMenu && toggleDragMenu('mouse', e); } }, onClick: onClick, "aria-label": formatMessage(_messages.tableMessages.dragHandleZone) }), /*#__PURE__*/_react.default.createElement("button", { type: "button", id: isDragMenuTarget ? showDragMenuAnchorId : undefined // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: (0, _classnames2.default)(_types.TableCssClassName.DRAG_HANDLE_BUTTON_CONTAINER, appearance, (0, _defineProperty2.default)({}, _types.TableCssClassName.DRAG_HANDLE_DISABLED, hasMergedCells)), ref: dragHandleDivRef, style: { transform: isColumn ? 'none' : 'rotate(90deg)', alignSelf: isColumn ? 'none' : 'center' }, "data-testid": "table-drag-handle-button", "aria-label": formatMessage(isRow ? _messages.tableMessages.rowDragHandle : _messages.tableMessages.columnDragHandle), "aria-expanded": isDragMenuOpen && isDragMenuTarget ? 'true' : 'false', "aria-haspopup": "menu", onMouseOver: function onMouseOver(e) { setIsHovered(true); _onMouseOver && _onMouseOver(e); }, onMouseOut: function onMouseOut(e) { setIsHovered(false); _onMouseOut && _onMouseOut(e); }, onFocus: (0, _expValEquals.expValEquals)('platform_editor_table_a11y_eslint_fix', 'isEnabled', true) ? function (e) { onFocus && onFocus(e); } : undefined, onBlur: (0, _expValEquals.expValEquals)('platform_editor_table_a11y_eslint_fix', 'isEnabled', true) ? function (e) { onBlur && onBlur(e); } : undefined, onMouseUp: function onMouseUp(e) { // return focus to editor so copying table selections whilst still works, i cannot call e.preventDefault in a mousemove event as this stops dragstart events from firing // -> this is bad for a11y but is the current standard new copy/paste keyboard shortcuts should be introduced instead editorView.focus(); toggleDragMenu && toggleDragMenu('mouse', e); }, onClick: onClick, onKeyDown: function onKeyDown(e) { if (e.key === 'Enter' || e.key === ' ') { toggleDragMenu && toggleDragMenu('keyboard'); } } }, appearance !== 'placeholder' ? // cannot block pointer events in Firefox as it breaks Dragging functionality browser.gecko ? /*#__PURE__*/ // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading _react.default.createElement(_HandleIconComponent.HandleIconComponent, handleIconProps) : /*#__PURE__*/ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 _react.default.createElement("span", { style: { pointerEvents: 'none' } }, /*#__PURE__*/_react.default.createElement(_HandleIconComponent.HandleIconComponent // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , handleIconProps)) : null), previewContainer && previewWidth !== undefined && previewHeight !== undefined && /*#__PURE__*/_reactDom.default.createPortal( /*#__PURE__*/_react.default.createElement(_DragPreview.DragPreview, { direction: direction, width: previewWidth, height: previewHeight }), previewContainer)); }; var DragHandle = exports.DragHandle = (0, _reactIntl.injectIntl)(DragHandleComponent);