UNPKG

@atlaskit/editor-plugin-tasks-and-decisions

Version:

Tasks and decisions plugin for @atlaskit/editor-core

106 lines (102 loc) 4.37 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import { tasksAndDecisionsMessages } from '@atlaskit/editor-common/messages'; import { DOMSerializer } from '@atlaskit/editor-prosemirror/model'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { decisionItemToDOM } from './decisionItemNodeSpec'; /** * NodeView for the DecisionItem node. * It renders the decision item with its content and exposes the contentDOM to prosemirror. */ export class DecisionItemNodeView { /** * Updates the hasChildren state based on the node's child count by setting the `data-empty` attribute on the contentDOM. * @param node - The ProseMirror node to check for children. * @private */ updateHasChildren(node) { const currentlyHasChildren = node.childCount > 0; if (currentlyHasChildren !== this.hasChildren) { var _this$contentDOM; this.hasChildren = currentlyHasChildren; (_this$contentDOM = this.contentDOM) === null || _this$contentDOM === void 0 ? void 0 : _this$contentDOM.toggleAttribute('data-empty', !currentlyHasChildren); if (expValEquals('editor_a11y_decision_aria_label', 'isEnabled', true)) { this.setIconAriaLabel(!currentlyHasChildren); } } return this.hasChildren; } setIcon(dom) { if (!dom || !(dom instanceof HTMLElement)) { return; } const maybeIcon = dom.querySelector('[data-component="icon"] > [role="img"]'); if (maybeIcon && maybeIcon instanceof HTMLElement) { this.icon = maybeIcon; } } setIconAriaLabel(isEmpty) { if (!this.icon || !this.intl) { return; } const ariaLabel = isEmpty ? this.intl.formatMessage(tasksAndDecisionsMessages.undefinedDecisionAriaLabel) : this.intl.formatMessage(tasksAndDecisionsMessages.decisionAriaLabel); this.icon.setAttribute('aria-label', ariaLabel); } /** * Creates a new DecisionItemNodeView. * @import type {PMNode} from '@atlaskit/editor-prosemirror/model'; * @import type {IntlShape} from 'react-intl'; * @param {PMNode} node - The ProseMirror node representing the decision item. * @param {IntlShape} intl - The IntlShape for internationalization, used to format the placeholder text. * @example * const decisionItemNodeView = new DecisionItemNodeView(node, getIntl()); */ constructor(node, intl) { _defineProperty(this, "icon", null); _defineProperty(this, "hasChildren", undefined); const spec = decisionItemToDOM(node, intl); const { dom, contentDOM } = DOMSerializer.renderSpec(document, spec); this.dom = dom; this.contentDOM = contentDOM; if (expValEquals('editor_a11y_decision_aria_label', 'isEnabled', true)) { this.setIcon(this.dom); this.intl = intl; } } /** * Updates the node view when the ProseMirror node changes. * @import type {PMNode} from '@atlaskit/editor-prosemirror/model'; * @param {PMNode} node - The ProseMirror node to update the view with. * @example * decisionItemNodeView.update(node); * @returns {boolean} - Returns true if the view was updated successfully. */ update(node) { this.updateHasChildren(node); return true; } /** * Determines whether a mutation should be ignored by ProseMirror. * This prevents unnecessary node view destruction during DOM changes that don't affect our content. * @param mutation - The DOM mutation record or selection change * @returns true if the mutation should be ignored, false if it should be processed * @example * // Mutation outside contentDOM will be ignored * const shouldIgnore = decisionItemNodeView.ignoreMutation(mutationRecord); */ ignoreMutation(mutation) { // This was discovered while implementing the platform_editor_debounce_portal_provider experiment // And there will only be an issue if the experiment is enabled. // As such, this fix is behind this experiment. if (!expValEquals('platform_editor_debounce_portal_provider', 'isEnabled', true, false)) { return false; // Let ProseMirror handle all mutations when experiment is disabled } if (!this.contentDOM) { return true; } // Ignore mutations that don't target our contentDOM and aren't selection changes return !this.contentDOM.contains(mutation.target) && mutation.type !== 'selection'; } }