UNPKG

@atlaskit/editor-plugin-placeholder

Version:

Placeholder plugin for @atlaskit/editor-core.

112 lines (107 loc) 5.71 kB
"use strict"; 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) })]); }