@atlaskit/editor-plugin-tasks-and-decisions
Version:
Tasks and decisions plugin for @atlaskit/editor-core
125 lines (122 loc) • 5.53 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DecisionItemNodeView = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _messages = require("@atlaskit/editor-common/messages");
var _model = require("@atlaskit/editor-prosemirror/model");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
var _decisionItemNodeSpec = require("./decisionItemNodeSpec");
/**
* NodeView for the DecisionItem node.
* It renders the decision item with its content and exposes the contentDOM to prosemirror.
*/
var DecisionItemNodeView = exports.DecisionItemNodeView = /*#__PURE__*/function () {
/**
* 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());
*/
function DecisionItemNodeView(node, intl) {
(0, _classCallCheck2.default)(this, DecisionItemNodeView);
(0, _defineProperty2.default)(this, "icon", null);
(0, _defineProperty2.default)(this, "hasChildren", undefined);
var spec = (0, _decisionItemNodeSpec.decisionItemToDOM)(node, intl);
var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, spec),
dom = _DOMSerializer$render.dom,
contentDOM = _DOMSerializer$render.contentDOM;
this.dom = dom;
this.contentDOM = contentDOM;
if ((0, _expValEquals.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.
*/
return (0, _createClass2.default)(DecisionItemNodeView, [{
key: "updateHasChildren",
value:
/**
* 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
*/
function updateHasChildren(node) {
var currentlyHasChildren = node.childCount > 0;
if (currentlyHasChildren !== this.hasChildren) {
var _this$contentDOM;
this.hasChildren = currentlyHasChildren;
(_this$contentDOM = this.contentDOM) === null || _this$contentDOM === void 0 || _this$contentDOM.toggleAttribute('data-empty', !currentlyHasChildren);
if ((0, _expValEquals.expValEquals)('editor_a11y_decision_aria_label', 'isEnabled', true)) {
this.setIconAriaLabel(!currentlyHasChildren);
}
}
return this.hasChildren;
}
}, {
key: "setIcon",
value: function setIcon(dom) {
if (!dom || !(dom instanceof HTMLElement)) {
return;
}
var maybeIcon = dom.querySelector('[data-component="icon"] > [role="img"]');
if (maybeIcon && maybeIcon instanceof HTMLElement) {
this.icon = maybeIcon;
}
}
}, {
key: "setIconAriaLabel",
value: function setIconAriaLabel(isEmpty) {
if (!this.icon || !this.intl) {
return;
}
var ariaLabel = isEmpty ? this.intl.formatMessage(_messages.tasksAndDecisionsMessages.undefinedDecisionAriaLabel) : this.intl.formatMessage(_messages.tasksAndDecisionsMessages.decisionAriaLabel);
this.icon.setAttribute('aria-label', ariaLabel);
}
}, {
key: "update",
value: function 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);
*/
}, {
key: "ignoreMutation",
value: function 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 (!(0, _expValEquals.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';
}
}]);
}();