@atlaskit/editor-plugin-unsupported-content
Version:
Unsupported Content plugin for @atlaskit/editor-core
121 lines (118 loc) • 5.64 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import { bind } from 'bind-event-listener';
import { ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics/types/enums';
import { getBrowserInfo } from '@atlaskit/editor-common/browser';
import { unsupportedContentMessages } from '@atlaskit/editor-common/messages/unsupportedContent';
import { trackUnsupportedContentTooltipDisplayedFor } from '@atlaskit/editor-common/utils/track-unsupported-content';
import { VANILLA_TOOLTIP_DEFAULT_CLASS, VanillaTooltip } from '@atlaskit/editor-common/vanilla-tooltip';
import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace/whitespace';
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
import { getUnsupportedContent } from './get-unsupported-content';
import { getUnsupportedContentIconSpec } from './get-unsupported-content-icon-spec';
const VanillaUnsupportedInlineCssClassName = {
INNER: 'unsupported-inline-vanilla-inner',
ICON: 'unsupported-vanilla-icon'
};
/** Identifies this tooltip for tests and debugging. */
const TOOLTIP_CLASS_NAME = 'unsupported-content-tooltip';
/** Distinct from the block node view's prefix, so the counter fallback below cannot collide. */
const TOOLTIP_ID_PREFIX = 'unsupported-inline-content-tooltip';
/** Classes applied to the tooltip element: the shared default look, plus our own hook. */
const TOOLTIP_CLASS_NAMES = `${VANILLA_TOOLTIP_DEFAULT_CLASS} ${TOOLTIP_CLASS_NAME}`;
const INLINE_NODE_VIEW_CLASS_NAME = 'inlineNodeView';
const ZERO_WIDTH_SPACE_CONTAINER_CLASS_NAME = 'zeroWidthSpaceContainer';
const ADD_ZERO_WIDTH_SPACE_CLASS_NAME = `${INLINE_NODE_VIEW_CLASS_NAME}AddZeroWidthSpace`;
const nextTooltipId = (() => {
let count = 0;
return () => typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function' ? `${TOOLTIP_ID_PREFIX}-${crypto.randomUUID()}` : `${TOOLTIP_ID_PREFIX}-${count += 1}`;
})();
function getInlineSpec(node, label) {
const browser = getBrowserInfo();
const trailingSpec = browser.android ? ['span', {
class: ZERO_WIDTH_SPACE_CONTAINER_CLASS_NAME,
contentEditable: 'false'
}, ['span', {
class: ADD_ZERO_WIDTH_SPACE_CLASS_NAME
}], ZERO_WIDTH_SPACE] : ['span', {
class: ADD_ZERO_WIDTH_SPACE_CLASS_NAME
}];
return ['span', {
class: `${node.type.name}View-content-wrap ${INLINE_NODE_VIEW_CLASS_NAME}`,
contentEditable: 'false'
}, ['span', {
class: ZERO_WIDTH_SPACE_CONTAINER_CLASS_NAME
}, ['span', {
class: ADD_ZERO_WIDTH_SPACE_CLASS_NAME
}], ZERO_WIDTH_SPACE], ['span', {
class: VanillaUnsupportedInlineCssClassName.INNER
}, label, getUnsupportedContentIconSpec(VanillaUnsupportedInlineCssClassName.ICON)], trailingSpec];
}
function createUnsupportedInlineDOM(node, intl) {
var _domElement$querySele;
const label = getUnsupportedContent(unsupportedContentMessages.unsupportedInlineContent, 'Unsupported', node, intl);
const {
dom
} = DOMSerializer.renderSpec(document, getInlineSpec(node, label));
const domElement = dom instanceof HTMLElement ? dom : undefined;
const icon = (_domElement$querySele = domElement === null || domElement === void 0 ? void 0 : domElement.querySelector(`.${VanillaUnsupportedInlineCssClassName.ICON}`)) !== null && _domElement$querySele !== void 0 ? _domElement$querySele : null;
return {
dom,
icon
};
}
export class UnsupportedInlineNodeViewVanilla {
constructor(node, intl, dispatchAnalyticsEvent) {
_defineProperty(this, "tooltip", null);
_defineProperty(this, "unbindMouseenter", null);
this.node = node;
const {
dom,
icon
} = createUnsupportedInlineDOM(node, intl);
this.dom = dom;
if (!icon) {
return;
}
this.unbindMouseenter = bind(icon, {
type: 'mouseenter',
options: {
once: true
},
listener: event => {
var _this$unbindMouseente;
(_this$unbindMouseente = this.unbindMouseenter) === null || _this$unbindMouseente === void 0 ? void 0 : _this$unbindMouseente.call(this);
this.unbindMouseenter = null;
const tooltipText = intl.formatMessage(unsupportedContentMessages.unsupportedContentTooltip);
this.tooltip = new VanillaTooltip(icon, tooltipText, nextTooltipId(), TOOLTIP_CLASS_NAMES, 300,
// Use default style by having the default tooltip class name.
undefined, () => {
if (dispatchAnalyticsEvent) {
var _this$node, _this$node$attrs, _this$node$attrs$orig;
trackUnsupportedContentTooltipDisplayedFor(dispatchAnalyticsEvent, ACTION_SUBJECT_ID.ON_UNSUPPORTED_INLINE, (_this$node = this.node) === null || _this$node === void 0 ? void 0 : (_this$node$attrs = _this$node.attrs) === null || _this$node$attrs === void 0 ? void 0 : (_this$node$attrs$orig = _this$node$attrs.originalValue) === null || _this$node$attrs$orig === void 0 ? void 0 : _this$node$attrs$orig.type);
}
});
icon.dispatchEvent(new Event(event.type));
}
});
}
update(node) {
if (node.type !== this.node.type) {
return false;
}
if (!this.node.sameMarkup(node)) {
return false;
}
this.node = node;
return true;
}
ignoreMutation(mutation) {
return mutation.type !== 'selection';
}
destroy() {
var _this$tooltip, _this$unbindMouseente2;
(_this$tooltip = this.tooltip) === null || _this$tooltip === void 0 ? void 0 : _this$tooltip.destroy();
this.tooltip = null;
(_this$unbindMouseente2 = this.unbindMouseenter) === null || _this$unbindMouseente2 === void 0 ? void 0 : _this$unbindMouseente2.call(this);
this.unbindMouseenter = null;
}
}