@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
103 lines (101 loc) • 3.13 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import ReactNodeView from '../react-node-view';
/**
* A ReactNodeView that handles React components sensitive
* to selection changes.
*
* If the selection changes, it will attempt to re-render the
* React component. Otherwise it does nothing.
*
* You can subclass `viewShouldUpdate` to include other
* props that your component might want to consider before
* entering the React lifecycle. These are usually props you
* compare in `shouldComponentUpdate`.
*
* An example:
*
* ```
* viewShouldUpdate(nextNode) {
* if (nextNode.attrs !== this.node.attrs) {
* return true;
* }
*
* return super.viewShouldUpdate(nextNode);
* }```
*/
export class SelectionBasedNodeView extends ReactNodeView {
constructor(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, hasContext = false, viewShouldUpdate, hasIntlContext = false) {
super(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, hasContext, viewShouldUpdate, hasIntlContext);
_defineProperty(this, "isSelectedNode", false);
_defineProperty(this, "isNodeInsideSelection", (from, to, pos, posEnd) => {
({
pos,
posEnd
} = this.getPositionsWithDefault(pos, posEnd));
if (typeof pos !== 'number' || typeof posEnd !== 'number') {
return false;
}
return from <= pos && to >= posEnd;
});
_defineProperty(this, "isSelectionInsideNode", (from, to, pos, posEnd) => {
({
pos,
posEnd
} = this.getPositionsWithDefault(pos, posEnd));
if (typeof pos !== 'number' || typeof posEnd !== 'number') {
return false;
}
return pos < from && to < posEnd;
});
_defineProperty(this, "insideSelection", () => {
const {
selection: {
from,
to
}
} = this.view.state;
return this.isSelectedNode || this.isSelectionInsideNode(from, to);
});
_defineProperty(this, "nodeInsideSelection", () => {
const {
selection
} = this.view.state;
const {
from,
to
} = selection;
return this.isSelectedNode || this.isNodeInsideSelection(from, to);
});
this.updatePos();
}
/**
* Update current node's start and end positions.
*
* Prefer `this.pos` rather than getPos(), because calling getPos is
* expensive, unless you know you're definitely going to render.
*/
updatePos() {
if (typeof this.getPos === 'boolean') {
return;
}
const pos = this.getPos();
if (typeof pos === 'number') {
this.pos = pos;
this.posEnd = pos + this.node.nodeSize;
}
}
getPositionsWithDefault(pos, posEnd) {
return {
pos: typeof pos !== 'number' ? this.pos : pos,
posEnd: typeof posEnd !== 'number' ? this.posEnd : posEnd
};
}
selectNode() {
this.isSelectedNode = true;
this.update(this.node, this.decorations);
}
deselectNode() {
this.isSelectedNode = false;
this.update(this.node, this.decorations);
}
}