UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

264 lines (258 loc) • 11.3 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; 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) { _defineProperty(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; } /** * @jsxRuntime classic * @jsx jsx */ import { useCallback, useEffect, useRef, useState } from 'react'; // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports -- Ignored via go/DSP-18766; jsx required at runtime for @jsxRuntime classic import { css, jsx } from '@emotion/react'; import { bind } from 'bind-event-listener'; import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import { withReactEditorViewOuterListeners as withOuterListeners } from '../../ui-react'; import Popup from '../Popup'; import tableSelectorPopup, { TABLE_SELECTOR_BUTTON_GAP, TABLE_SELECTOR_BUTTON_SIZE } from './table-selector'; var TABLE_SELECTOR_PADDING_TOP = 8; var POPUP_OFFSET = [0, 3]; var TABLE_SELECTOR_PADDING_SIDE = 10; var DEFAULT_TABLE_SELECTOR_ROWS = 5; var DEFAULT_TABLE_SELECTOR_COLS = 10; var DEFAULT_TABLE_SELECTOR_SELECTION_SIZE = 1; var DEFAULT_MAX_TABLE_SELECTOR_ROWS = 10; var TableSelectorWithListeners = withOuterListeners(tableSelectorPopup); var initialSizeState = { col: DEFAULT_TABLE_SELECTOR_SELECTION_SIZE, row: DEFAULT_TABLE_SELECTOR_SELECTION_SIZE, maxCol: DEFAULT_TABLE_SELECTOR_COLS, maxRow: DEFAULT_TABLE_SELECTOR_ROWS }; var tableSelectorPopupWrapperStyles = css({ borderRadius: "var(--ds-radius-small, 3px)", backgroundColor: "var(--ds-surface-overlay, #FFFFFF)", boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)", padding: "var(--ds-space-100, 8px)".concat(" ", TABLE_SELECTOR_PADDING_SIDE, "px") }); export var TableSelectorPopup = function TableSelectorPopup(props) { var _useState = useState(_objectSpread(_objectSpread({}, initialSizeState), props.defaultSize)), _useState2 = _slicedToArray(_useState, 2), size = _useState2[0], setSize = _useState2[1]; var tablePopupRef = useRef(null); // If popup opened by keyboard enable keyboard mode var isKeyboardMode = useRef(props.isOpenedByKeyboard); var enableKeyboardMode = useCallback(function () { if (!isKeyboardMode.current) { isKeyboardMode.current = true; } }, [isKeyboardMode]); var disableKeyboardMode = useCallback(function () { if (isKeyboardMode.current) { isKeyboardMode.current = false; } }, [isKeyboardMode]); // Mouse move is used to allow selection changes outside of the popup and is more reactive to changes. var handleMouseMove = useCallback(function (e) { if (!tablePopupRef.current) { return; } disableKeyboardMode(); var tablePopup = tablePopupRef.current; var _tablePopup$getBoundi = tablePopup.getBoundingClientRect(), left = _tablePopup$getBoundi.left, top = _tablePopup$getBoundi.top; // Mouse position on popup var selectedWidth = e.clientX - left; var selectedHeight = e.clientY - top; // Calculate number grid cells selected var selectedGridCols = Math.ceil((selectedWidth - TABLE_SELECTOR_PADDING_SIDE + TABLE_SELECTOR_BUTTON_GAP) / (TABLE_SELECTOR_BUTTON_GAP + TABLE_SELECTOR_BUTTON_SIZE)); var selectedGridRows = Math.ceil((selectedHeight - TABLE_SELECTOR_PADDING_TOP + TABLE_SELECTOR_BUTTON_GAP) / (TABLE_SELECTOR_BUTTON_GAP + TABLE_SELECTOR_BUTTON_SIZE)); // Keep the selected rows and columns within the defined bounds var gridRows = DEFAULT_TABLE_SELECTOR_ROWS; if (selectedGridCols < 1) { selectedGridCols = 1; } if (selectedGridCols > size.maxCol) { selectedGridCols = size.maxCol; } if (selectedGridRows < 1) { selectedGridRows = 1; } // Expand grid when row selection is greater than the default grid size if (selectedGridRows >= DEFAULT_TABLE_SELECTOR_ROWS && selectedGridRows < DEFAULT_MAX_TABLE_SELECTOR_ROWS) { gridRows = selectedGridRows + 1; } if (selectedGridRows >= DEFAULT_MAX_TABLE_SELECTOR_ROWS) { selectedGridRows = DEFAULT_MAX_TABLE_SELECTOR_ROWS; gridRows = DEFAULT_MAX_TABLE_SELECTOR_ROWS; } if (selectedGridCols !== size.col || selectedGridRows !== size.row) { setSize({ col: selectedGridCols, row: selectedGridRows, maxCol: DEFAULT_TABLE_SELECTOR_COLS, maxRow: gridRows }); } }, [disableKeyboardMode, size, setSize]); var decreasingSequence = function decreasingSequence(maxNumber, prevNumber) { var nextNumber = prevNumber - 1; if (prevNumber === 1) { nextNumber = maxNumber; } return nextNumber; }; var getMaxRow = function getMaxRow(prevSize, eventKey) { switch (eventKey) { case 'ArrowDown': // Expand the grid size when last row selected if (prevSize.maxRow < DEFAULT_MAX_TABLE_SELECTOR_ROWS && prevSize.row >= DEFAULT_TABLE_SELECTOR_ROWS - 1) { return prevSize.maxRow + 1; } if (prevSize.row === DEFAULT_MAX_TABLE_SELECTOR_ROWS) { return DEFAULT_TABLE_SELECTOR_ROWS; } return prevSize.maxRow; case 'ArrowLeft': var moveToPrevRow = prevSize.col === 1 && prevSize.row > 1; var moveToLastRow = prevSize.row === 1 && prevSize.col === 1; // Expand the popup to max size when selected row wraps around to last row if (moveToLastRow) { return DEFAULT_MAX_TABLE_SELECTOR_ROWS; } // Decrease the popup when decreased row selection if (prevSize.maxRow > DEFAULT_TABLE_SELECTOR_ROWS && moveToPrevRow) { return prevSize.row; } return prevSize.maxRow; case 'ArrowUp': if (prevSize.row === 1) { return DEFAULT_MAX_TABLE_SELECTOR_ROWS; // Decrease the popup size when decreased row selection } else if (prevSize.maxRow > DEFAULT_TABLE_SELECTOR_ROWS) { return prevSize.row; } return prevSize.maxRow; case 'ArrowRight': var moveToNextRow = prevSize.col === DEFAULT_TABLE_SELECTOR_COLS; var increaseMaxRow = prevSize.maxRow < DEFAULT_MAX_TABLE_SELECTOR_ROWS && moveToNextRow && prevSize.row + 1 === prevSize.maxRow; // Decrease popup size for wrap around to selection 1 x 1 if (prevSize.row === DEFAULT_MAX_TABLE_SELECTOR_ROWS && prevSize.col === DEFAULT_TABLE_SELECTOR_COLS) { return DEFAULT_TABLE_SELECTOR_ROWS; // Decrease the popup size when decreased row selection } else if (increaseMaxRow) { return prevSize.maxRow + 1; } return prevSize.maxRow; default: return prevSize.maxRow; } }; var handleInitialButtonFocus = useCallback(function () { if (isKeyboardMode.current !== true) { enableKeyboardMode(); setSize(initialSizeState); } }, [enableKeyboardMode, setSize]); var handleKeyDown = useCallback( // eslint-disable-next-line @typescript-eslint/no-explicit-any function (event) { if (event.key === 'ArrowDown') { enableKeyboardMode(); setSize(function (prevSize) { return _objectSpread(_objectSpread({}, prevSize), {}, { row: prevSize.row % prevSize.maxRow + 1, maxRow: getMaxRow(prevSize, event.key) }); }); if (editorExperiment('platform_editor_controls', 'variant1')) { event.preventDefault(); } } if (event.key === 'ArrowRight') { enableKeyboardMode(); setSize(function (prevSize) { var moveToNextRow = prevSize.col === DEFAULT_TABLE_SELECTOR_COLS; return _objectSpread(_objectSpread({}, prevSize), {}, { col: prevSize.col % DEFAULT_TABLE_SELECTOR_COLS + 1, row: moveToNextRow ? prevSize.row % prevSize.maxRow + 1 : prevSize.row, maxRow: getMaxRow(prevSize, event.key) }); }); } if (event.key === 'ArrowLeft') { enableKeyboardMode(); setSize(function (prevSize) { var getRow = function getRow(prevRow, prevCol) { var row = prevRow; // Move to previous row for wrap around if (prevSize.col === 1 && prevSize.row > 1) { return prevRow - 1; // Increase the selection to max size when selected row and column wraps around } else if (prevRow === 1 && prevCol === 1) { return DEFAULT_MAX_TABLE_SELECTOR_ROWS; } return row; }; return _objectSpread(_objectSpread({}, prevSize), {}, { col: decreasingSequence(prevSize.maxCol, prevSize.col), row: getRow(prevSize.row, prevSize.col), maxRow: getMaxRow(prevSize, event.key) }); }); } if (event.key === 'ArrowUp') { enableKeyboardMode(); setSize(function (prevSize) { var moveToLastRow = prevSize.row === 1; return _objectSpread(_objectSpread({}, prevSize), {}, { row: moveToLastRow ? DEFAULT_MAX_TABLE_SELECTOR_ROWS : decreasingSequence(prevSize.maxRow, prevSize.row), maxRow: getMaxRow(prevSize, event.key) }); }); if (editorExperiment('platform_editor_controls', 'variant1')) { event.preventDefault(); } } }, [enableKeyboardMode, setSize]); useEffect(function () { var unbind; var target = props.allowOutsideSelection ? window : tablePopupRef.current; if (target) { unbind = bind(target, { type: 'mousemove', listener: handleMouseMove }); } return unbind; }, [handleMouseMove, props.allowOutsideSelection, tablePopupRef]); var offset = expValEquals('platform_editor_perf_lint_cleanup', 'isEnabled', true) ? POPUP_OFFSET : [0, 3]; return jsx(Popup, { target: props.target, offset: offset, mountTo: props.popupsMountPoint, boundariesElement: props.popupsBoundariesElement, scrollableElement: props.popupsScrollableElement, focusTrap: true, onUnmount: props.onUnmount, zIndex: akEditorMenuZIndex }, jsx("div", { css: tableSelectorPopupWrapperStyles, ref: tablePopupRef }, jsx(TableSelectorWithListeners, { handleClickOutside: props.handleClickOutside, handleEscapeKeydown: props.handleEscapeKeydown, maxCols: size.maxCol, maxRows: size.maxRow, onSelection: props.onSelection, selectedCol: size.col, selectedRow: size.row, onKeyDown: handleKeyDown, isFocused: isKeyboardMode.current, handleInitialButtonFocus: handleInitialButtonFocus }))); }; export default TableSelectorPopup;