UNPKG

@atlaskit/editor-plugin-placeholder-text

Version:

placeholder text plugin for @atlaskit/editor-core

84 lines (82 loc) 2.85 kB
import { getBrowserInfo } from '@atlaskit/editor-common/browser'; import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace'; import { Selection } from '@atlaskit/editor-prosemirror/state'; const serializePlaceholderNode = node => { const element = document.createElement('span'); const browser = getBrowserInfo(); element.classList.add('pm-placeholder'); // the inline node api test suite requires the following class name element.classList.add('placeholderView-content-wrap'); element.innerText = ZERO_WIDTH_SPACE; const elementChildren = document.createElement('span'); elementChildren.classList.add('pm-placeholder__text'); elementChildren.dataset.placeholder = node.attrs.text; elementChildren.setAttribute('contenteditable', 'false'); element.appendChild(elementChildren); if (browser.safari) { element.appendChild(document.createTextNode(ZERO_WIDTH_SPACE)); } else { element.appendChild(document.createElement('wbr')); } return element; }; export class PlaceholderTextNodeView { constructor(node, view, getPos) { this.node = node; this.view = view; this.getPos = getPos; this.dom = serializePlaceholderNode(this.node); this.getPos = getPos; } stopEvent(e) { if (e.type === 'mousedown' && typeof this.getPos === 'function') { e.preventDefault(); const { view } = this; const startNodePosition = this.getPos(); if (typeof startNodePosition !== 'number') { return false; } const tr = view.state.tr; tr.setSelection(Selection.near(tr.doc.resolve(startNodePosition))); view.dispatch(tr); if (!view.hasFocus()) { window.requestAnimationFrame(() => { view.focus(); }); } return true; } return false; } ignoreMutation(record) { if (typeof this.getPos !== 'function' || record.type !== 'selection') { return true; } const { view, node } = this; const placeholderStartPosition = this.getPos(); if (typeof placeholderStartPosition !== 'number') { return false; } const placeholderEndPosition = placeholderStartPosition + node.nodeSize; const selection = view.state.selection; // when the selection is set right after the placeholder. // we should let ProseMirror deal with this edge-case if (selection.from === placeholderEndPosition) { return false; } const isSelectionAtPlaceholder = selection.from === placeholderStartPosition; const isSelectionAfterlaceholder = selection.from > placeholderEndPosition; if (isSelectionAtPlaceholder || isSelectionAfterlaceholder) { const tr = view.state.tr; tr.setSelection(Selection.near(tr.doc.resolve(placeholderEndPosition))); view.dispatch(tr); return true; } return true; } }