UNPKG

@atlaskit/editor-plugin-insert-block

Version:

Insert block plugin for @atlaskit/editor-core

251 lines (249 loc) 13.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.InsertButton = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireWildcard(require("react")); var _reactIntl = require("react-intl"); var _analytics = require("@atlaskit/editor-common/analytics"); var _keymaps = require("@atlaskit/editor-common/keymaps"); var _messages = require("@atlaskit/editor-common/messages"); var _toolbar = require("@atlaskit/editor-common/toolbar"); var _ui = require("@atlaskit/editor-common/ui"); var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector"); var _editorSharedStyles = require("@atlaskit/editor-shared-styles"); var _editorToolbar = require("@atlaskit/editor-toolbar"); var _InsertMenu = _interopRequireWildcard(require("../ElementBrowser/InsertMenu")); var _filterDropdownItems = require("./hooks/filterDropdownItems"); var _useEmojiPickerPopup = require("./hooks/useEmojiPickerPopup"); var _useInsertButtonState2 = require("./hooks/useInsertButtonState"); var _useTableSelectorPopup = require("./hooks/useTableSelectorPopup"); var _EmojiPickerPopup = require("./popups/EmojiPickerPopup"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } // This determines how the popup should fit. We prefer the insert menu // opening on the bottom as we have a search bar and should only open on // top if there is more than sufficient room. var FIT_HEIGHT_BUFFER = 100; var InsertButton = exports.InsertButton = function InsertButton(_ref) { var api = _ref.api, breakpoint = _ref.breakpoint, _ref$showElementBrows = _ref.showElementBrowserLink, showElementBrowserLink = _ref$showElementBrows === void 0 ? false : _ref$showElementBrows, _ref$isFullPageAppear = _ref.isFullPageAppearance, isFullPageAppearance = _ref$isFullPageAppear === void 0 ? false : _ref$isFullPageAppear, tableSelectorSupported = _ref.tableSelectorSupported, nativeStatusSupported = _ref.nativeStatusSupported, horizontalRuleEnabled = _ref.horizontalRuleEnabled, expandEnabled = _ref.expandEnabled, insertMenuItems = _ref.insertMenuItems, numberOfButtons = _ref.numberOfButtons, onInsertBlockType = _ref.onInsertBlockType, toolbarConfig = _ref.toolbarConfig; var _useEditorToolbar = (0, _toolbar.useEditorToolbar)(), editorView = _useEditorToolbar.editorView; var _useToolbarUI = (0, _editorToolbar.useToolbarUI)(), isDisabled = _useToolbarUI.isDisabled, popupsMountPoint = _useToolbarUI.popupsMountPoint, popupsBoundariesElement = _useToolbarUI.popupsBoundariesElement, popupsScrollableElement = _useToolbarUI.popupsScrollableElement; var _useIntl = (0, _reactIntl.useIntl)(), formatMessage = _useIntl.formatMessage; var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), insertMenuOpen = _useState2[0], setInsertMenuOpen = _useState2[1]; var insertButtonRef = (0, _react.useRef)(null); var emojiPickerPopup = (0, _useEmojiPickerPopup.useEmojiPickerPopup)({ api: api, buttonRef: insertButtonRef }); var tableSelectorPopup = (0, _useTableSelectorPopup.useTableSelectorPopup)({ api: api, buttonRef: insertButtonRef }); var showMediaPicker = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'media.showMediaPicker'); var _useInsertButtonState = (0, _useInsertButtonState2.useInsertButtonState)({ api: api, breakpoint: breakpoint, editorView: editorView || undefined, horizontalRuleEnabled: horizontalRuleEnabled, insertMenuItems: insertMenuItems, nativeStatusSupported: nativeStatusSupported, numberOfButtons: numberOfButtons, tableSelectorSupported: tableSelectorSupported, expandEnabled: expandEnabled, showElementBrowserLink: showElementBrowserLink, toolbarConfig: toolbarConfig }), dropdownItems = _useInsertButtonState.dropdownItems, emojiProvider = _useInsertButtonState.emojiProvider, isTypeAheadAllowed = _useInsertButtonState.isTypeAheadAllowed; if (!(api !== null && api !== void 0 && api.insertBlock)) { return null; } var toggleInsertMenuOpen = function toggleInsertMenuOpen(newState) { setInsertMenuOpen(newState); }; var onPopupUnmount = function onPopupUnmount() { requestAnimationFrame(function () { return api === null || api === void 0 ? void 0 : api.core.actions.focus(); }); }; var onClick = function onClick() { toggleInsertMenuOpen(!insertMenuOpen); }; var onItemActivated = function onItemActivated(_ref2) { var _api$core, _api$hyperlink, _api$imageUpload, _api$mention, _api$taskDecision, _api$rule, _api$core3, _api$date, _api$placeholderText, _api$layout, _api$core4, _api$status, _api$expand; var item = _ref2.item, inputMethod = _ref2.inputMethod; if (!editorView) { return; } var state = editorView.state, dispatch = editorView.dispatch; // need to do this before inserting nodes so scrollIntoView works properly if (!editorView.hasFocus()) { editorView.focus(); } switch (item.value.name) { case _filterDropdownItems.LINK_BUTTON_KEY: api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$hyperlink = api.hyperlink) === null || _api$hyperlink === void 0 ? void 0 : _api$hyperlink.commands.showLinkToolbar(inputMethod)); break; case 'table': // workaround to solve race condition where cursor is not placed correctly inside table queueMicrotask(function () { var _api$table, _api$table$actions$in, _api$table$actions; api === null || api === void 0 || (_api$table = api.table) === null || _api$table === void 0 || (_api$table$actions$in = (_api$table$actions = _api$table.actions).insertTable) === null || _api$table$actions$in === void 0 || _api$table$actions$in.call(_api$table$actions, { action: _analytics.ACTION.INSERTED, actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT, actionSubjectId: _analytics.ACTION_SUBJECT_ID.TABLE, attributes: { inputMethod: inputMethod }, eventType: _analytics.EVENT_TYPE.TRACK })(state, dispatch); }); break; case 'table selector': tableSelectorPopup.toggle(inputMethod); break; case 'image upload': if (api !== null && api !== void 0 && (_api$imageUpload = api.imageUpload) !== null && _api$imageUpload !== void 0 && _api$imageUpload.actions.startUpload) { api.imageUpload.actions.startUpload()(state, dispatch); } break; case 'media': if (showMediaPicker) { var _api$mediaInsert, _api$core2, _api$mediaInsert2; api !== null && api !== void 0 && (_api$mediaInsert = api.mediaInsert) !== null && _api$mediaInsert !== void 0 && _api$mediaInsert.commands.showMediaInsertPopup ? api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(api === null || api === void 0 || (_api$mediaInsert2 = api.mediaInsert) === null || _api$mediaInsert2 === void 0 ? void 0 : _api$mediaInsert2.commands.showMediaInsertPopup()) : showMediaPicker === null || showMediaPicker === void 0 ? void 0 : showMediaPicker(); } break; case 'mention': api === null || api === void 0 || (_api$mention = api.mention) === null || _api$mention === void 0 || (_api$mention = _api$mention.actions) === null || _api$mention === void 0 || _api$mention.openTypeAhead(inputMethod); break; case 'emoji': emojiPickerPopup.toggle(inputMethod); break; case 'codeblock': case 'blockquote': case 'panel': onInsertBlockType === null || onInsertBlockType === void 0 || onInsertBlockType(item.value.name)(state, dispatch); break; case 'action': case 'decision': var listType = item.value.name === 'action' ? 'taskList' : 'decisionList'; api === null || api === void 0 || (_api$taskDecision = api.taskDecision) === null || _api$taskDecision === void 0 || _api$taskDecision.actions.insertTaskDecision(listType, inputMethod)(state, dispatch); break; case 'horizontalrule': api === null || api === void 0 || (_api$rule = api.rule) === null || _api$rule === void 0 || _api$rule.actions.insertHorizontalRule(inputMethod)(state, dispatch); break; case 'date': api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 || (_api$date = api.date) === null || _api$date === void 0 || (_api$date = _api$date.commands) === null || _api$date === void 0 ? void 0 : _api$date.insertDate({ inputMethod: inputMethod })); break; case 'placeholder text': api === null || api === void 0 || (_api$placeholderText = api.placeholderText) === null || _api$placeholderText === void 0 || _api$placeholderText.actions.showPlaceholderFloatingToolbar(state, dispatch); break; case 'layout': api === null || api === void 0 || (_api$layout = api.layout) === null || _api$layout === void 0 || _api$layout.actions.insertLayoutColumns(inputMethod)(state, dispatch); break; case 'status': api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$status = api.status) === null || _api$status === void 0 || (_api$status = _api$status.commands) === null || _api$status === void 0 ? void 0 : _api$status.insertStatus(inputMethod)); break; case 'expand': api === null || api === void 0 || (_api$expand = api.expand) === null || _api$expand === void 0 || _api$expand.actions.insertExpand(state, dispatch); break; default: if (item && item.onClick) { item.onClick(); } break; } toggleInsertMenuOpen(false); }; var onInsert = function onInsert(_ref3) { var item = _ref3.item; onItemActivated({ item: item, inputMethod: _analytics.INPUT_METHOD.INSERT_MENU }); }; var toggleVisibility = function toggleVisibility() { toggleInsertMenuOpen(!insertMenuOpen); }; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, insertMenuOpen && insertButtonRef.current && editorView && /*#__PURE__*/_react.default.createElement(_ui.Popup, { target: insertButtonRef.current, fitHeight: _InsertMenu.DEFAULT_HEIGHT + FIT_HEIGHT_BUFFER, fitWidth: 350 // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , offset: [0, 3], mountTo: popupsMountPoint, boundariesElement: popupsBoundariesElement, scrollableElement: popupsScrollableElement, onUnmount: onPopupUnmount, focusTrap: true, zIndex: _editorSharedStyles.akEditorMenuZIndex, preventOverflow: true, alignX: "right" }, /*#__PURE__*/_react.default.createElement(_InsertMenu.default, { editorView: editorView, dropdownItems: dropdownItems, onInsert: onInsert, toggleVisiblity: toggleVisibility, showElementBrowserLink: showElementBrowserLink, pluginInjectionApi: api, isFullPageAppearance: isFullPageAppearance })), emojiProvider && /*#__PURE__*/_react.default.createElement(_EmojiPickerPopup.EmojiPickerPopup, { isOpen: emojiPickerPopup.isOpen, targetRef: insertButtonRef, emojiProvider: Promise.resolve(emojiProvider), onSelection: emojiPickerPopup.handleSelectedEmoji, onClickOutside: emojiPickerPopup.handleClickOutside, onEscapeKeydown: emojiPickerPopup.handleEscapeKeydown, onUnmount: emojiPickerPopup.onPopupUnmount, popupsMountPoint: popupsMountPoint, popupsBoundariesElement: popupsBoundariesElement, popupsScrollableElement: popupsScrollableElement }), /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarTooltip, { content: /*#__PURE__*/_react.default.createElement(_keymaps.ToolTipContent, { description: formatMessage(_messages.toolbarInsertBlockMessages.insertMenu), keymap: _keymaps.insertElements }) }, /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarButton, { iconBefore: /*#__PURE__*/_react.default.createElement(_editorToolbar.AddIcon, { size: "small", label: formatMessage(_messages.toolbarInsertBlockMessages.insertMenu) }), ariaKeyshortcuts: (0, _keymaps.getAriaKeyshortcuts)(_keymaps.insertElements), ref: insertButtonRef, onClick: onClick, isSelected: insertMenuOpen, isDisabled: !isTypeAheadAllowed || isDisabled, testId: _toolbar.TOOLBAR_BUTTON_TEST_ID.INSERT }))); };