UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

190 lines (188 loc) 8.39 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _extends from "@babel/runtime/helpers/extends"; /* eslint-disable @atlaskit/design-system/prefer-primitives */ import React, { useCallback, useState } from 'react'; import { DropList, Popup } from '@atlaskit/editor-common/ui'; import { ArrowKeyNavigationProvider, ArrowKeyNavigationType, DropdownMenuItem } from '@atlaskit/editor-common/ui-menu'; import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react'; import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles'; import { MenuGroup, Section } from '@atlaskit/menu'; import { dragMenuDropdownWidth } from '../consts'; var DropListWithOutsideClickTargetRef = function DropListWithOutsideClickTargetRef(props) { var setOutsideClickTargetRef = React.useContext(OutsideClickTargetRefContext); // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading return /*#__PURE__*/React.createElement(DropList, _extends({ onDroplistRef: setOutsideClickTargetRef }, props)); }; var DropListWithOutsideListeners = withReactEditorViewOuterListeners(DropListWithOutsideClickTargetRef); export var DropdownMenu = function DropdownMenu(_ref) { var items = _ref.items, section = _ref.section, disableKeyboardHandling = _ref.disableKeyboardHandling, onItemActivated = _ref.onItemActivated, handleClose = _ref.handleClose, onMouseEnter = _ref.onMouseEnter, onMouseLeave = _ref.onMouseLeave, fitWidth = _ref.fitWidth, fitHeight = _ref.fitHeight, direction = _ref.direction, mountPoint = _ref.mountPoint, boundariesElement = _ref.boundariesElement, scrollableElement = _ref.scrollableElement; var _useState = useState(['bottom', 'left']), _useState2 = _slicedToArray(_useState, 2), popupPlacement = _useState2[0], setPopupPlacement = _useState2[1]; var _useState3 = useState(null), _useState4 = _slicedToArray(_useState3, 2), targetRefDiv = _useState4[0], setTargetRefDiv = _useState4[1]; var handleRef = function handleRef(ref) { setTargetRefDiv(ref); }; // more offsets calculation as offsets depend on the direction and updated placement here var offsetY = direction === 'row' ? popupPlacement[0] === 'bottom' ? -8 : -34 : 0; var offsetX = direction === 'column' ? popupPlacement[1] === 'left' ? 0 : -7 : 0; var innerMenu = function innerMenu() { return /*#__PURE__*/React.createElement(DropListWithOutsideListeners, { isOpen: true, shouldFitContainer: true, position: popupPlacement.join(' ') // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleClickOutside: function handleClickOutside() { return handleClose('editor'); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleEscapeKeydown: function handleEscapeKeydown() { if (!disableKeyboardHandling) { handleClose('handle'); } } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleEnterKeydown: function handleEnterKeydown(e) { if (!disableKeyboardHandling) { e.preventDefault(); e.stopPropagation(); } }, targetRef: targetRefDiv }, /*#__PURE__*/React.createElement("div", { style: { height: 0, minWidth: dragMenuDropdownWidth } }), /*#__PURE__*/React.createElement(MenuGroup, { role: "menu" }, items.map(function (group, index) { return /*#__PURE__*/React.createElement(Section, { hasSeparator: (section === null || section === void 0 ? void 0 : section.hasSeparator) && index > 0, title: section === null || section === void 0 ? void 0 : section.title // Ignored via go/ees005 // eslint-disable-next-line react/no-array-index-key , key: index }, group.items.map(function (item) { var _item$key; return /*#__PURE__*/React.createElement(DropdownMenuItem, { shouldUseDefaultRole: false, key: (_item$key = item.key) !== null && _item$key !== void 0 ? _item$key : String(item.content), item: item, onItemActivated: onItemActivated, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave }); })); }))); }; var onClose = useCallback(function () { return handleClose('handle'); }, [handleClose]); var onSelection = useCallback(function (index) { var results = items.flatMap(function (item) { return 'items' in item ? item.items : item; }); // onSelection is called when any focusable element is 'activated' // this is an issue as some menu items have toggles, which cause the index value // in the callback to be outside of array length. // The logic below normalises the index value based on the number // of menu items with 2 focusable elements, and adjusts the index to ensure // the correct menu item is sent in onItemActivated callback var keys = ['row_numbers', 'header_row', 'header_column']; var doubleItemCount = 0; var firstIndex = results.findIndex(function (value) { var key = value.key; return key !== undefined && keys.includes(key); }); if (firstIndex === -1 || index <= firstIndex) { onItemActivated && onItemActivated({ item: results[index] }); return; } for (var i = firstIndex; i < results.length; i += 1) { var key = results[i].key; if (key !== undefined && keys.includes(key)) { doubleItemCount += 1; } if (firstIndex % 2 === 0 && index - doubleItemCount === i) { onItemActivated && onItemActivated({ item: results[i] }); return; } if (firstIndex % 2 === 1 && index - doubleItemCount === i) { onItemActivated && onItemActivated({ item: results[i] }); return; } } }, [items, onItemActivated]); return ( /*#__PURE__*/ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 React.createElement("div", { className: "drag-dropdown-menu-wrapper" }, /*#__PURE__*/React.createElement("div", { className: "drag-dropdown-menu-popup-ref", ref: handleRef }), /*#__PURE__*/React.createElement(Popup // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting , { target: targetRefDiv, mountTo: mountPoint, boundariesElement: boundariesElement, scrollableElement: scrollableElement // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onPlacementChanged: function onPlacementChanged(placement) { setPopupPlacement(placement); }, fitHeight: fitHeight, fitWidth: fitWidth, zIndex: akEditorFloatingPanelZIndex // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , offset: [offsetX, offsetY], allowOutOfBounds: true // required as this popup is child of a parent popup, should be allowed to be out of bound of the parent popup, otherwise horizontal offset is not right }, /*#__PURE__*/React.createElement(ArrowKeyNavigationProvider, { closeOnTab: !disableKeyboardHandling, type: ArrowKeyNavigationType.MENU, handleClose: onClose, onSelection: onSelection // disableKeyboardHandling is linked with isSubmenuOpen in DragMenu // When isSubmenuOpen is true, the background color picker palette is open, and the picker is a ColorPaletteArrowKeyNavigationProvider // At the same time the MenuArrowKeyNavigationProvider are renderer too, as it is the wrapper for all other DragMenu items // In this case we want the ColorPaletteArrowKeyNavigationProvider to handle the keyboard event, not the MenuArrowKeyNavigationProvider // Hence set disableArrowKeyNavigation to true when disableKeyboardHandling is true , disableArrowKeyNavigation: disableKeyboardHandling }, innerMenu()))) ); };