UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

166 lines (164 loc) 6.88 kB
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'; const DropListWithOutsideClickTargetRef = props => { const 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)); }; const DropListWithOutsideListeners = withReactEditorViewOuterListeners(DropListWithOutsideClickTargetRef); export const DropdownMenu = ({ items, section, disableKeyboardHandling, onItemActivated, handleClose, onMouseEnter, onMouseLeave, fitWidth, fitHeight, direction, mountPoint, boundariesElement, scrollableElement }) => { const [popupPlacement, setPopupPlacement] = useState(['bottom', 'left']); const [targetRefDiv, setTargetRefDiv] = useState(null); const handleRef = ref => { setTargetRefDiv(ref); }; // more offsets calculation as offsets depend on the direction and updated placement here const offsetY = direction === 'row' ? popupPlacement[0] === 'bottom' ? -8 : -34 : 0; const offsetX = direction === 'column' ? popupPlacement[1] === 'left' ? 0 : -7 : 0; const innerMenu = () => { return /*#__PURE__*/React.createElement(DropListWithOutsideListeners, { isOpen: true, shouldFitContainer: true, position: popupPlacement.join(' '), handleClickOutside: () => handleClose('editor'), handleEscapeKeydown: () => { if (!disableKeyboardHandling) { handleClose('handle'); } }, 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((group, index) => /*#__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(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 }); }))))); }; const onClose = useCallback(() => handleClose('handle'), [handleClose]); const onSelection = useCallback(index => { const results = items.flatMap(item => '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 const keys = ['row_numbers', 'header_row', 'header_column']; let doubleItemCount = 0; const firstIndex = results.findIndex(value => { const key = value.key; return key !== undefined && keys.includes(key); }); if (firstIndex === -1 || index <= firstIndex) { onItemActivated && onItemActivated({ item: results[index] }); return; } for (let i = firstIndex; i < results.length; i += 1) { const 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, onPlacementChanged: placement => { setPopupPlacement(placement); }, fitHeight: fitHeight, fitWidth: fitWidth, zIndex: akEditorFloatingPanelZIndex, 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()))) ); };