UNPKG

@atlaskit/editor-plugin-synced-block

Version:

SyncedBlock plugin for @atlaskit/editor-core

230 lines (227 loc) 13.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getToolbarConfig = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _analytics = require("@atlaskit/editor-common/analytics"); var _messages = _interopRequireWildcard(require("@atlaskit/editor-common/messages")); var _selection = require("@atlaskit/editor-common/selection"); var _ui = require("@atlaskit/editor-common/ui"); var _utils = require("@atlaskit/editor-prosemirror/utils"); var _consts = require("@atlaskit/editor-shared-styles/consts"); var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider"); var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy")); var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete")); var _edit = _interopRequireDefault(require("@atlaskit/icon/core/edit")); var _linkBroken = _interopRequireDefault(require("@atlaskit/icon/core/link-broken")); var _megaphone = _interopRequireDefault(require("@atlaskit/icon/core/megaphone")); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _editorCommands = require("../editor-commands"); var _utils2 = require("../pm-plugins/utils/utils"); var _types = require("../types"); var _SyncedLocationDropdown = require("./SyncedLocationDropdown"); 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); } 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; } var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(state, intl, api, syncBlockStore, isLivePage, onGiveFeedback) { var _syncBlockInstance$er, _api$decorations, _api$connectivity; var syncBlockObject = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(state.schema, state.selection); if (!syncBlockObject) { return; } if (syncBlockStore.sourceManager.isPendingCreation(syncBlockObject.node.attrs.resourceId)) { return; } var isSyncBlockActivationEnabled = (0, _expValEquals.expValEquals)('platform_editor_sync_block_activation', 'isEnabled', true); var syncBlockInstance = syncBlockStore.referenceManager.getFromCache(syncBlockObject.node.attrs.resourceId); var isUnsyncedBlock = (syncBlockInstance === null || syncBlockInstance === void 0 || (_syncBlockInstance$er = syncBlockInstance.error) === null || _syncBlockInstance$er === void 0 ? void 0 : _syncBlockInstance$er.type) === _editorSyncedBlockProvider.SyncBlockError.NotFound; var isErroredBlock = syncBlockInstance === null || syncBlockInstance === void 0 ? void 0 : syncBlockInstance.error; var bodiedSyncBlock = state.schema.nodes.bodiedSyncBlock; var isBodiedSyncBlock = (0, _utils2.isBodiedSyncBlockNode)(syncBlockObject.node, bodiedSyncBlock); var _syncBlockObject$node = syncBlockObject.node.attrs, resourceId = _syncBlockObject$node.resourceId, localId = _syncBlockObject$node.localId; var formatMessage = intl.formatMessage; var nodeType = syncBlockObject.node.type; var hoverDecoration = api === null || api === void 0 || (_api$decorations = api.decorations) === null || _api$decorations === void 0 ? void 0 : _api$decorations.actions.hoverDecoration; var hoverDecorationProps = function hoverDecorationProps(nodeType, className) { return { onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, true, className), onMouseLeave: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, false, className), onFocus: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, true, className), onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, false, className) }; }; var items = []; if (isUnsyncedBlock) { var deleteButton = _objectSpread({ type: 'button', title: formatMessage(_messages.default.delete), onClick: (0, _editorCommands.removeSyncedBlock)(api), icon: _delete.default, testId: _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceDelete }, hoverDecorationProps(nodeType, _consts.akEditorSelectedNodeClassName)); items.push(deleteButton); } else { // When the synced block activation experiment is enabled, the copy action is // re-framed as the primary "Copy to sync" action: it shows a visible label and // is moved to the first toolbar position (before the synced-location info). See // EDITOR-8060. var copyButton = _objectSpread({ id: 'editor.syncedBlock.copy', type: 'button', appearance: 'subtle', icon: _copy.default, title: isSyncBlockActivationEnabled ? formatMessage(_messages.syncBlockMessages.copyToSyncLabel) : formatMessage(_messages.syncBlockMessages.copySyncBlockLabel), showTitle: isSyncBlockActivationEnabled, tooltipContent: isSyncBlockActivationEnabled ? undefined : formatMessage(_messages.syncBlockMessages.copySyncedBlockTooltip), testId: isSyncBlockActivationEnabled ? _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarCopy : undefined, onClick: (0, _editorCommands.copySyncedBlockReferenceToClipboard)(syncBlockStore, _analytics.INPUT_METHOD.SYNCED_BLOCK_TB, api, isLivePage) }, hoverDecorationProps(nodeType, _consts.akEditorSelectedNodeClassName)); // In the activation experience the primary "Copy to sync" action leads the // toolbar, ahead of the informational synced-location dropdown. if (isSyncBlockActivationEnabled) { items.push(copyButton); } if (!isErroredBlock) { var syncedLocation = { type: 'custom', fallback: [], render: function render(_view, _idx, _dispatchAnalyticsEvent, floatingToolbarRenderContext) { if (isSyncBlockActivationEnabled) { return /*#__PURE__*/_react.default.createElement(_SyncedLocationDropdown.SyncedLocationDropdownWithCount, { key: "".concat(resourceId, ":").concat(localId, ":").concat(isBodiedSyncBlock), syncBlockStore: syncBlockStore, resourceId: resourceId, localId: localId, intl: intl, isSource: isBodiedSyncBlock, api: api, floatingToolbarRenderContext: floatingToolbarRenderContext }); } return /*#__PURE__*/_react.default.createElement(_SyncedLocationDropdown.SyncedLocationDropdown, { syncBlockStore: syncBlockStore, resourceId: resourceId, localId: localId, intl: intl, isSource: isBodiedSyncBlock, api: api, floatingToolbarRenderContext: floatingToolbarRenderContext }); } }; var unsyncButton = { type: 'custom', fallback: [], render: function render(view) { var _syncBlockInstance$da; return /*#__PURE__*/_react.default.createElement(_ui.FloatingToolbarButton, { areAnyNewToolbarFlagsEnabled: true, disabled: (syncBlockInstance === null || syncBlockInstance === void 0 || (_syncBlockInstance$da = syncBlockInstance.data) === null || _syncBlockInstance$da === void 0 ? void 0 : _syncBlockInstance$da.status) === 'unpublished', icon: /*#__PURE__*/_react.default.createElement(_linkBroken.default, { label: "" }), title: formatMessage(_messages.syncBlockMessages.unsyncButton) // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onClick: function onClick() { return (0, _editorCommands.unsync)(syncBlockStore, isBodiedSyncBlock, view); }, testId: isBodiedSyncBlock ? _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSourceUnsync : _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceUnsync }); } }; items.push(syncedLocation, unsyncButton); } // Outside the activation experience the copy button keeps its original // (icon-only, secondary) position after the synced-location info. if (!isSyncBlockActivationEnabled) { items.push(copyButton); } var disabled = !syncBlockStore.referenceManager.getSyncBlockURL(syncBlockObject.node.attrs.resourceId); if (!isBodiedSyncBlock) { var editSourceButton = _objectSpread({ id: 'editor.syncedBlock.editSource', type: 'button', disabled: disabled, appearance: 'subtle', icon: _edit.default, title: formatMessage(_messages.syncBlockMessages.editSourceLabel), showTitle: false, tooltipContent: disabled ? formatMessage(_messages.syncBlockMessages.editSourceTooltipDisabled) : formatMessage(_messages.syncBlockMessages.editSourceTooltip), onClick: (0, _editorCommands.editSyncedBlockSource)(syncBlockStore, api) }, hoverDecorationProps(nodeType, _consts.akEditorSelectedNodeClassName)); items.push(editSourceButton); } if (!isSyncBlockActivationEnabled) { var separator = { type: 'separator' }; var _deleteButton = _objectSpread({ id: 'editor.syncedBlock.delete', type: 'button', appearance: 'danger', title: formatMessage(_messages.default.delete), showTitle: false, tooltipContent: formatMessage(_messages.default.delete), onClick: (0, _editorCommands.removeSyncedBlock)(api), icon: _delete.default, testId: isBodiedSyncBlock ? _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSourceDelete : _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceDelete }, hoverDecorationProps(nodeType)); items.push(separator, _deleteButton); } else { // testId is required to show focus on trigger button on ESC key press // see hideOnEsc in platform/packages/editor/editor-plugin-floating-toolbar/src/ui/Dropdown.tsx var testId = isBodiedSyncBlock ? _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSourceOverflowTrigger : _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceOverflowTrigger; var overflowMenuConfig = [{ type: 'overflow-dropdown', testId: testId, options: [].concat((0, _toConsumableArray2.default)(isSyncBlockActivationEnabled && onGiveFeedback ? [{ title: formatMessage(_messages.toolbarInsertBlockMessages.feedbackDialog), icon: /*#__PURE__*/_react.default.createElement(_megaphone.default, { label: "" }), onClick: function onClick() { api === null || api === void 0 || api.core.actions.execute(function (_ref) { var tr = _ref.tr; return tr.setSelection(new _selection.GapCursorSelection(tr.doc.resolve(syncBlockObject.pos + syncBlockObject.node.nodeSize), _selection.Side.RIGHT)); }); onGiveFeedback({ blockType: isBodiedSyncBlock ? 'source' : 'reference', entryPoint: 'overflow-menu' }); return true; } }] : []), [_objectSpread({ title: formatMessage(_messages.default.delete), onClick: (0, _editorCommands.removeSyncedBlock)(api), icon: /*#__PURE__*/_react.default.createElement(_delete.default, { label: "" }), testId: isBodiedSyncBlock ? _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSourceDelete : _types.SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceDelete }, hoverDecorationProps(nodeType))]) }]; items.push.apply(items, overflowMenuConfig); } } var getDomRef = function getDomRef(editorView) { var domAtPos = editorView.domAtPos.bind(editorView); var element = (0, _utils.findDomRefAtPos)(syncBlockObject.pos, domAtPos); return element; }; return { title: 'Synced Block floating controls', getDomRef: getDomRef, nodeType: nodeType, items: items, scrollable: true, groupLabel: formatMessage(_messages.syncBlockMessages.syncBlockGroup), visible: (api === null || api === void 0 || (_api$connectivity = api.connectivity) === null || _api$connectivity === void 0 || (_api$connectivity = _api$connectivity.sharedState.currentState()) === null || _api$connectivity === void 0 ? void 0 : _api$connectivity.mode) !== 'offline' }; };