@atlaskit/editor-plugin-panel
Version:
Panel plugin for @atlaskit/editor-core.
144 lines (139 loc) • 6.57 kB
JavaScript
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import React from 'react';
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
import uuid from 'uuid/v4';
import { PanelType } from '@atlaskit/adf-schema';
import { Emoji } from '@atlaskit/editor-common/emoji';
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
import { PanelErrorIcon, PanelInfoIcon, PanelNoteIcon, PanelSuccessIcon, PanelWarningIcon } from '@atlaskit/editor-common/icons';
import { PanelSharedCssClassName } from '@atlaskit/editor-common/panel';
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
import { akEditorCustomIconSize } from '@atlaskit/editor-shared-styles/consts';
import LightbulbIcon from '@atlaskit/icon/core/lightbulb';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { panelAttrsToDom } from '../pm-plugins/utils/utils';
import { renderPanelIcon } from '../ui/renderPanelIcon';
/* eslint-disable @atlaskit/editor/no-re-export */
// Mapping export
export var panelIcons = {
info: PanelInfoIcon,
success: PanelSuccessIcon,
note: PanelNoteIcon,
tip: LightbulbIcon,
warning: PanelWarningIcon,
error: PanelErrorIcon,
custom: PanelInfoIcon
};
/* eslint-enable @atlaskit/editor/no-re-export */
var selector = function selector(states) {
return {
emojiState: states.emojiState
};
};
export var PanelIcon = function PanelIcon(props) {
var allowCustomPanel = props.allowCustomPanel,
providerFactory = props.providerFactory,
pluginInjectionApi = props.pluginInjectionApi,
_props$panelAttribute = props.panelAttributes,
panelType = _props$panelAttribute.panelType,
panelIcon = _props$panelAttribute.panelIcon,
panelIconId = _props$panelAttribute.panelIconId,
panelIconText = _props$panelAttribute.panelIconText;
var _useSharedPluginState = useSharedPluginStateWithSelector(pluginInjectionApi, ['emoji'], selector),
emojiState = _useSharedPluginState.emojiState;
var emojiProvider = emojiState === null || emojiState === void 0 ? void 0 : emojiState.emojiProvider;
if (allowCustomPanel && panelIcon && panelType === PanelType.CUSTOM) {
return /*#__PURE__*/React.createElement(Emoji, {
emojiProvider: emojiProvider,
providers: providerFactory,
shortName: panelIcon,
id: panelIconId,
fallback: panelIconText,
showTooltip: false,
allowTextFallback: false,
fitToHeight: akEditorCustomIconSize
});
}
var Icon = panelIcons[panelType];
return Icon ? /*#__PURE__*/React.createElement(Icon, {
label: "".concat(panelType, " panel")
}) : null;
};
var PanelNodeView = /*#__PURE__*/function () {
function PanelNodeView(node, view, getPos, pluginOptions, api, nodeViewPortalProviderAPI, providerFactory) {
var _this = this;
_classCallCheck(this, PanelNodeView);
this.nodeViewPortalProviderAPI = nodeViewPortalProviderAPI;
this.providerFactory = providerFactory;
this.pluginOptions = pluginOptions;
this.view = view;
this.node = node;
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
this.key = uuid();
var _DOMSerializer$render = DOMSerializer.renderSpec(document, panelAttrsToDom(node.attrs, pluginOptions.allowCustomPanel || false)),
dom = _DOMSerializer$render.dom,
contentDOM = _DOMSerializer$render.contentDOM;
this.getPos = getPos;
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
this.dom = dom;
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
this.contentDOM = contentDOM;
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
this.icon = this.dom.querySelector(".".concat(PanelSharedCssClassName.icon));
if (!this.icon) {
return;
}
// set contentEditable as false to be able to select the custom panels with keyboard
this.icon.contentEditable = 'false';
var panelAttrs = node.attrs;
// Determine if this is a standard panel type (info, note, success, warning, error)
var isStandardPanel = panelAttrs.panelType && [PanelType.INFO, PanelType.NOTE, PanelType.SUCCESS, PanelType.WARNING, PanelType.ERROR].includes(panelAttrs.panelType);
// For standard panels (info, note, success, warning, error), render icon directly as native DOM
// This avoids Portal rendering delays that cause flickering on SSR and page transitions
if (isStandardPanel && expValEquals('platform_editor_vc90_transition_panel_icon', 'isEnabled', true)) {
renderPanelIcon(panelAttrs.panelType, this.icon);
} else {
this.nodeViewPortalProviderAPI.render(function () {
return /*#__PURE__*/React.createElement(PanelIcon, {
pluginInjectionApi: api,
allowCustomPanel: pluginOptions.allowCustomPanel,
panelAttributes: panelAttrs,
providerFactory: _this.providerFactory
});
}, this.icon, this.key);
}
}
return _createClass(PanelNodeView, [{
key: "ignoreMutation",
value: function ignoreMutation(mutation) {
// ignore mutation if it caused by the icon.
if (!this.icon) {
return false;
}
var isIcon = mutation.target === this.icon || mutation.target.parentNode === this.icon;
// ignore mutation if it caused by the lazy load emoji inside icon.
var isInsideIcon = this.icon.contains(mutation.target);
return isIcon || isInsideIcon;
}
}, {
key: "destroy",
value: function destroy() {
var panelAttrs = this.node.attrs;
// Determine if this is a standard panel type (info, note, success, warning, error)
var isStandardPanel = panelAttrs.panelType && [PanelType.INFO, PanelType.NOTE, PanelType.SUCCESS, PanelType.WARNING, PanelType.ERROR].includes(panelAttrs.panelType);
// Only remove Portal if it was used (for custom emoji panels)
if (!(isStandardPanel && expValEquals('platform_editor_vc90_transition_panel_icon', 'isEnabled', true))) {
this.nodeViewPortalProviderAPI.remove(this.key);
}
}
}]);
}();
export var getPanelNodeView = function getPanelNodeView(pluginOptions, api, nodeViewPortalProviderAPI, providerFactory) {
return function (node, view, getPos) {
return new PanelNodeView(node, view, getPos, pluginOptions, api, nodeViewPortalProviderAPI, providerFactory);
};
};