@atlaskit/editor-plugin-breakout
Version:
Breakout plugin for @atlaskit/editor-core
182 lines (179 loc) • 8.38 kB
JavaScript
/**
* @jsxRuntime classic
* @jsx jsx
*/
import { useCallback } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
import { css, jsx } from '@emotion/react';
import { injectIntl } from 'react-intl';
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
import { BreakoutCssClassName } from '@atlaskit/editor-common/styles';
import { Popup } from '@atlaskit/editor-common/ui';
import { ToolbarButton } from '@atlaskit/editor-common/ui-menu';
import { getNextBreakoutMode, getTitle } from '@atlaskit/editor-common/utils';
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
import { findDomRefAtPos, findParentDomRefOfType } from '@atlaskit/editor-prosemirror/utils';
import { akEditorFullPageNarrowBreakout } from '@atlaskit/editor-shared-styles';
import GrowHorizontalIcon from '@atlaskit/icon/core/grow-horizontal';
import ShrinkHorizontalIcon from '@atlaskit/icon/core/shrink-horizontal';
import { layers } from '@atlaskit/theme/constants';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { removeBreakout } from '../editor-commands/remove-breakout';
import { setBreakoutMode } from '../editor-commands/set-breakout-mode';
import { getPluginState } from '../pm-plugins/plugin-key';
import { isBreakoutMarkAllowed } from '../pm-plugins/utils/is-breakout-mark-allowed';
import { isSupportedNodeForBreakout } from '../pm-plugins/utils/is-supported-node';
const toolbarButtonWrapperStyles = css({
// eslint-disable-next-line @atlaskit/design-system/no-nested-styles, @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
'&& button': {
background: "var(--ds-background-neutral, #0515240F)",
color: "var(--ds-icon, #292A2E)",
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
':hover': {
background: "var(--ds-background-neutral-hovered, #0B120E24)",
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles -- Ignored via go/DSP-18766
color: `${"var(--ds-icon, #292A2E)"} !important`
}
}
});
const toolbarButtonNarrowScreenStyles = css({
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-container-queries, @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/no-nested-styles, @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
[`@container editor-area (max-width: ${akEditorFullPageNarrowBreakout}px)`]: {
// eslint-disable-next-line @atlaskit/design-system/no-nested-styles, @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
'&& button': {
visibility: 'hidden',
opacity: 0
}
}
});
function getBreakoutNodeElement(pluginState, selection, editorView) {
if (!pluginState.breakoutNode) {
return undefined;
}
if (selection instanceof NodeSelection && isSupportedNodeForBreakout(selection.node)) {
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
return findDomRefAtPos(selection.from, editorView.domAtPos.bind(editorView));
}
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
return findParentDomRefOfType(pluginState.breakoutNode.node.type, editorView.domAtPos.bind(editorView))(selection);
}
const LayoutButton = ({
intl: {
formatMessage
},
mountPoint,
boundariesElement,
scrollableElement,
editorView,
isLivePage,
isBreakoutNodePresent,
breakoutMode: breakoutModeProp,
api
}) => {
var _api$analytics3;
const handleClick = useCallback(breakoutMode => {
var _getPluginState;
if (expValEquals('platform_editor_hydratable_ui', 'isEnabled', true) && !editorView) {
return;
}
// Remove ! during platform_editor_hydratable_ui cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const {
state,
dispatch
} = editorView;
const breakoutNode = (_getPluginState = getPluginState(state)) === null || _getPluginState === void 0 ? void 0 : _getPluginState.breakoutNode;
if (['wide', 'full-width'].indexOf(breakoutMode) !== -1) {
var _api$analytics;
setBreakoutMode(breakoutMode, isLivePage)(state, dispatch);
api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent({
action: ACTION.CHANGED_BREAKOUT_MODE,
actionSubject: ACTION_SUBJECT.ELEMENT,
eventType: EVENT_TYPE.TRACK,
attributes: {
mode: breakoutMode,
nodeType: breakoutNode === null || breakoutNode === void 0 ? void 0 : breakoutNode.node.type.name
}
});
} else {
var _api$analytics2;
removeBreakout(isLivePage)(state, dispatch);
api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent({
action: ACTION.CHANGED_BREAKOUT_MODE,
actionSubject: ACTION_SUBJECT.ELEMENT,
eventType: EVENT_TYPE.TRACK,
attributes: {
mode: 'center',
nodeType: breakoutNode === null || breakoutNode === void 0 ? void 0 : breakoutNode.node.type.name
}
});
}
}, [api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions, editorView, isLivePage]);
if (expValEquals('platform_editor_hydratable_ui', 'isEnabled', true) && !editorView) {
return null;
}
// Remove ! during platform_editor_hydratable_ui cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (!isBreakoutNodePresent || !isBreakoutMarkAllowed(editorView.state)) {
return null;
}
const breakoutMode = breakoutModeProp;
const titleMessage = getTitle(breakoutMode);
const title = formatMessage(titleMessage);
const nextBreakoutMode = getNextBreakoutMode(breakoutMode);
const belowOtherPopupsZIndex = layers.layer() - 1;
// Remove ! during platform_editor_hydratable_ui cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const pluginState = getPluginState(editorView.state);
if (!pluginState) {
return null;
}
// Remove ! during platform_editor_hydratable_ui cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
let element = getBreakoutNodeElement(pluginState, editorView.state.selection, editorView);
if (!element) {
return null;
}
const closestEl = element.querySelector(`.${BreakoutCssClassName.BREAKOUT_MARK_DOM}`);
if (closestEl && closestEl.firstChild) {
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
element = closestEl.firstChild;
}
return jsx(Popup, {
ariaLabel: title,
target: element
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
offset: [5, 0],
alignY: "start",
alignX: "end",
mountTo: mountPoint,
boundariesElement: boundariesElement,
scrollableElement: scrollableElement,
stick: true,
forcePlacement: true,
zIndex: belowOtherPopupsZIndex
}, jsx("div", {
css: [toolbarButtonWrapperStyles, editorExperiment('platform_editor_preview_panel_responsiveness', true) && toolbarButtonNarrowScreenStyles]
}, jsx(ToolbarButton, {
title: title,
testId: titleMessage.id
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
onClick: () => handleClick(nextBreakoutMode),
iconBefore: breakoutMode === 'full-width' ? jsx(ShrinkHorizontalIcon, {
label: title,
spacing: "spacious"
}) : jsx(GrowHorizontalIcon, {
label: title,
spacing: "spacious"
})
})));
};
LayoutButton.displayName = 'LayoutButton';
const _default_1 = injectIntl(LayoutButton);
export default _default_1;