@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
105 lines (103 loc) • 4.07 kB
JavaScript
import { createElement } from 'react';
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
import uuid from 'uuid';
import { Decoration } from '@atlaskit/editor-prosemirror/view';
import { fg } from '@atlaskit/platform-feature-flags';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { QuickInsertWithVisibility } from '../ui/quick-insert-button';
import { getActiveBlockMarks } from './utils/marks';
import { createVanillaButton } from './vanilla-quick-insert';
const TYPE_QUICK_INSERT = 'INSERT_BUTTON';
export const findQuickInsertInsertButtonDecoration = (decorations, from, to) => {
return decorations.find(from, to, spec => spec.type === TYPE_QUICK_INSERT);
};
export const quickInsertButtonDecoration = ({
api,
formatMessage,
rootPos,
anchorName,
nodeType,
nodeViewPortalProviderAPI,
rootAnchorName,
rootNodeType,
anchorRectCache,
editorState
}) => {
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
const key = uuid();
const cleanupCallbacks = [];
const widgetSpec = editorExperiment('platform_editor_breakout_resizing', true) ? {
side: -2,
type: TYPE_QUICK_INSERT,
/**
* sigh - `marks` influences the position that the widget is drawn (as described on the `side` property).
* Exclude 'breakout' on purpose, so the widgets render at the top of the document to avoid z-index issues
* Other block marks must be added, otherwise PM will split the DOM elements causing mutations and re-draws
*/
marks: expValEquals('platform_editor_clean_up_widget_mark_logic', 'isEnabled', true) ? [] : getActiveBlockMarks(editorState, rootPos),
destroy: _ => {
if (fg('platform_editor_fix_widget_destroy')) {
nodeViewPortalProviderAPI.remove(key);
}
cleanupCallbacks.forEach(cb => {
cb();
});
}
} : {
side: -2,
type: TYPE_QUICK_INSERT,
destroy: _ => {
if (fg('platform_editor_fix_widget_destroy')) {
nodeViewPortalProviderAPI.remove(key);
}
cleanupCallbacks.forEach(cb => {
cb();
});
}
};
return Decoration.widget(rootPos, (view, getPos) => {
const element = document.createElement('span');
// inline decoration causes cursor disappear when focusing editor at the first line (e.g. press Tab when title is focused)
element.style.display = 'block';
// make sure it does not interfere with elements floating next to each other e.g. paragraph next to image with wrap-right
element.style.clear = 'unset';
element.contentEditable = 'false';
element.setAttribute('data-blocks-quick-insert-container', 'true');
if (fg('confluence_remix_button_right_side_block_fg')) {
element.setAttribute('data-blocks-quick-insert-button', 'true');
}
element.setAttribute('data-testid', 'block-ctrl-quick-insert-button');
if (editorExperiment('platform_editor_block_control_optimise_render', true, {
exposure: true
})) {
const vanillaElement = createVanillaButton({
formatMessage,
api,
view,
getPos,
cleanupCallbacks,
rootAnchorName: rootAnchorName !== null && rootAnchorName !== void 0 ? rootAnchorName : nodeType,
anchorName,
rootNodeType: rootNodeType !== null && rootNodeType !== void 0 ? rootNodeType : nodeType,
anchorRectCache
});
element.appendChild(vanillaElement);
return element;
}
nodeViewPortalProviderAPI.render(() => /*#__PURE__*/createElement(QuickInsertWithVisibility, {
api,
getPos,
formatMessage,
view,
nodeType,
anchorName,
rootAnchorName,
rootNodeType: rootNodeType !== null && rootNodeType !== void 0 ? rootNodeType : nodeType,
anchorRectCache
}), element, key, undefined,
// @portal-render-immediately
true);
return element;
}, widgetSpec);
};