@atlaskit/editor-plugin-caption
Version:
Caption plugin for @atlaskit/editor-core
75 lines (74 loc) • 3.5 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import React from 'react';
import { SelectionBasedNodeView } from '@atlaskit/editor-common/selection-based-node-view';
import { Caption } from '@atlaskit/editor-common/ui';
export class CaptionNodeView extends SelectionBasedNodeView {
constructor(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, viewShouldUpdate, pluginInjectionApi) {
super(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, viewShouldUpdate);
_defineProperty(this, "selected", this.insideSelection());
this.pluginInjectionApi = pluginInjectionApi;
this.handleEditorDisabledChanged();
}
createDomRef() {
const domRef = document.createElement('figcaption');
domRef.setAttribute('data-caption', 'true');
return domRef;
}
getContentDOM() {
var _this$pluginInjection, _this$pluginInjection2, _this$pluginInjection3;
const dom = document.createElement('div');
// setting a className prevents PM/Chrome mutation observer from
// incorrectly deleting nodes
dom.className = 'caption-wrapper';
dom.setAttribute('contenteditable', (_this$pluginInjection = this.pluginInjectionApi) !== null && _this$pluginInjection !== void 0 && (_this$pluginInjection2 = _this$pluginInjection.editorDisabled) !== null && _this$pluginInjection2 !== void 0 && (_this$pluginInjection3 = _this$pluginInjection2.sharedState.currentState()) !== null && _this$pluginInjection3 !== void 0 && _this$pluginInjection3.editorDisabled ? 'false' : 'true');
return {
dom
};
}
// ED-24114: We need to ignore mutations that are not related to the caption node
// since these mutations can cause an infinite loop in React 18 when using createRoot
ignoreMutation(mutation) {
if (!this.contentDOM) {
return true;
}
return !this.contentDOM.contains(mutation.target) && mutation.type !== 'selection';
}
handleEditorDisabledChanged() {
var _this$pluginInjection4;
if ((_this$pluginInjection4 = this.pluginInjectionApi) !== null && _this$pluginInjection4 !== void 0 && _this$pluginInjection4.editorDisabled) {
this.cleanupEditorDisabledListener = this.pluginInjectionApi.editorDisabled.sharedState.onChange(sharedState => {
if (this.contentDOM) {
this.contentDOM.setAttribute('contenteditable', sharedState.nextSharedState.editorDisabled ? 'false' : 'true');
}
});
}
}
render(_props, forwardRef) {
return /*#__PURE__*/React.createElement(Caption, {
selected: this.insideSelection(),
hasContent: this.node.content.childCount > 0
}, /*#__PURE__*/React.createElement("div", {
ref: forwardRef
}));
}
viewShouldUpdate(nextNode) {
if (this.node.childCount !== nextNode.childCount) {
return true;
}
const newSelected = this.insideSelection();
const selectedStateChange = this.selected !== newSelected;
this.selected = newSelected;
return selectedStateChange;
}
destroy() {
if (this.cleanupEditorDisabledListener) {
this.cleanupEditorDisabledListener();
}
this.cleanupEditorDisabledListener = undefined;
}
}
export default function captionNodeView(portalProviderAPI, eventDispatcher, pluginInjectionApi) {
return (node, view, getPos) => {
return new CaptionNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, {}, undefined, undefined, pluginInjectionApi).init();
};
}