UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

128 lines (123 loc) 7.17 kB
/** * @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);