@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
128 lines (123 loc) • 7.17 kB
JavaScript
/**
* @jsxRuntime classic
* @jsx jsx
*/
import React, { useEffect, useCallback, useState } from 'react';
// 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
import { jsx } from '@emotion/react';
import { injectIntl } from 'react-intl';
import { ContextPanelConsumer } from '@atlaskit/editor-common/context-panel';
import { fullPageMessages as messages } from '@atlaskit/editor-common/messages';
import { ToolbarArrowKeyNavigationProvider } from '@atlaskit/editor-common/ui-menu';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { ToolbarPortalMountPoint, useToolbarPortal } from '../../Toolbar/ToolbarPortal';
import { ToolbarWithSizeDetector as Toolbar } from '../../Toolbar/ToolbarWithSizeDetector';
import { BeforePrimaryToolbarWrapper } from './BeforeWrapper';
import { MainToolbarForFirstChildWrapper, MainToolbarForSecondChildWrapper } from './CustomToolbarWrapper';
import { customToolbarWrapperStyle, mainToolbarIconBeforeStyle, MAXIMUM_TWO_LINE_TOOLBAR_BREAKPOINT, nonCustomToolbarWrapperStyle } from './MainToolbar';
import { MainToolbarWrapper } from './MainToolbarWrapper';
export const EditorToolbar = /*#__PURE__*/React.memo(props => {
var _props$primaryToolbar, _useToolbarPortal, _props$customPrimaryT;
const [shouldSplitToolbar, setShouldSplitToolbar] = useState(false);
const {
editorAPI
} = props;
// When primary toolbar components is undefined, do not show two line editor toolbar
const twoLineEditorToolbar = editorExperiment('platform_editor_controls', 'variant1') ? !!props.customPrimaryToolbarComponents && ((_props$primaryToolbar = props.primaryToolbarComponents) === null || _props$primaryToolbar === void 0 ? void 0 : _props$primaryToolbar.length) !== 0 : !!props.customPrimaryToolbarComponents;
// When a toolbar portal context is provided, render the toolbar inside a portal.
// Otherwise fall back to a fragment just to avoid forking rendering logic.
const {
Portal: ToolbarPortal
} = (_useToolbarPortal = useToolbarPortal()) !== null && _useToolbarPortal !== void 0 ? _useToolbarPortal : {
Portal: React.Fragment
};
const hasToolbarPortal = ToolbarPortal !== React.Fragment;
const popupsMountPoint = hasToolbarPortal ? undefined : props.popupsMountPoint;
const nonCustomToolbar =
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
jsx("div", {
css: nonCustomToolbarWrapperStyle
}, props.beforeIcon && jsx("div", {
css: mainToolbarIconBeforeStyle
}, props.beforeIcon), jsx(Toolbar, {
editorView: props.editorView,
editorActions: props.editorActions,
eventDispatcher: props.eventDispatcher,
providerFactory: props.providerFactory,
appearance: props.appearance,
items: props.primaryToolbarComponents,
popupsMountPoint: popupsMountPoint,
popupsBoundariesElement: props.popupsBoundariesElement,
popupsScrollableElement: props.popupsScrollableElement,
disabled: props.disabled,
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent,
containerElement: props.containerElement,
hasMinWidth: props.hasMinWidth,
twoLineEditorToolbar: twoLineEditorToolbar
}));
const customToolbar =
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
jsx("div", {
css: customToolbarWrapperStyle
}, !!props.customPrimaryToolbarComponents && 'before' in props.customPrimaryToolbarComponents ? jsx(BeforePrimaryToolbarWrapper, {
beforePrimaryToolbarComponents: (_props$customPrimaryT = props.customPrimaryToolbarComponents) === null || _props$customPrimaryT === void 0 ? void 0 : _props$customPrimaryT.before
}) : null, !editorExperiment('platform_editor_controls', 'variant1') && editorAPI !== null && editorAPI !== void 0 && editorAPI.findReplace && twoLineEditorToolbar ? editorAPI === null || editorAPI === void 0 ? void 0 : editorAPI.findReplace.actions.registerToolbarButton({
popupsBoundariesElement: props.popupsBoundariesElement,
popupsMountPoint: popupsMountPoint,
popupsScrollableElement: props.popupsScrollableElement,
editorView: props.editorView,
containerElement: props.containerElement,
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent
}) : null, !!props.customPrimaryToolbarComponents && 'after' in props.customPrimaryToolbarComponents ? props.customPrimaryToolbarComponents.after : props.customPrimaryToolbarComponents);
useEffect(() => {
if (twoLineEditorToolbar) {
const updateOnResize = () => {
setShouldSplitToolbar(window.innerWidth <= MAXIMUM_TWO_LINE_TOOLBAR_BREAKPOINT);
};
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
window.addEventListener('resize', updateOnResize);
updateOnResize();
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
return () => window.removeEventListener('resize', updateOnResize);
}
});
const isShortcutToFocusToolbar = useCallback(event => {
//Alt + F9 to reach first element in this main toolbar
return event.altKey && (event.key === 'F9' || event.keyCode === 120);
}, []);
const handleEscape = useCallback(event => {
var _props$editorView;
if (!((_props$editorView = props.editorView) !== null && _props$editorView !== void 0 && _props$editorView.hasFocus())) {
var _props$editorView2;
(_props$editorView2 = props.editorView) === null || _props$editorView2 === void 0 ? void 0 : _props$editorView2.focus();
}
event.preventDefault();
event.stopPropagation();
}, [props.editorView]);
return jsx(ContextPanelConsumer, null, ({
width: contextPanelWidth
}) => jsx(ToolbarArrowKeyNavigationProvider, {
editorView: props.editorView,
childComponentSelector: "[data-testid='ak-editor-main-toolbar']",
isShortcutToFocusToolbar: isShortcutToFocusToolbar,
handleEscape: handleEscape,
intl: props.intl
}, jsx(ToolbarPortal, null, jsx(MainToolbarWrapper, {
showKeyline: props.showKeyline || contextPanelWidth > 0,
twoLineEditorToolbar: twoLineEditorToolbar,
"data-testid": "ak-editor-main-toolbar"
}, jsx(MainToolbarForFirstChildWrapper, {
twoLineEditorToolbar: twoLineEditorToolbar,
role: "toolbar",
"aria-label": props.intl.formatMessage(messages.toolbarLabel)
}, shouldSplitToolbar ? customToolbar : nonCustomToolbar), jsx(MainToolbarForSecondChildWrapper, {
twoLineEditorToolbar: twoLineEditorToolbar,
"data-testid": "avatar-group-outside-plugin",
role: "region",
"aria-label": props.intl.formatMessage(messages.pageActionsLabel)
}, shouldSplitToolbar ? nonCustomToolbar : customToolbar), jsx(ToolbarPortalMountPoint, null)))));
});
// eslint-disable-next-line @typescript-eslint/ban-types
export const FullPageToolbar = injectIntl(EditorToolbar);