@atlaskit/editor-plugin-insert-block
Version:
Insert block plugin for @atlaskit/editor-core
233 lines (231 loc) • 12.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sortFeaturedItems = exports.default = exports.DEFAULT_HEIGHT = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = require("react");
var _react2 = require("@emotion/react");
var _CellMeasurer = require("react-virtualized/dist/commonjs/CellMeasurer");
var _enums = require("@atlaskit/editor-common/analytics/types/enums");
var _assets = require("@atlaskit/editor-common/assets");
var _isOfflineMode = require("@atlaskit/editor-common/connectivity/isOfflineMode");
var _constants = require("@atlaskit/editor-common/element-browser/constants");
var _ElementBrowserLoader = _interopRequireDefault(require("@atlaskit/editor-common/element-browser/ElementBrowserLoader"));
var _uiReact = require("@atlaskit/editor-common/ui-react");
var _withReactEditorViewOuterListeners = _interopRequireDefault(require("@atlaskit/editor-common/ui-react/with-react-editor-view-outer-listeners"));
var _useSharedPluginStateWithSelector = require("@atlaskit/editor-common/useSharedPluginStateWithSelector");
var _excluded = ["children"];
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) { (0, _defineProperty2.default)(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
*/ /* eslint-disable @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports, jsdoc/require-description -- Ignored via go/DSP-18766; jsdoc debt surfaced by this mechanical PR */
var DEFAULT_HEIGHT = exports.DEFAULT_HEIGHT = 560;
/**
* Sort featured elements by priority, matching the quick insert menu.
*/
var sortFeaturedItems = exports.sortFeaturedItems = function sortFeaturedItems(featuredItems) {
return featuredItems.slice(0).sort(function (a, b) {
var _a$priority, _b$priority;
return ((_a$priority = a.priority) !== null && _a$priority !== void 0 ? _a$priority : Number.POSITIVE_INFINITY) - ((_b$priority = b.priority) !== null && _b$priority !== void 0 ? _b$priority : Number.POSITIVE_INFINITY);
});
};
var selector = function selector(states) {
var _states$connectivityS;
return {
connectivityMode: (_states$connectivityS = states.connectivityState) === null || _states$connectivityS === void 0 ? void 0 : _states$connectivityS.mode
};
};
var InsertMenu = function InsertMenu(_ref) {
var _pluginInjectionApi$q6, _pluginInjectionApi$q7;
var editorView = _ref.editorView,
dropdownItems = _ref.dropdownItems,
showElementBrowserLink = _ref.showElementBrowserLink,
onInsert = _ref.onInsert,
toggleVisiblity = _ref.toggleVisiblity,
pluginInjectionApi = _ref.pluginInjectionApi;
var _useState = (0, _react.useState)(0),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
itemCount = _useState2[0],
setItemCount = _useState2[1];
var _useState3 = (0, _react.useState)(DEFAULT_HEIGHT),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
height = _useState4[0],
setHeight = _useState4[1];
var cache = (0, _react.useMemo)(function () {
return new _CellMeasurer.CellMeasurerCache({
fixedWidth: true,
defaultHeight: _constants.ELEMENT_ITEM_HEIGHT,
minHeight: _constants.ELEMENT_ITEM_HEIGHT
});
}, []);
(0, _react.useLayoutEffect)(function () {
// Figure based on visuals to exclude the searchbar, padding/margin, and the ViewMore item.
var EXTRA_SPACE_EXCLUDING_ELEMENTLIST = 128;
var totalItemHeight =
// eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed)
(0, _toConsumableArray2.default)(Array(itemCount)).reduce(function (sum, _, index) {
return sum + cache.rowHeight({
index: index
});
}, 0) + EXTRA_SPACE_EXCLUDING_ELEMENTLIST;
if (itemCount > 0 && totalItemHeight < DEFAULT_HEIGHT) {
setHeight(totalItemHeight);
} else {
setHeight(DEFAULT_HEIGHT);
}
}, [cache, itemCount]);
var transform = (0, _react.useCallback)(function (item) {
return {
title: item.content,
description: item.tooltipDescription,
keyshortcut: item.shortcut,
icon: function icon() {
return getSvgIconForItem({
name: item.value.name
}) || item.elemBefore;
},
/**
* @note This transformed items action is only used when a quick insert item has been
* called from the quick insert menu and a search has not been performed.
*/
action: function action() {
return onInsert({
item: item
});
},
// "insertInsertMenuItem" expects these 2 properties.
onClick: item.onClick,
value: item.value
};
}, [onInsert]);
var quickInsertDropdownItems = dropdownItems.map(transform);
var onInsertItem = (0, _react.useCallback)(function (item) {
var _pluginInjectionApi$q;
toggleVisiblity();
if (!editorView.hasFocus()) {
editorView.focus();
}
pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$q = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q === void 0 || _pluginInjectionApi$q.actions.insertItem(item, _enums.INPUT_METHOD.TOOLBAR)(editorView.state, editorView.dispatch);
}, [editorView, toggleVisiblity, pluginInjectionApi]);
var _useSharedPluginState = (0, _useSharedPluginStateWithSelector.useSharedPluginStateWithSelector)(pluginInjectionApi, ['connectivity'], selector),
connectivityMode = _useSharedPluginState.connectivityMode;
var getItems = (0, _react.useCallback)(function (query, category) {
var result;
/**
* @warning The results if there is a query are not the same as the results if there is no query.
* For example: If you have a typed panel and then select the panel item then it will call a different action
* than is specified on the editor plugins quick insert
* @see above transform function for more details.
*/
if (query) {
var _pluginInjectionApi$q2, _pluginInjectionApi$q3;
result = (_pluginInjectionApi$q2 = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$q3 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q3 === void 0 || (_pluginInjectionApi$q3 = _pluginInjectionApi$q3.actions.getSuggestions({
query: query,
category: category
})) === null || _pluginInjectionApi$q3 === void 0 ? void 0 : _pluginInjectionApi$q3.map(function (item) {
return (0, _isOfflineMode.isOfflineMode)(connectivityMode) && item.isDisabledOffline ? _objectSpread(_objectSpread({}, item), {}, {
isDisabled: true
}) : item;
})) !== null && _pluginInjectionApi$q2 !== void 0 ? _pluginInjectionApi$q2 : [];
} else {
var _pluginInjectionApi$q4, _pluginInjectionApi$q5;
var featuredQuickInsertSuggestions = (_pluginInjectionApi$q4 = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$q5 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q5 === void 0 || (_pluginInjectionApi$q5 = _pluginInjectionApi$q5.actions.getSuggestions({
category: category,
featuredItems: true
})) === null || _pluginInjectionApi$q5 === void 0 ? void 0 : _pluginInjectionApi$q5.map(function (item) {
return (0, _isOfflineMode.isOfflineMode)(connectivityMode) && item.isDisabledOffline ? _objectSpread(_objectSpread({}, item), {}, {
isDisabled: true
}) : item;
})) !== null && _pluginInjectionApi$q4 !== void 0 ? _pluginInjectionApi$q4 : [];
var unfilteredResult = quickInsertDropdownItems.concat(featuredQuickInsertSuggestions);
// need to sort on the concatenated list so desired elements are at the top
result = sortFeaturedItems(unfilteredResult);
}
setItemCount(result.length);
return result;
}, [pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$q6 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q6 === void 0 ? void 0 : _pluginInjectionApi$q6.actions, quickInsertDropdownItems, connectivityMode]);
var emptyStateHandler = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$q7 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q7 === void 0 || (_pluginInjectionApi$q7 = _pluginInjectionApi$q7.sharedState.currentState()) === null || _pluginInjectionApi$q7 === void 0 ? void 0 : _pluginInjectionApi$q7.emptyStateHandler;
var onViewMore = (0, _react.useCallback)(function () {
var _pluginInjectionApi$c, _pluginInjectionApi$q8;
toggleVisiblity();
pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c = pluginInjectionApi.core) === null || _pluginInjectionApi$c === void 0 || _pluginInjectionApi$c.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$q8 = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q8 === void 0 ? void 0 : _pluginInjectionApi$q8.commands.openElementBrowserModal);
}, [pluginInjectionApi, toggleVisiblity]);
return (
// eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
(0, _react2.jsx)("div", {
css: insertMenuWrapper(height)
}, (0, _react2.jsx)(ElementBrowserWrapper, {
handleClickOutside: toggleVisiblity,
handleEscapeKeydown: toggleVisiblity,
closeOnTab: false
}, (0, _react2.jsx)(_ElementBrowserLoader.default, {
mode: "inline",
getItems: getItems,
emptyStateHandler: emptyStateHandler,
onInsertItem: onInsertItem,
showSearch: true,
showCategories: false
// On page resize we want the InlineElementBrowser to show updated tools/overflow items
,
key: quickInsertDropdownItems.length,
onViewMore: showElementBrowserLink ? onViewMore : undefined,
cache: cache
})))
);
};
var getSvgIconForItem = function getSvgIconForItem(_ref2) {
var name = _ref2.name;
var Icon = {
codeblock: _assets.IconCode,
panel: _assets.IconPanel,
blockquote: _assets.IconQuote,
decision: _assets.IconDecision,
horizontalrule: _assets.IconDivider,
expand: _assets.IconExpand,
date: _assets.IconDate,
status: _assets.IconStatus
}[name];
return Icon ? (0, _react2.jsx)(Icon, {
label: ""
}) : undefined;
};
var insertMenuWrapper = function insertMenuWrapper(height) {
return (0, _react2.css)({
display: 'flex',
flexDirection: 'column',
width: '320px',
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
height: "".concat(height, "px"),
backgroundColor: "var(--ds-surface-overlay, #FFFFFF)",
borderRadius: "var(--ds-radius-small, 3px)",
boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)"
});
};
var flexWrapperStyles = (0, _react2.css)({
display: 'flex',
flex: 1,
boxSizing: 'border-box',
overflow: 'hidden'
});
var FlexWrapper = function FlexWrapper(props) {
var setOutsideClickTargetRef = (0, _react.useContext)(_uiReact.OutsideClickTargetRefContext);
var children = props.children,
divProps = (0, _objectWithoutProperties2.default)(props, _excluded);
return (
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
(0, _react2.jsx)("div", (0, _extends2.default)({
ref: setOutsideClickTargetRef,
css: flexWrapperStyles
}, divProps), children)
);
};
var ElementBrowserWrapper = (0, _withReactEditorViewOuterListeners.default)(FlexWrapper);
var _default = exports.default = InsertMenu;