UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

346 lines (338 loc) • 19 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.CommentEditorWithIntl = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _react2 = require("@emotion/react"); var _classnames = _interopRequireDefault(require("classnames")); var _reactIntl = require("react-intl"); var _buttonGroup = _interopRequireDefault(require("@atlaskit/button/button-group")); var _new = _interopRequireDefault(require("@atlaskit/button/new")); var _hooks = require("@atlaskit/editor-common/hooks"); var _messages = _interopRequireDefault(require("@atlaskit/editor-common/messages")); var _ui = require("@atlaskit/editor-common/ui"); var _uiMenu = require("@atlaskit/editor-common/ui-menu"); var _editorSharedStyles = require("@atlaskit/editor-shared-styles"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _experiments = require("@atlaskit/tmp-editor-statsig/experiments"); var _ClickAreaBlock = _interopRequireDefault(require("../../Addon/ClickAreaBlock")); var _contentComponentWrapper = require("../../Addon/ClickAreaBlock/contentComponentWrapper"); var _EditorContentContainer = _interopRequireDefault(require("../../EditorContentContainer/EditorContentContainer")); var _PluginSlot = _interopRequireDefault(require("../../PluginSlot")); var _getPrimaryToolbarComponents = require("../../Toolbar/getPrimaryToolbarComponents"); var _ToolbarWithSizeDetector = require("../../Toolbar/ToolbarWithSizeDetector"); var _WithFlash = _interopRequireDefault(require("../../WithFlash")); var _CommentToolbar = require("./CommentToolbar"); var _Toolbar = require("./Toolbar"); 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); } /** * @jsxRuntime classic * @jsx jsx */ // 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 // Ignored via go/ees005 // eslint-disable-next-line import/no-named-as-default var MAXIMUM_TWO_LINE_TOOLBAR_BREAKPOINT = 490; // Remove when platform_editor_comment_editor_border_radius is cleaned up var commentEditorStylesOld = (0, _react2.css)({ display: 'flex', flexDirection: 'column', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766 '.less-margin > .ProseMirror': { margin: "var(--ds-space-150, 12px)".concat(" ", "var(--ds-space-100, 8px)", " ", "var(--ds-space-100, 8px)") }, minWidth: '272px', height: 'auto', backgroundColor: "var(--ds-background-input, #FFFFFF)", border: "var(--ds-border-width, 1px)".concat(" solid ", "var(--ds-border-input, #8C8F97)"), boxSizing: 'border-box', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 borderRadius: "var(--ds-radius-small, 3px)", maxWidth: 'inherit', wordWrap: 'break-word' }); var commentEditorStyles = (0, _react2.css)({ display: 'flex', flexDirection: 'column', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766 '.less-margin > .ProseMirror': { margin: "var(--ds-space-150, 12px)".concat(" ", "var(--ds-space-100, 8px)", " ", "var(--ds-space-100, 8px)") }, minWidth: '272px', height: 'auto', backgroundColor: "var(--ds-background-input, #FFFFFF)", border: "var(--ds-border-width, 1px)".concat(" solid ", "var(--ds-border-input, #8C8F97)"), boxSizing: 'border-box', borderRadius: "var(--ds-radius-medium, 6px)", maxWidth: 'inherit', wordWrap: 'break-word' }); var secondaryToolbarStyles = (0, _react2.css)({ boxSizing: 'border-box', justifyContent: 'flex-end', alignItems: 'center', display: 'flex', padding: "var(--ds-space-150, 12px)".concat(" ", "var(--ds-space-025, 2px)") }); var mainToolbarCustomComponentsSlotStyleNew = (0, _react2.css)({ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', flexGrow: 1, paddingRight: "var(--ds-space-250, 20px)", // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors '> div': { display: 'flex', flexShrink: 0 } }); var mainToolbarCustomComponentsSlotStylePaddingOverride = (0, _react2.css)({ paddingRight: 0 }); var mainToolbarCustomComponentsSlotStyleTwoLineToolbarNew = (0, _react2.css)((0, _defineProperty2.default)({}, "@media (max-width: ".concat(MAXIMUM_TWO_LINE_TOOLBAR_BREAKPOINT, "px)"), { paddingRight: 0 })); var appearance = 'comment'; var CommentEditorWithIntl = exports.CommentEditorWithIntl = function CommentEditorWithIntl(props) { var _editorAPI$blockMenu$, _editorAPI$blockMenu; var editorAPI = props.editorAPI; // Get useStandardNodeWidth from block menu plugin shared state // Only access editorAPI when the experiment is enabled to avoid performance impact var useStandardNodeWidth = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && ((_editorAPI$blockMenu$ = editorAPI === null || editorAPI === void 0 || (_editorAPI$blockMenu = editorAPI.blockMenu) === null || _editorAPI$blockMenu === void 0 || (_editorAPI$blockMenu = _editorAPI$blockMenu.sharedState) === null || _editorAPI$blockMenu === void 0 || (_editorAPI$blockMenu = _editorAPI$blockMenu.currentState()) === null || _editorAPI$blockMenu === void 0 ? void 0 : _editorAPI$blockMenu.useStandardNodeWidth) !== null && _editorAPI$blockMenu$ !== void 0 ? _editorAPI$blockMenu$ : false); var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(editorAPI, ['maxContentSize', 'primaryToolbar', 'editorViewMode'], function (states) { var _states$maxContentSiz, _states$primaryToolba, _states$editorViewMod; return { maxContentSizeReached: !!((_states$maxContentSiz = states.maxContentSizeState) !== null && _states$maxContentSiz !== void 0 && _states$maxContentSiz.maxContentSizeReached), primaryToolbarComponentsState: (_states$primaryToolba = states.primaryToolbarState) === null || _states$primaryToolba === void 0 ? void 0 : _states$primaryToolba.components, editorViewMode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode }; }), editorViewMode = _useSharedPluginState.editorViewMode, primaryToolbarComponentsState = _useSharedPluginState.primaryToolbarComponentsState, maxContentSizeReached = _useSharedPluginState.maxContentSizeReached; var primaryToolbarState = (0, _getPrimaryToolbarComponents.getPrimaryToolbarComponents)(editorAPI, primaryToolbarComponentsState); var _useSharedPluginState2 = (0, _hooks.useSharedPluginState)(editorAPI, ['media']), mediaState = _useSharedPluginState2.mediaState; var intl = (0, _reactIntl.useIntl)(); var editorDOMElement = props.editorDOMElement, editorView = props.editorView, editorActions = props.editorActions, eventDispatcher = props.eventDispatcher, providerFactory = props.providerFactory, contentComponents = props.contentComponents, customContentComponents = props.customContentComponents, customPrimaryToolbarComponents = props.customPrimaryToolbarComponents, primaryToolbarComponentsProp = props.primaryToolbarComponents, customSecondaryToolbarComponents = props.customSecondaryToolbarComponents, popupsMountPoint = props.popupsMountPoint, popupsBoundariesElement = props.popupsBoundariesElement, popupsScrollableElement = props.popupsScrollableElement, maxHeight = props.maxHeight, _props$minHeight = props.minHeight, minHeight = _props$minHeight === void 0 ? 150 : _props$minHeight, onSave = props.onSave, onCancel = props.onCancel, disabled = props.disabled, dispatchAnalyticsEvent = props.dispatchAnalyticsEvent, useStickyToolbar = props.useStickyToolbar, pluginHooks = props.pluginHooks, featureFlags = props.featureFlags, innerRef = props.innerRef; var showSecondaryToolbar = !!onSave || !!onCancel || !!customSecondaryToolbarComponents; var containerElement = _react.default.useRef(null); // Wrapper container for toolbar and content area var wrapperElementRef = (0, _react.useMemo)(function () { return innerRef || /*#__PURE__*/_react.default.createRef(); }, [innerRef]); var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), saveButtonDisabled = _useState2[0], setSaveButtonDisabled = _useState2[1]; (0, _react.useEffect)(function () { if (mediaState) { mediaState.subscribeToUploadInProgressState(setSaveButtonDisabled); } return function () { return mediaState === null || mediaState === void 0 ? void 0 : mediaState.unsubscribeFromUploadInProgressState(setSaveButtonDisabled); }; }, [mediaState]); var handleSave = (0, _react.useCallback)(function () { if (editorView && onSave) { onSave(editorView); } }, [editorView, onSave]); var handleCancel = (0, _react.useCallback)(function () { if (editorView && onCancel) { onCancel(editorView); } }, [editorView, onCancel]); var isShortcutToFocusToolbar = (0, _react.useCallback)(function (event) { //Alt + F9 to reach first element in this main toolbar return event.altKey && (event.key === 'F9' || event.keyCode === 120); }, []); // When primary toolbar components is undefined, do not show two line editor toolbar var isTwoLineToolbarEnabled = !!customPrimaryToolbarComponents; var handleEscape = (0, _react.useCallback)(function (event) { if (!(editorView !== null && editorView !== void 0 && editorView.hasFocus())) { editorView === null || editorView === void 0 || editorView.focus(); } event.preventDefault(); event.stopPropagation(); }, [editorView]); var primaryToolbarComponents = primaryToolbarComponentsProp; if (Array.isArray(primaryToolbarState === null || primaryToolbarState === void 0 ? void 0 : primaryToolbarState.components) && Array.isArray(primaryToolbarComponents)) { primaryToolbarComponents = primaryToolbarState.components.concat(primaryToolbarComponents); } var isToolbarAIFCEnabled = Boolean(editorAPI === null || editorAPI === void 0 ? void 0 : editorAPI.toolbar); var memoizedContentAreaStyles = (0, _react.useMemo)(function () { return [maxHeight ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 (0, _react2.css)({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 maxHeight: "".concat(maxHeight, "px"), // When maxHeight is set, content area should have overflow-y explicitly set as auto // As we have overflow-x: clip for the content area, and when maxHeight prop is set, overflow-y will be computed as visible by default. // This will cause the content area to have content overflowing the container // so need to set overflow-y as auto to make sure the content area is scrollable overflowY: 'auto' }) : null]; }, [maxHeight]); var contentAreaStyles = (0, _expValEquals.expValEquals)('platform_editor_perf_lint_cleanup', 'isEnabled', true) ? memoizedContentAreaStyles : [maxHeight ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 (0, _react2.css)({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 maxHeight: "".concat(maxHeight, "px"), // When maxHeight is set, content area should have overflow-y explicitly set as auto // As we have overflow-x: clip for the content area, and when maxHeight prop is set, overflow-y will be computed as visible by default. // This will cause the content area to have content overflowing the container // so need to set overflow-y as auto to make sure the content area is scrollable overflowY: 'auto' }) : null]; var customToolbarSlot = (0, _react2.jsx)("div", { css: [mainToolbarCustomComponentsSlotStyleNew, isTwoLineToolbarEnabled && mainToolbarCustomComponentsSlotStyleTwoLineToolbarNew, isToolbarAIFCEnabled && mainToolbarCustomComponentsSlotStylePaddingOverride] }, customPrimaryToolbarComponents); return (0, _react2.jsx)(_WithFlash.default, { animate: maxContentSizeReached }, (0, _react2.jsx)(_ui.WidthProvider, null, (0, _react2.jsx)("div", { css: [(0, _expValEquals.expValEquals)('platform_editor_comment_editor_border_radius', 'isEnabled', true) ? commentEditorStyles : commentEditorStylesOld, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 (0, _react2.css)({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 minHeight: "".concat(minHeight, "px") })] // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: "akEditor", ref: wrapperElementRef }, (0, _react2.jsx)(_Toolbar.MainToolbar, { useStickyToolbar: useStickyToolbar, twoLineEditorToolbar: isTwoLineToolbarEnabled, isNewToolbarEnabled: isToolbarAIFCEnabled }, isToolbarAIFCEnabled ? (0, _react2.jsx)(_uiMenu.ToolbarArrowKeyNavigationProvider, { editorView: editorView, childComponentSelector: "[data-testid='ak-editor-main-toolbar']", isShortcutToFocusToolbar: isShortcutToFocusToolbar, handleEscape: handleEscape, editorAppearance: appearance, useStickyToolbar: useStickyToolbar, intl: intl }, (0, _react2.jsx)(_CommentToolbar.CommentToolbar, { editorAPI: editorAPI, editorView: editorView, editorAppearance: appearance, disabled: !!disabled, popupsBoundariesElement: popupsBoundariesElement, popupsScrollableElement: popupsScrollableElement, popupsMountPoint: popupsMountPoint }), customPrimaryToolbarComponents ? customToolbarSlot : null) : (0, _react2.jsx)(_uiMenu.ToolbarArrowKeyNavigationProvider, { editorView: editorView, childComponentSelector: "[data-testid='ak-editor-main-toolbar']", isShortcutToFocusToolbar: isShortcutToFocusToolbar, handleEscape: handleEscape, editorAppearance: appearance, useStickyToolbar: useStickyToolbar, intl: intl }, (0, _react2.jsx)(_ToolbarWithSizeDetector.ToolbarWithSizeDetector // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , { editorView: editorView, editorActions: editorActions // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , eventDispatcher: eventDispatcher // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , providerFactory: providerFactory, appearance: appearance, items: primaryToolbarComponents, popupsMountPoint: popupsMountPoint, popupsBoundariesElement: popupsBoundariesElement, popupsScrollableElement: popupsScrollableElement, disabled: !!disabled, dispatchAnalyticsEvent: dispatchAnalyticsEvent, containerElement: containerElement.current, twoLineEditorToolbar: isTwoLineToolbarEnabled }), customToolbarSlot)), (0, _react2.jsx)(_ClickAreaBlock.default, { editorView: editorView, editorDisabled: disabled }, (0, _react2.jsx)(_ui.WidthConsumer, null, function (_ref) { var width = _ref.width; return (0, _react2.jsx)(_EditorContentContainer.default, { ref: containerElement, css: contentAreaStyles, isScrollable: maxHeight ? true : undefined // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: (0, _classnames.default)('ak-editor-content-area', { 'less-margin': width < _editorSharedStyles.akEditorMobileBreakoutPoint }), featureFlags: featureFlags, viewMode: editorViewMode, appearance: appearance, useStandardNodeWidth: useStandardNodeWidth }, customContentComponents && 'before' in customContentComponents ? (0, _contentComponentWrapper.contentComponentClickWrapper)(customContentComponents.before) : (0, _contentComponentWrapper.contentComponentClickWrapper)(customContentComponents), (0, _react2.jsx)(_PluginSlot.default, { editorView: editorView, editorActions: editorActions, eventDispatcher: eventDispatcher, dispatchAnalyticsEvent: dispatchAnalyticsEvent, providerFactory: providerFactory, appearance: appearance, items: contentComponents, popupsMountPoint: popupsMountPoint, popupsBoundariesElement: popupsBoundariesElement, popupsScrollableElement: popupsScrollableElement, containerElement: containerElement.current, disabled: !!disabled, wrapperElement: wrapperElementRef.current, pluginHooks: pluginHooks }), editorDOMElement, customContentComponents && 'after' in customContentComponents ? (0, _contentComponentWrapper.contentComponentClickWrapper)(customContentComponents.after) : null); }))), showSecondaryToolbar && (0, _react2.jsx)("div", { css: secondaryToolbarStyles, "data-testid": "ak-editor-secondary-toolbar" }, (0, _react2.jsx)(_buttonGroup.default, null, !!onSave && (0, _react2.jsx)(_new.default, { appearance: "primary", onClick: handleSave, testId: "comment-save-button", isDisabled: disabled || saveButtonDisabled, interactionName: "editor-comment-save-button" }, intl.formatMessage(_messages.default.saveButton)), !!onCancel && (0, _react2.jsx)(_new.default, { appearance: "subtle", onClick: handleCancel, testId: "comment-cancel-button", isDisabled: disabled, interactionName: "editor-comment-cancel-button" }, intl.formatMessage(_messages.default.cancelButton))), (0, _react2.jsx)("span", { style: { flexGrow: 1 } }), customSecondaryToolbarComponents))); }; CommentEditorWithIntl.displayName = 'CommentEditorAppearance';