@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
264 lines (258 loc) • 11.3 kB
JavaScript
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;