UNPKG

@atlaskit/editor-common

Version:

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

319 lines (315 loc) • 14.5 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; 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; } import React from 'react'; import { NodeSelection } from '@atlaskit/editor-prosemirror/state'; import { hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils'; import { DEFAULT_EMBED_CARD_WIDTH } from '@atlaskit/editor-shared-styles'; import AlignImageCenterIcon from '@atlaskit/icon/core/align-image-center'; import AlignImageLeftIcon from '@atlaskit/icon/core/align-image-left'; import AlignImageRightIcon from '@atlaskit/icon/core/align-image-right'; import AlignTextCenterIcon from '@atlaskit/icon/core/align-text-center'; import AlignTextLeftIcon from '@atlaskit/icon/core/align-text-left'; import AlignTextRightIcon from '@atlaskit/icon/core/align-text-right'; import ContentWidthWide from '@atlaskit/icon/core/content-width-wide'; import ContentWrapLeftIcon from '@atlaskit/icon/core/content-wrap-left'; import ContentWrapRightIcon from '@atlaskit/icon/core/content-wrap-right'; import FullWidthIcon from '@atlaskit/icon/core/expand-horizontal'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '../../analytics'; import { insideTable } from '../../core-utils'; import { alignCenter, alignLeft, alignRight, tooltip } from '../../keymaps'; import commonMessages, { mediaAndEmbedToolbarMessages as toolbarMessages } from '../../messages'; import { Shortcut } from '../../ui'; import { alignAttributes, isInLayoutColumn, nonWrappedLayouts } from '../../utils'; // Workaround as we don't want to import this package into `editor-common` // We'll get type errors if this gets out of sync with `editor-plugin-width`. export var alignmentIcons = [{ id: 'editor.media.alignLeft', value: 'align-start', icon: function icon() { return /*#__PURE__*/React.createElement(AlignImageLeftIcon, { color: "currentColor", spacing: "spacious", label: "media-toolbar-align-left-icon" }); } }, { id: 'editor.media.alignCenter', value: 'center', icon: function icon() { return /*#__PURE__*/React.createElement(AlignImageCenterIcon, { color: "currentColor", spacing: "spacious", label: "media-toolbar-align-center-icon" }); } }, { id: 'editor.media.alignRight', value: 'align-end', icon: function icon() { return /*#__PURE__*/React.createElement(AlignImageRightIcon, { color: "currentColor", spacing: "spacious", label: "media-toolbar-align-right-icon" }); } }]; var alignmentIconsControls = [{ id: 'editor.media.alignLeft', value: 'align-start', icon: function icon() { return /*#__PURE__*/React.createElement(AlignTextLeftIcon, { color: "currentColor", spacing: "spacious", label: "" }); }, keyboardShortcut: alignLeft }, { id: 'editor.media.alignCenter', value: 'center', icon: function icon() { return /*#__PURE__*/React.createElement(AlignTextCenterIcon, { color: "currentColor", spacing: "spacious", label: "" }); }, keyboardShortcut: alignCenter }, { id: 'editor.media.alignRight', value: 'align-end', icon: function icon() { return /*#__PURE__*/React.createElement(AlignTextRightIcon, { color: "currentColor", spacing: "spacious", label: "" }); }, keyboardShortcut: alignRight }]; export var wrappingIcons = [{ id: 'editor.media.wrapLeft', value: 'wrap-left', icon: function icon() { return /*#__PURE__*/React.createElement(ContentWrapLeftIcon, { color: "currentColor", spacing: "spacious", label: "media-toolbar-wrap-left-icon" }); } }, { id: 'editor.media.wrapRight', value: 'wrap-right', icon: function icon() { return /*#__PURE__*/React.createElement(ContentWrapRightIcon, { color: "currentColor", spacing: "spacious", label: "media-toolbar-wrap-right-icon" }); } }]; var breakoutIcons = [{ value: 'wide', icon: ContentWidthWide }, { value: 'full-width', icon: FullWidthIcon }]; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any export var layoutToMessages = { 'wrap-left': toolbarMessages.wrapLeft, center: commonMessages.alignImageCenter, 'wrap-right': toolbarMessages.wrapRight, wide: commonMessages.layoutWide, 'full-width': commonMessages.layoutFullWidth, 'align-end': commonMessages.alignImageRight, 'align-start': commonMessages.alignImageLeft }; var getNodeWidth = function getNodeWidth(node, schema) { var embedCard = schema.nodes.embedCard; if (node.type === embedCard) { return node.attrs.originalWidth || DEFAULT_EMBED_CARD_WIDTH; } return node.firstChild && node.firstChild.attrs.width || node.attrs.width; }; var makeAlign = function makeAlign(layout, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing) { return function (state, dispatch) { var _ref = state.selection, node = _ref.node; var previousLayoutType = node.attrs.layout; var mediaSingle = state.schema.nodes.mediaSingle; if (!dispatch) { return false; } var widthPluginState = widthPluginDependencyApi === null || widthPluginDependencyApi === void 0 ? void 0 : widthPluginDependencyApi.sharedState.currentState(); if (!node || node.type !== nodeType || !widthPluginState) { return false; } var nodeWidth = getNodeWidth(node, state.schema); var newAttrs = allowPixelResizing ? // with extended experience, change alignment does not change media single width _objectSpread(_objectSpread({}, node.attrs), {}, { layout: layout }) : alignAttributes(layout, node.attrs, undefined, nodeWidth, widthPluginState.lineLength); var tr = state.tr.setNodeMarkup(state.selection.from, undefined, newAttrs); tr.setMeta('scrollIntoView', false); // when image captions are enabled, the wrong node gets selected after // setNodeMarkup is called tr.setSelection(NodeSelection.create(tr.doc, state.selection.from)); var paragraph = tr.doc.type.schema.nodes.paragraph; // see https://product-fabric.atlassian.net/browse/ED-15518 insert a new paragraph when an embedded card is wrapped left or right if (layout.startsWith('wrap') && paragraph && !tr.doc.nodeAt(state.selection.to) && (insideTable(state) || isInLayoutColumn(state))) { var emptyParaghraph = paragraph.createAndFill(); if (emptyParaghraph) { tr.insert(state.selection.to, emptyParaghraph); } } analyticsApi === null || analyticsApi === void 0 || analyticsApi.attachAnalyticsEvent({ eventType: EVENT_TYPE.TRACK, action: ACTION.SELECTED, actionSubject: ACTION_SUBJECT[node.type === mediaSingle ? 'MEDIA_SINGLE' : 'EMBEDS'], actionSubjectId: ACTION_SUBJECT_ID.RICH_MEDIA_LAYOUT, attributes: { previousLayoutType: previousLayoutType, currentLayoutType: layout } })(tr); dispatch(tr); return true; }; }; var getToolbarLayout = function getToolbarLayout(layout, allowPixelResizing) { if (nonWrappedLayouts.includes(layout) && allowPixelResizing) { return 'center'; } return layout; }; var mapIconsToToolbarItem = function mapIconsToToolbarItem(icons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, isChangingLayoutDisabled, allowPixelResizing) { return icons.map(function (toolbarItem) { var id = toolbarItem.id, value = toolbarItem.value; return _objectSpread({ id: id, type: 'button', icon: toolbarItem.icon, title: intl.formatMessage(layoutToMessages[value]), selected: getToolbarLayout(layout, allowPixelResizing) === value, onClick: makeAlign(value, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing) }, isChangingLayoutDisabled && { disabled: value !== 'center' }); }); }; var mapIconsToDropdownOptions = function mapIconsToDropdownOptions(_ref2) { var icons = _ref2.icons, layout = _ref2.layout, intl = _ref2.intl, nodeType = _ref2.nodeType, widthPluginDependencyApi = _ref2.widthPluginDependencyApi, analyticsApi = _ref2.analyticsApi, isChangingLayoutDisabled = _ref2.isChangingLayoutDisabled, allowPixelResizing = _ref2.allowPixelResizing; return icons.map(function (layoutOption) { var id = layoutOption.id, value = layoutOption.value; return _objectSpread(_objectSpread({ id: id, icon: /*#__PURE__*/React.createElement(layoutOption.icon, { label: "" }), title: intl.formatMessage(layoutToMessages[value]), selected: getToolbarLayout(layout, allowPixelResizing) === value, onClick: makeAlign(value, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing) }, layoutOption.keyboardShortcut && { elemAfter: /*#__PURE__*/React.createElement(Shortcut, null, tooltip(layoutOption.keyboardShortcut)) }), isChangingLayoutDisabled && { disabled: value !== 'center' }); }); }; var shouldHideLayoutToolbar = function shouldHideLayoutToolbar(selection, _ref3, allowResizingInTables) { var nodes = _ref3.nodes; return hasParentNodeOfType([nodes.bodiedExtension, nodes.extensionFrame, nodes.listItem].concat(_toConsumableArray(expValEquals('editor_enable_image_alignment_in_expand', 'isEnabled', true) ? [] : [nodes.expand, nodes.nestedExpand]), _toConsumableArray(allowResizingInTables ? [] : [nodes.table])).filter(Boolean))(selection); }; var buildLayoutButtons = function buildLayoutButtons(state, intl, nodeType, widthPluginDependencyApi, analyticsApi, allowResizing, allowResizingInTables) { var allowWrapping = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : true; var allowAlignment = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : true; var isChangingLayoutDisabled = arguments.length > 9 ? arguments[9] : undefined; var allowPixelResizing = arguments.length > 10 ? arguments[10] : undefined; var selection = state.selection; if (!(selection instanceof NodeSelection) || !selection.node || !nodeType || shouldHideLayoutToolbar(selection, state.schema, allowResizingInTables)) { return []; } var layout = selection.node.attrs.layout; var alignmentToolbarItems = allowAlignment ? mapIconsToToolbarItem(alignmentIcons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, isChangingLayoutDisabled, allowPixelResizing) : []; var wrappingToolbarItems = allowWrapping ? mapIconsToToolbarItem(wrappingIcons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, isChangingLayoutDisabled, allowPixelResizing) : []; var breakOutToolbarItems = !allowResizing ? mapIconsToToolbarItem(breakoutIcons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing) : []; var items = [].concat(_toConsumableArray(alignmentToolbarItems), _toConsumableArray(getSeparatorBetweenAlignmentAndWrapping(allowAlignment, allowWrapping)), _toConsumableArray(wrappingToolbarItems), _toConsumableArray(getSeparatorBeforeBreakoutItems(allowAlignment, allowWrapping, allowResizing)), _toConsumableArray(breakOutToolbarItems)); return items; }; export var buildLayoutDropdown = function buildLayoutDropdown(state, intl, nodeType, widthPluginDependencyApi, analyticsApi, allowResizing, allowResizingInTables) { var allowWrapping = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : true; var allowAlignment = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : true; var isChangingLayoutDisabled = arguments.length > 9 ? arguments[9] : undefined; var allowPixelResizing = arguments.length > 10 ? arguments[10] : undefined; var selection = state.selection; if (!(selection instanceof NodeSelection) || !selection.node || !nodeType || shouldHideLayoutToolbar(selection, state.schema, allowResizingInTables)) { return []; } var layout = selection.node.attrs.layout; var icons = []; if (allowAlignment) { icons.push.apply(icons, alignmentIconsControls); } if (allowWrapping) { icons.push.apply(icons, wrappingIcons); } if (!allowResizing) { icons.push.apply(icons, breakoutIcons); } if (icons.length === 0) { return []; } var selectedLayout = getSelectedLayoutIcon(icons, selection.node) || icons[0]; if (!selectedLayout) { return []; } var alignmentDropdownOptions = mapIconsToDropdownOptions({ icons: icons, layout: layout, intl: intl, nodeType: nodeType, widthPluginDependencyApi: widthPluginDependencyApi, analyticsApi: analyticsApi, isChangingLayoutDisabled: isChangingLayoutDisabled, allowPixelResizing: allowPixelResizing }); return [{ type: 'dropdown', title: intl.formatMessage(layoutToMessages[selectedLayout.value]), icon: selectedLayout.icon, options: alignmentDropdownOptions, shouldFitContainer: false, testId: "".concat(nodeType.name, "-layout-dropdown-trigger-button") }]; }; var getSelectedLayoutIcon = function getSelectedLayoutIcon(layoutIcons, selectedNode) { var selectedLayout = selectedNode.attrs.layout; return layoutIcons.find(function (icon) { return icon.value === (nonWrappedLayouts.includes(selectedLayout) ? 'center' : selectedLayout); }); }; var getSeparatorBetweenAlignmentAndWrapping = function getSeparatorBetweenAlignmentAndWrapping(allowAlignment, allowWrapping) { return allowAlignment && allowWrapping ? [{ type: 'separator' }] : []; }; var getSeparatorBeforeBreakoutItems = function getSeparatorBeforeBreakoutItems(allowAlignment, allowWrapping, allowResizing) { return !allowResizing && (allowAlignment || allowWrapping) ? [{ type: 'separator' }] : []; }; export default buildLayoutButtons;