@atlaskit/editor-plugin-placeholder
Version:
Placeholder plugin for @atlaskit/editor-core.
112 lines (107 loc) • 5.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createPlaceholderDecoration = createPlaceholderDecoration;
var _browser = require("@atlaskit/editor-common/browser");
var _processRawValue = require("@atlaskit/editor-common/process-raw-value");
var _utils = require("@atlaskit/editor-common/utils");
var _model = require("@atlaskit/editor-prosemirror/model");
var _view = require("@atlaskit/editor-prosemirror/view");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _animation = require("./animation");
var _constants = require("./constants");
function createPlaceholderDecoration(editorState, placeholderText, placeholderPrompts, activeTypewriterTimeouts) {
var pos = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
var initialDelayWhenUserTypedAndDeleted = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
var placeholderADF = arguments.length > 6 ? arguments[6] : undefined;
var showOnEmptyParagraph = arguments.length > 7 ? arguments[7] : undefined;
var browser = (0, _browser.getBrowserInfo)();
var placeholderDecoration = document.createElement('span');
var placeholderNodeWithText = placeholderDecoration;
placeholderDecoration.setAttribute('data-testid', _constants.placeholderTestId);
var shouldFadeIn = showOnEmptyParagraph;
placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
placeholderDecoration.setAttribute('aria-hidden', 'true');
// PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
// So adding an extra span which will contain the placeholder text
if (browser.gecko) {
var placeholderNode = document.createElement('span');
placeholderNode.setAttribute('contenteditable', 'true'); // explicitly overriding the default Decoration behaviour
placeholderDecoration.appendChild(placeholderNode);
placeholderNodeWithText = placeholderNode;
}
if (placeholderText) {
placeholderNodeWithText.textContent = placeholderText || ' ';
} else if (placeholderADF) {
var serializer = _model.DOMSerializer.fromSchema(editorState.schema);
// Get a PMNode from docnode
var docNode = (0, _processRawValue.processRawValue)(editorState.schema, placeholderADF);
if (docNode) {
// Extract only the inline content from paragraphs, avoiding block-level elements
// that can interfere with cursor rendering
docNode.children.forEach(function (node) {
// For paragraph nodes, serialize their content (inline elements) directly
// without the wrapping <p> tag
if (node.type.name === 'paragraph') {
node.content.forEach(function (inlineNode) {
var inlineDOM = serializer.serializeNode(inlineNode);
placeholderNodeWithText.append(inlineDOM);
});
} else {
// For non-paragraph nodes, serialize normally
var nodeDOM = serializer.serializeNode(node);
placeholderNodeWithText.append(nodeDOM);
}
});
var markElements = placeholderNodeWithText.querySelectorAll('[data-prosemirror-content-type="mark"]');
markElements.forEach(function (markEl) {
if (markEl instanceof HTMLElement) {
markEl.style.setProperty('color', "var(--ds-text-subtlest, #6B6E76)");
}
});
// Ensure all child elements don't block pointer events or cursor
var allElements = placeholderNodeWithText.querySelectorAll('*');
allElements.forEach(function (el) {
if (el instanceof HTMLElement) {
el.style.pointerEvents = 'none';
el.style.userSelect = 'none';
}
});
}
} else if (placeholderPrompts) {
(0, _animation.cycleThroughPlaceholderPrompts)(placeholderPrompts, activeTypewriterTimeouts, placeholderNodeWithText, initialDelayWhenUserTypedAndDeleted);
}
// ME-2289 Tapping on backspace in empty editor hides and displays the keyboard
// Add a editable buff node as the cursor moving forward is inevitable
// when backspace in GBoard composition
if (browser.android && browser.chrome) {
var buffNode = document.createElement('span');
buffNode.setAttribute('class', 'placeholder-android');
buffNode.setAttribute('contenteditable', 'true');
buffNode.textContent = ' ';
placeholderDecoration.appendChild(buffNode);
}
var isTargetNested = editorState.doc.resolve(pos).depth > 1;
// only truncate text for nested nodes, otherwise applying 'overflow: hidden;' to top level nodes
// creates issues with quick insert button
if (isTargetNested && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
placeholderDecoration.classList.add('placeholder-decoration-hide-overflow');
}
if (placeholderADF && browser.chrome) {
var fragment = document.createDocumentFragment();
// An issue occurs with the caret where it gets bigger when it's next to a non-editable element like a decoration.
// See: https://discuss.prosemirror.net/t/chrome-caret-cursor-larger-than-the-text-with-inlined-items/5946/2
// Adding a zero-width space seems to fix this issue.
fragment.appendChild(document.createTextNode(_utils.ZERO_WIDTH_SPACE));
fragment.appendChild(placeholderDecoration);
return _view.DecorationSet.create(editorState.doc, [_view.Decoration.widget(pos, fragment, {
side: 0,
key: "placeholder ".concat(placeholderText)
})]);
}
return _view.DecorationSet.create(editorState.doc, [_view.Decoration.widget(pos, placeholderDecoration, {
side: 0,
key: "placeholder ".concat(placeholderText)
})]);
}